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