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 fb264663d8)
(cherry picked from commit 004fdf6aeb)
This commit is contained in:
Jean-Marc Lasgouttes 2016-11-09 15:13:41 +01:00
parent 1e80436968
commit 133c2c62ee
4 changed files with 72 additions and 15 deletions

View File

@ -86,6 +86,8 @@ typedef limited_stack<pair<ParagraphList, DocumentClassConstPtr> > CutStack;
CutStack theCuts(10); CutStack theCuts(10);
// persistent selection, cleared until the next selection // persistent selection, cleared until the next selection
CutStack selectionBuffer(1); CutStack selectionBuffer(1);
// temporary scratch area
CutStack tempCut(1);
// store whether the tabular stack is newer than the normal copy stack // 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, // FIXME: this is a workaround for bug 1919. Should be removed for 1.5,
@ -111,7 +113,7 @@ struct PasteReturnValue {
PasteReturnValue PasteReturnValue
pasteSelectionHelper(DocIterator const & cur, ParagraphList const & parlist, pasteSelectionHelper(DocIterator const & cur, ParagraphList const & parlist,
DocumentClassConstPtr oldDocClass, Buffer * tmpbuffer, DocumentClassConstPtr oldDocClass, cap::BranchAction branchAction,
ErrorList & errorlist) ErrorList & errorlist)
{ {
Buffer const & buffer = *cur.buffer(); Buffer const & buffer = *cur.buffer();
@ -355,12 +357,15 @@ pasteSelectionHelper(DocIterator const & cur, ParagraphList const & parlist,
|| (is_child && (branchlist.find(name) || (is_child && (branchlist.find(name)
|| buffer.masterBuffer()->params().branchlist().find(name)))) || buffer.masterBuffer()->params().branchlist().find(name))))
break; break;
if (tmpbuffer) { switch(branchAction) {
case cap::BRANCH_ADD: {
// This is for a temporary buffer, so simply create the branch. // This is for a temporary buffer, so simply create the branch.
// Must not use lyx::dispatch(), since tmpbuffer has no view. // Must not use lyx::dispatch(), since tmpbuffer has no view.
DispatchResult dr; DispatchResult dr;
tmpbuffer->dispatch(FuncRequest(LFUN_BRANCH_ADD, name), dr); const_cast<Buffer&>(buffer).dispatch(FuncRequest(LFUN_BRANCH_ADD, name), dr);
} else { break;
}
case cap::BRANCH_ASK: {
docstring text = bformat( docstring text = bformat(
_("The pasted branch \"%1$s\" is undefined.\n" _("The pasted branch \"%1$s\" is undefined.\n"
"Do you want to add it to the document's branch list?"), "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) text, 0, 1, _("&Add"), _("&Don't Add")) != 0)
break; break;
lyx::dispatch(FuncRequest(LFUN_BRANCH_ADD, name)); lyx::dispatch(FuncRequest(LFUN_BRANCH_ADD, name));
break;
}
case cap::BRANCH_IGNORE:
break;
} }
// We need to update the list of branches. // We need to update the list of branches.
need_update = true; 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. // temporary Buffer, since it does a lot of things to fix them up.
DocIterator dit = doc_iterator_begin(buffer, &buffer->inset()); DocIterator dit = doc_iterator_begin(buffer, &buffer->inset());
ErrorList el; ErrorList el;
pasteSelectionHelper(dit, paragraphs, docclass, buffer, el); pasteSelectionHelper(dit, paragraphs, docclass, cap::BRANCH_ADD, el);
return buffer; return buffer;
} }
@ -836,8 +845,9 @@ size_type numberOfSelections()
return theCuts.size(); 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 // This doesn't make sense, if there is no selection
if (!cur.selection()) if (!cur.selection())
@ -865,11 +875,12 @@ void cutSelection(Cursor & cur, bool doclear, bool realcut)
*text, *text,
begpit, endpit, begpit, endpit,
cur.selBegin().pos(), endpos, cur.selBegin().pos(), endpos,
bp.documentClassPtr(), theCuts); bp.documentClassPtr(), cuts);
// Stuff what we got on the clipboard. // Stuff what we got on the clipboard.
// Even if there is no selection. // Even if there is no selection.
putClipboard(theCuts[0].first, theCuts[0].second, if (putclip)
cur.selectionAsString(true)); putClipboard(cuts[0].first, cuts[0].second,
cur.selectionAsString(true));
} }
if (begpit != endpit) 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) void copySelection(Cursor const & cur)
{ {
@ -1047,6 +1071,7 @@ void clearSelection()
void clearCutStack() void clearCutStack()
{ {
theCuts.clear(); theCuts.clear();
tempCut.clear();
} }
@ -1064,14 +1089,15 @@ docstring selection(size_t sel_index, DocumentClassConstPtr docclass)
void pasteParagraphList(Cursor & cur, ParagraphList const & parlist, void pasteParagraphList(Cursor & cur, ParagraphList const & parlist,
DocumentClassConstPtr docclass, ErrorList & errorList) DocumentClassConstPtr docclass, ErrorList & errorList,
cap::BranchAction branchAction)
{ {
if (cur.inTexted()) { if (cur.inTexted()) {
Text * text = cur.text(); Text * text = cur.text();
LBUFERR(text); LBUFERR(text);
PasteReturnValue prv = PasteReturnValue prv =
pasteSelectionHelper(cur, parlist, docclass, 0, errorList); pasteSelectionHelper(cur, parlist, docclass, branchAction, errorList);
cur.forceBufferUpdate(); cur.forceBufferUpdate();
cur.clearSelection(); cur.clearSelection();
text->setCursor(cur, prv.par, prv.pos); text->setCursor(cur, prv.par, prv.pos);
@ -1090,7 +1116,20 @@ bool pasteFromStack(Cursor & cur, ErrorList & errorList, size_t sel_index)
cur.recordUndo(); cur.recordUndo();
pasteParagraphList(cur, theCuts[sel_index].first, 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; return true;
} }

View File

@ -61,6 +61,9 @@ void replaceSelection(Cursor & cur);
* selection. * selection.
*/ */
void cutSelection(Cursor & cur, bool doclear = true, bool realcut = true); 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. /// Push the current selection to the cut buffer and the system clipboard.
void copySelection(Cursor const & cur); 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 /// Replace the current selection with cut buffer \c sel_index
/// Does handle undo. Does only work in text, not mathed. /// Does handle undo. Does only work in text, not mathed.
bool pasteFromStack(Cursor & cur, ErrorList & errorList, size_t sel_index); 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 /// Paste the clipboard as simple text, removing any formatting
void pasteSimpleText(Cursor & cur, bool asParagraphs); 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. /// Paste the paragraph list \p parlist at the position given by \p cur.
/// Does not handle undo. Does only work in text, not mathed. /// Does not handle undo. Does only work in text, not mathed.
void pasteParagraphList(Cursor & cur, ParagraphList const & parlist, 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 /** Needed to switch between different classes. This works

View File

@ -90,7 +90,9 @@ namespace lyx {
using cap::copySelection; using cap::copySelection;
using cap::cutSelection; using cap::cutSelection;
using cap::cutSelectionToTemp;
using cap::pasteFromStack; using cap::pasteFromStack;
using cap::pasteFromTemp;
using cap::pasteClipboardText; using cap::pasteClipboardText;
using cap::pasteClipboardGraphics; using cap::pasteClipboardGraphics;
using cap::replaceSelection; using cap::replaceSelection;
@ -298,7 +300,7 @@ static bool doInsertInset(Cursor & cur, Text * text,
bool gotsel = false; bool gotsel = false;
if (cur.selection()) { if (cur.selection()) {
cutSelection(cur, false, pastesel); cutSelectionToTemp(cur, false, pastesel);
cur.clearSelection(); cur.clearSelection();
gotsel = true; gotsel = true;
} }
@ -310,7 +312,7 @@ static bool doInsertInset(Cursor & cur, Text * text,
if (!gotsel || !pastesel) if (!gotsel || !pastesel)
return true; return true;
pasteFromStack(cur, cur.buffer()->errorList("Paste"), 0); pasteFromTemp(cur, cur.buffer()->errorList("Paste"));
cur.buffer()->errors("Paste"); cur.buffer()->errors("Paste");
cur.clearSelection(); // bug 393 cur.clearSelection(); // bug 393
cur.finishUndo(); cur.finishUndo();

View File

@ -139,6 +139,9 @@ What's new
fixes line breaking issues most noticeably in languages where spaces are rare fixes line breaking issues most noticeably in languages where spaces are rare
such as Chinese (bug 10299). such as Chinese (bug 10299).
- Do not use the clipboard stack when transforming selection into an
inset (bug 6570).
* INTERNALS * INTERNALS