diff options
author | Michael Stahl <mstahl@redhat.com> | 2017-04-28 18:54:27 +0200 |
---|---|---|
committer | Michael Stahl <mstahl@redhat.com> | 2017-04-28 19:01:51 +0200 |
commit | 32403675bf9d2d0380956f9a82da71593edbb53c (patch) | |
tree | c6204f6cfe59b23f9814bb4691acf865a56f45f8 /sw | |
parent | 5a4d03131ffe557fed9ab3c8e31a005188c7ea5c (diff) |
tdf#107494 sw: fix crash in SwCallMouseEvent when deleting header
The problem is that SwCallMouseEvent::PTR.pFormat is not cleared
when the format is destroyed; instead SwDoc::CallEvent() checks via
SwFrameFormats::Contains() that the format is still alive,
which uses dynamic_cast on the deleted format.
(presumably regression from 0f98299f7aa44bbb55c1bfeddca7799f727d14b0)
Change-Id: I0d155c162d75b5687b58329a2a862ad57a4eb72e
Diffstat (limited to 'sw')
-rw-r--r-- | sw/inc/swevent.hxx | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/sw/inc/swevent.hxx b/sw/inc/swevent.hxx index ed63b5f80b39..3eb0fb8bfa23 100644 --- a/sw/inc/swevent.hxx +++ b/sw/inc/swevent.hxx @@ -22,6 +22,8 @@ #include <tools/solar.h> #include <sfx2/sfx.hrc> +#include <calbck.hxx> +#include <frmfmt.hxx> #define SW_EVENT_OBJECT_SELECT ( EVENT_APP_START + 0 ) #define SW_EVENT_START_INS_GLOSSARY ( EVENT_APP_START + 1 ) @@ -62,6 +64,7 @@ enum SwCallEventObjectType // Structure for the exchange between UI/CORE. struct SwCallMouseEvent + : public SwClient { SwCallEventObjectType eType; union @@ -84,14 +87,21 @@ struct SwCallMouseEvent : eType( EVENT_OBJECT_NONE ) { PTR.pFormat = nullptr; PTR.IMAP.pIMapObj = nullptr; } + SwCallMouseEvent(SwCallMouseEvent const& rOther) + : SwClient(rOther.GetRegisteredInNonConst()) + , eType(rOther.eType) + { + memcpy(&PTR, &rOther.PTR, sizeof(PTR)); + } + void Set( SwCallEventObjectType eTyp, const SwFrameFormat* pFormat ) - { eType = eTyp; PTR.pFormat = pFormat; PTR.IMAP.pIMapObj = nullptr; } + { Clear(); eType = eTyp; PTR.pFormat = pFormat; PTR.IMAP.pIMapObj = nullptr; assert(pFormat); const_cast<SwFrameFormat*>(pFormat)->Add(this); } void Set( const SwFrameFormat* pFormat, const IMapObject* pIMapObj ) - { eType = EVENT_OBJECT_IMAGEMAP; PTR.pFormat = pFormat; PTR.IMAP.pIMapObj = pIMapObj; } + { Clear(); eType = EVENT_OBJECT_IMAGEMAP; PTR.pFormat = pFormat; PTR.IMAP.pIMapObj = pIMapObj; assert(pFormat); const_cast<SwFrameFormat*>(pFormat)->Add(this); } void Set( const SwFormatINetFormat* pINetAttr ) - { eType = EVENT_OBJECT_INETATTR; PTR.pINetAttr = pINetAttr; PTR.IMAP.pIMapObj = nullptr; } + { Clear(); eType = EVENT_OBJECT_INETATTR; PTR.pINetAttr = pINetAttr; PTR.IMAP.pIMapObj = nullptr; } bool operator==( const SwCallMouseEvent& rEvent ) const { @@ -103,9 +113,30 @@ struct SwCallMouseEvent { return !( *this == rEvent ); } void Clear() - { eType = EVENT_OBJECT_NONE; PTR.pFormat = nullptr; PTR.IMAP.pIMapObj = nullptr; } + { + if (EVENT_OBJECT_IMAGE == eType || EVENT_OBJECT_URLITEM == eType || EVENT_OBJECT_IMAGEMAP == eType) + { + // note: pFormat is not necessarily the same as + // GetRegisteredIn() here; see ~SwFormat() + assert(PTR.pFormat); + GetRegisteredInNonConst()->Remove(this); + } + eType = EVENT_OBJECT_NONE; PTR.pFormat = nullptr; PTR.IMAP.pIMapObj = nullptr; + } bool HasEvent() const { return EVENT_OBJECT_NONE != eType; } + + virtual void Modify(SfxPoolItem const*const pOldValue, SfxPoolItem const*const pNewValue) override + { + assert(EVENT_OBJECT_IMAGE == eType || EVENT_OBJECT_URLITEM == eType || EVENT_OBJECT_IMAGEMAP == eType); + SwClient::Modify(pOldValue, pNewValue); + if (!GetRegisteredIn() || + (RES_FMT_CHG == pOldValue->Which() + && static_cast<SwFormatChg const*>(pOldValue)->pChangedFormat == PTR.pFormat)) + { + Clear(); + } + } }; #endif |