1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sw.hxx" 30 31 #include <UndoSplitMove.hxx> 32 33 #include <doc.hxx> 34 #include <IDocumentUndoRedo.hxx> 35 #include <pam.hxx> 36 #include <swundo.hxx> // fuer die UndoIds 37 #include <ndtxt.hxx> 38 #include <UndoCore.hxx> 39 #include <rolbck.hxx> 40 41 42 // MOVE 43 44 SwUndoMove::SwUndoMove( const SwPaM& rRange, const SwPosition& rMvPos ) 45 : SwUndo( UNDO_MOVE ), SwUndRng( rRange ), 46 nMvDestNode( rMvPos.nNode.GetIndex() ), 47 nMvDestCntnt( rMvPos.nContent.GetIndex() ), 48 bMoveRedlines( false ) 49 { 50 bMoveRange = bJoinNext = bJoinPrev = sal_False; 51 52 // StartNode vorm loeschen von Fussnoten besorgen! 53 SwDoc* pDoc = rRange.GetDoc(); 54 SwTxtNode* pTxtNd = pDoc->GetNodes()[ nSttNode ]->GetTxtNode(); 55 SwTxtNode* pEndTxtNd = pDoc->GetNodes()[ nEndNode ]->GetTxtNode(); 56 57 pHistory = new SwHistory; 58 59 if( pTxtNd ) 60 { 61 pHistory->Add( pTxtNd->GetTxtColl(), nSttNode, ND_TEXTNODE ); 62 if ( pTxtNd->GetpSwpHints() ) 63 { 64 pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nSttNode, 65 0, pTxtNd->GetTxt().Len(), false ); 66 } 67 if( pTxtNd->HasSwAttrSet() ) 68 pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nSttNode ); 69 } 70 if( pEndTxtNd && pEndTxtNd != pTxtNd ) 71 { 72 pHistory->Add( pEndTxtNd->GetTxtColl(), nEndNode, ND_TEXTNODE ); 73 if ( pEndTxtNd->GetpSwpHints() ) 74 { 75 pHistory->CopyAttr( pEndTxtNd->GetpSwpHints(), nEndNode, 76 0, pEndTxtNd->GetTxt().Len(), false ); 77 } 78 if( pEndTxtNd->HasSwAttrSet() ) 79 pHistory->CopyFmtAttr( *pEndTxtNd->GetpSwAttrSet(), nEndNode ); 80 } 81 82 pTxtNd = rMvPos.nNode.GetNode().GetTxtNode(); 83 if (0 != pTxtNd) 84 { 85 pHistory->Add( pTxtNd->GetTxtColl(), nMvDestNode, ND_TEXTNODE ); 86 if ( pTxtNd->GetpSwpHints() ) 87 { 88 pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nMvDestNode, 89 0, pTxtNd->GetTxt().Len(), false ); 90 } 91 if( pTxtNd->HasSwAttrSet() ) 92 pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nMvDestNode ); 93 } 94 95 96 nFtnStt = pHistory->Count(); 97 DelFtn( rRange ); 98 99 if( pHistory && !pHistory->Count() ) 100 DELETEZ( pHistory ); 101 } 102 103 104 SwUndoMove::SwUndoMove( SwDoc* pDoc, const SwNodeRange& rRg, 105 const SwNodeIndex& rMvPos ) 106 : SwUndo( UNDO_MOVE ), 107 nMvDestNode( rMvPos.GetIndex() ), 108 bMoveRedlines( false ) 109 { 110 bMoveRange = sal_True; 111 bJoinNext = bJoinPrev = sal_False; 112 113 nSttCntnt = nEndCntnt = nMvDestCntnt = STRING_MAXLEN; 114 115 nSttNode = rRg.aStart.GetIndex(); 116 nEndNode = rRg.aEnd.GetIndex(); 117 118 // DelFtn( rRange ); 119 120 // wird aus dem CntntBereich in den Sonderbereich verschoben ? 121 sal_uLong nCntntStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex(); 122 if( nMvDestNode < nCntntStt && rRg.aStart.GetIndex() > nCntntStt ) 123 { 124 // loesche alle Fussnoten. Diese sind dort nicht erwuenscht. 125 SwPosition aPtPos( rRg.aEnd ); 126 SwCntntNode* pCNd = rRg.aEnd.GetNode().GetCntntNode(); 127 if( pCNd ) 128 aPtPos.nContent.Assign( pCNd, pCNd->Len() ); 129 SwPosition aMkPos( rRg.aStart ); 130 if( 0 != ( pCNd = aMkPos.nNode.GetNode().GetCntntNode() )) 131 aMkPos.nContent.Assign( pCNd, 0 ); 132 133 DelCntntIndex( aMkPos, aPtPos, nsDelCntntType::DELCNT_FTN ); 134 135 if( pHistory && !pHistory->Count() ) 136 DELETEZ( pHistory ); 137 } 138 139 nFtnStt = 0; 140 } 141 142 143 144 void SwUndoMove::SetDestRange( const SwPaM& rRange, 145 const SwPosition& rInsPos, 146 sal_Bool bJoin, sal_Bool bCorrPam ) 147 { 148 const SwPosition *pStt = rRange.Start(), 149 *pEnd = rRange.GetPoint() == pStt 150 ? rRange.GetMark() 151 : rRange.GetPoint(); 152 153 nDestSttNode = pStt->nNode.GetIndex(); 154 nDestSttCntnt = pStt->nContent.GetIndex(); 155 nDestEndNode = pEnd->nNode.GetIndex(); 156 nDestEndCntnt = pEnd->nContent.GetIndex(); 157 158 nInsPosNode = rInsPos.nNode.GetIndex(); 159 nInsPosCntnt = rInsPos.nContent.GetIndex(); 160 161 if( bCorrPam ) 162 { 163 nDestSttNode--; 164 nDestEndNode--; 165 } 166 167 bJoinNext = nDestSttNode != nDestEndNode && 168 pStt->nNode.GetNode().GetTxtNode() && 169 pEnd->nNode.GetNode().GetTxtNode(); 170 bJoinPrev = bJoin; 171 } 172 173 174 void SwUndoMove::SetDestRange( const SwNodeIndex& rStt, 175 const SwNodeIndex& rEnd, 176 const SwNodeIndex& rInsPos ) 177 { 178 nDestSttNode = rStt.GetIndex(); 179 nDestEndNode = rEnd.GetIndex(); 180 if( nDestSttNode > nDestEndNode ) 181 { 182 nDestSttNode = nDestEndNode; 183 nDestEndNode = rStt.GetIndex(); 184 } 185 nInsPosNode = rInsPos.GetIndex(); 186 187 nDestSttCntnt = nDestEndCntnt = nInsPosCntnt = STRING_MAXLEN; 188 } 189 190 191 void SwUndoMove::UndoImpl(::sw::UndoRedoContext & rContext) 192 { 193 SwDoc *const pDoc = & rContext.GetDoc(); 194 195 // Block, damit aus diesem gesprungen werden kann 196 do { 197 // erzeuge aus den Werten die Insert-Position und den Bereich 198 SwNodeIndex aIdx( pDoc->GetNodes(), nDestSttNode ); 199 200 if( bMoveRange ) 201 { 202 // nur ein Move mit SwRange 203 SwNodeRange aRg( aIdx, aIdx ); 204 aRg.aEnd = nDestEndNode; 205 aIdx = nInsPosNode; 206 bool bSuccess = pDoc->MoveNodeRange( aRg, aIdx, 207 IDocumentContentOperations::DOC_MOVEDEFAULT ); 208 if (!bSuccess) 209 break; 210 } 211 else 212 { 213 SwPaM aPam( aIdx.GetNode(), nDestSttCntnt, 214 *pDoc->GetNodes()[ nDestEndNode ], nDestEndCntnt ); 215 216 // #i17764# if redlines are to be moved, we may not remove them before 217 // pDoc->Move gets a chance to handle them 218 if( ! bMoveRedlines ) 219 RemoveIdxFromRange( aPam, sal_False ); 220 221 SwPosition aPos( *pDoc->GetNodes()[ nInsPosNode] ); 222 SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode(); 223 aPos.nContent.Assign( pCNd, nInsPosCntnt ); 224 225 if( pCNd->HasSwAttrSet() ) 226 pCNd->ResetAllAttr(); 227 228 if( pCNd->IsTxtNode() && ((SwTxtNode*)pCNd)->GetpSwpHints() ) 229 ((SwTxtNode*)pCNd)->ClearSwpHintsArr( false ); 230 231 // an der InsertPos erstmal alle Attribute entfernen, 232 const bool bSuccess = pDoc->MoveRange( aPam, aPos, (bMoveRedlines) 233 ? IDocumentContentOperations::DOC_MOVEREDLINES 234 : IDocumentContentOperations::DOC_MOVEDEFAULT ); 235 if (!bSuccess) 236 break; 237 238 aPam.Exchange(); 239 aPam.DeleteMark(); 240 // pDoc->ResetAttr( aPam, sal_False ); 241 if( aPam.GetNode()->IsCntntNode() ) 242 aPam.GetNode()->GetCntntNode()->ResetAllAttr(); 243 // der Pam wird jetzt aufgegeben. 244 } 245 246 SwTxtNode* pTxtNd = aIdx.GetNode().GetTxtNode(); 247 if( bJoinNext ) 248 { 249 { 250 RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx, 251 SwIndex( pTxtNd, pTxtNd->GetTxt().Len() ) ) ); 252 } 253 // sind keine Pams mehr im naechsten TextNode 254 pTxtNd->JoinNext(); 255 } 256 257 if( bJoinPrev && pTxtNd->CanJoinPrev( &aIdx ) ) 258 { 259 // ?? sind keine Pams mehr im naechsten TextNode ?? 260 pTxtNd = aIdx.GetNode().GetTxtNode(); 261 { 262 RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx, 263 SwIndex( pTxtNd, pTxtNd->GetTxt().Len() ) ) ); 264 } 265 pTxtNd->JoinNext(); 266 } 267 268 } while( sal_False ); 269 270 if( pHistory ) 271 { 272 if( nFtnStt != pHistory->Count() ) 273 pHistory->Rollback( pDoc, nFtnStt ); 274 pHistory->TmpRollback( pDoc, 0 ); 275 pHistory->SetTmpEnd( pHistory->Count() ); 276 } 277 278 // setze noch den Cursor auf den Undo-Bereich 279 if( !bMoveRange ) 280 { 281 AddUndoRedoPaM(rContext); 282 } 283 } 284 285 286 void SwUndoMove::RedoImpl(::sw::UndoRedoContext & rContext) 287 { 288 SwPaM *const pPam = & AddUndoRedoPaM(rContext); 289 SwDoc & rDoc = rContext.GetDoc(); 290 291 SwNodes& rNds = rDoc.GetNodes(); 292 SwNodeIndex aIdx( rNds, nMvDestNode ); 293 294 if( bMoveRange ) 295 { 296 // nur ein Move mit SwRange 297 SwNodeRange aRg( rNds, nSttNode, rNds, nEndNode ); 298 rDoc.MoveNodeRange( aRg, aIdx, (bMoveRedlines) 299 ? IDocumentContentOperations::DOC_MOVEREDLINES 300 : IDocumentContentOperations::DOC_MOVEDEFAULT ); 301 } 302 else 303 { 304 SwPaM aPam( *pPam->GetPoint() ); 305 SetPaM( aPam ); 306 SwPosition aMvPos( aIdx, SwIndex( aIdx.GetNode().GetCntntNode(), 307 nMvDestCntnt )); 308 309 DelFtn( aPam ); 310 RemoveIdxFromRange( aPam, sal_False ); 311 312 aIdx = aPam.Start()->nNode; 313 sal_Bool bJoinTxt = aIdx.GetNode().IsTxtNode(); 314 315 aIdx--; 316 rDoc.MoveRange( aPam, aMvPos, 317 IDocumentContentOperations::DOC_MOVEDEFAULT ); 318 319 if( nSttNode != nEndNode && bJoinTxt ) 320 { 321 aIdx++; 322 SwTxtNode * pTxtNd = aIdx.GetNode().GetTxtNode(); 323 if( pTxtNd && pTxtNd->CanJoinNext() ) 324 { 325 { 326 RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx, 327 SwIndex( pTxtNd, pTxtNd->GetTxt().Len() ) ) ); 328 } 329 pTxtNd->JoinNext(); 330 } 331 } 332 *pPam->GetPoint() = *aPam.GetPoint(); 333 pPam->SetMark(); 334 *pPam->GetMark() = *aPam.GetMark(); 335 } 336 } 337 338 339 void SwUndoMove::DelFtn( const SwPaM& rRange ) 340 { 341 // wird aus dem CntntBereich in den Sonderbereich verschoben ? 342 SwDoc* pDoc = rRange.GetDoc(); 343 sal_uLong nCntntStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex(); 344 if( nMvDestNode < nCntntStt && 345 rRange.GetPoint()->nNode.GetIndex() >= nCntntStt ) 346 { 347 // loesche alle Fussnoten. Diese sind dort nicht erwuenscht. 348 DelCntntIndex( *rRange.GetMark(), *rRange.GetPoint(), 349 nsDelCntntType::DELCNT_FTN ); 350 351 if( pHistory && !pHistory->Count() ) 352 delete pHistory, pHistory = 0; 353 } 354 } 355 356