sw/qa/core/doc/doc.cxx                        |   37 ++++++++++++++++++++++++++
 sw/source/core/doc/DocumentRedlineManager.cxx |   11 ++++++-
 sw/source/core/undo/unredln.cxx               |    4 ++
 3 files changed, 50 insertions(+), 2 deletions(-)

New commits:
commit 0a33618f791995a6a67aad14cd7b65976ffd8eda
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon Jul 7 10:52:26 2025 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Mon Jul 7 14:25:08 2025 +0200

    tdf#166319 sw interdependent redlines: fix redo of accept of ins-then-fmt's 
fmt
    
    The bugdoc has <ins>AA<format>BB</format>CC</ins>, go to middle of BB,
    accept, undo, redo: there is no format redline in the document, but
    there should be one.
    
    What happens is that the "accept" action creates an SwUndoAcceptRedline
    with the default depth = 0, but then it carefully calls
    lcl_DeleteInnerRedline() in
    sw::DocumentRedlineManager::AcceptRedlineRange() instead of a plain
    accept.
    
    The undo action already knows how to only accept the underlying redline,
    so fix the problem in sw::DocumentRedlineManager::AcceptRedlineRange()
    by correctly recording the UI action with depth = 1, which gives us both
    working undo & redo.
    
    The exec of the undo action's redo calls
    sw::DocumentRedlineManager::AcceptRedline(), which now calls the same
    lcl_DeleteInnerRedline() as the original UI action, so this looks
    consistent now.
    
    Change-Id: Ibb21c0745f3dd0aacec7cf7448c7c85245dbee69
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187467
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx
index ba2520d4054e..96869044ce82 100644
--- a/sw/qa/core/doc/doc.cxx
+++ b/sw/qa/core/doc/doc.cxx
@@ -908,6 +908,43 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testInsThenFormat)
     // Without the accompanying fix in place, this test would have failed, the 
text was AAABBBCCC,
     // just the format of BBB was dropped.
     CPPUNIT_ASSERT(pTextNode->GetText().isEmpty());
+
+    // And given a state where you're just after the undo for the accept of 
insert-then-format's
+    // format:
+    pWrtShell->Undo();
+    // Undo() creates a new cursor.
+    pCursor = pWrtShell->GetCursor();
+    pCursor->DeleteMark();
+    pWrtShell->SttEndDoc(/*bStt=*/true);
+    // Move inside "BBB".
+    pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 4, 
/*bBasicCall=*/false);
+    nRedline = 0;
+    rRedlines.FindAtPosition(*pCursor->Start(), nRedline);
+    // A redline is found.
+    CPPUNIT_ASSERT_LESS(rRedlines.size(), nRedline);
+    pWrtShell->AcceptRedline(nRedline);
+    pWrtShell->Undo();
+
+    // When redoing that accept:
+    pWrtShell->Redo();
+
+    // Then make sure we have a single format redline as a result:
+    pCursor = pWrtShell->GetCursor();
+    pCursor->DeleteMark();
+    pWrtShell->SttEndDoc(/*bStt=*/true);
+    // Move inside "BBB".
+    pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 4, 
/*bBasicCall=*/false);
+    nRedline = 0;
+    pRedline = rRedlines.FindAtPosition(*pCursor->Start(), nRedline);
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 1
+    // - Actual  : 0
+    // i.e. everything was accepted, even the format redline was gone from the 
document, instead of
+    // just accepting the underlying insert.
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());
+    CPPUNIT_ASSERT(pRedline);
+    CPPUNIT_ASSERT_EQUAL(RedlineType::Format, pRedline->GetType());
+    CPPUNIT_ASSERT(!pRedline->GetRedlineData().Next());
 }
 
 CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testDelThenFormat)
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx 
b/sw/source/core/doc/DocumentRedlineManager.cxx
index a02f5b947a57..8d8358d0fe80 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -3358,15 +3358,22 @@ bool 
DocumentRedlineManager::AcceptRedlineRange(SwRedlineTable::size_type nPosOr
         }
         else if (pTmp->GetRedlineData(0).CanCombineForAcceptReject(aOrigData))
         {
+            bool bHierarchicalFormat = pTmp->GetType() == RedlineType::Format 
&& pTmp->GetStackCount() > 1;
             if (m_rDoc.GetIDocumentUndoRedo().DoesUndo())
             {
+                sal_Int8 nDepth = 0;
+                if (bHierarchicalFormat && pTmp->GetType(1) == 
RedlineType::Insert)
+                {
+                    // Only work with the underlying insert, so the undo 
action matches the UI
+                    // action below.
+                    nDepth = 1;
+                }
                 m_rDoc.GetIDocumentUndoRedo().AppendUndo(
-                    std::make_unique<SwUndoAcceptRedline>(*pTmp));
+                    std::make_unique<SwUndoAcceptRedline>(*pTmp, nDepth));
             }
             nPamEndNI = pTmp->Start()->GetNodeIndex();
             nPamEndCI = pTmp->Start()->GetContentIndex();
 
-            bool bHierarchicalFormat = pTmp->GetType() == RedlineType::Format 
&& pTmp->GetStackCount() > 1;
             if (bHierarchicalFormat && pTmp->GetType(1) == RedlineType::Insert)
             {
                 // This combination of 2 redline types prefers accepting the 
inner one first.
diff --git a/sw/source/core/undo/unredln.cxx b/sw/source/core/undo/unredln.cxx
index 7786b1a5cf42..77c15f282b7d 100644
--- a/sw/source/core/undo/unredln.cxx
+++ b/sw/source/core/undo/unredln.cxx
@@ -125,6 +125,10 @@ void SwUndoRedline::dumpAsXml(xmlTextWriterPtr pWriter) 
const
     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"),
                                 
BAD_CAST(OString::boolean(mbHierarchical).getStr()));
     (void)xmlTextWriterEndElement(pWriter);
+    (void)xmlTextWriterStartElement(pWriter, BAD_CAST("depth"));
+    (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"),
+                                BAD_CAST(OString::number(mnDepth).getStr()));
+    (void)xmlTextWriterEndElement(pWriter);
 
     (void)xmlTextWriterEndElement(pWriter);
 }

Reply via email to