X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FCutAndPaste.cpp;h=a30f40040714e0bfbdbe4642bea3f03b661db4d1;hb=2098f1d8c20d51e63e670bcdc9da8996068975bf;hp=610f71caf88284e4f09febaeded123ec3a692db4;hpb=0bee8a3b5633cc89661cf7d73c96a18365e73218;p=lyx.git diff --git a/src/CutAndPaste.cpp b/src/CutAndPaste.cpp index 610f71caf8..a30f400407 100644 --- a/src/CutAndPaste.cpp +++ b/src/CutAndPaste.cpp @@ -15,6 +15,7 @@ #include "CutAndPaste.h" +#include "BranchList.h" #include "Buffer.h" #include "buffer_funcs.h" #include "BufferList.h" @@ -32,13 +33,13 @@ #include "LyXRC.h" #include "Text.h" #include "Paragraph.h" -#include "paragraph_funcs.h" #include "ParagraphParameters.h" #include "ParIterator.h" #include "Undo.h" -#include "insets/InsetFlex.h" +#include "insets/InsetBranch.h" #include "insets/InsetCommand.h" +#include "insets/InsetFlex.h" #include "insets/InsetGraphics.h" #include "insets/InsetGraphicsParams.h" #include "insets/InsetInclude.h" @@ -54,6 +55,7 @@ #include "support/limited_stack.h" #include "support/lstrings.h" +#include "frontends/alert.h" #include "frontends/Clipboard.h" #include "frontends/Selection.h" @@ -161,7 +163,7 @@ pasteSelectionHelper(Cursor & cur, ParagraphList const & parlist, } } - InsetText in(buffer); + InsetText in(cur.buffer()); // Make sure there is no class difference. in.paragraphs().clear(); // This works without copying any paragraph data because we have @@ -221,14 +223,12 @@ pasteSelectionHelper(Cursor & cur, ParagraphList const & parlist, InsetIterator const i_end = inset_iterator_end(in); for (InsetIterator it = inset_iterator_begin(in); it != i_end; ++it) { - // Insets store buffer references so need updating. - // FIXME This code can probably be deleted. The insets will get copied - // when they are pasted, at which point their buffer_ members will get - // set back to zero. + // Even though this will also be done later, it has to be done here + // since, e.g., InsetLabel::updateCommand() is going to try to access + // the buffer() member. it->setBuffer(const_cast(buffer)); - switch (it->lyxCode()) { - + case LABEL_CODE: { // check for duplicates InsetCommand & lab = static_cast(*it); @@ -273,6 +273,31 @@ pasteSelectionHelper(Cursor & cur, ParagraphList const & parlist, break; } + case BRANCH_CODE: { + // check if branch is known to target buffer + // or its master + InsetBranch & br = static_cast(*it); + docstring const name = br.branch(); + if (name.empty()) + break; + bool const is_child = (&buffer != buffer.masterBuffer()); + BranchList branchlist = buffer.params().branchlist(); + if ((!is_child && branchlist.find(name)) + || (is_child && (branchlist.find(name) + || buffer.masterBuffer()->params().branchlist().find(name)))) + break; + // FIXME: add an option to add the branch to the master's BranchList. + docstring text = bformat( + _("The pasted branch \"%1$s\" is undefined.\n" + "Do you want to add it to the document's branch list?"), + name); + if (frontend::Alert::prompt(_("Unknown branch"), + text, 0, 1, _("&Add"), _("&Don't Add")) != 0) + break; + lyx::dispatch(FuncRequest(LFUN_BRANCH_ADD, name)); + break; + } + default: break; // nothing } @@ -307,12 +332,12 @@ pasteSelectionHelper(Cursor & cur, ParagraphList const & parlist, pit = last_paste; pos = pars[last_paste].size(); + // FIXME Should we do it here, or should we let updateLabels() do it? // Set paragraph buffers. It's important to do this right away // before something calls Inset::buffer() and causes a crash. for (pit_type p = startpit; p <= pit; ++p) pars[p].setBuffer(const_cast(buffer)); - // Join (conditionally) last pasted paragraph with next one, i.e., // the tail of the spliced document paragraph if (!empty && last_paste + 1 != pit_type(pars.size())) { @@ -404,10 +429,27 @@ void putClipboard(ParagraphList const & paragraphs, } -void copySelectionHelper(Buffer const & buf, ParagraphList const & pars, +/// return true if the whole ParagraphList is deleted +static bool isFullyDeleted(ParagraphList const & pars) +{ + pit_type const pars_size = static_cast(pars.size()); + + // check all paragraphs + for (pit_type pit = 0; pit < pars_size; ++pit) { + if (!pars[pit].empty()) // prevent assertion failure + if (!pars[pit].isDeleted(0, pars[pit].size())) + return false; + } + return true; +} + + +void copySelectionHelper(Buffer const & buf, Text const & text, pit_type startpit, pit_type endpit, int start, int end, DocumentClass const * const dc, CutStack & cutstack) { + ParagraphList const & pars = text.paragraphs(); + LASSERT(0 <= start && start <= pars[startpit].size(), /**/); LASSERT(0 <= end && end <= pars[endpit].size(), /**/); LASSERT(startpit != endpit || start <= end, /**/); @@ -430,17 +472,32 @@ void copySelectionHelper(Buffer const & buf, ParagraphList const & pars, ParagraphList::iterator it_end = copy_pars.end(); for (; it != it_end; it++) { - // ERT paragraphs have the Language latex_language. - // This is invalid outside of ERT, so we need to change it - // to the buffer language. - if (it->ownerCode() == ERT_CODE || it->ownerCode() == LISTINGS_CODE) { - it->changeLanguage(buf.params(), latex_language, buf.language()); - } - it->setInsetOwner(0); + // Since we have a copy of the paragraphs, the insets + // do not have a proper buffer reference. It makes + // sense to add them temporarily, because the + // operations below depend on that (acceptChanges included). + it->setBuffer(const_cast(buf)); + // PassThru paragraphs have the Language + // latex_language. This is invalid for others, so we + // need to change it to the buffer language. + if (text.inset().getLayout().isPassThru()) + it->changeLanguage(buf.params(), + latex_language, buf.language()); } - // do not copy text (also nested in insets) which is marked as deleted - acceptChanges(copy_pars, buf.params()); + // do not copy text (also nested in insets) which is marked as + // deleted, unless the whole selection was deleted + if (!isFullyDeleted(copy_pars)) + acceptChanges(copy_pars, buf.params()); + + + // do some final cleanup now, to make sure that the paragraphs + // are not linked to something else. + it = copy_pars.begin(); + for (; it != it_end; it++) { + it->setBuffer(*static_cast(0)); + it->setInsetOwner(0); + } DocumentClass * d = const_cast(dc); cutstack.push(make_pair(copy_pars, d)); @@ -548,21 +605,20 @@ void switchBetweenClasses(DocumentClass const * const oldone, // character styles InsetIterator const i_end = inset_iterator_end(in); for (InsetIterator it = inset_iterator_begin(in); it != i_end; ++it) { - InsetCollapsable * inset = it->asInsetCollapsable(); - if (!inset) - continue; - if (inset->lyxCode() != FLEX_CODE) + if (it->lyxCode() != FLEX_CODE) // FIXME: Should we verify all InsetCollapsable? continue; - inset->setLayout(newone); - if (!inset->undefined()) + docstring const & n = newone->insetLayout(it->name()).name(); + bool const is_undefined = n.empty() || + n == DocumentClass::plainInsetLayout().name(); + if (!is_undefined) continue; // The flex inset is undefined in newtc docstring const s = bformat(_( "Flex inset %1$s is " "undefined because of class " "conversion from\n%2$s to %3$s"), - inset->name(), from_utf8(oldtc.name()), + it->name(), from_utf8(oldtc.name()), from_utf8(newtc.name())); // To warn the user that something had to be done. errorlist.push_back(ErrorItem( @@ -637,7 +693,7 @@ void cutSelection(Cursor & cur, bool doclear, bool realcut) BufferParams const & bp = cur.buffer()->params(); if (realcut) { copySelectionHelper(*cur.buffer(), - text->paragraphs(), + *text, begpit, endpit, cur.selBegin().pos(), endpos, bp.documentClassPtr(), theCuts); @@ -739,10 +795,14 @@ void copySelectionToStack(Cursor const & cur, CutStack & cutstack) (par != cur.selEnd().pit() || pos < cur.selEnd().pos())) ++pos; - copySelectionHelper(*cur.buffer(), pars, par, cur.selEnd().pit(), + copySelectionHelper(*cur.buffer(), *text, par, cur.selEnd().pit(), pos, cur.selEnd().pos(), cur.buffer()->params().documentClassPtr(), cutstack); - dirtyTabularStack(false); + + // Reset the dirty_tabular_stack_ flag only when something + // is copied to the clipboard (not to the selectionBuffer). + if (&cutstack == &theCuts) + dirtyTabularStack(false); } if (cur.inMathed()) { @@ -898,9 +958,9 @@ void pasteClipboardText(Cursor & cur, ErrorList & errorList, bool asParagraphs) return; cur.recordUndo(); if (asParagraphs) - cur.text()->insertStringAsParagraphs(cur, text); + cur.text()->insertStringAsParagraphs(cur, text, cur.current_font); else - cur.text()->insertStringAsLines(cur, text); + cur.text()->insertStringAsLines(cur, text, cur.current_font); } @@ -915,7 +975,7 @@ void pasteClipboardGraphics(Cursor & cur, ErrorList & /* errorList */, return; // create inset for graphic - InsetGraphics * inset = new InsetGraphics(*cur.buffer()); + InsetGraphics * inset = new InsetGraphics(cur.buffer()); InsetGraphicsParams params; params.filename = support::DocFileName(filename.absFilename()); inset->setParams(params); @@ -1044,7 +1104,8 @@ docstring grabSelection(Cursor const & cur) if (i1.idx() == i2.idx()) { if (i1.inset().asInsetMath()) { MathData::const_iterator it = i1.cell().begin(); - return asString(MathData(it + i1.pos(), it + i2.pos())); + Buffer * buf = cur.buffer(); + return asString(MathData(buf, it + i1.pos(), it + i2.pos())); } else { return from_ascii("unknown selection 1"); }