LCOV - code coverage report
Current view: top level - libreoffice/sw/source/core/docnode - nodes.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 372 1089 34.2 %
Date: 2012-12-27 Functions: 30 39 76.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10