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 )
 {
 }

Reply via email to