sw/inc/docary.hxx | 2 +- sw/qa/core/doc/doc.cxx | 23 +++++++++++++++++++++++ sw/source/core/doc/DocumentRedlineManager.cxx | 13 ++++++++++++- 3 files changed, 36 insertions(+), 2 deletions(-)
New commits: commit 8cabdef0b34210d026ea7a8229f321e272a49109 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Thu May 22 08:43:06 2025 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu May 22 14:52:23 2025 +0200 tdf#166319 sw interdependent redlines: handle 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 fully accepted portion, while the expected result is to accept the underlying insert, like in Word. The problem is that the accept code is not aware that the format has an underlying insert, so the format gets accepted and as a side effect the insert redline is gone, too. Fix this by extending DocumentRedlineManager::AcceptRedlineRange() to just get rid of the inner redline in the insert-then-format case, which results in a plain format redline, as wanted. lcl_DeleteInnerRedline() can do exactly this, added already in commit f468d61755fad1e38e481f8f439bbce9161a3aa7 (tdf#166319 sw interdependent redlines: handle reject of delete under format, 2025-05-16). Connecting this (effectively) insert redline (insert-then-format, to be precise) with the surrounding plain insert redlines is not done yet, though. Change-Id: I64e2ab1f6a6ce7872c3e4ea7b0bfb0c542c611ed Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185653 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/inc/docary.hxx b/sw/inc/docary.hxx index 248c7bfb510b..a05a8cba2fe3 100644 --- a/sw/inc/docary.hxx +++ b/sw/inc/docary.hxx @@ -213,7 +213,7 @@ struct CompareSwRedlineTable // Notification type for notifying about redlines to LOK clients enum class RedlineNotification { Add, Remove, Modify }; -class SwRedlineTable +class SW_DLLPUBLIC SwRedlineTable { public: typedef o3tl::sorted_vector<SwRangeRedline*, CompareSwRedlineTable, diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx index 62ddfb9bab26..f708bbf23827 100644 --- a/sw/qa/core/doc/doc.cxx +++ b/sw/qa/core/doc/doc.cxx @@ -790,6 +790,29 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testInsThenFormat) 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()); + + // And when accepting the format-on-insert: + pWrtShell->Undo(); + CPPUNIT_ASSERT_EQUAL(u"AAABBBCCC"_ustr, pTextNode->GetText()); + SwPaM* pCursor = pWrtShell->GetCursor(); + pCursor->DeleteMark(); + pWrtShell->SttEndDoc(/*bStt=*/true); + // Move inside "BBB". + pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 4, /*bBasicCall=*/false); + SwRedlineTable::size_type nRedline{}; + rRedlines.FindAtPosition(*pCursor->Start(), nRedline); + pWrtShell->AcceptRedline(nRedline); + + // Then make sure the format is kept and the insert is accepted: + pWrtShell->SttEndDoc(/*bStt=*/true); + // Move inside "BBB". + pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 4, /*bBasicCall=*/false); + 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()); } CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testDelThenFormat) diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx index 7cbb483fb0a1..0c16551b65c2 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -3290,7 +3290,18 @@ bool DocumentRedlineManager::AcceptRedlineRange(SwRedlineTable::size_type nPosOr } nPamEndtNI = pTmp->Start()->GetNodeIndex(); nPamEndCI = pTmp->Start()->GetContentIndex(); - bRet |= lcl_AcceptRedline(maRedlineTable, nRdlIdx, bCallDelete); + + if (pTmp->GetType() == RedlineType::Format && pTmp->GetStackCount() > 1 + && pTmp->GetType(1) == RedlineType::Insert) + { + // This combination of 2 redline types prefers accepting the inner one first. + bRet |= lcl_DeleteInnerRedline(maRedlineTable, nRdlIdx, 1); + } + else + { + bRet |= lcl_AcceptRedline(maRedlineTable, nRdlIdx, bCallDelete); + } + nRdlIdx++; //we will decrease it in the loop anyway. } else if (CanCombineTypesForAcceptReject(aOrigData, *pTmp)