sw/qa/core/doc/DocumentRedlineManager.cxx | 32 ++++++++++++++++++++++++++ sw/qa/core/doc/data/ins-then-format-self.docx |binary sw/source/core/doc/DocumentRedlineManager.cxx | 9 ++++++- 3 files changed, 40 insertions(+), 1 deletion(-)
New commits: commit c80832085d6606a082c7052d07262d95d20cb0db Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Tue Jul 15 08:23:09 2025 +0200 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Tue Jul 15 17:33:20 2025 +0200 tdf#166319 sw interdependent redlines: handle deleting a self ins-then-fmt The bugdoc has <ins>A<format>B</format>C</ins>, go to the end, delete C, result is <ins>A<format>B</format></ins> given that this was a self-insert, but the next delete results in <ins>A</ins><del>B</del>. The problem is that we have special code to deal with delete on self-insert (it's fine to just remove such content from the model), but this code won't handle insert-then-format as insert, while Word does. Fix the problem by extending DocumentRedlineManager::PreAppendDeleteRedline() to look "through" just format redlines to see the underlying insert. Note that the same is not needed for delete-then-format, since insert is always inserted next to an existing content or redlined content, so there is no overlap. Change-Id: I8b47839ffaa470714a5dd37722aa26ac0002c0bc Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187907 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins (cherry picked from commit f66d63da05dbe2f254ffaf428257684a38523f66) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187921 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/sw/qa/core/doc/DocumentRedlineManager.cxx b/sw/qa/core/doc/DocumentRedlineManager.cxx index 77f36c8012f1..8fac406a45aa 100644 --- a/sw/qa/core/doc/DocumentRedlineManager.cxx +++ b/sw/qa/core/doc/DocumentRedlineManager.cxx @@ -10,12 +10,15 @@ #include <swmodeltestbase.hxx> #include <editeng/wghtitem.hxx> +#include <comphelper/scopeguard.hxx> #include <IDocumentRedlineAccess.hxx> #include <docsh.hxx> #include <redline.hxx> #include <view.hxx> #include <wrtsh.hxx> +#include <swmodule.hxx> +#include <strings.hrc> namespace { @@ -96,6 +99,35 @@ CPPUNIT_TEST_FIXTURE(Test, testRedlineIns) CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlines[2]->GetType()); } } + +CPPUNIT_TEST_FIXTURE(Test, testInsThenFormatSelf) +{ + // Given a document with <ins>A<format>B</format>C</ins> redlines, created by Alice: + createSwDoc("ins-then-format-self.docx"); + SwModule* pModule = SwModule::get(); + pModule->SetRedlineAuthor("Alice"); + comphelper::ScopeGuard g( + [pModule] { pModule->SetRedlineAuthor(SwResId(STR_REDLINE_UNKNOWN_AUTHOR)); }); + SwDocShell* pDocShell = getSwDocShell(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + pWrtShell->SttEndDoc(/*bStt=*/false); + SwDoc* pDoc = pDocShell->GetDoc(); + IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess(); + SwRedlineTable& rRedlines = rIDRA.GetRedlineTable(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), rRedlines.size()); + pWrtShell->DelLeft(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rRedlines.size()); + + // When deleting B: + pWrtShell->DelLeft(); + + // Then make sure that B is removed from the document (since this is a self-insert): + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 2 + // i.e. a delete was created instead of removing the insert. + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size()); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/core/doc/data/ins-then-format-self.docx b/sw/qa/core/doc/data/ins-then-format-self.docx new file mode 100644 index 000000000000..55e90fbae7ac Binary files /dev/null and b/sw/qa/core/doc/data/ins-then-format-self.docx differ diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx index f19d352e4888..0eb97aeb3339 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -1918,7 +1918,14 @@ void DocumentRedlineManager::PreAppendInsertRedline(AppendRedlineContext& rCtx) void DocumentRedlineManager::PreAppendDeleteRedline(AppendRedlineContext& rCtx) { - switch( rCtx.pRedl->GetType() ) + RedlineType eRedlType = rCtx.pRedl->GetType(); + bool bHierarchicalFormat = rCtx.pRedl->GetType() == RedlineType::Format && rCtx.pRedl->GetStackCount() > 1; + if (bHierarchicalFormat && rCtx.pRedl->GetType(1) == RedlineType::Insert) + { + eRedlType = rCtx.pRedl->GetType(1); + } + + switch (eRedlType) { case RedlineType::Delete: switch( rCtx.eCmpPos )