354 lines
11 KiB
C++
354 lines
11 KiB
C++
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_sw.hxx"
|
|
|
|
#include <doc.hxx>
|
|
#include <IDocumentUndoRedo.hxx>
|
|
#include <pam.hxx>
|
|
#include <swundo.hxx> // fuer die UndoIds
|
|
#include <ndtxt.hxx>
|
|
#include <UndoCore.hxx>
|
|
#include <rolbck.hxx>
|
|
|
|
|
|
// MOVE
|
|
|
|
SwUndoMove::SwUndoMove( const SwPaM& rRange, const SwPosition& rMvPos )
|
|
: SwUndo( UNDO_MOVE ), SwUndRng( rRange ),
|
|
nMvDestNode( rMvPos.nNode.GetIndex() ),
|
|
nMvDestCntnt( rMvPos.nContent.GetIndex() ),
|
|
bMoveRedlines( false )
|
|
{
|
|
bMoveRange = bJoinNext = bJoinPrev = FALSE;
|
|
|
|
// StartNode vorm loeschen von Fussnoten besorgen!
|
|
SwDoc* pDoc = rRange.GetDoc();
|
|
SwTxtNode* pTxtNd = pDoc->GetNodes()[ nSttNode ]->GetTxtNode();
|
|
SwTxtNode* pEndTxtNd = pDoc->GetNodes()[ nEndNode ]->GetTxtNode();
|
|
|
|
pHistory = new SwHistory;
|
|
|
|
if( pTxtNd )
|
|
{
|
|
pHistory->Add( pTxtNd->GetTxtColl(), nSttNode, ND_TEXTNODE );
|
|
if ( pTxtNd->GetpSwpHints() )
|
|
{
|
|
pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nSttNode,
|
|
0, pTxtNd->GetTxt().Len(), false );
|
|
}
|
|
if( pTxtNd->HasSwAttrSet() )
|
|
pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nSttNode );
|
|
}
|
|
if( pEndTxtNd && pEndTxtNd != pTxtNd )
|
|
{
|
|
pHistory->Add( pEndTxtNd->GetTxtColl(), nEndNode, ND_TEXTNODE );
|
|
if ( pEndTxtNd->GetpSwpHints() )
|
|
{
|
|
pHistory->CopyAttr( pEndTxtNd->GetpSwpHints(), nEndNode,
|
|
0, pEndTxtNd->GetTxt().Len(), false );
|
|
}
|
|
if( pEndTxtNd->HasSwAttrSet() )
|
|
pHistory->CopyFmtAttr( *pEndTxtNd->GetpSwAttrSet(), nEndNode );
|
|
}
|
|
|
|
pTxtNd = rMvPos.nNode.GetNode().GetTxtNode();
|
|
if (0 != pTxtNd)
|
|
{
|
|
pHistory->Add( pTxtNd->GetTxtColl(), nMvDestNode, ND_TEXTNODE );
|
|
if ( pTxtNd->GetpSwpHints() )
|
|
{
|
|
pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nMvDestNode,
|
|
0, pTxtNd->GetTxt().Len(), false );
|
|
}
|
|
if( pTxtNd->HasSwAttrSet() )
|
|
pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nMvDestNode );
|
|
}
|
|
|
|
|
|
nFtnStt = pHistory->Count();
|
|
DelFtn( rRange );
|
|
|
|
if( pHistory && !pHistory->Count() )
|
|
DELETEZ( pHistory );
|
|
}
|
|
|
|
|
|
SwUndoMove::SwUndoMove( SwDoc* pDoc, const SwNodeRange& rRg,
|
|
const SwNodeIndex& rMvPos )
|
|
: SwUndo( UNDO_MOVE ),
|
|
nMvDestNode( rMvPos.GetIndex() ),
|
|
bMoveRedlines( false )
|
|
{
|
|
bMoveRange = TRUE;
|
|
bJoinNext = bJoinPrev = FALSE;
|
|
|
|
nSttCntnt = nEndCntnt = nMvDestCntnt = STRING_MAXLEN;
|
|
|
|
nSttNode = rRg.aStart.GetIndex();
|
|
nEndNode = rRg.aEnd.GetIndex();
|
|
|
|
// DelFtn( rRange );
|
|
|
|
// wird aus dem CntntBereich in den Sonderbereich verschoben ?
|
|
ULONG nCntntStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
|
|
if( nMvDestNode < nCntntStt && rRg.aStart.GetIndex() > nCntntStt )
|
|
{
|
|
// loesche alle Fussnoten. Diese sind dort nicht erwuenscht.
|
|
SwPosition aPtPos( rRg.aEnd );
|
|
SwCntntNode* pCNd = rRg.aEnd.GetNode().GetCntntNode();
|
|
if( pCNd )
|
|
aPtPos.nContent.Assign( pCNd, pCNd->Len() );
|
|
SwPosition aMkPos( rRg.aStart );
|
|
if( 0 != ( pCNd = aMkPos.nNode.GetNode().GetCntntNode() ))
|
|
aMkPos.nContent.Assign( pCNd, 0 );
|
|
|
|
DelCntntIndex( aMkPos, aPtPos, nsDelCntntType::DELCNT_FTN );
|
|
|
|
if( pHistory && !pHistory->Count() )
|
|
DELETEZ( pHistory );
|
|
}
|
|
|
|
nFtnStt = 0;
|
|
}
|
|
|
|
|
|
|
|
void SwUndoMove::SetDestRange( const SwPaM& rRange,
|
|
const SwPosition& rInsPos,
|
|
BOOL bJoin, BOOL bCorrPam )
|
|
{
|
|
const SwPosition *pStt = rRange.Start(),
|
|
*pEnd = rRange.GetPoint() == pStt
|
|
? rRange.GetMark()
|
|
: rRange.GetPoint();
|
|
|
|
nDestSttNode = pStt->nNode.GetIndex();
|
|
nDestSttCntnt = pStt->nContent.GetIndex();
|
|
nDestEndNode = pEnd->nNode.GetIndex();
|
|
nDestEndCntnt = pEnd->nContent.GetIndex();
|
|
|
|
nInsPosNode = rInsPos.nNode.GetIndex();
|
|
nInsPosCntnt = rInsPos.nContent.GetIndex();
|
|
|
|
if( bCorrPam )
|
|
{
|
|
nDestSttNode--;
|
|
nDestEndNode--;
|
|
}
|
|
|
|
bJoinNext = nDestSttNode != nDestEndNode &&
|
|
pStt->nNode.GetNode().GetTxtNode() &&
|
|
pEnd->nNode.GetNode().GetTxtNode();
|
|
bJoinPrev = bJoin;
|
|
}
|
|
|
|
|
|
void SwUndoMove::SetDestRange( const SwNodeIndex& rStt,
|
|
const SwNodeIndex& rEnd,
|
|
const SwNodeIndex& rInsPos )
|
|
{
|
|
nDestSttNode = rStt.GetIndex();
|
|
nDestEndNode = rEnd.GetIndex();
|
|
if( nDestSttNode > nDestEndNode )
|
|
{
|
|
nDestSttNode = nDestEndNode;
|
|
nDestEndNode = rStt.GetIndex();
|
|
}
|
|
nInsPosNode = rInsPos.GetIndex();
|
|
|
|
nDestSttCntnt = nDestEndCntnt = nInsPosCntnt = STRING_MAXLEN;
|
|
}
|
|
|
|
|
|
void SwUndoMove::UndoImpl(::sw::UndoRedoContext & rContext)
|
|
{
|
|
SwDoc *const pDoc = & rContext.GetDoc();
|
|
|
|
// Block, damit aus diesem gesprungen werden kann
|
|
do {
|
|
// erzeuge aus den Werten die Insert-Position und den Bereich
|
|
SwNodeIndex aIdx( pDoc->GetNodes(), nDestSttNode );
|
|
|
|
if( bMoveRange )
|
|
{
|
|
// nur ein Move mit SwRange
|
|
SwNodeRange aRg( aIdx, aIdx );
|
|
aRg.aEnd = nDestEndNode;
|
|
aIdx = nInsPosNode;
|
|
bool bSuccess = pDoc->MoveNodeRange( aRg, aIdx,
|
|
IDocumentContentOperations::DOC_MOVEDEFAULT );
|
|
if (!bSuccess)
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
SwPaM aPam( aIdx.GetNode(), nDestSttCntnt,
|
|
*pDoc->GetNodes()[ nDestEndNode ], nDestEndCntnt );
|
|
|
|
// #i17764# if redlines are to be moved, we may not remove them before
|
|
// pDoc->Move gets a chance to handle them
|
|
if( ! bMoveRedlines )
|
|
RemoveIdxFromRange( aPam, FALSE );
|
|
|
|
SwPosition aPos( *pDoc->GetNodes()[ nInsPosNode] );
|
|
SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode();
|
|
aPos.nContent.Assign( pCNd, nInsPosCntnt );
|
|
|
|
if( pCNd->HasSwAttrSet() )
|
|
pCNd->ResetAllAttr();
|
|
|
|
if( pCNd->IsTxtNode() && ((SwTxtNode*)pCNd)->GetpSwpHints() )
|
|
((SwTxtNode*)pCNd)->ClearSwpHintsArr( false );
|
|
|
|
// an der InsertPos erstmal alle Attribute entfernen,
|
|
const bool bSuccess = pDoc->MoveRange( aPam, aPos, (bMoveRedlines)
|
|
? IDocumentContentOperations::DOC_MOVEREDLINES
|
|
: IDocumentContentOperations::DOC_MOVEDEFAULT );
|
|
if (!bSuccess)
|
|
break;
|
|
|
|
aPam.Exchange();
|
|
aPam.DeleteMark();
|
|
// pDoc->ResetAttr( aPam, FALSE );
|
|
if( aPam.GetNode()->IsCntntNode() )
|
|
aPam.GetNode()->GetCntntNode()->ResetAllAttr();
|
|
// der Pam wird jetzt aufgegeben.
|
|
}
|
|
|
|
SwTxtNode* pTxtNd = aIdx.GetNode().GetTxtNode();
|
|
if( bJoinNext )
|
|
{
|
|
{
|
|
RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
|
|
SwIndex( pTxtNd, pTxtNd->GetTxt().Len() ) ) );
|
|
}
|
|
// sind keine Pams mehr im naechsten TextNode
|
|
pTxtNd->JoinNext();
|
|
}
|
|
|
|
if( bJoinPrev && pTxtNd->CanJoinPrev( &aIdx ) )
|
|
{
|
|
// ?? sind keine Pams mehr im naechsten TextNode ??
|
|
pTxtNd = aIdx.GetNode().GetTxtNode();
|
|
{
|
|
RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
|
|
SwIndex( pTxtNd, pTxtNd->GetTxt().Len() ) ) );
|
|
}
|
|
pTxtNd->JoinNext();
|
|
}
|
|
|
|
} while( FALSE );
|
|
|
|
if( pHistory )
|
|
{
|
|
if( nFtnStt != pHistory->Count() )
|
|
pHistory->Rollback( pDoc, nFtnStt );
|
|
pHistory->TmpRollback( pDoc, 0 );
|
|
pHistory->SetTmpEnd( pHistory->Count() );
|
|
}
|
|
|
|
// setze noch den Cursor auf den Undo-Bereich
|
|
if( !bMoveRange )
|
|
{
|
|
AddUndoRedoPaM(rContext);
|
|
}
|
|
}
|
|
|
|
|
|
void SwUndoMove::RedoImpl(::sw::UndoRedoContext & rContext)
|
|
{
|
|
SwPaM *const pPam = & AddUndoRedoPaM(rContext);
|
|
SwDoc & rDoc = rContext.GetDoc();
|
|
|
|
SwNodes& rNds = rDoc.GetNodes();
|
|
SwNodeIndex aIdx( rNds, nMvDestNode );
|
|
|
|
if( bMoveRange )
|
|
{
|
|
// nur ein Move mit SwRange
|
|
SwNodeRange aRg( rNds, nSttNode, rNds, nEndNode );
|
|
rDoc.MoveNodeRange( aRg, aIdx, (bMoveRedlines)
|
|
? IDocumentContentOperations::DOC_MOVEREDLINES
|
|
: IDocumentContentOperations::DOC_MOVEDEFAULT );
|
|
}
|
|
else
|
|
{
|
|
SwPaM aPam( *pPam->GetPoint() );
|
|
SetPaM( aPam );
|
|
SwPosition aMvPos( aIdx, SwIndex( aIdx.GetNode().GetCntntNode(),
|
|
nMvDestCntnt ));
|
|
|
|
DelFtn( aPam );
|
|
RemoveIdxFromRange( aPam, FALSE );
|
|
|
|
aIdx = aPam.Start()->nNode;
|
|
BOOL bJoinTxt = aIdx.GetNode().IsTxtNode();
|
|
|
|
aIdx--;
|
|
rDoc.MoveRange( aPam, aMvPos,
|
|
IDocumentContentOperations::DOC_MOVEDEFAULT );
|
|
|
|
if( nSttNode != nEndNode && bJoinTxt )
|
|
{
|
|
aIdx++;
|
|
SwTxtNode * pTxtNd = aIdx.GetNode().GetTxtNode();
|
|
if( pTxtNd && pTxtNd->CanJoinNext() )
|
|
{
|
|
{
|
|
RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
|
|
SwIndex( pTxtNd, pTxtNd->GetTxt().Len() ) ) );
|
|
}
|
|
pTxtNd->JoinNext();
|
|
}
|
|
}
|
|
*pPam->GetPoint() = *aPam.GetPoint();
|
|
pPam->SetMark();
|
|
*pPam->GetMark() = *aPam.GetMark();
|
|
}
|
|
}
|
|
|
|
|
|
void SwUndoMove::DelFtn( const SwPaM& rRange )
|
|
{
|
|
// wird aus dem CntntBereich in den Sonderbereich verschoben ?
|
|
SwDoc* pDoc = rRange.GetDoc();
|
|
ULONG nCntntStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
|
|
if( nMvDestNode < nCntntStt &&
|
|
rRange.GetPoint()->nNode.GetIndex() >= nCntntStt )
|
|
{
|
|
// loesche alle Fussnoten. Diese sind dort nicht erwuenscht.
|
|
DelCntntIndex( *rRange.GetMark(), *rRange.GetPoint(),
|
|
nsDelCntntType::DELCNT_FTN );
|
|
|
|
if( pHistory && !pHistory->Count() )
|
|
delete pHistory, pHistory = 0;
|
|
}
|
|
}
|
|
|