From 7ef8df460ae85bc19ce37124702599a469beb5eb Mon Sep 17 00:00:00 2001 From: Richard Heck Date: Mon, 4 Jun 2012 13:39:24 -0400 Subject: [PATCH] Fix crash reported by Tommaso: http://marc.info/?l=lyx-devel&m=133876924408431&w=2 The problem here is that the copy_params() routine in FindAndReplace.cpp created a new DocumentClass, but it never updated its Buffer to reflect that new DocumentClass. So its Paragraphs still contained points to the Layouts in the old DocumentClass which, since ead697d4b6c7, gets garbage collected once it is no longer needed. So the Layout doesn't exist, and we crash. --- src/BufferParams.h | 4 ++++ src/BufferView.cpp | 25 +++++++++++++------------ src/BufferView.h | 2 ++ src/frontends/qt4/FindAndReplace.cpp | 2 +- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/BufferParams.h b/src/BufferParams.h index f4f9bef8e0..dac9a4aef6 100644 --- a/src/BufferParams.h +++ b/src/BufferParams.h @@ -124,6 +124,10 @@ public: bool setBaseClass(std::string const & classname); /// Adds the module information to the baseClass information to /// create our local DocumentClass. + /// NOTE: This should NEVER be called externally unless one immediately goes + /// on to class BufferView::updateDocumentClass(). The exception, of course, + /// is in GuiDocument, where we use a BufferParams simply to hold a copy of + /// the parameters from the active Buffer. void makeDocumentClass(); /// Returns the DocumentClass currently in use: the BaseClass as modified /// by modules. diff --git a/src/BufferView.cpp b/src/BufferView.cpp index 6c9aa366b8..ff8482d81a 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -941,6 +941,14 @@ bool BufferView::scrollToCursor(DocIterator const & dit, bool recenter) } +void BufferView::makeDocumentClass() +{ + DocumentClassConstPtr olddc = buffer_.params().documentClassPtr(); + buffer_.params().makeDocumentClass(); + updateDocumentClass(olddc); +} + + void BufferView::updateDocumentClass(DocumentClassConstPtr olddc) { message(_("Converting document to new document class...")); @@ -956,6 +964,7 @@ void BufferView::updateDocumentClass(DocumentClassConstPtr olddc) buffer_.errors("Class Switch"); } + /** Return the change status at cursor position, taking in account the * status at each level of the document iterator (a table in a deleted * footnote is deleted). @@ -1256,11 +1265,9 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) } case LFUN_LAYOUT_MODULES_CLEAR: { - DocumentClassConstPtr oldClass = buffer_.params().documentClassPtr(); cur.recordUndoFullDocument(); buffer_.params().clearLayoutModules(); - buffer_.params().makeDocumentClass(); - updateDocumentClass(oldClass); + makeDocumentClass(); dr.screenUpdate(Update::Force); dr.forceBufferUpdate(); break; @@ -1274,11 +1281,9 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) "conflicts with installed modules."); break; } - DocumentClassConstPtr oldClass = params.documentClassPtr(); cur.recordUndoFullDocument(); buffer_.params().addLayoutModule(argument); - buffer_.params().makeDocumentClass(); - updateDocumentClass(oldClass); + makeDocumentClass(); dr.screenUpdate(Update::Force); dr.forceBufferUpdate(); break; @@ -1305,11 +1310,9 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) break; // Save the old, possibly modular, layout for use in conversion. - DocumentClassConstPtr oldDocClass = buffer_.params().documentClassPtr(); cur.recordUndoFullDocument(); buffer_.params().setBaseClass(argument); - buffer_.params().makeDocumentClass(); - updateDocumentClass(oldDocClass); + makeDocumentClass(); dr.screenUpdate(Update::Force); dr.forceBufferUpdate(); break; @@ -1330,12 +1333,10 @@ void BufferView::dispatch(FuncRequest const & cmd, DispatchResult & dr) } case LFUN_LAYOUT_RELOAD: { - DocumentClassConstPtr oldClass = buffer_.params().documentClassPtr(); LayoutFileIndex bc = buffer_.params().baseClassID(); LayoutFileList::get().reset(bc); buffer_.params().setBaseClass(bc); - buffer_.params().makeDocumentClass(); - updateDocumentClass(oldClass); + makeDocumentClass(); dr.screenUpdate(Update::Force); dr.forceBufferUpdate(); break; diff --git a/src/BufferView.h b/src/BufferView.h index d164438ad5..a58d251727 100644 --- a/src/BufferView.h +++ b/src/BufferView.h @@ -318,6 +318,8 @@ public: void clearLastInset(Inset * inset) const; /// Is the mouse hovering a clickable inset or element? bool clickableInset() const; + /// + void makeDocumentClass(); private: /// noncopyable diff --git a/src/frontends/qt4/FindAndReplace.cpp b/src/frontends/qt4/FindAndReplace.cpp index a4e973ba79..610168fe5f 100644 --- a/src/frontends/qt4/FindAndReplace.cpp +++ b/src/frontends/qt4/FindAndReplace.cpp @@ -503,7 +503,7 @@ static void copy_params(BufferView const & bv, BufferView & dest_bv) { Buffer & dest_buf = dest_bv.buffer(); dest_buf.params().setLanguage(lang); dest_buf.params().setBaseClass(doc_class); - dest_buf.params().makeDocumentClass(); + dest_bv.makeDocumentClass(); dest_bv.cursor().current_font.setLanguage(doc_bp.language); } -- 2.39.2