diff options
author | Michael Stahl <mstahl@redhat.com> | 2017-04-28 18:54:27 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2017-05-02 15:05:46 +0200 |
commit | 4601cae591ee83ec83d707d7b82f5d61aa979c71 (patch) | |
tree | 7a0dffb3a4d8193adda7db0dc80ee2236e29f0f6 | |
parent | b78cabc850e0a71873714c892c46c9edb25fd364 (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
(cherry picked from commit 32403675bf9d2d0380956f9a82da71593edbb53c)
Reviewed-on: https://gerrit.libreoffice.org/37084
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
-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 567928739b1d..df4478c5de84 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 ) @@ -68,6 +70,7 @@ enum SwCallEventObjectType // Structure for the exchange between UI/CORE. struct SwCallMouseEvent + : public SwClient { SwCallEventObjectType eType; union @@ -90,14 +93,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 { @@ -109,9 +119,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 |