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 2292bda37378d7f782abbda42c026affd3fa59e5
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri May 23 08:34:09 2025 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue May 27 09:45:49 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/+/185878
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx
index f708bbf23827..6488b9d12500 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 0c16551b65c2..8501838444c2 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -3329,6 +3329,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 dfc1eab8782a..22d07d027f66 100644
--- a/sw/source/core/doc/docredln.cxx
+++ b/sw/source/core/doc/docredln.cxx
@@ -837,9 +837,30 @@ bool lcl_CanCombineWithRange(const SwRangeRedline* 
pOrigin, SwRangeRedline* pAct
 
     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