sw/qa/core/doc/doc.cxx | 15 +++++++++++++++ sw/source/core/doc/DocumentRedlineManager.cxx | 26 ++++++++++++++++++-------- 2 files changed, 33 insertions(+), 8 deletions(-)
New commits: commit 3c039cb31239ba01e3d3b56c526bdb7ba6446032 Author: Miklos Vajna <[email protected]> AuthorDate: Fri May 9 09:15:17 2025 +0200 Commit: Miklos Vajna <[email protected]> CommitDate: Fri May 9 12:14:54 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/+/185089 Tested-by: Jenkins Reviewed-by: Miklos Vajna <[email protected]> diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx index 19f4a1fbcecc..dce183e12355 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 b08e804ea707..cdabed29313e 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -1135,7 +1135,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) { @@ -3283,7 +3283,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 another type of redline too @@ -3561,14 +3561,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 @@ -3580,7 +3578,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. }
