#include "paragraph.h"
#include "paragraph_funcs.h"
#include "ParagraphParameters.h"
-#include "ParagraphList_fwd.h"
#include "pariterator.h"
#include "undo.h"
#include "frontends/Clipboard.h"
#include "frontends/Selection.h"
+#include <boost/current_function.hpp>
#include <boost/tuple/tuple.hpp>
#include <string>
typedef limited_stack<pair<ParagraphList, textclass_type> > CutStack;
CutStack theCuts(10);
+// persistent selection, cleared until the next selection
+CutStack selectionBuffer(1);
// store whether the tabular stack is newer than the normal copy stack
// FIXME: this is a workaround for bug 1919. Should be removed for 1.5,
void putClipboard(ParagraphList const & paragraphs, textclass_type textclass,
docstring const & plaintext)
{
- Buffer buffer(string(), false);
+ // For some strange reason gcc 3.2 and 3.3 do not accept
+ // Buffer buffer(string(), false);
+ Buffer buffer("", false);
buffer.setUnnamed(true);
buffer.paragraphs() = paragraphs;
buffer.params().textclass = textclass;
void copySelectionHelper(Buffer const & buf, ParagraphList & pars,
pit_type startpit, pit_type endpit,
- int start, int end, textclass_type tc)
+ int start, int end, textclass_type tc, CutStack & cutstack)
{
BOOST_ASSERT(0 <= start && start <= pars[startpit].size());
BOOST_ASSERT(0 <= end && end <= pars[endpit].size());
BOOST_ASSERT(startpit != endpit || start <= end);
// Clone the paragraphs within the selection.
- ParagraphList paragraphs(boost::next(pars.begin(), startpit),
- boost::next(pars.begin(), endpit + 1));
+ ParagraphList copy_pars(boost::next(pars.begin(), startpit),
+ boost::next(pars.begin(), endpit + 1));
- ParagraphList::iterator it = paragraphs.begin();
- ParagraphList::iterator it_end = paragraphs.end();
+ // Remove the end of the last paragraph; afterwards, remove the beginning
+ // of the first paragraph. Keep this order - there may only be one paragraph!
+ // Do not track deletions here; this is an internal action not visible to the user
+ Paragraph & back = copy_pars.back();
+ back.eraseChars(end, back.size(), false);
+ Paragraph & front = copy_pars.front();
+ front.eraseChars(0, start, false);
+
+ ParagraphList::iterator it = copy_pars.begin();
+ ParagraphList::iterator it_end = copy_pars.end();
for (; it != it_end; it++) {
// ERT paragraphs have the Language latex_language.
it->setInsetOwner(0);
}
- // Cut out the end of the last paragraph.
- Paragraph & back = paragraphs.back();
- // do not track deletion here; it is an internal action not visible to the user
- back.eraseChars(end, back.size(), false);
+ // do not copy text (also nested in insets) which is marked as deleted
+ // acceptChanges() is defined for LyXText rather than ParagraphList
+ // Thus we must wrap copy_pars into a LyXText object and cross our fingers
+ LyXText lt;
+ copy_pars.swap(lt.paragraphs());
+ lt.acceptChanges(buf.params());
+ copy_pars.swap(lt.paragraphs());
- // Cut out the begin of the first paragraph
- Paragraph & front = paragraphs.front();
- // again, do not track deletion
- front.eraseChars(0, start, false);
-
- theCuts.push(make_pair(paragraphs, tc));
+ cutstack.push(make_pair(copy_pars, tc));
}
} // namespace anon
text->paragraphs(),
begpit, endpit,
cur.selBegin().pos(), endpos,
- bp.textclass);
+ bp.textclass, theCuts);
// Stuff what we got on the clipboard.
// Even if there is no selection.
putClipboard(theCuts[0].first, theCuts[0].second,
cur.selBegin().pos(), endpos,
doclear);
- // sometimes necessary
- if (doclear)
- text->paragraphs()[begpit].stripLeadingSpaces(bp.trackChanges);
-
// cutSelection can invalidate the cursor so we need to set
// it anew. (Lgb)
// we prefer the end for when tracking changes
cur.pos() = endpos;
cur.pit() = endpit;
+ // sometimes necessary
+ if (doclear
+ && text->paragraphs()[begpit].stripLeadingSpaces(bp.trackChanges))
+ cur.fixIfBroken();
+
// need a valid cursor. (Lgb)
cur.clearSelection();
updateLabels(cur.buffer());
}
-void copySelection(LCursor & cur, docstring const & plaintext)
-{
- copySelectionToStack(cur);
-
- // stuff the selection onto the X clipboard, from an explicit copy request
- putClipboard(theCuts[0].first, theCuts[0].second, plaintext);
-}
-
+namespace {
-void copySelectionToStack(LCursor & cur)
+void copySelectionToStack(LCursor & cur, CutStack & cutstack)
{
// this doesn't make sense, if there is no selection
if (!cur.selection())
ParagraphList & pars = text->paragraphs();
pos_type pos = cur.selBegin().pos();
pit_type par = cur.selBegin().pit();
- while (pos < pars[par].size()
- && pars[par].isLineSeparator(pos)
- && (par != cur.selEnd().pit() || pos < cur.selEnd().pos()))
+ while (pos < pars[par].size() &&
+ pars[par].isLineSeparator(pos) &&
+ (par != cur.selEnd().pit() || pos < cur.selEnd().pos()))
++pos;
copySelectionHelper(cur.buffer(), pars, par, cur.selEnd().pit(),
- pos, cur.selEnd().pos(), cur.buffer().params().textclass);
+ pos, cur.selEnd().pos(), cur.buffer().params().textclass, cutstack);
}
if (cur.inMathed()) {
par.layout(bp.getLyXTextClass().defaultLayout());
par.insert(0, grabSelection(cur), LyXFont(), Change(Change::UNCHANGED));
pars.push_back(par);
- theCuts.push(make_pair(pars, bp.textclass));
+ cutstack.push(make_pair(pars, bp.textclass));
}
- // tell tabular that a recent copy happened
- dirtyTabularStack(false);
+}
+
+}
+
+
+void copySelectionToStack()
+{
+ if (!selectionBuffer.empty())
+ theCuts.push(selectionBuffer[0]);
+}
+
+
+void copySelection(LCursor & cur, docstring const & plaintext)
+{
+ // In tablemode, because copy and paste actually use special table stack
+ // we do not attemp to get selected paragraphs under cursor. Instead, a
+ // paragraph with the plain text version is generated so that table cells
+ // can be pasted as pure text somewhere else.
+ if (cur.selBegin().idx() != cur.selEnd().idx()) {
+ ParagraphList pars;
+ Paragraph par;
+ BufferParams const & bp = cur.buffer().params();
+ par.layout(bp.getLyXTextClass().defaultLayout());
+ par.insert(0, plaintext, LyXFont(), Change(Change::UNCHANGED));
+ pars.push_back(par);
+ theCuts.push(make_pair(pars, bp.textclass));
+ } else
+ copySelectionToStack(cur, theCuts);
+
+ // stuff the selection onto the X clipboard, from an explicit copy request
+ putClipboard(theCuts[0].first, theCuts[0].second, plaintext);
+}
+
+
+void saveSelection(LCursor & cur)
+{
+ LYXERR(Debug::ACTION) << BOOST_CURRENT_FUNCTION << ": `"
+ << to_utf8(cur.selectionAsString(true)) << "'."
+ << endl;
+
+ if (cur.selection())
+ copySelectionToStack(cur, selectionBuffer);
+ // tell X whether we now have a valid selection
+ theSelection().haveSelection(cur.selection());
+}
+
+
+bool selection()
+{
+ return !selectionBuffer.empty();
+}
+
+
+void clearSelection()
+{
+ selectionBuffer.clear();
}
}
+void pasteFromStack(LCursor & cur, ErrorList & errorList, size_t sel_index)
+{
+ // this does not make sense, if there is nothing to paste
+ if (!checkPastePossible(sel_index))
+ return;
+
+ recordUndo(cur);
+ pasteParagraphList(cur, theCuts[sel_index].first,
+ theCuts[sel_index].second, errorList);
+ cur.setSelection();
+ saveSelection(cur);
+}
+
+
void pasteClipboard(LCursor & cur, ErrorList & errorList, bool asParagraphs)
{
// Use internal clipboard if it is the most recent one
if (theClipboard().isInternal()) {
- pasteSelection(cur, errorList, 0);
+ pasteFromStack(cur, errorList, 0);
return;
}
if (theClipboard().hasLyXContents()) {
string lyx = theClipboard().getAsLyX();
if (!lyx.empty()) {
- Buffer buffer(string(), false);
+ // For some strange reason gcc 3.2 and 3.3 do not accept
+ // Buffer buffer(string(), false);
+ Buffer buffer("", false);
buffer.setUnnamed(true);
if (buffer.readString(lyx)) {
recordUndo(cur);
}
-void pasteSelection(LCursor & cur, ErrorList & errorList, size_t sel_index)
+void pasteSelection(LCursor & cur, ErrorList & errorList)
{
- // this does not make sense, if there is nothing to paste
- if (!checkPastePossible(sel_index))
+ if (selectionBuffer.empty())
return;
-
recordUndo(cur);
- pasteParagraphList(cur, theCuts[sel_index].first,
- theCuts[sel_index].second, errorList);
+ pasteParagraphList(cur, selectionBuffer[0].first,
+ selectionBuffer[0].second, errorList);
cur.setSelection();
}
cur.setSelection(selbeg, -int(str.length()));
} else
cur.setSelection(selbeg, str.length());
+ saveSelection(cur);
}