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