[Libreoffice-commits] core.git: Branch 'libreoffice-4-4' - sw/source

Michael Stahl mstahl at redhat.com
Wed May 20 07:07:40 PDT 2015


 sw/source/core/docnode/nodes.cxx |   76 +++++++++++++++++++++++++++------------
 1 file changed, 54 insertions(+), 22 deletions(-)

New commits:
commit c781bad828b4bbea1ab888c6747b991ad5804a5b
Author: Michael Stahl <mstahl at redhat.com>
Date:   Fri May 8 23:53:16 2015 +0200

    sw: fix assert with frames anchored as-char in redlines on rhbz490395-1.odt
    
    SwRangeRedline::Hide() will copy and delete the redlined text range,
    and during the delete it happens that FLY_AS_CHAR frames are not deleted
    before their anchor SwTxtNode is destroyed, so SwFmtAnchor::m_pCntntAnchor
    will have its NodeIndex adjusted by SwNodes::RemoveNode() to a wrong
    node and then it cannot call RemoveAnchoredFly() on the proper node.
    
    Avoid the problem by manually deleting all FLY_AS_CHAR from nodes
    before they are deleted and before the SwNodeIndex adjustment.
    
    (regression from 738fb2ad77e5a1a4d6e2dc540886a17f4527e4db, which had
     the equivalent problem with differing SwNodeIndex keys)
    
    (cherry picked from commit 4dd2e61e2a52d0b5c582f16732de544391bad3d2)
    
    Conflicts:
    	sw/source/core/docnode/nodes.cxx
    
    Change-Id: I13c9577c01e3b8976b74fb9c58dc2ef2c2fc0666
    Reviewed-on: https://gerrit.libreoffice.org/15784
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/sw/source/core/docnode/nodes.cxx b/sw/source/core/docnode/nodes.cxx
index 24da3ef..1997952 100644
--- a/sw/source/core/docnode/nodes.cxx
+++ b/sw/source/core/docnode/nodes.cxx
@@ -2211,6 +2211,60 @@ void SwNodes::ForEach( const SwNodeIndex& rStart, const SwNodeIndex& rEnd,
 
 void SwNodes::RemoveNode( sal_uLong nDelPos, sal_uLong nSz, bool bDel )
 {
+    {
+#ifndef NDEBUG
+        SwNode *const pFirst((*this)[nDelPos]);
+#endif
+        for (sal_uLong nCnt = 0; nCnt < nSz; nCnt++)
+        {
+            SwNode* pNode = ((*this)[ nDelPos + nCnt ]);
+            SwTxtNode * pTxtNd = pNode->GetTxtNode();
+
+            if (pTxtNd)
+            {
+                pTxtNd->RemoveFromList();
+                // remove FLY_AS_CHAR *before* adjusting SwNodeIndex
+                // so their anchor still points to correct node when deleted!
+                // NOTE: this will call RemoveNode() recursively!
+                // so adjust our indexes to account for removed nodes
+                sal_uLong const nPos = pTxtNd->GetIndex();
+                SwpHints *const pHints(pTxtNd->GetpSwpHints());
+                if (pHints)
+                {
+                    std::vector<SwTxtAttr*> flys;
+                    for (size_t i = 0; i < pHints->Count(); ++i)
+                    {
+                        SwTxtAttr *const pHint(pHints->GetTextHint(i));
+                        if (RES_TXTATR_FLYCNT == pHint->Which())
+                        {
+                            flys.push_back(pHint);
+                        }
+                    }
+                    for (SwTxtAttr * pHint : flys)
+                    {
+                        pTxtNd->DeleteAttribute(pHint);
+                    }   // pHints may be dead now
+                    sal_uLong const nDiff = nPos - pTxtNd->GetIndex();
+                    if (nDiff)
+                    {
+                        nDelPos -= nDiff;
+                    }
+                    assert(pTxtNd == (*this)[nDelPos + nCnt]);
+                    assert(pFirst == (*this)[nDelPos]);
+                }
+            }
+            SwTableNode* pTableNode = pNode->GetTableNode();
+            if (pTableNode)
+            {
+                // The node that is deleted is a table node.
+                // Need to make sure that all the redlines that are
+                // related to this table are removed from the
+                // 'Extra Redlines' array
+                pTableNode->RemoveRedlines();
+            }
+        }
+    }
+
     sal_uLong nEnd = nDelPos + nSz;
     SwNode* pNew = (*this)[ nEnd ];
 
@@ -2239,28 +2293,6 @@ void SwNodes::RemoveNode( sal_uLong nDelPos, sal_uLong nSz, bool bDel )
         }
     }
 
-    {
-        for (sal_uLong nCnt = 0; nCnt < nSz; nCnt++)
-        {
-            SwNode* pNode = ((*this)[ nDelPos + nCnt ]);
-            SwTxtNode * pTxtNd = pNode->GetTxtNode();
-
-            if (pTxtNd)
-            {
-                pTxtNd->RemoveFromList();
-            }
-            SwTableNode* pTableNode = pNode->GetTableNode();
-            if (pTableNode)
-            {
-                // The node that is deleted is a table node.
-                // Need to make sure that all the redlines that are
-                // related to this table are removed from the
-                // 'Extra Redlines' array
-                pTableNode->RemoveRedlines();
-            }
-        }
-    }
-
     std::vector<BigPtrEntry> aTempEntries;
     if( bDel )
     {


More information about the Libreoffice-commits mailing list