sw/qa/core/doc/doc.cxx                        |   25 +++++++++++++++++++++++++
 sw/source/core/doc/DocumentRedlineManager.cxx |   24 ++++++++++++------------
 2 files changed, 37 insertions(+), 12 deletions(-)

New commits:
commit ba2d3e338ff72d426feda5112899fcbe7e8f90ea
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon Jun 2 08:45:18 2025 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Jun 2 11:10:53 2025 +0200

    tdf#166319 sw interdependent redlines: handle reject of del-then-fmt's fmt
    
    The bugdoc has <del>AA<format>BB</format>CC</del> in it, rejecting the
    BB part is meant to get rid of the delete redline and keep the format
    redline.
    
    The problem is that the old code only considered the primary type
    (format) of the 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::RejectRedlineRange(), so it ignores format
    for both insert as delete.
    
    Also simplify sw::DocumentRedlineManager::AcceptRedlineRange(), we have
    3 non-overlapping cases there, so no need for bHandled there.
    
    Change-Id: I2607740dd0c1ddc447bb3f761f06c07fe80486b9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186123
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx
index fc92707807f6..30811a5f241a 100644
--- a/sw/qa/core/doc/doc.cxx
+++ b/sw/qa/core/doc/doc.cxx
@@ -904,6 +904,31 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testDelThenFormat)
     // 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 when rejecting the delete with the cursor inside BBB:
+    pWrtShell->Undo();
+    CPPUNIT_ASSERT_EQUAL(u"AAABBBCCC"_ustr, pTextNode->GetText());
+    // 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;
+    const SwRangeRedline* pRedline = 
rRedlines.FindAtPosition(*pCursor->Start(), nRedline);
+    // A redline is found.
+    CPPUNIT_ASSERT_LESS(rRedlines.size(), nRedline);
+    pWrtShell->RejectRedline(nRedline);
+
+    // Then make sure the format-on-delete is rejected, i.e. the delete part 
is gone but the format
+    // part is kept:
+    nRedline = 0;
+    pRedline = rRedlines.FindAtPosition(*pCursor->Start(), nRedline);
+    // Without the accompanying fix in place, this test would have failed, the 
redline over BBB was
+    // gone completely.
+    CPPUNIT_ASSERT(pRedline);
+    CPPUNIT_ASSERT_EQUAL(RedlineType::Format, pRedline->GetType());
+    CPPUNIT_ASSERT(!pRedline->GetRedlineData().Next());
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx 
b/sw/source/core/doc/DocumentRedlineManager.cxx
index 03e597162618..ef731d5d6856 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -3346,21 +3346,17 @@ bool 
DocumentRedlineManager::AcceptRedlineRange(SwRedlineTable::size_type nPosOr
             nPamEndCI = pTmp->Start()->GetContentIndex();
 
             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 if (bHierarchicalFormat && pTmp->GetType(1) == 
RedlineType::Delete)
             {
                 // Get rid of the format itself and then accept the delete by 
deleting the range.
                 bRet |= lcl_AcceptInnerDelete(*pTmp, maRedlineTable, nRdlIdx, 
bCallDelete);
-                bHandled = true;
             }
-
-            if (!bHandled)
+            else
             {
                 bRet |= lcl_AcceptRedline(maRedlineTable, nRdlIdx, 
bCallDelete);
             }
@@ -3653,16 +3649,15 @@ bool 
DocumentRedlineManager::RejectRedlineRange(SwRedlineTable::size_type nPosOr
         }
         else if (pTmp->GetRedlineData(0).CanCombineForAcceptReject(aOrigData))
         {
-            bool bFormatOnInsert = pTmp->GetType() == RedlineType::Format
-                                   && pTmp->GetStackCount() > 1
-                                   && pTmp->GetType(1) == RedlineType::Insert;
+            bool bHierarchicalFormat
+                = pTmp->GetType() == RedlineType::Format && 
pTmp->GetStackCount() > 1;
             if (m_rDoc.GetIDocumentUndoRedo().DoesUndo())
             {
                 std::unique_ptr<SwUndoRedline> pUndoRdl;
-                if (bFormatOnInsert)
+                if (bHierarchicalFormat)
                 {
-                    // Format on insert: this is rejected by accepting the 
format + deleting the
-                    // range.
+                    // Format on an other type: just create an accept undo 
action, we'll deal with
+                    // insert or delete below separately.
                     pUndoRdl = std::make_unique<SwUndoAcceptRedline>(*pTmp);
                 }
                 else
@@ -3677,7 +3672,7 @@ bool 
DocumentRedlineManager::RejectRedlineRange(SwRedlineTable::size_type nPosOr
             nPamEndtNI = pTmp->Start()->GetNodeIndex();
             nPamEndCI = pTmp->Start()->GetContentIndex();
 
-            if (bFormatOnInsert)
+            if (bHierarchicalFormat && pTmp->GetType(1) == RedlineType::Insert)
             {
                 // Accept the format itself and then reject the insert by 
deleting the range.
                 SwPaM aPam(*pTmp->Start(), *pTmp->End());
@@ -3685,6 +3680,11 @@ bool 
DocumentRedlineManager::RejectRedlineRange(SwRedlineTable::size_type nPosOr
                 // Handles undo/redo itself.
                 m_rDoc.getIDocumentContentOperations().DeleteRange(aPam);
             }
+            else if (bHierarchicalFormat && pTmp->GetType(1) == 
RedlineType::Delete)
+            {
+                // Keep the format redline on top, just get rid of the delete 
at the bottom.
+                bRet |= lcl_DeleteInnerRedline(maRedlineTable, nRdlIdx, 1);
+            }
             else
             {
                 bRet |= lcl_RejectRedline(maRedlineTable, nRdlIdx, 
bCallDelete);

Reply via email to