[Libreoffice-commits] core.git: Branch 'private/mst/sw_redlinehide' - 18 commits - sw/inc sw/source

Michael Stahl Michael.Stahl at cib.de
Thu Jun 7 17:44:03 UTC 2018


Rebased ref, commits from common ancestor:
commit d960dccb11cb6330a95be7f182cb5bf005a5485f
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu Jun 7 19:36:06 2018 +0200

    sw_redlinehide: trivial conversions in lcl_DrawLineForWrongListData
    
    Change-Id: I7425bac439df7518b7fe1b62cd6f3fd7a9f88fec

diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx
index ed1b86f36218..a0a38aa94364 100644
--- a/sw/source/core/txtnode/fntcache.cxx
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -639,7 +639,7 @@ static bool lcl_IsFullstopCentered( const vcl::RenderContext& rOut )
 /* This helper structure (SwForbidden) contains the already marked parts of the string
     to avoid double lines (e.g grammar + spell check error) */
 
-typedef std::vector< std::pair< sal_Int32, sal_Int32 > > SwForbidden;
+typedef std::vector<std::pair<TextFrameIndex, TextFrameIndex>> SwForbidden;
 
 static void lcl_DrawLineForWrongListData(
     SwForbidden &rForbidden,
@@ -679,23 +679,20 @@ static void lcl_DrawLineForWrongListData(
     {
         nStart -= rInf.GetIdx();
 
-        const sal_Int32 nEnd = nStart + nWrLen;
-        sal_Int32 nNext = nStart;
+        const TextFrameIndex nEnd = nStart + nWrLen;
+        TextFrameIndex nNext = nStart;
         while( nNext < nEnd )
         {
             while( pIter != rForbidden.end() && pIter->second <= nNext )
                 ++pIter;
 
-            const sal_Int32 nNextStart = nNext;
-            sal_Int32 nNextEnd = nEnd;
+            const TextFrameIndex nNextStart = nNext;
+            TextFrameIndex nNextEnd = nEnd;
 
             if( pIter == rForbidden.end() || nNextEnd <= pIter->first )
             {
                 // No overlapping mark up found
-                std::pair< sal_Int32, sal_Int32 > aNew;
-                aNew.first = nNextStart;
-                aNew.second = nNextEnd;
-                rForbidden.insert( pIter, aNew );
+                rForbidden.insert(pIter, std::make_pair(nNextStart, nNextEnd));
                 pIter = rForbidden.begin();
                 nNext = nEnd;
             }
commit 0f7632aa580a20b9c6305c60b52ce32d170074bb
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu Jun 7 18:50:13 2018 +0200

    calbck Unwrap fuckup fix
    
    Change-Id: I0075d0a0183aa7ca134092b7a2adfe37c102a726

diff --git a/sw/inc/calbck.hxx b/sw/inc/calbck.hxx
index 6d64e3e5781f..967e4be6a314 100644
--- a/sw/inc/calbck.hxx
+++ b/sw/inc/calbck.hxx
@@ -227,10 +227,40 @@ template<typename TElementType, typename TSource, sw::IteratorMode eMode> class
 
 namespace sw
 {
-    class ListenerEntry;
-    class SW_DLLPUBLIC WriterMultiListener final
+    // this should be hidden but sadly SwIterator template needs it...
+    class ListenerEntry final : public SwClient
     {
+    private:
         template<typename E, typename S, sw::IteratorMode> friend class ::SwIterator;
+        SwClient *m_pToTell;
+
+    public:
+        ListenerEntry(SwClient *const pTellHim, SwModify *const pDepend)
+            : SwClient(pDepend), m_pToTell(pTellHim)
+        {}
+        ListenerEntry(ListenerEntry&) = delete;
+        ListenerEntry& operator=(ListenerEntry const&) = delete;
+        ListenerEntry(ListenerEntry&& other) noexcept
+            : SwClient(std::move(other))
+            , m_pToTell(other.m_pToTell)
+        { }
+        ListenerEntry& operator=(ListenerEntry&& other) noexcept
+        {
+            m_pToTell = other.m_pToTell;
+            other.GetRegisteredIn()->Add(this);
+            other.EndListeningAll();
+            return *this;
+        }
+
+        /** get Client information */
+        virtual bool GetInfo( SfxPoolItem& rInfo) const override;
+    private:
+        virtual void Modify(const SfxPoolItem* pOldValue, const SfxPoolItem *pNewValue) override;
+        virtual void SwClientNotify(const SwModify& rModify, const SfxHint& rHint) override;
+    };
+
+    class SW_DLLPUBLIC WriterMultiListener final
+    {
         SwClient& m_rToTell;
         std::vector<ListenerEntry> m_vDepends;
         public:
@@ -318,9 +348,9 @@ public:
         sw::WriterListener * pCurrent(m_pPosition);
         if (eMode == sw::IteratorMode::UnwrapMulti)
         {
-            if (auto const pWL = dynamic_cast<sw::WriterMultiListener const*>(pCurrent))
+            if (auto const pLE = dynamic_cast<sw::ListenerEntry const*>(pCurrent))
             {
-                pCurrent = &pWL->m_rToTell;
+                pCurrent = pLE->m_pToTell;
             }
         }
         if (dynamic_cast<const TElementType *>(pCurrent) != nullptr)
@@ -339,9 +369,9 @@ public:
         {
             if (eMode == sw::IteratorMode::UnwrapMulti)
             {
-                if (auto const pWL = dynamic_cast<sw::WriterMultiListener const*>(m_pPosition))
+                if (auto const pLE = dynamic_cast<sw::ListenerEntry const*>(m_pPosition))
                 {
-                    pCurrent = &pWL->m_rToTell;
+                    pCurrent = pLE->m_pToTell;
                 }
             }
             if (dynamic_cast<const TElementType *>(pCurrent) == nullptr)
@@ -363,9 +393,9 @@ public:
         {
             if (eMode == sw::IteratorMode::UnwrapMulti)
             {
-                if (auto const pWL = dynamic_cast<sw::WriterMultiListener const*>(m_pPosition))
+                if (auto const pLE = dynamic_cast<sw::ListenerEntry const*>(m_pPosition))
                 {
-                    pCurrent = &pWL->m_rToTell;
+                    pCurrent = pLE->m_pToTell;
                 }
             }
             if (dynamic_cast<const TElementType *>(pCurrent) == nullptr)
diff --git a/sw/source/core/attr/calbck.cxx b/sw/source/core/attr/calbck.cxx
index 3ab307bd6e24..c8c26164c1fd 100644
--- a/sw/source/core/attr/calbck.cxx
+++ b/sw/source/core/attr/calbck.cxx
@@ -27,51 +27,29 @@
 
 namespace sw
 {
-    class ListenerEntry final : public SwClient
+    bool ListenerEntry::GetInfo(SfxPoolItem& rInfo) const
+        { return m_pToTell == nullptr || m_pToTell->GetInfo( rInfo ); }
+    void ListenerEntry::Modify(const SfxPoolItem *const pOldValue,
+                               const SfxPoolItem *const pNewValue)
     {
-        SwClient *m_pToTell;
-
-    public:
-        ListenerEntry(SwClient* pTellHim, SwModify * pDepend) : SwClient(pDepend), m_pToTell(pTellHim) {}
-        ListenerEntry(ListenerEntry&) = delete;
-        ListenerEntry& operator=(ListenerEntry const&) = delete;
-        ListenerEntry(ListenerEntry&& other) noexcept
-            : SwClient(std::move(other))
-            , m_pToTell(other.m_pToTell)
-        { }
-        ListenerEntry& operator=(ListenerEntry&& other) noexcept
-        {
-            m_pToTell = other.m_pToTell;
-            other.GetRegisteredIn()->Add(this);
-            other.EndListeningAll();
-            return *this;
-        }
-
-        /** get Client information */
-        virtual bool GetInfo( SfxPoolItem& rInfo) const override
-            { return m_pToTell == nullptr || m_pToTell->GetInfo( rInfo ); }
-    private:
-        virtual void Modify( const SfxPoolItem* pOldValue, const SfxPoolItem *pNewValue ) override
-        {
-            SwClientNotify(*GetRegisteredIn(), sw::LegacyModifyHint(pOldValue, pNewValue));
-        }
-        virtual void SwClientNotify( const SwModify& rModify, const SfxHint& rHint ) override
+        SwClientNotify(*GetRegisteredIn(), sw::LegacyModifyHint(pOldValue, pNewValue));
+    }
+    void ListenerEntry::SwClientNotify(const SwModify& rModify, const SfxHint& rHint)
+    {
+        if (auto pLegacyHint = dynamic_cast<const sw::LegacyModifyHint*>(&rHint))
         {
-            if (auto pLegacyHint = dynamic_cast<const sw::LegacyModifyHint*>(&rHint))
+            if (pLegacyHint->m_pNew && pLegacyHint->m_pNew->Which() == RES_OBJECTDYING)
             {
-                if( pLegacyHint->m_pNew && pLegacyHint->m_pNew->Which() == RES_OBJECTDYING )
-                {
-                    auto pModifyChanged = CheckRegistration(pLegacyHint->m_pOld);
-                    if(pModifyChanged)
-                        m_pToTell->SwClientNotify(rModify, *pModifyChanged);
-                }
-                else if( m_pToTell )
-                    m_pToTell->ModifyNotification(pLegacyHint->m_pOld, pLegacyHint->m_pNew);
+                auto pModifyChanged = CheckRegistration(pLegacyHint->m_pOld);
+                if (pModifyChanged)
+                    m_pToTell->SwClientNotify(rModify, *pModifyChanged);
             }
-            else if(m_pToTell)
-                m_pToTell->SwClientNotifyCall(rModify, rHint);
+            else if (m_pToTell)
+                m_pToTell->ModifyNotification(pLegacyHint->m_pOld, pLegacyHint->m_pNew);
         }
-    };
+        else if (m_pToTell)
+            m_pToTell->SwClientNotifyCall(rModify, rHint);
+    }
 }
 
 sw::LegacyModifyHint::~LegacyModifyHint() {}
commit 7b367460e6b3ec73d785deb2db19122e470d44bf
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu Jun 7 18:48:15 2018 +0200

    drawfron.hxx
    
    Change-Id: Icb0957d34aad39e3e47c24c3134c93d5bb9ef1df

diff --git a/sw/source/core/inc/drawfont.hxx b/sw/source/core/inc/drawfont.hxx
index f484e56546c9..8cfa4b720082 100644
--- a/sw/source/core/inc/drawfont.hxx
+++ b/sw/source/core/inc/drawfont.hxx
@@ -30,7 +30,7 @@ class SwTextFrame;
 class SwViewShell;
 class SwScriptInfo;
 class Point;
-class SwWrongList;
+namespace sw { class WrongListIterator; }
 class Size;
 class SwFont;
 namespace vcl {
@@ -50,9 +50,9 @@ class SW_DLLPUBLIC SwDrawTextInfo
     Point m_aPos;
     vcl::TextLayoutCache const* m_pCachedVclData;
     OUString m_aText;
-    const SwWrongList* m_pWrong;
-    const SwWrongList* m_pGrammarCheck;
-    const SwWrongList* m_pSmartTags;
+    sw::WrongListIterator* m_pWrong;
+    sw::WrongListIterator* m_pGrammarCheck;
+    sw::WrongListIterator* m_pSmartTags;
     Size m_aSize;
     SwFont *m_pFnt;
     SwUnderlineFont* m_pUnderFnt;
@@ -220,7 +220,7 @@ public:
         return m_aText;
     }
 
-    const SwWrongList* GetWrong() const
+    sw::WrongListIterator* GetWrong() const
     {
 #ifdef DBG_UTIL
         OSL_ENSURE( m_bWrong, "DrawTextInfo: Undefined WrongList" );
@@ -228,7 +228,7 @@ public:
         return m_pWrong;
     }
 
-    const SwWrongList* GetGrammarCheck() const
+    sw::WrongListIterator* GetGrammarCheck() const
     {
 #ifdef DBG_UTIL
         OSL_ENSURE( m_bGrammarCheck, "DrawTextInfo: Undefined GrammarCheck List" );
@@ -236,7 +236,7 @@ public:
         return m_pGrammarCheck;
     }
 
-    const SwWrongList* GetSmartTags() const
+    sw::WrongListIterator* GetSmartTags() const
     {
         return m_pSmartTags;
     }
@@ -418,7 +418,7 @@ public:
         m_pCachedVclData = nullptr; // would any case benefit from save/restore?
     }
 
-    void SetWrong( const SwWrongList* pNew )
+    void SetWrong(sw::WrongListIterator *const pNew)
     {
         m_pWrong = pNew;
 #ifdef DBG_UTIL
@@ -426,7 +426,7 @@ public:
 #endif
     }
 
-    void SetGrammarCheck( const SwWrongList* pNew )
+    void SetGrammarCheck(sw::WrongListIterator *const pNew)
     {
         m_pGrammarCheck = pNew;
 #ifdef DBG_UTIL
@@ -434,7 +434,7 @@ public:
 #endif
     }
 
-    void SetSmartTags( const SwWrongList* pNew )
+    void SetSmartTags(sw::WrongListIterator *const pNew)
     {
         m_pSmartTags = pNew;
     }
commit a0821997a12541d407d62dec5218a580aed57fc8
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu Jun 7 17:55:12 2018 +0200

    frmpaint.cxx
    
    Change-Id: I3d704bc3324b7b0d37534185fe85af7ac44aeb94

diff --git a/sw/source/core/text/frmpaint.cxx b/sw/source/core/text/frmpaint.cxx
index 217615337e37..5cbc6dbd38c5 100644
--- a/sw/source/core/text/frmpaint.cxx
+++ b/sw/source/core/text/frmpaint.cxx
@@ -45,6 +45,7 @@
 #include <tabfrm.hxx>
 #include <numrule.hxx>
 #include <SwGrammarMarkUp.hxx>
+#include <wrong.hxx>
 
 #include <EnhancedPDFExportHelper.hxx>
 
@@ -651,9 +652,21 @@ void SwTextFrame::PaintSwFrame(vcl::RenderContext& rRenderContext, SwRect const&
             SwitchRTLtoLTR( const_cast<SwRect&>(rRect) );
 
         SwTextPaintInfo aInf( const_cast<SwTextFrame*>(this), rRect );
-        aInf.SetWrongList( const_cast<SwTextNode*>(GetTextNode())->GetWrong() );
-        aInf.SetGrammarCheckList( const_cast<SwTextNode*>(GetTextNode())->GetGrammarCheck() );
-        aInf.SetSmartTags( const_cast<SwTextNode*>(GetTextNode())->GetSmartTags() );
+        sw::WrongListIterator iterWrong(*this, &SwTextNode::GetWrong);
+        sw::WrongListIterator iterGrammar(*this, &SwTextNode::GetGrammarCheck);
+        sw::WrongListIterator iterSmartTags(*this, &SwTextNode::GetSmartTags);
+        if (iterWrong.LooksUseful())
+        {
+            aInf.SetWrongList( &iterWrong );
+        }
+        if (iterGrammar.LooksUseful())
+        {
+            aInf.SetGrammarCheckList( &iterGrammar );
+        }
+        if (iterSmartTags.LooksUseful())
+        {
+            aInf.SetSmartTags( &iterSmartTags );
+        }
         aInf.GetTextFly().SetTopRule();
 
         SwTextPainter  aLine( const_cast<SwTextFrame*>(this), &aInf );
commit b45fe6db204348ce1853646745779c3bcb3b16c9
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu Jun 7 17:48:03 2018 +0200

    inftxt.hxx
    
    Change-Id: I2500f9cd13c16745f4e6be07f01425d234910634

diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx
index a0e7c1c06131..9a29d58d0b19 100644
--- a/sw/source/core/text/inftxt.cxx
+++ b/sw/source/core/text/inftxt.cxx
@@ -487,18 +487,18 @@ void SwTextPaintInfo::CtorInitTextPaintInfo( OutputDevice* pRenderContext, SwTex
     aPaintRect = rPaint;
     nSpaceIdx = 0;
     pSpaceAdd = nullptr;
-    pWrongList = nullptr;
-    pGrammarCheckList = nullptr;
-    pSmartTags = nullptr;
+    m_pWrongList = nullptr;
+    m_pGrammarCheckList = nullptr;
+    m_pSmartTags = nullptr;
     pBrushItem = nullptr;
 }
 
 SwTextPaintInfo::SwTextPaintInfo( const SwTextPaintInfo &rInf, const OUString* pText )
-    : SwTextSizeInfo( rInf, pText ),
-      pWrongList( rInf.GetpWrongList() ),
-      pGrammarCheckList( rInf.GetGrammarCheckList() ),
-      pSmartTags( rInf.GetSmartTags() ),
-      pSpaceAdd( rInf.GetpSpaceAdd() ),
+    : SwTextSizeInfo( rInf, pText )
+    , m_pWrongList( rInf.GetpWrongList() )
+    , m_pGrammarCheckList( rInf.GetGrammarCheckList() )
+    , m_pSmartTags( rInf.GetSmartTags() )
+    , pSpaceAdd( rInf.GetpSpaceAdd() ),
       pBrushItem( rInf.GetBrushItem() ),
       aTextFly( rInf.GetTextFly() ),
       aPos( rInf.GetPos() ),
@@ -507,11 +507,11 @@ SwTextPaintInfo::SwTextPaintInfo( const SwTextPaintInfo &rInf, const OUString* p
 { }
 
 SwTextPaintInfo::SwTextPaintInfo( const SwTextPaintInfo &rInf )
-    : SwTextSizeInfo( rInf ),
-      pWrongList( rInf.GetpWrongList() ),
-      pGrammarCheckList( rInf.GetGrammarCheckList() ),
-      pSmartTags( rInf.GetSmartTags() ),
-      pSpaceAdd( rInf.GetpSpaceAdd() ),
+    : SwTextSizeInfo( rInf )
+    , m_pWrongList( rInf.GetpWrongList() )
+    , m_pGrammarCheckList( rInf.GetGrammarCheckList() )
+    , m_pSmartTags( rInf.GetSmartTags() )
+    , pSpaceAdd( rInf.GetpSpaceAdd() ),
       pBrushItem( rInf.GetBrushItem() ),
       aTextFly( rInf.GetTextFly() ),
       aPos( rInf.GetPos() ),
@@ -693,9 +693,9 @@ void SwTextPaintInfo::DrawText_( const OUString &rText, const SwLinePortion &rPo
         aDrawInf.SetSize( aSize );
         aDrawInf.SetAscent( rPor.GetAscent() );
         aDrawInf.SetKern( bKern ? rPor.Width() : 0 );
-        aDrawInf.SetWrong( bTmpWrong ? pWrongList : nullptr );
-        aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? pGrammarCheckList : nullptr );
-        aDrawInf.SetSmartTags( bTmpSmart ? pSmartTags : nullptr );
+        aDrawInf.SetWrong( bTmpWrong ? m_pWrongList : nullptr );
+        aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? m_pGrammarCheckList : nullptr );
+        aDrawInf.SetSmartTags( bTmpSmart ? m_pSmartTags : nullptr );
         GetTextFly().DrawTextOpaque( aDrawInf );
     }
     else
@@ -705,9 +705,9 @@ void SwTextPaintInfo::DrawText_( const OUString &rText, const SwLinePortion &rPo
             m_pFnt->DrawStretchText_( aDrawInf );
         else
         {
-            aDrawInf.SetWrong( bTmpWrong ? pWrongList : nullptr );
-            aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? pGrammarCheckList : nullptr );
-            aDrawInf.SetSmartTags( bTmpSmart ? pSmartTags : nullptr );
+            aDrawInf.SetWrong( bTmpWrong ? m_pWrongList : nullptr );
+            aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? m_pGrammarCheckList : nullptr );
+            aDrawInf.SetSmartTags( bTmpSmart ? m_pSmartTags : nullptr );
             m_pFnt->DrawText_( aDrawInf );
         }
     }
@@ -1718,9 +1718,8 @@ SwTextSlot::SwTextSlot(
     bool bExgLists,
     OUString const & rCh )
     : pOldText(nullptr)
-    , pOldSmartTagList(nullptr)
-    , pOldGrammarCheckList(nullptr)
-    , pTempList(nullptr)
+    , m_pOldSmartTagList(nullptr)
+    , m_pOldGrammarCheckList(nullptr)
     , nIdx(0)
     , nLen(0)
     , pInf(nullptr)
@@ -1751,37 +1750,63 @@ SwTextSlot::SwTextSlot(
         // ST2
         if ( bExgLists )
         {
-            pOldSmartTagList = static_cast<SwTextPaintInfo*>(pInf)->GetSmartTags();
-            if ( pOldSmartTagList )
+            m_pOldSmartTagList = static_cast<SwTextPaintInfo*>(pInf)->GetSmartTags();
+            if (m_pOldSmartTagList)
             {
-                const sal_uInt16 nPos = pOldSmartTagList->GetWrongPos(nIdx);
-                const sal_Int32 nListPos = pOldSmartTagList->Pos(nPos);
-                if( nListPos == nIdx )
-                    static_cast<SwTextPaintInfo*>(pInf)->SetSmartTags( pOldSmartTagList->SubList( nPos ) );
-                else if( !pTempList && nPos < pOldSmartTagList->Count() && nListPos < nIdx && !aText.isEmpty() )
+                std::pair<SwTextNode const*, sal_Int32> pos(pNew->GetTextFrame()->MapViewToModel(nIdx));
+                SwWrongList const*const pSmartTags(pos.first->GetSmartTags());
+                assert(m_pOldSmartTagList->MergedOrSame(pSmartTags));
+                if (pSmartTags)
                 {
-                    pTempList = new SwWrongList( WRONGLIST_SMARTTAG );
-                    pTempList->Insert( OUString(), nullptr, 0, aText.getLength(), 0 );
-                    static_cast<SwTextPaintInfo*>(pInf)->SetSmartTags( pTempList );
+                    const sal_uInt16 nPos = pSmartTags->GetWrongPos(pos.second);
+                    const sal_Int32 nListPos = pSmartTags->Pos(nPos);
+                    if (nListPos == pos.second)
+                    {
+                        m_pTempIter.reset(new sw::WrongListIterator(*pSmartTags->SubList(nPos)));
+                        static_cast<SwTextPaintInfo*>(pInf)->SetSmartTags(m_pTempIter.get());
+                    }
+                    else if (!m_pTempList && nPos < pSmartTags->Count()
+                                && nListPos < pos.second && !aText.isEmpty())
+                    {
+                        m_pTempList.reset(new SwWrongList( WRONGLIST_SMARTTAG ));
+                        m_pTempList->Insert( OUString(), nullptr, 0, aText.getLength(), 0 );
+                        m_pTempIter.reset(new sw::WrongListIterator(*m_pTempList));
+                        static_cast<SwTextPaintInfo*>(pInf)->SetSmartTags(m_pTempIter.get());
+                    }
+                    else
+                        static_cast<SwTextPaintInfo*>(pInf)->SetSmartTags(nullptr);
                 }
                 else
-                    static_cast<SwTextPaintInfo*>(pInf)->SetSmartTags( nullptr);
+                    static_cast<SwTextPaintInfo*>(pInf)->SetSmartTags(nullptr);
             }
-            pOldGrammarCheckList = static_cast<SwTextPaintInfo*>(pInf)->GetGrammarCheckList();
-            if ( pOldGrammarCheckList )
+            m_pOldGrammarCheckList = static_cast<SwTextPaintInfo*>(pInf)->GetGrammarCheckList();
+            if (m_pOldGrammarCheckList)
             {
-                const sal_uInt16 nPos = pOldGrammarCheckList->GetWrongPos(nIdx);
-                const sal_Int32 nListPos = pOldGrammarCheckList->Pos(nPos);
-                if( nListPos == nIdx )
-                    static_cast<SwTextPaintInfo*>(pInf)->SetGrammarCheckList( pOldGrammarCheckList->SubList( nPos ) );
-                else if( !pTempList && nPos < pOldGrammarCheckList->Count() && nListPos < nIdx && !aText.isEmpty() )
+                std::pair<SwTextNode const*, sal_Int32> pos(pNew->GetTextFrame()->MapViewToModel(nIdx));
+                SwWrongList const*const pGrammar(pos.first->GetGrammarCheck());
+                assert(m_pOldGrammarCheckList->MergedOrSame(pGrammar));
+                if (pGrammar)
                 {
-                    pTempList = new SwWrongList( WRONGLIST_GRAMMAR );
-                    pTempList->Insert( OUString(), nullptr, 0, aText.getLength(), 0 );
-                    static_cast<SwTextPaintInfo*>(pInf)->SetGrammarCheckList( pTempList );
+                    const sal_uInt16 nPos = pGrammar->GetWrongPos(pos.second);
+                    const sal_Int32 nListPos = pGrammar->Pos(nPos);
+                    if (nListPos == pos.second)
+                    {
+                        m_pTempIter.reset(new sw::WrongListIterator(*pGrammar->SubList(nPos)));
+                        static_cast<SwTextPaintInfo*>(pInf)->SetGrammarCheckList(m_pTempIter.get());
+                    }
+                    else if (!m_pTempList && nPos < pGrammar->Count()
+                                && nListPos < pos.second && !aText.isEmpty())
+                    {
+                        m_pTempList.reset(new SwWrongList( WRONGLIST_GRAMMAR ));
+                        m_pTempList->Insert( OUString(), nullptr, 0, aText.getLength(), 0 );
+                        m_pTempIter.reset(new sw::WrongListIterator(*m_pTempList));
+                        static_cast<SwTextPaintInfo*>(pInf)->SetGrammarCheckList(m_pTempIter.get());
+                    }
+                    else
+                        static_cast<SwTextPaintInfo*>(pInf)->SetGrammarCheckList(nullptr);
                 }
                 else
-                    static_cast<SwTextPaintInfo*>(pInf)->SetGrammarCheckList( nullptr);
+                    static_cast<SwTextPaintInfo*>(pInf)->SetGrammarCheckList(nullptr);
             }
         }
     }
@@ -1798,11 +1823,10 @@ SwTextSlot::~SwTextSlot()
 
         // ST2
         // Restore old smart tag list
-        if ( pOldSmartTagList )
-            static_cast<SwTextPaintInfo*>(pInf)->SetSmartTags( pOldSmartTagList );
-        if ( pOldGrammarCheckList )
-            static_cast<SwTextPaintInfo*>(pInf)->SetGrammarCheckList( pOldGrammarCheckList );
-        delete pTempList;
+        if (m_pOldSmartTagList)
+            static_cast<SwTextPaintInfo*>(pInf)->SetSmartTags(m_pOldSmartTagList);
+        if (m_pOldGrammarCheckList)
+            static_cast<SwTextPaintInfo*>(pInf)->SetGrammarCheckList(m_pOldGrammarCheckList);
     }
 }
 
diff --git a/sw/source/core/text/inftxt.hxx b/sw/source/core/text/inftxt.hxx
index 40bf57ebcebb..1156e1197c14 100644
--- a/sw/source/core/text/inftxt.hxx
+++ b/sw/source/core/text/inftxt.hxx
@@ -55,7 +55,7 @@ class SwViewShell;
 class SwAttrIter;
 struct SwMultiCreator;
 class SwMultiPortion;
-class SwWrongList;
+namespace sw { class WrongListIterator; }
 
 #define ARROW_WIDTH 200
 #define DIR_LEFT2RIGHT 0
@@ -351,9 +351,9 @@ public:
 
 class SwTextPaintInfo : public SwTextSizeInfo
 {
-    const SwWrongList *pWrongList;
-    const SwWrongList *pGrammarCheckList;
-    const SwWrongList *pSmartTags;
+    sw::WrongListIterator *m_pWrongList;
+    sw::WrongListIterator *m_pGrammarCheckList;
+    sw::WrongListIterator *m_pSmartTags;
     std::vector<long>* pSpaceAdd;
     const SvxBrushItem *pBrushItem; // For the background
     SwTextFly    aTextFly;    // Calculate the FlyFrame
@@ -371,9 +371,9 @@ class SwTextPaintInfo : public SwTextSizeInfo
 
 protected:
     SwTextPaintInfo()
-        : pWrongList(nullptr)
-        , pGrammarCheckList(nullptr)
-        , pSmartTags(nullptr)
+        : m_pWrongList(nullptr)
+        , m_pGrammarCheckList(nullptr)
+        , m_pSmartTags(nullptr)
         , pSpaceAdd(nullptr)
         , pBrushItem(nullptr)
         , nSpaceIdx(0)
@@ -458,14 +458,14 @@ public:
     void SetpSpaceAdd( std::vector<long>* pNew ){ pSpaceAdd = pNew; }
     std::vector<long>* GetpSpaceAdd() const { return pSpaceAdd; }
 
-    void SetWrongList( const SwWrongList *pNew ){ pWrongList = pNew; }
-    const SwWrongList* GetpWrongList() const { return pWrongList; }
+    void SetWrongList(sw::WrongListIterator *const pNew) { m_pWrongList = pNew; }
+    sw::WrongListIterator* GetpWrongList() const { return m_pWrongList; }
 
-    void SetGrammarCheckList( const SwWrongList *pNew ){ pGrammarCheckList = pNew; }
-    const SwWrongList* GetGrammarCheckList() const { return pGrammarCheckList; }
+    void SetGrammarCheckList(sw::WrongListIterator *const pNew) { m_pGrammarCheckList = pNew; }
+    sw::WrongListIterator* GetGrammarCheckList() const { return m_pGrammarCheckList; }
 
-    void SetSmartTags( const SwWrongList *pNew ){ pSmartTags = pNew; }
-    const SwWrongList* GetSmartTags() const { return pSmartTags; }
+    void SetSmartTags(sw::WrongListIterator *const pNew) { m_pSmartTags = pNew; }
+    sw::WrongListIterator* GetSmartTags() const { return m_pSmartTags; }
 };
 
 class SwTextFormatInfo : public SwTextPaintInfo
@@ -683,9 +683,10 @@ class SwTextSlot final
     OUString aText;
     std::shared_ptr<vcl::TextLayoutCache> m_pOldCachedVclData;
     const OUString *pOldText;
-    const SwWrongList* pOldSmartTagList;
-    const SwWrongList* pOldGrammarCheckList;
-    SwWrongList* pTempList;
+    sw::WrongListIterator * m_pOldSmartTagList;
+    sw::WrongListIterator * m_pOldGrammarCheckList;
+    std::unique_ptr<SwWrongList> m_pTempList;
+    std::unique_ptr<sw::WrongListIterator> m_pTempIter;
     TextFrameIndex nIdx;
     TextFrameIndex nLen;
     bool bOn;
commit bcc130fcedaff658c0d786bf4013b93f9202d550
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu Jun 7 17:41:55 2018 +0200

    use it
    
    Change-Id: I5a0999f7d39f2c907d07260c9cddfc3fa466b205

diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
index 8256d458357e..69593f8d157c 100644
--- a/sw/source/core/text/portxt.cxx
+++ b/sw/source/core/text/portxt.cxx
@@ -550,9 +550,9 @@ void SwTextPortion::Paint( const SwTextPaintInfo &rInf ) const
         if( rInf.OnWin() && pPortion && !pPortion->Width() )
             pPortion->PrePaint( rInf, this );
 
-        const SwWrongList *pWrongList = rInf.GetpWrongList();
-        const SwWrongList *pGrammarCheckList = rInf.GetGrammarCheckList();
-        const SwWrongList *pSmarttags = rInf.GetSmartTags();
+        auto const* pWrongList = rInf.GetpWrongList();
+        auto const* pGrammarCheckList = rInf.GetGrammarCheckList();
+        auto const* pSmarttags = rInf.GetSmartTags();
 
         const bool bWrong = nullptr != pWrongList;
         const bool bGrammarCheck = nullptr != pGrammarCheckList;
commit ac5557ba122fa2654821725249481f8193eb0255
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu Jun 7 17:37:52 2018 +0200

    sw_redlinehide: WrongListIteratr impl
    
    Change-Id: I9742e3793abe090cf58ad3f27b51e89be86a1964

diff --git a/sw/source/core/inc/wrong.hxx b/sw/source/core/inc/wrong.hxx
index 0aa575434483..cfb2a4cfe78d 100644
--- a/sw/source/core/inc/wrong.hxx
+++ b/sw/source/core/inc/wrong.hxx
@@ -32,6 +32,7 @@
 #include <tools/color.hxx>
 #include <swtypes.hxx>
 #include <viewopt.hxx>
+#include <TextFrameIndex.hxx>
 
 class SwWrongList;
 
@@ -331,6 +332,41 @@ public:
     bool LookForEntry( sal_Int32 nBegin, sal_Int32 nEnd );
 };
 
+class SwTextNode;
+class SwTextFrame;
+
+namespace sw {
+
+struct MergedPara;
+
+class WrongListIterator
+{
+private:
+    SwWrongList const* (SwTextNode::*const m_pGetWrongList)() const;
+    sw::MergedPara const*const m_pMergedPara;
+    size_t m_CurrentExtent;
+    TextFrameIndex m_CurrentIndex;
+    TextFrameIndex m_CurrentNodeIndex;
+    SwWrongList const*const m_pWrongList;
+
+public:
+    /// for the text frame
+    WrongListIterator(SwTextFrame const& rFrame,
+        SwWrongList const* (SwTextNode::*pGetWrongList)() const);
+    /// for SwTextSlot
+    WrongListIterator(SwWrongList const& rWrongList);
+
+    bool Check(TextFrameIndex &rStart, TextFrameIndex &rLen);
+    const SwWrongArea* GetWrongElement(TextFrameIndex nStart);
+
+    bool LooksUseful() { return m_pMergedPara || m_pWrongList; }
+    bool MergedOrSame(SwWrongList const*const pList) const {
+        return m_pMergedPara || m_pWrongList == pList;
+    }
+};
+
+} // namespace sw
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/wrong.cxx b/sw/source/core/text/wrong.cxx
index 20fdac821985..ceb2c8859029 100644
--- a/sw/source/core/text/wrong.cxx
+++ b/sw/source/core/text/wrong.cxx
@@ -20,6 +20,9 @@
 #include <swtypes.hxx>
 
 #include <SwGrammarMarkUp.hxx>
+#include <ndtxt.hxx>
+#include <txtfrm.hxx>
+
 #include <osl/diagnose.h>
 
 SwWrongArea::SwWrongArea( const OUString& rType, WrongListType listType,
@@ -659,4 +662,164 @@ void SwWrongList::Insert( const OUString& rType,
     maList.insert(aIter, SwWrongArea( rType, meType, xPropertyBag, nNewPos, nNewLen) );
 }
 
+namespace sw {
+
+WrongListIterator::WrongListIterator(SwTextFrame const& rFrame,
+        SwWrongList const* (SwTextNode::*pGetWrongList)() const)
+    : m_pGetWrongList(pGetWrongList)
+    , m_pMergedPara(rFrame.GetMergedPara())
+    , m_CurrentExtent(0)
+    , m_CurrentIndex(0)
+    , m_CurrentNodeIndex(0)
+    , m_pWrongList(m_pMergedPara
+                    ? nullptr
+                    : (rFrame.GetTextNodeFirst()->*pGetWrongList)())
+{
+}
+
+WrongListIterator::WrongListIterator(SwWrongList const& rWrongList)
+    : m_pGetWrongList(nullptr)
+    , m_pMergedPara(nullptr)
+    , m_CurrentExtent(0)
+    , m_CurrentIndex(0)
+    , m_CurrentNodeIndex(0)
+    , m_pWrongList(&rWrongList)
+{
+}
+
+bool WrongListIterator::Check(TextFrameIndex & rStart, TextFrameIndex & rLen)
+{
+    if (m_pMergedPara)
+    {
+        if (rStart < m_CurrentIndex)
+        {   // rewind
+            m_CurrentExtent = 0;
+            m_CurrentIndex = TextFrameIndex(0);
+            m_CurrentNodeIndex = TextFrameIndex(0);
+        }
+        while (m_CurrentExtent < m_pMergedPara->extents.size())
+        {
+            sw::Extent const& rExtent(m_pMergedPara->extents[m_CurrentExtent]);
+            if (rStart + rLen <= m_CurrentIndex)
+            {
+                return false;
+            }
+            else if (rStart < m_CurrentIndex)
+            {
+                rLen -= (m_CurrentIndex - rStart);
+                assert(0 < sal_Int32(rLen));
+                rStart = m_CurrentIndex;
+            }
+            if (m_CurrentIndex <= rStart &&
+                rStart < m_CurrentIndex + TextFrameIndex(rExtent.nEnd - rExtent.nStart))
+            {
+                SwWrongList const*const pWrongList((rExtent.pNode->*m_pGetWrongList)());
+                // found the extent containing start - first, call Check
+                sal_Int32 nStart(rStart - (m_CurrentIndex - m_CurrentNodeIndex));
+                sal_Int32 nLen(rLen); // upper bound; check it properly later
+                if (pWrongList && pWrongList->Check(nStart, nLen))
+                {
+                    // check if there's overlap with this extent
+                    if (rExtent.nStart <= nStart && nStart < rExtent.nEnd)
+                    {
+                        // yes - now compute end position / length
+                        sal_Int32 const nEnd(nStart + nLen);
+                        rStart = m_CurrentIndex + TextFrameIndex(nStart - rExtent.nStart);
+                        if (nEnd < rExtent.nEnd)
+                        {
+                            rLen = TextFrameIndex(nEnd - nStart);
+                        }
+                        else // have to search other extents for the end...
+                        {
+                            rLen = TextFrameIndex(rExtent.nEnd - nStart);
+                            for (size_t i = m_CurrentExtent + 1;
+                                 i < m_pMergedPara->extents.size(); ++i)
+                            {
+                                sw::Extent const& rExtentEnd(m_pMergedPara->extents[i]);
+                                if (rExtentEnd.pNode != rExtent.pNode
+                                    || nEnd <= rExtentEnd.nStart)
+                                {
+                                    break;
+                                }
+                                if (nEnd <= rExtentEnd.nEnd)
+                                {
+                                    rLen += TextFrameIndex(nEnd - rExtentEnd.nStart);
+                                    break;
+                                }
+                                rLen += TextFrameIndex(rExtentEnd.nEnd - rExtentEnd.nStart);
+                            }
+                        }
+                        return true;
+                    }
+                }
+            }
+            m_CurrentIndex += TextFrameIndex(rExtent.nEnd - rExtent.nStart);
+            ++m_CurrentExtent;
+            if (m_CurrentExtent < m_pMergedPara->extents.size() &&
+                rExtent.pNode != m_pMergedPara->extents[m_CurrentExtent].pNode)
+            {
+                m_CurrentNodeIndex = m_CurrentIndex; // reset
+            }
+        }
+        return false;
+    }
+    else if (m_pWrongList)
+    {
+        sal_Int32 nStart(rStart);
+        sal_Int32 nLen(rLen);
+        bool const bRet(m_pWrongList->Check(nStart, nLen));
+        rStart = TextFrameIndex(nStart);
+        rLen = TextFrameIndex(nLen);
+        return bRet;
+    }
+    return false;
+}
+
+const SwWrongArea*
+WrongListIterator::GetWrongElement(TextFrameIndex const nStart)
+{
+    if (m_pMergedPara)
+    {
+        if (nStart < m_CurrentIndex)
+        {   // rewind
+            m_CurrentExtent = 0;
+            m_CurrentIndex = TextFrameIndex(0);
+            m_CurrentNodeIndex = TextFrameIndex(0);
+        }
+        while (m_CurrentExtent < m_pMergedPara->extents.size())
+        {
+            sw::Extent const& rExtent(m_pMergedPara->extents[m_CurrentExtent]);
+            if (m_CurrentIndex <= nStart &&
+                nStart <= m_CurrentIndex + TextFrameIndex(rExtent.nEnd - rExtent.nStart))
+            {
+                // note: the returned object isn't wrapped because fntcache.cxx
+                // does not look at its positions, only its formatting props
+                SwWrongList const*const pWrongList((rExtent.pNode->*m_pGetWrongList)());
+                if (pWrongList)
+                {
+                    sal_Int16 const nPos(pWrongList->GetWrongPos(
+                        sal_Int32(nStart - (m_CurrentIndex - m_CurrentNodeIndex))));
+                    return pWrongList->GetElement(nPos);
+                }
+            }
+            m_CurrentIndex += TextFrameIndex(rExtent.nEnd - rExtent.nStart);
+            ++m_CurrentExtent;
+            if (m_CurrentExtent < m_pMergedPara->extents.size() &&
+                rExtent.pNode != m_pMergedPara->extents[m_CurrentExtent].pNode)
+            {
+                m_CurrentNodeIndex = m_CurrentIndex; // reset
+            }
+        }
+        return nullptr;
+    }
+    else if (m_pWrongList)
+    {
+        sal_Int16 const nPos(m_pWrongList->GetWrongPos(sal_Int32(nStart)));
+        return m_pWrongList->GetElement(nPos);
+    }
+    return nullptr;
+}
+
+} // namespace sw
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 5d4e37a19162ec174c1c41164a5f5916347889fd
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu Jun 7 17:37:00 2018 +0200

    sw_redlinehide: WrongListIterator
    
    Change-Id: Ie13119d456fa6fe3919871cc541a9ad927b5982e

diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx
index c45b14086a2a..ed1b86f36218 100644
--- a/sw/source/core/txtnode/fntcache.cxx
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -644,7 +644,7 @@ typedef std::vector< std::pair< sal_Int32, sal_Int32 > > SwForbidden;
 static void lcl_DrawLineForWrongListData(
     SwForbidden &rForbidden,
     const SwDrawTextInfo    &rInf,
-    const SwWrongList       *pWList,
+    sw::WrongListIterator *pWList,
     const CalcLinePosData   &rCalcLinePosData,
     const Size              &rPrtFontSize )
 {
@@ -715,10 +715,7 @@ static void lcl_DrawLineForWrongListData(
             Point aEnd;
             lcl_calcLinePos( rCalcLinePosData, aStart, aEnd, nNextStart, nNextEnd - nNextStart );
 
-            const sal_uInt16 wrongPos = pWList->GetWrongPos(nNextStart + rInf.GetIdx());
-
-            const SwWrongArea* wrongArea = pWList->GetElement(wrongPos);
-
+            SwWrongArea const*const wrongArea = pWList->GetWrongElement(nNextStart + rInf.GetIdx());
             if (wrongArea != nullptr)
             {
                 if (WRONGAREA_DASHED == wrongArea->mLineType)
commit 1ae14637ebb48b2d4d3215da223cd51a76fdcee1
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu Jun 7 17:34:36 2018 +0200

    sw_redlinehide: SwTextNode funcs
    
    Change-Id: I9b110159a21399c3b9d9f3f8c6566d6ab79eb42f

diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index 894f8c078635..d1a8801eb9c7 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -194,8 +194,11 @@ public:
     const SwWrongList* GetWrong() const;
     void SetGrammarCheck( SwGrammarMarkUp* pNew, bool bDelete = true );
     SwGrammarMarkUp* GetGrammarCheck();
+    // return SwWrongList because *function pointer* return values aren't covariant
+    SwWrongList const* GetGrammarCheck() const;
     void SetSmartTags( SwWrongList* pNew, bool bDelete = true );
     SwWrongList* GetSmartTags();
+    SwWrongList const* GetSmartTags() const;
     void TryCharSetExpandToNum(const SfxItemSet& pCharSet);
 
     /// End: Data collected during idle time
diff --git a/sw/source/core/txtnode/txtedt.cxx b/sw/source/core/txtnode/txtedt.cxx
index 1f1468b1429d..7a646fc2b8ed 100644
--- a/sw/source/core/txtnode/txtedt.cxx
+++ b/sw/source/core/txtnode/txtedt.cxx
@@ -2216,6 +2216,11 @@ SwGrammarMarkUp* SwTextNode::GetGrammarCheck()
     return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pGrammarCheck : nullptr;
 }
 
+SwWrongList const* SwTextNode::GetGrammarCheck() const
+{
+    return static_cast<SwWrongList const*>(const_cast<SwTextNode*>(this)->GetGrammarCheck());
+}
+
 void SwTextNode::SetSmartTags( SwWrongList* pNew, bool bDelete )
 {
     OSL_ENSURE( !pNew || SwSmartTagMgr::Get().IsSmartTagsEnabled(),
@@ -2236,6 +2241,11 @@ SwWrongList* SwTextNode::GetSmartTags()
     return m_pParaIdleData_Impl ? m_pParaIdleData_Impl->pSmartTags : nullptr;
 }
 
+SwWrongList const* SwTextNode::GetSmartTags() const
+{
+    return const_cast<SwWrongList const*>(const_cast<SwTextNode*>(this)->GetSmartTags());
+}
+
 void SwTextNode::SetWordCountDirty( bool bNew ) const
 {
     if ( m_pParaIdleData_Impl )
commit 6de7f83b6416764a04fcc731caf8725fcc8c99d8
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu Jun 7 10:31:33 2018 +0200

    porrst.cxx
    
    Change-Id: Ic3ee9d616a81751b4bb314a5b87d0b2adf3f8e58

diff --git a/sw/source/core/text/porrst.cxx b/sw/source/core/text/porrst.cxx
index 5631e8434ce0..24778b6ec9d6 100644
--- a/sw/source/core/text/porrst.cxx
+++ b/sw/source/core/text/porrst.cxx
@@ -287,7 +287,7 @@ bool SwTextFrame::FormatEmpty()
     // sw_redlinehide: just disable FormatEmpty optimisation for now
     if (HasFollow() || GetMergedPara() || GetTextNodeFirst()->GetpSwpHints() ||
         nullptr != GetTextNodeForParaProps()->GetNumRule() ||
-        GetTextNode()->HasHiddenCharAttribute( true ) ||
+        GetTextNodeFirst()->HasHiddenCharAttribute(true) ||
          IsInFootnote() || ( HasPara() && GetPara()->IsPrepMustFit() ) )
         return false;
     const SwAttrSet& aSet = GetTextNodeForParaProps()->GetSwAttrSet();
commit 4e05002a48fff2b36eb5adad8bbe94dba7f93119
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu Jun 7 10:27:52 2018 +0200

    sw_redlinehide: convert spelling SwTextFrame funcs called by DoIdleJob_
    
    These currently get passed the current shell cursor position, which
    seems quite pointless as the caller DoIdleJob_ can handle that case
    in one place.
    
    Instead, pass in the actual node that should be checked, since the
    SwTextFrame can have multiple nodes now.
    
    Change-Id: Id7a8a7a2a5a3eaeb700963eff5147d37b194a953

diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index f6fbb686903e..98a18f7ed8ad 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -280,14 +280,14 @@ public:
      */
     void Init();
 
-    /// Is called by FormatSpelling()
-    SwRect AutoSpell_( const SwContentNode*, sal_Int32 );
+    /// Is called by DoIdleJob_() and ExecSpellPopup()
+    SwRect AutoSpell_(SwTextNode &, sal_Int32);
 
-    /// Is called by FormatSpelling()
-    SwRect SmartTagScan();
+    /// Is called by DoIdleJob_()
+    SwRect SmartTagScan(SwTextNode &);
 
-    /// Is called by CollectAutoCmplWords()
-    void CollectAutoCmplWrds( SwContentNode const * , sal_Int32 );
+    /// Is called by DoIdleJob_()
+    void CollectAutoCmplWrds(SwTextNode &, sal_Int32);
 
     /**
      * Returns the screen position of rPos. The values are relative to the upper
diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx
index e98f19ccb771..761a85c51741 100644
--- a/sw/source/core/layout/layact.cxx
+++ b/sw/source/core/layout/layact.cxx
@@ -1849,7 +1849,7 @@ bool SwLayIdle::DoIdleJob_( const SwContentFrame *pCnt, IdleJobType eJob )
 
     SwTextFrame const*const pTextFrame(static_cast<SwTextFrame const*>(pCnt));
     // sw_redlinehide: spell check only the nodes with visible content?
-    const SwTextNode* pTextNode = pTextFrame->GetTextNodeForParaProps();
+    SwTextNode* pTextNode = const_cast<SwTextNode*>(pTextFrame->GetTextNodeForParaProps());
 
     bool bProcess = false;
     for (size_t i = 0; pTextNode; )
@@ -1895,6 +1895,7 @@ bool SwLayIdle::DoIdleJob_( const SwContentFrame *pCnt, IdleJobType eJob )
 
     if( bProcess )
     {
+        assert(pTextNode);
         SwViewShell *pSh = pImp->GetShell();
         if( COMPLETE_STRING == nTextPos )
         {
@@ -1909,12 +1910,15 @@ bool SwLayIdle::DoIdleJob_( const SwContentFrame *pCnt, IdleJobType eJob )
                 }
             }
         }
+        sal_Int32 const nPos((pContentNode && pTextNode == pContentNode)
+                ? nTextPos
+                : COMPLETE_STRING);
 
         switch ( eJob )
         {
             case ONLINE_SPELLING :
             {
-                SwRect aRepaint( const_cast<SwTextFrame*>(static_cast<const SwTextFrame*>(pCnt))->AutoSpell_( pContentNode, nTextPos ) );
+                SwRect aRepaint( const_cast<SwTextFrame*>(pTextFrame)->AutoSpell_(*pTextNode, nPos) );
                 // PENDING should stop idle spell checking
                 bPageValid = bPageValid && (SwTextNode::WrongState::TODO != pTextNode->GetWrongDirty());
                 if ( aRepaint.HasArea() )
@@ -1924,7 +1928,7 @@ bool SwLayIdle::DoIdleJob_( const SwContentFrame *pCnt, IdleJobType eJob )
                 break;
             }
             case AUTOCOMPLETE_WORDS :
-                const_cast<SwTextFrame*>(static_cast<const SwTextFrame*>(pCnt))->CollectAutoCmplWrds( pContentNode, nTextPos );
+                const_cast<SwTextFrame*>(pTextFrame)->CollectAutoCmplWrds(*pTextNode, nPos);
                 // note: bPageValid remains true here even if the cursor
                 // position is skipped, so no PENDING state needed currently
                 if (Application::AnyInput(VCL_INPUT_ANY & VclInputFlags(~VclInputFlags::TIMER)))
@@ -1942,7 +1946,7 @@ bool SwLayIdle::DoIdleJob_( const SwContentFrame *pCnt, IdleJobType eJob )
             case SMART_TAGS :
             {
                 try {
-                    const SwRect aRepaint( const_cast<SwTextFrame*>(static_cast<const SwTextFrame*>(pCnt))->SmartTagScan() );
+                    const SwRect aRepaint( const_cast<SwTextFrame*>(pTextFrame)->SmartTagScan(*pTextNode) );
                     bPageValid = bPageValid && !pTextNode->IsSmartTagDirty();
                     if ( aRepaint.HasArea() )
                         pImp->GetShell()->InvalidateWindows( aRepaint );
diff --git a/sw/source/core/txtnode/txtedt.cxx b/sw/source/core/txtnode/txtedt.cxx
index 7523293b45ea..1f1468b1429d 100644
--- a/sw/source/core/txtnode/txtedt.cxx
+++ b/sw/source/core/txtnode/txtedt.cxx
@@ -200,14 +200,16 @@ lcl_MaskRedlinesAndHiddenText( const SwTextNode& rNode, OUStringBuffer& rText,
 /**
  * Used for spell checking. Calculates a rectangle for repaint.
  */
-static SwRect lcl_CalculateRepaintRect( SwTextFrame& rTextFrame, sal_Int32 nChgStart, sal_Int32 nChgEnd )
+static SwRect lcl_CalculateRepaintRect(
+        SwTextFrame & rTextFrame, SwTextNode & rNode,
+        sal_Int32 const nChgStart, sal_Int32 const nChgEnd)
 {
     SwRect aRect;
 
-    SwTextNode *pNode = rTextFrame.GetTextNode();
+    TextFrameIndex const iChgStart(rTextFrame.MapModelToView(&rNode, nChgStart));
+    TextFrameIndex const iChgEnd(rTextFrame.MapModelToView(&rNode, nChgEnd));
 
-    SwNodeIndex aNdIdx( *pNode );
-    SwPosition aPos( aNdIdx, SwIndex( pNode, nChgEnd ) );
+    SwPosition aPos( rNode, nChgEnd );
     SwCursorMoveState aTmpState( MV_NONE );
     aTmpState.m_b2Lines = true;
     rTextFrame.GetCharRect( aRect, aPos, &aTmpState );
@@ -217,7 +219,7 @@ static SwRect lcl_CalculateRepaintRect( SwTextFrame& rTextFrame, sal_Int32 nChgS
     const SwTextFrame *pEndFrame = &rTextFrame;
 
     while( pEndFrame->HasFollow() &&
-           nChgEnd >= pEndFrame->GetFollow()->GetOfst() )
+           iChgEnd >= pEndFrame->GetFollow()->GetOfst())
         pEndFrame = pEndFrame->GetFollow();
 
     if ( pEnd2Pos )
@@ -236,7 +238,7 @@ static SwRect lcl_CalculateRepaintRect( SwTextFrame& rTextFrame, sal_Int32 nChgS
 
     aTmpState.m_p2Lines = nullptr;
     SwRect aTmp;
-    aPos = SwPosition( aNdIdx, SwIndex( pNode, nChgStart ) );
+    aPos = SwPosition( rNode, nChgStart );
     rTextFrame.GetCharRect( aTmp, aPos, &aTmpState );
 
     // i63141: GetCharRect(..) could cause a formatting,
@@ -244,11 +246,11 @@ static SwRect lcl_CalculateRepaintRect( SwTextFrame& rTextFrame, sal_Int32 nChgS
     // => we have to reinit pStartFrame and pEndFrame after the formatting
     const SwTextFrame* pStartFrame = &rTextFrame;
     while( pStartFrame->HasFollow() &&
-           nChgStart >= pStartFrame->GetFollow()->GetOfst() )
+           iChgStart >= pStartFrame->GetFollow()->GetOfst())
         pStartFrame = pStartFrame->GetFollow();
     pEndFrame = pStartFrame;
     while( pEndFrame->HasFollow() &&
-           nChgEnd >= pEndFrame->GetFollow()->GetOfst() )
+           iChgEnd >= pEndFrame->GetFollow()->GetOfst())
         pEndFrame = pEndFrame->GetFollow();
 
     // information about start of repaint area
@@ -1266,11 +1268,12 @@ bool SwTextNode::Convert( SwConversionArgs &rArgs )
 }
 
 // Note: this is a clone of SwTextNode::Spell, so keep them in sync when fixing things!
-SwRect SwTextFrame::AutoSpell_( const SwContentNode* pActNode, sal_Int32 nActPos )
+SwRect SwTextFrame::AutoSpell_(SwTextNode & rNode, sal_Int32 nActPos)
 {
     SwRect aRect;
-    SwTextNode *pNode = GetTextNode();
-    if( pNode != pActNode || !nActPos )
+    assert(sw::FrameContainsNode(*this, rNode.GetIndex()));
+    SwTextNode *const pNode(&rNode);
+    if (!nActPos)
         nActPos = COMPLETE_STRING;
 
     SwAutoCompleteWord& rACW = SwDoc::GetAutoCompleteWords();
@@ -1281,7 +1284,7 @@ SwRect SwTextFrame::AutoSpell_( const SwContentNode* pActNode, sal_Int32 nActPos
     const bool bRestoreString =
         lcl_MaskRedlinesAndHiddenText(*pNode, buf, 0, pNode->GetText().getLength());
     if (bRestoreString)
-    {   // ??? UGLY: is it really necessary to modify m_Text here?
+    {   // ??? UGLY: is it really necessary to modify m_Text here? just for GetLang()?
         pNode->m_Text = buf.makeStringAndClear();
     }
 
@@ -1415,7 +1418,7 @@ SwRect SwTextFrame::AutoSpell_( const SwContentNode* pActNode, sal_Int32 nActPos
 
         if( nChgStart < nChgEnd )
         {
-            aRect = lcl_CalculateRepaintRect( *this, nChgStart, nChgEnd );
+            aRect = lcl_CalculateRepaintRect(*this, rNode, nChgStart, nChgEnd);
 
             // fdo#71558 notify misspelled word to accessibility
             SwViewShell* pViewSh = getRootFrame() ? getRootFrame()->GetCurrShell() : nullptr;
@@ -1451,10 +1454,12 @@ SwRect SwTextFrame::AutoSpell_( const SwContentNode* pActNode, sal_Int32 nActPos
 
     @return SwRect Repaint area
 */
-SwRect SwTextFrame::SmartTagScan()
+SwRect SwTextFrame::SmartTagScan(SwTextNode & rNode)
 {
     SwRect aRet;
-    SwTextNode *pNode = GetTextNode();
+
+    assert(sw::FrameContainsNode(*this, rNode.GetIndex()));
+    SwTextNode *const pNode = &rNode;
     const OUString& rText = pNode->GetText();
 
     // Iterate over language portions
@@ -1556,7 +1561,7 @@ SwRect SwTextFrame::SmartTagScan()
         if ( nBegin < nEnd && ( 0 != nNumberOfRemovedEntries ||
                                 0 != nNumberOfInsertedEntries ) )
         {
-            aRet = lcl_CalculateRepaintRect( *this, nBegin, nEnd );
+            aRet = lcl_CalculateRepaintRect(*this, rNode, nBegin, nEnd);
         }
     }
     else
@@ -1565,10 +1570,11 @@ SwRect SwTextFrame::SmartTagScan()
     return aRet;
 }
 
-void SwTextFrame::CollectAutoCmplWrds( SwContentNode const * pActNode, sal_Int32 nActPos )
+void SwTextFrame::CollectAutoCmplWrds(SwTextNode & rNode, sal_Int32 nActPos)
 {
-    SwTextNode *pNode = GetTextNode();
-    if( pNode != pActNode || !nActPos )
+    assert(sw::FrameContainsNode(*this, rNode.GetIndex()));
+    SwTextNode *const pNode(&rNode);
+    if (!nActPos)
         nActPos = COMPLETE_STRING;
 
     SwDoc* pDoc = pNode->GetDoc();
diff --git a/sw/source/uibase/uiview/viewling.cxx b/sw/source/uibase/uiview/viewling.cxx
index 0f646e637c5e..1e0b389aefb0 100644
--- a/sw/source/uibase/uiview/viewling.cxx
+++ b/sw/source/uibase/uiview/viewling.cxx
@@ -656,7 +656,8 @@ bool SwView::ExecSpellPopup(const Point& rPt)
                                         &rPt, &aPoint, false);
                 if (pContentFrame)
                 {
-                    SwRect aRepaint(static_cast<SwTextFrame*>(pContentFrame)->AutoSpell_(nullptr, 0));
+                    SwRect aRepaint(static_cast<SwTextFrame*>(pContentFrame)->AutoSpell_(
+                        *pCursor->GetContentNode()->GetTextNode(), 0));
                     if (aRepaint.HasArea())
                         m_pWrtShell->InvalidateWindows(aRepaint);
                 }
commit 3987774559e7a8add261339b74ab7c252128d833
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu Jun 7 10:14:55 2018 +0200

    fix pormulti
    
    Change-Id: If715320806b43b71ba8469599a202963d2b29bd1

diff --git a/sw/source/core/text/pormulti.cxx b/sw/source/core/text/pormulti.cxx
index 7d671961dff0..13b7207b71d9 100644
--- a/sw/source/core/text/pormulti.cxx
+++ b/sw/source/core/text/pormulti.cxx
@@ -955,10 +955,10 @@ SwMultiCreator* SwTextSizeInfo::GetMultiCreator(TextFrameIndex &rPos,
 
     // need the node that contains input rPos
     std::pair<SwTextNode const*, sal_Int32> startPos(m_pFrame->MapViewToModel(rPos));
-    const SvxCharRotateItem* pActiveRotateItem = nullptr;
-    const SfxPoolItem* pNodeRotateItem;
-    const SvxTwoLinesItem* pActiveTwoLinesItem = nullptr;
-    const SfxPoolItem* pNodeTwoLinesItem;
+    const SvxCharRotateItem* pActiveRotateItem(nullptr);
+    const SfxPoolItem* pNodeRotateItem(nullptr);
+    const SvxTwoLinesItem* pActiveTwoLinesItem(nullptr);
+    const SfxPoolItem* pNodeTwoLinesItem(nullptr);
     SwTextAttr const* pActiveTwoLinesHint(nullptr);
     SwTextAttr const* pActiveRotateHint(nullptr);
     const SwTextAttr *pRuby = nullptr;
commit 28795bf964dcb9e7f5a1207c482f15d3877943de
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Wed Jun 6 17:24:55 2018 +0200

    sw_redlinehide: itrpaint.cxx
    
    Change-Id: Ic57847eee777bb13413a4b874e2a8a43e898f6dc

diff --git a/sw/source/core/text/itrpaint.cxx b/sw/source/core/text/itrpaint.cxx
index 295765d7f809..7e2458fcb2b9 100644
--- a/sw/source/core/text/itrpaint.cxx
+++ b/sw/source/core/text/itrpaint.cxx
@@ -596,8 +596,8 @@ void SwTextPainter::CheckSpecialUnderline( const SwLinePortion* pPor,
     {
         // here starts the algorithm for calculating the underline font
         SwScriptInfo& rScriptInfo = GetInfo().GetParaPortion()->GetScriptInfo();
-        SwAttrIter aIter( *GetInfo().GetTextFrame()->GetTextNode(),
-                          rScriptInfo );
+        SwAttrIter aIter(*GetInfo().GetTextFrame()->GetTextNodeFirst(),
+                         rScriptInfo, GetTextFrame());
 
         TextFrameIndex nTmpIdx = nIndx;
         sal_uLong nSumWidth = 0;
commit d335c040950860a1bab2f59068775c74b5bbd69e
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Wed Jun 6 17:23:49 2018 +0200

    sw_redlinehide: SwAttrIter direct ctor gets a SwTextFrame arg
    
    Change-Id: I904cb955f0bc8dc1f92612b47dc129922865c198

diff --git a/sw/source/core/text/itratr.hxx b/sw/source/core/text/itratr.hxx
index 016f97c333bc..c47be02230d8 100644
--- a/sw/source/core/text/itratr.hxx
+++ b/sw/source/core/text/itratr.hxx
@@ -71,7 +71,7 @@ private:
 protected:
     void Chg( SwTextAttr const *pHt );
     void Rst( SwTextAttr const *pHt );
-    void CtorInitAttrIter(SwTextNode& rTextNode, SwScriptInfo& rScrInf, SwTextFrame * pFrame = nullptr);
+    void CtorInitAttrIter(SwTextNode& rTextNode, SwScriptInfo& rScrInf, SwTextFrame const* pFrame = nullptr);
     explicit SwAttrIter(SwTextNode const * pTextNode)
         : m_pViewShell(nullptr)
         , m_pFont(nullptr)
@@ -93,7 +93,7 @@ public:
     /// All subclasses of this always have a SwTextFrame passed to the
     /// constructor, but SwAttrIter itself may be created without a
     /// SwTextFrame in certain special cases via this ctor here
-    SwAttrIter( SwTextNode& rTextNode, SwScriptInfo& rScrInf )
+    SwAttrIter(SwTextNode& rTextNode, SwScriptInfo& rScrInf, SwTextFrame const*const pFrame = nullptr)
         : m_pViewShell(nullptr)
         , m_pFont(nullptr)
         , m_pScriptInfo(nullptr)
@@ -103,7 +103,9 @@ public:
         , m_nPropFont(0)
         , m_pTextNode(&rTextNode)
         , m_pMergedPara(nullptr)
-        { CtorInitAttrIter( rTextNode, rScrInf ); }
+    {
+        CtorInitAttrIter(rTextNode, rScrInf, pFrame);
+    }
 
     virtual ~SwAttrIter();
 
diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx
index 9ae23cb69772..afebb9418789 100644
--- a/sw/source/core/text/redlnitr.cxx
+++ b/sw/source/core/text/redlnitr.cxx
@@ -189,7 +189,7 @@ void SwAttrIter::InitFontAndAttrHandler(SwTextNode const& rTextNode,
 }
 
 void SwAttrIter::CtorInitAttrIter(SwTextNode & rTextNode,
-        SwScriptInfo & rScriptInfo, SwTextFrame *const pFrame)
+        SwScriptInfo & rScriptInfo, SwTextFrame const*const pFrame)
 {
     // during HTML-Import it can happen, that no layout exists
     SwRootFrame* pRootFrame = rTextNode.getIDocumentLayoutAccess().GetCurrentLayout();
commit f8b9ac036518d67a874699feac4eb68d91f40f08
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Tue Jun 5 15:49:21 2018 +0200

    fix sw_redlinehide: use WriterMultiListener to connect SwTextFrame
    
    Unfortunately there's still a few GetTextNode() left and those will
    crash now...
    
    Change-Id: I3318b422eaa8108ada5978f09f3c2801f4442ce2

diff --git a/sw/source/core/layout/ssfrm.cxx b/sw/source/core/layout/ssfrm.cxx
index 3012bd954a94..7be4a5615a5d 100644
--- a/sw/source/core/layout/ssfrm.cxx
+++ b/sw/source/core/layout/ssfrm.cxx
@@ -443,7 +443,10 @@ void SwTextFrame::RegisterToNode(SwTextNode & rNode)
 {
     assert(&rNode != GetDep());
     m_pMergedPara = sw::CheckParaRedlineMerge(*this, rNode);
-    rNode.Add( this );
+    if (!m_pMergedPara)
+    {
+        rNode.Add(this);
+    }
 }
 
 void SwLayoutFrame::DestroyImpl()
diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx
index 09e72ea5a75d..9ae23cb69772 100644
--- a/sw/source/core/text/redlnitr.cxx
+++ b/sw/source/core/text/redlnitr.cxx
@@ -123,6 +123,7 @@ CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode)
     {
         pRet->listener.StartListening(pTmp);
     }
+    rFrame.EndListeningAll();
     return pRet;
 }
 
commit 5cabaa3c2e4f862544280018846121cc1a7727cb
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Mon May 7 17:44:44 2018 +0200

    hack in Show - not sure if...
    
    Change-Id: I6ca49cfe9c61b3562e87ca994b284e056c2bab54

diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx
index a7a56c6f81aa..ad1a5925d644 100644
--- a/sw/source/core/doc/docredln.cxx
+++ b/sw/source/core/doc/docredln.cxx
@@ -60,6 +60,7 @@
 #include <txtfld.hxx>
 
 #include <flowfrm.hxx>
+#include <txtfrm.hxx>
 
 using namespace com::sun::star;
 
@@ -1672,6 +1673,20 @@ void SwRangeRedline::MoveFromSection(size_t nMyPos)
             *pItem = *Start();
         for( auto& pItem : aBehindArr )
             *pItem = *End();
+
+        // sw_redlinehide: assume that Show will only be called by filters;
+        // when it is called, ensure that no MergedPara instance survives
+        for (SwNodeIndex node = Start()->nNode; node.GetIndex() <= End()->nNode.GetIndex(); ++node)
+        {
+            if (SwTextNode const*const pNode = node.GetNode().GetTextNode())
+            {
+                SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pNode);
+                for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
+                {
+                    pFrame->SetMergedPara(nullptr);
+                }
+            }
+        }
     }
     else
         InvalidateRange();
commit e275778195654d6b548f278494689e4c4d1a7c72
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu May 17 13:00:33 2018 +0200

    sw_redlinehide: let the Show menu item toggle new mode
    
    Change-Id: I1201e84b231be17e6a5ec2294acfb1e3111c9ada

diff --git a/sw/source/uibase/uiview/view2.cxx b/sw/source/uibase/uiview/view2.cxx
index 90ca68a0f404..1d57aefdd498 100644
--- a/sw/source/uibase/uiview/view2.cxx
+++ b/sw/source/uibase/uiview/view2.cxx
@@ -140,6 +140,7 @@
 #include <vcl/settings.hxx>
 #include <i18nutil/searchopt.hxx>
 #include <paratr.hxx>
+#include <rootfrm.hxx>
 
 #include <memory>
 
@@ -639,7 +640,15 @@ void SwView::Execute(SfxRequest &rReq)
                 if( static_cast<const SfxBoolItem*>(pItem)->GetValue() )
                     nMode |= RedlineFlags::ShowDelete;
 
-                m_pWrtShell->SetRedlineFlagsAndCheckInsMode( nMode );
+                if (getenv("SW_REDLINEHIDE")) // TODO...
+                {
+                    m_pWrtShell->GetLayout()->SetHideRedlines(
+                        !static_cast<const SfxBoolItem*>(pItem)->GetValue());
+                    if (m_pWrtShell->IsRedlineOn())
+                        m_pWrtShell->SetInsMode();
+                }
+                else
+                    m_pWrtShell->SetRedlineFlagsAndCheckInsMode( nMode );
             }
             break;
         case FN_MAILMERGE_SENDMAIL_CHILDWINDOW:
commit 13ad63f11dc84c3e5e116c1e8089ac88e03bfb79
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Thu May 17 14:16:27 2018 +0200

    sw_redlinehide: very incomplete impl. of SwRootFrame::SetHideRedlines()
    
    Change-Id: Icff1b1aac20a0a6d3f957e7025f6a08a6d0edbee

diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index a25bb8d7bb9f..cdce7870a536 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -4171,6 +4171,53 @@ void SwRootFrame::SetHideRedlines(bool const bHideRedlines)
         return;
     }
     mbHideRedlines = bHideRedlines;
+    SwNodes const& rNodes(GetFormat()->GetDoc()->GetNodes());
+    // Hide->Show: clear MergedPara, create frames
+    // Show->Hide: call CheckParaRedlineMerge, delete frames
+    // TODO how to traverse
+    // * via layout
+    //      - but that won't find nodes that don't have frames in ->Show case
+    // * via nodes
+    //      - what about special sections before content? flys? footnotes?
+    //        is order of these predictable? flys not anchored in content?
+    // * ideally should call something existing that tries to create everything?
+    //      - is that done automatically somewhere already?
+    // * other direction ->Hide - delete frames!
+    // in-order traversal should init flags in nodes *before* the nodes are found
+    for (sal_uLong i = 0; i < rNodes.Count(); ++i)
+    {
+        SwNode *const pNode(rNodes[i]);
+        if (pNode->IsTextNode())
+        {
+            SwTextNode & rTextNode(*pNode->GetTextNode());
+            SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(rTextNode);
+            std::vector<SwTextFrame*> frames;
+            for (SwTextFrame * pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
+            {
+                if (pFrame->getRootFrame() == this)
+                {
+                    frames.push_back(pFrame);
+                }
+            }
+            // this messes with pRegisteredIn so do it outside SwIterator
+            for (SwTextFrame * pFrame : frames)
+            {
+                if (mbHideRedlines && pNode->IsCreateFrameWhenHidingRedlines())
+                {
+                    pFrame->SetMergedPara(CheckParaRedlineMerge(*pFrame, rTextNode));
+                }
+                else
+                {
+                    if (pFrame->GetMergedPara())
+                    {
+                        pFrame->SetMergedPara(nullptr);
+                        rTextNode.DelFrames(); // FIXME only those in this layout?
+                    }
+                }
+            }
+        }
+    }
+    InvalidateAllContent(SwInvalidateFlags::Size); // ??? TODO what to invalidate?
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list