tdf#107427 sw: fix crash with stale entries in SwNavigationMgr

When deleting a header, the sw::UnoCursorPointer of SwNavigationMgr
spontaneously self-destructs, but SwNavigationMgr expects its cursors
to always be alive, so add another SfxListener to remove dying cursors.

(probably regression from a2c467a58ade9f55e0154b2935c747bb283ebd45)

Change-Id: I1055ea3cfc47114dc36002198f1ddffea87d2d85
diff --git a/sw/source/uibase/inc/navmgr.hxx b/sw/source/uibase/inc/navmgr.hxx
index 733fd35..dffe1cb 100644
--- a/sw/source/uibase/inc/navmgr.hxx
+++ b/sw/source/uibase/inc/navmgr.hxx
@@ -21,7 +21,7 @@ class   SwWrtShell;
struct  SwPosition;
class SwUnoCursor;

class SwNavigationMgr final
class SwNavigationMgr final : public SfxListener
{
private:
    /*
@@ -43,11 +43,7 @@ private:
public:
    /* Constructor that initializes the shell to the current shell */
    SwNavigationMgr( SwWrtShell & rShell );
    ~SwNavigationMgr()
    {
        SolarMutexGuard g;
        m_entries.clear();
    }
    ~SwNavigationMgr();
    /* Can we go back in the history ? */
    bool backEnabled() ;
    /* Can we go forward in the history ? */
@@ -58,6 +54,9 @@ public:
    void goForward() ;
    /* The method that adds the position pPos to the navigation history */
    bool addEntry(const SwPosition& rPos);
    /* to get notified if our cursors self-destruct */
    virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override;
};
#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/wrtsh/navmgr.cxx b/sw/source/uibase/wrtsh/navmgr.cxx
index 3852e19..b507c7c 100644
--- a/sw/source/uibase/wrtsh/navmgr.cxx
+++ b/sw/source/uibase/wrtsh/navmgr.cxx
@@ -46,6 +46,34 @@ SwNavigationMgr::SwNavigationMgr(SwWrtShell & rShell)
{
}

SwNavigationMgr::~SwNavigationMgr()
{
    SolarMutexGuard g;
    for (auto & it : m_entries)
    {
        EndListening(it.get()->m_aNotifier);
    }
    m_entries.clear();
}

void SwNavigationMgr::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
{
    // our cursors may now spontaneously self-destruct: remove from
    // m_entries if that happens
    if (typeid(rHint) == typeid(sw::UnoCursorHint))
    {
        for (auto it = m_entries.begin(); it != m_entries.end(); ++it)
        {
            if (!it->get() || & rBC == & it->get()->m_aNotifier)
            {
                EndListening(rBC);
                m_entries.erase(it);
                break;
            }
        }
    }
}

// This method is used by the navigation shell - defined in sw/source/uibase/inc/navsh.hxx
// and implemented in sw/source/uibase/shells/navsh.cxx
// It is called when we want to check if the back button should be enabled or not.
@@ -163,6 +191,7 @@ bool SwNavigationMgr::addEntry(const SwPosition& rPos) {
        if (*m_entries.back()->GetPoint() != rPos)
        {
            sw::UnoCursorPointer pCursor(m_rMyShell.GetDoc()->CreateUnoCursor(rPos));
            StartListening(pCursor->m_aNotifier);
            m_entries.push_back(pCursor);
        }
        bRet = true;
@@ -170,6 +199,7 @@ bool SwNavigationMgr::addEntry(const SwPosition& rPos) {
    else {
        if ( (!m_entries.empty() && *m_entries.back()->GetPoint() != rPos) || m_entries.empty() ) {
            sw::UnoCursorPointer pCursor(m_rMyShell.GetDoc()->CreateUnoCursor(rPos));
            StartListening(pCursor->m_aNotifier);
            m_entries.push_back(pCursor);
            bRet = true;
        }