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