sw/qa/core/doc/DocumentRedlineManager.cxx     |   39 ++++++++++++++++++++++++++
 sw/qa/core/doc/data/del-then-format-own.docx  |binary
 sw/source/core/doc/DocumentRedlineManager.cxx |    9 ++++++
 3 files changed, 48 insertions(+)

New commits:
commit c25c52dd2286ad0aac86389574d3b3bd258b5b08
Author:     Miklos Vajna <[email protected]>
AuthorDate: Mon Dec 22 09:35:27 2025 +0100
Commit:     Miklos Vajna <[email protected]>
CommitDate: Mon Dec 22 16:35:02 2025 +0100

    tdf#168751 sw interdependent redlines, format on delete: fix unwanted 
combine
    
    The DOCX bugdoc has a format redline (mark as bold) + a delete redline,
    and these two overlap. Open the document in Writer, reject the delete
    redline, the boldness remains in the document, which is unexpected.
    
    The problem is an in case a format redline is created and that would be
    on top of an insert or delete from the same author, then we currently
    merge this into the insert/delete redline. The reason for this seems to
    be that search&replace inserts text to the document and then copies
    direct format from the insert position to the inserted text range, and
    this format should not show up on the UI, since the UI action was just
    to replace text. Another variant of this is autocorrect "make first
    character of the paragraph uppercase" in action, which is internally
    again a replace.
    
    Fix the problem by disabling combine of redlines in
    sw::DocumentRedlineManager::PreAppendFormatRedline(), in case we would
    do a combine and this is a format on delete. This way the format is
    rejected by the UI reject action and the unwanted format on insert still
    doesn't show up. The behavior was like this already in case the authors
    of the format and the delete redlines were different.
    
    Note that this tweak is not even important for the insert-then-format
    case: accept doesn't modify the body text and reject would remove text
    from the body text, so we get rid of the unwanted format anyway.
    
    Change-Id: Ib08b0c62c012f14801deae47a4b85d77e32fc1a8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196095
    Reviewed-by: Miklos Vajna <[email protected]>
    Tested-by: Jenkins

diff --git a/sw/qa/core/doc/DocumentRedlineManager.cxx 
b/sw/qa/core/doc/DocumentRedlineManager.cxx
index 15c2b432bb08..d2a51a18d897 100644
--- a/sw/qa/core/doc/DocumentRedlineManager.cxx
+++ b/sw/qa/core/doc/DocumentRedlineManager.cxx
@@ -353,6 +353,45 @@ CPPUNIT_TEST_FIXTURE(Test, testInsThenFormatDirect)
     // i.e. we got <ins>AAA</ins>BBB<ins>CCC</ins> instead of one big insert.
     CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testDelThenFormatOwn)
+{
+    // Given a document with an overlapping delete and format redline:
+    // When importing that document:
+    createSwDoc("del-then-format-own.docx");
+
+    // Then make sure that the overlap part is not lost, instead it's 
represented with an
+    // SwRangeRedline with 2 SwRedlineData members:
+    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:
+    // - Expected: 3
+    // - Actual  : 2
+    // i.e. the document had a format and a delete redline, but part of the 
format was lost.
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), rRedlines.size());
+    {
+        const SwRedlineData& rRedlineData = rRedlines[0]->GetRedlineData(0);
+        CPPUNIT_ASSERT_EQUAL(RedlineType::Format, rRedlineData.GetType());
+        CPPUNIT_ASSERT(!rRedlineData.Next());
+    }
+    {
+        // Overlap: both format and delete is tracked, so reject removes all 
boldness from the
+        // document.
+        const SwRedlineData& rRedlineData = rRedlines[1]->GetRedlineData(0);
+        CPPUNIT_ASSERT_EQUAL(RedlineType::Format, rRedlineData.GetType());
+        CPPUNIT_ASSERT(rRedlineData.Next());
+        const SwRedlineData& rRedlineData2 = rRedlines[1]->GetRedlineData(1);
+        CPPUNIT_ASSERT_EQUAL(RedlineType::Delete, rRedlineData2.GetType());
+        CPPUNIT_ASSERT(!rRedlineData2.Next());
+    }
+    {
+        const SwRedlineData& rRedlineData = rRedlines[2]->GetRedlineData(0);
+        CPPUNIT_ASSERT_EQUAL(RedlineType::Delete, rRedlineData.GetType());
+        CPPUNIT_ASSERT(!rRedlineData.Next());
+    }
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/core/doc/data/del-then-format-own.docx 
b/sw/qa/core/doc/data/del-then-format-own.docx
new file mode 100644
index 000000000000..6263df4e0f6f
Binary files /dev/null and b/sw/qa/core/doc/data/del-then-format-own.docx differ
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx 
b/sw/source/core/doc/DocumentRedlineManager.cxx
index c5e1c2b016bc..9f80926582d9 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -2260,6 +2260,15 @@ void 
DocumentRedlineManager::PreAppendFormatRedline(AppendRedlineContext& rCtx)
         bool bCombineRedlines = !(eOld & RedlineFlags::DontCombineRedlines)
                                 && rCtx.pRedl->IsOwnRedline(*rCtx.pNewRedl)
                                 && 
!rCtx.pRedl->GetRedlineData(0).IsAnonymized();
+
+        if (bCombineRedlines && rCtx.pRedl->GetType() == RedlineType::Delete
+            && rCtx.pNewRedl->GetType() == RedlineType::Format)
+        {
+            // Don't fold format on top of delete into the delete, that would 
give an incorrect
+            // result when rejecting this redline, the format would remain in 
the doc model.
+            bCombineRedlines = false;
+        }
+
         if (bCombineRedlines || rCtx.pRedl->IsMoved())
         {
             switch( rCtx.eCmpPos )

Reply via email to