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: */

Reply via email to