summaryrefslogtreecommitdiff
path: root/sw/inc
diff options
context:
space:
mode:
authorMichael Stahl <mstahl@redhat.com>2017-04-28 18:54:27 +0200
committerMichael Stahl <mstahl@redhat.com>2017-04-28 19:01:51 +0200
commit32403675bf9d2d0380956f9a82da71593edbb53c (patch)
treec6204f6cfe59b23f9814bb4691acf865a56f45f8 /sw/inc
parent5a4d03131ffe557fed9ab3c8e31a005188c7ea5c (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/inc')
-rw-r--r--sw/inc/swevent.hxx39
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