sw/inc/crsrsh.hxx                             |    2 +-
 sw/qa/core/doc/doc.cxx                        |   21 +++++++++++++++++++++
 sw/source/core/doc/DocumentRedlineManager.cxx |   18 +++++++++++++++---
 3 files changed, 37 insertions(+), 4 deletions(-)

New commits:
commit b05614d687b2d109883787e0c1d0b404353bd758
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu May 29 08:57:23 2025 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Thu May 29 10:32:31 2025 +0200

    tdf#166319 sw interdependent redlines: handle accept of del-then-fmt's fmt
    
    The bugdoc has <del>AA<format>BB</format>CC</del> in it, accepting the
    BB part resulted in <del>AA</del>BB<del>CC</del>, while the expected
    result would be removal of BB from the document.
    
    The problem is that reject only saw the 'format' in the combined
    delete+format redline, but that's not correct: it's just a small detail
    that there was a format on top of the delete.
    
    Fix the problem by extending
    sw::DocumentRedlineManager::AcceptRedlineRange() to handle the
    delete-then-format case as a delete and only then do the generic redline
    handling.
    
    The surrounding plain delete redlines are not combined yet.
    
    Change-Id: I7ea92a86d8881694ad3da571831100f5996b5d3f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185984
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>

diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index 211f6b0592ad..f23cba777449 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -453,7 +453,7 @@ public:
     SW_DLLPUBLIC void SwapPam();
     SW_DLLPUBLIC bool TestCurrPam( const Point & rPt,
                       bool bTstHit = false);   // only exact matches
-    void KillPams();
+    SW_DLLPUBLIC void KillPams();
 
     /// store a copy of the current cursor on the cursor stack
     SW_DLLPUBLIC void Push();
diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx
index 0d4f635b3d00..68433eb15939 100644
--- a/sw/qa/core/doc/doc.cxx
+++ b/sw/qa/core/doc/doc.cxx
@@ -884,6 +884,27 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testDelThenFormat)
     CPPUNIT_ASSERT(!rRedlineData.Next());
     // This was AAACCC.
     CPPUNIT_ASSERT_EQUAL(u"AAABBBCCC"_ustr, pTextNode->GetText());
+
+    // And when accepting the delete with the cursor inside BBB:
+    pWrtShell->Undo();
+    CPPUNIT_ASSERT_EQUAL(u"AAABBBCCC"_ustr, pTextNode->GetText());
+    pWrtShell->KillPams();
+    SwPaM* pCursor = pWrtShell->GetCursor();
+    pCursor->DeleteMark();
+    pWrtShell->SttEndDoc(/*bStt=*/true);
+    // Move inside "BBB".
+    pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 4, 
/*bBasicCall=*/false);
+    SwRedlineTable::size_type nRedline{};
+    rRedlines.FindAtPosition(*pCursor->Start(), nRedline);
+    CPPUNIT_ASSERT_LESS(rRedlines.size(), nRedline);
+    pWrtShell->AcceptRedline(nRedline);
+
+    // Then make sure BBB gets removed from the document:
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: AAACCC
+    // - Actual  : AAABBBCCC
+    // i.e. BBB's formatting was removed, but not BBB itself.
+    CPPUNIT_ASSERT_EQUAL(u"AAACCC"_ustr, pTextNode->GetText());
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx 
b/sw/source/core/doc/DocumentRedlineManager.cxx
index 5778b02299e2..8d66eff2f9ae 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -3292,13 +3292,25 @@ bool 
DocumentRedlineManager::AcceptRedlineRange(SwRedlineTable::size_type nPosOr
             nPamEndtNI = pTmp->Start()->GetNodeIndex();
             nPamEndCI = pTmp->Start()->GetContentIndex();
 
-            if (pTmp->GetType() == RedlineType::Format && 
pTmp->GetStackCount() > 1
-                && pTmp->GetType(1) == RedlineType::Insert)
+            bool bHierarchicalFormat = pTmp->GetType() == RedlineType::Format 
&& pTmp->GetStackCount() > 1;
+            bool bHandled = false;
+            if (bHierarchicalFormat && pTmp->GetType(1) == RedlineType::Insert)
             {
                 // This combination of 2 redline types prefers accepting the 
inner one first.
                 bRet |= lcl_DeleteInnerRedline(maRedlineTable, nRdlIdx, 1);
+                bHandled = true;
             }
-            else
+            else if (bHierarchicalFormat && pTmp->GetType(1) == 
RedlineType::Delete)
+            {
+                // Get rid of the format itself and then accept the delete by 
deleting the range.
+                SwPaM aPam(*pTmp->Start(), *pTmp->End());
+                bRet |= lcl_RejectRedline(maRedlineTable, nRdlIdx, 
bCallDelete);
+                // Handles undo/redo itself.
+                m_rDoc.getIDocumentContentOperations().DeleteRange(aPam);
+                bHandled = true;
+            }
+
+            if (!bHandled)
             {
                 bRet |= lcl_AcceptRedline(maRedlineTable, nRdlIdx, 
bCallDelete);
             }

Reply via email to