From aacc5147b633b738579f283c518cceb305b73d38 Mon Sep 17 00:00:00 2001 From: Richard Kimberly Heck Date: Fri, 28 Jul 2023 22:57:57 -0400 Subject: [PATCH] Fix crash when modifying an InsetRef inserted by the current author. The problem was that, in this case, we actually delete the current inset in changeCmdName. So when we return from that and attempt to call initView(), we're in a non-existent inset. --- src/Cursor.cpp | 6 +++--- src/insets/InsetCommand.cpp | 26 +++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/Cursor.cpp b/src/Cursor.cpp index 98b2b156f0..b20ab0fc0e 100644 --- a/src/Cursor.cpp +++ b/src/Cursor.cpp @@ -789,15 +789,15 @@ void Cursor::dispatch(FuncRequest const & cmd0) beginUndoGroup(); + Inset * nextins = nextInset(); // Is this a function that acts on inset at point? - if (lyxaction.funcHasFlag(cmd.action(), LyXAction::AtPoint) - && nextInset()) { + if (lyxaction.funcHasFlag(cmd.action(), LyXAction::AtPoint) && nextins) { disp_.dispatched(true); disp_.screenUpdate(Update::FitCursor | Update::Force); FuncRequest tmpcmd = cmd; LYXERR(Debug::ACTION, "Cursor::dispatch: (AtPoint) cmd: " << cmd0 << endl << *this); - nextInset()->dispatch(*this, tmpcmd); + nextins->dispatch(*this, tmpcmd); if (disp_.dispatched()) { endUndoGroup(); return; diff --git a/src/insets/InsetCommand.cpp b/src/insets/InsetCommand.cpp index 9ca958b5f8..b16259da7d 100644 --- a/src/insets/InsetCommand.cpp +++ b/src/insets/InsetCommand.cpp @@ -20,6 +20,7 @@ #include "Cursor.h" #include "FuncRequest.h" #include "FuncStatus.h" +#include "InsetIterator.h" #include "Lexer.h" #include "LyX.h" #include "MetricsInfo.h" @@ -191,7 +192,30 @@ void InsetCommand::changeCmdName(string const & new_name) if (buffer().masterParams().track_changes) { // With change tracking, we insert a new inset and - // delete the old one + // delete the old one. + // But we need to make sure that the inset isn't one + // that the current author inserted. Otherwise, we might + // delete ourselves! + InsetIterator it = begin(buffer().inset()); + InsetIterator const itend = end(buffer().inset()); + for (; it != itend; ++it) { + if (&*it == this) + break; + } + if (it == itend) { + LYXERR0("Unable to find inset!"); + p_.setCmdName(new_name); + return; + } + Paragraph const & ourpara = it.paragraph(); + pos_type const ourpos = it.pos(); + Change const & change = ourpara.lookupChange(ourpos); + if (change.currentAuthor()) { + p_.setCmdName(new_name); + return; + } + + // OK, so this is not an inset the current author inserted InsetCommandParams p(p_.code()); p = p_; p.setCmdName(new_name);