sw/qa/core/doc/doc.cxx | 19 +++++++++++++ sw/source/core/doc/DocumentRedlineManager.cxx | 38 +++++++++++++++++++------- 2 files changed, 48 insertions(+), 9 deletions(-)
New commits: commit f5b92d0d027c8f69b0c571e306e31578f858d4bf Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Wed Jun 18 09:35:21 2025 +0200 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Thu Jun 19 06:23:55 2025 +0200 tdf#166319 sw interdependent redlines: fix redo of reject of del-then-fmt's del The bugdoc has <del>AA<format>BB</format>CC</del>, rejecting AA just leaves the BB format redline, undo works, but redo results in no redlines, while we again want a single format redline. The first problem was that the del-then-fmt redline's undo action was an SwUndoAcceptRedline, while the UI action was a reject. This was not a problem on undo, since both accept and reject has the undo code to restore a previous state, but redo will have to perform different actions (re-accept or re-reject). The second problem was that sw::DocumentRedlineManager::RejectRedline() assumed that rejecting an underlying redline (depth = 1, instead of the usual depth = 0) could be always implemented by accepting the redline, since that works for the insert/delete combination. Improve this, so in case we get a format-on-delete, then we again properly reject just the underlying redline, as the original UI action did. Change-Id: I846abcfa34a7d55709bc9af6e566a3e83d79d833 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186646 Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx index a3826cde2791..fc0772e08d1d 100644 --- a/sw/qa/core/doc/doc.cxx +++ b/sw/qa/core/doc/doc.cxx @@ -970,6 +970,25 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testDelThenFormat) // - Actual : 3 // i.e. the surrounding delete redlines were not combined on reject. CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size()); + + // Reset to the state after file load: + pWrtShell->Undo(); + // And when we do a reject for the first "delete" part, undo, redo: + pWrtShell->RejectRedline(0); + pWrtShell->Undo(); + pWrtShell->Redo(); + + // Then make sure get a single format redline, matching the state right after reject: + { + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 0 + // i.e. the format redline was lost on redo. + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size()); + const SwRedlineData& rRedlineData1 = rRedlines[0]->GetRedlineData(0); + CPPUNIT_ASSERT_EQUAL(RedlineType::Format, rRedlineData1.GetType()); + CPPUNIT_ASSERT(!rRedlineData1.Next()); + } } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx index b86e0691d8bf..3ae851126f8b 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -3706,11 +3706,21 @@ bool DocumentRedlineManager::RejectRedlineRange(SwRedlineTable::size_type nPosOr else if (CanCombineTypesForAcceptReject(aOrigData, *pTmp) && pTmp->GetRedlineData(1).CanCombineForAcceptReject(aOrigData)) { - // The Insert/Delete redline we want to reject has an other type of redline too + RedlineType eInnerType = aOrigData.GetType(); + RedlineType eOuterType = pTmp->GetType(); if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) { - std::unique_ptr<SwUndoAcceptRedline> pUndoRdl - = std::make_unique<SwUndoAcceptRedline>(*pTmp); + std::unique_ptr<SwUndoRedline> pUndoRdl; + if (eInnerType == RedlineType::Delete && eOuterType == RedlineType::Format) + { + // Format on insert: record rejection of the underlying insert. + pUndoRdl = std::make_unique<SwUndoRejectRedline>(*pTmp, /*nDepth=*/1, /*bHierarchical=*/true); + } + else + { + // The Insert/Delete redline we want to reject has an other type of redline too + pUndoRdl = std::make_unique<SwUndoAcceptRedline>(*pTmp); + } #if OSL_DEBUG_LEVEL > 0 pUndoRdl->SetRedlineCountDontCheck(true); #endif @@ -3719,8 +3729,6 @@ bool DocumentRedlineManager::RejectRedlineRange(SwRedlineTable::size_type nPosOr nPamEndNI = pTmp->Start()->GetNodeIndex(); nPamEndCI = pTmp->Start()->GetContentIndex(); std::optional<SwPaM> oPam; - RedlineType eInnerType = aOrigData.GetType(); - RedlineType eOuterType = pTmp->GetType(); if (eInnerType == RedlineType::Insert && eOuterType == RedlineType::Format) { // The accept won't implicitly delete the range, so track its boundaries. @@ -3922,11 +3930,23 @@ bool DocumentRedlineManager::RejectRedline( const SwPaM& rPam, bool bCallDelete, } else { - // For now it is called only if it is an Insert redline in a delete redline. SwRedlineTable::size_type nRdlIdx = 0; - maRedlineTable.FindAtPosition(*rPam.Start(), nRdlIdx); - if (lcl_AcceptRedline(maRedlineTable, nRdlIdx, bCallDelete)) - nRet = 1; + const SwRangeRedline* pRedline = maRedlineTable.FindAtPosition(*rPam.Start(), nRdlIdx); + if (nDepth == 1 && pRedline && pRedline->GetType(0) == RedlineType::Format + && pRedline->GetType(1) == RedlineType::Delete) + { + // Reject a format-on-delete by getting rid of the underlying delete. + if (lcl_DeleteInnerRedline(maRedlineTable, nRdlIdx, nDepth)) + { + nRet = 1; + } + } + else + { + // For now it is called only if it is an Insert redline in a delete redline. + if (lcl_AcceptRedline(maRedlineTable, nRdlIdx, bCallDelete)) + nRet = 1; + } } if( nRet > 0 )