sw/qa/core/frmedt/data/paste-fly-in-textbox.docx |binary
 sw/qa/core/frmedt/frmedt.cxx                     |   30 ++++++++++++++++
 sw/source/core/frmedt/fecopy.cxx                 |   42 +++++++++++++++++++++++
 3 files changed, 72 insertions(+)

New commits:
commit 3ac675736066b47da7329269a01c1ef4a9cfe72a
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon Nov 2 21:01:14 2020 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue Nov 3 09:01:49 2020 +0100

    tdf#135893 sw paste: fix copying fly frame in textbox twice
    
    Regression from commit c7307c77254557646f33017af915f6808a861e29
    (fdo#82191 sw::DocumentLayoutManager: copy textbox content of draw
    formats, 2014-08-15), the problem is that the fly+draw format copies the
    fly content recursively already, so when we would copy all special
    formats of the document, the inner fly frame is copied twice.
    
    This is normally not a problem for fly frames (where you can't select
    multiple fly frames at the same time), nor a problem for draw frames
    (which have no sw content), but it's a problem for the combination of
    these, TextBoxes.
    
    Fix the problem by ignoring fly frames which are anchored in such
    TextBoxes: we do the same for fly frames which have an associated draw
    format already.
    
    Change-Id: I3376beb414f91abfa6f3f5640f825ccae34911c2
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105204
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/core/frmedt/data/paste-fly-in-textbox.docx 
b/sw/qa/core/frmedt/data/paste-fly-in-textbox.docx
new file mode 100644
index 000000000000..75bf13b13b67
Binary files /dev/null and b/sw/qa/core/frmedt/data/paste-fly-in-textbox.docx 
differ
diff --git a/sw/qa/core/frmedt/frmedt.cxx b/sw/qa/core/frmedt/frmedt.cxx
index b4074a73e12d..c0ea7e0566e9 100644
--- a/sw/qa/core/frmedt/frmedt.cxx
+++ b/sw/qa/core/frmedt/frmedt.cxx
@@ -22,6 +22,7 @@
 #include <frameformats.hxx>
 #include <unotxdoc.hxx>
 #include <docsh.hxx>
+#include <swdtflvr.hxx>
 
 char const DATA_DIRECTORY[] = "/sw/qa/core/frmedt/data/";
 
@@ -109,6 +110,35 @@ CPPUNIT_TEST_FIXTURE(SwCoreFrmedtTest, 
testVertPosFromBottomBoundingBox)
     CPPUNIT_ASSERT_EQUAL(-1 * nPagePrintAreaBottom, aBoundRect.Pos().getY());
 }
 
+CPPUNIT_TEST_FIXTURE(SwCoreFrmedtTest, testPasteFlyInTextBox)
+{
+    // Given a document that contains a textbox, which contains an sw image 
(fly frame)
+    load(DATA_DIRECTORY, "paste-fly-in-textbox.docx");
+    SwXTextDocument* pTextDoc = 
dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    SwDocShell* pDocShell = pTextDoc->GetDocShell();
+    SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+    SwDoc* pDoc = pDocShell->GetDoc();
+    SdrPage* pPage = 
pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
+    SdrObject* pObject = pPage->GetObj(0);
+    pWrtShell->SelectObj(Point(), 0, pObject);
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), 
pDoc->GetSpzFrameFormats()->GetFormatCount());
+    rtl::Reference<SwTransferable> pTransfer = new SwTransferable(*pWrtShell);
+    pTransfer->Cut();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), 
pDoc->GetSpzFrameFormats()->GetFormatCount());
+    TransferableDataHelper aHelper(pTransfer.get());
+
+    // When pasting that to an empty document.
+    SwTransferable::Paste(*pWrtShell, aHelper);
+
+    // Then we should have the image only once: 3 formats (draw+fly formats 
for the textbox and a
+    // fly format for the image).
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 3
+    // - Actual  : 4
+    // i.e. the image was pasted twice.
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), 
pDoc->GetSpzFrameFormats()->GetFormatCount());
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx
index ca20591a9a61..9257514a2236 100644
--- a/sw/source/core/frmedt/fecopy.cxx
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -666,6 +666,41 @@ namespace {
     {
         return rPaM.HasMark() && *rPaM.GetPoint() != *rPaM.GetMark();
     }
+
+    /// Is pFormat anchored in a fly frame which has an associated draw format?
+    bool IsInTextBox(const SwFrameFormat* pFormat)
+    {
+        const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
+        const SwPosition* pPosition = rAnchor.GetContentAnchor();
+        if (!pPosition)
+        {
+            return false;
+        }
+
+        const SwStartNode* pFlyNode = 
pPosition->nNode.GetNode().FindFlyStartNode();
+        if (!pFlyNode)
+        {
+            return false;
+        }
+
+        for ( const auto& pSpzFormat : 
*pFormat->GetDoc()->GetSpzFrameFormats() )
+        {
+            if (pSpzFormat->Which() != RES_FLYFRMFMT)
+            {
+                continue;
+            }
+
+            const SwNodeIndex* pIdx = pSpzFormat->GetContent().GetContentIdx();
+            if (!pIdx || pFlyNode != &pIdx->GetNode())
+            {
+                continue;
+            }
+
+            return SwTextBoxHelper::isTextBox(pSpzFormat, RES_FLYFRMFMT);
+        }
+
+        return false;
+    }
 }
 
 bool SwFEShell::Paste(SwDoc& rClpDoc, bool bNestedTable)
@@ -952,6 +987,13 @@ bool SwFEShell::Paste(SwDoc& rClpDoc, bool bNestedTable)
                                 if (pCpyObj && CheckControlLayer(pCpyObj))
                                     continue;
                             }
+                            else if (pCpyFormat->Which() == RES_FLYFRMFMT && 
IsInTextBox(pCpyFormat))
+                            {
+                                // This is a fly frame which is anchored in a 
TextBox, ignore it as
+                                // it's already copied as part of copying the 
content of the
+                                // TextBox.
+                                continue;
+                            }
 
                             // Ignore TextBoxes, they are already handled in 
sw::DocumentLayoutManager::CopyLayoutFormat().
                             if (SwTextBoxHelper::isTextBox(pCpyFormat, 
RES_FLYFRMFMT))
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to