sw/inc/frmfmt.hxx                            |    6 -
 sw/inc/textboxhelper.hxx                     |    9 ++
 sw/qa/extras/ooxmlexport/data/Tdf147485.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport14.cxx   |    6 +
 sw/source/core/doc/DocumentLayoutManager.cxx |    8 +-
 sw/source/core/doc/docdraw.cxx               |   29 ++++----
 sw/source/core/doc/textboxhelper.cxx         |   92 +++++++++++++++++----------
 sw/source/core/draw/dcontact.cxx             |    2 
 sw/source/core/layout/atrfrm.cxx             |   31 ++-------
 sw/source/core/text/porfly.cxx               |    2 
 sw/source/core/undo/undobj1.cxx              |   22 +++---
 sw/source/core/undo/undraw.cxx               |   32 ++++-----
 12 files changed, 135 insertions(+), 104 deletions(-)

New commits:
commit 2110597ac730fa07dbbdd603fda82b182ed27c9e
Author:     Attila Bakos (NISZ) <bakos.attilakar...@nisz.hu>
AuthorDate: Wed Mar 30 13:05:37 2022 +0200
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Fri Apr 1 08:01:57 2022 +0200

    tdf#147485 sw: fix group shape crash using std::shared_ptr
    
    for SwFrameFormat::m_pOtherTextBoxeFormats.
    Before there was broken manual handling of this
    member, resulting random crashes.
    
    Details: Writer textboxes are textframe + shape
    pairs. Accordingly the shape has a draw format,
    the frame has a fly format. In case of group
    shapes the paired structure doesn't work, because
    there is one shape format and many fly formats.
    To handle this there is a class (SwTextBoxNode)
    which has a small frame format table inside.
    This cache gives the possibility to handle
    each frame shape pairs inside the group depending
    on what SdrObject owns that textbox.
    
    However there is another place where these formats
    stored, namely the SpzFrameFormatTable in SwDoc.
    The only problem is that, when a flyframe removed,
    it has to be deleted from both tables, but if the
    DelLayoutFormat() is called, that will call the
    ~FrameFormat(), and if the format already deleted
    from the SwTextBoxNode, there will be double deleting
    for the same address, which caused the crash.
    
    To avoid this the following is present:
    
    When fly deletion occurs, first the format is
    deleted from the doc, then via the ~SwFrameFomat()
    will be deleted from the TextBoxNode. If the deleted
    format is a drawing, the whole node will be destructed
    via the shared_ptr. Hopefully that will be fine,
    without any leak.
    
    Change-Id: I007724695bc035998cb35efeefecd308aae36e85
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132308
    Reviewed-by: László Németh <nem...@numbertext.org>
    Tested-by: László Németh <nem...@numbertext.org>

diff --git a/sw/inc/frmfmt.hxx b/sw/inc/frmfmt.hxx
index 12795bf10428..4a5f2f1e8e87 100644
--- a/sw/inc/frmfmt.hxx
+++ b/sw/inc/frmfmt.hxx
@@ -74,7 +74,7 @@ class SW_DLLPUBLIC SwFrameFormat
     // The assigned SwFrmFmt list.
     SwFrameFormats *m_ffList;
 
-    SwTextBoxNode* m_pOtherTextBoxFormat;
+    std::shared_ptr< SwTextBoxNode > m_pOtherTextBoxFormats;
 
     struct change_name
     {
@@ -102,8 +102,8 @@ protected:
 
 public:
 
-    SwTextBoxNode* GetOtherTextBoxFormat() const { return 
m_pOtherTextBoxFormat; };
-    void SetOtherTextBoxFormat(SwTextBoxNode* pNew) { m_pOtherTextBoxFormat = 
pNew; };
+    const std::shared_ptr< SwTextBoxNode >& GetOtherTextBoxFormats() const { 
return m_pOtherTextBoxFormats; };
+    void SetOtherTextBoxFormats(const std::shared_ptr<SwTextBoxNode>& rNew) { 
m_pOtherTextBoxFormats = rNew; };
 
     virtual ~SwFrameFormat() override;
 
diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx
index 3881d897c629..d851a0fda7d2 100644
--- a/sw/inc/textboxhelper.hxx
+++ b/sw/inc/textboxhelper.hxx
@@ -213,7 +213,7 @@ public:
     ~SwTextBoxNode();
 
     // default copy ctor is enough
-    SwTextBoxNode(SwTextBoxNode&) = default;
+    SwTextBoxNode(const SwTextBoxNode&) = default;
 
     // This method adds a textbox entry to the shape
     // Parameters:
@@ -224,7 +224,12 @@ public:
     // This will remove the textbox entry.
     // Parameters:
     //     pDrawObject: The shape which have the textbox to be deleted.
-    void DelTextBox(const SdrObject* pDrawObject);
+    void DelTextBox(const SdrObject* pDrawObject, bool bDelFromDoc = false);
+
+    // This will remove the textbox entry.
+    // Parameters:
+    //     pTextBox: The textbox what have to be deleted.
+    void DelTextBox(const SwFrameFormat* pTextBox, bool bDelFromDoc = false);
 
     // This will return with the frame format of the textbox what belongs
     // to the given shape (pDrawObject)
diff --git a/sw/qa/extras/ooxmlexport/data/Tdf147485.docx 
b/sw/qa/extras/ooxmlexport/data/Tdf147485.docx
new file mode 100644
index 000000000000..cb630efb8717
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/Tdf147485.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx
index 8ee4c8c3650c..fa0199ede9dd 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx
@@ -837,6 +837,12 @@ CPPUNIT_TEST_FIXTURE(SwModelTestBase, 
testSemiTransparentText)
     CPPUNIT_ASSERT_EQUAL(nTransparence, nActual);
 }
 
