fix leak of wronglist in SwTextNode

Change-Id: Ib388575d60d7cc32829108f70d7900d95fc34121
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/116022
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index 50986f3..5e189bb 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -187,14 +187,20 @@ public:
    void SetGrammarCheckDirty( bool bNew ) const;
    void SetSmartTagDirty( bool bNew ) const;
    void SetAutoCompleteWordDirty( bool bNew ) const;
    void SetWrong( SwWrongList* pNew, bool bDelete = true );
    void SetWrong( std::unique_ptr<SwWrongList> pNew );
    void ClearWrong();
    std::unique_ptr<SwWrongList> ReleaseWrong();
    SwWrongList* GetWrong();
    const SwWrongList* GetWrong() const;
    void SetGrammarCheck( SwGrammarMarkUp* pNew, bool bDelete = true );
    void SetGrammarCheck( std::unique_ptr<SwGrammarMarkUp> pNew );
    void ClearGrammarCheck();
    std::unique_ptr<SwGrammarMarkUp> ReleaseGrammarCheck();
    SwGrammarMarkUp* GetGrammarCheck();
    // return SwWrongList because *function pointer* return values aren't covariant
    SwWrongList const* GetGrammarCheck() const;
    void SetSmartTags( SwWrongList* pNew, bool bDelete = true );
    void SetSmartTags( std::unique_ptr<SwWrongList> pNew );
    void ClearSmartTags();
    std::unique_ptr<SwWrongList> ReleaseSmartTags();
    SwWrongList* GetSmartTags();
    SwWrongList const* GetSmartTags() const;
    void TryCharSetExpandToNum(const SfxItemSet& pCharSet);
diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx
index adcb0aa..280bbae 100644
--- a/sw/source/core/crsr/viscrs.cxx
+++ b/sw/source/core/crsr/viscrs.cxx
@@ -248,8 +248,7 @@ void SwVisibleCursor::SetPosAndShow(SfxViewShell const * pViewShell)
                    sal_Int32 nBegin = aPos.nContent.GetIndex();
                    sal_Int32 nLen = 1;

                    SwWrongList *pWrong = nullptr;
                    pWrong = pNode->GetWrong();
                    SwWrongList *pWrong = pNode->GetWrong();
                    if (!pWrong)
                        pWrong = pNode->GetGrammarCheck();
                    if (pWrong)
diff --git a/sw/source/core/doc/doc.cxx b/sw/source/core/doc/doc.cxx
index 8fb7040..e1929ca 100644
--- a/sw/source/core/doc/doc.cxx
+++ b/sw/source/core/doc/doc.cxx
@@ -1144,10 +1144,7 @@ static bool lcl_CheckSmartTagsAgain( const SwNodePtr& rpNd, void*  )
    if( pTextNode )
    {
        pTextNode->SetSmartTagDirty( true );
        if( pTextNode->GetSmartTags() )
        {
            pTextNode->SetSmartTags( nullptr );
        }
        pTextNode->ClearSmartTags();
    }
    return true;
}
diff --git a/sw/source/core/inc/SwGrammarMarkUp.hxx b/sw/source/core/inc/SwGrammarMarkUp.hxx
index 86f0b55..efefadf 100644
--- a/sw/source/core/inc/SwGrammarMarkUp.hxx
+++ b/sw/source/core/inc/SwGrammarMarkUp.hxx
@@ -50,7 +50,7 @@ public:
    /* SwWrongList::Move() + handling of maSentence */
    void MoveGrammar(sal_Int32 nPos, sal_Int32 nDiff);
    /* SwWrongList::SplitList() + handling of maSentence */
    SwGrammarMarkUp* SplitGrammarList(sal_Int32 nSplitPos);
    std::unique_ptr<SwGrammarMarkUp> SplitGrammarList(sal_Int32 nSplitPos);
    /* SwWrongList::JoinList() + handling of maSentence */
    void JoinGrammarList(SwGrammarMarkUp* pNext, sal_Int32 nInsertPos);
    /* SwWrongList::ClearList() + handling of maSentence */
diff --git a/sw/source/core/inc/wrong.hxx b/sw/source/core/inc/wrong.hxx
index 3d32eae..0a2f010 100644
--- a/sw/source/core/inc/wrong.hxx
+++ b/sw/source/core/inc/wrong.hxx
@@ -28,7 +28,7 @@
#include <com/sun/star/uno/Any.hxx>

