From 4dd2e61e2a52d0b5c582f16732de544391bad3d2 Mon Sep 17 00:00:00 2001 From: Michael Stahl Date: Fri, 8 May 2015 23:53:16 +0200 Subject: 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) Change-Id: I13c9577c01e3b8976b74fb9c58dc2ef2c2fc0666 --- sw/source/core/docnode/nodes.cxx | 52 ++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 10 deletions(-) (limited to 'sw') diff --git a/sw/source/core/docnode/nodes.cxx b/sw/source/core/docnode/nodes.cxx index 25f94bf74fc6..380c1031c1c8 100644 --- a/sw/source/core/docnode/nodes.cxx +++ b/sw/source/core/docnode/nodes.cxx @@ -2210,17 +2210,10 @@ void SwNodes::ForEach( const SwNodeIndex& rStart, const SwNodeIndex& rEnd, void SwNodes::RemoveNode( sal_uLong nDelPos, sal_uLong nSz, bool bDel ) { - sal_uLong nEnd = nDelPos + nSz; - SwNode* pNew = (*this)[ nEnd ]; - - for(SwNodeIndex& rIndex : vIndices->GetRingContainer()) - { - sal_uLong nIdx = rIndex.GetIndex(); - if( nDelPos <= nIdx && nIdx < nEnd ) - rIndex = *pNew; - } - { +#if OSL_DEBUG_LEVEL > 0 + SwNode *const pFirst((*this)[nDelPos]); +#endif for (sal_uLong nCnt = 0; nCnt < nSz; nCnt++) { SwNode* pNode = ((*this)[ nDelPos + nCnt ]); @@ -2229,6 +2222,35 @@ void SwNodes::RemoveNode( sal_uLong nDelPos, sal_uLong nSz, bool bDel ) 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 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) @@ -2242,6 +2264,16 @@ void SwNodes::RemoveNode( sal_uLong nDelPos, sal_uLong nSz, bool bDel ) } } + sal_uLong nEnd = nDelPos + nSz; + SwNode* pNew = (*this)[ nEnd ]; + + for (SwNodeIndex& rIndex : vIndices->GetRingContainer()) + { + sal_uLong const nIdx = rIndex.GetIndex(); + if (nDelPos <= nIdx && nIdx < nEnd) + rIndex = *pNew; + } + std::vector aTempEntries; if( bDel ) { -- cgit v1.2.3