sw/qa/core/edit/edit.cxx | 48 ++++++++++++++++++++++++++++++++++++++++ sw/source/core/edit/edredln.cxx | 11 ++++++++- 2 files changed, 58 insertions(+), 1 deletion(-)
New commits: commit 157c00922959adc8fd2e0203ed94dfd847479c54 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Tue Mar 25 09:14:04 2025 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue Mar 25 16:35:00 2025 +0100 cool#11357 sw redline reinstate: handle deletes in selection In case the cursor is inside a delete redline, then .uno:ReinstateTrackedChange works for that change, but if the cursor is a selection that covers one or more deletes, then this simply kills the selection. This happens because reinstating creates new redlines, but SwEditShell::ReinstateRedlinesInSelection() iterates the redline table while reinstating. Fix the problem by creating a copy of the redline pointers and work on that copy, this way all deletes are reinstated correctly. The command has no explicit state yet, though. Change-Id: Ia0e7b8365cb423ebf10d8f75aaff30d6495e1f7a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183302 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/qa/core/edit/edit.cxx b/sw/qa/core/edit/edit.cxx index 21455842da24..3bf605e565f0 100644 --- a/sw/qa/core/edit/edit.cxx +++ b/sw/qa/core/edit/edit.cxx @@ -282,6 +282,54 @@ CPPUNIT_TEST_FIXTURE(Test, testRedlineReinstateSingleRichDelete) CPPUNIT_ASSERT_GREATER(pRedline2->Start()->nNode, pRedline2->End()->nNode); } +CPPUNIT_TEST_FIXTURE(Test, testRedlineReinstateDeletesInSelection) +{ + // Given a document with two deletions: + createSwDoc(); + SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell(); + pWrtShell->Insert("abcde"); + SwModule* pModule = SwModule::get(); + pModule->SetRedlineAuthor("Alice"); + RedlineFlags nMode = pWrtShell->GetRedlineFlags(); + pWrtShell->SetRedlineFlags(nMode | RedlineFlags::On); + pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false); + pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false); + pWrtShell->DelRight(); + pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 2, /*bBasicCall=*/false); + pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, /*bBasicCall=*/false); + pWrtShell->DelRight(); + pWrtShell->SetRedlineFlags(nMode); + + // When a 2nd user reinstates those changes with a selection: + pModule->SetRedlineAuthor("Bob"); + // Create a selection that excludes the initial "a" and the last "e": + pWrtShell->SttPara(/*bSelect=*/false); + pWrtShell->EndPara(/*bSelect=*/true); + dispatchCommand(mxComponent, ".uno:ReinstateTrackedChange", {}); + + // Then make sure this results in inserts after deletes: + SwDoc* pDoc = pWrtShell->GetDoc(); + IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess(); + SwRedlineTable& rRedlines = rIDRA.GetRedlineTable(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 4 + // - Actual : 2 + // i.e. no insert redlines were created. + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), rRedlines.size()); + const SwRangeRedline* pRedline1 = rRedlines[0]; + const SwRedlineData& rRedlineData1 = pRedline1->GetRedlineData(0); + CPPUNIT_ASSERT_EQUAL(RedlineType::Delete, rRedlineData1.GetType()); + const SwRangeRedline* pRedline2 = rRedlines[1]; + const SwRedlineData& rRedlineData2 = pRedline2->GetRedlineData(0); + CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlineData2.GetType()); + const SwRangeRedline* pRedline3 = rRedlines[2]; + const SwRedlineData& rRedlineData3 = pRedline3->GetRedlineData(0); + CPPUNIT_ASSERT_EQUAL(RedlineType::Delete, rRedlineData3.GetType()); + const SwRangeRedline* pRedline4 = rRedlines[3]; + const SwRedlineData& rRedlineData4 = pRedline4->GetRedlineData(0); + CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlineData4.GetType()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sw/source/core/edit/edredln.cxx b/sw/source/core/edit/edredln.cxx index a99a8f2e459d..6f2bec071498 100644 --- a/sw/source/core/edit/edredln.cxx +++ b/sw/source/core/edit/edredln.cxx @@ -220,9 +220,18 @@ void SwEditShell::ReinstateRedlinesInSelection() SwPosition aCursorStart(*GetCursor()->Start()); SwPosition aCursorEnd(*GetCursor()->End()); SwRedlineTable& rTable = GetDoc()->getIDocumentRedlineAccess().GetRedlineTable(); + + // Work on a copy, since reinstate will modify the table, and reinstate of just inserted + // redlines is not wanted. + std::vector<SwRangeRedline*> aRedlines(rTable.size()); for (size_t nIndex = 0; nIndex < rTable.size(); ++nIndex) { - const SwRangeRedline& rRedline = *rTable[nIndex]; + aRedlines[nIndex] = rTable[nIndex]; + } + + for (size_t nIndex = 0; nIndex < aRedlines.size(); ++nIndex) + { + const SwRangeRedline& rRedline = *aRedlines[nIndex]; if (!rRedline.HasMark() || !rRedline.IsVisible()) { continue;