+CPPUNIT_TEST_FIXTURE(SwModelTestBase, testTdf147485)
+{
+    // Before the fix this was impossible.
+    load(DATA_DIRECTORY, "Tdf147485.docx");
+}
+
 CPPUNIT_TEST_FIXTURE(SwModelTestBase, testUserField)
 {
     // Create an in-memory empty document with a user field.
diff --git a/sw/source/core/doc/DocumentLayoutManager.cxx 
b/sw/source/core/doc/DocumentLayoutManager.cxx
index c67e9e05e9a6..006501b3aa36 100644
--- a/sw/source/core/doc/DocumentLayoutManager.cxx
+++ b/sw/source/core/doc/DocumentLayoutManager.cxx
@@ -464,11 +464,11 @@ SwFrameFormat *DocumentLayoutManager::CopyLayoutFormat(
         pDest->MakeFrames();
 
     // If the draw format has a TextBox, then copy its fly format as well.
-    if (rSource.Which() == RES_DRAWFRMFMT && rSource.GetOtherTextBoxFormat())
+    if (rSource.Which() == RES_DRAWFRMFMT && rSource.GetOtherTextBoxFormats())
     {
         auto pObj = rSource.FindRealSdrObject();
-        auto pTextBoxNd = new SwTextBoxNode(pDest);
-        pDest->SetOtherTextBoxFormat(pTextBoxNd);
+        auto pTextBoxNd = 
std::make_shared<SwTextBoxNode>(SwTextBoxNode(pDest));
+        pDest->SetOtherTextBoxFormats(pTextBoxNd);
 
         if (pObj)
         {
@@ -515,7 +515,7 @@ SwFrameFormat *DocumentLayoutManager::CopyLayoutFormat(
                         && pNewObj->getChildrenOfSdrObject()->GetObj(it))
                         pNewObj = 
pNewObj->getChildrenOfSdrObject()->GetObj(it);
                     pTextBoxNd->AddTextBox(pNewObj, pDestTextBox);
-                    pDestTextBox->SetOtherTextBoxFormat(pTextBoxNd);
+                    pDestTextBox->SetOtherTextBoxFormats(pTextBoxNd);
                 }
 
                 if (!bIsGroupObj)
diff --git a/sw/source/core/doc/docdraw.cxx b/sw/source/core/doc/docdraw.cxx
index 6445ab757a0e..cd1883ee346b 100644
--- a/sw/source/core/doc/docdraw.cxx
+++ b/sw/source/core/doc/docdraw.cxx
@@ -225,7 +225,7 @@ SwDrawContact* SwDoc::GroupSelection( SdrView& rDrawView )
 #endif
             // Before the format will be killed, save its textbox for later 
use.
             if (auto pShapeFormat = pContact->GetFormat())
-                if (auto pTextBoxNode = pShapeFormat->GetOtherTextBoxFormat())
+                if (auto pTextBoxNode = pShapeFormat->GetOtherTextBoxFormats())
                     for (const auto& rTextBoxElement : 
pTextBoxNode->GetAllTextBoxes())
                         vSavedTextBoxes.emplace(rTextBoxElement);
 
@@ -255,14 +255,15 @@ SwDrawContact* SwDoc::GroupSelection( SdrView& rDrawView )
             text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
 
         // Add the saved textboxes to the new format.
-        auto pTextBoxNode = new SwTextBoxNode(pFormat);
+        auto pTextBoxNode = std::make_shared<SwTextBoxNode>(
+            SwTextBoxNode(static_cast<SwFrameFormat*>(pFormat)));
         for (const auto& pTextBoxEntry : vSavedTextBoxes)
         {
             
pTextBoxNode->AddTextBox(const_cast<SdrObject*>(pTextBoxEntry.first),
                                      pTextBoxEntry.second);
-            pTextBoxEntry.second->SetOtherTextBoxFormat(pTextBoxNode);
+            pTextBoxEntry.second->SetOtherTextBoxFormats(pTextBoxNode);
         }
-        pFormat->SetOtherTextBoxFormat(pTextBoxNode);
+        pFormat->SetOtherTextBoxFormats(pTextBoxNode);
         vSavedTextBoxes.clear();
 
         rDrawView.GroupMarked();
@@ -302,7 +303,7 @@ SwDrawContact* SwDoc::GroupSelection( SdrView& rDrawView )
     return pNewContact;
 }
 
-static void lcl_CollectTextBoxesForSubGroupObj(SwFrameFormat* pTargetFormat, 
SwTextBoxNode* pTextBoxNode,
+static void lcl_CollectTextBoxesForSubGroupObj(SwFrameFormat* pTargetFormat, 
std::shared_ptr<SwTextBoxNode> pTextBoxNode,
                                                SdrObject* pSourceObjs)
 {
     if (auto pChildrenObjs = pSourceObjs->getChildrenOfSdrObject())
@@ -312,12 +313,12 @@ static void 
lcl_CollectTextBoxesForSubGroupObj(SwFrameFormat* pTargetFormat, SwT
     {
         if (auto pTextBox = pTextBoxNode->GetTextBox(pSourceObjs))
         {
-            if (!pTargetFormat->GetOtherTextBoxFormat())
+            if (!pTargetFormat->GetOtherTextBoxFormats())
             {
-                pTargetFormat->SetOtherTextBoxFormat(new 
SwTextBoxNode(pTargetFormat));
+                
pTargetFormat->SetOtherTextBoxFormats(std::make_shared<SwTextBoxNode>(SwTextBoxNode(pTargetFormat)));
             }
-            pTargetFormat->GetOtherTextBoxFormat()->AddTextBox(pSourceObjs, 
pTextBox);
-            
pTextBox->SetOtherTextBoxFormat(pTargetFormat->GetOtherTextBoxFormat());
+            pTargetFormat->GetOtherTextBoxFormats()->AddTextBox(pSourceObjs, 
pTextBox);
+            
pTextBox->SetOtherTextBoxFormats(pTargetFormat->GetOtherTextBoxFormats());
         }
     }
 }
@@ -351,9 +352,9 @@ void SwDoc::UnGroupSelection( SdrView& rDrawView )
                 {
                     SwDrawContact *pContact = 
static_cast<SwDrawContact*>(GetUserCall(pObj));
 
-                    SwTextBoxNode* pTextBoxNode = nullptr;
+                    std::shared_ptr<SwTextBoxNode> pTextBoxNode;
                     if (auto pGroupFormat = pContact->GetFormat())
-                        pTextBoxNode = pGroupFormat->GetOtherTextBoxFormat();
+                        pTextBoxNode = pGroupFormat->GetOtherTextBoxFormats();
 
                     SwFormatAnchor aAnch( pContact->GetFormat()->GetAnchor() );
                     SdrObjList *pLst = pObjGroup->GetSubList();
@@ -378,10 +379,10 @@ void SwDoc::UnGroupSelection( SdrView& rDrawView )
                             {
                                 if (auto pTextBoxFormat = 
pTextBoxNode->GetTextBox(pSubObj))
                                 {
-                                    auto pNewTextBoxNode = new 
SwTextBoxNode(pFormat);
+                                    auto pNewTextBoxNode 
=std::make_shared<SwTextBoxNode>(SwTextBoxNode(pFormat));
                                     pNewTextBoxNode->AddTextBox(pSubObj, 
pTextBoxFormat);
-                                    
pFormat->SetOtherTextBoxFormat(pNewTextBoxNode);
-                                    
pTextBoxFormat->SetOtherTextBoxFormat(pNewTextBoxNode);
+                                    
pFormat->SetOtherTextBoxFormats(pNewTextBoxNode);
+                                    
pTextBoxFormat->SetOtherTextBoxFormats(pNewTextBoxNode);
                                 }
                             }
                             else
diff --git a/sw/source/core/doc/textboxhelper.cxx 
b/sw/source/core/doc/textboxhelper.cxx
index 50af58ae4786..74d29aad270b 100644
--- a/sw/source/core/doc/textboxhelper.cxx
+++ b/sw/source/core/doc/textboxhelper.cxx
@@ -69,7 +69,7 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape, 
SdrObject* pObject, bool bCo
     const bool bIsGroupObj = 
dynamic_cast<SdrObjGroup*>(pObject->getParentSdrObjectFromSdrObject());
 
     // If TextBox wasn't enabled previously
-    if (pShape->GetOtherTextBoxFormat() && 
pShape->GetOtherTextBoxFormat()->GetTextBox(pObject))
+    if (pShape->GetOtherTextBoxFormats() && 
pShape->GetOtherTextBoxFormats()->GetTextBox(pObject))
         return;
 
     // Store the current text content of the shape
@@ -115,19 +115,19 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape, 
SdrObject* pObject, bool bCo
     assert(nullptr != dynamic_cast<SwDrawFrameFormat*>(pShape));
     assert(nullptr != dynamic_cast<SwFlyFrameFormat*>(pFormat));
 
-    if (!pShape->GetOtherTextBoxFormat())
+    if (!pShape->GetOtherTextBoxFormats())
     {
-        auto* pTextBox = new SwTextBoxNode(pShape);
+        auto pTextBox = std::make_shared<SwTextBoxNode>(SwTextBoxNode(pShape));
         pTextBox->AddTextBox(pObject, pFormat);
-        pShape->SetOtherTextBoxFormat(pTextBox);
-        pFormat->SetOtherTextBoxFormat(pTextBox);
+        pShape->SetOtherTextBoxFormats(pTextBox);
+        pFormat->SetOtherTextBoxFormats(pTextBox);
     }
     else
     {
-        auto* pTextBox = pShape->GetOtherTextBoxFormat();
+        auto pTextBox = pShape->GetOtherTextBoxFormats();
         pTextBox->AddTextBox(pObject, pFormat);
-        pShape->SetOtherTextBoxFormat(pTextBox);
-        pFormat->SetOtherTextBoxFormat(pTextBox);
+        pShape->SetOtherTextBoxFormats(pTextBox);
+        pFormat->SetOtherTextBoxFormats(pTextBox);
     }
     // Initialize properties.
     uno::Reference<beans::XPropertySet> xPropertySet(xTextFrame, 
uno::UNO_QUERY);
@@ -222,7 +222,7 @@ void SwTextBoxHelper::set(SwFrameFormat* pShapeFormat, 
SdrObject* pObj,
         return;
     std::vector<std::pair<beans::Property, uno::Any>> aOldProps;
     // If there is a format, check if the shape already has a textbox assigned 
to.
-    if (auto pTextBoxNode = pShapeFormat->GetOtherTextBoxFormat())
+    if (auto pTextBoxNode = pShapeFormat->GetOtherTextBoxFormats())
     {
         // If it has a texbox, destroy it.
         if (pTextBoxNode->GetTextBox(pObj))
@@ -251,16 +251,16 @@ void SwTextBoxHelper::set(SwFrameFormat* pShapeFormat, 
SdrObject* pObj,
         }
         // And set the new one.
         pTextBoxNode->AddTextBox(pObj, pFormat);
-        pFormat->SetOtherTextBoxFormat(pTextBoxNode);
+        pFormat->SetOtherTextBoxFormats(pTextBoxNode);
     }
     else
     {
         // If the shape do not have a texbox node and textbox,
         // create that for the shape.
-        auto* pTextBox = new SwTextBoxNode(pShapeFormat);
+        auto pTextBox = std::shared_ptr<SwTextBoxNode>(new 
SwTextBoxNode(pShapeFormat));
         pTextBox->AddTextBox(pObj, pFormat);
-        pShapeFormat->SetOtherTextBoxFormat(pTextBox);
-        pFormat->SetOtherTextBoxFormat(pTextBox);
+        pShapeFormat->SetOtherTextBoxFormats(pTextBox);
+        pFormat->SetOtherTextBoxFormats(pTextBox);
     }
     // Initialize its properties
     uno::Reference<beans::XPropertySet> xPropertySet(xNew, uno::UNO_QUERY);
@@ -336,14 +336,14 @@ void SwTextBoxHelper::set(SwFrameFormat* pShapeFormat, 
SdrObject* pObj,
 void SwTextBoxHelper::destroy(const SwFrameFormat* pShape, const SdrObject* 
pObject)
 {
     // If a TextBox was enabled previously
-    auto pTextBox = pShape->GetOtherTextBoxFormat();
+    auto pTextBox = pShape->GetOtherTextBoxFormats();
     if (pTextBox && pTextBox->IsTextBoxActive(pObject))
     {
         // Unlink the TextBox's text range from the original shape.
         pTextBox->SetTextBoxInactive(pObject);
 
         // Delete the associated TextFrame.
-        pTextBox->DelTextBox(pObject);
+        pTextBox->DelTextBox(pObject, true);
     }
 }
 
@@ -355,7 +355,7 @@ bool SwTextBoxHelper::isTextBox(const SwFrameFormat* 
pFormat, sal_uInt16 nType,
     if (!pFormat || pFormat->Which() != nType)
         return false;
 
-    auto pTextBox = pFormat->GetOtherTextBoxFormat();
+    auto pTextBox = pFormat->GetOtherTextBoxFormats();
     if (!pTextBox)
         return false;
 
@@ -474,14 +474,14 @@ SwFrameFormat* 
SwTextBoxHelper::getOtherTextBoxFormat(const SwFrameFormat* pForm
     if (nType == RES_DRAWFRMFMT)
     {
         if (pObject)
-            return pFormat->GetOtherTextBoxFormat()->GetTextBox(pObject);
+            return pFormat->GetOtherTextBoxFormats()->GetTextBox(pObject);
         if (pFormat->FindRealSdrObject())
-            return 
pFormat->GetOtherTextBoxFormat()->GetTextBox(pFormat->FindRealSdrObject());
+            return 
pFormat->GetOtherTextBoxFormats()->GetTextBox(pFormat->FindRealSdrObject());
         return nullptr;
     }
     if (nType == RES_FLYFRMFMT)
     {
-        return pFormat->GetOtherTextBoxFormat()->GetOwnerShape();
+        return pFormat->GetOtherTextBoxFormats()->GetOwnerShape();
     }
     return nullptr;
 }
@@ -1633,13 +1633,7 @@ SwTextBoxNode::SwTextBoxNode(SwFrameFormat* pOwnerShape)
         m_pTextBoxes.clear();
 }
 
-SwTextBoxNode::~SwTextBoxNode()
-{
-    m_pTextBoxes.clear();
-
-    if (m_pOwnerShapeFormat && m_pOwnerShapeFormat->GetOtherTextBoxFormat())
-        m_pOwnerShapeFormat->SetOtherTextBoxFormat(nullptr);
-}
+SwTextBoxNode::~SwTextBoxNode() { m_pTextBoxes.clear(); }
 
 void SwTextBoxNode::AddTextBox(SdrObject* pDrawObject, SwFrameFormat* 
pNewTextBox)
 {
@@ -1660,7 +1654,7 @@ void SwTextBoxNode::AddTextBox(SdrObject* pDrawObject, 
SwFrameFormat* pNewTextBo
     m_pTextBoxes.push_back(aElem);
 }
 
-void SwTextBoxNode::DelTextBox(const SdrObject* pDrawObject)
+void SwTextBoxNode::DelTextBox(const SdrObject* pDrawObject, bool bDelFromDoc)
 {
     assert(pDrawObject);
     if (m_pTextBoxes.empty())
@@ -1670,10 +1664,46 @@ void SwTextBoxNode::DelTextBox(const SdrObject* 
pDrawObject)
     {
         if (it->m_pDrawObject == pDrawObject)
         {
-            
m_pOwnerShapeFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat(
-                it->m_pTextBoxFormat);
-            it = m_pTextBoxes.erase(it);
-            break;
+            if (bDelFromDoc)
+            {
+                
m_pOwnerShapeFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat(
+                    it->m_pTextBoxFormat);
+                // What about m_pTextBoxes? So, when the DelLayoutFormat() 
removes the format
+                // then the ~SwFrameFormat() will call this method again to 
remove the entry.
+                break;
+            }
+            else
+            {
+                it = m_pTextBoxes.erase(it);
+                break;
+            }
+        }
+        ++it;
+    }
+}
+
+void SwTextBoxNode::DelTextBox(const SwFrameFormat* pTextBox, bool bDelFromDoc)
+{
+    if (m_pTextBoxes.empty())
+        return;
+
+    for (auto it = m_pTextBoxes.begin(); it != m_pTextBoxes.end();)
+    {
+        if (it->m_pTextBoxFormat == pTextBox)
+        {
+            if (bDelFromDoc)
+            {
+                
m_pOwnerShapeFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat(
+                    it->m_pTextBoxFormat);
+                // What about m_pTextBoxes? So, when the DelLayoutFormat() 
removes the format
+                // then the ~SwFrameFormat() will call this method again to 
remove the entry.
+                break;
+            }
+            else
+            {
+                it = m_pTextBoxes.erase(it);
+                break;
+            }
         }
         ++it;
     }
diff --git a/sw/source/core/draw/dcontact.cxx b/sw/source/core/draw/dcontact.cxx
index f698309e4775..54e156710de0 100644
--- a/sw/source/core/draw/dcontact.cxx
+++ b/sw/source/core/draw/dcontact.cxx
@@ -1342,7 +1342,7 @@ void SwDrawContact::Changed_( const SdrObject& rObj,
             // tdf#135198: keep text box together with its shape
             const SwPageFrame* rPageFrame = pAnchoredDrawObj->GetPageFrame();
             if (rPageFrame && rPageFrame->isFrameAreaPositionValid() && 
GetFormat()
-                && GetFormat()->GetOtherTextBoxFormat())
+                && GetFormat()->GetOtherTextBoxFormats())
             {
                 SwDoc* const pDoc = GetFormat()->GetDoc();
 
diff --git a/sw/source/core/layout/atrfrm.cxx b/sw/source/core/layout/atrfrm.cxx
index e3f193470367..7db55da058d0 100644
--- a/sw/source/core/layout/atrfrm.cxx
+++ b/sw/source/core/layout/atrfrm.cxx
@@ -2520,8 +2520,7 @@ SwFrameFormat::SwFrameFormat(
     sal_uInt16 nFormatWhich,
     const WhichRangesContainer& pWhichRange)
 :   SwFormat(rPool, pFormatNm, pWhichRange, pDrvdFrame, nFormatWhich),
-    m_ffList(nullptr),
-    m_pOtherTextBoxFormat(nullptr)
+    m_ffList(nullptr)
 {
 }
 
@@ -2532,8 +2531,7 @@ SwFrameFormat::SwFrameFormat(
     sal_uInt16 nFormatWhich,
     const WhichRangesContainer& pWhichRange)
 :   SwFormat(rPool, rFormatNm, pWhichRange, pDrvdFrame, nFormatWhich),
-    m_ffList(nullptr),
-    m_pOtherTextBoxFormat(nullptr)
+    m_ffList(nullptr)
 {
 }
 
@@ -2548,24 +2546,15 @@ SwFrameFormat::~SwFrameFormat()
         }
     }
 
-    if( nullptr == m_pOtherTextBoxFormat )
+    if( nullptr == m_pOtherTextBoxFormats )
         return;
 
-    auto pObj = FindRealSdrObject();
-    if (Which() == RES_FLYFRMFMT && pObj)
-    {
-        // This is a fly-frame-format just delete this
-        // textbox entry from the draw-frame-format.
-        m_pOtherTextBoxFormat->DelTextBox(pObj);
-    }
+    // This is a fly-frame-format just delete this
+    // textbox entry from the textbox collection.
+    if (Which() == RES_FLYFRMFMT)
+        m_pOtherTextBoxFormats->DelTextBox(this);
 
-    if (Which() == RES_DRAWFRMFMT)
-    {
-        // This format is the owner shape, so its time
-        // to del the textbox node.
-        delete m_pOtherTextBoxFormat;
-        m_pOtherTextBoxFormat = nullptr;
-    }
+    m_pOtherTextBoxFormats.reset();
 }
 
 void SwFrameFormat::SetName( const OUString& rNewName, bool bBroadcast )
@@ -2884,9 +2873,9 @@ void SwFrameFormat::dumpAsXml(xmlTextWriterPtr pWriter) 
const
     if (pWhich)
         (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("which"), 
BAD_CAST(pWhich));
 
-    if (m_pOtherTextBoxFormat)
+    if (m_pOtherTextBoxFormats)
     {
-        (void)xmlTextWriterWriteFormatAttribute(pWriter, 
BAD_CAST("OtherTextBoxFormat"), "%p", m_pOtherTextBoxFormat);
+        (void)xmlTextWriterWriteFormatAttribute(pWriter, 
BAD_CAST("OtherTextBoxFormat"), "%p", m_pOtherTextBoxFormats.get());
     }
 
     GetAttrSet().dumpAsXml(pWriter);
diff --git a/sw/source/core/text/porfly.cxx b/sw/source/core/text/porfly.cxx
index f2877273f088..8a4b8befa1dc 100644
--- a/sw/source/core/text/porfly.cxx
+++ b/sw/source/core/text/porfly.cxx
@@ -364,7 +364,7 @@ void SwFlyCntPortion::SetBase( const SwTextFrame& rFrame, 
const Point &rBase,
 
     if (auto pFormat = FindFrameFormat(pSdrObj))
     {
-        if (pFormat->GetOtherTextBoxFormat())
+        if (pFormat->GetOtherTextBoxFormats())
         {
             const bool bModified = 
pFormat->GetDoc()->getIDocumentState().IsEnableSetModified();
             pFormat->GetDoc()->getIDocumentState().SetEnableSetModified(false);
diff --git a/sw/source/core/undo/undobj1.cxx b/sw/source/core/undo/undobj1.cxx
index fa88f6179442..846311867e0d 100644
--- a/sw/source/core/undo/undobj1.cxx
+++ b/sw/source/core/undo/undobj1.cxx
@@ -55,9 +55,9 @@ SwUndoFlyBase::~SwUndoFlyBase()
 {
     if( m_bDelFormat )       // delete during an Undo?
     {
-        if (m_pFrameFormat->GetOtherTextBoxFormat())
+        if (m_pFrameFormat->GetOtherTextBoxFormats())
         {   // clear that before delete
-            m_pFrameFormat->SetOtherTextBoxFormat(nullptr);
+            m_pFrameFormat->SetOtherTextBoxFormats(nullptr);
         }
         delete m_pFrameFormat;
     }
@@ -138,19 +138,19 @@ void SwUndoFlyBase::InsFly(::sw::UndoRedoContext & 
rContext, bool bShowSelFrame)
         pCNd->GetTextNode()->InsertItem(aFormat, m_nContentPos, m_nContentPos, 
SetAttrMode::NOHINTEXPAND);
     }
 
-    if (m_pFrameFormat->GetOtherTextBoxFormat())
+    if (m_pFrameFormat->GetOtherTextBoxFormats())
     {
         // recklessly assume that this thing will live longer than the
         // SwUndoFlyBase - not sure what could be done if that isn't the 
case...
-        
m_pFrameFormat->GetOtherTextBoxFormat()->GetOwnerShape()->SetOtherTextBoxFormat(
-            m_pFrameFormat->GetOtherTextBoxFormat());
+        
m_pFrameFormat->GetOtherTextBoxFormats()->GetOwnerShape()->SetOtherTextBoxFormats(
+            m_pFrameFormat->GetOtherTextBoxFormats());
 
         SdrObject* pSdrObject
-            = 
m_pFrameFormat->GetOtherTextBoxFormat()->GetOwnerShape()->FindSdrObject();
+            = 
m_pFrameFormat->GetOtherTextBoxFormats()->GetOwnerShape()->FindSdrObject();
         if (pSdrObject && m_pFrameFormat->Which() == RES_FLYFRMFMT)
-            m_pFrameFormat->GetOtherTextBoxFormat()->AddTextBox(pSdrObject, 
m_pFrameFormat);
+            m_pFrameFormat->GetOtherTextBoxFormats()->AddTextBox(pSdrObject, 
m_pFrameFormat);
 
-        if (m_pFrameFormat->GetOtherTextBoxFormat()->GetOwnerShape()->Which() 
== RES_DRAWFRMFMT)
+        if (m_pFrameFormat->GetOtherTextBoxFormats()->GetOwnerShape()->Which() 
== RES_DRAWFRMFMT)
         {
 
             if (pSdrObject)
@@ -163,7 +163,7 @@ void SwUndoFlyBase::InsFly(::sw::UndoRedoContext & 
rContext, bool bShowSelFrame)
         }
         if (m_pFrameFormat->Which() == RES_FLYFRMFMT)
         {
-            SwFrameFormat* pShapeFormat = 
m_pFrameFormat->GetOtherTextBoxFormat()->GetOwnerShape();
+            SwFrameFormat* pShapeFormat = 
m_pFrameFormat->GetOtherTextBoxFormats()->GetOwnerShape();
             pShapeFormat->SetFormatAttr(m_pFrameFormat->GetContent());
         }
     }
@@ -207,9 +207,9 @@ void SwUndoFlyBase::DelFly( SwDoc* pDoc )
     m_bDelFormat = true;                 // delete Format in DTOR
     m_pFrameFormat->DelFrames();                 // destroy Frames
 
-    if (m_pFrameFormat->GetOtherTextBoxFormat())
+    if (m_pFrameFormat->GetOtherTextBoxFormats())
     {   // tdf#108867 clear that pointer
-        
m_pFrameFormat->GetOtherTextBoxFormat()->GetOwnerShape()->SetOtherTextBoxFormat(nullptr);
+        
m_pFrameFormat->GetOtherTextBoxFormats()->GetOwnerShape()->SetOtherTextBoxFormats(nullptr);
     }
 
     // all Uno objects should now log themselves off
diff --git a/sw/source/core/undo/undraw.cxx b/sw/source/core/undo/undraw.cxx
index 94146fef2a22..f316858c2bfd 100644
--- a/sw/source/core/undo/undraw.cxx
+++ b/sw/source/core/undo/undraw.cxx
@@ -199,7 +199,7 @@ void SwUndoDrawGroup::UndoImpl(::sw::UndoRedoContext &)
 
     // This will store the textboxes what were owned by this group
     std::vector<std::pair<SdrObject*, SwFrameFormat*>> vTextBoxes;
-    if (auto pOldTextBoxNode = pFormat->GetOtherTextBoxFormat())
+    if (auto pOldTextBoxNode = pFormat->GetOtherTextBoxFormats())
     {
         if (auto pChildren = pObj->getChildrenOfSdrObject())
         {
@@ -240,10 +240,10 @@ void SwUndoDrawGroup::UndoImpl(::sw::UndoRedoContext &)
         {
             if (rElem.first == pObj)
             {
-                auto pNewTextBoxNode = new SwTextBoxNode(rSave.pFormat);
-                rSave.pFormat->SetOtherTextBoxFormat(pNewTextBoxNode);
+                auto pNewTextBoxNode = 
std::make_shared<SwTextBoxNode>(SwTextBoxNode(rSave.pFormat));
+                rSave.pFormat->SetOtherTextBoxFormats(pNewTextBoxNode);
                 pNewTextBoxNode->AddTextBox(rElem.first, rElem.second);
-                rElem.second->SetOtherTextBoxFormat(pNewTextBoxNode);
+                rElem.second->SetOtherTextBoxFormats(pNewTextBoxNode);
                 break;
             }
         }
@@ -278,7 +278,7 @@ void SwUndoDrawGroup::RedoImpl(::sw::UndoRedoContext &)
         SwDrawContact *pContact = 
static_cast<SwDrawContact*>(GetUserCall(pObj));
 
         // Save the textboxes
-        if (auto pOldTextBoxNode = rSave.pFormat->GetOtherTextBoxFormat())
+        if (auto pOldTextBoxNode = rSave.pFormat->GetOtherTextBoxFormats())
         {
             if (auto pTextBox = pOldTextBoxNode->GetTextBox(pObj))
                 vTextBoxes.push_back(std::pair(pObj, pTextBox));
@@ -310,13 +310,13 @@ void SwUndoDrawGroup::RedoImpl(::sw::UndoRedoContext &)
     // Restore the textboxes
     if (vTextBoxes.size())
     {
-        auto pNewTextBoxNode = new SwTextBoxNode(m_pObjArray[0].pFormat);
+        auto pNewTextBoxNode = 
std::make_shared<SwTextBoxNode>(SwTextBoxNode(m_pObjArray[0].pFormat));
         for (auto& rElem : vTextBoxes)
         {
             pNewTextBoxNode->AddTextBox(rElem.first, rElem.second);
-            rElem.second->SetOtherTextBoxFormat(pNewTextBoxNode);
+            rElem.second->SetOtherTextBoxFormats(pNewTextBoxNode);
         }
-        m_pObjArray[0].pFormat->SetOtherTextBoxFormat(pNewTextBoxNode);
+        m_pObjArray[0].pFormat->SetOtherTextBoxFormats(pNewTextBoxNode);
     }
 
     // #i45952# - notify that position attributes are already set
@@ -401,7 +401,7 @@ void SwUndoDrawUnGroup::UndoImpl(::sw::UndoRedoContext & 
rContext)
         ::lcl_SaveAnchor( rSave.pFormat, rSave.nNodeIdx );
 
         // copy the textboxes for later use to this vector
-        if (auto pTxBxNd = rSave.pFormat->GetOtherTextBoxFormat())
+        if (auto pTxBxNd = rSave.pFormat->GetOtherTextBoxFormats())
         {
             if (auto pGroupObj = m_pObjArray[0].pObj)
             {
@@ -436,13 +436,13 @@ void SwUndoDrawUnGroup::UndoImpl(::sw::UndoRedoContext & 
rContext)
     // Restore the vector content for the new formats
     if (vTextBoxes.size())
     {
-        auto pNewTxBxNd = new SwTextBoxNode(m_pObjArray[0].pFormat);
+        auto pNewTxBxNd = std::make_shared<SwTextBoxNode>( 
SwTextBoxNode(m_pObjArray[0].pFormat));
         for (auto& rElem : vTextBoxes)
         {
             pNewTxBxNd->AddTextBox(rElem.first, rElem.second);
-            rElem.second->SetOtherTextBoxFormat(pNewTxBxNd);
+            rElem.second->SetOtherTextBoxFormats(pNewTxBxNd);
         }
-        m_pObjArray[0].pFormat->SetOtherTextBoxFormat(pNewTxBxNd);
+        m_pObjArray[0].pFormat->SetOtherTextBoxFormats(pNewTxBxNd);
     }
 
 
@@ -466,7 +466,7 @@ void SwUndoDrawUnGroup::RedoImpl(::sw::UndoRedoContext &)
 
     // Store the textboxes in this vector for later use.
     std::vector<std::pair<SdrObject*, SwFrameFormat*>> vTextBoxes;
-    if (auto pTextBoxNode = pFormat->GetOtherTextBoxFormat())
+    if (auto pTextBoxNode = pFormat->GetOtherTextBoxFormats())
     {
         auto pMasterObj = m_pObjArray[0].pObj;
 
@@ -498,10 +498,10 @@ void SwUndoDrawUnGroup::RedoImpl(::sw::UndoRedoContext &)
         {
             if (pElem.first == rSave.pObj)
             {
-                auto pTmpTxBxNd = new SwTextBoxNode(rSave.pFormat);
+                auto pTmpTxBxNd = 
std::make_shared<SwTextBoxNode>(SwTextBoxNode(rSave.pFormat));
                 pTmpTxBxNd->AddTextBox(rSave.pObj, pElem.second);
-                pFormat->SetOtherTextBoxFormat(pTmpTxBxNd);
-                pElem.second->SetOtherTextBoxFormat(pTmpTxBxNd);
+                pFormat->SetOtherTextBoxFormats(pTmpTxBxNd);
+                pElem.second->SetOtherTextBoxFormats(pTmpTxBxNd);
                 break;
             }
         }

Reply via email to