sw/qa/core/doc/doc.cxx                        |    8 ++++++++
 sw/source/core/doc/DocumentRedlineManager.cxx |   16 ++++++++++++++++
 sw/source/core/doc/docredln.cxx               |   25 +++++++++++++++++++++++--
 3 files changed, 47 insertions(+), 2 deletions(-)

New commits:
commit f31293c9fcbc47e43367857085e135f09ed378b8
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri May 23 08:34:09 2025 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Sun May 25 00:44:39 2025 +0200

    tdf#166319 sw interdependent redlines: combine on accept of ins-then-fmt's 
fmt
    
    The bugdoc has <ins>AA<format>BB</format>CC</ins> in it, accepting the
    "BB" part resulted in a format-only redline in the middle (good), but
    "AA" and "CC" wasn't accepted, as expected.
    
    The first trouble was that SwRedlineTable::getConnectedArea() calling
    lcl_CanCombineWithRange() considered combining AA with BB when the
    cursor was at AA, but it didn't consider combining BB with AA when the
    curor was at BB. There doesn't seem to be a reason why combining one
    type with the underlying type of a next redline should be only done in
    one direction, so allow both directions. With this, at least
    AcceptRedlineRange() gets the right redline indexes, so it considers the
    two surrounding redlines.
    
    The other trouble was that DocumentRedlineManager::AcceptRedlineRange()
    only tried to combine a redline with 1 type together with an other
    redline with 2 types (assuming that perhaps the 2nd/underlying type is a
    match), and didn't try to combine a redline with 2 types with an other
    redline with 1 type. Allow that case at least for the insert vs
    insert-then-format case when the cursor is at the insert-then-format
    redline.
    
    The reject of insert-then-format's format is still broken, though.
    
    Change-Id: Ic8ab03e9cd2c24506cf98c5e82c09464eab8f6b5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185701
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>

diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx
index dfe5bd2c830f..39fdf63fb03c 100644
--- a/sw/qa/core/doc/doc.cxx
+++ b/sw/qa/core/doc/doc.cxx
@@ -807,12 +807,20 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testInsThenFormat)
     pWrtShell->SttEndDoc(/*bStt=*/true);
     // Move inside "BBB".
     pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 4, 
/*bBasicCall=*/false);
+    // Search from start in the table again, for a redline that covers the 
cursor position.
+    nRedline = 0;
     const SwRangeRedline* pRedline = 
rRedlines.FindAtPosition(*pCursor->Start(), nRedline);
     // Without the accompanying fix in place, this test would have failed, 
there was no redline for
     // "BBB".
     CPPUNIT_ASSERT(pRedline);
     CPPUNIT_ASSERT_EQUAL(RedlineType::Format, pRedline->GetType());
     CPPUNIT_ASSERT(!pRedline->GetRedlineData().Next());
+
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 1
+    // - Actual  : 3
+    // i.e. the insert redlines before/after BBB were not accepted.
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());
 }
 
 CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testDelThenFormat)
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx 
b/sw/source/core/doc/DocumentRedlineManager.cxx
index 33a6881e1785..82048aa836e4 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -3330,6 +3330,22 @@ 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)
+        {
+            // 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.
+            if (m_rDoc.GetIDocumentUndoRedo().DoesUndo())
+            {
+                m_rDoc.GetIDocumentUndoRedo().AppendUndo(
+                    std::make_unique<SwUndoAcceptRedline>(*pTmp));
+            }
+            nPamEndtNI = pTmp->Start()->GetNodeIndex();
+            nPamEndCI = pTmp->Start()->GetContentIndex();
+            bRet |= lcl_AcceptRedline(maRedlineTable, nRdlIdx, bCallDelete);
+            nRdlIdx++;
+        }
     } while (nRdlIdx > 0);
     return bRet;
 }
diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx
index ada8f45d34c1..4596a959044c 100644
--- a/sw/source/core/doc/docredln.cxx
+++ b/sw/source/core/doc/docredln.cxx
@@ -837,9 +837,30 @@ bool lcl_CanCombineWithRange(SwRangeRedline* pOrigin, 
SwRangeRedline* pActual,
 
     if 
(!pOrigin->GetRedlineData(0).CanCombineForAcceptReject(pOther->GetRedlineData(0)))
     {
-        if (!bCheckChilds || pOther->GetStackCount() <= 1
-            || 
!pOrigin->GetRedlineData(0).CanCombineForAcceptReject(pOther->GetRedlineData(1)))
+        if (!bCheckChilds)
+        {
+            return false;
+        }
+
+        // See if pOrigin and pOther can be combined because one redline data 
can combine with the
+        // underlying redline data of the other redline.
+        bool bChildCanCombine = false;
+        if (pOther->GetStackCount() > 1
+            && 
pOrigin->GetRedlineData(0).CanCombineForAcceptReject(pOther->GetRedlineData(1)))
+        {
+            bChildCanCombine = true;
+        }
+
+        if (!bChildCanCombine && pOrigin->GetStackCount() > 1
+            && 
pOther->GetRedlineData(0).CanCombineForAcceptReject(pOrigin->GetRedlineData(1)))
+        {
+            bChildCanCombine = true;
+        }
+
+        if (!bChildCanCombine)
+        {
             return false;
+        }
     }
     if (pOther->Start()->GetNode().StartOfSectionNode()
         != pActual->Start()->GetNode().StartOfSectionNode())

Reply via email to