sw/qa/core/doc/doc.cxx                        |   11 +---
 sw/source/core/doc/DocumentRedlineManager.cxx |   66 ++++++++++++++++++++++----
 2 files changed, 61 insertions(+), 16 deletions(-)

New commits:
commit a76771f6e9b4bc845a69adf9d72e34223f7097bc
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri May 30 08:26:07 2025 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Fri May 30 10:36:41 2025 +0200

    tdf#166319 sw interdependent redlines: combine on 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><del>CC</del>. The removal of BB is
    good, but there was no combine to also remove AA and CC.
    
    The problem is that the delete-then-format wasn't combined with the
    surrounding delete redlines.
    
    Fix the problem by introducing a new CanReverseCombineTypesForAccept()
    for the case when the redline with 2 types is conditionally combined
    with an other redline and by using that in
    sw::DocumentRedlineManager::AcceptRedlineRange().
    
    Also extract some duplicated code into a new lcl_AcceptInnerDelete().
    
    Change-Id: Ib5881b6c9aa44ae5dcf79342dbd64bbd61f734c2
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186029
    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 68433eb15939..fc92707807f6 100644
--- a/sw/qa/core/doc/doc.cxx
+++ b/sw/qa/core/doc/doc.cxx
@@ -899,12 +899,11 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testDelThenFormat)
     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());
+    // Then make sure the format-on-delete is accepted, i.e. neither the 
format-on-delete BBB, nor
+    // the surrounding AAA and CCC deletes are in the text anymore:
+    // 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());
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx 
b/sw/source/core/doc/DocumentRedlineManager.cxx
index 8d66eff2f9ae..cde8434a6641 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -1012,6 +1012,24 @@ namespace
         return true;
     }
 
+    /// Given a redline that has two types and the underlying type is
+    /// delete, reject the redline based on that underlying type. Used
+    /// to accept a delete-then-format, i.e. this does change the text
+    /// node string.
+    bool lcl_AcceptInnerDelete(SwRangeRedline& rRedline, SwRedlineTable& 
rRedlines,
+                               SwRedlineTable::size_type& rRedlineIndex, bool 
bCallDelete)
+    {
+        bool bRet = false;
+
+        SwPaM aPam(*rRedline.Start(), *rRedline.End());
+        bRet |= lcl_RejectRedline(rRedlines, rRedlineIndex, bCallDelete);
+        // Handles undo/redo itself.
+        SwDoc& rDoc = rRedline.GetDoc();
+        rDoc.getIDocumentContentOperations().DeleteRange(aPam);
+
+        return bRet;
+    }
+
     typedef bool (*Fn_AcceptReject)( SwRedlineTable& rArr, 
SwRedlineTable::size_type& rPos,
                             bool bCallDelete,
                             const SwPosition* pSttRng,
@@ -1174,6 +1192,41 @@ bool CanCombineTypesForAcceptReject(SwRedlineData& 
rInnerData, SwRangeRedline& r
 
     return true;
 }
+
+/// Decides if it's OK to combine this rInnerData having 2 types with an
+/// outer rOuterRedline for accept purposes. E.g. format-on-delete and
+/// delete can be combined if accepting a delete.
+bool CanReverseCombineTypesForAccept(SwRangeRedline& rOuterRedline, 
SwRedlineData& rInnerData)
+{
+    switch (rOuterRedline.GetType())
+    {
+        case RedlineType::Insert:
+        case RedlineType::Delete:
+            break;
+        default:
+            return false;
+    }
+
+    if (rInnerData.GetType() != RedlineType::Format)
+    {
+        return false;
+    }
+
+    const SwRedlineData* pInnerDataNext = rInnerData.Next();
+    if (!pInnerDataNext)
+    {
+        return false;
+    }
+
+    switch (pInnerDataNext->GetType())
+    {
+        case RedlineType::Insert:
+        case RedlineType::Delete:
+            return pInnerDataNext->GetType() == rOuterRedline.GetType();
+        default:
+            return false;
+    }
+}
 }
 
 namespace sw
@@ -3303,10 +3356,7 @@ bool 
DocumentRedlineManager::AcceptRedlineRange(SwRedlineTable::size_type nPosOr
             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);
+                bRet |= lcl_AcceptInnerDelete(*pTmp, maRedlineTable, nRdlIdx, 
bCallDelete);
                 bHandled = true;
             }
 
@@ -3331,9 +3381,7 @@ bool 
DocumentRedlineManager::AcceptRedlineRange(SwRedlineTable::size_type nPosOr
             if (aOrigData.GetType() == RedlineType::Delete)
             {
                 // We should delete the other type of redline when accepting 
the inner delete.
-                SwPaM aPam(*pTmp->Start(), *pTmp->End());
-                bRet |= lcl_RejectRedline(maRedlineTable, nRdlIdx, 
bCallDelete);
-                m_rDoc.getIDocumentContentOperations().DeleteRange(aPam);
+                bRet |= lcl_AcceptInnerDelete(*pTmp, maRedlineTable, nRdlIdx, 
bCallDelete);
             }
             else
             {
@@ -3342,9 +3390,7 @@ bool 
DocumentRedlineManager::AcceptRedlineRange(SwRedlineTable::size_type nPosOr
             }
             nRdlIdx++; //we will decrease it in the loop anyway.
         }
-        else if (pTmp->GetType() == RedlineType::Insert
-                 && aOrigData.GetType() == RedlineType::Format && 
aOrigData.Next()
-                 && aOrigData.Next()->GetType() == RedlineType::Insert)
+        else if (CanReverseCombineTypesForAccept(*pTmp, aOrigData))
         {
             // The aOrigData has 2 types and for these types we want the 
underlying type to be
             // combined with the type of the surrounding redlines, so accept 
pTmp, too.

Reply via email to