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

Michael Stahl Michael.Stahl at cib.de
Wed May 30 16:44:55 UTC 2018


Rebased ref, commits from common ancestor:
commit 48aa937ddd3286b030c8d1ec05e9b8d8aa1c2cbc
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Wed May 30 18:10:44 2018 +0200

    sw_redlinehide: adapt SwFrame::InvalidatePage()
    
    Change-Id: I38f2b4b34e3c740f94f2d6564e1a923a8ee4aaf8

diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index 965b755bc79f..254c6cd3c4e8 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -678,9 +678,33 @@ void SwFrame::InvalidatePage( const SwPageFrame *pPage ) const
         }
         pRoot->SetIdleFlags();
 
-        const SwTextNode *pTextNode = dynamic_cast< const SwTextNode * >(GetDep());
-        if (pTextNode && pTextNode->IsGrammarCheckDirty())
-            pRoot->SetNeedGrammarCheck( true );
+        if (IsTextFrame())
+        {
+            SwTextFrame const*const pText(static_cast<SwTextFrame const*>(this));
+            if (sw::MergedPara const*const pMergedPara = pText->GetMergedPara())
+            {
+                SwTextNode const* pNode(nullptr);
+                for (auto const& e : pMergedPara->extents)
+                {
+                    if (e.pNode != pNode)
+                    {
+                        pNode = e.pNode;
+                        if (pNode->IsGrammarCheckDirty())
+                        {
+                            pRoot->SetNeedGrammarCheck( true );
+                            break;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                if (pText->GetTextNodeFirst()->IsGrammarCheckDirty())
+                {
+                    pRoot->SetNeedGrammarCheck( true );
+                }
+            }
+        }
     }
 }
 
commit 24254f63947cf7d857cd868896ede41d5bc482b8
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Wed May 30 16:41:11 2018 +0200

    sw_redlinehide: SwTextFrame::IsHiddenNow() needs some work
    
    Iterating the fields here looks a bit expensive, maybe it would be
    better to check the ViewOptions first...
    
    Change-Id: I41830e89a4fd683eee35bd2b0901fb9fb121b51c

diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index c6f799db460b..cc6370e40bcb 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -75,6 +75,7 @@
 #include <numrule.hxx>
 #include <swtable.hxx>
 #include <fldupde.hxx>
+#include <docufld.hxx>
 #include <IGrammarContact.hxx>
 #include <calbck.hxx>
 #include <ftnidx.hxx>
@@ -937,8 +938,45 @@ bool SwTextFrame::IsHiddenNow() const
         return true;
     }
 
-    const bool bHiddenCharsHidePara = GetTextNode()->HasHiddenCharAttribute( true );
-    const bool bHiddenParaField = GetTextNode()->HasHiddenParaField();
+    bool bHiddenCharsHidePara(false);
+    bool bHiddenParaField(false);
+    if (m_pMergedPara)
+    {
+        TextFrameIndex nHiddenStart(COMPLETE_STRING);
+        TextFrameIndex nHiddenEnd(0);
+        assert(GetScriptInfo());
+        if (GetScriptInfo()->GetBoundsOfHiddenRange(TextFrameIndex(0),
+                    nHiddenStart, nHiddenEnd))
+        {
+            if (TextFrameIndex(0) == nHiddenStart &&
+                TextFrameIndex(GetText().getLength()) <= nHiddenEnd)
+            {
+                bHiddenCharsHidePara = true;
+            }
+        }
+        sw::MergedAttrIter iter(*this);
+        SwTextNode const* pNode(nullptr);
+        for (SwTextAttr const* pHint = iter.NextAttr(&pNode); pHint; pHint = iter.NextAttr(&pNode))
+        {
+            if (pHint->Which() == RES_TXTATR_FIELD)
+            {
+                const SwFormatField& rField = pHint->GetFormatField();
+                if (SwFieldIds::HiddenPara == rField.GetField()->GetTyp()->Which())
+                {
+                    if (static_cast<const SwHiddenParaField*>(rField.GetField())->IsHidden())
+                    {
+                        bHiddenParaField = true;
+                    }
+                    break;
+                }
+            }
+        }
+    }
+    else
+    {
+        bHiddenCharsHidePara = GetTextNode()->HasHiddenCharAttribute( true );
+        bHiddenParaField = GetTextNode()->HasHiddenParaField();
+    }
     const SwViewShell* pVsh = getRootFrame()->GetCurrShell();
 
     if ( pVsh && ( bHiddenCharsHidePara || bHiddenParaField ) )
commit a29b1df557c51987dc745daf562dc07813bd5a44
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Wed May 30 16:05:19 2018 +0200

    sw_redlinehide: SwTextFrame::HideAndShowObjects()
    
    Let it get the SwTextNode from the fly's anchor position, instead of
    from SwTextFrame.
    
    Change-Id: I833db32b2d7dd689c04fe93d75910364b6b91a3c

diff --git a/sw/inc/anchoredobject.hxx b/sw/inc/anchoredobject.hxx
index 1999354deb79..7e9c89a31d41 100644
--- a/sw/inc/anchoredobject.hxx
+++ b/sw/inc/anchoredobject.hxx
@@ -23,6 +23,7 @@
 #include "swrect.hxx"
 #include <libxml/xmlwriter.h>
 
+struct SwPosition;
 class SdrObject;
 class SwFrame;
 class SwLayoutFrame;
