sw/qa/core/doc/doc.cxx                        |   15 +++++++++++++++
 sw/source/core/doc/DocumentRedlineManager.cxx |   26 ++++++++++++++++++--------
 2 files changed, 33 insertions(+), 8 deletions(-)

New commits:
commit 90077e9b4372e1e3445cc6fb2158a0f2bbb8b1b8
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri May 9 09:15:17 2025 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Fri May 9 10:02:17 2025 +0200

    tdf#166319 sw interdependent redlines: handle reject of insert under format
    
    The bugdoc has <insert>AA<format>BB</format>CC</insert> in it, clicking
    reject in the middle of AA results in a leftover BB in the document.
    
    This is because the outer redline type of BB is format, so the other
    type is not rejected together with the insert reject. But this is not
    correct: if the insert is to be rejected, then it's just a small detail
    that there was a format on top of it: all this is meant to be rejected,
    like Word does.
    
    Fix the problem similar to how commit
    d5ca8b09d5ecdc28e28486e5dbd1ecb655d817ab (tdf#166319 sw interdependent
    redlines: handle accept of insert under format, 2025-05-05) handled
    accept: if there is a format, then see if it has an underlying insert,
    and if so, still combine the to-be-rejected changes.
    
    Note that in contrast to insert-then-delete, it's not enough to accept
    the change to delete it (for the higher level reject purpose), so
    explicitly call DeleteRange() on the range of the format after the
    format redline is gone.
    
    Change-Id: Iaf1122d8e37e210790972e0312564245fa6f813f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185083
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx
index 62e8c198f46a..8870f80fbba3 100644
--- a/sw/qa/core/doc/doc.cxx
+++ b/sw/qa/core/doc/doc.cxx
@@ -775,6 +775,21 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testInsThenFormat)
     // Without the accompanying fix in place, this test would have failed, the 
insert under format
     // was not accepted.
     CPPUNIT_ASSERT(!rRedlineData.Next());
+
+    // And when rejecting the insert:
+    pWrtShell->Undo();
+    SwTextNode* pTextNode = 
pWrtShell->GetCursor()->GetPointNode().GetTextNode();
+    CPPUNIT_ASSERT_EQUAL(u"AAABBBCCC"_ustr, pTextNode->GetText());
+    pWrtShell->RejectRedline(0);
+
+    // Then make sure no redlines and no content remain:
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 0
+    // - Actual  : 1
+    // i.e. a format-on-insert redline remained.
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), rRedlines.size());
+    // Also make sure the text of the format-on-insert redline is removed.
+    CPPUNIT_ASSERT(pTextNode->GetText().isEmpty());
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx 
b/sw/source/core/doc/DocumentRedlineManager.cxx
index 1f2dd69b683e..3ec093c5b06f 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -1136,7 +1136,7 @@ namespace
 
 /// 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)
+bool CanCombineTypesForAcceptReject(SwRedlineData& rInnerData, SwRangeRedline& 
rOuterRedline)
 {
     if (rInnerData.GetType() != RedlineType::Insert)
     {
@@ -3284,7 +3284,7 @@ bool 
DocumentRedlineManager::AcceptRedlineRange(SwRedlineTable::size_type nPosOr
             bRet |= lcl_AcceptRedline(maRedlineTable, nRdlIdx, bCallDelete);
             nRdlIdx++; //we will decrease it in the loop anyway.
         }
-        else if (CanCombineTypesForAccept(aOrigData, *pTmp)
+        else if (CanCombineTypesForAcceptReject(aOrigData, *pTmp)
                  && 
pTmp->GetRedlineData(1).CanCombineForAcceptReject(aOrigData))
         {
             // The Insert redline we want to accept has an other type of 
redline too
@@ -3562,14 +3562,12 @@ bool 
DocumentRedlineManager::RejectRedlineRange(SwRedlineTable::size_type nPosOr
             bRet |= lcl_RejectRedline(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 (CanCombineTypesForAcceptReject(aOrigData, *pTmp)
                  && 
pTmp->GetRedlineData(1).CanCombineForAcceptReject(aOrigData))
         {
-            // The Insert redline we want to reject has a deletion redline too
-            // without the insert, the delete is meaningless
-            // so we rather just accept the deletion redline
+            // The Insert redline we want to reject has an other type of 
redline too
+            // without the insert, the other type is meaningless
+            // so we rather just accept the other type of redline
             if (m_rDoc.GetIDocumentUndoRedo().DoesUndo())
             {
                 std::unique_ptr<SwUndoAcceptRedline> pUndoRdl
@@ -3581,7 +3579,19 @@ bool 
DocumentRedlineManager::RejectRedlineRange(SwRedlineTable::size_type nPosOr
             }
             nPamEndtNI = pTmp->Start()->GetNodeIndex();
             nPamEndCI = pTmp->Start()->GetContentIndex();
+            std::optional<SwPaM> oPam;
+            RedlineType eOuterType = pTmp->GetType();
+            if (eOuterType == RedlineType::Format)
+            {
+                // The accept won't implicitly delete the range, so track its 
boundaries.
+                oPam.emplace(*pTmp->Start(), *pTmp->End());
+            }
             bRet |= lcl_AcceptRedline(maRedlineTable, nRdlIdx, bCallDelete);
+            if (oPam)
+            {
+                // Handles undo/redo itself.
+                m_rDoc.getIDocumentContentOperations().DeleteRange(*oPam);
+            }
             nRdlIdx++; //we will decrease it in the loop anyway.
         }
 

Reply via email to