SwDoc::CopyImpl: avoid ~SwIndexReg assertions:

These happen when enabling change tracking, deleting a full paragraph
(incl. paragraph break) and then copying the deleted paragraph to the
clipboard; the "rPos" and "aCpyPam" SwPositions are registered at a node
that is deleted by lcl_DeleteRedlines.

Change-Id: I3e9e29548d23377807c26fdd401b3c9637fddf25
This commit is contained in:
Michael Stahl
2013-05-16 12:01:30 +02:00
parent 87bdc30851
commit c7b883498c

View File

@@ -31,6 +31,7 @@
#include <fldbas.hxx> #include <fldbas.hxx>
#include <swtable.hxx> #include <swtable.hxx>
#include <ddefld.hxx> #include <ddefld.hxx>
#include <unocrsr.hxx>
#include <undobj.hxx> #include <undobj.hxx>
#include <IMark.hxx> #include <IMark.hxx>
#include <mvsave.hxx> #include <mvsave.hxx>
@@ -865,13 +866,15 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
// If Undo is enabled, create the UndoCopy object // If Undo is enabled, create the UndoCopy object
SwUndoCpyDoc* pUndo = 0; SwUndoCpyDoc* pUndo = 0;
SwPaM aCpyPam( rPos ); // lcl_DeleteRedlines may delete the start or end node of the cursor when
// removing the redlines so use cursor that is corrected by PaMCorrAbs
::boost::scoped_ptr<SwUnoCrsr> const pCopyPam(pDoc->CreateUnoCrsr(rPos));
SwTblNumFmtMerge aTNFM( *this, *pDoc ); SwTblNumFmtMerge aTNFM( *this, *pDoc );
if (pDoc->GetIDocumentUndoRedo().DoesUndo()) if (pDoc->GetIDocumentUndoRedo().DoesUndo())
{ {
pUndo = new SwUndoCpyDoc( aCpyPam ); pUndo = new SwUndoCpyDoc(*pCopyPam);
pDoc->GetIDocumentUndoRedo().AppendUndo( pUndo ); pDoc->GetIDocumentUndoRedo().AppendUndo( pUndo );
} }
@@ -880,21 +883,21 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
// Move the PaM one node back from the insert position, so that // Move the PaM one node back from the insert position, so that
// the position doesn't get moved // the position doesn't get moved
aCpyPam.SetMark(); pCopyPam->SetMark();
sal_Bool bCanMoveBack = aCpyPam.Move( fnMoveBackward, fnGoCntnt ); sal_Bool bCanMoveBack = pCopyPam->Move(fnMoveBackward, fnGoCntnt);
// If the position was shifted from more than one node, an end node has been skipped // If the position was shifted from more than one node, an end node has been skipped
bool bAfterTable = false; bool bAfterTable = false;
if ( ( rPos.nNode.GetIndex() - aCpyPam.GetPoint()->nNode.GetIndex() ) > 1 ) if ((rPos.nNode.GetIndex() - pCopyPam->GetPoint()->nNode.GetIndex()) > 1)
{ {
// First go back to the original place // First go back to the original place
aCpyPam.GetPoint()->nNode = rPos.nNode; pCopyPam->GetPoint()->nNode = rPos.nNode;
aCpyPam.GetPoint()->nContent = rPos.nContent; pCopyPam->GetPoint()->nContent = rPos.nContent;
bCanMoveBack = false; bCanMoveBack = false;
bAfterTable = true; bAfterTable = true;
} }
if( !bCanMoveBack ) if( !bCanMoveBack )
aCpyPam.GetPoint()->nNode--; pCopyPam->GetPoint()->nNode--;
SwNodeRange aRg( pStt->nNode, pEnd->nNode ); SwNodeRange aRg( pStt->nNode, pEnd->nNode );
SwNodeIndex aInsPos( rPos.nNode ); SwNodeIndex aInsPos( rPos.nNode );
@@ -969,11 +972,11 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
pDoc->SplitNode( rPos, false ); pDoc->SplitNode( rPos, false );
} }
if( bCanMoveBack && rPos == *aCpyPam.GetPoint() ) if (bCanMoveBack && rPos == *pCopyPam->GetPoint())
{ {
// after the SplitNode, span the CpyPam correctly again // after the SplitNode, span the CpyPam correctly again
aCpyPam.Move( fnMoveBackward, fnGoCntnt ); pCopyPam->Move( fnMoveBackward, fnGoCntnt );
aCpyPam.Move( fnMoveBackward, fnGoCntnt ); pCopyPam->Move( fnMoveBackward, fnGoCntnt );
} }
pDestTxtNd = pDoc->GetNodes()[ aInsPos.GetIndex()-1 ]->GetTxtNode(); pDestTxtNd = pDoc->GetNodes()[ aInsPos.GetIndex()-1 ]->GetTxtNode();
@@ -1096,11 +1099,11 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
pDoc->SplitNode( rPos, false ); pDoc->SplitNode( rPos, false );
} }
if( bCanMoveBack && rPos == *aCpyPam.GetPoint() ) if (bCanMoveBack && rPos == *pCopyPam->GetPoint())
{ {
// after the SplitNode, span the CpyPam correctly again // after the SplitNode, span the CpyPam correctly again
aCpyPam.Move( fnMoveBackward, fnGoCntnt ); pCopyPam->Move( fnMoveBackward, fnGoCntnt );
aCpyPam.Move( fnMoveBackward, fnGoCntnt ); pCopyPam->Move( fnMoveBackward, fnGoCntnt );
} }
// Correct the area again // Correct the area again
@@ -1122,9 +1125,9 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
// See below, before the SetInsertRange funciton of the undo object will be called, // See below, before the SetInsertRange funciton of the undo object will be called,
// the CpyPam would be moved to the next content position. This has to be avoided // the CpyPam would be moved to the next content position. This has to be avoided
// We want to be moved to the table node itself thus we have to set bCanMoveBack // We want to be moved to the table node itself thus we have to set bCanMoveBack
// and to manipulate aCpyPam. // and to manipulate pCopyPam.
bCanMoveBack = false; bCanMoveBack = false;
aCpyPam.GetPoint()->nNode--; pCopyPam->GetPoint()->nNode--;
} }
} }
@@ -1236,7 +1239,7 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
// Put the breaks back into the first node // Put the breaks back into the first node
if( aBrkSet.Count() && 0 != ( pDestTxtNd = pDoc->GetNodes()[ if( aBrkSet.Count() && 0 != ( pDestTxtNd = pDoc->GetNodes()[
aCpyPam.GetPoint()->nNode.GetIndex()+1 ]->GetTxtNode() ) ) pCopyPam->GetPoint()->nNode.GetIndex()+1 ]->GetTxtNode()))
{ {
pDestTxtNd->SetAttr( aBrkSet ); pDestTxtNd->SetAttr( aBrkSet );
} }
@@ -1249,53 +1252,59 @@ bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
if( rPos.nNode != aInsPos ) if( rPos.nNode != aInsPos )
{ {
aCpyPam.GetMark()->nNode = aInsPos; pCopyPam->GetMark()->nNode = aInsPos;
aCpyPam.GetMark()->nContent.Assign( aCpyPam.GetCntntNode(sal_False), 0 ); pCopyPam->GetMark()->nContent.Assign(pCopyPam->GetCntntNode(sal_False), 0);
rPos = *aCpyPam.GetMark(); rPos = *pCopyPam->GetMark();
} }
else else
*aCpyPam.GetMark() = rPos; *pCopyPam->GetMark() = rPos;
if ( !bAfterTable ) if ( !bAfterTable )
aCpyPam.Move( fnMoveForward, bCanMoveBack ? fnGoCntnt : fnGoNode ); pCopyPam->Move( fnMoveForward, bCanMoveBack ? fnGoCntnt : fnGoNode );
else else
{ {
// Reset the offset to 0 as it was before the insertion // Reset the offset to 0 as it was before the insertion
aCpyPam.GetPoint( )->nContent -= aCpyPam.GetPoint( )->nContent; pCopyPam->GetPoint()->nContent -= pCopyPam->GetPoint()->nContent;
aCpyPam.GetPoint( )->nNode++; pCopyPam->GetPoint()->nNode++;
// If the next node is a start node, then step back: the start node // If the next node is a start node, then step back: the start node
// has been copied and needs to be in the selection for the undo // has been copied and needs to be in the selection for the undo
if ( aCpyPam.GetPoint()->nNode.GetNode().IsStartNode() ) if (pCopyPam->GetPoint()->nNode.GetNode().IsStartNode())
aCpyPam.GetPoint( )->nNode--; pCopyPam->GetPoint()->nNode--;
} }
aCpyPam.Exchange(); pCopyPam->Exchange();
// Also copy all bookmarks // Also copy all bookmarks
if( bCopyBookmarks && getIDocumentMarkAccess()->getMarksCount() ) if( bCopyBookmarks && getIDocumentMarkAccess()->getMarksCount() )
lcl_CopyBookmarks( rPam, aCpyPam ); lcl_CopyBookmarks( rPam, *pCopyPam );
if( nsRedlineMode_t::REDLINE_DELETE_REDLINES & eOld ) if( nsRedlineMode_t::REDLINE_DELETE_REDLINES & eOld )
lcl_DeleteRedlines( rPam, aCpyPam ); {
assert(*pCopyPam->GetPoint() == rPos);
// the Node rPos points to may be deleted so unregister ...
rPos.nContent = SwIndex(0);
lcl_DeleteRedlines(rPam, *pCopyPam);
rPos = *pCopyPam->GetPoint(); // ... and restore.
}
// If Undo is enabled, store the inserted area // If Undo is enabled, store the inserted area
if (pDoc->GetIDocumentUndoRedo().DoesUndo()) if (pDoc->GetIDocumentUndoRedo().DoesUndo())
{ {
pUndo->SetInsertRange( aCpyPam, sal_True, bStartIsTxtNode ); pUndo->SetInsertRange( *pCopyPam, sal_True, bStartIsTxtNode );
} }
if( pCpyRange ) if( pCpyRange )
{ {
pCpyRange->SetMark(); pCpyRange->SetMark();
*pCpyRange->GetPoint() = *aCpyPam.GetPoint(); *pCpyRange->GetPoint() = *pCopyPam->GetPoint();
*pCpyRange->GetMark() = *aCpyPam.GetMark(); *pCpyRange->GetMark() = *pCopyPam->GetMark();
} }
if ( pNumRuleToPropagate ) if ( pNumRuleToPropagate )
{ {
// #i86492# - use <SwDoc::SetNumRule(..)>, because it also handles the <ListId> // #i86492# - use <SwDoc::SetNumRule(..)>, because it also handles the <ListId>
pDoc->SetNumRule( aCpyPam, *pNumRuleToPropagate, false, pDoc->SetNumRule( *pCopyPam, *pNumRuleToPropagate, false,
aListIdToPropagate, sal_True, true ); aListIdToPropagate, sal_True, true );
} }