summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <mstahl@redhat.com>2015-05-08 23:53:16 +0200
committerCaolán McNamara <caolanm@redhat.com>2015-05-20 14:07:12 +0000
commitc781bad828b4bbea1ab888c6747b991ad5804a5b (patch)
tree2c2c5d0a03bae23a354fb18ef36cc53e9ffd7276
parentdfe435f81c5c28a20e41b9127027b1be4f207055 (diff)
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@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r--sw/source/core/docnode/nodes.cxx76
1 files changed, 54 insertions, 22 deletions
diff --git a/sw/source/core/docnode/nodes.cxx b/sw/source/core/docnode/nodes.cxx
index 24da3ef20a14..1997952cb1de 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 )
{