sw/qa/core/doc/data/at-char-image-copy.odt |binary sw/qa/core/doc/doc.cxx | 39 ++++++++++++++++ sw/source/core/doc/DocumentContentOperationsManager.cxx | 5 +- 3 files changed, 42 insertions(+), 2 deletions(-)
New commits: commit eb8a5d4630dcb09fea320b182424d8b6140c1166 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Tue Oct 8 09:03:01 2024 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue Oct 8 13:54:51 2024 +0200 tdf#134198 sw: avoid losing char pos of anchor point on content copy Load the 5 pages bugdoc to Writer, notice the image on the last page, select-all, copy, new document, paste the selection: no image on the last page. Given the new document may have different compat flags, this may not be a bug, but bisect shows this was working before commit 591673d1637b25f83e01baccc321a83f10fc0ce7 (use more SwPosition::Assign, 2022-08-29). Also note that the image in question is anchored to-char and it has a non-zero content (character) index, that's why it's on the last page, and not on page 4. The old code kept the content index unchanged while changing the node index, the new code avoids touching the nNode member directly. Fix the problem by still not touching the nNode member directly (to keep the benefits of the above commit), but explicitly keep the content index unchanged. Changing the node index without changing the char index in general is not safe (the new node may have less characters), but it does work in this case, and this fixes the regression. Change-Id: I2a90e4a88608d7435543880f46f09bea21eba48a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/174655 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/qa/core/doc/data/at-char-image-copy.odt b/sw/qa/core/doc/data/at-char-image-copy.odt new file mode 100644 index 000000000000..4af5c7f9a665 Binary files /dev/null and b/sw/qa/core/doc/data/at-char-image-copy.odt differ diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx index 3481f2687cad..80f149be88ac 100644 --- a/sw/qa/core/doc/doc.cxx +++ b/sw/qa/core/doc/doc.cxx @@ -22,6 +22,7 @@ #include <editeng/langitem.hxx> #include <vcl/scheduler.hxx> #include <comphelper/propertyvalue.hxx> +#include <comphelper/scopeguard.hxx> #include <wrtsh.hxx> #include <fmtanchr.hxx> @@ -659,6 +660,44 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testTextBoxWordWrap) CPPUNIT_ASSERT_LESS(static_cast<sal_Int32>(1000), nFlyHeight); } +CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testAtCharImageCopy) +{ + // Given a document with 2 pages, one draw object on both pages: + createSwDoc("at-char-image-copy.odt"); + SwWrtShell* pWrtShell1 = getSwDocShell()->GetWrtShell(); + pWrtShell1->SelAll(); + rtl::Reference<SwTransferable> xTransfer = new SwTransferable(*pWrtShell1); + xTransfer->Copy(); + // Don't use createSwDoc(), UnoApiTest::loadWithParams() would dispose the first document. + uno::Reference<lang::XComponent> xComponent2 = loadFromDesktop(u"private:factory/swriter"_ustr); + comphelper::ScopeGuard g([xComponent2] { xComponent2->dispose(); }); + + // When copying the body text from that document to a new one: + auto pXTextDocument2 = dynamic_cast<SwXTextDocument*>(xComponent2.get()); + SwDocShell* pDocShell2 = pXTextDocument2->GetDocShell(); + SwWrtShell* pWrtShell2 = pDocShell2->GetWrtShell(); + TransferableDataHelper aHelper(xTransfer); + SwTransferable::Paste(*pWrtShell2, aHelper); + + // Then make sure the new document also has the 2 images on the 2 pages: + SwDoc* pDoc2 = pDocShell2->GetDoc(); + SwRootFrame* pLayout2 = pDoc2->getIDocumentLayoutAccess().GetCurrentLayout(); + auto pPage1 = pLayout2->GetLower()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage1); + CPPUNIT_ASSERT(pPage1->GetSortedObjs()); + const SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 2 + // i.e. both images went to page 1. + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs.size()); + auto pPage2 = pPage1->GetNext()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage2); + CPPUNIT_ASSERT(pPage2->GetSortedObjs()); + const SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx index 79ad75ea2007..2588decb8136 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -4144,8 +4144,9 @@ void DocumentContentOperationsManager::CopyFlyInFlyImpl( ++aAnchorNdIdx; } } - // apply found anchor text node as new anchor position - newPos.Assign( aAnchorNdIdx ); + // apply found anchor text node as new anchor position, but keep the content index + // unchanged + newPos.Assign( aAnchorNdIdx, newPos.GetContentIndex() ); } else {