X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FCutAndPaste.C;h=e554ac6311098839dcff14ca605c8e4445001370;hb=52eb91c94fb70d58dceef430659c8781de2eccda;hp=8a4d989f36fdad0087f5070e2a58a3e77a5e03b1;hpb=1bc54962570477dedb44aa909096d15f550ce1dc;p=lyx.git diff --git a/src/CutAndPaste.C b/src/CutAndPaste.C index 8a4d989f36..e554ac6311 100644 --- a/src/CutAndPaste.C +++ b/src/CutAndPaste.C @@ -33,7 +33,6 @@ #include "paragraph.h" #include "paragraph_funcs.h" #include "ParagraphParameters.h" -#include "ParagraphList_fwd.h" #include "pariterator.h" #include "undo.h" @@ -49,16 +48,11 @@ #include "frontends/Clipboard.h" #include "frontends/Selection.h" +#include #include #include - -namespace lyx { - -using support::bformat; -using frontend::Clipboard; - using std::endl; using std::for_each; using std::make_pair; @@ -67,6 +61,11 @@ using std::vector; using std::string; +namespace lyx { + +using support::bformat; +using frontend::Clipboard; + namespace { typedef std::pair PitPosPair; @@ -74,6 +73,8 @@ typedef std::pair PitPosPair; typedef limited_stack > 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, @@ -330,7 +331,9 @@ PitPosPair eraseSelectionHelper(BufferParams const & params, 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; @@ -344,18 +347,26 @@ void putClipboard(ParagraphList const & paragraphs, textclass_type 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. @@ -368,17 +379,15 @@ void copySelectionHelper(Buffer const & buf, ParagraphList & pars, 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); - - // Cut out the begin of the first paragraph - Paragraph & front = paragraphs.front(); - // again, do not track deletion - front.eraseChars(0, start, 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()); - theCuts.push(make_pair(paragraphs, tc)); + cutstack.push(make_pair(copy_pars, tc)); } } // namespace anon @@ -525,7 +534,7 @@ void cutSelection(LCursor & cur, bool doclear, bool realcut) 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, @@ -539,16 +548,17 @@ void cutSelection(LCursor & cur, bool doclear, bool realcut) 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()); @@ -581,16 +591,9 @@ void copySelection(LCursor & cur) } -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()) @@ -606,13 +609,13 @@ void copySelectionToStack(LCursor & cur) 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()) { @@ -623,10 +626,65 @@ void copySelectionToStack(LCursor & cur) 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) +{ + if (lyxerr.debugging(Debug::ACTION)) + lyxerr << 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(); } @@ -661,11 +719,25 @@ void pasteParagraphList(LCursor & cur, ParagraphList const & parlist, } +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; } @@ -673,7 +745,9 @@ void pasteClipboard(LCursor & cur, ErrorList & errorList, bool asParagraphs) 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); @@ -697,15 +771,13 @@ void pasteClipboard(LCursor & cur, ErrorList & errorList, bool asParagraphs) } -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(); } @@ -736,6 +808,7 @@ void replaceSelectionWithString(LCursor & cur, docstring const & str, bool backw cur.setSelection(selbeg, -int(str.length())); } else cur.setSelection(selbeg, str.length()); + saveSelection(cur); }