#include <vector>

#include <memory>
#include <optional>

#include <tools/color.hxx>
@@ -305,7 +305,7 @@ public:

    // Divide the list into two part, the wrong words until nSplitPos will be
    // removed and transferred to a new SwWrongList.
    SwWrongList* SplitList( sal_Int32 nSplitPos );
    std::unique_ptr<SwWrongList> SplitList( sal_Int32 nSplitPos );
    // Join the next SwWrongList, nInsertPos is my own text length, where
    // the other wrong list has to be inserted.
    void JoinList( SwWrongList* pNext, sal_Int32 nInsertPos );
diff --git a/sw/source/core/text/SwGrammarMarkUp.cxx b/sw/source/core/text/SwGrammarMarkUp.cxx
index 3a007ce..53fd4b13 100644
--- a/sw/source/core/text/SwGrammarMarkUp.cxx
+++ b/sw/source/core/text/SwGrammarMarkUp.cxx
@@ -54,9 +54,9 @@ void SwGrammarMarkUp::MoveGrammar( sal_Int32 nPos, sal_Int32 nDiff )
    }
}

SwGrammarMarkUp* SwGrammarMarkUp::SplitGrammarList( sal_Int32 nSplitPos )
std::unique_ptr<SwGrammarMarkUp> SwGrammarMarkUp::SplitGrammarList( sal_Int32 nSplitPos )
{
    SwGrammarMarkUp* pNew = static_cast<SwGrammarMarkUp*>(SplitList( nSplitPos ));
    std::unique_ptr<SwGrammarMarkUp> pNew( static_cast<SwGrammarMarkUp*>(SplitList( nSplitPos ).release()) );
    if( maSentence.empty() )
        return pNew;
    auto pIter = std::find_if(maSentence.begin(), maSentence.end(),
@@ -64,7 +64,7 @@ SwGrammarMarkUp* SwGrammarMarkUp::SplitGrammarList( sal_Int32 nSplitPos )
    if( pIter != maSentence.begin() )
    {
        if( !pNew ) {
            pNew = new SwGrammarMarkUp();
            pNew.reset(new SwGrammarMarkUp());
            pNew->SetInvalid( 0, COMPLETE_STRING );
        }
        pNew->maSentence.insert( pNew->maSentence.begin(), maSentence.begin(), pIter );
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 9d7aa1e..ce0d6cc 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -1831,12 +1831,12 @@ static void lcl_SetWrong( SwTextFrame& rFrame, SwTextNode const& rNode,
        const sal_Int32 nEnd = nPos + (nCnt > 0 ? nCnt : 1 );
        if ( !pTextNode->GetWrong() && !pTextNode->IsWrongDirty() )
        {
            pTextNode->SetWrong( new SwWrongList( WRONGLIST_SPELL ) );
            pTextNode->SetWrong( std::make_unique<SwWrongList>( WRONGLIST_SPELL ) );
            pTextNode->GetWrong()->SetInvalid( nPos, nEnd );
        }
        if ( !pTextNode->GetSmartTags() && !pTextNode->IsSmartTagDirty() )
        {
            pTextNode->SetSmartTags( new SwWrongList( WRONGLIST_SMARTTAG ) );
            pTextNode->SetSmartTags( std::make_unique<SwWrongList>( WRONGLIST_SMARTTAG ) );
            pTextNode->GetSmartTags()->SetInvalid( nPos, nEnd );
        }
        pTextNode->SetWrongDirty(SwTextNode::WrongState::TODO);
diff --git a/sw/source/core/text/wrong.cxx b/sw/source/core/text/wrong.cxx
index 0022f4e..347f4fe 100644
--- a/sw/source/core/text/wrong.cxx
+++ b/sw/source/core/text/wrong.cxx
@@ -442,9 +442,9 @@ bool SwWrongList::InvalidateWrong( )
    return false;
}

SwWrongList* SwWrongList::SplitList( sal_Int32 nSplitPos )
std::unique_ptr<SwWrongList> SwWrongList::SplitList( sal_Int32 nSplitPos )
{
    SwWrongList *pRet = nullptr;
    std::unique_ptr<SwWrongList> pRet;
    sal_uInt16 nLst = 0;
    while( nLst < Count() && Pos( nLst ) < nSplitPos )
        ++nLst;
@@ -462,9 +462,9 @@ SwWrongList* SwWrongList::SplitList( sal_Int32 nSplitPos )
    if( nLst )
    {
        if( WRONGLIST_GRAMMAR == GetWrongListType() )
            pRet = new SwGrammarMarkUp();
            pRet.reset(new SwGrammarMarkUp());
        else
            pRet = new SwWrongList( GetWrongListType() );
            pRet.reset(new SwWrongList( GetWrongListType() ));
        pRet->Insert(0, maList.begin(), ( nLst >= maList.size() ? maList.end() : maList.begin() + nLst ) );
        pRet->SetInvalid( GetBeginInv(), GetEndInv() );
        pRet->Invalidate_( nSplitPos ? nSplitPos - 1 : nSplitPos, nSplitPos );
diff --git a/sw/source/core/txtnode/SwGrammarContact.cxx b/sw/source/core/txtnode/SwGrammarContact.cxx
index 162e0af..9ca33f6 100644
--- a/sw/source/core/txtnode/SwGrammarContact.cxx
+++ b/sw/source/core/txtnode/SwGrammarContact.cxx
@@ -80,7 +80,7 @@ IMPL_LINK( SwGrammarContact, TimerRepaint, Timer *, pTimer, void )
        pTimer->Stop();
        if( m_pTextNode )
        {   //Replace the old wrong list by the proxy list and repaint all frames
            m_pTextNode->SetGrammarCheck( m_pProxyList.release() );
            m_pTextNode->SetGrammarCheck( std::move(m_pProxyList) );
            SwTextFrame::repaintTextFrames( *m_pTextNode );
        }
    }
@@ -99,7 +99,7 @@ void SwGrammarContact::updateCursorPosition( const SwPosition& rNewPos )
    {
        if( m_pProxyList )
        {   // replace old list by the proxy list and repaint
            m_pTextNode->SetGrammarCheck( m_pProxyList.release() );
            m_pTextNode->SetGrammarCheck( std::move(m_pProxyList) );
            SwTextFrame::repaintTextFrames( *m_pTextNode );
        }
        EndListeningAll();
@@ -146,7 +146,7 @@ SwGrammarMarkUp* SwGrammarContact::getGrammarCheck( SwTextNode& rTextNode, bool 
        {
            pRet = new SwGrammarMarkUp();
            pRet->SetInvalid( 0, COMPLETE_STRING );
            rTextNode.SetGrammarCheck( pRet );
            rTextNode.SetGrammarCheck( std::unique_ptr<SwGrammarMarkUp>(pRet) );
            rTextNode.SetGrammarCheckDirty( true );
        }
    }
@@ -167,7 +167,7 @@ void SwGrammarContact::finishGrammarCheck( SwTextNode& rTextNode )
        }
        else if( m_pTextNode->GetGrammarCheck() )
        {   // all grammar problems seems to be gone, no delay needed
            m_pTextNode->SetGrammarCheck( nullptr );
            m_pTextNode->ClearGrammarCheck();
            SwTextFrame::repaintTextFrames( *m_pTextNode );
        }
    }
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index 93b11b1..d513fe9 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -570,18 +570,15 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
    }
    else
    {
        SwWrongList *pList = GetWrong();
        SetWrong( nullptr, false );
        std::unique_ptr<SwWrongList> pList = ReleaseWrong();
        SetWrongDirty(WrongState::TODO);

        SwGrammarMarkUp *pList3 = GetGrammarCheck();
        SetGrammarCheck( nullptr, false );
        std::unique_ptr<SwGrammarMarkUp> pList3 = ReleaseGrammarCheck();
        SetGrammarCheckDirty( true );

        SetWordCountDirty( true );

        SwWrongList *pList2 = GetSmartTags();
        SetSmartTags( nullptr, false );
        std::unique_ptr<SwWrongList> pList2 = ReleaseSmartTags();
        SetSmartTagDirty( true );

        SwIndex aIdx( this );
@@ -607,19 +604,19 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
        if( pList )
        {
            pNode->SetWrong( pList->SplitList( nSplitPos ) );
            SetWrong( pList, false );
            SetWrong( std::move(pList) );
        }

        if( pList3 )
        {
            pNode->SetGrammarCheck( pList3->SplitGrammarList( nSplitPos ) );
            SetGrammarCheck( pList3, false );
            SetGrammarCheck( std::move(pList3) );
        }

        if( pList2 )
        {
            pNode->SetSmartTags( pList2->SplitList( nSplitPos ) );
            SetSmartTags( pList2, false );
            SetSmartTags( std::move(pList2) );
        }

        if (pContentIndexRestore)
@@ -956,57 +953,51 @@ SwContentNode *SwTextNode::JoinNext()
        // METADATA: merge
        JoinMetadatable(*pTextNode, !Len(), !pTextNode->Len());

        SwWrongList *pList = GetWrong();
        std::unique_ptr<SwWrongList> pList = ReleaseWrong();
        if( pList )
        {
            pList->JoinList( pTextNode->GetWrong(), nOldLen );
            SetWrongDirty(WrongState::TODO);
            SetWrong( nullptr, false );
        }
        else
        {
            pList = pTextNode->GetWrong();
            pList = pTextNode->ReleaseWrong();
            if( pList )
            {
                pList->Move( 0, nOldLen );
                SetWrongDirty(WrongState::TODO);
                pTextNode->SetWrong( nullptr, false );
            }
        }

        SwGrammarMarkUp *pList3 = GetGrammarCheck();
        std::unique_ptr<SwGrammarMarkUp> pList3 = ReleaseGrammarCheck();
        if( pList3 )
        {
            pList3->JoinGrammarList( pTextNode->GetGrammarCheck(), nOldLen );
            SetGrammarCheckDirty( true );
            SetGrammarCheck( nullptr, false );
        }
        else
        {
            pList3 = pTextNode->GetGrammarCheck();
            pList3 = pTextNode->ReleaseGrammarCheck();
            if( pList3 )
            {
                pList3->MoveGrammar( 0, nOldLen );
                SetGrammarCheckDirty( true );
                pTextNode->SetGrammarCheck( nullptr, false );
            }
        }

        SwWrongList *pList2 = GetSmartTags();
        std::unique_ptr<SwWrongList> pList2 = ReleaseSmartTags();
        if( pList2 )
        {
            pList2->JoinList( pTextNode->GetSmartTags(), nOldLen );
            SetSmartTagDirty( true );
            SetSmartTags( nullptr, false );
        }
        else
        {
            pList2 = pTextNode->GetSmartTags();
            pList2 = pTextNode->ReleaseSmartTags();
            if( pList2 )
            {
                pList2->Move( 0, nOldLen );
                SetSmartTagDirty( true );
                pTextNode->SetSmartTags( nullptr, false );
            }
        }

@@ -1026,9 +1017,9 @@ SwContentNode *SwTextNode::JoinNext()
        bool bOldHasNumberingWhichNeedsLayoutUpdate = HasNumberingWhichNeedsLayoutUpdate(*pTextNode);

        rNds.Delete(aIdx);
        SetWrong( pList, false );
        SetGrammarCheck( pList3, false );
        SetSmartTags( pList2, false );
        SetWrong( std::move(pList) );
        SetGrammarCheck( std::move(pList3) );
        SetSmartTags( std::move(pList2) );

        if (bOldHasNumberingWhichNeedsLayoutUpdate || HasNumberingWhichNeedsLayoutUpdate(*this))
        {
@@ -1060,60 +1051,54 @@ void SwTextNode::JoinPrev()
        SwTextNode *pTextNode = aIdx.GetNode().GetTextNode();
        const sal_Int32 nLen = pTextNode->Len();

        SwWrongList *pList = pTextNode->GetWrong();
        std::unique_ptr<SwWrongList> pList = pTextNode->ReleaseWrong();
        if( pList )
        {
            pList->JoinList( GetWrong(), Len() );
            SetWrongDirty(WrongState::TODO);
            pTextNode->SetWrong( nullptr, false );
            SetWrong( nullptr );
            ClearWrong();
        }
        else
        {
            pList = GetWrong();
            pList = ReleaseWrong();
            if( pList )
            {
                pList->Move( 0, nLen );
                SetWrongDirty(WrongState::TODO);
                SetWrong( nullptr, false );
            }
        }

        SwGrammarMarkUp *pList3 = pTextNode->GetGrammarCheck();
        std::unique_ptr<SwGrammarMarkUp> pList3 = pTextNode->ReleaseGrammarCheck();
        if( pList3 )
        {
            pList3->JoinGrammarList( GetGrammarCheck(), Len() );
            SetGrammarCheckDirty( true );
            pTextNode->SetGrammarCheck( nullptr, false );
            SetGrammarCheck( nullptr );
            ClearGrammarCheck();
        }
        else
        {
            pList3 = GetGrammarCheck();
            pList3 = ReleaseGrammarCheck();
            if( pList3 )
            {
                pList3->MoveGrammar( 0, nLen );
                SetGrammarCheckDirty( true );
                SetGrammarCheck( nullptr, false );
            }
        }

        SwWrongList *pList2 = pTextNode->GetSmartTags();
        std::unique_ptr<SwWrongList> pList2 = pTextNode->ReleaseSmartTags();
        if( pList2 )
        {
            pList2->JoinList( GetSmartTags(), Len() );
            SetSmartTagDirty( true );
            pTextNode->SetSmartTags( nullptr, false );
            SetSmartTags( nullptr );
            ClearSmartTags();
        }
        else
        {
            pList2 = GetSmartTags();
            pList2 = ReleaseSmartTags();
            if( pList2 )
            {
                pList2->Move( 0, nLen );
                SetSmartTagDirty( true );
                SetSmartTags( nullptr, false );
            }
        }

@@ -1136,9 +1121,9 @@ void SwTextNode::JoinPrev()
            sw::MoveDeletedPrevFrames(*pTextNode, *this);
        }
        rNds.Delete(aIdx);
        SetWrong( pList, false );
        SetGrammarCheck( pList3, false );
        SetSmartTags( pList2, false );
        SetWrong( std::move(pList) );
        SetGrammarCheck( std::move(pList3) );
        SetSmartTags( std::move(pList2) );
        InvalidateNumRule();
        sw::CheckResetRedlineMergeFlag(*this,
                eOldMergeFlag == SwNode::Merge::NonFirst
diff --git a/sw/source/core/txtnode/txtedt.cxx b/sw/source/core/txtnode/txtedt.cxx
index 853632d..19fcade 100644
--- a/sw/source/core/txtnode/txtedt.cxx
+++ b/sw/source/core/txtnode/txtedt.cxx
@@ -99,9 +99,9 @@ namespace

struct SwParaIdleData_Impl
{
    SwWrongList* pWrong;                // for spell checking
    SwGrammarMarkUp* pGrammarCheck;     // for grammar checking /  proof reading
    SwWrongList* pSmartTags;
    std::unique_ptr<SwWrongList> pWrong;                // for spell checking
    std::unique_ptr<SwGrammarMarkUp> pGrammarCheck;     // for grammar checking /  proof reading
    std::unique_ptr<SwWrongList> pSmartTags;
    sal_uLong nNumberOfWords;
    sal_uLong nNumberOfAsianWords;
    sal_uLong nNumberOfChars;
@@ -113,9 +113,6 @@ struct SwParaIdleData_Impl
    bool bAutoComplDirty;               ///< auto complete list dirty

    SwParaIdleData_Impl() :
        pWrong              ( nullptr ),
        pGrammarCheck       ( nullptr ),
        pSmartTags          ( nullptr ),
        nNumberOfWords      ( 0 ),
        nNumberOfAsianWords ( 0 ),
        nNumberOfChars      ( 0 ),
@@ -1343,7 +1340,7 @@ SwRect SwTextFrame::AutoSpell_(SwTextNode & rNode, sal_Int32 nActPos)
                    {
                        if( !pNode->GetWrong() )
                        {
                            pNode->SetWrong( new SwWrongList( WRONGLIST_SPELL ) );
                            pNode->SetWrong( std::make_unique<SwWrongList>( WRONGLIST_SPELL ) );
                            pNode->GetWrong()->SetInvalid( 0, nEnd );
                        }
                        SwWrongList::FreshState const eState(pNode->GetWrong()->Fresh(
@@ -1403,7 +1400,7 @@ SwRect SwTextFrame::AutoSpell_(SwTextNode & rNode, sal_Int32 nActPos)
                    : SwTextNode::WrongState::TODO)
                : SwTextNode::WrongState::DONE);
        if( !pNode->GetWrong()->Count() && ! pNode->IsWrongDirty() )
            pNode->SetWrong( nullptr );
            pNode->ClearWrong();
    }
    else
        pNode->SetWrongDirty(SwTextNode::WrongState::DONE);
@@ -1524,7 +1521,7 @@ SwRect SwTextFrame::SmartTagScan(SwTextNode & rNode)
        pNode->SetSmartTagDirty( COMPLETE_STRING != pSmartTagList->GetBeginInv() );

        if( !pSmartTagList->Count() && !pNode->IsSmartTagDirty() )
            pNode->SetSmartTags( nullptr );
            pNode->ClearSmartTags();

        // Calculate repaint area:
        if ( nBegin < nEnd && ( 0 != nNumberOfRemovedEntries ||
@@ -2166,52 +2163,62 @@ void SwTextNode::InitSwParaStatistics( bool bNew )
    }
    else if ( m_pParaIdleData_Impl )
    {
        delete m_pParaIdleData_Impl->pWrong;
        delete m_pParaIdleData_Impl->pGrammarCheck;
        delete m_pParaIdleData_Impl->pSmartTags;
        m_pParaIdleData_Impl->pWrong.reset();
        m_pParaIdleData_Impl->pGrammarCheck.reset();
        m_pParaIdleData_Impl->pSmartTags.reset();
        delete m_pParaIdleData_Impl;
        m_pParaIdleData_Impl = nullptr;
    }
}

void SwTextNode::SetWrong( SwWrongList* pNew, bool bDelete )
void SwTextNode::SetWrong( std::unique_ptr<SwWrongList> pNew )
{
    if ( m_pParaIdleData_Impl )
    {
        if ( bDelete )
        {
            delete m_pParaIdleData_Impl->pWrong;
        }
        m_pParaIdleData_Impl->pWrong = pNew;
    }
        m_pParaIdleData_Impl->pWrong = std::move(pNew);
}

void SwTextNode::ClearWrong()
{
    if ( m_pParaIdleData_Impl )
        m_pParaIdleData_Impl->pWrong.reset();
}

std::unique_ptr<SwWrongList> SwTextNode::ReleaseWrong()
{
    return m_pParaIdleData_Impl ? std::move(m_pParaIdleData_Impl->pWrong) : nullptr;
}

SwWrongList* SwTextNode::GetWrong()
{
    return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pWrong : nullptr;
    return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pWrong.get() : nullptr;
}

// #i71360#
const SwWrongList* SwTextNode::GetWrong() const
{
    return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pWrong : nullptr;
    return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pWrong.get() : nullptr;
}

void SwTextNode::SetGrammarCheck( SwGrammarMarkUp* pNew, bool bDelete )
void SwTextNode::SetGrammarCheck( std::unique_ptr<SwGrammarMarkUp> pNew )
{
    if ( m_pParaIdleData_Impl )
    {
        if ( bDelete )
        {
            delete m_pParaIdleData_Impl->pGrammarCheck;
        }
        m_pParaIdleData_Impl->pGrammarCheck = pNew;
    }
        m_pParaIdleData_Impl->pGrammarCheck = std::move(pNew);
}

void SwTextNode::ClearGrammarCheck()
{
    if ( m_pParaIdleData_Impl )
        m_pParaIdleData_Impl->pGrammarCheck.reset();
}

std::unique_ptr<SwGrammarMarkUp> SwTextNode::ReleaseGrammarCheck()
{
    return m_pParaIdleData_Impl ? std::move(m_pParaIdleData_Impl->pGrammarCheck) : nullptr;
}

SwGrammarMarkUp* SwTextNode::GetGrammarCheck()
{
    return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pGrammarCheck : nullptr;
    return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pGrammarCheck.get() : nullptr;
}

SwWrongList const* SwTextNode::GetGrammarCheck() const
@@ -2219,24 +2226,29 @@ SwWrongList const* SwTextNode::GetGrammarCheck() const
    return static_cast<SwWrongList const*>(const_cast<SwTextNode*>(this)->GetGrammarCheck());
}

void SwTextNode::SetSmartTags( SwWrongList* pNew, bool bDelete )
void SwTextNode::SetSmartTags( std::unique_ptr<SwWrongList> pNew )
{
    OSL_ENSURE( !pNew || SwSmartTagMgr::Get().IsSmartTagsEnabled(),
    OSL_ENSURE( SwSmartTagMgr::Get().IsSmartTagsEnabled(),
            "Weird - we have a smart tag list without any recognizers?" );

    if ( m_pParaIdleData_Impl )
    {
        if ( bDelete )
        {
            delete m_pParaIdleData_Impl->pSmartTags;
        }
        m_pParaIdleData_Impl->pSmartTags = pNew;
    }
        m_pParaIdleData_Impl->pSmartTags = std::move(pNew);
}

void SwTextNode::ClearSmartTags()
{
    if ( m_pParaIdleData_Impl )
        m_pParaIdleData_Impl->pSmartTags.reset();
}

std::unique_ptr<SwWrongList> SwTextNode::ReleaseSmartTags()
{
    return m_pParaIdleData_Impl ? std::move(m_pParaIdleData_Impl->pSmartTags) : nullptr;
}

SwWrongList* SwTextNode::GetSmartTags()
{
    return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pSmartTags : nullptr;
    return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pSmartTags.get() : nullptr;
}

SwWrongList const* SwTextNode::GetSmartTags() const
diff --git a/sw/source/core/unocore/unoobj.cxx b/sw/source/core/unocore/unoobj.cxx
index c96e8ea..eeff6699 100644
--- a/sw/source/core/unocore/unoobj.cxx
+++ b/sw/source/core/unocore/unoobj.cxx
@@ -2460,17 +2460,17 @@ void SAL_CALL SwXTextCursor::invalidateMarkings(::sal_Int32 nType)
    if ( text::TextMarkupType::SPELLCHECK == nType )
    {
        txtNode->SetWrongDirty(SwTextNode::WrongState::TODO);
        txtNode->SetWrong(nullptr);
        txtNode->ClearWrong();
    }
    else if( text::TextMarkupType::PROOFREADING == nType )
    {
        txtNode->SetGrammarCheckDirty(true);
        txtNode->SetGrammarCheck(nullptr);
        txtNode->ClearGrammarCheck();
    }
    else if ( text::TextMarkupType::SMARTTAG == nType )
    {
        txtNode->SetSmartTagDirty(true);
        txtNode->SetSmartTags(nullptr);
        txtNode->ClearSmartTags();
    }
    else return;

diff --git a/sw/source/core/unocore/unotextmarkup.cxx b/sw/source/core/unocore/unotextmarkup.cxx
index f20b47e..7d544d1 100644
--- a/sw/source/core/unocore/unotextmarkup.cxx
+++ b/sw/source/core/unocore/unotextmarkup.cxx
@@ -164,7 +164,7 @@ void SAL_CALL SwXTextMarkup::commitStringMarkup(
        if ( !pWList )
        {
            pWList = new SwWrongList( WRONGLIST_SPELL );
            m_pImpl->m_pTextNode->SetWrong( pWList );
            m_pImpl->m_pTextNode->SetWrong( std::unique_ptr<SwWrongList>(pWList) );
        }
    }
    else if ( nType == text::TextMarkupType::PROOFREADING || nType == text::TextMarkupType::SENTENCE )
@@ -180,7 +180,7 @@ void SAL_CALL SwXTextMarkup::commitStringMarkup(
            pWList = m_pImpl->m_pTextNode->GetGrammarCheck();
            if ( !pWList )
            {
                m_pImpl->m_pTextNode->SetGrammarCheck( new SwGrammarMarkUp() );
                m_pImpl->m_pTextNode->SetGrammarCheck( std::make_unique<SwGrammarMarkUp>() );
                pWList = m_pImpl->m_pTextNode->GetGrammarCheck();
            }
        }
@@ -194,7 +194,7 @@ void SAL_CALL SwXTextMarkup::commitStringMarkup(
        if ( !pWList )
        {
            pWList = new SwWrongList( WRONGLIST_SMARTTAG );
            m_pImpl->m_pTextNode->SetSmartTags( pWList );
            m_pImpl->m_pTextNode->SetSmartTags( std::unique_ptr<SwWrongList>(pWList) );
        }
    }
    else
@@ -434,7 +434,7 @@ void SAL_CALL SwXTextMarkup::commitMultiTextMarkup(
        pWList = m_pImpl->m_pTextNode->GetGrammarCheck();
        if ( !pWList )
        {
            m_pImpl->m_pTextNode->SetGrammarCheck( new SwGrammarMarkUp() );
            m_pImpl->m_pTextNode->SetGrammarCheck( std::make_unique<SwGrammarMarkUp>() );
            pWList = m_pImpl->m_pTextNode->GetGrammarCheck();
            pWList->SetInvalid( 0, COMPLETE_STRING );
        }