summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorAttila Bakos (NISZ) <bakos.attilakaroly@nisz.hu>2022-03-30 13:05:37 +0200
committerLászló Németh <nemeth@numbertext.org>2022-04-01 08:01:57 +0200
commit2110597ac730fa07dbbdd603fda82b182ed27c9e (patch)
tree61553a1fb72d01db0c5b260fb470fbc189bffbf1 /sw
parentd3e7dd4d4ddc88ba60be6ce5e90a1d1fcde47cca (diff)
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 <nemeth@numbertext.org> Tested-by: László Németh <nemeth@numbertext.org>
Diffstat (limited to 'sw')
-rw-r--r--sw/inc/frmfmt.hxx6
-rw-r--r--sw/inc/textboxhelper.hxx9
-rw-r--r--sw/qa/extras/ooxmlexport/data/Tdf147485.docxbin0 -> 62544 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport14.cxx6
-rw-r--r--sw/source/core/doc/DocumentLayoutManager.cxx8
-rw-r--r--sw/source/core/doc/docdraw.cxx29
-rw-r--r--sw/source/core/doc/textboxhelper.cxx92
-rw-r--r--sw/source/core/draw/dcontact.cxx2
-rw-r--r--sw/source/core/layout/atrfrm.cxx31
-rw-r--r--sw/source/core/text/porfly.cxx2
-rw-r--r--sw/source/core/undo/undobj1.cxx22
-rw-r--r--sw/source/core/undo/undraw.cxx32
12 files changed, 135 insertions, 104 deletions
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
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/Tdf147485.docx
Binary files 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;
}
}