@@ -168,7 +169,7 @@ class SW_DLLPUBLIC SwAnchoredObject
         // object positioning
         friend bool sw_HideObj( const SwTextFrame& _rFrame,
                                  const RndStdIds _eAnchorType,
-                                 const sal_Int32 _nObjAnchorPos,
+                                 SwPosition const& rAnchorPos,
                                  SwAnchoredObject* _pAnchoredObj );
     protected:
         SwAnchoredObject();
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 91e1761a9b3a..c6f799db460b 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -1003,7 +1003,7 @@ void SwTextFrame::HideFootnotes(TextFrameIndex const nStart, TextFrameIndex cons
  */
 bool sw_HideObj( const SwTextFrame& _rFrame,
                   const RndStdIds _eAnchorType,
-                  const sal_Int32 _nObjAnchorPos,
+                  SwPosition const& rAnchorPos,
                   SwAnchoredObject* _pAnchoredObj )
 {
     bool bRet( true );
@@ -1017,13 +1017,16 @@ bool sw_HideObj( const SwTextFrame& _rFrame,
               pIDSA->get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION) &&
              _rFrame.IsInDocBody() && !_rFrame.FindNextCnt() )
         {
-            const OUString &rStr = _rFrame.GetTextNode()->GetText();
-            const sal_Unicode cAnchorChar = _nObjAnchorPos < rStr.getLength() ? rStr[_nObjAnchorPos] : 0;
+            SwTextNode const& rNode(*rAnchorPos.nNode.GetNode().GetTextNode());
+            assert(_rFrame.GetMergedPara() || &rNode == _rFrame.GetRegisteredIn()); // simple consistency check
+            sal_Int32 const nObjAnchorPos(rAnchorPos.nContent.GetIndex());
+            const sal_Unicode cAnchorChar = nObjAnchorPos < rNode.Len()
+                ? rNode.GetText()[nObjAnchorPos]
+                : 0;
             if (cAnchorChar == CH_TXTATR_BREAKWORD)
             {
                 const SwTextAttr* const pHint(
-                    _rFrame.GetTextNode()->GetTextAttrForCharAt(_nObjAnchorPos,
-                        RES_TXTATR_FLYCNT) );
+                    rNode.GetTextAttrForCharAt(nObjAnchorPos, RES_TXTATR_FLYCNT));
                 if ( pHint )
                 {
                     const SwFrameFormat* pFrameFormat =
@@ -1074,9 +1077,8 @@ void SwTextFrame::HideAndShowObjects()
                 SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall());
                 // under certain conditions
                 const RndStdIds eAnchorType( pContact->GetAnchorId() );
-                const sal_Int32 nObjAnchorPos = pContact->GetContentAnchorIndex().GetIndex();
                 if ((eAnchorType != RndStdIds::FLY_AT_CHAR) ||
-                    sw_HideObj( *this, eAnchorType, nObjAnchorPos,
+                    sw_HideObj(*this, eAnchorType, pContact->GetContentAnchor(),
                                  i ))
                 {
                     pContact->MoveObjToInvisibleLayer( pObj );
@@ -1087,7 +1089,6 @@ void SwTextFrame::HideAndShowObjects()
         {
             // paragraph is visible, but can contain hidden text portion.
             // first we check if objects are allowed to be hidden:
-            const SwTextNode& rNode = *GetTextNode();
             const SwViewShell* pVsh = getRootFrame()->GetCurrShell();
             const bool bShouldBeHidden = !pVsh || !pVsh->GetWin() ||
                                          !pVsh->GetViewOptions()->IsShowHiddenChar();
@@ -1111,12 +1112,16 @@ void SwTextFrame::HideAndShowObjects()
                 {
                     sal_Int32 nHiddenStart;
                     sal_Int32 nHiddenEnd;
-                    const sal_Int32 nObjAnchorPos = pContact->GetContentAnchorIndex().GetIndex();
-                    SwScriptInfo::GetBoundsOfHiddenRange( rNode, nObjAnchorPos, nHiddenStart, nHiddenEnd );
+                    const SwPosition& rAnchor = pContact->GetContentAnchor();
+                    SwScriptInfo::GetBoundsOfHiddenRange(
+                        *rAnchor.nNode.GetNode().GetTextNode(),
+                        rAnchor.nContent.GetIndex(), nHiddenStart, nHiddenEnd);
                     // Under certain conditions
                     if ( nHiddenStart != COMPLETE_STRING && bShouldBeHidden &&
-                         sw_HideObj( *this, eAnchorType, nObjAnchorPos, i ) )
+                        sw_HideObj(*this, eAnchorType, rAnchor, i))
+                    {
                         pContact->MoveObjToInvisibleLayer( pObj );
+                    }
                     else
                         pContact->MoveObjToVisibleLayer( pObj );
                 }
commit 1891b027e8dcb8a4f82a558b65dc944f89cbb88f
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Wed May 30 14:43:11 2018 +0200

    sw_redlinehide: SwTextFrame::DestroyImpl() needs to remove more
    
    ... footnotes for merged paragraphs.
    
    Change-Id: Ia32a2a776cb3a383f9ea0ecf51dcea872d6378be

diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index fdab5fb6bf63..91e1761a9b3a 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -599,34 +599,60 @@ SwTextFrame::SwTextFrame(SwTextNode * const pNode, SwFrame* pSib )
     mnFrameType = SwFrameType::Txt;
 }
 
+static void RemoveFootnotesForNode(
+        SwTextFrame const& rTextFrame, SwTextNode const& rTextNode)
+{
+    const SwFootnoteIdxs &rFootnoteIdxs = rTextNode.GetDoc()->GetFootnoteIdxs();
+    size_t nPos = 0;
+    sal_uLong const nIndex = rTextNode.GetIndex();
+    rFootnoteIdxs.SeekEntry( rTextNode, &nPos );
+    if (nPos < rFootnoteIdxs.size())
+    {
+        while (nPos && &rTextNode == &(rFootnoteIdxs[ nPos ]->GetTextNode()))
+            --nPos;
+        if (nPos || &rTextNode != &(rFootnoteIdxs[ nPos ]->GetTextNode()))
+            ++nPos;
+    }
+    while (nPos < rFootnoteIdxs.size())
+    {
+        SwTextFootnote* pTextFootnote = rFootnoteIdxs[ nPos ];
+        if (pTextFootnote->GetTextNode().GetIndex() > nIndex)
+            break;
+        pTextFootnote->DelFrames( &rTextFrame );
+        ++nPos;
+    }
+}
+
 void SwTextFrame::DestroyImpl()
 {
     // Remove associated SwParaPortion from s_pTextCache
     ClearPara();
 
-    const SwContentNode* pCNd;
-    if( nullptr != ( pCNd = dynamic_cast<SwContentNode*>( GetRegisteredIn() ) ) &&
-        !pCNd->GetDoc()->IsInDtor() && HasFootnote() )
+    assert(!GetDoc().IsInDtor()); // this shouldn't be happening with ViewShell owning layout
+    if (!GetDoc().IsInDtor() && HasFootnote())
     {
-        SwTextNode *pTextNd = GetTextNode();
-        const SwFootnoteIdxs &rFootnoteIdxs = pCNd->GetDoc()->GetFootnoteIdxs();
-        size_t nPos = 0;
-        sal_uLong nIndex = pCNd->GetIndex();
-        rFootnoteIdxs.SeekEntry( *pTextNd, &nPos );
-        if( nPos < rFootnoteIdxs.size() )
+        if (m_pMergedPara)
         {
-            while( nPos && pTextNd == &(rFootnoteIdxs[ nPos ]->GetTextNode()) )
-                --nPos;
-            if( nPos || pTextNd != &(rFootnoteIdxs[ nPos ]->GetTextNode()) )
-                ++nPos;
+            SwTextNode const* pNode(nullptr);
+            for (auto const& e : m_pMergedPara->extents)
+            {
+                if (e.pNode != pNode)
+                {
+                    pNode = e.pNode;
+                    // sw_redlinehide: not sure if it's necessary to check
+                    // if the nodes are still alive here, which would require
+                    // accessing WriterMultiListener::m_vDepends
+                    RemoveFootnotesForNode(*this, *pNode);
+                }
+            }
         }
-        while( nPos < rFootnoteIdxs.size() )
+        else
         {
-            SwTextFootnote* pTextFootnote = rFootnoteIdxs[ nPos ];
-            if( pTextFootnote->GetTextNode().GetIndex() > nIndex )
-                break;
-            pTextFootnote->DelFrames( this );
-            ++nPos;
+            SwTextNode *const pNode(static_cast<SwTextNode*>(GetRegisteredIn()));
+            if (pNode)
+            {
+                RemoveFootnotesForNode(*this, *pNode);
+            }
         }
     }
 
commit e27fb4a5da4df8f30586397c2bd33589725f39b4
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Wed May 30 14:16:02 2018 +0200

    sw_redlinehide: TextFrameIndex conversion in SwTextFrame::SwClientNotify
    
    ... etc.
    
    Change-Id: I34336fa923b5c40a040490dd618633035efd5d94

diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 28d51eea49c0..fdab5fb6bf63 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -1161,7 +1161,9 @@ bool SwTextFrame::IsIdxInside(TextFrameIndex const nPos, TextFrameIndex const nL
     TextFrameIndex const nMax = GetFollow()->GetOfst();
 
     // either the range overlap or our text has been deleted
-    if( nMax > nPos || nMax > GetText().getLength() )
+    // sw_redlinehide: GetText() should be okay here because it has already
+    // been updated in the INS/DEL hint case
+    if (nMax > nPos || nMax > TextFrameIndex(GetText().getLength()))
         return true;
 
     // changes made in the first line of a follow can modify the master
@@ -1280,11 +1282,12 @@ void SwTextFrame::CalcLineSpace()
     }
 }
 
-static void lcl_SetWrong( SwTextFrame& rFrame, sal_Int32 nPos, sal_Int32 nCnt, bool bMove )
+static void lcl_SetWrong( SwTextFrame& rFrame, SwTextNode const& rNode,
+        sal_Int32 const nPos, sal_Int32 const nCnt, bool const bMove)
 {
     if ( !rFrame.IsFollow() )
     {
-        SwTextNode* pTextNode = rFrame.GetTextNode();
+        SwTextNode* pTextNode = const_cast<SwTextNode*>(&rNode);
         IGrammarContact* pGrammarContact = getGrammarContact( *pTextNode );
         SwGrammarMarkUp* pWrongGrammar = pGrammarContact ?
             pGrammarContact->getGrammarCheck( *pTextNode, false ) :
@@ -1344,7 +1347,7 @@ static void lcl_SetWrong( SwTextFrame& rFrame, sal_Int32 nPos, sal_Int32 nCnt, b
     }
 }
 
-static void lcl_SetScriptInval( SwTextFrame& rFrame, sal_Int32 nPos )
+static void lcl_SetScriptInval(SwTextFrame& rFrame, TextFrameIndex const nPos)
 {
     if( rFrame.GetPara() )
         rFrame.GetPara()->GetScriptInfo().SetInvalidityA( nPos );
@@ -1429,7 +1432,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
             // collection has changed
             Prepare();
             InvalidatePrt_();
-            lcl_SetWrong( *this, 0, COMPLETE_STRING, false );
+            lcl_SetWrong( *this, rNode, 0, COMPLETE_STRING, false );
             SetDerivedR2L( false );
             CheckDirChange();
             // Force complete paint due to existing indents.
@@ -1453,8 +1456,8 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
 
     // save stack
     // warning: one has to ensure that all variables are set
-    sal_Int32 nPos;
-    sal_Int32 nLen;
+    TextFrameIndex nPos;
+    TextFrameIndex nLen;
     bool bSetFieldsDirty = false;
     bool bRecalcFootnoteFlag = false;
 
@@ -1468,11 +1471,13 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
         break;
         case RES_INS_TXT:
         {
-            nPos = static_cast<const SwInsText*>(pNew)->nPos;
-            nLen = static_cast<const SwInsText*>(pNew)->nLen;
+            sal_Int32 const nNPos = static_cast<const SwInsText*>(pNew)->nPos;
+            sal_Int32 const nNLen = static_cast<const SwInsText*>(pNew)->nLen;
+            nPos = MapModelToView(&rNode, nNPos);
+            nLen = TextFrameIndex(nNLen);
             if (m_pMergedPara)
             {
-                UpdateMergedParaForInsert(*m_pMergedPara, rNode, nPos, nLen);
+                UpdateMergedParaForInsert(*m_pMergedPara, rNode, nNPos, nNLen);
             }
             if( IsIdxInside( nPos, nLen ) )
             {
@@ -1485,9 +1490,9 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
                         Prepare();
                 }
                 else
-                    InvalidateRange_( SwCharRange( nPos, nLen ), nLen );
+                    InvalidateRange_( SwCharRange( nPos, nLen ), nNLen );
             }
-            lcl_SetWrong( *this, nPos, nLen, true );
+            lcl_SetWrong( *this, rNode, nNPos, nNLen, true );
             lcl_SetScriptInval( *this, nPos );
             bSetFieldsDirty = true;
             if( HasFollow() )
@@ -1496,33 +1501,38 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
         break;
         case RES_DEL_CHR:
         {
-            nPos = static_cast<const SwDelChr*>(pNew)->nPos;
+            sal_Int32 const nNPos = static_cast<const SwDelChr*>(pNew)->nPos;
+            nPos = MapModelToView(&rNode, nNPos);
+            nLen = MapModelToView(&rNode, nNPos + 1) - nPos;
             bool bDeleted(true);
             if (m_pMergedPara)
             {
-                bDeleted = UpdateMergedParaForDelete(*m_pMergedPara, rNode, nPos, 1);
+                bDeleted = UpdateMergedParaForDelete(*m_pMergedPara, rNode, nNPos, 1);
             }
-            lcl_SetWrong( *this, nPos, -1, true );
+            lcl_SetWrong( *this, rNode, nNPos, -1, true );
             if (bDeleted)
             {
+                assert(nLen);
                 InvalidateRange( SwCharRange(nPos, TextFrameIndex(1)), -1 );
                 lcl_SetScriptInval( *this, nPos );
                 bSetFieldsDirty = bRecalcFootnoteFlag = true;
                 if (HasFollow())
-                    lcl_ModifyOfst( this, nPos, COMPLETE_STRING );
+                    lcl_ModifyOfst(this, nPos, TextFrameIndex(COMPLETE_STRING));
             }
         }
         break;
         case RES_DEL_TXT:
         {
-            nPos = static_cast<const SwDelText*>(pNew)->nStart;
-            nLen = static_cast<const SwDelText*>(pNew)->nLen;
+            sal_Int32 const nNPos = static_cast<const SwDelText*>(pNew)->nStart;
+            sal_Int32 const nNLen = static_cast<const SwDelText*>(pNew)->nLen;
+            nPos = MapModelToView(&rNode, nNPos);
+            nLen = MapModelToView(&rNode, nNPos + nNLen) - nPos;
             bool bDeleted(true);
             if (m_pMergedPara)
             {   // update merged before doing anything else
-                bDeleted = UpdateMergedParaForDelete(*m_pMergedPara, rNode, nPos, nLen);
+                bDeleted = UpdateMergedParaForDelete(*m_pMergedPara, rNode, nNPos, nNLen);
             }
-            const sal_Int32 m = -nLen;
+            const sal_Int32 m = -nNLen;
             if (bDeleted && IsIdxInside(nPos, nLen))
             {
                 if( !nLen )
@@ -1530,9 +1540,10 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
                 else
                     InvalidateRange( SwCharRange(nPos, TextFrameIndex(1)), m );
             }
-            lcl_SetWrong( *this, nPos, m, true );
+            lcl_SetWrong( *this, rNode, nNPos, m, true );
             if (bDeleted)
             {
+                assert(!nNLen || nLen);
                 lcl_SetScriptInval( *this, nPos );
                 bSetFieldsDirty = bRecalcFootnoteFlag = true;
                 if (HasFollow())
@@ -1542,8 +1553,10 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
         break;
         case RES_UPDATE_ATTR:
         {
-            nPos = static_cast<const SwUpdateAttr*>(pNew)->getStart();
-            nLen = static_cast<const SwUpdateAttr*>(pNew)->getEnd() - nPos;
+            sal_Int32 const nNPos = static_cast<const SwUpdateAttr*>(pNew)->getStart();
+            sal_Int32 const nNLen = static_cast<const SwUpdateAttr*>(pNew)->getEnd() - nNPos;
+            nPos = MapModelToView(&rNode, nNPos);
+            nLen = MapModelToView(&rNode, nNPos + nNLen) - nPos;
             if( IsIdxInside( nPos, nLen ) )
             {
                 // We need to reformat anyways, even if the invalidated
@@ -1553,7 +1566,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
 
                 // FootnoteNumbers need to be formatted
                 if( !nLen )
-                    nLen = 1;
+                    nLen = TextFrameIndex(1);
 
                 InvalidateRange_( SwCharRange( nPos, nLen) );
                 const sal_uInt16 nTmp = static_cast<const SwUpdateAttr*>(pNew)->getWhichAttr();
@@ -1561,7 +1574,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
                 if( ! nTmp || RES_TXTATR_CHARFMT == nTmp || RES_TXTATR_INETFMT == nTmp || RES_TXTATR_AUTOFMT == nTmp ||
                     RES_FMT_CHG == nTmp || RES_ATTRSET_CHG == nTmp )
                 {
-                    lcl_SetWrong( *this, nPos, nPos + nLen, false );
+                    lcl_SetWrong( *this, rNode, nNPos, nNPos + nNLen, false );
                     lcl_SetScriptInval( *this, nPos );
                 }
             }
@@ -1595,7 +1608,8 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
         case RES_TXTATR_FIELD:
         case RES_TXTATR_ANNOTATION:
             {
-                nPos = static_cast<const SwFormatField*>(pNew)->GetTextField()->GetStart();
+                sal_Int32 const nNPos = static_cast<const SwFormatField*>(pNew)->GetTextField()->GetStart();
+                nPos = MapModelToView(&rNode, nNPos);
                 if (IsIdxInside(nPos, TextFrameIndex(1)))
                 {
                     if( pNew == pOld )
@@ -1611,13 +1625,14 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
                 bSetFieldsDirty = true;
                 // ST2
                 if ( SwSmartTagMgr::Get().IsSmartTagsEnabled() )
-                    lcl_SetWrong( *this, nPos, nPos + 1, false );
+                    lcl_SetWrong( *this, rNode, nNPos, nNPos + 1, false );
             }
             break;
 
         case RES_TXTATR_FTN :
         {
-            nPos = static_cast<const SwFormatFootnote*>(pNew)->GetTextFootnote()->GetStart();
+            nPos = MapModelToView(&rNode,
+                static_cast<const SwFormatFootnote*>(pNew)->GetTextFootnote()->GetStart());
             if (IsInFootnote() || IsIdxInside(nPos, TextFrameIndex(1)))
                 Prepare( PREP_FTN, static_cast<const SwFormatFootnote*>(pNew)->GetTextFootnote() );
             break;
@@ -1634,7 +1649,8 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
 
             if( SfxItemState::SET == rNewSet.GetItemState( RES_TXTATR_FTN, false, &pItem ))
             {
-                nPos = static_cast<const SwFormatFootnote*>(pItem)->GetTextFootnote()->GetStart();
+                nPos = MapModelToView(&rNode,
+                    static_cast<const SwFormatFootnote*>(pItem)->GetTextFootnote()->GetStart());
                 if (IsIdxInside(nPos, TextFrameIndex(1)))
                     Prepare( PREP_FTN, pNew );
                 nClear = 0x01;
@@ -1643,7 +1659,8 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
 
             if( SfxItemState::SET == rNewSet.GetItemState( RES_TXTATR_FIELD, false, &pItem ))
             {
-                nPos = static_cast<const SwFormatField*>(pItem)->GetTextField()->GetStart();
+                nPos = MapModelToView(&rNode,
+                    static_cast<const SwFormatField*>(pItem)->GetTextField()->GetStart());
                 if (IsIdxInside(nPos, TextFrameIndex(1)))
                 {
                     const SfxPoolItem* pOldItem = pOld ?
@@ -1746,8 +1763,8 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
             if ( SfxItemState::SET ==
                  rNewSet.GetItemState( RES_TXTATR_CHARFMT, false ) )
             {
-                lcl_SetWrong( *this, 0, COMPLETE_STRING, false );
-                lcl_SetScriptInval( *this, 0 );
+                lcl_SetWrong( *this, rNode, 0, COMPLETE_STRING, false );
+                lcl_SetScriptInval( *this, TextFrameIndex(0) );
             }
             else if ( SfxItemState::SET ==
                       rNewSet.GetItemState( RES_CHRATR_LANGUAGE, false ) ||
@@ -1755,14 +1772,14 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
                       rNewSet.GetItemState( RES_CHRATR_CJK_LANGUAGE, false ) ||
                       SfxItemState::SET ==
                       rNewSet.GetItemState( RES_CHRATR_CTL_LANGUAGE, false ) )
-                lcl_SetWrong( *this, 0, COMPLETE_STRING, false );
+                lcl_SetWrong( *this, rNode, 0, COMPLETE_STRING, false );
             else if ( SfxItemState::SET ==
                       rNewSet.GetItemState( RES_CHRATR_FONT, false ) ||
                       SfxItemState::SET ==
                       rNewSet.GetItemState( RES_CHRATR_CJK_FONT, false ) ||
                       SfxItemState::SET ==
                       rNewSet.GetItemState( RES_CHRATR_CTL_FONT, false ) )
-                lcl_SetScriptInval( *this, 0 );
+                lcl_SetScriptInval( *this, TextFrameIndex(0) );
             else if ( SfxItemState::SET ==
                       rNewSet.GetItemState( RES_FRAMEDIR, false )
                 && (!m_pMergedPara || m_pMergedPara->pParaPropsNode == &rModify))
@@ -1861,8 +1878,9 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
                 if( pDocPos->nDocPos <= getFrameArea().Top() )
                 {
                     const SwFormatField *pField = static_cast<const SwFormatField *>(pNew);
-                    InvalidateRange(
-                        SwCharRange(pField->GetTextField()->GetStart(), TextFrameIndex(1)));
+                    TextFrameIndex const nIndex(MapModelToView(&rNode,
+                                pField->GetTextField()->GetStart()));
+                    InvalidateRange(SwCharRange(nIndex, TextFrameIndex(1)));
                 }
             }
             break;
@@ -2143,7 +2161,8 @@ bool SwTextFrame::Prepare( const PrepareHint ePrep, const void* pVoid,
             else
             {
                 // We are the TextFrame _with_ the footnote
-                const sal_Int32 nPos = pFootnote->GetStart();
+                TextFrameIndex const nPos = MapModelToView(
+                        &pFootnote->GetTextNode(), pFootnote->GetStart());
                 InvalidateRange(SwCharRange(nPos, TextFrameIndex(1)), 1);
             }
             break;
commit ae3db15c9cbcad962501922009c8dda181c74aa7
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Wed May 30 13:08:43 2018 +0200

    sw_redlinehide: update MergedPara in SwTextFrame::SwClientNotify()
    
    Change-Id: Ic61309f7ae56b014a19b86173d520fb72a33667e

diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 456cfd4997f4..aab128ad1ae6 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -77,9 +77,9 @@ namespace sw {
 
 struct Extent
 {
-    SwTextNode *const pNode;
-    sal_Int32 const nStart;
-    sal_Int32 const nEnd;
+    SwTextNode * /*const logically, but need assignment for std::vector*/ pNode;
+    sal_Int32 nStart;
+    sal_Int32 nEnd;
     Extent(SwTextNode *const p, sal_Int32 const s, sal_Int32 const e)
         : pNode(p), nStart(s), nEnd(e)
     {
@@ -904,9 +904,9 @@ namespace sw {
 struct MergedPara
 {
     sw::WriterMultiListener listener;
-    std::vector<Extent> const extents;
+    std::vector<Extent> extents;
     /// note: cannot be const currently to avoid UB because SwTextGuess::Guess
-    /// const_casts it and modifies it
+    /// const_casts it and modifies it (also, Update will modify it)
     OUString mergedText;
     /// most paragraph properties are taken from the first non-empty node
     SwTextNode const*const pParaPropsNode;
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index a9514dc07be7..28d51eea49c0 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -639,6 +639,115 @@ SwTextFrame::~SwTextFrame()
 
 namespace sw {
 
+void UpdateMergedParaForInsert(MergedPara & rMerged,
+        SwTextNode const& rNode, sal_Int32 const nIndex, sal_Int32 const nLen)
+{
+    assert(nIndex <= rNode.Len());
+    assert(nIndex + nLen <= rNode.Len());
+    OUStringBuffer text(rMerged.mergedText);
+    sal_Int32 nTFIndex(0);
+    bool bInserted(false);
+    bool bFoundNode(false);
+    auto it = rMerged.extents.begin();
+    for (; it != rMerged.extents.end(); ++it)
+    {
+        if (it->pNode == &rNode)
+        {
+            if (it->nStart <= nIndex && nIndex <= it->nEnd)
+            {   // note: this can happen only once
+                it->nEnd += nLen;
+                text.insert(nTFIndex + (nIndex - it->nStart),
+                        rNode.GetText().copy(nIndex, nLen));
+                bInserted = true;
+            }
+            else if (nIndex < it->nStart)
+            {
+                it->nStart += nLen;
+                it->nEnd += nLen;
+            }
+            bFoundNode = true;
+        }
+        else if (bFoundNode)
+        {
+            break;
+        }
+        nTFIndex += it->nEnd - it->nStart;
+    }
+    assert(bFoundNode && "text node not found - why is it sending hints to us");
+    if (!bInserted)
+    {   // must be in a gap at the end of the node
+        rMerged.extents.emplace(it, const_cast<SwTextNode*>(&rNode), nIndex, nIndex + nLen);
+        text.insert(nTFIndex, rNode.GetText().copy(nIndex, nLen));
+    }
+    rMerged.mergedText = text.makeStringAndClear();
+}
+
+bool UpdateMergedParaForDelete(MergedPara & rMerged,
+        SwTextNode const& rNode, sal_Int32 nIndex, sal_Int32 nLen)
+{
+    assert(nIndex <= rNode.Len());
+    OUStringBuffer text(rMerged.mergedText);
+    sal_Int32 nTFIndex(0);
+    sal_Int32 nDeleted(0);
+    bool bFoundNode(false);
+    auto it = rMerged.extents.begin();
+    for (; it != rMerged.extents.end(); ++it)
+    {
+        if (it->pNode == &rNode)
+        {
+            if (nIndex + nLen <= it->nStart)
+            {
+                nLen = 0;
+                it->nStart -= nDeleted;
+                it->nEnd -= nDeleted;
+            }
+            else
+            {
+                if (nIndex < it->nStart)
+                {
+                    // do not adjust nIndex into the text frame index space!
+                    nLen -= it->nStart - nIndex;
+                    nIndex = it->nStart;
+                    // note: continue with the if check below, no else!
+                }
+                if (it->nStart <= nIndex && nIndex < it->nEnd)
+                {
+                    sal_Int32 const nDeleteHere(nIndex + nLen <= it->nEnd
+                            ? nLen
+                            : it->nEnd - nIndex);
+                    if (nDeleteHere == it->nEnd - it->nStart)
+                    {
+                        assert(it->nStart == nIndex);
+                        rMerged.extents.erase(it);
+                    }
+                    else
+                    {
+                        it->nStart -= nDeleted;
+                        it->nEnd -= (nDeleted + nDeleteHere);
+                    }
+                    text.remove(nTFIndex + (nIndex - it->nStart), nDeleteHere);
+                    nDeleted += nDeleteHere;
+                    nLen -= nDeleteHere;
+                    nIndex += nDeleteHere;
+                }
+            }
+            bFoundNode = true;
+        }
+        else if (bFoundNode)
+        {
+            break;
+        }
+        nTFIndex += it->nEnd - it->nStart;
+    }
+    assert(bFoundNode && "text node not found - why is it sending hints to us");
+    assert(nIndex <= rNode.Len());
+    --it; // last one in paragraph - must be valid
+    // if there's a remaining deletion, it must be in gap at the end of the node
+    assert(nLen == 0 || it->nEnd <= nIndex);
+    rMerged.mergedText = text.makeStringAndClear();
+    return nDeleted != 0;
+}
+
 std::pair<SwTextNode*, sal_Int32>
 MapViewToModel(MergedPara const& rMerged, TextFrameIndex const i_nIndex)
 {
@@ -1277,6 +1386,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
 
     SfxPoolItem const*const pOld(pHint->m_pOld);
     SfxPoolItem const*const pNew(pHint->m_pNew);
+    SwTextNode const& rNode(static_cast<SwTextNode const&>(rModify));
 
 #if 1
     if (m_pMergedPara)
@@ -1360,6 +1470,10 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
         {
             nPos = static_cast<const SwInsText*>(pNew)->nPos;
             nLen = static_cast<const SwInsText*>(pNew)->nLen;
+            if (m_pMergedPara)
+            {
+                UpdateMergedParaForInsert(*m_pMergedPara, rNode, nPos, nLen);
+            }
             if( IsIdxInside( nPos, nLen ) )
             {
                 if( !nLen )
@@ -1383,20 +1497,33 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
         case RES_DEL_CHR:
         {
             nPos = static_cast<const SwDelChr*>(pNew)->nPos;
-            InvalidateRange( SwCharRange(nPos, TextFrameIndex(1)), -1 );
+            bool bDeleted(true);
+            if (m_pMergedPara)
+            {
+                bDeleted = UpdateMergedParaForDelete(*m_pMergedPara, rNode, nPos, 1);
+            }
             lcl_SetWrong( *this, nPos, -1, true );
-            lcl_SetScriptInval( *this, nPos );
-            bSetFieldsDirty = bRecalcFootnoteFlag = true;
-            if( HasFollow() )
-                lcl_ModifyOfst( this, nPos, COMPLETE_STRING );
+            if (bDeleted)
+            {
+                InvalidateRange( SwCharRange(nPos, TextFrameIndex(1)), -1 );
+                lcl_SetScriptInval( *this, nPos );
+                bSetFieldsDirty = bRecalcFootnoteFlag = true;
+                if (HasFollow())
+                    lcl_ModifyOfst( this, nPos, COMPLETE_STRING );
+            }
         }
         break;
         case RES_DEL_TXT:
         {
             nPos = static_cast<const SwDelText*>(pNew)->nStart;
             nLen = static_cast<const SwDelText*>(pNew)->nLen;
+            bool bDeleted(true);
+            if (m_pMergedPara)
+            {   // update merged before doing anything else
+                bDeleted = UpdateMergedParaForDelete(*m_pMergedPara, rNode, nPos, nLen);
+            }
             const sal_Int32 m = -nLen;
-            if( IsIdxInside( nPos, nLen ) )
+            if (bDeleted && IsIdxInside(nPos, nLen))
             {
                 if( !nLen )
                     InvalidateSize();
@@ -1404,10 +1531,13 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
                     InvalidateRange( SwCharRange(nPos, TextFrameIndex(1)), m );
             }
             lcl_SetWrong( *this, nPos, m, true );
-            lcl_SetScriptInval( *this, nPos );
-            bSetFieldsDirty = bRecalcFootnoteFlag = true;
-            if( HasFollow() )
-                lcl_ModifyOfst( this, nPos, nLen );
+            if (bDeleted)
+            {
+                lcl_SetScriptInval( *this, nPos );
+                bSetFieldsDirty = bRecalcFootnoteFlag = true;
+                if (HasFollow())
+                    lcl_ModifyOfst( this, nPos, nLen );
+            }
         }
         break;
         case RES_UPDATE_ATTR:
commit 0aaabc383b1dda88ed0a166e74babc9f4ce1908b
Author: Michael Stahl <Michael.Stahl at cib.de>
Date:   Tue May 29 18:33:06 2018 +0200

    sw_redlinehide: replace SwTextFrame::Modify() with SwClientNotify()
    
    This is critical because it needs to know what SwTextNode sent the hint.
    
    Fortunately it looks like we can just convert this one implementation
    and the backward compat stuff in SwClient will keep the other
    SwFrames working as before with their Modify().
    
    Change-Id: I16f0bf7495002e7393148429640262cb38dc4849

diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 70f2566e06f2..456cfd4997f4 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -263,7 +263,7 @@ class SW_DLLPUBLIC SwTextFrame: public SwContentFrame
     virtual ~SwTextFrame() override;
 
 protected:
-    virtual void Modify( const SfxPoolItem*, const SfxPoolItem* ) override;
+    virtual void SwClientNotify(SwModify const& rModify, SfxHint const& rHint) override;
 
 public:
 
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 047175b8eb8f..a9514dc07be7 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -1264,13 +1264,55 @@ static bool isA11yRelevantAttribute(sal_uInt16 nWhich)
     return nWhich != RES_CHRATR_RSID;
 }
 
-void SwTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
+// Note: for now this overrides SwClient::SwClientNotify; the intermediary
+// classes still override SwClient::Modify, which should continue to work
+// as their implementation of SwClientNotify is SwClient's which calls Modify.
+// Therefore we also don't need to call SwClient::SwClientNotify(rModify, rHint)
+// because that's all it does, and this implementation calls
+// SwContentFrame::Modify() when appropriate.
+void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
 {
+    auto const pHint(dynamic_cast<sw::LegacyModifyHint const*>(&rHint));
+    assert(pHint); // TODO this is the only type expected here for now
+
+    SfxPoolItem const*const pOld(pHint->m_pOld);
+    SfxPoolItem const*const pNew(pHint->m_pNew);
+
+#if 1
+    if (m_pMergedPara)
+    {
+            bool good(false);
+            struct HorribleDebugHack : public SwClient { SwClient * m; };
+            std::vector<HorribleDebugHack> const* p(reinterpret_cast<std::vector<HorribleDebugHack> const*>(&m_pMergedPara->listener));
+            for (HorribleDebugHack const& h : *p)
+            {
+                if (h.GetRegisteredIn() == &rModify)
+                {
+                    (void) h.m;
+                    good = true;
+                    break;
+                }
+            }
+            assert(good);
+    }
+#endif
+
     const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
 
     // modifications concerning frame attributes are processed by the base class
     if( IsInRange( aFrameFormatSetRange, nWhich ) || RES_FMT_CHG == nWhich )
     {
+        if (m_pMergedPara)
+        {   // ignore item set changes that don't apply
+            SwTextNode const*const pAttrNode(
+                (nWhich == RES_PAGEDESC || nWhich == RES_BREAK)
+                    ? m_pMergedPara->pFirstNode
+                    : m_pMergedPara->pParaPropsNode);
+            if (pAttrNode != &rModify)
+            {
+                return;
+            }
+        }
         SwContentFrame::Modify( pOld, pNew );
         if( nWhich == RES_FMT_CHG && getRootFrame()->GetCurrShell() )
         {
@@ -1287,6 +1329,14 @@ void SwTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
         return;
     }
 
+    if (m_pMergedPara && m_pMergedPara->pParaPropsNode != &rModify)
+    {
+        if (isPARATR(nWhich) || isPARATR_LIST(nWhich)) // FRMATR handled above
+        {
+            return; // ignore it
+        }
+    }
+
     // while locked ignore all modifications
     if( IsLocked() )
         return;
@@ -1302,6 +1352,7 @@ void SwTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
     {
         case RES_LINENUMBER:
         {
+            assert(false); // should have been forwarded to SwContentFrame
             InvalidateLineNum();
         }
         break;
@@ -1484,23 +1535,27 @@ void SwTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
                                             RES_PARATR_REGISTER, false );
             if ( bLineSpace || bRegister )
             {
-                Prepare( bRegister ? PREP_REGISTER : PREP_ADJUST_FRM );
-                CalcLineSpace();
-                InvalidateSize();
-                InvalidatePrt_();
+                if (!m_pMergedPara || m_pMergedPara->pParaPropsNode == &rModify)
+                {
+                    Prepare( bRegister ? PREP_REGISTER : PREP_ADJUST_FRM );
+                    CalcLineSpace();
+                    InvalidateSize();
+                    InvalidatePrt_();
 
-                // i#11859
-                //  (1) Also invalidate next frame on next page/column.
-                //  (2) Skip empty sections and hidden paragraphs
-                //  Thus, use method <InvalidateNextPrtArea()>
-                InvalidateNextPrtArea();
+                    // i#11859
+                    //  (1) Also invalidate next frame on next page/column.
+                    //  (2) Skip empty sections and hidden paragraphs
+                    //  Thus, use method <InvalidateNextPrtArea()>
+                    InvalidateNextPrtArea();
 
-                SetCompletePaint();
+                    SetCompletePaint();
+                }
                 nClear |= 0x04;
                 if ( bLineSpace )
                 {
                     --nCount;
-                    if( IsInSct() && !GetPrev() )
+                    if ((!m_pMergedPara || m_pMergedPara->pParaPropsNode == &rModify)
+                        && IsInSct() && !GetPrev())
                     {
                         SwSectionFrame *pSect = FindSctFrame();
                         if( pSect->ContainsAny() == this )
@@ -1513,15 +1568,19 @@ void SwTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
             if ( SfxItemState::SET == rNewSet.GetItemState( RES_PARATR_SPLIT,
                                                        false ))
             {
-                if ( GetPrev() )
-                    CheckKeep();
-                Prepare();
-                InvalidateSize();
+                if (!m_pMergedPara || m_pMergedPara->pParaPropsNode == &rModify)
+                {
+                    if (GetPrev())
+                        CheckKeep();
+                    Prepare();
+                    InvalidateSize();
+                }
                 nClear |= 0x08;
                 --nCount;
             }
 
             if( SfxItemState::SET == rNewSet.GetItemState( RES_BACKGROUND, false)
+                && (!m_pMergedPara || m_pMergedPara->pParaPropsNode == &rModify)
                 && !IsFollow() && GetDrawObjs() )
             {
                 SwSortedObjs *pObjs = GetDrawObjs();
@@ -1575,7 +1634,8 @@ void SwTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
                       rNewSet.GetItemState( RES_CHRATR_CTL_FONT, false ) )
                 lcl_SetScriptInval( *this, 0 );
             else if ( SfxItemState::SET ==
-                      rNewSet.GetItemState( RES_FRAMEDIR, false ) )
+                      rNewSet.GetItemState( RES_FRAMEDIR, false )
+                && (!m_pMergedPara || m_pMergedPara->pParaPropsNode == &rModify))
             {
                 SetDerivedR2L( false );
                 CheckDirChange();
@@ -1591,11 +1651,32 @@ void SwTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
                     InvalidatePrt_();
                 }
 
-                if( nClear )
+                if (nClear || (m_pMergedPara &&
+                        (m_pMergedPara->pParaPropsNode != &rModify ||
+                         m_pMergedPara->pFirstNode != &rModify)))
                 {
                     SwAttrSetChg aOldSet( *static_cast<const SwAttrSetChg*>(pOld) );
                     SwAttrSetChg aNewSet( *static_cast<const SwAttrSetChg*>(pNew) );
 
+                    if (m_pMergedPara && m_pMergedPara->pParaPropsNode != &rModify)
+                    {
+                        for (sal_uInt16 i = RES_PARATR_BEGIN; i != RES_FRMATR_END; ++i)
+                        {
+                            if (i != RES_BREAK && i != RES_PAGEDESC)
+                            {
+                                aOldSet.ClearItem(i);
+                                aNewSet.ClearItem(i);
+                            }
+                        }
+                    }
+                    if (m_pMergedPara && m_pMergedPara->pFirstNode != &rModify)
+                    {
+                        aOldSet.ClearItem(RES_BREAK);
+                        aNewSet.ClearItem(RES_BREAK);
+                        aOldSet.ClearItem(RES_PAGEDESC);
+                        aNewSet.ClearItem(RES_PAGEDESC);
+                    }
+
                     if( 0x01 & nClear )
                     {
                         aOldSet.ClearItem( RES_TXTATR_FTN );
@@ -1663,6 +1744,7 @@ void SwTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
             bSetFieldsDirty = true;
             break;
         case RES_FRAMEDIR :
+            assert(false); // should have been forwarded to SwContentFrame
             SetDerivedR2L( false );
             CheckDirChange();
             break;


More information about the Libreoffice-commits mailing list