sw/qa/core/doc/doc.cxx                        |   15 +++++++++-
 sw/source/core/doc/DocumentRedlineManager.cxx |   39 ++++++++++++++++++++++----
 2 files changed, 48 insertions(+), 6 deletions(-)

New commits:
commit 8e85d559a68f980d99af4ded6a91b7f0458048b9
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon May 5 09:05:04 2025 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue May 6 12:32:21 2025 +0200

    tdf#166319 sw interdependent redlines: handle accept of insert under format
    
    Open the bugdoc, move the cursor inside "AAA", accept the change, the
    result is that "BBB" still has a change, which is marked as a "format on
    top of insert", while the intent was to accept the insert.
    
    A similar use-case is the same with "delete on top of insert", and that
    one works since commit 52fa7aed48632166e064e6a227e034f0981c4205
    (tdf#157662 SW: redline: accept/reject done for all parts, 2023-10-14).
    
    Fix the problem by extending
    sw::DocumentRedlineManager::AcceptRedlineRange(), so it considers
    format-on-insert the same as delete-on-insert, so all 3 redlines get
    their insert part accepted.
    
    The result is that that the insert-only redlines are deleted and the
    insert-and-format redline is downgraded to be a simple format redline.
    
    Change-Id: I2fdcc906d40c7e94d5446e8912390fe814a5f84c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184983
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx
index 226e972ec103..19f4a1fbcecc 100644
--- a/sw/qa/core/doc/doc.cxx
+++ b/sw/qa/core/doc/doc.cxx
@@ -747,7 +747,8 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testInsThenFormat)
     createSwDoc("ins-then-format.docx");
 
     // Then make sure that both the insert and the format on top of it is in 
the model:
-    SwDoc* pDoc = getSwDocShell()->GetDoc();
+    SwDocShell* pDocShell = getSwDocShell();
+    SwDoc* pDoc = pDocShell->GetDoc();
     IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess();
     SwRedlineTable& rRedlines = rIDRA.GetRedlineTable();
     // Without the accompanying fix in place, this test would have failed with:
@@ -762,6 +763,18 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testInsThenFormat)
     const SwRedlineData& rInnerRedlineData = *rRedlineData1.Next();
     CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rInnerRedlineData.GetType());
     CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlines[2]->GetType());
+
+    // And when accepting the insert:
+    SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+    pWrtShell->AcceptRedline(0);
+
+    // Then make sure only the format on top of insert remains:
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());
+    CPPUNIT_ASSERT_EQUAL(RedlineType::Format, rRedlines[0]->GetType());
+    const SwRedlineData& rRedlineData = rRedlines[0]->GetRedlineData(0);
+    // Without the accompanying fix in place, this test would have failed, the 
insert under format
+    // was not accepted.
+    CPPUNIT_ASSERT(!rRedlineData.Next());
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx 
b/sw/source/core/doc/DocumentRedlineManager.cxx
index 736db017b8cd..f7e0e2745d7b 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -1132,6 +1132,37 @@ namespace
             static_cast<SwPaM&>(m_rRedline) = *m_pCursor;
         }
     };
+
+/// Decides if it's OK to combine two types of redlines next to each other, 
e.g. insert and
+/// delete-on-insert can be combined if accepting an insert.
+bool CanCombineTypesForAccept(SwRedlineData& rInnerData, SwRangeRedline& 
rOuterRedline)
+{
+    if (rInnerData.GetType() != RedlineType::Insert)
+    {
+        return false;
+    }
+
+    switch (rOuterRedline.GetType())
+    {
+        case RedlineType::Delete:
+        case RedlineType::Format:
+            break;
+        default:
+            return false;
+    }
+
+    if (rOuterRedline.GetStackCount() <= 1)
+    {
+        return false;
+    }
+
+    if (rOuterRedline.GetType(1) != RedlineType::Insert)
+    {
+        return false;
+    }
+
+    return true;
+}
 }
 
 namespace sw
@@ -3198,13 +3229,11 @@ bool 
DocumentRedlineManager::AcceptRedlineRange(SwRedlineTable::size_type nPosOr
             bRet |= lcl_AcceptRedline(maRedlineTable, nRdlIdx, bCallDelete);
             nRdlIdx++; //we will decrease it in the loop anyway.
         }
-        else if (aOrigData.GetType() == RedlineType::Insert
-                 && pTmp->GetType() == RedlineType::Delete && 
pTmp->GetStackCount() > 1
-                 && pTmp->GetType(1) == RedlineType::Insert
+        else if (CanCombineTypesForAccept(aOrigData, *pTmp)
                  && 
pTmp->GetRedlineData(1).CanCombineForAcceptReject(aOrigData))
         {
-            // The Insert redline we want to accept has a deletion redline too
-            // we should leave the deletion redline, and only accept the inner 
insert.
+            // The Insert redline we want to accept has an other type of 
redline too
+            // we should leave the other type of redline, and only accept the 
inner insert.
             if (m_rDoc.GetIDocumentUndoRedo().DoesUndo())
             {
                 m_rDoc.GetIDocumentUndoRedo().AppendUndo(

Reply via email to