blob: 5747ab09e49a2869f74ebe9dacf81794b45c7878 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#include <UndoSplitMove.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 = sal_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 = sal_True;
bJoinNext = bJoinPrev = sal_False;
nSttCntnt = nEndCntnt = nMvDestCntnt = STRING_MAXLEN;
nSttNode = rRg.aStart.GetIndex();
nEndNode = rRg.aEnd.GetIndex();
// DelFtn( rRange );
// wird aus dem CntntBereich in den Sonderbereich verschoben ?
sal_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,
sal_Bool bJoin, sal_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, sal_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, sal_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( sal_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, sal_False );
aIdx = aPam.Start()->nNode;
sal_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();
sal_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;
}
}