tdf#108867 sw: fix dangling text box frame format pointers in Undo
If the text box is removed, the SwFrameFormat of the drawing shape still
retains a pointer to the frame SwFrameFormat, and the latter is owned by
the SwUndoFlyBase. This is pretty bad, so try to clear & reset the
connection between them in SwUndoFlyBase::InsFly() and DelFly().
Hopefully nothing will actually delete the drawing shape SwFrameFormat
while the Undo object is alive.
Note that when the SwUndoInsLayFormat is created when the text box is
added, the GetOtherTextBoxFormat() returns null as it's set later,
that's why the constructor can't do anything.
Change-Id: Iae562b6f8f272e47b2b5cf8ee80778db15d29ce0
diff --git a/sw/inc/frmfmt.hxx b/sw/inc/frmfmt.hxx
index 2dd3c81..6c2de6c 100644
--- a/sw/inc/frmfmt.hxx
+++ b/sw/inc/frmfmt.hxx
@@ -61,6 +61,7 @@ class SW_DLLPUBLIC SwFrameFormat: public SwFormat
friend class ::sw::DocumentLayoutManager; ///< Is allowed to call protected CTor.
friend class SwFrameFormats; ///< Is allowed to update the list backref.
friend class SwTextBoxHelper;
friend class SwUndoFlyBase; ///< calls SetOtherTextBoxFormat
css::uno::WeakReference<css::uno::XInterface> m_wXObject;
diff --git a/sw/source/core/undo/undobj1.cxx b/sw/source/core/undo/undobj1.cxx
index d35f773..8011e77 100644
--- a/sw/source/core/undo/undobj1.cxx
+++ b/sw/source/core/undo/undobj1.cxx
@@ -52,7 +52,13 @@ SwUndoFlyBase::SwUndoFlyBase( SwFrameFormat* pFormat, SwUndoId nUndoId )
SwUndoFlyBase::~SwUndoFlyBase()
{
if( bDelFormat ) // delete during an Undo?
{
if (pFrameFormat->GetOtherTextBoxFormat())
{ // clear that before delete
pFrameFormat->SetOtherTextBoxFormat(nullptr);
}
delete pFrameFormat;
}
}
void SwUndoFlyBase::InsFly(::sw::UndoRedoContext & rContext, bool bShowSelFrame)
@@ -107,6 +113,13 @@ void SwUndoFlyBase::InsFly(::sw::UndoRedoContext & rContext, bool bShowSelFrame)
pCNd->GetTextNode()->InsertItem(aFormat, nCntPos, nCntPos, SetAttrMode::NOHINTEXPAND);
}
if (pFrameFormat->GetOtherTextBoxFormat())
{
// recklessly assume that this thing will live longer than the
// SwUndoFlyBase - not sure what could be done if that isn't the case...
pFrameFormat->GetOtherTextBoxFormat()->SetOtherTextBoxFormat(pFrameFormat);
}
pFrameFormat->MakeFrames();
if( bShowSelFrame )
@@ -146,6 +159,11 @@ void SwUndoFlyBase::DelFly( SwDoc* pDoc )
bDelFormat = true; // delete Format in DTOR
pFrameFormat->DelFrames(); // destroy Frames
if (pFrameFormat->GetOtherTextBoxFormat())
{ // tdf#108867 clear that pointer
pFrameFormat->GetOtherTextBoxFormat()->SetOtherTextBoxFormat(nullptr);
}
// all Uno objects should now log themselves off
{
SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFrameFormat );