diff options
author | Michael Stahl <mstahl@redhat.com> | 2015-05-08 23:53:16 +0200 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2015-05-20 14:07:12 +0000 |
commit | c781bad828b4bbea1ab888c6747b991ad5804a5b (patch) | |
tree | 2c2c5d0a03bae23a354fb18ef36cc53e9ffd7276 | |
parent | dfe435f81c5c28a20e41b9127027b1be4f207055 (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.cxx | 76 |
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 ) { |