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
         {

Reply via email to