sw/qa/core/doc/doc.cxx | 8 ++++++++ sw/source/core/doc/DocumentRedlineManager.cxx | 16 ++++++++++++++++ sw/source/core/doc/docredln.cxx | 25 +++++++++++++++++++++++-- 3 files changed, 47 insertions(+), 2 deletions(-)
New commits: commit f31293c9fcbc47e43367857085e135f09ed378b8 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri May 23 08:34:09 2025 +0200 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Sun May 25 00:44:39 2025 +0200 tdf#166319 sw interdependent redlines: combine on accept of ins-then-fmt's fmt The bugdoc has <ins>AA<format>BB</format>CC</ins> in it, accepting the "BB" part resulted in a format-only redline in the middle (good), but "AA" and "CC" wasn't accepted, as expected. The first trouble was that SwRedlineTable::getConnectedArea() calling lcl_CanCombineWithRange() considered combining AA with BB when the cursor was at AA, but it didn't consider combining BB with AA when the curor was at BB. There doesn't seem to be a reason why combining one type with the underlying type of a next redline should be only done in one direction, so allow both directions. With this, at least AcceptRedlineRange() gets the right redline indexes, so it considers the two surrounding redlines. The other trouble was that DocumentRedlineManager::AcceptRedlineRange() only tried to combine a redline with 1 type together with an other redline with 2 types (assuming that perhaps the 2nd/underlying type is a match), and didn't try to combine a redline with 2 types with an other redline with 1 type. Allow that case at least for the insert vs insert-then-format case when the cursor is at the insert-then-format redline. The reject of insert-then-format's format is still broken, though. Change-Id: Ic8ab03e9cd2c24506cf98c5e82c09464eab8f6b5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185701 Reviewed-by: Caolán McNamara <caolan.mcnam...@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 dfe5bd2c830f..39fdf63fb03c 100644 --- a/sw/qa/core/doc/doc.cxx +++ b/sw/qa/core/doc/doc.cxx @@ -807,12 +807,20 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testInsThenFormat) pWrtShell->SttEndDoc(/*bStt=*/true); // Move inside "BBB". pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 4, /*bBasicCall=*/false); + // Search from start in the table again, for a redline that covers the cursor position. + nRedline = 0; const SwRangeRedline* pRedline = rRedlines.FindAtPosition(*pCursor->Start(), nRedline); // Without the accompanying fix in place, this test would have failed, there was no redline for // "BBB". CPPUNIT_ASSERT(pRedline); CPPUNIT_ASSERT_EQUAL(RedlineType::Format, pRedline->GetType()); CPPUNIT_ASSERT(!pRedline->GetRedlineData().Next()); + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 3 + // i.e. the insert redlines before/after BBB were not accepted. + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size()); } CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testDelThenFormat) diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx index 33a6881e1785..82048aa836e4 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -3330,6 +3330,22 @@ bool DocumentRedlineManager::AcceptRedlineRange(SwRedlineTable::size_type nPosOr } nRdlIdx++; //we will decrease it in the loop anyway. } + else if (pTmp->GetType() == RedlineType::Insert + && aOrigData.GetType() == RedlineType::Format && aOrigData.Next() + && aOrigData.Next()->GetType() == RedlineType::Insert) + { + // The aOrigData has 2 types and for these types we want the underlying type to be + // combined with the type of the surrounding redlines, so accept pTmp, too. + if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) + { + m_rDoc.GetIDocumentUndoRedo().AppendUndo( + std::make_unique<SwUndoAcceptRedline>(*pTmp)); + } + nPamEndtNI = pTmp->Start()->GetNodeIndex(); + nPamEndCI = pTmp->Start()->GetContentIndex(); + bRet |= lcl_AcceptRedline(maRedlineTable, nRdlIdx, bCallDelete); + nRdlIdx++; + } } while (nRdlIdx > 0); return bRet; } diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx index ada8f45d34c1..4596a959044c 100644 --- a/sw/source/core/doc/docredln.cxx +++ b/sw/source/core/doc/docredln.cxx @@ -837,9 +837,30 @@ bool lcl_CanCombineWithRange(SwRangeRedline* pOrigin, SwRangeRedline* pActual, if (!pOrigin->GetRedlineData(0).CanCombineForAcceptReject(pOther->GetRedlineData(0))) { - if (!bCheckChilds || pOther->GetStackCount() <= 1 - || !pOrigin->GetRedlineData(0).CanCombineForAcceptReject(pOther->GetRedlineData(1))) + if (!bCheckChilds) + { + return false; + } + + // See if pOrigin and pOther can be combined because one redline data can combine with the + // underlying redline data of the other redline. + bool bChildCanCombine = false; + if (pOther->GetStackCount() > 1 + && pOrigin->GetRedlineData(0).CanCombineForAcceptReject(pOther->GetRedlineData(1))) + { + bChildCanCombine = true; + } + + if (!bChildCanCombine && pOrigin->GetStackCount() > 1 + && pOther->GetRedlineData(0).CanCombineForAcceptReject(pOrigin->GetRedlineData(1))) + { + bChildCanCombine = true; + } + + if (!bChildCanCombine) + { return false; + } } if (pOther->Start()->GetNode().StartOfSectionNode() != pActual->Start()->GetNode().StartOfSectionNode())