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