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 <stdlib.h> 32 33 #include <node.hxx> 34 #include <doc.hxx> 35 #include <IDocumentUndoRedo.hxx> 36 #include <pam.hxx> 37 #include <txtfld.hxx> 38 #include <fmtfld.hxx> 39 #include <hints.hxx> 40 #include <numrule.hxx> 41 #include <ndtxt.hxx> 42 #include <ndnotxt.hxx> 43 #include <swtable.hxx> // fuer erzuegen / loeschen der Table-Frames 44 #include <tblsel.hxx> 45 #include <section.hxx> 46 #include <ddefld.hxx> 47 #include <swddetbl.hxx> 48 #include <frame.hxx> 49 #include <txtatr.hxx> 50 #include <tox.hxx> // InvalidateTOXMark 51 52 #include <docsh.hxx> 53 #include <svl/smplhint.hxx> 54 55 extern sal_Bool CheckNodesRange( const SwNodeIndex& rStt, 56 const SwNodeIndex& rEnd, sal_Bool bChkSection ); 57 58 SV_DECL_PTRARR(SwSttNdPtrs,SwStartNode*,2,2) 59 60 61 //#define JP_DEBUG 62 #ifdef JP_DEBUG 63 #include "shellio.hxx" 64 #endif 65 66 67 // Funktion zum bestimmen des hoechsten Levels innerhalb des Bereiches 68 69 sal_uInt16 HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange ); 70 71 //----------------------------------------------------------------------- 72 73 /******************************************************************* 74 |* SwNodes::SwNodes 75 |* 76 |* Beschreibung 77 |* Konstruktor; legt die vier Grundsektions (PostIts, 78 |* Inserts, Icons, Inhalt) an 79 *******************************************************************/ 80 SwNodes::SwNodes( SwDoc* pDocument ) 81 : pRoot( 0 ), pMyDoc( pDocument ) 82 { 83 bInNodesDel = bInDelUpdOutl = bInDelUpdNum = sal_False; 84 85 ASSERT( pMyDoc, "in welchem Doc stehe ich denn?" ); 86 87 sal_uLong nPos = 0; 88 SwStartNode* pSttNd = new SwStartNode( *this, nPos++ ); 89 pEndOfPostIts = new SwEndNode( *this, nPos++, *pSttNd ); 90 91 SwStartNode* pTmp = new SwStartNode( *this, nPos++ ); 92 pEndOfInserts = new SwEndNode( *this, nPos++, *pTmp ); 93 94 pTmp = new SwStartNode( *this, nPos++ ); 95 pTmp->pStartOfSection = pSttNd; 96 pEndOfAutotext = new SwEndNode( *this, nPos++, *pTmp ); 97 98 pTmp = new SwStartNode( *this, nPos++ ); 99 pTmp->pStartOfSection = pSttNd; 100 pEndOfRedlines = new SwEndNode( *this, nPos++, *pTmp ); 101 102 pTmp = new SwStartNode( *this, nPos++ ); 103 pTmp->pStartOfSection = pSttNd; 104 pEndOfContent = new SwEndNode( *this, nPos++, *pTmp ); 105 106 pOutlineNds = new SwOutlineNodes; 107 } 108 109 /******************************************************************* 110 |* 111 |* SwNodes::~SwNodes 112 |* 113 |* Beschreibung 114 |* dtor, loescht alle Nodes, deren Pointer in diesem dynamischen 115 |* Array sind. Ist kein Problem, da Nodes ausserhalb dieses 116 |* Arrays nicht erzeugt werden koennen und somit auch nicht 117 |* in mehreren drin sein koennen 118 |* 119 |* Ersterstellung 120 |* VER0100 vb 901214 121 |* 122 |* Stand 123 |* VER0100 vb 901214 124 |* 125 *******************************************************************/ 126 127 SwNodes::~SwNodes() 128 { 129 delete pOutlineNds; 130 131 { 132 SwNode *pNode; 133 SwNodeIndex aNdIdx( *this ); 134 while( sal_True ) 135 { 136 pNode = &aNdIdx.GetNode(); 137 if( pNode == pEndOfContent ) 138 break; 139 140 aNdIdx++; 141 delete pNode; 142 } 143 } 144 145 // jetzt muessen alle SwNodeIndizies abgemeldet sein!!! 146 delete pEndOfContent; 147 } 148 149 void SwNodes::ChgNode( SwNodeIndex& rDelPos, sal_uLong nSz, 150 SwNodeIndex& rInsPos, sal_Bool bNewFrms ) 151 { 152 // im UndoBereich brauchen wir keine Frames 153 SwNodes& rNds = rInsPos.GetNodes(); 154 const SwNode* pPrevInsNd = rNds[ rInsPos.GetIndex() -1 ]; 155 156 //JP 03.02.99: alle Felder als invalide erklaeren, aktu. erfolgt im 157 // Idle-Handler des Docs 158 if( GetDoc()->SetFieldsDirty( sal_True, &rDelPos.GetNode(), nSz ) && 159 rNds.GetDoc() != GetDoc() ) 160 rNds.GetDoc()->SetFieldsDirty( true, NULL, 0 ); 161 162 //JP 12.03.99: 63293 - Nodes vom RedlineBereich NIE aufnehmen 163 sal_uLong nNd = rInsPos.GetIndex(); 164 sal_Bool bInsOutlineIdx = !( 165 rNds.GetEndOfRedlines().StartOfSectionNode()->GetIndex() < nNd && 166 nNd < rNds.GetEndOfRedlines().GetIndex() ); 167 168 if( &rNds == this ) // im gleichen Nodes-Array -> moven !! 169 { 170 // wird von vorne nach hinten gemovt, so wird nach vorne immer 171 // nachgeschoben, d.H. die Loeschposition ist immer gleich 172 sal_uInt16 nDiff = rDelPos.GetIndex() < rInsPos.GetIndex() ? 0 : 1; 173 174 for( sal_uLong n = rDelPos.GetIndex(); nSz; n += nDiff, --nSz ) 175 { 176 SwNodeIndex aDelIdx( *this, n ); 177 SwNode& rNd = aDelIdx.GetNode(); 178 179 // --> OD 2005-11-16 #i57920# 180 // correction of refactoring done by cws swnumtree: 181 // - <SwTxtNode::SetLevel( NO_NUMBERING ) is deprecated and 182 // set <IsCounted> state of the text node to <false>, which 183 // isn't correct here. 184 if ( rNd.IsTxtNode() ) 185 { 186 SwTxtNode* pTxtNode = rNd.GetTxtNode(); 187 // --> OD 2008-03-13 #refactorlists# 188 // pTxtNode->UnregisterNumber(); 189 pTxtNode->RemoveFromList(); 190 // <-- 191 192 //if ( pTxtNode->GetTxtColl()->GetOutlineLevel() != NO_NUMBERING )//#outline level,zhaojianwei 193 if ( pTxtNode->GetAttrOutlineLevel() != 0 )//<-end,zhaojianwei 194 { 195 const SwNodePtr pSrch = (SwNodePtr)&rNd; 196 pOutlineNds->Remove( pSrch ); 197 } 198 } 199 // <-- 200 201 BigPtrArray::Move( aDelIdx.GetIndex(), rInsPos.GetIndex() ); 202 203 if( rNd.IsTxtNode() ) 204 { 205 SwTxtNode& rTxtNd = (SwTxtNode&)rNd; 206 // --> OD 2008-03-13 #refactorlists# 207 // rTxtNd.SyncNumberAndNumRule(); 208 rTxtNd.AddToList(); 209 // <-- 210 211 if( bInsOutlineIdx && 212 //NO_NUMBERING != rTxtNd.GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei 213 0 != rTxtNd.GetAttrOutlineLevel() )//<-end,zhaojianwei 214 { 215 const SwNodePtr pSrch = (SwNodePtr)&rNd; 216 pOutlineNds->Insert( pSrch ); 217 } 218 rTxtNd.InvalidateNumRule(); 219 220 //FEATURE::CONDCOLL 221 if( RES_CONDTXTFMTCOLL == rTxtNd.GetTxtColl()->Which() ) 222 rTxtNd.ChkCondColl(); 223 //FEATURE::CONDCOLL 224 } 225 else if( rNd.IsCntntNode() ) 226 ((SwCntntNode&)rNd).InvalidateNumRule(); 227 } 228 } 229 else 230 { 231 bool bSavePersData(GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(rNds)); 232 bool bRestPersData(GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(*this)); 233 SwDoc* pDestDoc = rNds.GetDoc() != GetDoc() ? rNds.GetDoc() : 0; 234 OSL_ENSURE(!pDestDoc, "SwNodes::ChgNode(): " 235 "the code to handle text fields here looks broken\n" 236 "if the target is in a different document."); 237 if( !bRestPersData && !bSavePersData && pDestDoc ) 238 bSavePersData = bRestPersData = sal_True; 239 240 String sNumRule; 241 SwNodeIndex aInsPos( rInsPos ); 242 for( sal_uLong n = 0; n < nSz; n++ ) 243 { 244 SwNode* pNd = &rDelPos.GetNode(); 245 246 // NoTextNode muessen ihre Persitenten Daten mitnehmen 247 if( pNd->IsNoTxtNode() ) 248 { 249 if( bSavePersData ) 250 ((SwNoTxtNode*)pNd)->SavePersistentData(); 251 } 252 else if( pNd->IsTxtNode() ) 253 { 254 SwTxtNode* pTxtNd = (SwTxtNode*)pNd; 255 256 // loesche die Gliederungs-Indizies aus dem alten Nodes-Array 257 //if( NO_NUMBERING != pTxtNd->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei 258 if( 0 != pTxtNd->GetAttrOutlineLevel() )//<-end,zhaojianwei 259 pOutlineNds->Remove( pNd ); 260 261 // muss die Rule kopiere werden? 262 if( pDestDoc ) 263 { 264 const SwNumRule* pNumRule = pTxtNd->GetNumRule(); 265 if( pNumRule && sNumRule != pNumRule->GetName() ) 266 { 267 sNumRule = pNumRule->GetName(); 268 SwNumRule* pDestRule = pDestDoc->FindNumRulePtr( sNumRule ); 269 if( pDestRule ) 270 pDestRule->SetInvalidRule( sal_True ); 271 else 272 pDestDoc->MakeNumRule( sNumRule, pNumRule ); 273 } 274 } 275 else 276 // wenns ins UndoNodes-Array gemoved wird, sollten die 277 // Numerierungen auch aktualisiert werden. 278 pTxtNd->InvalidateNumRule(); 279 280 // --> OD 2008-03-13 #refactorlists# 281 // pTxtNd->UnregisterNumber(); 282 pTxtNd->RemoveFromList(); 283 // <-- 284 } 285 286 RemoveNode( rDelPos.GetIndex(), 1, sal_False ); // Indizies verschieben !! 287 SwCntntNode * pCNd = pNd->GetCntntNode(); 288 rNds.InsertNode( pNd, aInsPos ); 289 290 if( pCNd ) 291 { 292 SwTxtNode* pTxtNd = pCNd->GetTxtNode(); 293 if( pTxtNd ) 294 { 295 SwpHints * const pHts = pTxtNd->GetpSwpHints(); 296 // setze die OultineNodes im neuen Nodes-Array 297 //if( bInsOutlineIdx && NO_NUMBERING != //#outline level,removed by zhaojianwei 298 // pTxtNd->GetTxtColl()->GetOutlineLevel() ) 299 if( bInsOutlineIdx && 300 0 != pTxtNd->GetAttrOutlineLevel() ) //#outline level,added by zhaojianwei 301 { 302 rNds.pOutlineNds->Insert( pTxtNd ); 303 } 304 305 // --> OD 2008-03-13 #refactorlists# 306 // pTxtNd->SyncNumberAndNumRule(); 307 pTxtNd->AddToList(); 308 // <-- 309 310 // Sonderbehandlung fuer die Felder! 311 if( pHts && pHts->Count() ) 312 { 313 // this looks fishy if pDestDoc != 0 314 bool const bToUndo = !pDestDoc && 315 GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(rNds); 316 for( sal_uInt16 i = pHts->Count(); i; ) 317 { 318 sal_uInt16 nDelMsg = 0; 319 SwTxtAttr * const pAttr = pHts->GetTextHint( --i ); 320 switch ( pAttr->Which() ) 321 { 322 case RES_TXTATR_FIELD: 323 { 324 SwTxtFld* pTxtFld = 325 static_cast<SwTxtFld*>(pAttr); 326 rNds.GetDoc()->InsDelFldInFldLst( !bToUndo, *pTxtFld ); 327 328 const SwFieldType* pTyp = pTxtFld->GetFld().GetFld()->GetTyp(); 329 if ( RES_POSTITFLD == pTyp->Which() ) 330 { 331 rNds.GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( &pTxtFld->GetFld(), pTxtFld->GetFld().IsFldInDoc() ? SWFMTFLD_INSERTED : SWFMTFLD_REMOVED ) ); 332 } 333 else 334 if( RES_DDEFLD == pTyp->Which() ) 335 { 336 if( bToUndo ) 337 ((SwDDEFieldType*)pTyp)->DecRefCnt(); 338 else 339 ((SwDDEFieldType*)pTyp)->IncRefCnt(); 340 } 341 nDelMsg = RES_FIELD_DELETED; 342 } 343 break; 344 case RES_TXTATR_FTN: 345 nDelMsg = RES_FOOTNOTE_DELETED; 346 break; 347 348 case RES_TXTATR_TOXMARK: 349 static_cast<SwTOXMark&>(pAttr->GetAttr()) 350 .InvalidateTOXMark(); 351 break; 352 353 case RES_TXTATR_REFMARK: 354 nDelMsg = RES_REFMARK_DELETED; 355 break; 356 357 case RES_TXTATR_META: 358 case RES_TXTATR_METAFIELD: 359 { 360 SwTxtMeta *const pTxtMeta( 361 static_cast<SwTxtMeta*>(pAttr)); 362 // force removal of UNO object 363 pTxtMeta->ChgTxtNode(0); 364 pTxtMeta->ChgTxtNode(pTxtNd); 365 } 366 break; 367 368 default: 369 break; 370 } 371 if( nDelMsg && bToUndo ) 372 { 373 SwPtrMsgPoolItem aMsgHint( nDelMsg, 374 (void*)&pAttr->GetAttr() ); 375 rNds.GetDoc()->GetUnoCallBack()-> 376 ModifyNotification( &aMsgHint, &aMsgHint ); 377 } 378 } 379 } 380 //FEATURE::CONDCOLL 381 if( RES_CONDTXTFMTCOLL == pTxtNd->GetTxtColl()->Which() ) 382 pTxtNd->ChkCondColl(); 383 //FEATURE::CONDCOLL 384 } 385 else 386 { 387 // in unterschiedliche Docs gemoved ? 388 // dann die Daten wieder persistent machen 389 if( pCNd->IsNoTxtNode() && bRestPersData ) 390 ((SwNoTxtNode*)pCNd)->RestorePersistentData(); 391 } 392 } 393 } 394 } 395 396 //JP 03.02.99: alle Felder als invalide erklaeren, aktu. erfolgt im 397 // Idle-Handler des Docs 398 GetDoc()->SetFieldsDirty( true, NULL, 0 ); 399 if( rNds.GetDoc() != GetDoc() ) 400 rNds.GetDoc()->SetFieldsDirty( true, NULL, 0 ); 401 402 403 if( bNewFrms ) 404 bNewFrms = &GetDoc()->GetNodes() == (const SwNodes*)&rNds && 405 GetDoc()->GetCurrentViewShell(); //swmod 071108//swmod 071225 406 if( bNewFrms ) 407 { 408 // Frames besorgen: 409 SwNodeIndex aIdx( *pPrevInsNd, 1 ); 410 SwNodeIndex aFrmNdIdx( aIdx ); 411 SwNode* pFrmNd = rNds.FindPrvNxtFrmNode( aFrmNdIdx, 412 rNds[ rInsPos.GetIndex() - 1 ] ); 413 414 if( !pFrmNd && aFrmNdIdx > rNds.GetEndOfExtras().GetIndex() ) 415 { 416 ASSERT( !this, "ob das so richtig ist ??" ); 417 aFrmNdIdx = rNds.GetEndOfContent(); 418 pFrmNd = rNds.GoPrevSection( &aFrmNdIdx, sal_True, sal_False ); 419 if( pFrmNd && !((SwCntntNode*)pFrmNd)->GetDepends() ) 420 pFrmNd = 0; 421 422 #ifdef DBG_UTIL 423 if( !pFrmNd ) 424 ASSERT( !this, "ChgNode() - kein FrameNode gefunden" ); 425 #endif 426 } 427 if( pFrmNd ) 428 while( aIdx != rInsPos ) 429 { 430 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode(); 431 if( pCNd ) 432 { 433 if( pFrmNd->IsTableNode() ) 434 ((SwTableNode*)pFrmNd)->MakeFrms( aIdx ); 435 else if( pFrmNd->IsSectionNode() ) 436 ((SwSectionNode*)pFrmNd)->MakeFrms( aIdx ); 437 else 438 ((SwCntntNode*)pFrmNd)->MakeFrms( *pCNd ); 439 pFrmNd = pCNd; 440 } 441 aIdx++; 442 } 443 } 444 } 445 446 447 /*********************************************************************** 448 |* 449 |* SwNodes::Move 450 |* 451 |* Beschreibung 452 |* Move loescht die Node-Pointer ab und einschliesslich der Startposition 453 |* bis zu und ausschliesslich der Endposition und fuegt sie an 454 |* der vor der Zielposition ein. 455 |* Wenn das Ziel vor dem ersten oder dem letzten zu bewegenden Element oder 456 |* dazwischen liegt, geschieht nichts. 457 |* Wenn der zu bewegende Bereich leer ist oder das Ende vor 458 |* dem Anfang liegt, geschieht nichts. 459 |* 460 |* Allg.: aRange beschreibt den Bereich -exklusive- aEnd !! 461 |* ( 1.Node: aStart, letzer Node: aEnd-1 !! ) 462 |* 463 |* 464 |* 465 ***********************************************************************/ 466 467 sal_Bool SwNodes::_MoveNodes( const SwNodeRange& aRange, SwNodes & rNodes, 468 const SwNodeIndex& aIndex, sal_Bool bNewFrms ) 469 { 470 SwNode * pAktNode; 471 if( aIndex == 0 || 472 ( (pAktNode = &aIndex.GetNode())->GetStartNode() && 473 !pAktNode->StartOfSectionIndex() )) 474 return sal_False; 475 476 SwNodeRange aRg( aRange ); 477 478 // "einfache" StartNodes oder EndNodes ueberspringen 479 while( ND_STARTNODE == (pAktNode = &aRg.aStart.GetNode())->GetNodeType() 480 || ( pAktNode->IsEndNode() && 481 !pAktNode->pStartOfSection->IsSectionNode() ) ) 482 aRg.aStart++; 483 aRg.aStart--; 484 485 // falls aEnd-1 auf keinem ContentNode steht, dann suche den vorherigen 486 aRg.aEnd--; 487 while( ( (( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() && 488 !pAktNode->IsSectionNode() ) || 489 ( pAktNode->IsEndNode() && 490 ND_STARTNODE == pAktNode->pStartOfSection->GetNodeType()) ) && 491 aRg.aEnd > aRg.aStart ) 492 aRg.aEnd--; 493 494 495 // wird im selben Array's verschoben, dann ueberpruefe die Einfuegepos. 496 if( aRg.aStart >= aRg.aEnd ) 497 return sal_False; 498 499 if( this == &rNodes ) 500 { 501 if( ( aIndex.GetIndex()-1 >= aRg.aStart.GetIndex() && 502 aIndex.GetIndex()-1 < aRg.aEnd.GetIndex()) || 503 ( aIndex.GetIndex()-1 == aRg.aEnd.GetIndex() ) ) 504 return sal_False; 505 } 506 507 sal_uInt16 nLevel = 0; // Level-Counter 508 sal_uLong nInsPos = 0; // Cnt fuer das TmpArray 509 510 // das Array bildet einen Stack, es werden alle StartOfSelction's gesichert 511 SwSttNdPtrs aSttNdStack( 1, 5 ); 512 513 // setze den Start-Index 514 SwNodeIndex aIdx( aIndex ); 515 /* 516 --- JP 17.11.94: sollte ueberholt sein, wird im ChgNode schon erledigt! 517 sal_Bool bCorrNum = pSect && pSect->aStart.GetIndex() == aIdx.GetIndex(); 518 */ 519 520 SwStartNode* pStartNode = aIdx.GetNode().pStartOfSection; 521 aSttNdStack.C40_INSERT( SwStartNode, pStartNode, 0 ); 522 // aSttNdStack.Insert( rNodes[ aIdx ]->pStartOfSection, 0 ); 523 SwNodeRange aOrigInsPos( aIdx, -1, aIdx ); // Originale Insert Pos 524 525 //JP 16.01.98: SectionNodes: DelFrms/MakeFrms beim obersten SectionNode! 526 sal_uInt16 nSectNdCnt = 0; 527 sal_Bool bSaveNewFrms = bNewFrms; 528 529 // bis alles verschoben ist 530 while( aRg.aStart < aRg.aEnd ) 531 switch( (pAktNode = &aRg.aEnd.GetNode())->GetNodeType() ) 532 { 533 case ND_ENDNODE: 534 { 535 if( nInsPos ) // verschieb schon mal alle bis hier her 536 { 537 // loeschen und kopieren. ACHTUNG: die Indizies ab 538 // "aRg.aEnd+1" werden mit verschoben !! 539 SwNodeIndex aSwIndex( aRg.aEnd, 1 ); 540 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms ); 541 aIdx -= nInsPos; 542 nInsPos = 0; 543 } 544 545 SwStartNode* pSttNd = pAktNode->pStartOfSection; 546 if( pSttNd->IsTableNode() ) 547 { 548 SwTableNode* pTblNd = (SwTableNode*)pSttNd; 549 550 // dann bewege die gesamte Tabelle/den Bereich !! 551 nInsPos = (aRg.aEnd.GetIndex() - 552 pSttNd->GetIndex() )+1; 553 aRg.aEnd -= nInsPos; 554 555 //JP 12.03.99: 63293 - Nodes vom RedlineBereich NIE aufnehmen 556 sal_uLong nNd = aIdx.GetIndex(); 557 sal_Bool bInsOutlineIdx = !( rNodes.GetEndOfRedlines(). 558 StartOfSectionNode()->GetIndex() < nNd && 559 nNd < rNodes.GetEndOfRedlines().GetIndex() ); 560 561 if( bNewFrms ) 562 // loesche erstmal die Frames 563 pTblNd->DelFrms(); 564 if( &rNodes == this ) // in sich selbst moven ?? 565 { 566 // dann bewege alle Start/End/ContentNodes. Loesche 567 // bei den ContentNodes auch die Frames !! 568 pTblNd->pStartOfSection = aIdx.GetNode().pStartOfSection; 569 for( sal_uLong n = 0; n < nInsPos; ++n ) 570 { 571 SwNodeIndex aMvIdx( aRg.aEnd, 1 ); 572 SwCntntNode* pCNd = 0; 573 SwNode* pTmpNd = &aMvIdx.GetNode(); 574 if( pTmpNd->IsCntntNode() ) 575 { 576 pCNd = (SwCntntNode*)pTmpNd; 577 if( pTmpNd->IsTxtNode() ) 578 ((SwTxtNode*)pTmpNd)->RemoveFromList(); 579 580 // if( bNewFrms ) 581 // pCNd->DelFrms(); 582 583 // setze bei Start/EndNodes die richtigen Indizies 584 // loesche die Gliederungs-Indizies aus 585 // dem alten Nodes-Array 586 //if( pCNd->IsTxtNode() && NO_NUMBERING != //#outline level,zhaojianwei 587 // ((SwTxtNode*)pCNd)->GetTxtColl()->GetOutlineLevel() ) 588 if( pCNd->IsTxtNode() && 0 != 589 ((SwTxtNode*)pCNd)->GetAttrOutlineLevel() )//<-end,by zhaojianwei 590 pOutlineNds->Remove( pCNd ); 591 else 592 pCNd = 0; 593 } 594 // else if( bNewFrms && pTmpNd->IsSectionNode() ) 595 // ((SwSectionNode*)pTmpNd)->DelFrms(); 596 BigPtrArray::Move( aMvIdx.GetIndex(), aIdx.GetIndex() ); 597 598 if( bInsOutlineIdx && pCNd ) 599 pOutlineNds->Insert( pCNd ); 600 if( pTmpNd->IsTxtNode() ) 601 ((SwTxtNode*)pTmpNd)->AddToList(); 602 } 603 } 604 else 605 { 606 // StartNode holen 607 // Even aIdx points to a startnode, we need the startnode 608 // of the environment of aIdx (#i80941) 609 SwStartNode* pSttNode = aIdx.GetNode().pStartOfSection; 610 611 // Hole alle Boxen mit Inhalt. Deren Indizies auf die 612 // StartNodes muessen umgemeldet werden !! 613 // (Array kopieren und alle gefunden wieder loeschen; 614 // erleichtert das suchen!!) 615 SwNodeIndex aMvIdx( aRg.aEnd, 1 ); 616 for( sal_uLong n = 0; n < nInsPos; ++n ) 617 { 618 SwNode* pNd = &aMvIdx.GetNode(); 619 /* if( bNewFrms ) 620 { 621 if( pNd->IsCntntNode() ) 622 ((SwCntntNode*)pNd)->DelFrms(); 623 else if( pNd->IsSectionNode() ) 624 ((SwSectionNode*)pNd)->DelFrms(); 625 } 626 */ 627 //sal_Bool bOutlNd = pNd->IsTxtNode() && NO_NUMBERING !=//#outline level,zhaojianwei 628 // ((SwTxtNode*)pNd)->GetTxtColl()->GetOutlineLevel(); 629 const bool bOutlNd = pNd->IsTxtNode() && 630 0 != ((SwTxtNode*)pNd)->GetAttrOutlineLevel();//<-end,zhaojianwei 631 // loesche die Gliederungs-Indizies aus 632 // dem alten Nodes-Array 633 if( bOutlNd ) 634 pOutlineNds->Remove( pNd ); 635 636 RemoveNode( aMvIdx.GetIndex(), 1, sal_False ); 637 pNd->pStartOfSection = pSttNode; 638 rNodes.InsertNode( pNd, aIdx ); 639 640 // setze bei Start/EndNodes die richtigen Indizies 641 if( bInsOutlineIdx && bOutlNd ) 642 // und setze sie im neuen Nodes-Array 643 rNodes.pOutlineNds->Insert( pNd ); 644 else if( pNd->IsStartNode() ) 645 pSttNode = (SwStartNode*)pNd; 646 else if( pNd->IsEndNode() ) 647 { 648 pSttNode->pEndOfSection = (SwEndNode*)pNd; 649 if( pSttNode->IsSectionNode() ) 650 ((SwSectionNode*)pSttNode)->NodesArrChgd(); 651 pSttNode = pSttNode->pStartOfSection; 652 } 653 } 654 655 if( pTblNd->GetTable().IsA( TYPE( SwDDETable ) )) 656 { 657 SwDDEFieldType* pTyp = ((SwDDETable&)pTblNd-> 658 GetTable()).GetDDEFldType(); 659 if( pTyp ) 660 { 661 if( rNodes.IsDocNodes() ) 662 pTyp->IncRefCnt(); 663 else 664 pTyp->DecRefCnt(); 665 } 666 } 667 668 if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes( 669 rNodes)) 670 { 671 SwFrmFmt* pTblFmt = pTblNd->GetTable().GetFrmFmt(); 672 SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, 673 pTblFmt ); 674 pTblFmt->ModifyNotification( &aMsgHint, &aMsgHint ); 675 } 676 } 677 if( bNewFrms ) 678 { 679 SwNodeIndex aTmp( aIdx ); 680 pTblNd->MakeFrms( &aTmp ); 681 } 682 aIdx -= nInsPos; 683 nInsPos = 0; 684 } 685 else if( pSttNd->GetIndex() < aRg.aStart.GetIndex() ) 686 { 687 // SectionNode: es wird nicht die gesamte Section 688 // verschoben, also bewege nur die 689 // ContentNodes 690 // StartNode: erzeuge an der Postion eine neue Section 691 do { // middle check loop 692 if( !pSttNd->IsSectionNode() ) 693 { 694 // Start und EndNode an der InsertPos erzeugen 695 SwStartNode* pTmp = new SwStartNode( aIdx, 696 ND_STARTNODE, 697 /*?? welcher NodeTyp ??*/ 698 SwNormalStartNode ); 699 700 nLevel++; // den Index auf StartNode auf den Stack 701 aSttNdStack.C40_INSERT( SwStartNode, pTmp, nLevel ); 702 703 // noch den EndNode erzeugen 704 new SwEndNode( aIdx, *pTmp ); 705 } 706 else if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes( 707 rNodes)) 708 { 709 // im UndoNodes-Array spendieren wir einen 710 // Platzhalter 711 new SwNode( aIdx, ND_SECTIONDUMMY ); 712 } 713 else 714 { 715 // JP 18.5.2001: neue Section anlegen?? Bug 70454 716 aRg.aEnd--; 717 break; 718 719 } 720 721 aRg.aEnd--; 722 aIdx--; 723 } while( sal_False ); 724 } 725 else 726 { 727 // Start und EndNode komplett verschieben 728 // s. u. SwIndex aOldStt( pSttNd->theIndex ); 729 //JP 21.05.97: sollte der Start genau der Start des Bereiches sein, so muss 730 // der Node auf jedenfall noch besucht werden! 731 if( &aRg.aStart.GetNode() == pSttNd ) 732 --aRg.aStart; 733 734 SwSectionNode* pSctNd = pSttNd->GetSectionNode(); 735 if( bNewFrms && pSctNd ) 736 pSctNd->DelFrms(); 737 738 RemoveNode( aRg.aEnd.GetIndex(), 1, sal_False ); // EndNode loeschen 739 sal_uLong nSttPos = pSttNd->GetIndex(); 740 741 // dieser StartNode wird spaeter wieder entfernt! 742 SwStartNode* pTmpSttNd = new SwStartNode( *this, nSttPos+1 ); 743 pTmpSttNd->pStartOfSection = pSttNd->pStartOfSection; 744 745 RemoveNode( nSttPos, 1, sal_False ); // SttNode loeschen 746 747 pSttNd->pStartOfSection = aIdx.GetNode().pStartOfSection; 748 rNodes.InsertNode( pSttNd, aIdx ); 749 rNodes.InsertNode( pAktNode, aIdx ); 750 aIdx--; 751 pSttNd->pEndOfSection = (SwEndNode*)pAktNode; 752 753 aRg.aEnd--; 754 755 nLevel++; // den Index auf StartNode auf den Stack 756 aSttNdStack.C40_INSERT( SwStartNode, pSttNd, nLevel ); 757 758 // SectionNode muss noch ein paar Indizies ummelden 759 if( pSctNd ) 760 { 761 pSctNd->NodesArrChgd(); 762 ++nSectNdCnt; 763 bNewFrms = sal_False; 764 } 765 } 766 } 767 break; 768 769 770 771 case ND_SECTIONNODE: 772 if( !nLevel && 773 GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(rNodes)) 774 { 775 // dann muss an der akt. InsPos ein SectionDummyNode 776 // eingefuegt werden 777 if( nInsPos ) // verschieb schon mal alle bis hier her 778 { 779 // loeschen und kopieren. ACHTUNG: die Indizies ab 780 // "aRg.aEnd+1" werden mit verschoben !! 781 SwNodeIndex aSwIndex( aRg.aEnd, 1 ); 782 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms ); 783 aIdx -= nInsPos; 784 nInsPos = 0; 785 } 786 new SwNode( aIdx, ND_SECTIONDUMMY ); 787 aRg.aEnd--; 788 aIdx--; 789 break; 790 } 791 // kein break !! 792 case ND_TABLENODE: 793 case ND_STARTNODE: 794 { 795 // Bug #78589# - empty section -> nothing to do 796 // and only if it's a top level section 797 if( !nInsPos && !nLevel ) 798 { 799 aRg.aEnd--; 800 break; 801 } 802 803 if( !nLevel ) // es wird eine Stufe runter gestuft 804 { 805 // erzeuge die Runterstufung 806 SwNodeIndex aTmpSIdx( aOrigInsPos.aStart, 1 ); 807 SwStartNode* pTmpStt = new SwStartNode( aTmpSIdx, 808 ND_STARTNODE, 809 ((SwStartNode*)pAktNode)->GetStartNodeType() ); 810 811 aTmpSIdx--; 812 813 SwNodeIndex aTmpEIdx( aOrigInsPos.aEnd ); 814 new SwEndNode( aTmpEIdx, *pTmpStt ); 815 aTmpEIdx--; 816 aTmpSIdx++; 817 818 // setze die StartOfSection richtig 819 aRg.aEnd++; 820 { 821 SwNodeIndex aCntIdx( aRg.aEnd ); 822 for( sal_uLong n = 0; n < nInsPos; n++, aCntIdx++) 823 aCntIdx.GetNode().pStartOfSection = pTmpStt; 824 } 825 826 // Setze auch bei allen runtergestuften den richtigen StartNode 827 while( aTmpSIdx < aTmpEIdx ) 828 if( 0 != (( pAktNode = &aTmpEIdx.GetNode())->GetEndNode()) ) 829 aTmpEIdx = pAktNode->StartOfSectionIndex(); 830 else 831 { 832 pAktNode->pStartOfSection = pTmpStt; 833 aTmpEIdx--; 834 } 835 836 aIdx--; // hinter den eingefuegten StartNode 837 aRg.aEnd--; // vor den StartNode 838 // kopiere jetzt das Array. ACHTUNG: die Indizies ab 839 // "aRg.aEnd+1" werden mit verschoben !! 840 SwNodeIndex aSwIndex( aRg.aEnd, 1 ); 841 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms ); 842 aIdx -= nInsPos+1; 843 nInsPos = 0; 844 } 845 else // es wurden alle Nodes innerhalb eines 846 { // Start- und End-Nodes verschoben 847 ASSERT( pAktNode == aSttNdStack[nLevel] || 848 ( pAktNode->IsStartNode() && 849 aSttNdStack[nLevel]->IsSectionNode()), 850 "falscher StartNode" ); 851 852 SwNodeIndex aSwIndex( aRg.aEnd, 1 ); 853 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms ); 854 aIdx -= nInsPos+1; // vor den eingefuegten StartNode 855 nInsPos = 0; 856 857 // loesche nur noch den Pointer aus dem Nodes-Array. 858 // RemoveNode( aRg.aEnd.GetIndex(), 1, sal_False ); 859 RemoveNode( aRg.aEnd.GetIndex(), 1, sal_True ); 860 aRg.aEnd--; 861 862 SwSectionNode* pSectNd = aSttNdStack[ nLevel ]->GetSectionNode(); 863 if( pSectNd && !--nSectNdCnt ) 864 { 865 SwNodeIndex aTmp( *pSectNd ); 866 pSectNd->MakeFrms( &aTmp ); 867 bNewFrms = bSaveNewFrms; 868 } 869 aSttNdStack.Remove( nLevel ); // vom Stack loeschen 870 nLevel--; 871 } 872 873 // loesche alle entstehenden leeren Start-/End-Node-Paare 874 SwNode* pTmpNode = (*this)[ aRg.aEnd.GetIndex()+1 ]->GetEndNode(); 875 if( pTmpNode && ND_STARTNODE == (pAktNode = &aRg.aEnd.GetNode()) 876 ->GetNodeType() && pAktNode->StartOfSectionIndex() && 877 pTmpNode->StartOfSectionNode() == pAktNode ) 878 { 879 DelNodes( aRg.aEnd, 2 ); 880 aRg.aEnd--; 881 } 882 // aRg.aEnd--; 883 } 884 break; 885 886 case ND_TEXTNODE: 887 case ND_GRFNODE: 888 case ND_OLENODE: 889 { 890 if( bNewFrms && pAktNode->GetCntntNode() ) 891 ((SwCntntNode*)pAktNode)->DelFrms(); 892 893 pAktNode->pStartOfSection = aSttNdStack[ nLevel ]; 894 nInsPos++; 895 aRg.aEnd--; 896 } 897 break; 898 899 case ND_SECTIONDUMMY: 900 if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(*this)) 901 { 902 if( &rNodes == this ) // innerhalb vom UndoNodesArray 903 { 904 // mit verschieben 905 pAktNode->pStartOfSection = aSttNdStack[ nLevel ]; 906 nInsPos++; 907 } 908 else // in ein "normales" Nodes-Array verschieben 909 { 910 // dann muss an der akt. InsPos auch ein SectionNode 911 // (Start/Ende) stehen; dann diesen ueberspringen. 912 // Andernfalls nicht weiter beachten. 913 if( nInsPos ) // verschieb schon mal alle bis hier her 914 { 915 // loeschen und kopieren. ACHTUNG: die Indizies ab 916 // "aRg.aEnd+1" werden mit verschoben !! 917 SwNodeIndex aSwIndex( aRg.aEnd, 1 ); 918 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms ); 919 aIdx -= nInsPos; 920 nInsPos = 0; 921 } 922 SwNode* pTmpNd = &aIdx.GetNode(); 923 if( pTmpNd->IsSectionNode() || 924 pTmpNd->StartOfSectionNode()->IsSectionNode() ) 925 aIdx--; // ueberspringen 926 } 927 } 928 else { 929 ASSERT( sal_False, "wie kommt diser Node ins Nodes-Array??" ); 930 } 931 aRg.aEnd--; 932 break; 933 934 default: 935 ASSERT( sal_False, "was ist das fuer ein Node??" ); 936 break; 937 } 938 939 if( nInsPos ) // kopiere den Rest 940 { 941 // der Rest muesste so stimmen 942 SwNodeIndex aSwIndex( aRg.aEnd, 1 ); 943 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms ); 944 } 945 aRg.aEnd++; // wieder exklusive Ende 946 947 // loesche alle leeren Start-/End-Node-Paare 948 if( ( pAktNode = &aRg.aStart.GetNode())->GetStartNode() && 949 pAktNode->StartOfSectionIndex() && 950 aRg.aEnd.GetNode().GetEndNode() ) 951 DelNodes( aRg.aStart, 2 ); 952 953 // rufe jetzt noch das Update fuer die Gliederung/Nummerierung auf 954 aOrigInsPos.aStart++; 955 // im gleichen Nodes-Array verschoben ??, 956 // dann von oben nach unten das Update aufrufen !! 957 if( this == &rNodes && 958 aRg.aEnd.GetIndex() >= aOrigInsPos.aStart.GetIndex() ) 959 { 960 UpdtOutlineIdx( aOrigInsPos.aStart.GetNode() ); 961 UpdtOutlineIdx( aRg.aEnd.GetNode() ); 962 } 963 else 964 { 965 UpdtOutlineIdx( aRg.aEnd.GetNode() ); 966 rNodes.UpdtOutlineIdx( aOrigInsPos.aStart.GetNode() ); 967 } 968 969 #ifdef JP_DEBUG 970 { 971 extern Writer* GetDebugWriter(const String&); 972 973 Writer* pWriter = GetDebugWriter(aEmptyStr); 974 if( pWriter ) 975 { 976 int nError; 977 SvFileStream aStrm( "c:\\$$move.db", STREAM_WRITE ); 978 SwWriter aWriter( aStrm, *pMyDoc ); 979 aWriter.Write( &nError, pWriter ); 980 } 981 } 982 #endif 983 984 return sal_True; 985 } 986 987 988 /******************************************************************* 989 |* 990 |* SwNodes::SectionDown 991 |* 992 |* Beschreibung 993 |* SectionDown() legt ein Paar von Start- und EndSection-Node 994 |* (andere Nodes koennen dazwischen liegen) an. 995 |* 996 |* Zustand des SRange beim Verlassen der Funktion: nStart ist der 997 |* Index des ersten Node hinter dem Start Section Node, nEnd ist 998 |* der Index des End Section Nodes. Beispiel: Wird Insert Section 999 |* mehrmals hintereinander aufgerufen, so werden mehrere 1000 |* unmittelbar geschachtelte Sections (keine Content Nodes 1001 |* zwischen Start- bzw. End Nodes) angelegt. 1002 |* 1003 |* Allg.: aRange beschreibt den Bereich -exklusive- aEnd !! 1004 |* ( 1.Node: aStart, letzer Node: aEnd-1 !! ) 1005 |* 1006 |* Parameter 1007 |* SwRange &rRange 1008 |* IO: 1009 |* IN 1010 |* rRange.aStart: Einfuegeposition des StartNodes 1011 |* rRange.aEnd: Einfuegeposition des EndNodes 1012 |* OUT 1013 |* rRange.aStart: steht hinter dem eingefuegten Startnode 1014 |* rRange.aEnd: steht auf dem eingefuegen Endnode 1015 |* 1016 |* Ausnahmen 1017 |* 1. SRange-Anfang und SRange-Ende muessen auf dem gleichen Level sein 1018 |* 2. duerfen nicht auf dem obersten Level sein 1019 |* Ist dies nicht der Fall, wird die 1020 |* Funktion durch Aufruf von ERR_RAISE verlassen. 1021 |* 1022 |* Debug-Funktionen 1023 |* die Debugging Tools geben rRange beim Eintritt und beim 1024 |* Verlassen der Funktion aus 1025 |* 1026 |* Ersterstellung 1027 |* VER0100 vb 901214 1028 |* 1029 |* Stand 1030 |* VER0100 vb 901214 1031 |* 1032 *******************************************************************/ 1033 void SwNodes::SectionDown(SwNodeRange *pRange, SwStartNodeType eSttNdTyp ) 1034 { 1035 if( pRange->aStart >= pRange->aEnd || 1036 pRange->aEnd >= Count() || 1037 !CheckNodesRange( pRange->aStart, pRange->aEnd )) 1038 return; 1039 1040 // Ist der Anfang vom Bereich vor oder auf einem EndNode, so loesche 1041 // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes enstehen. 1042 // Bei anderen Nodes wird eine neuer StartNode eingefuegt 1043 SwNode * pAktNode = &pRange->aStart.GetNode(); 1044 SwNodeIndex aTmpIdx( *pAktNode->StartOfSectionNode() ); 1045 1046 if( pAktNode->GetEndNode() ) 1047 DelNodes( pRange->aStart, 1 ); // verhinder leere Section 1048 else 1049 { 1050 // fuege einen neuen StartNode ein 1051 SwNode* pSttNd = new SwStartNode( pRange->aStart, ND_STARTNODE, eSttNdTyp ); 1052 pRange->aStart = *pSttNd; 1053 aTmpIdx = pRange->aStart; 1054 } 1055 1056 // Ist das Ende vom Bereich vor oder auf einem StartNode, so loesche 1057 // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes enstehen 1058 // Bei anderen Nodes wird eine neuer EndNode eingefuegt 1059 pRange->aEnd--; 1060 if( pRange->aEnd.GetNode().GetStartNode() ) 1061 DelNodes( pRange->aEnd, 1 ); 1062 else 1063 { 1064 pRange->aEnd++; 1065 // fuege einen neuen EndNode ein 1066 new SwEndNode( pRange->aEnd, *pRange->aStart.GetNode().GetStartNode() ); 1067 } 1068 pRange->aEnd--; 1069 1070 SectionUpDown( aTmpIdx, pRange->aEnd ); 1071 } 1072 1073 /******************************************************************* 1074 |* 1075 |* SwNodes::SectionUp 1076 |* 1077 |* Beschreibung 1078 |* Der von rRange umspannte Bereich wird auf die naechst hoehere 1079 |* Ebene gehoben. Das geschieht dadurch, dass bei 1080 |* rRange.aStart ein Endnode und bei rRange.aEnd ein 1081 |* Startnode eingefuegt wird. Die Indices fuer den Bereich 1082 |* innerhalb von rRange werden geupdated. 1083 |* 1084 |* Allg.: aRange beschreibt den Bereich -exklusive- aEnd !! 1085 |* ( 1.Node: aStart, letzer Node: aEnd-1 !! ) 1086 |* 1087 |* Parameter 1088 |* SwRange &rRange 1089 |* IO: 1090 |* IN 1091 |* rRange.aStart: Anfang des hoeher zubewegenden Bereiches 1092 |* rRange.aEnd: der 1.Node hinter dem Bereich 1093 |* OUT 1094 |* rRange.aStart: an der ersten Position innerhalb des 1095 |* hochbewegten Bereiches 1096 |* rRange.aEnd: an der letzten Position innerhalb des 1097 |* hochbewegten Bereiches 1098 |* 1099 |* Debug-Funktionen 1100 |* die Debugging Tools geben rRange beim Eintritt und beim 1101 |* Verlassen der Funktion aus 1102 |* 1103 |* Ersterstellung 1104 |* VER0100 vb 901214 1105 |* 1106 |* Stand 1107 |* VER0100 vb 901214 1108 |* 1109 *******************************************************************/ 1110 void SwNodes::SectionUp(SwNodeRange *pRange) 1111 { 1112 if( pRange->aStart >= pRange->aEnd || 1113 pRange->aEnd >= Count() || 1114 !CheckNodesRange( pRange->aStart, pRange->aEnd ) || 1115 !( HighestLevel( *this, *pRange ) > 1 )) 1116 return; 1117 1118 // Ist der Anfang vom Bereich vor oder auf einem StartNode, so loesche 1119 // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes enstehen. 1120 // Bei anderen Nodes wird eine neuer EndNode eingefuegt 1121 SwNode * pAktNode = &pRange->aStart.GetNode(); 1122 SwNodeIndex aIdx( *pAktNode->StartOfSectionNode() ); 1123 if( pAktNode->IsStartNode() ) // selbst StartNode 1124 { 1125 SwEndNode* pEndNd = pRange->aEnd.GetNode().GetEndNode(); 1126 if( pAktNode == pEndNd->pStartOfSection ) 1127 { 1128 // dann wurde paarig aufgehoben, also nur die im Berich neu anpassen 1129 SwStartNode* pTmpSttNd = pAktNode->pStartOfSection; 1130 RemoveNode( pRange->aStart.GetIndex(), 1, sal_True ); 1131 RemoveNode( pRange->aEnd.GetIndex(), 1, sal_True ); 1132 1133 SwNodeIndex aTmpIdx( pRange->aStart ); 1134 while( aTmpIdx < pRange->aEnd ) 1135 { 1136 pAktNode = &aTmpIdx.GetNode(); 1137 pAktNode->pStartOfSection = pTmpSttNd; 1138 if( pAktNode->IsStartNode() ) 1139 aTmpIdx = pAktNode->EndOfSectionIndex() + 1; 1140 else 1141 aTmpIdx++; 1142 } 1143 return ; 1144 } 1145 DelNodes( pRange->aStart, 1 ); 1146 } 1147 else if( aIdx == pRange->aStart.GetIndex()-1 ) // vor StartNode 1148 DelNodes( aIdx, 1 ); 1149 else 1150 new SwEndNode( pRange->aStart, *aIdx.GetNode().GetStartNode() ); 1151 1152 // Ist das Ende vom Bereich vor oder auf einem StartNode, so loesche 1153 // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes entstehen 1154 // Bei anderen Nodes wird eine neuer EndNode eingefuegt 1155 SwNodeIndex aTmpIdx( pRange->aEnd ); 1156 if( pRange->aEnd.GetNode().IsEndNode() ) 1157 DelNodes( pRange->aEnd, 1 ); 1158 else 1159 { 1160 pAktNode = new SwStartNode( pRange->aEnd ); 1161 /*?? welcher NodeTyp ??*/ 1162 aTmpIdx = *pRange->aEnd.GetNode().EndOfSectionNode(); 1163 pRange->aEnd--; 1164 } 1165 1166 SectionUpDown( aIdx, aTmpIdx ); 1167 } 1168 1169 1170 /************************************************************************* 1171 |* 1172 |* SwNodes::SectionUpDown() 1173 |* 1174 |* Beschreibung 1175 |* Methode setzt die Indizies die bei SectionUp oder SectionDwon 1176 |* veraendert wurden wieder richtig, sodass die Ebenen wieder 1177 |* Konsistent sind. 1178 |* 1179 |* Parameter 1180 |* SwIndex & aStart StartNode !!! 1181 |* SwIndex & aEnd EndPunkt 1182 |* 1183 |* Ersterstellung JP 23.04.91 1184 |* Letzte Aenderung JP 23.04.91 1185 |* 1186 *************************************************************************/ 1187 void SwNodes::SectionUpDown( const SwNodeIndex & aStart, const SwNodeIndex & aEnd ) 1188 { 1189 SwNode * pAktNode; 1190 SwNodeIndex aTmpIdx( aStart, +1 ); 1191 // das Array bildet einen Stack, es werden alle StartOfSelction's gesichert 1192 SwSttNdPtrs aSttNdStack( 1, 5 ); 1193 SwStartNode* pTmp = aStart.GetNode().GetStartNode(); 1194 aSttNdStack.C40_INSERT( SwStartNode, pTmp, 0 ); 1195 1196 // durchlaufe bis der erste zu aendernde Start-Node gefunden wurde 1197 // ( Es wird vom eingefuegten EndNode bis nach vorne die Indexe gesetzt ) 1198 for( ;; aTmpIdx++ ) 1199 { 1200 pAktNode = &aTmpIdx.GetNode(); 1201 pAktNode->pStartOfSection = aSttNdStack[ aSttNdStack.Count()-1 ]; 1202 1203 if( pAktNode->GetStartNode() ) 1204 { 1205 pTmp = (SwStartNode*)pAktNode; 1206 aSttNdStack.C40_INSERT( SwStartNode, pTmp, aSttNdStack.Count() ); 1207 } 1208 else if( pAktNode->GetEndNode() ) 1209 { 1210 SwStartNode* pSttNd = aSttNdStack[ aSttNdStack.Count() - 1 ]; 1211 pSttNd->pEndOfSection = (SwEndNode*)pAktNode; 1212 aSttNdStack.Remove( aSttNdStack.Count() - 1 ); 1213 if( aSttNdStack.Count() ) 1214 continue; // noch genuegend EndNodes auf dem Stack 1215 1216 else if( aTmpIdx < aEnd ) // Uebergewicht an StartNodes 1217 // ist das Ende noch nicht erreicht, so hole den Start von 1218 // der uebergeordneten Section 1219 { 1220 aSttNdStack.C40_INSERT( SwStartNode, pSttNd->pStartOfSection, 0 ); 1221 } 1222 else // wenn ueber den Bereich hinaus, dann Ende 1223 break; 1224 } 1225 } 1226 } 1227 1228 1229 1230 1231 /******************************************************************* 1232 |* 1233 |* SwNodes::Delete 1234 |* 1235 |* Beschreibung 1236 |* Spezielle Implementierung der Delete-Funktion des 1237 |* variablen Array. Diese spezielle Implementierung ist 1238 |* notwendig, da durch das Loeschen von Start- bzw. 1239 |* Endnodes Inkonsistenzen entstehen koennen. Diese werden 1240 |* durch diese Funktion beseitigt. 1241 |* 1242 |* Parameter 1243 |* IN 1244 |* SwIndex &rIndex bezeichnet die Position, an der 1245 |* geloescht wird 1246 |* rIndex ist nach Aufruf der Funktion unveraendert (Kopie?!) 1247 |* sal_uInt16 nNodes bezeichnet die Anzahl der zu loeschenden 1248 |* Nodes; ist auf 1 defaulted 1249 |* 1250 |* Debug-Funktionen 1251 |* geben beim Eintritt in die Funktion Position und Anzahl 1252 |* der zu loeschenden Nodes aus. 1253 |* 1254 |* Ersterstellung 1255 |* VER0100 vb 901214 1256 |* 1257 |* Stand 1258 |* VER0100 vb 901214 1259 |* 1260 *******************************************************************/ 1261 void SwNodes::Delete(const SwNodeIndex &rIndex, sal_uLong nNodes) 1262 { 1263 sal_uInt16 nLevel = 0; // Level-Counter 1264 SwNode * pAktNode; 1265 1266 sal_uLong nCnt = Count() - rIndex.GetIndex() - 1; 1267 if( nCnt > nNodes ) nCnt = nNodes; 1268 1269 if( nCnt == 0 ) // keine Anzahl -> return 1270 return; 1271 1272 SwNodeRange aRg( rIndex, 0, rIndex, nCnt-1 ); 1273 // ueberprufe ob rIndex..rIndex + nCnt ueber einen Bereich hinausragt !! 1274 if( ( !aRg.aStart.GetNode().StartOfSectionIndex() && 1275 !aRg.aStart.GetIndex() ) || 1276 ! CheckNodesRange( aRg.aStart, aRg.aEnd ) ) 1277 return; 1278 1279 1280 // falls aEnd auf keinem ContentNode steht, dann suche den vorherigen 1281 while( ( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() || 1282 ( pAktNode->GetEndNode() && 1283 !pAktNode->pStartOfSection->IsTableNode() )) 1284 aRg.aEnd--; 1285 1286 nCnt = 0; 1287 // Start erhoehen, damit auf < abgefragt wird. ( bei <= kann es zu 1288 // Problemen fuehren; ist aEnd == aStart und wird aEnd geloscht, 1289 // so ist aEnd <= aStart 1290 aRg.aStart--; 1291 1292 sal_Bool bSaveInNodesDel = bInNodesDel; 1293 bInNodesDel = sal_True; 1294 sal_Bool bUpdateOutline = sal_False; 1295 1296 // bis alles geloescht ist 1297 while( aRg.aStart < aRg.aEnd ) 1298 { 1299 pAktNode = &aRg.aEnd.GetNode(); 1300 1301 if( pAktNode->GetEndNode() ) 1302 { 1303 // die gesamte Section loeschen ? 1304 if( pAktNode->StartOfSectionIndex() > aRg.aStart.GetIndex() ) 1305 { 1306 SwTableNode* pTblNd = pAktNode->pStartOfSection->GetTableNode(); 1307 if( pTblNd ) 1308 pTblNd->DelFrms(); 1309 1310 SwNode *pNd, *pChkNd = pAktNode->pStartOfSection; 1311 sal_uInt16 nIdxPos; 1312 do { 1313 pNd = &aRg.aEnd.GetNode(); 1314 1315 if( pNd->IsTxtNode() ) 1316 { 1317 //if( NO_NUMBERING != //#outline level,zhaojianwei 1318 // ((SwTxtNode*)pNd)->GetTxtColl()->GetOutlineLevel() && 1319 if( 0 != ((SwTxtNode*)pNd)->GetAttrOutlineLevel() &&//<-end,zhaojianwei 1320 pOutlineNds->Seek_Entry( pNd, &nIdxPos )) 1321 { 1322 // loesche die Gliederungs-Indizies. 1323 pOutlineNds->Remove( nIdxPos ); 1324 bUpdateOutline = sal_True; 1325 } 1326 ((SwTxtNode*)pNd)->InvalidateNumRule(); 1327 } 1328 else if( pNd->IsEndNode() && 1329 pNd->pStartOfSection->IsTableNode() ) 1330 ((SwTableNode*)pNd->pStartOfSection)->DelFrms(); 1331 1332 aRg.aEnd--; 1333 nCnt++; 1334 1335 } while( pNd != pChkNd ); 1336 } 1337 else 1338 { 1339 RemoveNode( aRg.aEnd.GetIndex()+1, nCnt, sal_True ); // loesche 1340 nCnt = 0; 1341 aRg.aEnd--; // vor den EndNode 1342 nLevel++; 1343 } 1344 } 1345 else if( pAktNode->GetStartNode() ) // StartNode gefunden 1346 { 1347 if( nLevel == 0 ) // es wird eine Stufe runter gestuft 1348 { 1349 if( nCnt ) 1350 { 1351 // loesche jetzt das Array 1352 aRg.aEnd++; 1353 RemoveNode( aRg.aEnd.GetIndex(), nCnt, sal_True ); 1354 nCnt = 0; 1355 } 1356 } 1357 else // es werden alle Nodes Innerhalb eines Start- und 1358 { // End-Nodes geloescht, loesche mit Start/EndNode 1359 RemoveNode( aRg.aEnd.GetIndex(), nCnt + 2, sal_True ); // loesche Array 1360 nCnt = 0; 1361 nLevel--; 1362 } 1363 1364 // nach dem loeschen kann aEnd auf einem EndNode stehen 1365 // loesche alle leeren Start-/End-Node-Paare 1366 SwNode* pTmpNode = aRg.aEnd.GetNode().GetEndNode(); 1367 aRg.aEnd--; 1368 while( pTmpNode && 1369 ( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() && 1370 pAktNode->StartOfSectionIndex() ) 1371 { 1372 // loesche den EndNode und StartNode 1373 DelNodes( aRg.aEnd, 2 ); 1374 pTmpNode = aRg.aEnd.GetNode().GetEndNode(); 1375 aRg.aEnd--; 1376 } 1377 } 1378 else // normaler Node, also ins TmpArray einfuegen 1379 { 1380 SwTxtNode* pTxtNd = pAktNode->GetTxtNode(); 1381 if( pTxtNd ) 1382 { 1383 if( pTxtNd->IsOutline()) 1384 { // loesche die Gliederungs-Indizies. 1385 pOutlineNds->Remove( pTxtNd ); 1386 bUpdateOutline = sal_True; 1387 } 1388 pTxtNd->InvalidateNumRule(); 1389 } 1390 else if( pAktNode->IsCntntNode() ) 1391 ((SwCntntNode*)pAktNode)->InvalidateNumRule(); 1392 1393 aRg.aEnd--; 1394 nCnt++; 1395 } 1396 } 1397 1398 aRg.aEnd++; 1399 if( nCnt != 0 ) 1400 RemoveNode( aRg.aEnd.GetIndex(), nCnt, sal_True ); // loesche den Rest 1401 1402 // loesche alle leeren Start-/End-Node-Paare 1403 while( aRg.aEnd.GetNode().GetEndNode() && 1404 ( pAktNode = &aRg.aStart.GetNode())->GetStartNode() && 1405 pAktNode->StartOfSectionIndex() ) 1406 // aber ja keinen der heiligen 5. 1407 { 1408 DelNodes( aRg.aStart, 2 ); // loesche den Start- und EndNode 1409 aRg.aStart--; 1410 } 1411 1412 bInNodesDel = bSaveInNodesDel; 1413 1414 if( !bInNodesDel ) 1415 { 1416 // rufe jetzt noch das Update fuer die Gliederung/Nummerierung auf 1417 if( bUpdateOutline || bInDelUpdOutl ) 1418 { 1419 UpdtOutlineIdx( aRg.aEnd.GetNode() ); 1420 bInDelUpdOutl = sal_False; 1421 } 1422 1423 } 1424 else 1425 { 1426 if( bUpdateOutline ) 1427 bInDelUpdOutl = sal_True; 1428 } 1429 } 1430 1431 /******************************************************************* 1432 |* 1433 |* SwNodes::GetSectionLevel 1434 |* 1435 |* Beschreibung 1436 |* Die Funktion liefert den Sectionlevel an der durch 1437 |* aIndex bezeichneten Position. Die Funktion ruft die 1438 |* GetSectionlevel-Funktion des durch aIndex bezeichneten 1439 |* Nodes. Diese ist eine virtuelle Funktion, die fuer 1440 |* Endnodes speziell implementiert werden musste. 1441 |* Die Sectionlevels werden ermittelt, indem rekursiv durch 1442 |* die Nodesstruktur (jeweils zum naechsten theEndOfSection) 1443 |* gegangen wird, bis die oberste Ebene erreicht ist 1444 |* (theEndOfSection == 0) 1445 |* 1446 |* Parameter 1447 |* aIndex bezeichnet die Position des Nodes, dessen 1448 |* Sectionlevel ermittelt werden soll. Hier wird eine Kopie 1449 |* uebergeben, da eine Veraenderung der Variablen in der 1450 |* rufenden Funktion nicht wuenschenswert ist. 1451 |* 1452 |* Ausnahmen 1453 |* Der erste Node im Array sollte immer ein Startnode sein. 1454 |* Dieser erfaehrt in der Funktion SwNodes::GetSectionLevel() 1455 |* eine Sonderbehandlung; es wird davon ausgegangen, dass der 1456 |* erste Node auch ein Startnode ist. 1457 |* 1458 |* Ersterstellung 1459 |* VER0100 vb 901214 1460 |* 1461 |* Stand 1462 |* VER0100 vb 901214 1463 |* 1464 *******************************************************************/ 1465 sal_uInt16 SwNodes::GetSectionLevel(const SwNodeIndex &rIdx) const { 1466 // Sonderbehandlung 1. Node 1467 if(rIdx == 0) return 1; 1468 /* 1469 * Keine Rekursion! - hier wird das SwNode::GetSectionLevel 1470 * aufgerufen 1471 */ 1472 return rIdx.GetNode().GetSectionLevel(); 1473 } 1474 1475 void SwNodes::GoStartOfSection(SwNodeIndex *pIdx) const 1476 { 1477 // hinter den naechsten Startnode 1478 SwNodeIndex aTmp( *pIdx->GetNode().StartOfSectionNode(), +1 ); 1479 1480 // steht der Index auf keinem ContentNode, dann gehe dahin. Ist aber 1481 // kein weiterer vorhanden, dann lasse den Index an alter Pos stehen !!! 1482 while( !aTmp.GetNode().IsCntntNode() ) 1483 { // gehe vom StartNode ( es kann nur ein StartNode sein ! ) an sein 1484 // Ende 1485 if( *pIdx <= aTmp ) 1486 return; // FEHLER: Steht schon hinter der Sektion 1487 aTmp = aTmp.GetNode().EndOfSectionIndex()+1; 1488 if( *pIdx <= aTmp ) 1489 return; // FEHLER: Steht schon hinter der Sektion 1490 } 1491 (*pIdx) = aTmp; // steht auf einem ContentNode 1492 } 1493 1494 void SwNodes::GoEndOfSection(SwNodeIndex *pIdx) const 1495 { 1496 // falls er vor einem Endnode steht --> nichts tun 1497 if( !pIdx->GetNode().IsEndNode() ) 1498 (*pIdx) = *pIdx->GetNode().EndOfSectionNode(); 1499 } 1500 1501 SwCntntNode* SwNodes::GoNext(SwNodeIndex *pIdx) const 1502 { 1503 if( pIdx->GetIndex() >= Count() - 1 ) 1504 return 0; 1505 1506 SwNodeIndex aTmp(*pIdx, +1); 1507 SwNode* pNd = 0; 1508 while( aTmp < Count()-1 && 0 == ( pNd = &aTmp.GetNode())->IsCntntNode() ) 1509 aTmp++; 1510 1511 if( aTmp == Count()-1 ) 1512 pNd = 0; 1513 else 1514 (*pIdx) = aTmp; 1515 return (SwCntntNode*)pNd; 1516 } 1517 1518 SwCntntNode* SwNodes::GoPrevious(SwNodeIndex *pIdx) const 1519 { 1520 if( !pIdx->GetIndex() ) 1521 return 0; 1522 1523 SwNodeIndex aTmp( *pIdx, -1 ); 1524 SwNode* pNd = 0; 1525 while( aTmp.GetIndex() && 0 == ( pNd = &aTmp.GetNode())->IsCntntNode() ) 1526 aTmp--; 1527 1528 if( !aTmp.GetIndex() ) 1529 pNd = 0; 1530 else 1531 (*pIdx) = aTmp; 1532 return (SwCntntNode*)pNd; 1533 } 1534 1535 /************************************************************************* 1536 |* 1537 |* sal_Bool SwNodes::CheckNodesRange() 1538 |* 1539 |* Beschreibung 1540 |* Teste ob der uebergene SRange nicht ueber die Grenzen der 1541 |* einzelnen Bereiche (PosIts, Autotext, Content, Icons und Inserts ) 1542 |* hinaus reicht. 1543 |* Nach Wahrscheinlichkeit des Ranges sortiert. 1544 |* 1545 |* Alg.: Da festgelegt ist, das aRange.aEnd den 1.Node hinter dem Bereich 1546 |* bezeichnet, wird hier auf aEnd <= End.. getestet !! 1547 |* 1548 |* Parameter SwIndex & Start-Index vom Bereich 1549 |* SwIndex & End-Index vom Bereich 1550 |* sal_Bool sal_True: Start+End in gleicher Section! 1551 |* sal_False: Start+End in verschiedenen Sect. 1552 |* Return-Wert sal_Bool sal_True: gueltiger SRange 1553 |* sal_False: ungueltiger SRange 1554 |* 1555 |* Ersterstellung JP 23.04.91 1556 |* Letzte Aenderung JP 18.06.92 1557 |* 1558 *************************************************************************/ 1559 1560 inline int TstIdx( sal_uLong nSttIdx, sal_uLong nEndIdx, sal_uLong nStt, sal_uLong nEnd ) 1561 { 1562 return nStt < nSttIdx && nEnd >= nSttIdx && 1563 nStt < nEndIdx && nEnd >= nEndIdx; 1564 } 1565 1566 sal_Bool SwNodes::CheckNodesRange( const SwNodeIndex& rStt, const SwNodeIndex& rEnd ) const 1567 { 1568 sal_uLong nStt = rStt.GetIndex(), nEnd = rEnd.GetIndex(); 1569 if( TstIdx( nStt, nEnd, pEndOfContent->StartOfSectionIndex(), 1570 pEndOfContent->GetIndex() )) return sal_True; 1571 if( TstIdx( nStt, nEnd, pEndOfAutotext->StartOfSectionIndex(), 1572 pEndOfAutotext->GetIndex() )) return sal_True; 1573 if( TstIdx( nStt, nEnd, pEndOfPostIts->StartOfSectionIndex(), 1574 pEndOfPostIts->GetIndex() )) return sal_True; 1575 if( TstIdx( nStt, nEnd, pEndOfInserts->StartOfSectionIndex(), 1576 pEndOfInserts->GetIndex() )) return sal_True; 1577 if( TstIdx( nStt, nEnd, pEndOfRedlines->StartOfSectionIndex(), 1578 pEndOfRedlines->GetIndex() )) return sal_True; 1579 1580 return sal_False; // liegt irgendwo dazwischen, FEHLER 1581 } 1582 1583 1584 /************************************************************************* 1585 |* 1586 |* void SwNodes::DelNodes() 1587 |* 1588 |* Beschreibung 1589 |* Loesche aus den NodesArray ab einer Position entsprechend Node's. 1590 |* 1591 |* Parameter SwIndex & Der Startpunkt im Nodes-Array 1592 |* sal_uInt16 die Anzahl 1593 |* 1594 |* Ersterstellung JP 23.04.91 1595 |* Letzte Aenderung JP 23.04.91 1596 |* 1597 *************************************************************************/ 1598 void SwNodes::DelNodes( const SwNodeIndex & rStart, sal_uLong nCnt ) 1599 { 1600 int bUpdateNum = 0; 1601 sal_uLong nSttIdx = rStart.GetIndex(); 1602 1603 if( !nSttIdx && nCnt == GetEndOfContent().GetIndex()+1 ) 1604 { 1605 // es wird das gesamte Nodes-Array zerstoert, man ist im Doc DTOR! 1606 // Die initialen Start-/End-Nodes duerfen nur im SwNodes-DTOR 1607 // zerstoert werden! 1608 SwNode* aEndNdArr[] = { pEndOfContent, 1609 pEndOfPostIts, pEndOfInserts, 1610 pEndOfAutotext, pEndOfRedlines, 1611 0 1612 }; 1613 1614 SwNode** ppEndNdArr = aEndNdArr; 1615 while( *ppEndNdArr ) 1616 { 1617 nSttIdx = (*ppEndNdArr)->StartOfSectionIndex() + 1; 1618 sal_uLong nEndIdx = (*ppEndNdArr)->GetIndex(); 1619 1620 if( nSttIdx != nEndIdx ) 1621 RemoveNode( nSttIdx, nEndIdx - nSttIdx, sal_True ); 1622 1623 ++ppEndNdArr; 1624 } 1625 } 1626 else 1627 { 1628 for( sal_uLong n = nSttIdx, nEnd = nSttIdx + nCnt; n < nEnd; ++n ) 1629 { 1630 SwNode* pNd = (*this)[ n ]; 1631 1632 if( pNd->IsTxtNode() && 1633 //NO_NUMBERING != ((SwTxtNode*)pNd)->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei 1634 0 != ((SwTxtNode*)pNd)->GetAttrOutlineLevel() ) //<-end,zhaojianwei 1635 { // loesche die Gliederungs-Indizies. 1636 sal_uInt16 nIdxPos; 1637 if( pOutlineNds->Seek_Entry( pNd, &nIdxPos )) 1638 { 1639 pOutlineNds->Remove( nIdxPos ); 1640 bUpdateNum = 1; 1641 } 1642 } 1643 if( pNd->IsCntntNode() ) 1644 { 1645 ((SwCntntNode*)pNd)->InvalidateNumRule(); 1646 ((SwCntntNode*)pNd)->DelFrms(); 1647 } 1648 } 1649 RemoveNode( nSttIdx, nCnt, sal_True ); 1650 1651 // rufe noch das Update fuer die Gliederungsnumerierung auf 1652 if( bUpdateNum ) 1653 UpdtOutlineIdx( rStart.GetNode() ); 1654 } 1655 } 1656 1657 1658 /************************************************************************* 1659 |* 1660 |* sal_uInt16 HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange ) 1661 |* 1662 |* Beschreibung 1663 |* Berechne den hoehsten Level innerhalb des Bereiches 1664 |* 1665 |* Parameter SwNodes & das Node-Array 1666 |* SwNodeRange & der zu ueberpruefende Bereich 1667 |* Return sal_uInt16 der hoechste Level 1668 |* 1669 |* Ersterstellung JP 24.04.91 1670 |* Letzte Aenderung JP 24.04.91 1671 |* 1672 *************************************************************************/ 1673 1674 struct HighLevel 1675 { 1676 sal_uInt16 nLevel, nTop; 1677 HighLevel( sal_uInt16 nLv ) : nLevel( nLv ), nTop( nLv ) {} 1678 1679 }; 1680 1681 sal_Bool _HighestLevel( const SwNodePtr& rpNode, void * pPara ) 1682 { 1683 HighLevel * pHL = (HighLevel*)pPara; 1684 if( rpNode->GetStartNode() ) 1685 pHL->nLevel++; 1686 else if( rpNode->GetEndNode() ) 1687 pHL->nLevel--; 1688 if( pHL->nTop > pHL->nLevel ) 1689 pHL->nTop = pHL->nLevel; 1690 return sal_True; 1691 1692 } 1693 1694 sal_uInt16 HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange ) 1695 { 1696 HighLevel aPara( rNodes.GetSectionLevel( rRange.aStart )); 1697 rNodes.ForEach( rRange.aStart, rRange.aEnd, _HighestLevel, &aPara ); 1698 return aPara.nTop; 1699 1700 } 1701 1702 /************************************************************************* 1703 |* 1704 |* SwNodes::Move() 1705 |* 1706 |* Beschreibung 1707 |* Parameter SwPaM& zu kopierender Bereich 1708 |* SwNodes& in dieses Nodes-Array 1709 |* SwPosition& auf diese Position im Nodes-Array 1710 |* Ersterstellung JP 09.07.92 1711 |* Letzte Aenderung JP 09.07.92 1712 |* 1713 *************************************************************************/ 1714 void SwNodes::MoveRange( SwPaM & rPam, SwPosition & rPos, SwNodes& rNodes ) 1715 { 1716 SwPosition * const pStt = rPam.Start(); 1717 SwPosition * const pEnd = rPam.End(); 1718 1719 if( !rPam.HasMark() || *pStt >= *pEnd ) 1720 return; 1721 1722 if( this == &rNodes && *pStt <= rPos && rPos < *pEnd ) 1723 return; 1724 1725 SwNodeIndex aEndIdx( pEnd->nNode ); 1726 SwNodeIndex aSttIdx( pStt->nNode ); 1727 SwTxtNode *const pSrcNd = aSttIdx.GetNode().GetTxtNode(); 1728 SwTxtNode * pDestNd = rPos.nNode.GetNode().GetTxtNode(); 1729 sal_Bool bSplitDestNd = sal_True; 1730 sal_Bool bCopyCollFmt = pDestNd && !pDestNd->GetTxt().Len(); 1731 1732 if( pSrcNd ) 1733 { 1734 // ist der 1.Node ein TextNode, dann muss im NodesArray auch 1735 // ein TextNode vorhanden sein, in den der Inhalt geschoben wird 1736 if( !pDestNd ) 1737 { 1738 pDestNd = rNodes.MakeTxtNode( rPos.nNode, pSrcNd->GetTxtColl() ); 1739 rPos.nNode--; 1740 rPos.nContent.Assign( pDestNd, 0 ); 1741 bCopyCollFmt = sal_True; 1742 } 1743 bSplitDestNd = pDestNd->Len() > rPos.nContent.GetIndex() || 1744 pEnd->nNode.GetNode().IsTxtNode(); 1745 1746 // verschiebe jetzt noch den Inhalt in den neuen Node 1747 sal_Bool bOneNd = pStt->nNode == pEnd->nNode; 1748 const xub_StrLen nLen = 1749 ( (bOneNd) ? pEnd->nContent.GetIndex() : pSrcNd->Len() ) 1750 - pStt->nContent.GetIndex(); 1751 1752 if( !pEnd->nNode.GetNode().IsCntntNode() ) 1753 { 1754 bOneNd = sal_True; 1755 sal_uLong nSttNdIdx = pStt->nNode.GetIndex() + 1; 1756 const sal_uLong nEndNdIdx = pEnd->nNode.GetIndex(); 1757 for( ; nSttNdIdx < nEndNdIdx; ++nSttNdIdx ) 1758 { 1759 if( (*this)[ nSttNdIdx ]->IsCntntNode() ) 1760 { 1761 bOneNd = sal_False; 1762 break; 1763 } 1764 } 1765 } 1766 1767 // das kopieren / setzen der Vorlagen darf erst nach 1768 // dem Splitten erfolgen 1769 if( !bOneNd && bSplitDestNd ) 1770 { 1771 if( !rPos.nContent.GetIndex() ) 1772 { 1773 bCopyCollFmt = sal_True; 1774 } 1775 if( rNodes.IsDocNodes() ) 1776 { 1777 SwDoc* const pInsDoc = pDestNd->GetDoc(); 1778 ::sw::UndoGuard const ug(pInsDoc->GetIDocumentUndoRedo()); 1779 pInsDoc->SplitNode( rPos, false ); 1780 } 1781 else 1782 { 1783 pDestNd->SplitCntntNode( rPos ); 1784 } 1785 1786 if( rPos.nNode == aEndIdx ) 1787 { 1788 aEndIdx--; 1789 } 1790 bSplitDestNd = sal_True; 1791 1792 pDestNd = rNodes[ rPos.nNode.GetIndex() - 1 ]->GetTxtNode(); 1793 if( nLen ) 1794 { 1795 pSrcNd->CutText( pDestNd, SwIndex( pDestNd, pDestNd->Len()), 1796 pStt->nContent, nLen ); 1797 } 1798 } 1799 else if ( nLen ) 1800 { 1801 pSrcNd->CutText( pDestNd, rPos.nContent, pStt->nContent, nLen ); 1802 } 1803 1804 if( bCopyCollFmt ) 1805 { 1806 SwDoc* const pInsDoc = pDestNd->GetDoc(); 1807 ::sw::UndoGuard const undoGuard(pInsDoc->GetIDocumentUndoRedo()); 1808 pSrcNd->CopyCollFmt( *pDestNd ); 1809 bCopyCollFmt = sal_False; 1810 } 1811 1812 if( bOneNd ) // das wars schon 1813 { 1814 // der PaM wird korrigiert, denn falls ueber Nodegrenzen verschoben 1815 // wurde, so stehen sie in unterschieden Nodes. Auch die Selektion 1816 // wird aufgehoben ! 1817 pEnd->nContent = pStt->nContent; 1818 rPam.DeleteMark(); 1819 GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( 0, 1820 rNodes.IsDocNodes() ? SWFMTFLD_INSERTED : SWFMTFLD_REMOVED ) ); 1821 return; 1822 } 1823 1824 aSttIdx++; 1825 } 1826 else if( pDestNd ) 1827 { 1828 if( rPos.nContent.GetIndex() ) 1829 { 1830 if( rPos.nContent.GetIndex() == pDestNd->Len() ) 1831 { 1832 rPos.nNode++; 1833 } 1834 else if( rPos.nContent.GetIndex() ) 1835 { 1836 // falls im EndNode gesplittet wird, dann muss der EndIdx 1837 // korrigiert werden !! 1838 const bool bCorrEnd = aEndIdx == rPos.nNode; 1839 // es wird kein Text an den TextNode angehaengt, also splitte ihn 1840 1841 if( rNodes.IsDocNodes() ) 1842 { 1843 SwDoc* const pInsDoc = pDestNd->GetDoc(); 1844 ::sw::UndoGuard const ug(pInsDoc->GetIDocumentUndoRedo()); 1845 pInsDoc->SplitNode( rPos, false ); 1846 } 1847 else 1848 { 1849 pDestNd->SplitCntntNode( rPos ); 1850 } 1851 1852 pDestNd = rPos.nNode.GetNode().GetTxtNode(); 1853 1854 if ( bCorrEnd ) 1855 { 1856 aEndIdx--; 1857 } 1858 } 1859 } 1860 // am Ende steht noch ein leerer Text Node herum. 1861 bSplitDestNd = sal_True; 1862 } 1863 1864 SwTxtNode* const pEndSrcNd = aEndIdx.GetNode().GetTxtNode(); 1865 if ( pEndSrcNd ) 1866 { 1867 { 1868 // am Bereichsende entsteht ein neuer TextNode 1869 if( !bSplitDestNd ) 1870 { 1871 if( rPos.nNode < rNodes.GetEndOfContent().GetIndex() ) 1872 { 1873 rPos.nNode++; 1874 } 1875 1876 pDestNd = 1877 rNodes.MakeTxtNode( rPos.nNode, pEndSrcNd->GetTxtColl() ); 1878 rPos.nNode--; 1879 rPos.nContent.Assign( pDestNd, 0 ); 1880 } 1881 else 1882 { 1883 pDestNd = rPos.nNode.GetNode().GetTxtNode(); 1884 } 1885 1886 if( pDestNd && pEnd->nContent.GetIndex() ) 1887 { 1888 // verschiebe jetzt noch den Inhalt in den neuen Node 1889 SwIndex aIdx( pEndSrcNd, 0 ); 1890 pEndSrcNd->CutText( pDestNd, rPos.nContent, aIdx, 1891 pEnd->nContent.GetIndex()); 1892 } 1893 1894 if( bCopyCollFmt ) 1895 { 1896 SwDoc* const pInsDoc = pDestNd->GetDoc(); 1897 ::sw::UndoGuard const ug(pInsDoc->GetIDocumentUndoRedo()); 1898 pEndSrcNd->CopyCollFmt( *pDestNd ); 1899 } 1900 } 1901 } 1902 else 1903 { 1904 if ( pSrcNd && aEndIdx.GetNode().IsCntntNode() ) 1905 { 1906 aEndIdx++; 1907 } 1908 if( !bSplitDestNd ) 1909 { 1910 rPos.nNode++; 1911 rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), 0 ); 1912 } 1913 } 1914 1915 if( aEndIdx != aSttIdx ) 1916 { 1917 // verschiebe jetzt die Nodes in das NodesArary 1918 const sal_uLong nSttDiff = aSttIdx.GetIndex() - pStt->nNode.GetIndex(); 1919 SwNodeRange aRg( aSttIdx, aEndIdx ); 1920 _MoveNodes( aRg, rNodes, rPos.nNode ); 1921 // falls ins gleiche Nodes-Array verschoben wurde, stehen die 1922 // Indizies jetzt auch an der neuen Position !!!! 1923 // (also alles wieder umsetzen) 1924 if( &rNodes == this ) 1925 { 1926 pStt->nNode = aRg.aEnd.GetIndex() - nSttDiff; 1927 } 1928 } 1929 1930 // falls der Start-Node verschoben wurde, in dem der Cursor stand, so 1931 // muss der Content im akt. Content angemeldet werden !!! 1932 if ( &pStt->nNode.GetNode() == &GetEndOfContent() ) 1933 { 1934 const bool bSuccess = GoPrevious( &pStt->nNode ); 1935 ASSERT( bSuccess, "Move() - no ContentNode here" ); 1936 (void) bSuccess; 1937 } 1938 pStt->nContent.Assign( pStt->nNode.GetNode().GetCntntNode(), 1939 pStt->nContent.GetIndex() ); 1940 // der PaM wird korrigiert, denn falls ueber Nodegrenzen verschoben 1941 // wurde, so stehen sie in unterschielichen Nodes. Auch die Selektion 1942 // wird aufgehoben ! 1943 *pEnd = *pStt; 1944 rPam.DeleteMark(); 1945 GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( 0, 1946 rNodes.IsDocNodes() ? SWFMTFLD_INSERTED : SWFMTFLD_REMOVED ) ); 1947 } 1948 1949 1950 1951 /************************************************************************* 1952 |* 1953 |* SwNodes::_Copy() 1954 |* 1955 |* Beschreibung 1956 |* Parameter SwNodeRange& zu kopierender Bereich 1957 |* SwDoc& in dieses Dokument 1958 |* SwIndex& auf diese Position im Nodes-Array 1959 |* Ersterstellung JP 11.11.92 1960 |* Letzte Aenderung JP 11.11.92 1961 |* 1962 *************************************************************************/ 1963 1964 inline sal_uInt8 MaxLvl( sal_uInt8 nMin, sal_uInt8 nMax, short nNew ) 1965 { 1966 return (sal_uInt8)(nNew < nMin ? nMin : nNew > nMax ? nMax : nNew); 1967 } 1968 1969 void SwNodes::_CopyNodes( const SwNodeRange& rRange, 1970 const SwNodeIndex& rIndex, sal_Bool bNewFrms, sal_Bool bTblInsDummyNode ) const 1971 { 1972 SwDoc* pDoc = rIndex.GetNode().GetDoc(); 1973 1974 SwNode * pAktNode; 1975 if( rIndex == 0 || 1976 ( (pAktNode = &rIndex.GetNode())->GetStartNode() && 1977 !pAktNode->StartOfSectionIndex() )) 1978 return; 1979 1980 SwNodeRange aRg( rRange ); 1981 1982 // "einfache" StartNodes oder EndNodes ueberspringen 1983 while( ND_STARTNODE == (pAktNode = & aRg.aStart.GetNode())->GetNodeType() 1984 || ( pAktNode->IsEndNode() && 1985 !pAktNode->pStartOfSection->IsSectionNode() ) ) 1986 aRg.aStart++; 1987 1988 // falls aEnd-1 auf keinem ContentNode steht, dann suche den vorherigen 1989 aRg.aEnd--; 1990 // #i107142#: if aEnd is start node of a special section, do nothing. 1991 // Otherwise this could lead to crash: going through all previous 1992 // special section nodes and then one before the first. 1993 if (aRg.aEnd.GetNode().StartOfSectionIndex() != 0) 1994 { 1995 while( ((pAktNode = & aRg.aEnd.GetNode())->GetStartNode() && 1996 !pAktNode->IsSectionNode() ) || 1997 ( pAktNode->IsEndNode() && 1998 ND_STARTNODE == pAktNode->pStartOfSection->GetNodeType()) ) 1999 { 2000 aRg.aEnd--; 2001 } 2002 } 2003 aRg.aEnd++; 2004 2005 // wird im selben Array's verschoben, dann ueberpruefe die Einfuegepos. 2006 if( aRg.aStart >= aRg.aEnd ) 2007 return; 2008 2009 // when inserting into the source range, nothing need to be done 2010 DBG_ASSERT( &aRg.aStart.GetNodes() == this, 2011 "aRg should use thisnodes array" ); 2012 DBG_ASSERT( &aRg.aStart.GetNodes() == &aRg.aEnd.GetNodes(), 2013 "Range across different nodes arrays? You deserve punishment!"); 2014 if( &rIndex.GetNodes() == &aRg.aStart.GetNodes() && 2015 rIndex.GetIndex() >= aRg.aStart.GetIndex() && 2016 rIndex.GetIndex() < aRg.aEnd.GetIndex() ) 2017 return; 2018 2019 SwNodeIndex aInsPos( rIndex ); 2020 SwNodeIndex aOrigInsPos( rIndex, -1 ); // Originale Insert Pos 2021 sal_uInt16 nLevel = 0; // Level-Counter 2022 2023 for( sal_uLong nNodeCnt = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex(); 2024 nNodeCnt > 0; --nNodeCnt ) 2025 { 2026 pAktNode = &aRg.aStart.GetNode(); 2027 switch( pAktNode->GetNodeType() ) 2028 { 2029 case ND_TABLENODE: 2030 // dann kopiere mal den TableNode 2031 // Tabell in Fussnote kopieren ? 2032 if( aInsPos < pDoc->GetNodes().GetEndOfInserts().GetIndex() && 2033 pDoc->GetNodes().GetEndOfInserts().StartOfSectionIndex() 2034 < aInsPos.GetIndex() ) 2035 { 2036 nNodeCnt -= 2037 ( pAktNode->EndOfSectionIndex() - 2038 aRg.aStart.GetIndex() ); 2039 2040 // dann alle Nodes der Tabelle in die akt. Zelle kopieren 2041 // fuer den TabellenNode einen DummyNode einfuegen? 2042 if( bTblInsDummyNode ) 2043 new SwNode( aInsPos, ND_SECTIONDUMMY ); 2044 2045 for( aRg.aStart++; aRg.aStart.GetIndex() < 2046 pAktNode->EndOfSectionIndex(); 2047 aRg.aStart++ ) 2048 { 2049 // fuer den Box-StartNode einen DummyNode einfuegen? 2050 if( bTblInsDummyNode ) 2051 new SwNode( aInsPos, ND_SECTIONDUMMY ); 2052 2053 SwStartNode* pSttNd = aRg.aStart.GetNode().GetStartNode(); 2054 _CopyNodes( SwNodeRange( *pSttNd, + 1, 2055 *pSttNd->EndOfSectionNode() ), 2056 aInsPos, bNewFrms, sal_False ); 2057 2058 // fuer den Box-EndNode einen DummyNode einfuegen? 2059 if( bTblInsDummyNode ) 2060 new SwNode( aInsPos, ND_SECTIONDUMMY ); 2061 aRg.aStart = *pSttNd->EndOfSectionNode(); 2062 } 2063 // fuer den TabellenEndNode einen DummyNode einfuegen? 2064 if( bTblInsDummyNode ) 2065 new SwNode( aInsPos, ND_SECTIONDUMMY ); 2066 aRg.aStart = *pAktNode->EndOfSectionNode(); 2067 } 2068 else 2069 { 2070 SwNodeIndex nStt( aInsPos, -1 ); 2071 SwTableNode* pTblNd = ((SwTableNode*)pAktNode)-> 2072 MakeCopy( pDoc, aInsPos ); 2073 nNodeCnt -= aInsPos.GetIndex() - nStt.GetIndex() -2; 2074 2075 aRg.aStart = pAktNode->EndOfSectionIndex(); 2076 2077 if( bNewFrms && pTblNd ) 2078 { 2079 nStt = aInsPos; 2080 pTblNd->MakeFrms( &nStt ); 2081 } 2082 } 2083 break; 2084 2085 case ND_SECTIONNODE: // SectionNode 2086 // If the end of the section is outside the copy range, 2087 // the section node will skipped, not copied! 2088 // If someone want to change this behaviour, he has to adjust the function 2089 // lcl_NonCopyCount(..) in ndcopy.cxx which relies on it. 2090 if( pAktNode->EndOfSectionIndex() < aRg.aEnd.GetIndex() ) 2091 { 2092 // also der gesamte, lege einen neuen SectionNode an 2093 SwNodeIndex nStt( aInsPos, -1 ); 2094 SwSectionNode* pSectNd = ((SwSectionNode*)pAktNode)-> 2095 MakeCopy( pDoc, aInsPos ); 2096 2097 nNodeCnt -= aInsPos.GetIndex() - nStt.GetIndex() -2; 2098 aRg.aStart = pAktNode->EndOfSectionIndex(); 2099 2100 if( bNewFrms && pSectNd && 2101 !pSectNd->GetSection().IsHidden() ) 2102 pSectNd->MakeFrms( &nStt ); 2103 } 2104 break; 2105 2106 case ND_STARTNODE: // StartNode gefunden 2107 { 2108 SwStartNode* pTmp = new SwStartNode( aInsPos, ND_STARTNODE, 2109 ((SwStartNode*)pAktNode)->GetStartNodeType() ); 2110 new SwEndNode( aInsPos, *pTmp ); 2111 aInsPos--; 2112 nLevel++; 2113 } 2114 break; 2115 2116 case ND_ENDNODE: 2117 if( nLevel ) // vollstaendige Section 2118 { 2119 --nLevel; 2120 aInsPos++; // EndNode schon vorhanden 2121 } 2122 else if( !pAktNode->pStartOfSection->IsSectionNode() ) 2123 { 2124 // erzeuge eine Section an der originalen InsertPosition 2125 SwNodeRange aTmpRg( aOrigInsPos, 1, aInsPos ); 2126 pDoc->GetNodes().SectionDown( &aTmpRg, 2127 pAktNode->pStartOfSection->GetStartNodeType() ); 2128 } 2129 break; 2130 2131 case ND_TEXTNODE: 2132 case ND_GRFNODE: 2133 case ND_OLENODE: 2134 { 2135 SwCntntNode* pNew = ((SwCntntNode*)pAktNode)->MakeCopy( 2136 pDoc, aInsPos ); 2137 if( !bNewFrms ) // dflt. werden die Frames immer angelegt 2138 pNew->DelFrms(); 2139 } 2140 break; 2141 2142 case ND_SECTIONDUMMY: 2143 if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(*this)) 2144 { 2145 // dann muss an der akt. InsPos auch ein SectionNode 2146 // (Start/Ende) stehen; dann diesen ueberspringen. 2147 // Andernfalls nicht weiter beachten. 2148 SwNode *const pTmpNd = & aInsPos.GetNode(); 2149 if( pTmpNd->IsSectionNode() || 2150 pTmpNd->StartOfSectionNode()->IsSectionNode() ) 2151 aInsPos++; // ueberspringen 2152 } 2153 else { 2154 ASSERT( sal_False, "wie kommt diser Node ins Nodes-Array??" ); 2155 } 2156 break; 2157 2158 default: 2159 ASSERT( sal_False, "weder Start-/End-/Content-Node, unbekannter Typ" ); 2160 } 2161 aRg.aStart++; 2162 } 2163 2164 2165 #ifdef JP_DEBUG 2166 { 2167 extern Writer* GetDebugWriter(const String&); 2168 2169 Writer* pWriter = GetDebugWriter(aEmptyStr); 2170 if( pWriter ) 2171 { 2172 int nError; 2173 SvFileStream aStrm( "c:\\$$copy.db", STREAM_WRITE ); 2174 SwWriter aWriter( aStrm, *pMyDoc ); 2175 aWriter.Write( &nError, pWriter ); 2176 } 2177 } 2178 #endif 2179 } 2180 2181 void SwNodes::_DelDummyNodes( const SwNodeRange& rRg ) 2182 { 2183 SwNodeIndex aIdx( rRg.aStart ); 2184 while( aIdx.GetIndex() < rRg.aEnd.GetIndex() ) 2185 { 2186 if( ND_SECTIONDUMMY == aIdx.GetNode().GetNodeType() ) 2187 RemoveNode( aIdx.GetIndex(), 1, sal_True ); 2188 else 2189 aIdx++; 2190 } 2191 } 2192 2193 SwStartNode* SwNodes::MakeEmptySection( const SwNodeIndex& rIdx, 2194 SwStartNodeType eSttNdTyp ) 2195 { 2196 SwStartNode* pSttNd = new SwStartNode( rIdx, ND_STARTNODE, eSttNdTyp ); 2197 new SwEndNode( rIdx, *pSttNd ); 2198 return pSttNd; 2199 } 2200 2201 2202 SwStartNode* SwNodes::MakeTextSection( const SwNodeIndex & rWhere, 2203 SwStartNodeType eSttNdTyp, 2204 SwTxtFmtColl *pColl, 2205 SwAttrSet* pAutoAttr ) 2206 { 2207 SwStartNode* pSttNd = new SwStartNode( rWhere, ND_STARTNODE, eSttNdTyp ); 2208 new SwEndNode( rWhere, *pSttNd ); 2209 MakeTxtNode( SwNodeIndex( rWhere, - 1 ), pColl, pAutoAttr ); 2210 return pSttNd; 2211 } 2212 2213 // zum naechsten Content-Node, der nicht geschuetzt oder versteckt ist 2214 // (beides auf sal_False ==> GoNext/GoPrevious!!!) 2215 SwCntntNode* SwNodes::GoNextSection( SwNodeIndex * pIdx, 2216 int bSkipHidden, int bSkipProtect ) const 2217 { 2218 int bFirst = sal_True; 2219 SwNodeIndex aTmp( *pIdx ); 2220 const SwNode* pNd; 2221 while( aTmp < Count() - 1 ) 2222 { 2223 pNd = & aTmp.GetNode(); 2224 if (ND_SECTIONNODE == pNd->GetNodeType()) 2225 { 2226 const SwSection& rSect = ((SwSectionNode*)pNd)->GetSection(); 2227 if( (bSkipHidden && rSect.IsHiddenFlag()) || 2228 (bSkipProtect && rSect.IsProtectFlag()) ) 2229 // dann diese Section ueberspringen 2230 aTmp = *pNd->EndOfSectionNode(); 2231 bFirst = sal_False; 2232 } 2233 else if( bFirst ) 2234 { 2235 bFirst = sal_False; 2236 if( pNd->pStartOfSection->IsSectionNode() ) 2237 { 2238 const SwSection& rSect = ((SwSectionNode*)pNd-> 2239 pStartOfSection)->GetSection(); 2240 if( (bSkipHidden && rSect.IsHiddenFlag()) || 2241 (bSkipProtect && rSect.IsProtectFlag()) ) 2242 // dann diese Section ueberspringen 2243 aTmp = *pNd->EndOfSectionNode(); 2244 } 2245 } 2246 else if( ND_CONTENTNODE & pNd->GetNodeType() ) 2247 { 2248 const SwSectionNode* pSectNd; 2249 if( ( bSkipHidden || bSkipProtect ) && 2250 0 != (pSectNd = pNd->FindSectionNode() ) && 2251 ( ( bSkipHidden && pSectNd->GetSection().IsHiddenFlag() ) || 2252 ( bSkipProtect && pSectNd->GetSection().IsProtectFlag() )) ) 2253 { 2254 aTmp = *pSectNd->EndOfSectionNode(); 2255 } 2256 else 2257 { 2258 (*pIdx) = aTmp; 2259 return (SwCntntNode*)pNd; 2260 } 2261 } 2262 aTmp++; 2263 bFirst = sal_False; 2264 } 2265 return 0; 2266 } 2267 2268 SwCntntNode* SwNodes::GoPrevSection( SwNodeIndex * pIdx, 2269 int bSkipHidden, int bSkipProtect ) const 2270 { 2271 int bFirst = sal_True; 2272 SwNodeIndex aTmp( *pIdx ); 2273 const SwNode* pNd; 2274 while( aTmp > 0 ) 2275 { 2276 pNd = & aTmp.GetNode(); 2277 if (ND_ENDNODE == pNd->GetNodeType()) 2278 { 2279 if( pNd->pStartOfSection->IsSectionNode() ) 2280 { 2281 const SwSection& rSect = ((SwSectionNode*)pNd-> 2282 pStartOfSection)->GetSection(); 2283 if( (bSkipHidden && rSect.IsHiddenFlag()) || 2284 (bSkipProtect && rSect.IsProtectFlag()) ) 2285 // dann diese Section ueberspringen 2286 aTmp = *pNd->StartOfSectionNode(); 2287 } 2288 bFirst = sal_False; 2289 } 2290 else if( bFirst ) 2291 { 2292 bFirst = sal_False; 2293 if( pNd->pStartOfSection->IsSectionNode() ) 2294 { 2295 const SwSection& rSect = ((SwSectionNode*)pNd-> 2296 pStartOfSection)->GetSection(); 2297 if( (bSkipHidden && rSect.IsHiddenFlag()) || 2298 (bSkipProtect && rSect.IsProtectFlag()) ) 2299 // dann diese Section ueberspringen 2300 aTmp = *pNd->StartOfSectionNode(); 2301 } 2302 } 2303 else if( ND_CONTENTNODE & pNd->GetNodeType() ) 2304 { 2305 const SwSectionNode* pSectNd; 2306 if( ( bSkipHidden || bSkipProtect ) && 2307 0 != (pSectNd = pNd->FindSectionNode() ) && 2308 ( ( bSkipHidden && pSectNd->GetSection().IsHiddenFlag() ) || 2309 ( bSkipProtect && pSectNd->GetSection().IsProtectFlag() )) ) 2310 { 2311 aTmp = *pSectNd; 2312 } 2313 else 2314 { 2315 (*pIdx) = aTmp; 2316 return (SwCntntNode*)pNd; 2317 } 2318 } 2319 aTmp--; 2320 } 2321 return 0; 2322 } 2323 2324 2325 // suche den vorhergehenden [/nachfolgenden ] ContentNode oder 2326 // TabellenNode mit Frames. Wird kein Ende angeben, dann wird mit 2327 // dem FrameIndex begonnen; ansonsten, wird mit dem vor rFrmIdx und 2328 // dem hintern pEnd die Suche gestartet. Sollte kein gueltiger Node 2329 // gefunden werden, wird 0 returnt. rFrmIdx zeigt auf dem Node mit 2330 // Frames 2331 SwNode* SwNodes::FindPrvNxtFrmNode( SwNodeIndex& rFrmIdx, 2332 const SwNode* pEnd ) const 2333 { 2334 SwNode* pFrmNd = 0; 2335 2336 // habe wir gar kein Layout, vergiss es 2337 if( GetDoc()->GetCurrentViewShell() ) //swmod 071108//swmod 071225 2338 { 2339 SwNode* pSttNd = &rFrmIdx.GetNode(); 2340 2341 // wird in eine versteckte Section verschoben ?? 2342 SwSectionNode* pSectNd = pSttNd->IsSectionNode() 2343 ? pSttNd->StartOfSectionNode()->FindSectionNode() 2344 : pSttNd->FindSectionNode(); 2345 if( !( pSectNd && pSectNd->GetSection().CalcHiddenFlag()/*IsHiddenFlag()*/ ) ) 2346 { 2347 // #130650# in a table in table situation we have to assure that we don't leave the 2348 // outer table cell when the inner table is looking for a PrvNxt... 2349 SwTableNode* pTableNd = pSttNd->IsTableNode() 2350 ? pSttNd->StartOfSectionNode()->FindTableNode() 2351 : pSttNd->FindTableNode(); 2352 SwNodeIndex aIdx( rFrmIdx ); 2353 SwNode* pNd; 2354 if( pEnd ) 2355 { 2356 aIdx--; 2357 pNd = &aIdx.GetNode(); 2358 } 2359 else 2360 pNd = pSttNd; 2361 2362 if( ( pFrmNd = pNd )->IsCntntNode() ) 2363 rFrmIdx = aIdx; 2364 2365 // suche nach vorne/hinten nach einem Content Node 2366 else if( 0 != ( pFrmNd = GoPrevSection( &aIdx, sal_True, sal_False )) && 2367 ::CheckNodesRange( aIdx, rFrmIdx, sal_True ) && 2368 // nach vorne nie aus der Tabelle hinaus! 2369 pFrmNd->FindTableNode() == pTableNd && 2370 // Bug 37652: nach hinten nie aus der Tabellenzelle hinaus! 2371 (!pFrmNd->FindTableNode() || pFrmNd->FindTableBoxStartNode() 2372 == pSttNd->FindTableBoxStartNode() ) && 2373 (!pSectNd || pSttNd->IsSectionNode() || 2374 pSectNd->GetIndex() < pFrmNd->GetIndex()) 2375 ) 2376 { 2377 rFrmIdx = aIdx; 2378 } 2379 else 2380 { 2381 if( pEnd ) 2382 aIdx = pEnd->GetIndex() + 1; 2383 else 2384 aIdx = rFrmIdx; 2385 2386 // JP 19.09.93: aber nie die Section dafuer verlassen !! 2387 if( ( pEnd && ( pFrmNd = &aIdx.GetNode())->IsCntntNode() ) || 2388 ( 0 != ( pFrmNd = GoNextSection( &aIdx, sal_True, sal_False )) && 2389 ::CheckNodesRange( aIdx, rFrmIdx, sal_True ) && 2390 ( pFrmNd->FindTableNode() == pTableNd && 2391 // Bug 37652: nach hinten nie aus der Tabellenzelle hinaus! 2392 (!pFrmNd->FindTableNode() || pFrmNd->FindTableBoxStartNode() 2393 == pSttNd->FindTableBoxStartNode() ) ) && 2394 (!pSectNd || pSttNd->IsSectionNode() || 2395 pSectNd->EndOfSectionIndex() > pFrmNd->GetIndex()) 2396 )) 2397 { 2398 //JP 18.02.99: Undo von Merge einer Tabelle mit der 2399 // der vorherigen, wenn dahinter auch noch eine steht 2400 // falls aber der Node in einer Tabelle steht, muss 2401 // natuerlich dieser returnt werden, wenn der SttNode eine 2402 // Section oder Tabelle ist! 2403 SwTableNode* pTblNd; 2404 if( pSttNd->IsTableNode() && 2405 0 != ( pTblNd = pFrmNd->FindTableNode() ) && 2406 // TABLE IN TABLE: 2407 pTblNd != pSttNd->StartOfSectionNode()->FindTableNode() ) 2408 { 2409 pFrmNd = pTblNd; 2410 rFrmIdx = *pFrmNd; 2411 } 2412 else 2413 rFrmIdx = aIdx; 2414 } 2415 else if( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsTableNode() ) 2416 { 2417 pFrmNd = pNd->StartOfSectionNode(); 2418 rFrmIdx = *pFrmNd; 2419 } 2420 else 2421 { 2422 if( pEnd ) 2423 aIdx = pEnd->GetIndex() + 1; 2424 else 2425 aIdx = rFrmIdx.GetIndex() + 1; 2426 2427 if( (pFrmNd = &aIdx.GetNode())->IsTableNode() ) 2428 rFrmIdx = aIdx; 2429 else 2430 { 2431 pFrmNd = 0; 2432 2433 // is there some sectionnodes before a tablenode? 2434 while( aIdx.GetNode().IsSectionNode() ) 2435 { 2436 const SwSection& rSect = aIdx.GetNode(). 2437 GetSectionNode()->GetSection(); 2438 if( rSect.IsHiddenFlag() ) 2439 aIdx = aIdx.GetNode().EndOfSectionIndex()+1; 2440 else 2441 aIdx++; 2442 } 2443 if( aIdx.GetNode().IsTableNode() ) 2444 { 2445 rFrmIdx = aIdx; 2446 pFrmNd = &aIdx.GetNode(); 2447 } 2448 } 2449 } 2450 } 2451 } 2452 } 2453 return pFrmNd; 2454 } 2455 2456 void SwNodes::ForEach( const SwNodeIndex& rStart, const SwNodeIndex& rEnd, 2457 FnForEach_SwNodes fnForEach, void* pArgs ) 2458 { 2459 BigPtrArray::ForEach( rStart.GetIndex(), rEnd.GetIndex(), 2460 (FnForEach) fnForEach, pArgs ); 2461 } 2462 2463 struct _TempBigPtrEntry : public BigPtrEntry 2464 { 2465 _TempBigPtrEntry() {} 2466 }; 2467 2468 2469 void SwNodes::RemoveNode( sal_uLong nDelPos, sal_uLong nSz, sal_Bool bDel ) 2470 { 2471 sal_uLong nEnd = nDelPos + nSz; 2472 SwNode* pNew = (*this)[ nEnd ]; 2473 2474 if( pRoot ) 2475 { 2476 SwNodeIndex *p = pRoot; 2477 while( p ) 2478 { 2479 sal_uLong nIdx = p->GetIndex(); 2480 SwNodeIndex* pNext = p->pNext; 2481 if( nDelPos <= nIdx && nIdx < nEnd ) 2482 (*p) = *pNew; 2483 2484 p = pNext; 2485 } 2486 2487 p = pRoot->pPrev; 2488 while( p ) 2489 { 2490 sal_uLong nIdx = p->GetIndex(); 2491 SwNodeIndex* pPrev = p->pPrev; 2492 if( nDelPos <= nIdx && nIdx < nEnd ) 2493 (*p) = *pNew; 2494 2495 p = pPrev; 2496 } 2497 } 2498 2499 { 2500 for (sal_uLong nCnt = 0; nCnt < nSz; nCnt++) 2501 { 2502 SwTxtNode * pTxtNd = ((*this)[ nDelPos + nCnt ])->GetTxtNode(); 2503 2504 if (pTxtNd) 2505 { 2506 // --> OD 2008-03-13 #refactorlists# 2507 // pTxtNd->UnregisterNumber(); 2508 pTxtNd->RemoveFromList(); 2509 // <-- 2510 } 2511 } 2512 } 2513 2514 if( bDel ) 2515 { 2516 sal_uLong nCnt = nSz; 2517 SwNode *pDel = (*this)[ nDelPos+nCnt-1 ], *pPrev = (*this)[ nDelPos+nCnt-2 ]; 2518 2519 // temp. Object setzen 2520 //JP 24.08.98: muessten eigentlich einzeln removed werden, weil 2521 // das Remove auch rekursiv gerufen werden kann, z.B. bei 2522 // zeichengebundenen Rahmen. Da aber dabei viel zu viel 2523 // ablaueft, wird hier ein temp. Objekt eingefuegt, das 2524 // dann mit dem Remove wieder entfernt wird. 2525 // siehe Bug 55406 2526 _TempBigPtrEntry aTempEntry; 2527 BigPtrEntry* pTempEntry = &aTempEntry; 2528 2529 while( nCnt-- ) 2530 { 2531 delete pDel; 2532 pDel = pPrev; 2533 sal_uLong nPrevNdIdx = pPrev->GetIndex(); 2534 BigPtrArray::Replace( nPrevNdIdx+1, pTempEntry ); 2535 if( nCnt ) 2536 pPrev = (*this)[ nPrevNdIdx - 1 ]; 2537 } 2538 nDelPos = pDel->GetIndex() + 1; 2539 } 2540 2541 BigPtrArray::Remove( nDelPos, nSz ); 2542 } 2543 2544 void SwNodes::RegisterIndex( SwNodeIndex& rIdx ) 2545 { 2546 if( !pRoot ) // noch keine Root gesetzt? 2547 { 2548 pRoot = &rIdx; 2549 pRoot->pPrev = 0; 2550 pRoot->pNext = 0; 2551 } 2552 else 2553 { 2554 // immer hinter die Root haengen 2555 rIdx.pNext = pRoot->pNext; 2556 pRoot->pNext = &rIdx; 2557 rIdx.pPrev = pRoot; 2558 if( rIdx.pNext ) 2559 rIdx.pNext->pPrev = &rIdx; 2560 } 2561 } 2562 2563 void SwNodes::DeRegisterIndex( SwNodeIndex& rIdx ) 2564 { 2565 SwNodeIndex* pN = rIdx.pNext; 2566 SwNodeIndex* pP = rIdx.pPrev; 2567 2568 if( pRoot == &rIdx ) 2569 pRoot = pP ? pP : pN; 2570 2571 if( pP ) 2572 pP->pNext = pN; 2573 if( pN ) 2574 pN->pPrev = pP; 2575 2576 rIdx.pNext = 0; 2577 rIdx.pPrev = 0; 2578 } 2579 2580 void SwNodes::InsertNode( const SwNodePtr pNode, 2581 const SwNodeIndex& rPos ) 2582 { 2583 const ElementPtr pIns = pNode; 2584 BigPtrArray::Insert( pIns, rPos.GetIndex() ); 2585 } 2586 2587 void SwNodes::InsertNode( const SwNodePtr pNode, 2588 sal_uLong nPos ) 2589 { 2590 const ElementPtr pIns = pNode; 2591 BigPtrArray::Insert( pIns, nPos ); 2592 } 2593 2594 // ->#112139# 2595 SwNode * SwNodes::DocumentSectionStartNode(SwNode * pNode) const 2596 { 2597 if (NULL != pNode) 2598 { 2599 SwNodeIndex aIdx(*pNode); 2600 2601 if (aIdx <= (*this)[0]->EndOfSectionIndex()) 2602 pNode = (*this)[0]; 2603 else 2604 { 2605 while ((*this)[0] != pNode->StartOfSectionNode()) 2606 pNode = pNode->StartOfSectionNode(); 2607 } 2608 } 2609 2610 return pNode; 2611 } 2612 2613 SwNode * SwNodes::DocumentSectionEndNode(SwNode * pNode) const 2614 { 2615 return DocumentSectionStartNode(pNode)->EndOfSectionNode(); 2616 } 2617 2618 //SwNode * SwNodes::operator[](int n) const 2619 //{ 2620 // return operator[]((sal_uLong) n); 2621 //} 2622 // <-#112139# 2623 2624 sal_Bool SwNodes::IsDocNodes() const 2625 { 2626 return this == &pMyDoc->GetNodes(); 2627 } 2628