ofz#26943 detect if FormatOfJustInsertedApo was deleted

move FrameDeleteWatch for reuse in the doc filter

Change-Id: I6e53549a837968cb738b5188e8670dd3e38a9c0e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105264
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/sw/source/filter/basflt/fltshell.cxx b/sw/source/filter/basflt/fltshell.cxx
index b799dee..1fe51c4 100644
--- a/sw/source/filter/basflt/fltshell.cxx
+++ b/sw/source/filter/basflt/fltshell.cxx
@@ -1101,4 +1101,31 @@ void UpdatePageDescs(SwDoc &rDoc, size_t nInPageDescOffset)
        rDoc.ChgPageDesc(i, rDoc.GetPageDesc(i));
}

FrameDeleteWatch::FrameDeleteWatch(SwFrameFormat* pFormat)
    : m_pFormat(pFormat)
{
    if(m_pFormat)
        StartListening(pFormat->GetNotifier());
}

void FrameDeleteWatch::Notify(const SfxHint& rHint)
{
    bool bDying = false;
    if (rHint.GetId() == SfxHintId::Dying)
        bDying = true;
    else if (auto pDrawFrameFormatHint = dynamic_cast<const sw::DrawFrameFormatHint*>(&rHint))
        bDying = pDrawFrameFormatHint->m_eId == sw::DrawFrameFormatHintId::DYING;
    if (bDying)
    {
        m_pFormat = nullptr;
        EndListeningAll();
    }
}

