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