dev/null |binary sw/inc/textboxhelper.hxx | 11 --- sw/qa/extras/uiwriter/uiwriter4.cxx | 25 -------- sw/source/core/doc/DocumentLayoutManager.cxx | 65 ++++++++++++++++++++- sw/source/core/doc/textboxhelper.cxx | 81 --------------------------- 5 files changed, 62 insertions(+), 120 deletions(-)
New commits: commit a4ea14695a8e7b7beeb89fae170df2f7ec9f4171 Author: Justin Luth <[email protected]> AuthorDate: Wed Apr 12 08:20:48 2023 -0400 Commit: Andras Timar <[email protected]> CommitDate: Wed Apr 12 21:32:36 2023 +0200 Revert "tdf#149550 sw: fix crash by implementing nested textbox copy" This reverts commit d981737bcebf825949cd8b13c2c609a109abc984. It was added for T38690 and removed for T41585 Change-Id: Iae7f0f273f81f050a2fbfa589451e6039a1a2193 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150291 Reviewed-by: Justin Luth <[email protected]> Reviewed-by: Andras Timar <[email protected]> Tested-by: Andras Timar <[email protected]> diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx index b0ab5618b466..a389634c60eb 100644 --- a/sw/inc/textboxhelper.hxx +++ b/sw/inc/textboxhelper.hxx @@ -27,7 +27,6 @@ class SdrObject; class SfxItemSet; class SwFrameFormat; class SwFrameFormats; -class SwFormatAnchor; class SwFormatContent; class SwDoc; namespace tools @@ -205,8 +204,6 @@ class SwTextBoxNode // (and the textboxes) SwFrameFormat* m_pOwnerShapeFormat; - mutable bool m_bIsCloningInProgress; - public: // Not needed. SwTextBoxNode() = delete; @@ -254,14 +251,6 @@ public: size_t GetTextBoxCount() const { return m_pTextBoxes.size(); }; // Returns with a const collection of textboxes owned by this node. std::map<SdrObject*, SwFrameFormat*> GetAllTextBoxes() const; - - void Clone(SwDoc* pDoc, const SwFormatAnchor& rNewAnc, SwFrameFormat* o_pTarget, bool bSetAttr, - bool bMakeFrame) const; - -private: - void Clone_Impl(SwDoc* pDoc, const SwFormatAnchor& rNewAnc, SwFrameFormat* o_pTarget, - const SdrObject* pSrcObj, SdrObject* pDestObj, bool bSetAttr, - bool bMakeFrame) const; }; #endif // INCLUDED_SW_INC_TEXTBOXHELPER_HXX diff --git a/sw/qa/extras/uiwriter/data/tdf149550.docx b/sw/qa/extras/uiwriter/data/tdf149550.docx deleted file mode 100644 index 3434fc1fff93..000000000000 Binary files a/sw/qa/extras/uiwriter/data/tdf149550.docx and /dev/null differ diff --git a/sw/qa/extras/uiwriter/uiwriter4.cxx b/sw/qa/extras/uiwriter/uiwriter4.cxx index 715f58334002..575e71681685 100644 --- a/sw/qa/extras/uiwriter/uiwriter4.cxx +++ b/sw/qa/extras/uiwriter/uiwriter4.cxx @@ -293,7 +293,6 @@ public: void testInsertPdf(); void testTdf143760WrapContourToOff(); void testHatchFill(); - void testNestedGroupTextBoxCopyCrash(); CPPUNIT_TEST_SUITE(SwUiWriterTest4); CPPUNIT_TEST(testTdf96515); @@ -420,7 +419,6 @@ public: CPPUNIT_TEST(testInsertPdf); CPPUNIT_TEST(testTdf143760WrapContourToOff); CPPUNIT_TEST(testHatchFill); - CPPUNIT_TEST(testNestedGroupTextBoxCopyCrash); CPPUNIT_TEST_SUITE_END(); }; @@ -4183,29 +4181,6 @@ void SwUiWriterTest4::testHatchFill() CPPUNIT_ASSERT_EQUAL(sal_Int32(30), getProperty<sal_Int32>(getShape(1), "FillTransparence")); } -void SwUiWriterTest4::testNestedGroupTextBoxCopyCrash() -{ - createSwDoc(DATA_DIRECTORY, "tdf149550.docx"); - - dispatchCommand(mxComponent, ".uno:SelectAll", {}); - Scheduler::ProcessEventsToIdle(); - dispatchCommand(mxComponent, ".uno:Copy", {}); - Scheduler::ProcessEventsToIdle(); - // This crashed here before the fix. - SwXTextDocument* pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get()); - CPPUNIT_ASSERT(pXTextDocument); - pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_ESCAPE); - Scheduler::ProcessEventsToIdle(); - dispatchCommand(mxComponent, ".uno:Paste", {}); - Scheduler::ProcessEventsToIdle(); - - CPPUNIT_ASSERT_MESSAGE("Where is the doc, it crashed, isn't it?!", mxComponent); - - auto pLayout = parseLayoutDump(); - // There must be 2 textboxes! - assertXPath(pLayout, "/root/page/body/txt/anchored/fly[2]"); -} - CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest4); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/core/doc/DocumentLayoutManager.cxx b/sw/source/core/doc/DocumentLayoutManager.cxx index a03d5dc1d60d..006501b3aa36 100644 --- a/sw/source/core/doc/DocumentLayoutManager.cxx +++ b/sw/source/core/doc/DocumentLayoutManager.cxx @@ -463,6 +463,67 @@ SwFrameFormat *DocumentLayoutManager::CopyLayoutFormat( if( bMakeFrames ) pDest->MakeFrames(); + // If the draw format has a TextBox, then copy its fly format as well. + if (rSource.Which() == RES_DRAWFRMFMT && rSource.GetOtherTextBoxFormats()) + { + auto pObj = rSource.FindRealSdrObject(); + auto pTextBoxNd = std::make_shared<SwTextBoxNode>(SwTextBoxNode(pDest)); + pDest->SetOtherTextBoxFormats(pTextBoxNd); + + if (pObj) + { + const bool bIsGroupObj = pObj->getChildrenOfSdrObject(); + for (size_t it = 0; + it < (bIsGroupObj ? pObj->getChildrenOfSdrObject()->GetObjCount() : 1); it++) + { + auto pChild = bIsGroupObj ? pObj->getChildrenOfSdrObject()->GetObj(it) + : const_cast<SdrObject*>(pObj); + if (auto pSourceTextBox + = SwTextBoxHelper::getOtherTextBoxFormat(&rSource, RES_DRAWFRMFMT, pChild)) + { + SwFormatAnchor boxAnchor(rNewAnchor); + if (RndStdIds::FLY_AS_CHAR == boxAnchor.GetAnchorId()) + { + // AS_CHAR *must not* be set on textbox fly-frame + boxAnchor.SetType(RndStdIds::FLY_AT_CHAR); + } + // presumably these anchors are supported though not sure + assert(RndStdIds::FLY_AT_CHAR == boxAnchor.GetAnchorId() + || RndStdIds::FLY_AT_PARA == boxAnchor.GetAnchorId() + || boxAnchor.GetAnchorId() == RndStdIds::FLY_AT_PAGE); + + if (!bMakeFrames && rNewAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR) + { + // If the draw format is as-char, then it will be copied with bMakeFrames=false, but + // doing the same for the fly format would result in not making fly frames at all. + bMakeFrames = true; + } + SwFrameFormat* pDestTextBox + = CopyLayoutFormat(*pSourceTextBox, boxAnchor, bSetTextFlyAtt, bMakeFrames); + + SwAttrSet aSet(pDest->GetAttrSet()); + SwFormatContent aContent( + pDestTextBox->GetContent().GetContentIdx()->GetNode().GetStartNode()); + aSet.Put(aContent); + pDest->SetFormatAttr(aSet); + + // Link FLY and DRAW formats, so it becomes a text box + SdrObject* pNewObj = pDest->FindRealSdrObject(); + if (bIsGroupObj && pNewObj + && pNewObj->getChildrenOfSdrObject() + && (pNewObj->getChildrenOfSdrObject()->GetObjCount() > it) + && pNewObj->getChildrenOfSdrObject()->GetObj(it)) + pNewObj = pNewObj->getChildrenOfSdrObject()->GetObj(it); + pTextBoxNd->AddTextBox(pNewObj, pDestTextBox); + pDestTextBox->SetOtherTextBoxFormats(pTextBoxNd); + } + + if (!bIsGroupObj) + break; + } + } + } + if (pDest->GetName().isEmpty()) { // Format name should have unique name. Let's use object name as a fallback @@ -471,10 +532,6 @@ SwFrameFormat *DocumentLayoutManager::CopyLayoutFormat( pDest->SetName(pObj->GetName()); } - // If the draw format has a TextBox, then copy its fly format as well. - if (const auto& pTextBoxes = rSource.GetOtherTextBoxFormats()) - pTextBoxes->Clone(&m_rDoc, rNewAnchor, pDest, bSetTextFlyAtt, bMakeFrames); - return pDest; } diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx index bcdf25002305..41ca905f5d19 100644 --- a/sw/source/core/doc/textboxhelper.cxx +++ b/sw/source/core/doc/textboxhelper.cxx @@ -247,7 +247,7 @@ void SwTextBoxHelper::set(SwFrameFormat* pShapeFormat, SdrObject* pObj, { // If the shape do not have a texbox node and textbox, // create that for the shape. - auto pTextBox = std::make_shared<SwTextBoxNode>(SwTextBoxNode(pShapeFormat)); + auto pTextBox = std::shared_ptr<SwTextBoxNode>(new SwTextBoxNode(pShapeFormat)); pTextBox->AddTextBox(pObj, pFormat); pShapeFormat->SetOtherTextBoxFormats(pTextBox); pFormat->SetOtherTextBoxFormats(pTextBox); @@ -1525,8 +1525,6 @@ SwTextBoxNode::SwTextBoxNode(SwFrameFormat* pOwnerShape) assert(pOwnerShape); assert(pOwnerShape->Which() == RES_DRAWFRMFMT); - m_bIsCloningInProgress = false; - m_pOwnerShapeFormat = pOwnerShape; if (!m_pTextBoxes.empty()) m_pTextBoxes.clear(); @@ -1685,81 +1683,4 @@ std::map<SdrObject*, SwFrameFormat*> SwTextBoxNode::GetAllTextBoxes() const return aRet; } -void SwTextBoxNode::Clone(SwDoc* pDoc, const SwFormatAnchor& rNewAnc, SwFrameFormat* o_pTarget, - bool bSetAttr, bool bMakeFrame) const -{ - if (!o_pTarget || !pDoc) - return; - - if (o_pTarget->Which() != RES_DRAWFRMFMT) - return; - - if (m_bIsCloningInProgress) - return; - - m_bIsCloningInProgress = true; - - Clone_Impl(pDoc, rNewAnc, o_pTarget, m_pOwnerShapeFormat->FindSdrObject(), - o_pTarget->FindSdrObject(), bSetAttr, bMakeFrame); - - m_bIsCloningInProgress = false; -} - -void SwTextBoxNode::Clone_Impl(SwDoc* pDoc, const SwFormatAnchor& rNewAnc, SwFrameFormat* o_pTarget, - const SdrObject* pSrcObj, SdrObject* pDestObj, bool bSetAttr, - bool bMakeFrame) const -{ - if (!pSrcObj || !pDestObj) - return; - - auto pSrcList = pSrcObj->getChildrenOfSdrObject(); - auto pDestList = pDestObj->getChildrenOfSdrObject(); - - if (pSrcList && pDestList) - { - if (pSrcList->GetObjCount() != pDestList->GetObjCount()) - return; - - for (size_t i = 0; i < pSrcList->GetObjCount(); ++i) - { - Clone_Impl(pDoc, rNewAnc, o_pTarget, pSrcList->GetObj(i), pDestList->GetObj(i), - bSetAttr, bMakeFrame); - } - return; - } - - if (!pSrcList && !pDestList) - { - if (auto pSrcFormat = GetTextBox(pSrcObj)) - { - SwFormatAnchor aNewAnchor(rNewAnc); - if (aNewAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR) - { - aNewAnchor.SetType(RndStdIds::FLY_AT_CHAR); - - if (!bMakeFrame) - bMakeFrame = true; - } - - if (auto pTargetFormat = pDoc->getIDocumentLayoutAccess().CopyLayoutFormat( - *pSrcFormat, aNewAnchor, bSetAttr, bMakeFrame)) - { - if (!o_pTarget->GetOtherTextBoxFormats()) - { - auto pNewTextBoxes = std::make_shared<SwTextBoxNode>(SwTextBoxNode(o_pTarget)); - o_pTarget->SetOtherTextBoxFormats(pNewTextBoxes); - pNewTextBoxes->AddTextBox(pDestObj, pTargetFormat); - pTargetFormat->SetOtherTextBoxFormats(pNewTextBoxes); - } - else - { - o_pTarget->GetOtherTextBoxFormats()->AddTextBox(pDestObj, pTargetFormat); - pTargetFormat->SetOtherTextBoxFormats(o_pTarget->GetOtherTextBoxFormats()); - } - o_pTarget->SetFormatAttr(pTargetFormat->GetContent()); - } - } - } -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
