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 2292bda37378d7f782abbda42c026affd3fa59e5 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri May 23 08:34:09 2025 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue May 27 09:45:49 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/+/185878 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx index f708bbf23827..6488b9d12500 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 0c16551b65c2..8501838444c2 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -3329,6 +3329,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 dfc1eab8782a..22d07d027f66 100644 --- a/sw/source/core/doc/docredln.cxx +++ b/sw/source/core/doc/docredln.cxx @@ -837,9 +837,30 @@ bool lcl_CanCombineWithRange(const SwRangeRedline* pOrigin, SwRangeRedline* pAct 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())