In the existing codebase, there is a problem about how Insets get their Buffers set after undo/redo. What we do at the moment is go through the *entire Buffer* and set the Buffer for every single inset. This seems like overkill. The attached patch fixes this by just setting the Buffers for the newly created insets, i.e., those in the paragraphs we just pasted.
I'm proposing this at the moment for master only, but would appreciate comments first. The second patch is just a renaming, from Paragraph::setBuffer to Paragraph::setInsetBuffers. The former is misleading as to what the method does. I'd like to commit this to master and 2.3.x, the latter simply to avoid conflicts when cherry-picking. Richard
>From 2d77bd1c027b26efcb31691bb640d124e65a63c8 Mon Sep 17 00:00:00 2001 From: Richard Heck <rgh...@lyx.org> Date: Sun, 15 Oct 2017 22:22:22 -0400 Subject: [PATCH 1/2] Fix the way that the Buffer gets set on undo. Previously, we went through the entire Buffer and set it for every single inset. Now we just do it for the insets we pasted. --- src/Buffer.cpp | 6 ------ src/Buffer.h | 4 ---- src/Undo.cpp | 15 ++++++++++++--- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/Buffer.cpp b/src/Buffer.cpp index c4ce8ea..89a76b5 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -4699,12 +4699,6 @@ void Buffer::bufferErrors(TeXErrors const & terr, ErrorList & errorList) const } -void Buffer::setBuffersForInsets() const -{ - inset().setBuffer(const_cast<Buffer &>(*this)); -} - - void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const { LBUFERR(!text().paragraphs().empty()); diff --git a/src/Buffer.h b/src/Buffer.h index 165f5d8..6d50e70 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -719,10 +719,6 @@ public: /// return a list of all used branches (also in children) void getUsedBranches(std::list<docstring> &, bool const from_master = false) const; - /// sets the buffer_ member for every inset in this buffer. - // FIXME This really shouldn't be needed, but at the moment it's not - // clear how to do it just for the individual pieces we need. - void setBuffersForInsets() const; /// Updates screen labels and some other information associated with /// insets and paragraphs. Actually, it's more like a general "recurse /// through the Buffer" routine, that visits all the insets and paragraphs. diff --git a/src/Undo.cpp b/src/Undo.cpp index a479728..4798737 100644 --- a/src/Undo.cpp +++ b/src/Undo.cpp @@ -497,6 +497,18 @@ void Undo::Private::doTextUndoOrRedo(CursorData & cur, UndoElementStack & stack, for (; pit != end; ++pit) pit->setInsetOwner(dit.realInset()); plist.insert(first, undo.pars->begin(), undo.pars->end()); + + // set the buffers for insets we created + // pargraphs were inserted before first, so first paragraph + // inserted is first - 1 + ParagraphList::iterator fpit = first; + advance(fpit, -1); + // one more than last paragraph we inserted + ParagraphList::iterator fend = fpit; + advance(fend, undo.pars->size()); + for (; fpit != fend; ++fpit) + fpit->setBuffer(buffer_); + delete undo.pars; undo.pars = 0; } @@ -531,9 +543,6 @@ bool Undo::Private::textUndoOrRedo(CursorData & cur, bool isUndoOperation) const size_t gid = stack.top().group_id; while (!stack.empty() && stack.top().group_id == gid) doTextUndoOrRedo(cur, stack, otherstack); - - // Adapt the new material to current buffer. - buffer_.setBuffersForInsets(); // FIXME This shouldn't be here. return true; } -- 2.9.5
>From ff21a3cc972ce8b874f8023e1afac9544a7611c3 Mon Sep 17 00:00:00 2001 From: Richard Heck <rgh...@lyx.org> Date: Sun, 15 Oct 2017 22:14:08 -0400 Subject: [PATCH 2/2] Rename Paragraph::setBuffer to Paragraph::setInsetBuffers, to avoid confusion about what this routine does. --- src/Compare.cpp | 2 +- src/CutAndPaste.cpp | 6 +++--- src/Paragraph.cpp | 2 +- src/Paragraph.h | 2 +- src/Undo.cpp | 2 +- src/insets/InsetText.cpp | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Compare.cpp b/src/Compare.cpp index 796eb19..214f25c 100644 --- a/src/Compare.cpp +++ b/src/Compare.cpp @@ -736,7 +736,7 @@ bool Compare::Impl::diff(Buffer const * new_buf, Buffer const * old_buf, diff_i(rp_new); for (pit_type p = 0; p < (pit_type)dest_pars_->size(); ++p) { - (*dest_pars_)[p].setBuffer(const_cast<Buffer &>(*dest_buf)); + (*dest_pars_)[p].setInsetBuffers(const_cast<Buffer &>(*dest_buf)); (*dest_pars_)[p].setInsetOwner(&dest_buf_->inset()); } diff --git a/src/CutAndPaste.cpp b/src/CutAndPaste.cpp index 05f9b90..b649d8f 100644 --- a/src/CutAndPaste.cpp +++ b/src/CutAndPaste.cpp @@ -422,7 +422,7 @@ pasteSelectionHelper(DocIterator const & cur, ParagraphList const & parlist, // 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 &>(buffer)); + pars[p].setInsetBuffers(const_cast<Buffer &>(buffer)); // Join (conditionally) last pasted paragraph with next one, i.e., // the tail of the spliced document paragraph @@ -631,7 +631,7 @@ void copySelectionHelper(Buffer const & buf, Text const & text, // 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<Buffer &>(buf)); + it->setInsetBuffers(const_cast<Buffer &>(buf)); // PassThru paragraphs have the Language // latex_language. This is invalid for others, so we // need to change it to the buffer language. @@ -827,7 +827,7 @@ vector<docstring> availableSelections(Buffer const * buf) for (; pit != pend; ++pit) { Paragraph par(*pit, 0, 46); // adapt paragraph to current buffer. - par.setBuffer(const_cast<Buffer &>(*buf)); + par.setInsetBuffers(const_cast<Buffer &>(*buf)); textSel += par.asString(AS_STR_INSETS); if (textSel.size() > 45) { support::truncateWithEllipsis(textSel,45); diff --git a/src/Paragraph.cpp b/src/Paragraph.cpp index c9a234d..7620251 100644 --- a/src/Paragraph.cpp +++ b/src/Paragraph.cpp @@ -3673,7 +3673,7 @@ InsetList const & Paragraph::insetList() const } -void Paragraph::setBuffer(Buffer & b) +void Paragraph::setInsetBuffers(Buffer & b) { d->insetlist_.setBuffer(b); } diff --git a/src/Paragraph.h b/src/Paragraph.h index d462f4c..790c3f2 100644 --- a/src/Paragraph.h +++ b/src/Paragraph.h @@ -397,7 +397,7 @@ public: /// InsetList const & insetList() const; /// - void setBuffer(Buffer &); + void setInsetBuffers(Buffer &); /// void resetBuffer(); diff --git a/src/Undo.cpp b/src/Undo.cpp index 4798737..2ecda7f 100644 --- a/src/Undo.cpp +++ b/src/Undo.cpp @@ -507,7 +507,7 @@ void Undo::Private::doTextUndoOrRedo(CursorData & cur, UndoElementStack & stack, ParagraphList::iterator fend = fpit; advance(fend, undo.pars->size()); for (; fpit != fend; ++fpit) - fpit->setBuffer(buffer_); + fpit->setInsetBuffers(buffer_); delete undo.pars; undo.pars = 0; diff --git a/src/insets/InsetText.cpp b/src/insets/InsetText.cpp index 8228fd2..cf41883 100644 --- a/src/insets/InsetText.cpp +++ b/src/insets/InsetText.cpp @@ -97,7 +97,7 @@ void InsetText::setBuffer(Buffer & buf) { ParagraphList::iterator end = paragraphs().end(); for (ParagraphList::iterator it = paragraphs().begin(); it != end; ++it) - it->setBuffer(buf); + it->setInsetBuffers(buf); Inset::setBuffer(buf); } -- 2.9.5