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