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 de12d41f140aee260fa751cd75b19ce3dc895dbf Author: Miklos Vajna <[email protected]> AuthorDate: Mon Dec 22 09:35:27 2025 +0100 Commit: Mike Kaganski <[email protected]> CommitDate: Mon Dec 22 13:21:24 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/+/196066 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Mike Kaganski <[email protected]> diff --git a/sw/qa/core/doc/DocumentRedlineManager.cxx b/sw/qa/core/doc/DocumentRedlineManager.cxx index cba1b81727f1..6bc0e2fef3bd 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 b33ab235f486..5b64c1ed8fc6 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -2261,6 +2261,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 )
