summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2020-11-02 21:01:14 +0100
committerMiklos Vajna <vmiklos@collabora.com>2020-11-03 09:01:49 +0100
commit3ac675736066b47da7329269a01c1ef4a9cfe72a (patch)
treefc82197ece40dc43975e2f7fb1445839c869fa65
parenta83e6e96b65903d6e154b3711ec261d44e55b324 (diff)
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 <vmiklos@collabora.com>
-rw-r--r--sw/qa/core/frmedt/data/paste-fly-in-textbox.docxbin0 -> 6092 bytes
-rw-r--r--sw/qa/core/frmedt/frmedt.cxx30
-rw-r--r--sw/source/core/frmedt/fecopy.cxx42
3 files changed, 72 insertions, 0 deletions
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
--- /dev/null
+++ b/sw/qa/core/frmedt/data/paste-fly-in-textbox.docx
Binary files 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))