FrameDeleteWatch::~FrameDeleteWatch()
{
    m_pFormat = nullptr;
    EndListeningAll();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/html/htmltab.cxx b/sw/source/filter/html/htmltab.cxx
index e127882..4326e66 100644
--- a/sw/source/filter/html/htmltab.cxx
+++ b/sw/source/filter/html/htmltab.cxx
@@ -4875,41 +4875,6 @@ HTMLTableOptions::HTMLTableOptions( const HTMLOptions& rOptions,

namespace
{
    class FrameDeleteWatch final: public SvtListener
    {
        SwFrameFormat* m_pFormat;
    public:
        FrameDeleteWatch(SwFrameFormat* pFormat)
            : m_pFormat(pFormat)
        {
            if(m_pFormat)
                StartListening(pFormat->GetNotifier());
        }

        virtual void Notify(const SfxHint& rHint) override
        {
            if (auto pDrawFrameFormatHint = dynamic_cast<const sw::DrawFrameFormatHint*>(&rHint))
            {
                if (pDrawFrameFormatHint->m_eId == sw::DrawFrameFormatHintId::DYING)
                {
                    m_pFormat = nullptr;
                    EndListeningAll();
                }
            }
        }

        bool WasDeleted() const
        {
            return !m_pFormat;
        }

        virtual ~FrameDeleteWatch() override
        {
            m_pFormat = nullptr;
            EndListeningAll();
        }
    };

    class IndexInRange
    {
    private:
diff --git a/sw/source/filter/inc/fltshell.hxx b/sw/source/filter/inc/fltshell.hxx
index 2dbf2d6..959bf59 100644
--- a/sw/source/filter/inc/fltshell.hxx
+++ b/sw/source/filter/inc/fltshell.hxx
@@ -330,6 +330,28 @@ public:
    }
};

// detect if the SwFrameFormat it is watching was deleted
class SW_DLLPUBLIC FrameDeleteWatch final: public SvtListener
{
    SwFrameFormat* m_pFormat;
public:
    FrameDeleteWatch(SwFrameFormat* pFormat);

    virtual void Notify(const SfxHint& rHint) override;

    SwFrameFormat* GetFormat()
    {
        return m_pFormat;
    }

    bool WasDeleted() const
    {
        return !m_pFormat;
    }

    virtual ~FrameDeleteWatch() override;
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx
index 544baec..b98b8bd 100644
--- a/sw/source/filter/ww8/ww8par.cxx
+++ b/sw/source/filter/ww8/ww8par.cxx
@@ -2185,7 +2185,7 @@ tools::Long SwWW8ImplReader::Read_And(WW8PLCFManResult* pRes)
    std::unique_ptr<OutlinerParaObject> pOutliner = ImportAsOutliner( sText, pRes->nCp2OrIdx,
        pRes->nCp2OrIdx + pRes->nMemLen, MAN_AND );

    m_pFormatOfJustInsertedApo = nullptr;
    m_xFormatOfJustInsertedApo.reset();
    SwPostItField aPostIt(
        static_cast<SwPostItFieldType*>(m_rDoc.getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::Postit)), sAuthor,
        sText, sInitials, OUString(), aDate );
@@ -4275,7 +4275,6 @@ SwWW8ImplReader::SwWW8ImplReader(sal_uInt8 nVersionPara, SotStorage* pStorage,
    , m_aParaStyleMapper(rD)
    , m_aCharStyleMapper(rD)
    , m_pFlyFormatOfJustInsertedGraphic(nullptr)
    , m_pFormatOfJustInsertedApo(nullptr)
    , m_pPreviousNumPaM(nullptr)
    , m_pPrevNumRule(nullptr)
    , m_aTextNodesHavingFirstLineOfstSet()
diff --git a/sw/source/filter/ww8/ww8par.hxx b/sw/source/filter/ww8/ww8par.hxx
index 01020a3..3bfb203 100644
--- a/sw/source/filter/ww8/ww8par.hxx
+++ b/sw/source/filter/ww8/ww8par.hxx
@@ -1200,7 +1200,7 @@ private:
    std::unique_ptr<SwMSConvertControls> m_xFormImpl; // implementation of control

    SwFlyFrameFormat* m_pFlyFormatOfJustInsertedGraphic;
    SwFrameFormat* m_pFormatOfJustInsertedApo;
    std::unique_ptr<FrameDeleteWatch> m_xFormatOfJustInsertedApo;
    SwPaM* m_pPreviousNumPaM;
    const SwNumRule* m_pPrevNumRule;

diff --git a/sw/source/filter/ww8/ww8par2.cxx b/sw/source/filter/ww8/ww8par2.cxx
index 827b3f4..bf5a275 100644
--- a/sw/source/filter/ww8/ww8par2.cxx
+++ b/sw/source/filter/ww8/ww8par2.cxx
@@ -2375,18 +2375,20 @@ void WW8TabDesc::CreateSwTable()
     Set fly anchor to its anchor pos, so that if a table starts immediately
     at this position a new node will be inserted before inserting the table.
    */
    if (!bInsNode && m_pIo->m_pFormatOfJustInsertedApo)
    SwFrameFormat* pFormat = (!bInsNode && m_pIo->m_xFormatOfJustInsertedApo)
        ? m_pIo->m_xFormatOfJustInsertedApo->GetFormat() : nullptr;
    if (pFormat)
    {
        const SwPosition* pAPos =
            m_pIo->m_pFormatOfJustInsertedApo->GetAnchor().GetContentAnchor();
            pFormat->GetAnchor().GetContentAnchor();
        if (pAPos && &pAPos->nNode.GetNode() == &pPoint->nNode.GetNode())
        {
            bInsNode = true;
            bSetMinHeight = true;

            SwFormatSurround aSur(m_pIo->m_pFormatOfJustInsertedApo->GetSurround());
            SwFormatSurround aSur(pFormat->GetSurround());
            aSur.SetAnchorOnly(true);
            m_pIo->m_pFormatOfJustInsertedApo->SetFormatAttr(aSur);
            pFormat->SetFormatAttr(aSur);
        }
    }

@@ -2800,7 +2802,7 @@ void WW8TabDesc::FinishSwTable()
            }
        }
    }
    m_pIo->m_pFormatOfJustInsertedApo = nullptr;
    m_pIo->m_xFormatOfJustInsertedApo.reset();
    m_MergeGroups.clear();
}

diff --git a/sw/source/filter/ww8/ww8par6.cxx b/sw/source/filter/ww8/ww8par6.cxx
index 36656d8..82f9353 100644
--- a/sw/source/filter/ww8/ww8par6.cxx
+++ b/sw/source/filter/ww8/ww8par6.cxx
@@ -2723,7 +2723,7 @@ void SwWW8ImplReader::StopApo()

    //#i8062#
    if (m_xSFlyPara && m_xSFlyPara->pFlyFormat)
        m_pFormatOfJustInsertedApo = m_xSFlyPara->pFlyFormat;
        m_xFormatOfJustInsertedApo.reset(new FrameDeleteWatch(m_xSFlyPara->pFlyFormat));

    m_xSFlyPara.reset();
    m_xWFlyPara.reset();