sw/qa/core/doc/DocumentRedlineManager.cxx | 17 +++++++++++++++++ sw/source/core/undo/unattr.cxx | 8 ++++++++ 2 files changed, 25 insertions(+)
New commits: commit 20f02593e6c493bba60d4760cbf4032e4df80477 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon Jun 16 08:44:19 2025 +0200 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Mon Jun 16 14:08:07 2025 +0200 tdf#166319 sw interdependent redlines: redo of creating an ins-then-fmt redline The bugdoc has <ins>AABBCC</ins> in it, selecting BB, marking the selection as e.g. bold + undo + redo resulted in a plain format redline for BB instead of a hierarchical insert-then-format redline. Checking SwUndoAttr, its item set correctly tracks the boldness, also it tracks the own (format) redline in m_pRedlineData correctly, together with the pre-existing redline data in m_pRedlineSaveData. Also, checking how this works in the undo case, SwUndoAttr::UndoImpl() first deletes all redlines in the interesting text range and then restores the pre-existing redline using a call to SwUndo::SetSaveData(). In the bad case, what instead happens is that SwUndoAttr::redoAttribute() calls sw::DocumentContentOperationsManager::InsertItemSet() with redline tracking enabled, that creates a format redline, then we try to create our own format redline, and the last one wins, losing the underlying insert redline. Fix the problem by improving SwUndoAttr::redoAttribute() to also call SwUndo::SetSaveData() to re-create just the pre-existing insert redline: with this the following AppendRedline() will result in the correct insert-then-format hierarchical redline. Change-Id: I1e1a284c017f39c62dcc03b6b49463bac106f21b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186537 Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> diff --git a/sw/qa/core/doc/DocumentRedlineManager.cxx b/sw/qa/core/doc/DocumentRedlineManager.cxx index 667d571b8516..77f36c8012f1 100644 --- a/sw/qa/core/doc/DocumentRedlineManager.cxx +++ b/sw/qa/core/doc/DocumentRedlineManager.cxx @@ -78,6 +78,23 @@ CPPUNIT_TEST_FIXTURE(Test, testRedlineIns) CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size()); CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlines[0]->GetType()); CPPUNIT_ASSERT_EQUAL(u"AAABBBCCC"_ustr, rRedlines[0]->GetText()); + + // And when redoing: + pWrtShell->Redo(); + + // Then make sure we get <ins>AAA<format>BBB</format>CCC</ins>: + { + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), rRedlines.size()); + CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlines[0]->GetType()); + const SwRedlineData& rRedlineData1 = rRedlines[1]->GetRedlineData(0); + CPPUNIT_ASSERT_EQUAL(RedlineType::Format, rRedlineData1.GetType()); + // Without the accompanying fix in place, this test would have failed, the "format" redline + // has no underlying "insert" redline. + CPPUNIT_ASSERT(rRedlineData1.Next()); + const SwRedlineData& rInnerRedlineData = *rRedlineData1.Next(); + CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rInnerRedlineData.GetType()); + CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlines[2]->GetType()); + } } } diff --git a/sw/source/core/undo/unattr.cxx b/sw/source/core/undo/unattr.cxx index 98d8e6a5c8d5..d8151669b068 100644 --- a/sw/source/core/undo/unattr.cxx +++ b/sw/source/core/undo/unattr.cxx @@ -795,6 +795,8 @@ void SwUndoAttr::dumpAsXml(xmlTextWriterPtr pWriter) const (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwUndoAttr")); (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this); + m_AttrSet.dumpAsXml(pWriter); + if (m_pHistory) { m_pHistory->dumpAsXml(pWriter); @@ -895,6 +897,12 @@ void SwUndoAttr::redoAttribute(SwPaM& rPam, sw::UndoRedoContext & rContext) } rPam.DeleteMark(); } else { + if (m_pRedlineSaveData) + { + // We saved some (typically non-format) redline before our action. First set that on + // the document, so AppendRedline() can create a hierarchical redline. + SetSaveData(rDoc, *m_pRedlineSaveData); + } rDoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( *m_pRedlineData, rPam ), true); }