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);
         }
 

Reply via email to