summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorMichael Stahl <mstahl@redhat.com>2015-05-08 23:53:16 +0200
committerMichael Stahl <mstahl@redhat.com>2015-05-09 11:02:27 +0200
commit4dd2e61e2a52d0b5c582f16732de544391bad3d2 (patch)
treea6be18638e0dfb6dfd97a5f825d71f3a5c3d3e91 /sw
parentfb0553d6b4905fe2c923a2b5591c001d0be52398 (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) Change-Id: I13c9577c01e3b8976b74fb9c58dc2ef2c2fc0666
Diffstat (limited to 'sw')
-rw-r--r--sw/source/core/docnode/nodes.cxx52
1 files changed, 42 insertions, 10 deletions
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<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)
@@ -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<BigPtrEntry> aTempEntries;
if( bDel )
{