From 133c2c62ee755d10e267505bbb2d98d947fff078 Mon Sep 17 00:00:00 2001 From: Jean-Marc Lasgouttes Date: Wed, 9 Nov 2016 15:13:41 +0100 Subject: [PATCH] Make insertInset use a temporary cut-and-paste area. This is a long wanted feature, although it does not go all the way to fix #6604 (private-cut/private-paste). Additionally, it fixes a crash that can happen when using undefined branches. This is done by making the action when pasting unknown branches configurable. Fixes bug #6570. (cherry picked from commit fb264663d8c3aadc3da0b922e31105c0aa7e319d) (cherry picked from commit 004fdf6aebd7669c4b1df33236fe2a8f515584c0) --- src/CutAndPaste.cpp | 63 ++++++++++++++++++++++++++++++++++++--------- src/CutAndPaste.h | 15 ++++++++++- src/Text3.cpp | 6 +++-- status.22x | 3 +++ 4 files changed, 72 insertions(+), 15 deletions(-) diff --git a/src/CutAndPaste.cpp b/src/CutAndPaste.cpp index cd037d1429..44ada2aa59 100644 --- a/src/CutAndPaste.cpp +++ b/src/CutAndPaste.cpp @@ -86,6 +86,8 @@ typedef limited_stack > CutStack; CutStack theCuts(10); // persistent selection, cleared until the next selection CutStack selectionBuffer(1); +// temporary scratch area +CutStack tempCut(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, @@ -111,7 +113,7 @@ struct PasteReturnValue { PasteReturnValue pasteSelectionHelper(DocIterator const & cur, ParagraphList const & parlist, - DocumentClassConstPtr oldDocClass, Buffer * tmpbuffer, + DocumentClassConstPtr oldDocClass, cap::BranchAction branchAction, ErrorList & errorlist) { Buffer const & buffer = *cur.buffer(); @@ -355,12 +357,15 @@ pasteSelectionHelper(DocIterator const & cur, ParagraphList const & parlist, || (is_child && (branchlist.find(name) || buffer.masterBuffer()->params().branchlist().find(name)))) break; - if (tmpbuffer) { + switch(branchAction) { + case cap::BRANCH_ADD: { // This is for a temporary buffer, so simply create the branch. // Must not use lyx::dispatch(), since tmpbuffer has no view. DispatchResult dr; - tmpbuffer->dispatch(FuncRequest(LFUN_BRANCH_ADD, name), dr); - } else { + const_cast(buffer).dispatch(FuncRequest(LFUN_BRANCH_ADD, name), dr); + break; + } + case cap::BRANCH_ASK: { docstring text = bformat( _("The pasted branch \"%1$s\" is undefined.\n" "Do you want to add it to the document's branch list?"), @@ -369,6 +374,10 @@ pasteSelectionHelper(DocIterator const & cur, ParagraphList const & parlist, text, 0, 1, _("&Add"), _("&Don't Add")) != 0) break; lyx::dispatch(FuncRequest(LFUN_BRANCH_ADD, name)); + break; + } + case cap::BRANCH_IGNORE: + break; } // We need to update the list of branches. need_update = true; @@ -519,7 +528,7 @@ Buffer * copyToTempBuffer(ParagraphList const & paragraphs, DocumentClassConstPt // temporary Buffer, since it does a lot of things to fix them up. DocIterator dit = doc_iterator_begin(buffer, &buffer->inset()); ErrorList el; - pasteSelectionHelper(dit, paragraphs, docclass, buffer, el); + pasteSelectionHelper(dit, paragraphs, docclass, cap::BRANCH_ADD, el); return buffer; } @@ -836,8 +845,9 @@ size_type numberOfSelections() return theCuts.size(); } +namespace { -void cutSelection(Cursor & cur, bool doclear, bool realcut) +void cutSelectionHelper(Cursor & cur, CutStack & cuts, bool doclear, bool realcut, bool putclip) { // This doesn't make sense, if there is no selection if (!cur.selection()) @@ -865,11 +875,12 @@ void cutSelection(Cursor & cur, bool doclear, bool realcut) *text, begpit, endpit, cur.selBegin().pos(), endpos, - bp.documentClassPtr(), theCuts); + bp.documentClassPtr(), cuts); // Stuff what we got on the clipboard. // Even if there is no selection. - putClipboard(theCuts[0].first, theCuts[0].second, - cur.selectionAsString(true)); + if (putclip) + putClipboard(cuts[0].first, cuts[0].second, + cur.selectionAsString(true)); } if (begpit != endpit) @@ -921,6 +932,19 @@ void cutSelection(Cursor & cur, bool doclear, bool realcut) } } +} + +void cutSelection(Cursor & cur, bool doclear, bool realcut) +{ + cutSelectionHelper(cur, theCuts, doclear, realcut, true); +} + + +void cutSelectionToTemp(Cursor & cur, bool doclear, bool realcut) +{ + cutSelectionHelper(cur, tempCut, doclear, realcut, false); +} + void copySelection(Cursor const & cur) { @@ -1047,6 +1071,7 @@ void clearSelection() void clearCutStack() { theCuts.clear(); + tempCut.clear(); } @@ -1064,14 +1089,15 @@ docstring selection(size_t sel_index, DocumentClassConstPtr docclass) void pasteParagraphList(Cursor & cur, ParagraphList const & parlist, - DocumentClassConstPtr docclass, ErrorList & errorList) + DocumentClassConstPtr docclass, ErrorList & errorList, + cap::BranchAction branchAction) { if (cur.inTexted()) { Text * text = cur.text(); LBUFERR(text); PasteReturnValue prv = - pasteSelectionHelper(cur, parlist, docclass, 0, errorList); + pasteSelectionHelper(cur, parlist, docclass, branchAction, errorList); cur.forceBufferUpdate(); cur.clearSelection(); text->setCursor(cur, prv.par, prv.pos); @@ -1090,7 +1116,20 @@ bool pasteFromStack(Cursor & cur, ErrorList & errorList, size_t sel_index) cur.recordUndo(); pasteParagraphList(cur, theCuts[sel_index].first, - theCuts[sel_index].second, errorList); + theCuts[sel_index].second, errorList, BRANCH_ASK); + return true; +} + + +bool pasteFromTemp(Cursor & cur, ErrorList & errorList) +{ + // this does not make sense, if there is nothing to paste + if (tempCut.empty() || tempCut[0].first.empty()) + return false; + + cur.recordUndo(); + pasteParagraphList(cur, tempCut[0].first, + tempCut[0].second, errorList, BRANCH_IGNORE); return true; } diff --git a/src/CutAndPaste.h b/src/CutAndPaste.h index c332e0b725..c14182cf8d 100644 --- a/src/CutAndPaste.h +++ b/src/CutAndPaste.h @@ -61,6 +61,9 @@ void replaceSelection(Cursor & cur); * selection. */ void cutSelection(Cursor & cur, bool doclear = true, bool realcut = true); +/// Like cutSelection, but only put to temporary cut buffer +void cutSelectionToTemp(Cursor & cur, bool doclear = true, bool realcut = true); + /// Push the current selection to the cut buffer and the system clipboard. void copySelection(Cursor const & cur); /// @@ -97,13 +100,23 @@ void pasteClipboardGraphics(Cursor & cur, ErrorList & errorList, /// Replace the current selection with cut buffer \c sel_index /// Does handle undo. Does only work in text, not mathed. bool pasteFromStack(Cursor & cur, ErrorList & errorList, size_t sel_index); +/// Replace the current selection with temporary cut buffer +/// Does handle undo. Does only work in text, not mathed. +bool pasteFromTemp(Cursor & cur, ErrorList & errorList); /// Paste the clipboard as simple text, removing any formatting void pasteSimpleText(Cursor & cur, bool asParagraphs); +// What to do with unknown branches? +enum BranchAction { + BRANCH_ADD, // add the branch unconditionally + BRANCH_IGNORE, // leave the branch undefined + BRANCH_ASK // ask the user whether the branch should be added +}; /// Paste the paragraph list \p parlist at the position given by \p cur. /// Does not handle undo. Does only work in text, not mathed. void pasteParagraphList(Cursor & cur, ParagraphList const & parlist, - DocumentClassConstPtr textclass, ErrorList & errorList); + DocumentClassConstPtr textclass, ErrorList & errorList, + BranchAction branchAction = BRANCH_ASK); /** Needed to switch between different classes. This works diff --git a/src/Text3.cpp b/src/Text3.cpp index 45cc7637c5..710737e782 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -90,7 +90,9 @@ namespace lyx { using cap::copySelection; using cap::cutSelection; +using cap::cutSelectionToTemp; using cap::pasteFromStack; +using cap::pasteFromTemp; using cap::pasteClipboardText; using cap::pasteClipboardGraphics; using cap::replaceSelection; @@ -298,7 +300,7 @@ static bool doInsertInset(Cursor & cur, Text * text, bool gotsel = false; if (cur.selection()) { - cutSelection(cur, false, pastesel); + cutSelectionToTemp(cur, false, pastesel); cur.clearSelection(); gotsel = true; } @@ -310,7 +312,7 @@ static bool doInsertInset(Cursor & cur, Text * text, if (!gotsel || !pastesel) return true; - pasteFromStack(cur, cur.buffer()->errorList("Paste"), 0); + pasteFromTemp(cur, cur.buffer()->errorList("Paste")); cur.buffer()->errors("Paste"); cur.clearSelection(); // bug 393 cur.finishUndo(); diff --git a/status.22x b/status.22x index 239350df85..2c52f5cce6 100644 --- a/status.22x +++ b/status.22x @@ -139,6 +139,9 @@ What's new fixes line breaking issues most noticeably in languages where spaces are rare such as Chinese (bug 10299). +- Do not use the clipboard stack when transforming selection into an + inset (bug 6570). + * INTERNALS -- 2.39.5