sw/inc/calbck.hxx | 170 ++++++++++----------------------------- sw/inc/fmthdft.hxx | 18 +--- sw/inc/ring.hxx | 1 sw/source/core/attr/calbck.cxx | 120 +++++++++++++++++++-------- sw/source/core/doc/docdesc.cxx | 2 sw/source/core/layout/atrfrm.cxx | 18 +--- 6 files changed, 147 insertions(+), 182 deletions(-)
New commits: commit 9d69c20f8bcd9df4051e4f287c467efbdeae7eed Author: Stephan Bergmann <stephan.bergm...@allotropia.de> AuthorDate: Sun Dec 29 10:43:30 2024 +0100 Commit: Stephan Bergmann <stephan.bergm...@allotropia.de> CommitDate: Sun Dec 29 12:54:02 2024 +0100 Revert "stronger typing for SwClient::GetRegisteredIn" This reverts commit 687080c2d284f111fdd1fde1ab768ef924c04aa9, as it caused e.g. CppunitTest_sw_docbookexport to fail with > sw/inc/calbck.hxx:428:18: runtime error: downcast of address 0x7ba8053a9db8 which does not point to an object of type 'SwClient' (aka 'ClientBase<SwModify>') > 0x7ba8053a9da0: note: object is base class subobject at offset 24 within object of type 'SwFormatHeader' > 00 00 00 00 d0 8b c9 ae 47 7b 00 00 01 00 00 00 66 00 48 01 40 6c 00 00 88 be be be 50 8c c9 ae > ^ ~~~~~~~~~~~ > vptr for 'sw::ClientBase<SwFrameFormat>' base class of 'SwFormatHeader' > #0 in SwIterator<sw::ClientBase<SwModify>, SwModify, (sw::IteratorMode)0>::First() at sw/inc/calbck.hxx:428:18 > #1 in SwModify::CallSwClientNotify(SfxHint const&) const at sw/source/core/attr/calbck.cxx:237:35 > #2 in sw::BroadcastingModify::CallSwClientNotify(SfxHint const&) const at sw/source/core/attr/calbck.cxx:259:15 > #3 in SwModify::SwClientNotify(SwModify const&, SfxHint const&) at sw/source/core/attr/calbck.cxx:229:5 > #4 in SwFormat::SwClientNotify(SwModify const&, SfxHint const&) at sw/source/core/attr/format.cxx:309:19 > #5 in SwFrameFormat::SwClientNotify(SwModify const&, SfxHint const&) at sw/source/core/layout/atrfrm.cxx:2849:15 > #6 in sw::ClientNotifyAttrChg(SwModify&, SwAttrSet const&, SwAttrSet&, SwAttrSet&) at sw/source/core/attr/calbck.cxx:268:13 > #7 in SwFormat::SetFormatAttr(SfxItemSet const&) at sw/source/core/attr/format.cxx:604:13 > #8 in FillHdFt(SwFrameFormat*, SfxItemSet const&) at sw/source/uibase/utlui/uitool.cxx:239:14 > #9 in ItemSetToPageDesc(SfxItemSet const&, SwPageDesc&) at sw/source/uibase/utlui/uitool.cxx:340:13 > #10 in SwDocStyleSheet::SetItemSet(SfxItemSet const&, bool, bool) at sw/source/uibase/app/docstyle.cxx:1894:13 > #11 in SwXPageStyle::SetPropertyValues_Impl(com::sun::star::uno::Sequence<rtl::OUString> const&, com::sun::star::uno::Sequence<com::sun::star::uno::Any> const&) at sw/source/core/unocore/unostyle.cxx:3157:33 > #12 in SwXPageStyle::setPropertyValue(rtl::OUString const&, com::sun::star::uno::Any const&) at sw/source/core/unocore/unostyle.cxx:3453:5 > #13 in writerfilter::dmapper::DomainMapper_Impl::PushPageHeaderFooter(writerfilter::dmapper::PagePartType, writerfilter::dmapper::PageType) at sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx:3910:25 > #14 in writerfilter::dmapper::DomainMapper_Impl::substream(unsigned int, tools::SvRef<writerfilter::Reference<writerfilter::Stream>> const&) at sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx:10049:13 > #15 in writerfilter::dmapper::DomainMapper::lcl_substream(unsigned int, tools::SvRef<writerfilter::Reference<writerfilter::Stream>> const&) at sw/source/writerfilter/dmapper/DomainMapper.cxx:4746:14 > #16 in writerfilter::LoggedStream::substream(unsigned int, tools::SvRef<writerfilter::Reference<writerfilter::Stream>> const&) at sw/source/writerfilter/dmapper/LoggedResources.cxx:272:5 > #17 in writerfilter::ooxml::OOXMLDocumentImpl::resolveFastSubStreamWithId(writerfilter::Stream&, tools::SvRef<writerfilter::Reference<writerfilter::Stream>> const&, unsigned int) at sw/source/writerfilter/ooxml/OOXMLDocumentImpl.cxx:127:13 > #18 in writerfilter::ooxml::OOXMLDocumentImpl::resolveHeader(writerfilter::Stream&, int, rtl::OUString const&) at sw/source/writerfilter/ooxml/OOXMLDocumentImpl.cxx:384:10 > #19 in writerfilter::ooxml::OOXMLFastContextHandler::resolveHeader(int, rtl::OUString const&) at sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx:895:35 > #20 in writerfilter::ooxml::OOXMLHeaderHandler::finalize() at sw/source/writerfilter/ooxml/Handler.cxx:214:20 > #21 in writerfilter::ooxml::OOXMLFastContextHandlerProperties::handleHdrFtr() at sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx:1117:28 > #22 in writerfilter::ooxml::OOXMLFactory_wml::endAction(writerfilter::ooxml::OOXMLFastContextHandler*) at workdir/CustomTarget/sw/source/writerfilter/ooxml/OOXMLFactory_wml.cxx:7530:26 > #23 in writerfilter::ooxml::OOXMLFactory::endAction(writerfilter::ooxml::OOXMLFastContextHandler*) at sw/source/writerfilter/ooxml/OOXMLFactory.cxx:157:19 > #24 in writerfilter::ooxml::OOXMLFastContextHandler::endAction() at sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx:320:5 > #25 in writerfilter::ooxml::OOXMLFastContextHandlerProperties::lcl_endFastElement(int) at sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx:1038:9 > #26 in writerfilter::ooxml::OOXMLFastContextHandler::endFastElement(int) at sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx:227:9 > #27 in (anonymous namespace)::Entity::endElement() at sax/source/fastparser/fastparser.cxx:515:27 > #28 in sax_fastparser::FastSaxParserImpl::callbackEndElement() at sax/source/fastparser/fastparser.cxx:1338:17 > #29 in (anonymous namespace)::call_callbackEndElement(void*, unsigned char const*, unsigned char const*, unsigned char const*) at sax/source/fastparser/fastparser.cxx:339:18 > #30 in xmlParseTryOrFinish at workdir/UnpackedTarball/libxml2/parser.c:11254:8 > #31 in xmlParseChunk at workdir/UnpackedTarball/libxml2/parser.c:11636:5 > #32 in sax_fastparser::FastSaxParserImpl::parse() at sax/source/fastparser/fastparser.cxx:1117:25 > #33 in sax_fastparser::FastSaxParserImpl::parseStream(com::sun::star::xml::sax::InputSource const&) at sax/source/fastparser/fastparser.cxx:896:9 > #34 in sax_fastparser::FastSaxParser::parseStream(com::sun::star::xml::sax::InputSource const&) at sax/source/fastparser/fastparser.cxx:1477:13 > #35 in writerfilter::ooxml::OOXMLDocumentImpl::resolve(writerfilter::Stream&) at sw/source/writerfilter/ooxml/OOXMLDocumentImpl.cxx:514:18 > #36 in (anonymous namespace)::WriterFilter::filter(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at sw/source/writerfilter/filter/WriterFilter.cxx:210:24 > #37 in SfxObjectShell::ImportFrom(SfxMedium&, com::sun::star::uno::Reference<com::sun::star::text::XTextRange> const&) at sfx2/source/doc/objstor.cxx:2719:34 > #38 in SfxObjectShell::DoLoad(SfxMedium*) at sfx2/source/doc/objstor.cxx:767:23 > #39 in SfxBaseModel::load(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at sfx2/source/doc/sfxbasemodel.cxx:1991:36 > #40 in (anonymous namespace)::SfxFrameLoader_Impl::load(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&, com::sun::star::uno::Reference<com::sun::star::frame::XFrame> const&) at sfx2/source/view/frmload.cxx:725:28 > #41 in framework::LoadEnv::impl_loadContent() at framework/source/loadenv/loadenv.cxx:1180:37 > #42 in framework::LoadEnv::start() at framework/source/loadenv/loadenv.cxx:415:20 > #43 in framework::LoadEnv::startLoading(rtl::OUString const&, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&, com::sun::star::uno::Reference<com::sun::star::frame::XFrame> const&, rtl::OUString const&, int, LoadEnvFeatures) at framework/source/loadenv/loadenv.cxx:311:5 > #44 in framework::LoadEnv::loadComponentFromURL(com::sun::star::uno::Reference<com::sun::star::frame::XComponentLoader> const&, com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext> const&, rtl::OUString const&, rtl::OUString const&, int, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at framework/source/loadenv/loadenv.cxx:167:14 > #45 in framework::Desktop::loadComponentFromURL(rtl::OUString const&, rtl::OUString const&, int, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at framework/source/services/desktop.cxx:592:16 > #46 in non-virtual thunk to framework::Desktop::loadComponentFromURL(rtl::OUString const&, rtl::OUString const&, int, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at framework/source/services/desktop.cxx > #47 in unotest::MacrosTest::loadFromDesktop(rtl::OUString const&, rtl::OUString const&, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at unotest/source/cpp/macros_test.cxx:72:62 > #48 in UnoApiTest::loadWithParams(rtl::OUString const&, com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&) at test/source/unoapi_test.cxx:126:19 > #49 in UnoApiTest::loadFromURL(rtl::OUString const&, char const*) at test/source/unoapi_test.cxx:108:5 > #50 in SwModelTestBase::loadURL(rtl::OUString const&, char const*) at sw/qa/unit/swmodeltestbase.cxx:384:5 > #51 in SwModelTestBase::createSwDoc(char const*, char const*) at sw/qa/unit/swmodeltestbase.cxx:433:9 > #52 in (anonymous namespace)::testtdf91095::TestBody() at sw/qa/extras/docbookexport/docbookexport.cxx:35:5 Change-Id: I1e6d6888c8b311988e627845107148c7970fbaab Reviewed-on: https://gerrit.libreoffice.org/c/core/+/179502 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <stephan.bergm...@allotropia.de> diff --git a/sw/inc/calbck.hxx b/sw/inc/calbck.hxx index 451be70017e4..58a336bbc92b 100644 --- a/sw/inc/calbck.hxx +++ b/sw/inc/calbck.hxx @@ -24,7 +24,6 @@ #include <svl/hint.hxx> #include <svl/broadcast.hxx> #include <svl/poolitem.hxx> -#include <tools/debug.hxx> #include "swdllapi.h" #include "ring.hxx" #include <type_traits> @@ -65,18 +64,10 @@ class SwFindNearestNode; This is still subject to refactoring. */ - namespace sw { class ClientIteratorBase; class ListenerEntry; - enum class IteratorMode { Exact, UnwrapMulti }; -} - -template<typename TElementType, typename TSource, sw::IteratorMode eMode> class SwIterator; - -namespace sw -{ void ClientNotifyAttrChg(SwModify& rModify, const SwAttrSet& aSet, SwAttrSet& aOld, SwAttrSet& aNew); struct SAL_DLLPUBLIC_RTTI LegacyModifyHint final: SfxHint { @@ -135,58 +126,52 @@ namespace sw virtual const SwRowFrame* DynCastRowFrame() const { return nullptr; } virtual const SwTable* DynCastTable() const { return nullptr; } }; + enum class IteratorMode { Exact, UnwrapMulti }; +} - template<typename T> - class SW_DLLPUBLIC ClientBase : public ::sw::WriterListener - { - // avoids making the details of the linked list and the callback method public - friend class ::SwModify; - friend class sw::ClientIteratorBase; - friend class sw::ListenerEntry; - template<typename E, typename S, sw::IteratorMode> friend class ::SwIterator; - - T *m_pRegisteredIn; ///< event source +// SwClient +class SW_DLLPUBLIC SwClient : public ::sw::WriterListener +{ + // avoids making the details of the linked list and the callback method public + friend class SwModify; + friend class sw::ClientIteratorBase; + friend class sw::ListenerEntry; + template<typename E, typename S, sw::IteratorMode> friend class SwIterator; - protected: - // single argument ctors shall be explicit. - inline explicit ClientBase( T* pToRegisterIn ) - : m_pRegisteredIn( nullptr ) - { - if(pToRegisterIn) - pToRegisterIn->Add(*this); - } + SwModify *m_pRegisteredIn; ///< event source - // write access to pRegisteredIn shall be granted only to the object itself (protected access) - T* GetRegisteredInNonConst() const { return m_pRegisteredIn; } +protected: + // single argument ctors shall be explicit. + inline explicit SwClient( SwModify* pToRegisterIn ); - // when overriding this, you MUST call SwClient::SwClientNotify() in the override! - virtual void SwClientNotify(const SwModify&, const SfxHint& rHint) override; + // write access to pRegisteredIn shall be granted only to the object itself (protected access) + SwModify* GetRegisteredInNonConst() const { return m_pRegisteredIn; } - public: - ClientBase() : m_pRegisteredIn(nullptr) {} - ClientBase(ClientBase&&) noexcept; - virtual ~ClientBase() override; + // when overriding this, you MUST call SwClient::SwClientNotify() in the override! + virtual void SwClientNotify(const SwModify&, const SfxHint& rHint) override; +public: + SwClient() : m_pRegisteredIn(nullptr) {} + SwClient(SwClient&&) noexcept; + virtual ~SwClient() override; - // in case an SwModify object is destroyed that itself is registered in another SwModify, - // its SwClient objects can decide to get registered to the latter instead by calling this method - std::optional<sw::ModifyChangedHint> CheckRegistration( const SfxPoolItem* pOldValue ); - // SwFormat wants to die different than the rest: It wants to reparent every client to its parent - // and then send a SwFormatChg hint. - void CheckRegistrationFormat(SwFormat& rOld); - const T* GetRegisteredIn() const { return m_pRegisteredIn; } - T* GetRegisteredIn() { return m_pRegisteredIn; } - void EndListeningAll(); - void StartListeningToSameModifyAs(const ClientBase&); + // in case an SwModify object is destroyed that itself is registered in another SwModify, + // its SwClient objects can decide to get registered to the latter instead by calling this method + std::optional<sw::ModifyChangedHint> CheckRegistration( const SfxPoolItem* pOldValue ); + // SwFormat wants to die different than the rest: It wants to reparent every client to its parent + // and then send a SwFormatChg hint. + void CheckRegistrationFormat(SwFormat& rOld); + const SwModify* GetRegisteredIn() const { return m_pRegisteredIn; } + SwModify* GetRegisteredIn() { return m_pRegisteredIn; } + void EndListeningAll(); + void StartListeningToSameModifyAs(const SwClient&); - // get information about attribute - virtual bool GetInfo( SwFindNearestNode& ) const { return true; } - }; -} -typedef sw::ClientBase<SwModify> SwClient; + // get information about attribute + virtual bool GetInfo( SwFindNearestNode& ) const { return true; } +}; // SwModify @@ -196,13 +181,12 @@ class SW_DLLPUBLIC SwModify: public SwClient { friend class sw::ClientIteratorBase; friend void sw::ClientNotifyAttrChg(SwModify&, const SwAttrSet&, SwAttrSet&, SwAttrSet&); - template<typename E, typename S, sw::IteratorMode> friend class ::SwIterator; + template<typename E, typename S, sw::IteratorMode> friend class SwIterator; sw::WriterListener* m_pWriterListeners; // the start of the linked list of clients bool m_bModifyLocked; // don't broadcast changes now SwModify(SwModify const &) = delete; SwModify &operator =(const SwModify&) = delete; - void EnsureBroadcasting(); protected: virtual void SwClientNotify(const SwModify&, const SfxHint& rHint) override; public: @@ -215,8 +199,8 @@ public: virtual ~SwModify() override; - template<typename T> void Add(sw::ClientBase<T>& rDepend); - template<typename T> void Remove(sw::ClientBase<T>& rDepend); + void Add(SwClient& rDepend); + void Remove(SwClient& rDepend); bool HasWriterListeners() const { return m_pWriterListeners; } bool HasOnlyOneListener() const { return m_pWriterListeners && m_pWriterListeners->IsLast(); } @@ -228,6 +212,7 @@ public: bool IsModifyLocked() const { return m_bModifyLocked; } }; +template<typename TElementType, typename TSource, sw::IteratorMode eMode> class SwIterator; namespace sw { @@ -291,7 +276,8 @@ namespace sw }; class ClientIteratorBase : public sw::Ring< ::sw::ClientIteratorBase > { - friend class ::SwModify; + friend void SwModify::Remove(SwClient&); + friend void SwModify::Add(SwClient&); protected: const SwModify& m_rRoot; // the current object in an iteration @@ -435,77 +421,11 @@ public: using sw::ClientIteratorBase::IsChanged; }; -template<typename T> -void SwModify::Add(sw::ClientBase<T>& rDepend) +SwClient::SwClient( SwModify* pToRegisterIn ) + : m_pRegisteredIn( nullptr ) { - DBG_TESTSOLARMUTEX(); -#ifdef DBG_UTIL - EnsureBroadcasting(); - assert(dynamic_cast<T*>(this)); -#endif - - if (rDepend.GetRegisteredIn() == this) - return; - - // deregister new client in case it is already registered elsewhere - if( rDepend.GetRegisteredIn() != nullptr ) - rDepend.m_pRegisteredIn->Remove(rDepend); - - if( !m_pWriterListeners ) - { - // first client added - m_pWriterListeners = &rDepend; - m_pWriterListeners->m_pLeft = nullptr; - m_pWriterListeners->m_pRight = nullptr; - } - else - { - // append client - rDepend.m_pRight = m_pWriterListeners->m_pRight; - m_pWriterListeners->m_pRight = &rDepend; - rDepend.m_pLeft = m_pWriterListeners; - if( rDepend.m_pRight ) - rDepend.m_pRight->m_pLeft = &rDepend; - } - - // connect client to me - rDepend.m_pRegisteredIn = static_cast<T*>(this); + if(pToRegisterIn) + pToRegisterIn->Add(*this); } -template<typename T> -void SwModify::Remove(sw::ClientBase<T>& rDepend) -{ - DBG_TESTSOLARMUTEX(); - assert(rDepend.m_pRegisteredIn == this); - - // SwClient is my listener - // remove it from my list - ::sw::WriterListener* pR = rDepend.m_pRight; - ::sw::WriterListener* pL = rDepend.m_pLeft; - if( m_pWriterListeners == &rDepend ) - m_pWriterListeners = pL ? pL : pR; - - if( pL ) - pL->m_pRight = pR; - if( pR ) - pR->m_pLeft = pL; - - // update ClientIterators - if(sw::ClientIteratorBase::s_pClientIters) - { - for(auto& rIter : sw::ClientIteratorBase::s_pClientIters->GetRingContainer()) - { - if (&rIter.m_rRoot == this && - (rIter.m_pCurrent == &rDepend || rIter.m_pPosition == &rDepend)) - { - // if object being removed is the current or next object in an - // iterator, advance this iterator - rIter.m_pPosition = pR; - } - } - } - rDepend.m_pLeft = nullptr; - rDepend.m_pRight = nullptr; - rDepend.m_pRegisteredIn = nullptr; -} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/inc/fmthdft.hxx b/sw/inc/fmthdft.hxx index 2a0c48eb3f32..731e46b490b2 100644 --- a/sw/inc/fmthdft.hxx +++ b/sw/inc/fmthdft.hxx @@ -25,16 +25,12 @@ #include "calbck.hxx" #include "frmfmt.hxx" -namespace sw { - typedef ClientBase<::SwFrameFormat> FrameFormatClient; -} - class IntlWrapper; /** Header, for PageFormats Client of FrameFormat describing the header. */ -class SW_DLLPUBLIC SwFormatHeader final : public SfxPoolItem, public sw::FrameFormatClient +class SW_DLLPUBLIC SwFormatHeader final : public SfxPoolItem, public SwClient { bool m_bActive; ///< Only for controlling (creation of content). @@ -55,10 +51,10 @@ public: OUString &rText, const IntlWrapper& rIntl ) const override; - const SwFrameFormat *GetHeaderFormat() const { return GetRegisteredIn(); } - SwFrameFormat *GetHeaderFormat() { return GetRegisteredIn(); } + const SwFrameFormat *GetHeaderFormat() const { return static_cast<const SwFrameFormat*>(GetRegisteredIn()); } + SwFrameFormat *GetHeaderFormat() { return static_cast<SwFrameFormat*>(GetRegisteredIn()); } - void RegisterToFormat( SwFrameFormat& rFormat ); + void RegisterToFormat( SwFormat& rFormat ); bool IsActive() const { return m_bActive; } void dumpAsXml(xmlTextWriterPtr pWriter) const override; }; @@ -66,7 +62,7 @@ public: /**Footer, for pageformats Client of FrameFormat describing the footer */ -class SW_DLLPUBLIC SwFormatFooter final : public SfxPoolItem, public sw::FrameFormatClient +class SW_DLLPUBLIC SwFormatFooter final : public SfxPoolItem, public SwClient { bool m_bActive; // Only for controlling (creation of content). @@ -87,8 +83,8 @@ public: OUString &rText, const IntlWrapper& rIntl ) const override; - const SwFrameFormat *GetFooterFormat() const { return GetRegisteredIn(); } - SwFrameFormat *GetFooterFormat() { return GetRegisteredIn(); } + const SwFrameFormat *GetFooterFormat() const { return static_cast<const SwFrameFormat*>(GetRegisteredIn()); } + SwFrameFormat *GetFooterFormat() { return static_cast<SwFrameFormat*>(GetRegisteredIn()); } void RegisterToFormat( SwFormat& rFormat ); bool IsActive() const { return m_bActive; } diff --git a/sw/inc/ring.hxx b/sw/inc/ring.hxx index f9ee213fc6e8..194ed47db10b 100644 --- a/sw/inc/ring.hxx +++ b/sw/inc/ring.hxx @@ -19,7 +19,6 @@ #ifndef INCLUDED_SW_INC_RING_HXX #define INCLUDED_SW_INC_RING_HXX -#include <cassert> #include <utility> #include <sal/types.h> #include <iterator> diff --git a/sw/source/core/attr/calbck.cxx b/sw/source/core/attr/calbck.cxx index b7b552a885a4..e4a1f437cef7 100644 --- a/sw/source/core/attr/calbck.cxx +++ b/sw/source/core/attr/calbck.cxx @@ -20,7 +20,6 @@ #include <algorithm> #include <format.hxx> -#include <frmfmt.hxx> #include <hintids.hxx> #include <hints.hxx> #include <osl/diagnose.h> @@ -56,8 +55,7 @@ namespace sw sw::LegacyModifyHint::~LegacyModifyHint() {} -template<typename T> -sw::ClientBase<T>::ClientBase(sw::ClientBase<T>&& o) noexcept +SwClient::SwClient(SwClient&& o) noexcept : m_pRegisteredIn(nullptr) { if(o.m_pRegisteredIn) @@ -67,8 +65,7 @@ sw::ClientBase<T>::ClientBase(sw::ClientBase<T>&& o) noexcept } } -template<typename T> -sw::ClientBase<T>::~ClientBase() +SwClient::~SwClient() { if(GetRegisteredIn()) DBG_TESTSOLARMUTEX(); @@ -77,8 +74,7 @@ sw::ClientBase<T>::~ClientBase() m_pRegisteredIn->Remove(*this); } -template<typename T> -std::optional<sw::ModifyChangedHint> sw::ClientBase<T>::CheckRegistration( const SfxPoolItem* pOld ) +std::optional<sw::ModifyChangedHint> SwClient::CheckRegistration( const SfxPoolItem* pOld ) { DBG_TESTSOLARMUTEX(); // this method only handles notification about dying SwModify objects @@ -108,8 +104,7 @@ std::optional<sw::ModifyChangedHint> sw::ClientBase<T>::CheckRegistration( const return sw::ModifyChangedHint(pAbove); } -template<typename T> -void sw::ClientBase<T>::CheckRegistrationFormat(SwFormat& rOld) +void SwClient::CheckRegistrationFormat(SwFormat& rOld) { assert(GetRegisteredIn() == &rOld); auto pNew = rOld.DerivedFrom(); @@ -120,8 +115,7 @@ void sw::ClientBase<T>::CheckRegistrationFormat(SwFormat& rOld) SwClientNotify(rOld, aHint); } -template<typename T> -void sw::ClientBase<T>::SwClientNotify(const SwModify&, const SfxHint& rHint) +void SwClient::SwClientNotify(const SwModify&, const SfxHint& rHint) { if (rHint.GetId() != SfxHintId::SwLegacyModify) return; @@ -129,8 +123,7 @@ void sw::ClientBase<T>::SwClientNotify(const SwModify&, const SfxHint& rHint) CheckRegistration(pLegacyHint->m_pOld); }; -template<typename T> -void sw::ClientBase<T>::StartListeningToSameModifyAs(const sw::ClientBase<T>& other) +void SwClient::StartListeningToSameModifyAs(const SwClient& other) { if(other.m_pRegisteredIn) other.m_pRegisteredIn->Add(*this); @@ -138,8 +131,7 @@ void sw::ClientBase<T>::StartListeningToSameModifyAs(const sw::ClientBase<T>& ot EndListeningAll(); } -template<typename T> -void sw::ClientBase<T>::EndListeningAll() +void SwClient::EndListeningAll() { if(m_pRegisteredIn) m_pRegisteredIn->Remove(*this); @@ -175,6 +167,85 @@ bool SwModify::GetInfo( SwFindNearestNode& rInfo ) const return true; } +void SwModify::Add(SwClient& rDepend) +{ + DBG_TESTSOLARMUTEX(); +#ifdef DBG_UTIL + // You should not EVER use SwModify directly in new code: + // - Preexisting SwModifys should only ever be used via sw::BroadcastingModify. + // This includes sw::BroadcastMixin, which is the long-term target (without + // SwModify). + // - New classes should use sw::BroadcastMixin alone. + if(!dynamic_cast<sw::BroadcastingModify*>(this)) + { + auto pBT = sal::backtrace_get(20); + SAL_WARN("sw.core", "Modify that is not broadcasting used! " << sal::backtrace_to_string(pBT.get())); + } +#endif + + if (rDepend.m_pRegisteredIn == this) + return; + + // deregister new client in case it is already registered elsewhere + if( rDepend.m_pRegisteredIn != nullptr ) + rDepend.m_pRegisteredIn->Remove(rDepend); + + if( !m_pWriterListeners ) + { + // first client added + m_pWriterListeners = &rDepend; + m_pWriterListeners->m_pLeft = nullptr; + m_pWriterListeners->m_pRight = nullptr; + } + else + { + // append client + rDepend.m_pRight = m_pWriterListeners->m_pRight; + m_pWriterListeners->m_pRight = &rDepend; + rDepend.m_pLeft = m_pWriterListeners; + if( rDepend.m_pRight ) + rDepend.m_pRight->m_pLeft = &rDepend; + } + + // connect client to me + rDepend.m_pRegisteredIn = this; +} + +void SwModify::Remove(SwClient& rDepend) +{ + DBG_TESTSOLARMUTEX(); + assert(rDepend.m_pRegisteredIn == this); + + // SwClient is my listener + // remove it from my list + ::sw::WriterListener* pR = rDepend.m_pRight; + ::sw::WriterListener* pL = rDepend.m_pLeft; + if( m_pWriterListeners == &rDepend ) + m_pWriterListeners = pL ? pL : pR; + + if( pL ) + pL->m_pRight = pR; + if( pR ) + pR->m_pLeft = pL; + + // update ClientIterators + if(sw::ClientIteratorBase::s_pClientIters) + { + for(auto& rIter : sw::ClientIteratorBase::s_pClientIters->GetRingContainer()) + { + if (&rIter.m_rRoot == this && + (rIter.m_pCurrent == &rDepend || rIter.m_pPosition == &rDepend)) + { + // if object being removed is the current or next object in an + // iterator, advance this iterator + rIter.m_pPosition = pR; + } + } + } + rDepend.m_pLeft = nullptr; + rDepend.m_pRight = nullptr; + rDepend.m_pRegisteredIn = nullptr; +} sw::WriterMultiListener::WriterMultiListener(SwClient& rToTell) : m_rToTell(rToTell) @@ -238,22 +309,6 @@ void SwModify::CallSwClientNotify( const SfxHint& rHint ) const pClient->SwClientNotify( *this, rHint ); } -void SwModify::EnsureBroadcasting() -{ -#ifdef DBG_UTIL - // You should not EVER use SwModify directly in new code: - // - Preexisting SwModifys should only ever be used via sw::BroadcastingModify. - // This includes sw::BroadcastMixin, which is the long-term target (without - // SwModify). - // - New classes should use sw::BroadcastMixin alone. - if(!dynamic_cast<sw::BroadcastingModify*>(this)) - { - auto pBT = sal::backtrace_get(20); - SAL_WARN("sw.core", "Modify that is not broadcasting used! " << sal::backtrace_to_string(pBT.get())); - } -#endif -} - void sw::BroadcastingModify::CallSwClientNotify(const SfxHint& rHint) const { SwModify::CallSwClientNotify(rHint); @@ -267,7 +322,4 @@ void sw::ClientNotifyAttrChg(SwModify& rModify, const SwAttrSet& aSet, SwAttrSet const sw::LegacyModifyHint aHint(&aChgOld, &aChgNew); rModify.SwClientNotify(rModify, aHint); } - -template class sw::ClientBase<SwModify>; -template class sw::ClientBase<SwFrameFormat>; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/doc/docdesc.cxx b/sw/source/core/doc/docdesc.cxx index 04c318cdbff1..b03a3558baca 100644 --- a/sw/source/core/doc/docdesc.cxx +++ b/sw/source/core/doc/docdesc.cxx @@ -458,7 +458,7 @@ void SwDoc::ChgPageDesc( size_t i, const SwPageDesc &rChged ) rDesc.GetLeft().ResetFormatAttr(RES_FOOTER); rDesc.GetFirstLeft().ResetFormatAttr(RES_FOOTER); - auto lDelHFFormat = [this](sw::ClientBase<SwFrameFormat>* pToRemove, SwFrameFormat* pFormat) + auto lDelHFFormat = [this](SwClient* pToRemove, SwFrameFormat* pFormat) { // Code taken from lcl_DelHFFormat pFormat->Remove(*pToRemove); diff --git a/sw/source/core/layout/atrfrm.cxx b/sw/source/core/layout/atrfrm.cxx index 98f41721d89b..937b30d74e7e 100644 --- a/sw/source/core/layout/atrfrm.cxx +++ b/sw/source/core/layout/atrfrm.cxx @@ -134,10 +134,8 @@ bool GetAtPageRelOrientation(sal_Int16 & rOrientation, bool const isIgnorePrintA } } - } // namespace sw - SfxPoolItem* SwFormatLineNumber::CreateDefault() { return new SwFormatLineNumber; } static sal_Int16 lcl_IntToRelation(const uno::Any& rVal) @@ -148,7 +146,7 @@ static sal_Int16 lcl_IntToRelation(const uno::Any& rVal) return nVal; } -static void lcl_DelHFFormat( sw::FrameFormatClient *pToRemove, SwFrameFormat *pFormat ) +static void lcl_DelHFFormat( SwClient *pToRemove, SwFrameFormat *pFormat ) { //If the client is the last one who uses this format, then we have to delete //it - before this is done, we may need to delete the content-section. @@ -511,21 +509,21 @@ sal_uInt16 SwFormatFillOrder::GetValueCount() const // Partially implemented inline in hxx SwFormatHeader::SwFormatHeader( SwFrameFormat *pHeaderFormat ) : SfxPoolItem( RES_HEADER, SfxItemType::SwFormatHeaderType ), - sw::FrameFormatClient( pHeaderFormat ), + SwClient( pHeaderFormat ), m_bActive( pHeaderFormat ) { } SwFormatHeader::SwFormatHeader( const SwFormatHeader &rCpy ) : SfxPoolItem( RES_HEADER, SfxItemType::SwFormatHeaderType ), - sw::FrameFormatClient( const_cast<SwFrameFormat*>(rCpy.GetRegisteredIn()) ), + SwClient( const_cast<sw::BroadcastingModify*>(static_cast<const sw::BroadcastingModify*>(rCpy.GetRegisteredIn())) ), m_bActive( rCpy.IsActive() ) { } SwFormatHeader::SwFormatHeader( bool bOn ) : SfxPoolItem( RES_HEADER, SfxItemType::SwFormatHeaderType ), - sw::FrameFormatClient( nullptr ), + SwClient( nullptr ), m_bActive( bOn ) { } @@ -548,7 +546,7 @@ SwFormatHeader* SwFormatHeader::Clone( SfxItemPool* ) const return new SwFormatHeader( *this ); } -void SwFormatHeader::RegisterToFormat( SwFrameFormat& rFormat ) +void SwFormatHeader::RegisterToFormat( SwFormat& rFormat ) { rFormat.Add(*this); } @@ -570,21 +568,21 @@ void SwFormatHeader::dumpAsXml(xmlTextWriterPtr pWriter) const // Partially implemented inline in hxx SwFormatFooter::SwFormatFooter( SwFrameFormat *pFooterFormat ) : SfxPoolItem( RES_FOOTER, SfxItemType::SwFormatFooterType ), - sw::FrameFormatClient( pFooterFormat ), + SwClient( pFooterFormat ), m_bActive( pFooterFormat ) { } SwFormatFooter::SwFormatFooter( const SwFormatFooter &rCpy ) : SfxPoolItem( RES_FOOTER, SfxItemType::SwFormatFooterType ), - sw::FrameFormatClient( const_cast<SwFrameFormat*>(rCpy.GetRegisteredIn()) ), + SwClient( const_cast<sw::BroadcastingModify*>(static_cast<const sw::BroadcastingModify*>(rCpy.GetRegisteredIn())) ), m_bActive( rCpy.IsActive() ) { } SwFormatFooter::SwFormatFooter( bool bOn ) : SfxPoolItem( RES_FOOTER, SfxItemType::SwFormatFooterType ), - sw::FrameFormatClient( nullptr ), + SwClient( nullptr ), m_bActive( bOn ) { }