sw/qa/core/doc/DocumentRedlineManager.cxx |   12 ++++++++++++
 sw/source/core/undo/unattr.cxx            |   10 ++++++++++
 sw/source/core/undo/undobj.cxx            |   16 +++++++++++++++-
 3 files changed, 37 insertions(+), 1 deletion(-)

New commits:
commit 63e488df28f18baf0444fca1e6a6318cc2d5709b
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Jun 13 09:34:21 2025 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Jun 13 09:52:20 2025 +0200

    tdf#166319 sw interdependent redlines: undo 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 resulted in <ins>AA</ins>BB<ins>CC</ins>
    instead of the original <ins>AABBCC</ins>.
    
    What happened is that the created SwUndoAttr didn't record the deleted
    insert redline, so there was no chance to restore it. The same was
    working for the insert-then-delete case via SwUndoRedlineDelete, because
    that stored the direct delete redline as an SwRedlineData, and also
    stored the underlying insert redline inside SwRedlineSaveDatas.
    
    Fix the problem by extending the types of redlines we save in
    SwUndo::FillSaveDataForFormat(), so SwUndoAttr also saves the insert
    redline in its SwRedlineSaveDatas array, then undo starts to work.
    
    Redo still needs fixing, though.
    
    Change-Id: Ic436974f15633eabcc298f062e57183220a48b27
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186436
    Reviewed-by: Miklos Vajna <vmik...@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 699b1f61570e..667d571b8516 100644
--- a/sw/qa/core/doc/DocumentRedlineManager.cxx
+++ b/sw/qa/core/doc/DocumentRedlineManager.cxx
@@ -66,6 +66,18 @@ CPPUNIT_TEST_FIXTURE(Test, testRedlineIns)
         CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rInnerRedlineData.GetType());
         CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlines[2]->GetType());
     }
+
+    // And when undoing:
+    pWrtShell->Undo();
+
+    // Then make sure we again have a single insert that covers all text:
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 1
+    // - Actual  : 2
+    // i.e. the insert redline of BBB was lost on undo.
+    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());
 }
 }
 
diff --git a/sw/source/core/undo/unattr.cxx b/sw/source/core/undo/unattr.cxx
index 34219649a6de..98d8e6a5c8d5 100644
--- a/sw/source/core/undo/unattr.cxx
+++ b/sw/source/core/undo/unattr.cxx
@@ -800,6 +800,16 @@ void SwUndoAttr::dumpAsXml(xmlTextWriterPtr pWriter) const
         m_pHistory->dumpAsXml(pWriter);
     }
 
+    if (m_pRedlineData)
+    {
+        m_pRedlineData->dumpAsXml(pWriter);
+    }
+
+    if (m_pRedlineSaveData)
+    {
+        m_pRedlineSaveData->dumpAsXml(pWriter);
+    }
+
     (void)xmlTextWriterEndElement(pWriter);
 }
 
diff --git a/sw/source/core/undo/undobj.cxx b/sw/source/core/undo/undobj.cxx
index c4271727ebc2..6c98bde6f64a 100644
--- a/sw/source/core/undo/undobj.cxx
+++ b/sw/source/core/undo/undobj.cxx
@@ -1519,7 +1519,21 @@ bool SwUndo::FillSaveDataForFormat(
     for ( ; n < rTable.size(); ++n )
     {
         SwRangeRedline* pRedl = rTable[n];
-        if ( RedlineType::Format == pRedl->GetType() )
+        bool bSaveRedline = false;
+        switch (pRedl->GetType())
+        {
+            case RedlineType::Insert:
+            case RedlineType::Delete:
+                // These are allowed "under" a format redline.
+            case RedlineType::Format:
+                // This is a previous format: will be removed from the 
document, so save it in the
+                // undo action.
+                bSaveRedline = true;
+                break;
+            default:
+                break;
+        }
+        if (bSaveRedline)
         {
             const SwComparePosition eCmpPos = ComparePosition( *pStart, *pEnd, 
*pRedl->Start(), *pRedl->End() );
             if ( eCmpPos != SwComparePosition::Before

Reply via email to