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 0566e8e1776921ecb26f0ddd0546ec10afeed8e0
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 12:47:55 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/+/186449
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.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 abc62eab27a6..55bc6ad26c1d 100644
--- a/sw/source/core/undo/unattr.cxx
+++ b/sw/source/core/undo/unattr.cxx
@@ -818,6 +818,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 36f63b6436d4..6d73d8d80c11 100644
--- a/sw/source/core/undo/undobj.cxx
+++ b/sw/source/core/undo/undobj.cxx
@@ -1522,7 +1522,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