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