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