sw/qa/core/doc/doc.cxx | 15 +++++++++- sw/source/core/doc/DocumentRedlineManager.cxx | 39 ++++++++++++++++++++++---- 2 files changed, 48 insertions(+), 6 deletions(-)
New commits: commit d5ca8b09d5ecdc28e28486e5dbd1ecb655d817ab Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon May 5 09:05:04 2025 +0200 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Mon May 5 18:29:31 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/+/184951 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 67b639fd0e29..62e8c198f46a 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 3bfe62bd0779..a040a32fad89 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -1133,6 +1133,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 @@ -3199,13 +3230,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(