LCOV - code coverage report
Current view: top level - sw/source/core/docnode - nodes.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 794 1119 71.0 %
Date: 2014-04-11 Functions: 38 40 95.0 %
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             : #include <stdlib.h>
      21             : 
      22             : #include <node.hxx>
      23             : #include <doc.hxx>
      24             : #include <IDocumentUndoRedo.hxx>
      25             : #include <pam.hxx>
      26             : #include <txtfld.hxx>
      27             : #include <fmtfld.hxx>
      28             : #include <hints.hxx>
      29             : #include <numrule.hxx>
      30             : #include <ndtxt.hxx>
      31             : #include <ndnotxt.hxx>
      32             : #include <swtable.hxx>
      33             : #include <tblsel.hxx>
      34             : #include <section.hxx>
      35             : #include <ddefld.hxx>
      36             : #include <swddetbl.hxx>
      37             : #include <frame.hxx>
      38             : #include <txtatr.hxx>
      39             : #include <tox.hxx>
      40             : 
      41             : #include <docsh.hxx>
      42             : #include <svl/smplhint.hxx>
      43             : 
      44             : typedef std::vector<SwStartNode*> SwSttNdPtrs;
      45             : 
      46             : // function to determine the highest level in the given range
      47             : sal_uInt16 HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange );
      48             : 
      49             : /** Constructor
      50             :  *
      51             :  * creates the base sections (PostIts, Inserts, AutoText, RedLines, Content)
      52             :  *
      53             :  * @param pDocument TODO: provide documentation
      54             :  */
      55        3704 : SwNodes::SwNodes( SwDoc* pDocument )
      56        3704 :     : pRoot( 0 ), pMyDoc( pDocument )
      57             : {
      58        3704 :     bInNodesDel = bInDelUpdOutl = bInDelUpdNum = sal_False;
      59             : 
      60             :     OSL_ENSURE( pMyDoc, "in which Doc am I?" );
      61             : 
      62        3704 :     sal_uLong nPos = 0;
      63        3704 :     SwStartNode* pSttNd = new SwStartNode( *this, nPos++ );
      64        3704 :     pEndOfPostIts = new SwEndNode( *this, nPos++, *pSttNd );
      65             : 
      66        3704 :     SwStartNode* pTmp = new SwStartNode( *this, nPos++ );
      67        3704 :     pEndOfInserts = new SwEndNode( *this, nPos++, *pTmp );
      68             : 
      69        3704 :     pTmp = new SwStartNode( *this, nPos++ );
      70        3704 :     pTmp->pStartOfSection = pSttNd;
      71        3704 :     pEndOfAutotext = new SwEndNode( *this, nPos++, *pTmp );
      72             : 
      73        3704 :     pTmp = new SwStartNode( *this, nPos++ );
      74        3704 :     pTmp->pStartOfSection = pSttNd;
      75        3704 :     pEndOfRedlines = new SwEndNode( *this, nPos++, *pTmp );
      76             : 
      77        3704 :     pTmp = new SwStartNode( *this, nPos++ );
      78        3704 :     pTmp->pStartOfSection = pSttNd;
      79        3704 :     pEndOfContent = new SwEndNode( *this, nPos++, *pTmp );
      80             : 
      81        3704 :     pOutlineNds = new SwOutlineNodes;
      82        3704 : }
      83             : 
      84             : /** Destructor
      85             :  *
      86             :  * Deletes all nodes whose pointer are in a dynamic array. This should be no
      87             :  * problem as nodes cannot be created outside this array and, thus, cannot be
      88             :  * part of multiple arrays.
      89             :  */
      90        7392 : SwNodes::~SwNodes()
      91             : {
      92        3696 :     delete pOutlineNds;
      93             : 
      94             :     {
      95             :         SwNode *pNode;
      96        3696 :         SwNodeIndex aNdIdx( *this );
      97             :         while( true )
      98             :         {
      99       36960 :             pNode = &aNdIdx.GetNode();
     100       36960 :             if( pNode == pEndOfContent )
     101        3696 :                 break;
     102             : 
     103       33264 :             ++aNdIdx;
     104       33264 :             delete pNode;
     105        3696 :         }
     106             :     }
     107             : 
     108             :     // here, all SwNodeIndices must be unregistered
     109        3696 :     delete pEndOfContent;
     110        3696 : }
     111             : 
     112         191 : void SwNodes::ChgNode( SwNodeIndex& rDelPos, sal_uLong nSz,
     113             :                         SwNodeIndex& rInsPos, sal_Bool bNewFrms )
     114             : {
     115             :     // no need for frames in the UndoArea
     116         191 :     SwNodes& rNds = rInsPos.GetNodes();
     117         191 :     const SwNode* pPrevInsNd = rNds[ rInsPos.GetIndex() -1 ];
     118             : 
     119             :     // declare all fields as invalid, updating will happen
     120             :     // in the idle-handler of the doc
     121         191 :     if( GetDoc()->SetFieldsDirty( true, &rDelPos.GetNode(), nSz ) &&
     122           0 :         rNds.GetDoc() != GetDoc() )
     123           0 :         rNds.GetDoc()->SetFieldsDirty( true, NULL, 0 );
     124             : 
     125             :     // NEVER include nodes from the RedLineArea
     126         191 :     sal_uLong nNd = rInsPos.GetIndex();
     127             :     bool bInsOutlineIdx = !(
     128         191 :             rNds.GetEndOfRedlines().StartOfSectionNode()->GetIndex() < nNd &&
     129         191 :             nNd < rNds.GetEndOfRedlines().GetIndex() );
     130             : 
     131         191 :     if( &rNds == this ) // if in the same node array -> move
     132             :     {
     133             :         // Move order: from front to back, so that new entries are added at
     134             :         // first position, thus, deletion position stays the same
     135          62 :         sal_uInt16 nDiff = rDelPos.GetIndex() < rInsPos.GetIndex() ? 0 : 1;
     136             : 
     137         124 :         for( sal_uLong n = rDelPos.GetIndex(); nSz; n += nDiff, --nSz )
     138             :         {
     139          62 :             SwNodeIndex aDelIdx( *this, n );
     140          62 :             SwNode& rNd = aDelIdx.GetNode();
     141             : 
     142             :             // #i57920# - correction of refactoring done by cws swnumtree:
     143             :             // - <SwTxtNode::SetLevel( NO_NUMBERING ) is deprecated and
     144             :             //   set <IsCounted> state of the text node to <false>, which
     145             :             //   isn't correct here.
     146          62 :             if ( rNd.IsTxtNode() )
     147             :             {
     148          62 :                 SwTxtNode* pTxtNode = rNd.GetTxtNode();
     149             : 
     150          62 :                 pTxtNode->RemoveFromList();
     151             : 
     152          62 :                 if (pTxtNode->IsOutline())
     153             :                 {
     154           0 :                     const SwNodePtr pSrch = (SwNodePtr)&rNd;
     155           0 :                     pOutlineNds->erase( pSrch );
     156             :                 }
     157             :             }
     158             : 
     159          62 :             BigPtrArray::Move( aDelIdx.GetIndex(), rInsPos.GetIndex() );
     160             : 
     161          62 :             if( rNd.IsTxtNode() )
     162             :             {
     163          62 :                 SwTxtNode& rTxtNd = (SwTxtNode&)rNd;
     164             : 
     165          62 :                 rTxtNd.AddToList();
     166             : 
     167          62 :                 if (bInsOutlineIdx && rTxtNd.IsOutline())
     168             :                 {
     169           0 :                     const SwNodePtr pSrch = (SwNodePtr)&rNd;
     170           0 :                     pOutlineNds->insert( pSrch );
     171             :                 }
     172          62 :                 rTxtNd.InvalidateNumRule();
     173             : 
     174             : //FEATURE::CONDCOLL
     175          62 :                 if( RES_CONDTXTFMTCOLL == rTxtNd.GetTxtColl()->Which() )
     176           0 :                     rTxtNd.ChkCondColl();
     177             : //FEATURE::CONDCOLL
     178             :             }
     179           0 :             else if( rNd.IsCntntNode() )
     180           0 :                 ((SwCntntNode&)rNd).InvalidateNumRule();
     181          62 :         }
     182             :     }
     183             :     else
     184             :     {
     185         129 :         bool bSavePersData(GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(rNds));
     186         129 :         bool bRestPersData(GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(*this));
     187         129 :         SwDoc* pDestDoc = rNds.GetDoc() != GetDoc() ? rNds.GetDoc() : 0;
     188             :         OSL_ENSURE(!pDestDoc, "SwNodes::ChgNode(): "
     189             :             "the code to handle text fields here looks broken\n"
     190             :             "if the target is in a different document.");
     191         129 :         if( !bRestPersData && !bSavePersData && pDestDoc )
     192           0 :             bSavePersData = bRestPersData = true;
     193             : 
     194         129 :         OUString sNumRule;
     195         258 :         SwNodeIndex aInsPos( rInsPos );
     196         266 :         for( sal_uLong n = 0; n < nSz; n++ )
     197             :         {
     198         137 :             SwNode* pNd = &rDelPos.GetNode();
     199             : 
     200             :             // NoTextNode keep their persistent data
     201         137 :             if( pNd->IsNoTxtNode() )
     202             :             {
     203           4 :                 if( bSavePersData )
     204           3 :                     ((SwNoTxtNode*)pNd)->SavePersistentData();
     205             :             }
     206         133 :             else if( pNd->IsTxtNode() )
     207             :             {
     208         133 :                 SwTxtNode* pTxtNd = (SwTxtNode*)pNd;
     209             : 
     210             :                 // remove outline index from old nodes array
     211         133 :                 if (pTxtNd->IsOutline())
     212             :                 {
     213           1 :                     pOutlineNds->erase( pNd );
     214             :                 }
     215             : 
     216             :                 // copy rules if needed
     217         133 :                 if( pDestDoc )
     218             :                 {
     219           0 :                     const SwNumRule* pNumRule = pTxtNd->GetNumRule();
     220           0 :                     if( pNumRule && sNumRule != pNumRule->GetName() )
     221             :                     {
     222           0 :                         sNumRule = pNumRule->GetName();
     223           0 :                         SwNumRule* pDestRule = pDestDoc->FindNumRulePtr( sNumRule );
     224           0 :                         if( pDestRule )
     225           0 :                             pDestRule->SetInvalidRule( sal_True );
     226             :                         else
     227           0 :                             pDestDoc->MakeNumRule( sNumRule, pNumRule );
     228             :                     }
     229             :                 }
     230             :                 else
     231             :                     // if movement into the UndoNodes-array, update numbering
     232         133 :                     pTxtNd->InvalidateNumRule();
     233             : 
     234         133 :                 pTxtNd->RemoveFromList();
     235             :             }
     236             : 
     237         137 :             RemoveNode( rDelPos.GetIndex(), 1, sal_False ); // move indices
     238         137 :             SwCntntNode * pCNd = pNd->GetCntntNode();
     239         137 :             rNds.InsertNode( pNd, aInsPos );
     240             : 
     241         137 :             if( pCNd )
     242             :             {
     243         137 :                 SwTxtNode* pTxtNd = pCNd->GetTxtNode();
     244         137 :                 if( pTxtNd )
     245             :                 {
     246         133 :                     SwpHints * const pHts = pTxtNd->GetpSwpHints();
     247             :                     // OultineNodes set the new nodes in the array
     248         133 :                     if (bInsOutlineIdx && pTxtNd->IsOutline())
     249             :                     {
     250           1 :                         rNds.pOutlineNds->insert( pTxtNd );
     251             :                     }
     252             : 
     253         133 :                     pTxtNd->AddToList();
     254             : 
     255             :                     // special treatment for fields
     256         133 :                     if( pHts && pHts->Count() )
     257             :                     {
     258           4 :                         bool const bToUndo = !pDestDoc &&
     259           4 :                             GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(rNds);
     260           8 :                         for( sal_uInt16 i = pHts->Count(); i; )
     261             :                         {
     262           4 :                             sal_uInt16 nDelMsg = 0;
     263           4 :                             SwTxtAttr * const pAttr = pHts->GetTextHint( --i );
     264           4 :                             switch ( pAttr->Which() )
     265             :                             {
     266             :                             case RES_TXTATR_FIELD:
     267             :                             case RES_TXTATR_ANNOTATION:
     268             :                             case RES_TXTATR_INPUTFIELD:
     269             :                                 {
     270           0 :                                     SwTxtFld* pTxtFld = static_cast<SwTxtFld*>(pAttr);
     271           0 :                                     rNds.GetDoc()->InsDelFldInFldLst( !bToUndo, *pTxtFld );
     272             : 
     273           0 :                                     const SwFieldType* pTyp = pTxtFld->GetFmtFld().GetField()->GetTyp();
     274           0 :                                     if ( RES_POSTITFLD == pTyp->Which() )
     275             :                                     {
     276           0 :                                         rNds.GetDoc()->GetDocShell()->Broadcast(
     277             :                                             SwFmtFldHint(
     278           0 :                                                 &pTxtFld->GetFmtFld(),
     279           0 :                                                 ( pTxtFld->GetFmtFld().IsFldInDoc()
     280             :                                                   ? SWFMTFLD_INSERTED
     281           0 :                                                   : SWFMTFLD_REMOVED ) ) );
     282             :                                     }
     283           0 :                                     else if( RES_DDEFLD == pTyp->Which() )
     284             :                                     {
     285           0 :                                         if( bToUndo )
     286           0 :                                             ((SwDDEFieldType*)pTyp)->DecRefCnt();
     287             :                                         else
     288           0 :                                             ((SwDDEFieldType*)pTyp)->IncRefCnt();
     289             :                                     }
     290           0 :                                     nDelMsg = RES_FIELD_DELETED;
     291             :                                 }
     292           0 :                                 break;
     293             : 
     294             :                             case RES_TXTATR_FTN:
     295           0 :                                 nDelMsg = RES_FOOTNOTE_DELETED;
     296           0 :                                 break;
     297             : 
     298             :                             case RES_TXTATR_TOXMARK:
     299           0 :                                 static_cast<SwTOXMark&>(pAttr->GetAttr())
     300           0 :                                     .InvalidateTOXMark();
     301           0 :                                 break;
     302             : 
     303             :                             case RES_TXTATR_REFMARK:
     304           0 :                                 nDelMsg = RES_REFMARK_DELETED;
     305           0 :                                 break;
     306             : 
     307             :                             case RES_TXTATR_META:
     308             :                             case RES_TXTATR_METAFIELD:
     309             :                                 {
     310             :                                     SwTxtMeta *const pTxtMeta(
     311           0 :                                         static_cast<SwTxtMeta*>(pAttr));
     312             :                                     // force removal of UNO object
     313           0 :                                     pTxtMeta->ChgTxtNode(0);
     314           0 :                                     pTxtMeta->ChgTxtNode(pTxtNd);
     315             :                                 }
     316           0 :                                 break;
     317             : 
     318             :                             default:
     319           4 :                                 break;
     320             :                             }
     321             : 
     322           4 :                             if( nDelMsg && bToUndo )
     323             :                             {
     324             :                                 SwPtrMsgPoolItem aMsgHint( nDelMsg,
     325           0 :                                     (void*)&pAttr->GetAttr() );
     326           0 :                                 rNds.GetDoc()->GetUnoCallBack()->
     327           0 :                                     ModifyNotification( &aMsgHint, &aMsgHint );
     328             :                             }
     329             :                         }
     330             :                     }
     331             :                     //FEATURE::CONDCOLL
     332         133 :                     if( RES_CONDTXTFMTCOLL == pTxtNd->GetTxtColl()->Which() )
     333           0 :                         pTxtNd->ChkCondColl();
     334             :                     //FEATURE::CONDCOLL
     335             :                 }
     336             :                 else
     337             :                 {
     338             :                     // Moved into different Docs? Persist data again!
     339           4 :                     if( pCNd->IsNoTxtNode() && bRestPersData )
     340           1 :                         ((SwNoTxtNode*)pCNd)->RestorePersistentData();
     341             :                 }
     342             :             }
     343         129 :         }
     344             :     }
     345             : 
     346             :     // declare all fields as invalid, updating will happen
     347             :     // in the idle-handler of the doc
     348         191 :     GetDoc()->SetFieldsDirty( true, NULL, 0 );
     349         191 :     if( rNds.GetDoc() != GetDoc() )
     350           0 :         rNds.GetDoc()->SetFieldsDirty( true, NULL, 0 );
     351             : 
     352         191 :     if( bNewFrms )
     353         226 :         bNewFrms = &GetDoc()->GetNodes() == (const SwNodes*)&rNds &&
     354         226 :                     GetDoc()->GetCurrentViewShell();
     355             : 
     356         191 :     if( bNewFrms )
     357             :     {
     358             :         // get the frames:
     359          62 :         SwNodeIndex aIdx( *pPrevInsNd, 1 );
     360         124 :         SwNodeIndex aFrmNdIdx( aIdx );
     361             :         SwNode* pFrmNd = rNds.FindPrvNxtFrmNode( aFrmNdIdx,
     362          62 :                                         rNds[ rInsPos.GetIndex() - 1 ] );
     363             : 
     364          62 :         if( !pFrmNd && aFrmNdIdx > rNds.GetEndOfExtras().GetIndex() )
     365             :         {
     366             :             OSL_ENSURE( !this, "here, something wrong happened" );
     367           0 :             aFrmNdIdx = rNds.GetEndOfContent();
     368           0 :             pFrmNd = rNds.GoPrevSection( &aFrmNdIdx, true, false );
     369           0 :             if( pFrmNd && !((SwCntntNode*)pFrmNd)->GetDepends() )
     370           0 :                 pFrmNd = 0;
     371             :             OSL_ENSURE( pFrmNd, "ChgNode() - no FrameNode found" );
     372             :         }
     373          62 :         if( pFrmNd )
     374         186 :             while( aIdx != rInsPos )
     375             :             {
     376          62 :                 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
     377          62 :                 if( pCNd )
     378             :                 {
     379          62 :                     if( pFrmNd->IsTableNode() )
     380           0 :                         ((SwTableNode*)pFrmNd)->MakeFrms( aIdx );
     381          62 :                     else if( pFrmNd->IsSectionNode() )
     382           0 :                         ((SwSectionNode*)pFrmNd)->MakeFrms( aIdx );
     383             :                     else
     384          62 :                         ((SwCntntNode*)pFrmNd)->MakeFrms( *pCNd );
     385          62 :                     pFrmNd = pCNd;
     386             :                 }
     387          62 :                 ++aIdx;
     388          62 :             }
     389             :     }
     390         191 : }
     391             : 
     392             : // TODO: provide documentation
     393             : /** move the node pointer
     394             :  *
     395             :  * Move the node pointer from "(inclusive) start position to (exclusive) end
     396             :  * position" to target position.
     397             :  * If the target is in front of the first or in the area between first and
     398             :  * last element to move, nothing happens.
     399             :  * If the area to move is empty or the end position is before the start
     400             :  * position, nothing happens.
     401             :  *
     402             :  * @param aRange range to move (excluding end node)
     403             :  * @param rNodes
     404             :  * @param aIndex
     405             :  * @param bNewFrms
     406             :  * @return
     407             :  */
     408         212 : sal_Bool SwNodes::_MoveNodes( const SwNodeRange& aRange, SwNodes & rNodes,
     409             :                     const SwNodeIndex& aIndex, sal_Bool bNewFrms )
     410             : {
     411             :     SwNode * pAktNode;
     412         424 :     if( aIndex == 0 ||
     413         212 :         ( (pAktNode = &aIndex.GetNode())->GetStartNode() &&
     414           0 :           !pAktNode->StartOfSectionIndex() ))
     415           0 :         return sal_False;
     416             : 
     417         212 :     SwNodeRange aRg( aRange );
     418             : 
     419             :     // skip "simple" start or end nodes
     420         636 :     while( ND_STARTNODE == (pAktNode = &aRg.aStart.GetNode())->GetNodeType()
     421         432 :             || ( pAktNode->IsEndNode() &&
     422           8 :                 !pAktNode->pStartOfSection->IsSectionNode() ) )
     423           0 :         aRg.aStart++;
     424         212 :     aRg.aStart--;
     425             : 
     426             :     // if aEnd-1 points to no ContentNode, search previous one
     427         212 :     aRg.aEnd--;
     428         636 :     while( ( (( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() &&
     429         212 :             !pAktNode->IsSectionNode() ) ||
     430         227 :             ( pAktNode->IsEndNode() &&
     431         439 :             ND_STARTNODE == pAktNode->pStartOfSection->GetNodeType()) ) &&
     432           0 :             aRg.aEnd > aRg.aStart )
     433           0 :         aRg.aEnd--;
     434             : 
     435             :     // if in same array, check insertion position
     436         212 :     if( aRg.aStart >= aRg.aEnd )
     437           0 :         return sal_False;
     438             : 
     439         212 :     if( this == &rNodes )
     440             :     {
     441         186 :         if( ( aIndex.GetIndex()-1 >= aRg.aStart.GetIndex() &&
     442         136 :               aIndex.GetIndex()-1 < aRg.aEnd.GetIndex()) ||
     443          62 :             ( aIndex.GetIndex()-1 == aRg.aEnd.GetIndex() ) )
     444          12 :             return sal_False;
     445             :     }
     446             : 
     447         200 :     sal_uInt16 nLevel = 0; // level counter
     448         200 :     sal_uLong nInsPos = 0; // counter for tmp array
     449             : 
     450             :     // array as a stack, storing all StartOfSelections
     451         400 :     SwSttNdPtrs aSttNdStack;
     452             : 
     453             :     // set start index
     454         400 :     SwNodeIndex  aIdx( aIndex );
     455             : 
     456         200 :     SwStartNode* pStartNode = aIdx.GetNode().pStartOfSection;
     457         200 :     aSttNdStack.insert( aSttNdStack.begin(), pStartNode );
     458             : 
     459         400 :     SwNodeRange aOrigInsPos( aIdx, -1, aIdx ); // original insertion position
     460             : 
     461             :     // call DelFrms/MakeFrms for the upmost SectionNode
     462         200 :     sal_uInt16 nSectNdCnt = 0;
     463         200 :     sal_Bool bSaveNewFrms = bNewFrms;
     464             : 
     465             :     // continue until everything has been moved
     466         621 :     while( aRg.aStart < aRg.aEnd )
     467         221 :         switch( (pAktNode = &aRg.aEnd.GetNode())->GetNodeType() )
     468             :         {
     469             :         case ND_ENDNODE:
     470             :             {
     471          18 :                 if( nInsPos ) // move everything until here
     472             :                 {
     473             :                     // delete and copy. CAUTION: all indices after
     474             :                     // "aRg.aEnd+1" will be moved as well!
     475           3 :                     SwNodeIndex aSwIndex( aRg.aEnd, 1 );
     476           3 :                     ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
     477           3 :                     aIdx -= nInsPos;
     478           3 :                     nInsPos = 0;
     479             :                 }
     480             : 
     481          18 :                 SwStartNode* pSttNd = pAktNode->pStartOfSection;
     482          18 :                 if( pSttNd->IsTableNode() )
     483             :                 {
     484           6 :                     SwTableNode* pTblNd = (SwTableNode*)pSttNd;
     485             : 
     486             :                     // move the whole table/range
     487          12 :                     nInsPos = (aRg.aEnd.GetIndex() -
     488          12 :                                     pSttNd->GetIndex() )+1;
     489           6 :                     aRg.aEnd -= nInsPos;
     490             : 
     491             :                     // NEVER include nodes from the RedLineArea
     492           6 :                     sal_uLong nNd = aIdx.GetIndex();
     493           6 :                     bool bInsOutlineIdx = !( rNodes.GetEndOfRedlines().
     494           6 :                             StartOfSectionNode()->GetIndex() < nNd &&
     495           6 :                             nNd < rNodes.GetEndOfRedlines().GetIndex() );
     496             : 
     497           6 :                     if( bNewFrms )
     498             :                         // delete all frames
     499           6 :                         pTblNd->DelFrms();
     500           6 :                     if( &rNodes == this ) // move into self?
     501             :                     {
     502             :                         // move all Start/End/ContentNodes
     503             :                         // ContentNodes: delete also the frames!
     504           0 :                         pTblNd->pStartOfSection = aIdx.GetNode().pStartOfSection;
     505           0 :                         for( sal_uLong n = 0; n < nInsPos; ++n )
     506             :                         {
     507           0 :                             SwNodeIndex aMvIdx( aRg.aEnd, 1 );
     508           0 :                             SwCntntNode* pCNd = 0;
     509           0 :                             SwNode* pTmpNd = &aMvIdx.GetNode();
     510           0 :                             if( pTmpNd->IsCntntNode() )
     511             :                             {
     512           0 :                                 pCNd = (SwCntntNode*)pTmpNd;
     513           0 :                                 if( pTmpNd->IsTxtNode() )
     514           0 :                                     ((SwTxtNode*)pTmpNd)->RemoveFromList();
     515             : 
     516             :                                 // remove outline index from old nodes array
     517           0 :                                 if (pCNd->IsTxtNode() &&
     518           0 :                                     static_cast<SwTxtNode*>(pCNd)->IsOutline())
     519             :                                 {
     520           0 :                                     pOutlineNds->erase( pCNd );
     521             :                                 }
     522             :                                 else
     523           0 :                                     pCNd = 0;
     524             :                             }
     525             : 
     526           0 :                             BigPtrArray::Move( aMvIdx.GetIndex(), aIdx.GetIndex() );
     527             : 
     528           0 :                             if( bInsOutlineIdx && pCNd )
     529           0 :                                 pOutlineNds->insert( pCNd );
     530           0 :                             if( pTmpNd->IsTxtNode() )
     531           0 :                                 ((SwTxtNode*)pTmpNd)->AddToList();
     532           0 :                         }
     533             :                     }
     534             :                     else
     535             :                     {
     536             :                         // get StartNode
     537             :                         // Even aIdx points to a startnode, we need the startnode
     538             :                         // of the environment of aIdx (#i80941)
     539           6 :                         SwStartNode* pSttNode = aIdx.GetNode().pStartOfSection;
     540             : 
     541             :                         // get all boxes with content because their indices
     542             :                         // pointing to the StartNodes need to be reset
     543             :                         // (copying the array and deleting all found ones eases
     544             :                         // searching)
     545           6 :                         SwNodeIndex aMvIdx( aRg.aEnd, 1 );
     546         288 :                         for( sal_uLong n = 0; n < nInsPos; ++n )
     547             :                         {
     548         282 :                             SwNode* pNd = &aMvIdx.GetNode();
     549             : 
     550         372 :                             const bool bOutlNd = pNd->IsTxtNode() &&
     551         372 :                                 static_cast<SwTxtNode*>(pNd)->IsOutline();
     552             :                             // delete outline indices from old node array
     553         282 :                             if( bOutlNd )
     554           0 :                                 pOutlineNds->erase( pNd );
     555             : 
     556         282 :                             RemoveNode( aMvIdx.GetIndex(), 1, sal_False );
     557         282 :                             pNd->pStartOfSection = pSttNode;
     558         282 :                             rNodes.InsertNode( pNd, aIdx );
     559             : 
     560             :                             // set correct indices in Start/EndNodes
     561         282 :                             if( bInsOutlineIdx && bOutlNd )
     562             :                                 // and put them into the new node array
     563           0 :                                 rNodes.pOutlineNds->insert( pNd );
     564         282 :                             else if( pNd->IsStartNode() )
     565          96 :                                 pSttNode = (SwStartNode*)pNd;
     566         186 :                             else if( pNd->IsEndNode() )
     567             :                             {
     568          96 :                                 pSttNode->pEndOfSection = (SwEndNode*)pNd;
     569          96 :                                 if( pSttNode->IsSectionNode() )
     570           0 :                                     ((SwSectionNode*)pSttNode)->NodesArrChgd();
     571          96 :                                 pSttNode = pSttNode->pStartOfSection;
     572             :                             }
     573             :                         }
     574             : 
     575           6 :                         if( pTblNd->GetTable().IsA( TYPE( SwDDETable ) ))
     576             :                         {
     577             :                             SwDDEFieldType* pTyp = ((SwDDETable&)pTblNd->
     578           0 :                                                 GetTable()).GetDDEFldType();
     579           0 :                             if( pTyp )
     580             :                             {
     581           0 :                                 if( rNodes.IsDocNodes() )
     582           0 :                                     pTyp->IncRefCnt();
     583             :                                 else
     584           0 :                                     pTyp->DecRefCnt();
     585             :                             }
     586             :                         }
     587             : 
     588          12 :                         if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(
     589           6 :                                     rNodes))
     590             :                         {
     591           6 :                             SwFrmFmt* pTblFmt = pTblNd->GetTable().GetFrmFmt();
     592             :                             SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT,
     593           6 :                                                         pTblFmt );
     594           6 :                             pTblFmt->ModifyNotification( &aMsgHint, &aMsgHint );
     595           6 :                         }
     596             :                     }
     597           6 :                     if( bNewFrms )
     598             :                     {
     599           6 :                         SwNodeIndex aTmp( aIdx );
     600           6 :                         pTblNd->MakeFrms( &aTmp );
     601             :                     }
     602           6 :                     aIdx -= nInsPos;
     603           6 :                     nInsPos = 0;
     604             :                 }
     605          12 :                 else if( pSttNd->GetIndex() < aRg.aStart.GetIndex() )
     606             :                 {
     607             :                     // SectionNode: not the whole section will be moved, thus,
     608             :                     //              move only the ContentNodes
     609             :                     // StartNode:   create a new section at the given position
     610             :                     do {        // middle check loop
     611           8 :                         if( !pSttNd->IsSectionNode() )
     612             :                         {
     613             :                             // create StartNode and EndNode at InsertPos
     614             :                             SwStartNode* pTmp = new SwStartNode( aIdx,
     615             :                                                     ND_STARTNODE,
     616           0 : /*?? NodeType ??*/                                  SwNormalStartNode );
     617             : 
     618           0 :                             nLevel++; // put the index to StartNode on the stack
     619           0 :                             aSttNdStack.insert( aSttNdStack.begin() + nLevel, pTmp );
     620             : 
     621             :                             // create EndNode
     622           0 :                             new SwEndNode( aIdx, *pTmp );
     623             :                         }
     624          16 :                         else if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(
     625           8 :                                     rNodes))
     626             :                         {
     627             :                             // use placeholder in UndoNodes array
     628           8 :                             new SwDummySectionNode( aIdx );
     629             :                         }
     630             :                         else
     631             :                         {
     632             :                             // JP 18.5.2001 (Bug 70454) creating new section?
     633           0 :                             aRg.aEnd--;
     634           0 :                             break;
     635             : 
     636             :                         }
     637             : 
     638           8 :                         aRg.aEnd--;
     639           8 :                         aIdx--;
     640             :                     } while( false );
     641             :                 }
     642             :                 else
     643             :                 {
     644             :                     // move StartNode and EndNode in total
     645             : 
     646             :                     // if Start is exactly the Start of the area,
     647             :                     // then the Node needs to be re-visited
     648           4 :                     if( &aRg.aStart.GetNode() == pSttNd )
     649           0 :                         --aRg.aStart;
     650             : 
     651           4 :                     SwSectionNode* pSctNd = pSttNd->GetSectionNode();
     652           4 :                     if( bNewFrms && pSctNd )
     653           2 :                         pSctNd->DelFrms();
     654             : 
     655           4 :                     RemoveNode( aRg.aEnd.GetIndex(), 1, sal_False ); // EndNode loeschen
     656           4 :                     sal_uLong nSttPos = pSttNd->GetIndex();
     657             : 
     658             :                     // this StartNode will be removed later
     659           4 :                     SwStartNode* pTmpSttNd = new SwStartNode( *this, nSttPos+1 );
     660           4 :                     pTmpSttNd->pStartOfSection = pSttNd->pStartOfSection;
     661             : 
     662           4 :                     RemoveNode( nSttPos, 1, sal_False ); // SttNode loeschen
     663             : 
     664           4 :                     pSttNd->pStartOfSection = aIdx.GetNode().pStartOfSection;
     665           4 :                     rNodes.InsertNode( pSttNd, aIdx  );
     666           4 :                     rNodes.InsertNode( pAktNode, aIdx );
     667           4 :                     aIdx--;
     668           4 :                     pSttNd->pEndOfSection = (SwEndNode*)pAktNode;
     669             : 
     670           4 :                     aRg.aEnd--;
     671             : 
     672           4 :                     nLevel++; // put the index pointing to the StartNode onto the stack
     673           4 :                     aSttNdStack.insert( aSttNdStack.begin() + nLevel, pSttNd );
     674             : 
     675             :                     // reset remaining indices if SectionNode
     676           4 :                     if( pSctNd )
     677             :                     {
     678           4 :                         pSctNd->NodesArrChgd();
     679           4 :                         ++nSectNdCnt;
     680           4 :                         bNewFrms = sal_False;
     681             :                     }
     682             :                 }
     683             :             }
     684          18 :             break;
     685             : 
     686             :         case ND_SECTIONNODE:
     687           0 :             if( !nLevel &&
     688           0 :                 GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(rNodes))
     689             :             {
     690             :                 // here, a SectionDummyNode needs to be inserted at the current position
     691           0 :                 if( nInsPos ) // move everything until here
     692             :                 {
     693             :                     // delete and copy. CAUTION: all indices after
     694             :                     // "aRg.aEnd+1" will be moved as well!
     695           0 :                     SwNodeIndex aSwIndex( aRg.aEnd, 1 );
     696           0 :                     ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
     697           0 :                     aIdx -= nInsPos;
     698           0 :                     nInsPos = 0;
     699             :                 }
     700           0 :                 new SwDummySectionNode( aIdx );
     701           0 :                 aRg.aEnd--;
     702           0 :                 aIdx--;
     703           0 :                 break;
     704             :             }
     705             :             // no break !!
     706             :         case ND_TABLENODE:
     707             :         case ND_STARTNODE:
     708             :             {
     709             :                 // empty section -> nothing to do
     710             :                 //  and only if it's a top level section
     711           4 :                 if( !nInsPos && !nLevel )
     712             :                 {
     713           0 :                     aRg.aEnd--;
     714           0 :                     break;
     715             :                 }
     716             : 
     717           4 :                 if( !nLevel ) // level is decreasing
     718             :                 {
     719             :                     // create decrease
     720           0 :                     SwNodeIndex aTmpSIdx( aOrigInsPos.aStart, 1 );
     721             :                     SwStartNode* pTmpStt = new SwStartNode( aTmpSIdx,
     722             :                                 ND_STARTNODE,
     723           0 :                                 ((SwStartNode*)pAktNode)->GetStartNodeType() );
     724             : 
     725           0 :                     aTmpSIdx--;
     726             : 
     727           0 :                     SwNodeIndex aTmpEIdx( aOrigInsPos.aEnd );
     728           0 :                     new SwEndNode( aTmpEIdx, *pTmpStt );
     729           0 :                     aTmpEIdx--;
     730           0 :                     ++aTmpSIdx;
     731             : 
     732             :                     // set correct StartOfSection
     733           0 :                     aRg.aEnd++;
     734             :                     {
     735           0 :                         SwNodeIndex aCntIdx( aRg.aEnd );
     736           0 :                         for( sal_uLong n = 0; n < nInsPos; n++, aCntIdx++)
     737           0 :                             aCntIdx.GetNode().pStartOfSection = pTmpStt;
     738             :                     }
     739             : 
     740             :                     // also set correct StartNode for all decreased nodes
     741           0 :                     while( aTmpSIdx < aTmpEIdx )
     742           0 :                         if( 0 != (( pAktNode = &aTmpEIdx.GetNode())->GetEndNode()) )
     743           0 :                             aTmpEIdx = pAktNode->StartOfSectionIndex();
     744             :                         else
     745             :                         {
     746           0 :                             pAktNode->pStartOfSection = pTmpStt;
     747           0 :                             aTmpEIdx--;
     748             :                         }
     749             : 
     750           0 :                     aIdx--;     // after the inserted StartNode
     751           0 :                     aRg.aEnd--; // before StartNode
     752             :                     // copy array. CAUTION: all indices after
     753             :                     // "aRg.aEnd+1" will be moved as well!
     754           0 :                     SwNodeIndex aSwIndex( aRg.aEnd, 1 );
     755           0 :                     ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
     756           0 :                     aIdx -= nInsPos+1;
     757           0 :                     nInsPos = 0;
     758             :                 }
     759             :                 else // all nodes between StartNode and EndNode were moved
     760             :                 {
     761             :                     OSL_ENSURE( pAktNode == aSttNdStack[nLevel] ||
     762             :                             ( pAktNode->IsStartNode() &&
     763             :                                 aSttNdStack[nLevel]->IsSectionNode()),
     764             :                              "wrong StartNode" );
     765             : 
     766           4 :                     SwNodeIndex aSwIndex( aRg.aEnd, 1 );
     767           4 :                     ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
     768           4 :                     aIdx -= nInsPos+1; // before inserted StartNode
     769           4 :                     nInsPos = 0;
     770             : 
     771             :                     // remove pointer from node array
     772           4 :                     RemoveNode( aRg.aEnd.GetIndex(), 1, sal_True );
     773           4 :                     aRg.aEnd--;
     774             : 
     775           4 :                     SwSectionNode* pSectNd = aSttNdStack[ nLevel ]->GetSectionNode();
     776           4 :                     if( pSectNd && !--nSectNdCnt )
     777             :                     {
     778           2 :                         SwNodeIndex aTmp( *pSectNd );
     779           2 :                         pSectNd->MakeFrms( &aTmp );
     780           2 :                         bNewFrms = bSaveNewFrms;
     781             :                     }
     782           4 :                     aSttNdStack.erase( aSttNdStack.begin() + nLevel ); // remove from stack
     783           4 :                     nLevel--;
     784             :                 }
     785             : 
     786             :                 // delete all resulting empty start/end node pairs
     787           4 :                 SwNode* pTmpNode = (*this)[ aRg.aEnd.GetIndex()+1 ]->GetEndNode();
     788           4 :                 if( pTmpNode && ND_STARTNODE == (pAktNode = &aRg.aEnd.GetNode())
     789           4 :                     ->GetNodeType() && pAktNode->StartOfSectionIndex() &&
     790           0 :                     pTmpNode->StartOfSectionNode() == pAktNode )
     791             :                 {
     792           0 :                     DelNodes( aRg.aEnd, 2 );
     793           0 :                     aRg.aEnd--;
     794             :                 }
     795             :             }
     796           4 :             break;
     797             : 
     798             :         case ND_TEXTNODE:
     799             :             //Add special function to text node.
     800             :             {
     801         195 :                 if( bNewFrms && pAktNode->GetCntntNode() )
     802         173 :                     ((SwCntntNode*)pAktNode)->DelFrms( sal_False );
     803         195 :                 pAktNode->pStartOfSection = aSttNdStack[ nLevel ];
     804         195 :                 nInsPos++;
     805         195 :                 aRg.aEnd--;
     806             :             }
     807         195 :             break;
     808             :         case ND_GRFNODE:
     809             :         case ND_OLENODE:
     810             :             {
     811           4 :                 if( bNewFrms && pAktNode->GetCntntNode() )
     812           0 :                     ((SwCntntNode*)pAktNode)->DelFrms();
     813             : 
     814           4 :                 pAktNode->pStartOfSection = aSttNdStack[ nLevel ];
     815           4 :                 nInsPos++;
     816           4 :                 aRg.aEnd--;
     817             :             }
     818           4 :             break;
     819             : 
     820             :         case ND_SECTIONDUMMY:
     821           0 :             if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(*this))
     822             :             {
     823           0 :                 if( &rNodes == this ) // inside UndoNodesArray
     824             :                 {
     825             :                     // move everything
     826           0 :                     pAktNode->pStartOfSection = aSttNdStack[ nLevel ];
     827           0 :                     nInsPos++;
     828             :                 }
     829             :                 else // move into "normal" node array
     830             :                 {
     831             :                     // than a SectionNode (start/end) is needed at the current
     832             :                     // InsPos; if so skip it, otherwise ignore current node
     833           0 :                     if( nInsPos ) // move everything until here
     834             :                     {
     835             :                         // delete and copy. CAUTION: all indices after
     836             :                         // "aRg.aEnd+1" will be moved as well!
     837           0 :                         SwNodeIndex aSwIndex( aRg.aEnd, 1 );
     838           0 :                         ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
     839           0 :                         aIdx -= nInsPos;
     840           0 :                         nInsPos = 0;
     841             :                     }
     842           0 :                     SwNode* pTmpNd = &aIdx.GetNode();
     843           0 :                     if( pTmpNd->IsSectionNode() ||
     844           0 :                         pTmpNd->StartOfSectionNode()->IsSectionNode() )
     845           0 :                         aIdx--; // skip
     846             :                 }
     847             :             }
     848             :             else {
     849             :                 OSL_FAIL( "How can this node be in the node array?" );
     850             :             }
     851           0 :             aRg.aEnd--;
     852           0 :             break;
     853             : 
     854             :         default:
     855             :             OSL_FAIL( "Unknown node type" );
     856           0 :             break;
     857             :         }
     858             : 
     859         200 :     if( nInsPos ) // copy remaining rest
     860             :     {
     861             :         // rest should be ok
     862         184 :         SwNodeIndex aSwIndex( aRg.aEnd, 1 );
     863         184 :         ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
     864             :     }
     865         200 :     aRg.aEnd++; // again, exclusive end
     866             : 
     867             :     // delete all resulting empty start/end node pairs
     868         447 :     if( ( pAktNode = &aRg.aStart.GetNode())->GetStartNode() &&
     869         440 :         pAktNode->StartOfSectionIndex() &&
     870          40 :         aRg.aEnd.GetNode().GetEndNode() )
     871          38 :             DelNodes( aRg.aStart, 2 );
     872             : 
     873             :     // initialize numbering update
     874         200 :     aOrigInsPos.aStart++;
     875             :     // Moved in same node array? Then call update top down!
     876         262 :     if( this == &rNodes &&
     877          62 :         aRg.aEnd.GetIndex() >= aOrigInsPos.aStart.GetIndex() )
     878             :     {
     879          36 :         UpdtOutlineIdx( aOrigInsPos.aStart.GetNode() );
     880          36 :         UpdtOutlineIdx( aRg.aEnd.GetNode() );
     881             :     }
     882             :     else
     883             :     {
     884         164 :         UpdtOutlineIdx( aRg.aEnd.GetNode() );
     885         164 :         rNodes.UpdtOutlineIdx( aOrigInsPos.aStart.GetNode() );
     886             :     }
     887             : 
     888         412 :     return sal_True;
     889             : }
     890             : 
     891             : /** create a start/end section pair
     892             :  *
     893             :  * Other nodes might be in between.
     894             :  *
     895             :  * After this method call, the start node of pRange will be pointing to the
     896             :  * first node after the start section node and the end node will be the index
     897             :  * of the end section node. If this method is called multiple times with the
     898             :  * same input, multiple sections containing the previous ones will be created
     899             :  * (no content nodes between start or end node).
     900             :  *
     901             :  * @note Start and end node of the range must be on the same level but MUST
     902             :  *       NOT be on the top level.
     903             :  *
     904             :  * @param [IN,OUT] pRange the range (excl. end)
     905             :  * @param eSttNdTyp type of the start node
     906             :  */
     907        1447 : void SwNodes::SectionDown(SwNodeRange *pRange, SwStartNodeType eSttNdTyp )
     908             : {
     909        4341 :     if( pRange->aStart >= pRange->aEnd ||
     910        2894 :         pRange->aEnd >= Count() ||
     911        1447 :         !CheckNodesRange( pRange->aStart, pRange->aEnd ))
     912        1447 :         return;
     913             : 
     914             :     // If the beginning of a range is before or at a start node position, so
     915             :     // delete it, otherwise empty S/E or E/S nodes would be created.
     916             :     // For other nodes, create a new start node.
     917        1447 :     SwNode * pAktNode = &pRange->aStart.GetNode();
     918        1447 :     SwNodeIndex aTmpIdx( *pAktNode->StartOfSectionNode() );
     919             : 
     920        1447 :     if( pAktNode->GetEndNode() )
     921           0 :         DelNodes( pRange->aStart, 1 ); // prevent empty section
     922             :     else
     923             :     {
     924             :         // insert a new StartNode
     925        1447 :         SwNode* pSttNd = new SwStartNode( pRange->aStart, ND_STARTNODE, eSttNdTyp );
     926        1447 :         pRange->aStart = *pSttNd;
     927        1447 :         aTmpIdx = pRange->aStart;
     928             :     }
     929             : 
     930             :     // If the end of a range is before or at a StartNode, so delete it,
     931             :     // otherwise empty S/E or E/S nodes would be created.
     932             :     // For other nodes, insert a new end node.
     933        1447 :     pRange->aEnd--;
     934        1447 :     if( pRange->aEnd.GetNode().GetStartNode() )
     935           0 :         DelNodes( pRange->aEnd, 1 );
     936             :     else
     937             :     {
     938        1447 :         pRange->aEnd++;
     939             :         // insert a new EndNode
     940        1447 :         new SwEndNode( pRange->aEnd, *pRange->aStart.GetNode().GetStartNode() );
     941             :     }
     942        1447 :     pRange->aEnd--;
     943             : 
     944        1447 :     SectionUpDown( aTmpIdx, pRange->aEnd );
     945             : }
     946             : 
     947             : /** increase level of the given range
     948             :  *
     949             :  * The range contained in pRange will be lifted to the next higher level.
     950             :  * This is done by adding a end node at pRange.start and a start node at
     951             :  * pRange.end. Furthermore all indices for this range will be updated.
     952             :  *
     953             :  * After this method call, the start node of pRange will be pointing to the
     954             :  * first node inside the lifted range and the end node will be pointing to the
     955             :  * last position inside the lifted range.
     956             :  *
     957             :  * @param [IN,OUT] pRange the range of nodes where the level should be increased
     958             :  */
     959           3 : void SwNodes::SectionUp(SwNodeRange *pRange)
     960             : {
     961           9 :     if( pRange->aStart >= pRange->aEnd ||
     962           6 :         pRange->aEnd >= Count() ||
     963           9 :         !CheckNodesRange( pRange->aStart, pRange->aEnd ) ||
     964           3 :         !( HighestLevel( *this, *pRange ) > 1 ))
     965           3 :         return;
     966             : 
     967             :     // If the beginning of a range is before or at a start node position, so
     968             :     // delete it, otherwise empty S/E or E/S nodes would be created.
     969             :     // For other nodes, create a new start node.
     970           3 :     SwNode * pAktNode = &pRange->aStart.GetNode();
     971           3 :     SwNodeIndex aIdx( *pAktNode->StartOfSectionNode() );
     972           3 :     if( pAktNode->IsStartNode() )       // selbst StartNode
     973             :     {
     974           3 :         SwEndNode* pEndNd = pRange->aEnd.GetNode().GetEndNode();
     975           3 :         if( pAktNode == pEndNd->pStartOfSection )
     976             :         {
     977             :             // there was a pairwise reset, adjust only those in the range
     978           3 :             SwStartNode* pTmpSttNd = pAktNode->pStartOfSection;
     979           3 :             RemoveNode( pRange->aStart.GetIndex(), 1, sal_True );
     980           3 :             RemoveNode( pRange->aEnd.GetIndex(), 1, sal_True );
     981             : 
     982           3 :             SwNodeIndex aTmpIdx( pRange->aStart );
     983          11 :             while( aTmpIdx < pRange->aEnd )
     984             :             {
     985           5 :                 pAktNode = &aTmpIdx.GetNode();
     986           5 :                 pAktNode->pStartOfSection = pTmpSttNd;
     987           5 :                 if( pAktNode->IsStartNode() )
     988           1 :                     aTmpIdx = pAktNode->EndOfSectionIndex() + 1;
     989             :                 else
     990           4 :                     ++aTmpIdx;
     991             :             }
     992           3 :             return ;
     993             :         }
     994           0 :         DelNodes( pRange->aStart, 1 );
     995             :     }
     996           0 :     else if( aIdx == pRange->aStart.GetIndex()-1 ) // before StartNode
     997           0 :         DelNodes( aIdx, 1 );
     998             :     else
     999           0 :         new SwEndNode( pRange->aStart, *aIdx.GetNode().GetStartNode() );
    1000             : 
    1001             :     // If the end of a range is before or at a StartNode, so delete it,
    1002             :     // otherwise empty S/E or E/S nodes would be created.
    1003             :     // For other nodes, insert a new end node.
    1004           0 :     SwNodeIndex aTmpIdx( pRange->aEnd );
    1005           0 :     if( pRange->aEnd.GetNode().IsEndNode() )
    1006           0 :         DelNodes( pRange->aEnd, 1 );
    1007             :     else
    1008             :     {
    1009           0 :         pAktNode = new SwStartNode( pRange->aEnd );
    1010             : /*?? which NodeType ??*/
    1011           0 :         aTmpIdx = *pRange->aEnd.GetNode().EndOfSectionNode();
    1012           0 :         pRange->aEnd--;
    1013             :     }
    1014             : 
    1015           0 :     SectionUpDown( aIdx, aTmpIdx );
    1016             : }
    1017             : 
    1018             : /** correct indices after movement
    1019             :  *
    1020             :  * Update all indices after movement so that the levels are consistent again.
    1021             :  *
    1022             :  * @param aStart index of the start node
    1023             :  * @param aEnd index of the end point
    1024             :  *
    1025             :  * @see SwNodes::SectionUp
    1026             :  * @see SwNodes::SectionDown
    1027             :  */
    1028        1447 : void SwNodes::SectionUpDown( const SwNodeIndex & aStart, const SwNodeIndex & aEnd )
    1029             : {
    1030             :     SwNode * pAktNode;
    1031        1447 :     SwNodeIndex aTmpIdx( aStart, +1 );
    1032             :     // array forms a stack, holding all StartOfSelections
    1033        2894 :     SwSttNdPtrs aSttNdStack;
    1034        1447 :     SwStartNode* pTmp = aStart.GetNode().GetStartNode();
    1035        1447 :     aSttNdStack.push_back( pTmp );
    1036             : 
    1037             :     // loop until the first start node that needs to be change was found
    1038             :     // (the indices are updated from the end node backwards to the start)
    1039        1524 :     for( ;; ++aTmpIdx )
    1040             :     {
    1041        2971 :         pAktNode = &aTmpIdx.GetNode();
    1042        2971 :         pAktNode->pStartOfSection = aSttNdStack[ aSttNdStack.size()-1 ];
    1043             : 
    1044        2971 :         if( pAktNode->GetStartNode() )
    1045             :         {
    1046           2 :             pTmp = (SwStartNode*)pAktNode;
    1047           2 :             aSttNdStack.push_back( pTmp );
    1048             :         }
    1049        2969 :         else if( pAktNode->GetEndNode() )
    1050             :         {
    1051        1449 :             SwStartNode* pSttNd = aSttNdStack[ aSttNdStack.size() - 1 ];
    1052        1449 :             pSttNd->pEndOfSection = (SwEndNode*)pAktNode;
    1053        1449 :             aSttNdStack.pop_back();
    1054        1449 :             if( !aSttNdStack.empty() )
    1055           2 :                 continue; // still enough EndNodes on the stack
    1056             : 
    1057        1447 :             else if( aTmpIdx < aEnd ) // too many StartNodes
    1058             :                 // if the end is not reached, yet, get the start of the section above
    1059             :             {
    1060           0 :                 aSttNdStack.insert( aSttNdStack.begin(), pSttNd->pStartOfSection );
    1061             :             }
    1062             :             else // finished, as soon as out of the range
    1063        1447 :                 break;
    1064             :         }
    1065        2971 :     }
    1066        1447 : }
    1067             : 
    1068             : /** delete nodes
    1069             :  *
    1070             :  * This is a specific implementation of a delete function for a variable array.
    1071             :  * It is necessary as there might be inconsistencies after deleting start or
    1072             :  * end nodes. This method can clean those up.
    1073             :  *
    1074             :  * @param rIndex position to delete at (unchanged afterwards)
    1075             :  * @param nNodes number of nodes to delete (default: 1)
    1076             :  */
    1077        4101 : void SwNodes::Delete(const SwNodeIndex &rIndex, sal_uLong nNodes)
    1078             : {
    1079        4101 :     sal_uInt16 nLevel = 0; // level counter
    1080             :     SwNode * pAktNode;
    1081             : 
    1082        4101 :     sal_uLong nCnt = Count() - rIndex.GetIndex() - 1;
    1083        4101 :     if( nCnt > nNodes ) nCnt = nNodes;
    1084             : 
    1085        4101 :     if( nCnt == 0 ) // no count -> return
    1086           0 :         return;
    1087             : 
    1088        4101 :     SwNodeRange aRg( rIndex, 0, rIndex, nCnt-1 );
    1089             :     // check if [rIndex..rIndex + nCnt] is larger than the range
    1090        8221 :     if( ( !aRg.aStart.GetNode().StartOfSectionIndex() &&
    1091        8202 :             !aRg.aStart.GetIndex() ) ||
    1092        4101 :             ! CheckNodesRange( aRg.aStart, aRg.aEnd ) )
    1093           0 :         return;
    1094             : 
    1095             :     // if aEnd is not on a ContentNode, search the previous one
    1096       12558 :     while( ( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() ||
    1097        4304 :              ( pAktNode->GetEndNode() &&
    1098         118 :                 !pAktNode->pStartOfSection->IsTableNode() ))
    1099          85 :         aRg.aEnd--;
    1100             : 
    1101        4101 :     nCnt = 0;
    1102             : //TODO: check/improve comment
    1103             :     // increase start so that we are able to use "<" (using "<=" might cause
    1104             :     // problems if aEnd == aStart and aEnd is deleted, so aEnd <= aStart)
    1105        4101 :     aRg.aStart--;
    1106             : 
    1107        4101 :     sal_Bool bSaveInNodesDel = bInNodesDel;
    1108        4101 :     bInNodesDel = sal_True;
    1109        4101 :     bool bUpdateOutline = false;
    1110             : 
    1111             :     // loop until everything is deleted
    1112       12249 :     while( aRg.aStart < aRg.aEnd )
    1113             :     {
    1114        4047 :         pAktNode = &aRg.aEnd.GetNode();
    1115             : 
    1116        4047 :         if( pAktNode->GetEndNode() )
    1117             :         {
    1118             :             // delete the whole section?
    1119          42 :             if( pAktNode->StartOfSectionIndex() > aRg.aStart.GetIndex() )
    1120             :             {
    1121          42 :                 SwTableNode* pTblNd = pAktNode->pStartOfSection->GetTableNode();
    1122          42 :                 if( pTblNd )
    1123          38 :                     pTblNd->DelFrms();
    1124             : 
    1125          42 :                 SwNode *pNd, *pChkNd = pAktNode->pStartOfSection;
    1126             :                 sal_uInt16 nIdxPos;
    1127        1182 :                 do {
    1128        1182 :                     pNd = &aRg.aEnd.GetNode();
    1129             : 
    1130        1182 :                     if( pNd->IsTxtNode() )
    1131             :                     {
    1132         382 :                         SwTxtNode *const pTxtNode(static_cast<SwTxtNode*>(pNd));
    1133         389 :                         if (pTxtNode->IsOutline() &&
    1134           7 :                                 pOutlineNds->Seek_Entry( pNd, &nIdxPos ))
    1135             :                         {
    1136             :                             // remove outline indices
    1137           7 :                             pOutlineNds->erase(nIdxPos);
    1138           7 :                             bUpdateOutline = true;
    1139             :                         }
    1140         382 :                         pTxtNode->InvalidateNumRule();
    1141             :                     }
    1142        1200 :                     else if( pNd->IsEndNode() &&
    1143         400 :                             pNd->pStartOfSection->IsTableNode() )
    1144          39 :                         ((SwTableNode*)pNd->pStartOfSection)->DelFrms();
    1145             : 
    1146        1182 :                     aRg.aEnd--;
    1147        1182 :                     nCnt++;
    1148             : 
    1149        1182 :                 } while( pNd != pChkNd );
    1150             :             }
    1151             :             else
    1152             :             {
    1153           0 :                 RemoveNode( aRg.aEnd.GetIndex()+1, nCnt, sal_True ); // delete
    1154           0 :                 nCnt = 0;
    1155           0 :                 aRg.aEnd--; // before the EndNode
    1156           0 :                 nLevel++;
    1157             :             }
    1158             :         }
    1159        4005 :         else if( pAktNode->GetStartNode() ) // found StartNode
    1160             :         {
    1161           3 :             if( nLevel == 0 ) // decrease one level
    1162             :             {
    1163           3 :                 if( nCnt )
    1164             :                 {
    1165             :                     // now delete array
    1166           3 :                     aRg.aEnd++;
    1167           3 :                     RemoveNode( aRg.aEnd.GetIndex(), nCnt, sal_True );
    1168           3 :                     nCnt = 0;
    1169             :                 }
    1170             :             }
    1171             :             else // remove all nodes between start and end node (incl. both)
    1172             :             {
    1173           0 :                 RemoveNode( aRg.aEnd.GetIndex(), nCnt + 2, sal_True ); // delete array
    1174           0 :                 nCnt = 0;
    1175           0 :                 nLevel--;
    1176             :             }
    1177             : 
    1178             :             // after deletion, aEnd might point to a EndNode...
    1179             :             // delete all empty start/end node pairs
    1180           3 :             SwNode* pTmpNode = aRg.aEnd.GetNode().GetEndNode();
    1181           3 :             aRg.aEnd--;
    1182          19 :             while(  pTmpNode &&
    1183          14 :                     ( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() &&
    1184           3 :                     pAktNode->StartOfSectionIndex() )
    1185             :             {
    1186             :                 // remove end and start node
    1187           3 :                 DelNodes( aRg.aEnd, 2 );
    1188           3 :                 pTmpNode = aRg.aEnd.GetNode().GetEndNode();
    1189           3 :                 aRg.aEnd--;
    1190             :             }
    1191             :         }
    1192             :         else // "normal" node, so insert into TmpArray
    1193             :         {
    1194        4002 :             SwTxtNode* pTxtNd = pAktNode->GetTxtNode();
    1195        4002 :             if( pTxtNd )
    1196             :             {
    1197        3992 :                 if( pTxtNd->IsOutline())
    1198             :                 {
    1199             :                     // delete outline indices
    1200           6 :                     pOutlineNds->erase( pTxtNd );
    1201           6 :                     bUpdateOutline = true;
    1202             :                 }
    1203        3992 :                 pTxtNd->InvalidateNumRule();
    1204             :             }
    1205          10 :             else if( pAktNode->IsCntntNode() )
    1206           2 :                 ((SwCntntNode*)pAktNode)->InvalidateNumRule();
    1207             : 
    1208        4002 :             aRg.aEnd--;
    1209        4002 :             nCnt++;
    1210             :         }
    1211             :     }
    1212             : 
    1213        4101 :     aRg.aEnd++;
    1214        4101 :     if( nCnt != 0 )
    1215        4016 :         RemoveNode( aRg.aEnd.GetIndex(), nCnt, sal_True ); // delete the rest
    1216             : 
    1217             :     // delete all empty start/end node pairs
    1218       19695 :     while( aRg.aEnd.GetNode().GetEndNode() &&
    1219        7803 :             ( pAktNode = &aRg.aStart.GetNode())->GetStartNode() &&
    1220           6 :             pAktNode->StartOfSectionIndex() )
    1221             :     // but none of the holy 5. (???)
    1222             :     {
    1223           0 :         DelNodes( aRg.aStart, 2 );  // delete start and end node
    1224           0 :         aRg.aStart--;
    1225             :     }
    1226             : 
    1227        4101 :     bInNodesDel = bSaveInNodesDel;
    1228             : 
    1229        4101 :     if( !bInNodesDel )
    1230             :     {
    1231             :         // update numbering
    1232        4101 :         if( bUpdateOutline || bInDelUpdOutl )
    1233             :         {
    1234           9 :             UpdtOutlineIdx( aRg.aEnd.GetNode() );
    1235           9 :             bInDelUpdOutl = sal_False;
    1236             :         }
    1237             : 
    1238             :     }
    1239             :     else
    1240             :     {
    1241           0 :         if( bUpdateOutline )
    1242           0 :             bInDelUpdOutl = sal_True;
    1243        4101 :     }
    1244             : }
    1245             : 
    1246             : /** get section level at the given position
    1247             :  *
    1248             :  * @note The first node in an array should always be a start node.
    1249             :  *       Because of this, there is a special treatment here based on the
    1250             :  *       assumption that this is true in this context as well.
    1251             :  *
    1252             :  * @param rIdx position of the node
    1253             :  * @return section level at the given position
    1254             :  */
    1255          11 : sal_uInt16 SwNodes::GetSectionLevel(const SwNodeIndex &rIdx) const {
    1256             :     // special treatment for 1st Node
    1257          11 :     if(rIdx == 0) return 1;
    1258             :     // no recursion! This calles a SwNode::GetSectionLevel (missing "s")
    1259          11 :     return rIdx.GetNode().GetSectionLevel();
    1260             : }
    1261             : 
    1262        8217 : void SwNodes::GoStartOfSection(SwNodeIndex *pIdx) const
    1263             : {
    1264             :     // after the next start node
    1265        8217 :     SwNodeIndex aTmp( *pIdx->GetNode().StartOfSectionNode(), +1 );
    1266             : 
    1267             :     // If index points to no ContentNode, than go to one.
    1268             :     // If there is no further available, do not change the index' position!
    1269       16435 :     while( !aTmp.GetNode().IsCntntNode() )
    1270             :     {   // go from this StartNode (can only be one) to its end
    1271           1 :         if( *pIdx <= aTmp )
    1272           0 :             return;     // ERROR: already after the section
    1273           1 :         aTmp = aTmp.GetNode().EndOfSectionIndex()+1;
    1274           1 :         if( *pIdx <= aTmp )
    1275           0 :             return;     // ERROR: already after the section
    1276             :     }
    1277        8217 :     (*pIdx) = aTmp;     // is on a ContentNode
    1278             : }
    1279             : 
    1280       14159 : void SwNodes::GoEndOfSection(SwNodeIndex *pIdx) const
    1281             : {
    1282       14159 :     if( !pIdx->GetNode().IsEndNode() )
    1283       14142 :         (*pIdx) = *pIdx->GetNode().EndOfSectionNode();
    1284       14159 : }
    1285             : 
    1286      184858 : SwCntntNode* SwNodes::GoNext(SwNodeIndex *pIdx) const
    1287             : {
    1288      184858 :     if( pIdx->GetIndex() >= Count() - 1 )
    1289          10 :         return 0;
    1290             : 
    1291      184848 :     SwNodeIndex aTmp(*pIdx, +1);
    1292      184848 :     SwNode* pNd = 0;
    1293      458855 :     while( aTmp < Count()-1 && 0 == ( pNd = &aTmp.GetNode())->IsCntntNode() )
    1294       89159 :         ++aTmp;
    1295             : 
    1296      184848 :     if( aTmp == Count()-1 )
    1297        3537 :         pNd = 0;
    1298             :     else
    1299      181311 :         (*pIdx) = aTmp;
    1300      184848 :     return (SwCntntNode*)pNd;
    1301             : }
    1302             : 
    1303      119141 : SwCntntNode* SwNodes::GoPrevious(SwNodeIndex *pIdx) const
    1304             : {
    1305      119141 :     if( !pIdx->GetIndex() )
    1306           0 :         return 0;
    1307             : 
    1308      119141 :     SwNodeIndex aTmp( *pIdx, -1 );
    1309      119141 :     SwNode* pNd = 0;
    1310      243253 :     while( aTmp.GetIndex() && 0 == ( pNd = &aTmp.GetNode())->IsCntntNode() )
    1311        4971 :         aTmp--;
    1312             : 
    1313      119141 :     if( !aTmp.GetIndex() )
    1314         337 :         pNd = 0;
    1315             :     else
    1316      118804 :         (*pIdx) = aTmp;
    1317      119141 :     return (SwCntntNode*)pNd;
    1318             : }
    1319             : 
    1320        8374 : inline bool TstIdx( sal_uLong nSttIdx, sal_uLong nEndIdx, sal_uLong nStt, sal_uLong nEnd )
    1321             : {
    1322        5562 :     return nStt < nSttIdx && nEnd >= nSttIdx &&
    1323       13925 :             nStt < nEndIdx && nEnd >= nEndIdx;
    1324             : }
    1325             : 
    1326             : /** Check if the given range is inside the defined ranges
    1327             :  *
    1328             :  * The defined ranges are Content, AutoText, PostIts, Inserts, and Redlines.
    1329             :  *
    1330             :  * @param rStt start index of the range
    1331             :  * @param rEnd end index of the range
    1332             :  * @return <true> if valid range
    1333             :  */
    1334        5551 : sal_Bool SwNodes::CheckNodesRange( const SwNodeIndex& rStt, const SwNodeIndex& rEnd ) const
    1335             : {
    1336        5551 :     sal_uLong nStt = rStt.GetIndex(), nEnd = rEnd.GetIndex();
    1337        5551 :     if( TstIdx( nStt, nEnd, pEndOfContent->StartOfSectionIndex(),
    1338        8317 :                 pEndOfContent->GetIndex() )) return sal_True;
    1339        2785 :     if( TstIdx( nStt, nEnd, pEndOfAutotext->StartOfSectionIndex(),
    1340        5542 :                 pEndOfAutotext->GetIndex() )) return sal_True;
    1341          28 :     if( TstIdx( nStt, nEnd, pEndOfPostIts->StartOfSectionIndex(),
    1342          47 :                 pEndOfPostIts->GetIndex() )) return sal_True;
    1343           9 :     if( TstIdx( nStt, nEnd, pEndOfInserts->StartOfSectionIndex(),
    1344          17 :                 pEndOfInserts->GetIndex() )) return sal_True;
    1345           1 :     if( TstIdx( nStt, nEnd, pEndOfRedlines->StartOfSectionIndex(),
    1346           2 :                 pEndOfRedlines->GetIndex() )) return sal_True;
    1347             : 
    1348           0 :     return sal_False;       // is somewhere in the middle, ERROR
    1349             : }
    1350             : 
    1351             : /** Delete a number of nodes
    1352             :  *
    1353             :  * @param rStart starting position in this nodes array
    1354             :  * @param nCnt number of nodes to delete
    1355             :  */
    1356        5699 : void SwNodes::DelNodes( const SwNodeIndex & rStart, sal_uLong nCnt )
    1357             : {
    1358        5699 :     sal_uLong nSttIdx = rStart.GetIndex();
    1359             : 
    1360        5699 :     if( !nSttIdx && nCnt == GetEndOfContent().GetIndex()+1 )
    1361             :     {
    1362             :         // The whole nodes array will be destroyed, you're in the Doc's DTOR!
    1363             :         // The initial start/end nodes should be only destroyed in the SwNodes' DTOR!
    1364             :         SwNode* aEndNdArr[] = { pEndOfContent,
    1365             :                                 pEndOfPostIts, pEndOfInserts,
    1366             :                                 pEndOfAutotext, pEndOfRedlines,
    1367             :                                 0
    1368        3696 :                               };
    1369             : 
    1370        3696 :         SwNode** ppEndNdArr = aEndNdArr;
    1371       25872 :         while( *ppEndNdArr )
    1372             :         {
    1373       18480 :             nSttIdx = (*ppEndNdArr)->StartOfSectionIndex() + 1;
    1374       18480 :             sal_uLong nEndIdx = (*ppEndNdArr)->GetIndex();
    1375             : 
    1376       18480 :             if( nSttIdx != nEndIdx )
    1377        4425 :                 RemoveNode( nSttIdx, nEndIdx - nSttIdx, sal_True );
    1378             : 
    1379       18480 :             ++ppEndNdArr;
    1380             :         }
    1381             :     }
    1382             :     else
    1383             :     {
    1384        2003 :         int bUpdateNum = 0;
    1385       10257 :         for( sal_uLong n = nSttIdx, nEnd = nSttIdx + nCnt; n < nEnd; ++n )
    1386             :         {
    1387        8254 :             SwNode* pNd = (*this)[ n ];
    1388             : 
    1389        8254 :             if (pNd->IsTxtNode() && static_cast<SwTxtNode*>(pNd)->IsOutline())
    1390             :             {
    1391             :                 // remove the outline indices
    1392             :                 sal_uInt16 nIdxPos;
    1393          39 :                 if( pOutlineNds->Seek_Entry( pNd, &nIdxPos ))
    1394             :                 {
    1395          39 :                     pOutlineNds->erase(nIdxPos);
    1396          39 :                     bUpdateNum = 1;
    1397             :                 }
    1398             :             }
    1399        8254 :             if( pNd->IsCntntNode() )
    1400             :             {
    1401        2912 :                 ((SwCntntNode*)pNd)->InvalidateNumRule();
    1402        2912 :                 ((SwCntntNode*)pNd)->DelFrms();
    1403             :             }
    1404             :         }
    1405        2003 :         RemoveNode( nSttIdx, nCnt, sal_True );
    1406             : 
    1407             :         // update numbering
    1408        2003 :         if( bUpdateNum )
    1409          39 :             UpdtOutlineIdx( rStart.GetNode() );
    1410             :     }
    1411        5699 : }
    1412             : 
    1413             : struct HighLevel
    1414             : {
    1415             :     sal_uInt16 nLevel, nTop;
    1416           3 :     HighLevel( sal_uInt16 nLv ) : nLevel( nLv ), nTop( nLv ) {}
    1417             : 
    1418             : };
    1419             : 
    1420          10 : static bool lcl_HighestLevel( const SwNodePtr& rpNode, void * pPara )
    1421             : {
    1422          10 :     HighLevel * pHL = (HighLevel*)pPara;
    1423          10 :     if( rpNode->GetStartNode() )
    1424           4 :         pHL->nLevel++;
    1425           6 :     else if( rpNode->GetEndNode() )
    1426           1 :         pHL->nLevel--;
    1427          10 :     if( pHL->nTop > pHL->nLevel )
    1428           0 :         pHL->nTop = pHL->nLevel;
    1429          10 :     return true;
    1430             : 
    1431             : }
    1432             : 
    1433             : /** Calculate the highest level in a range
    1434             :  *
    1435             :  * @param rNodes the nodes array
    1436             :  * @param rRange the range to inspect
    1437             :  * @return the highest level
    1438             :  */
    1439           3 : sal_uInt16 HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange )
    1440             : {
    1441           3 :     HighLevel aPara( rNodes.GetSectionLevel( rRange.aStart ));
    1442           3 :     rNodes.ForEach( rRange.aStart, rRange.aEnd, lcl_HighestLevel, &aPara );
    1443           3 :     return aPara.nTop;
    1444             : 
    1445             : }
    1446             : 
    1447             : /** move a range
    1448             :  *
    1449             :  * @param rPam the range to move
    1450             :  * @param rPos to destination position in the given nodes array
    1451             :  * @param rNodes the node array to move the range into
    1452             :  */
    1453           1 : void SwNodes::MoveRange( SwPaM & rPam, SwPosition & rPos, SwNodes& rNodes )
    1454             : {
    1455           1 :     SwPosition * const pStt = rPam.Start();
    1456           1 :     SwPosition * const pEnd = rPam.End();
    1457             : 
    1458           1 :     if( !rPam.HasMark() || *pStt >= *pEnd )
    1459           0 :         return;
    1460             : 
    1461           1 :     if( this == &rNodes && *pStt <= rPos && rPos < *pEnd )
    1462           0 :         return;
    1463             : 
    1464           1 :     SwNodeIndex aEndIdx( pEnd->nNode );
    1465           2 :     SwNodeIndex aSttIdx( pStt->nNode );
    1466           1 :     SwTxtNode *const pSrcNd = aSttIdx.GetNode().GetTxtNode();
    1467           1 :     SwTxtNode * pDestNd = rPos.nNode.GetNode().GetTxtNode();
    1468           1 :     bool bSplitDestNd = true;
    1469           1 :     bool bCopyCollFmt = pDestNd && pDestNd->GetTxt().isEmpty();
    1470             : 
    1471           1 :     if( pSrcNd )
    1472             :     {
    1473             :         // if the first node is a TextNode, than there must
    1474             :         // be also a TextNode in the NodesArray to store the content
    1475           1 :         if( !pDestNd )
    1476             :         {
    1477           0 :             pDestNd = rNodes.MakeTxtNode( rPos.nNode, pSrcNd->GetTxtColl() );
    1478           0 :             rPos.nNode--;
    1479           0 :             rPos.nContent.Assign( pDestNd, 0 );
    1480           0 :             bCopyCollFmt = true;
    1481             :         }
    1482           2 :         bSplitDestNd = pDestNd->Len() > rPos.nContent.GetIndex() ||
    1483           2 :                         pEnd->nNode.GetNode().IsTxtNode();
    1484             : 
    1485             :         // move the content into the new node
    1486           1 :         bool bOneNd = pStt->nNode == pEnd->nNode;
    1487             :         const sal_Int32 nLen =
    1488           1 :                 ( (bOneNd) ? pEnd->nContent.GetIndex() : pSrcNd->Len() )
    1489           2 :                 - pStt->nContent.GetIndex();
    1490             : 
    1491           1 :         if( !pEnd->nNode.GetNode().IsCntntNode() )
    1492             :         {
    1493           0 :             bOneNd = true;
    1494           0 :             sal_uLong nSttNdIdx = pStt->nNode.GetIndex() + 1;
    1495           0 :             const sal_uLong nEndNdIdx = pEnd->nNode.GetIndex();
    1496           0 :             for( ; nSttNdIdx < nEndNdIdx; ++nSttNdIdx )
    1497             :             {
    1498           0 :                 if( (*this)[ nSttNdIdx ]->IsCntntNode() )
    1499             :                 {
    1500           0 :                     bOneNd = false;
    1501           0 :                     break;
    1502             :                 }
    1503             :             }
    1504             :         }
    1505             : 
    1506             :         // templates must be copied/set after a split
    1507           1 :         if( !bOneNd && bSplitDestNd )
    1508             :         {
    1509           1 :             if( !rPos.nContent.GetIndex() )
    1510             :             {
    1511           1 :                 bCopyCollFmt = true;
    1512             :             }
    1513           1 :             if( rNodes.IsDocNodes() )
    1514             :             {
    1515           1 :                 SwDoc* const pInsDoc = pDestNd->GetDoc();
    1516           1 :                 ::sw::UndoGuard const ug(pInsDoc->GetIDocumentUndoRedo());
    1517           1 :                 pInsDoc->SplitNode( rPos, false );
    1518             :             }
    1519             :             else
    1520             :             {
    1521           0 :                 pDestNd->SplitCntntNode( rPos );
    1522             :             }
    1523             : 
    1524           1 :             if( rPos.nNode == aEndIdx )
    1525             :             {
    1526           0 :                 aEndIdx--;
    1527             :             }
    1528           1 :             bSplitDestNd = true;
    1529             : 
    1530           1 :             pDestNd = rNodes[ rPos.nNode.GetIndex() - 1 ]->GetTxtNode();
    1531           1 :             if( nLen )
    1532             :             {
    1533           0 :                 pSrcNd->CutText( pDestNd, SwIndex( pDestNd, pDestNd->Len()),
    1534           0 :                             pStt->nContent, nLen );
    1535           1 :             }
    1536             :         }
    1537           0 :         else if ( nLen )
    1538             :         {
    1539           0 :             pSrcNd->CutText( pDestNd, rPos.nContent, pStt->nContent, nLen );
    1540             :         }
    1541             : 
    1542           1 :         if( bCopyCollFmt )
    1543             :         {
    1544           1 :             SwDoc* const pInsDoc = pDestNd->GetDoc();
    1545           1 :             ::sw::UndoGuard const undoGuard(pInsDoc->GetIDocumentUndoRedo());
    1546           1 :             pSrcNd->CopyCollFmt( *pDestNd );
    1547           1 :             bCopyCollFmt = false;
    1548             :         }
    1549             : 
    1550           1 :         if( bOneNd )
    1551             :         {
    1552             :             // Correct the PaM, because it might have happened that the move
    1553             :             // went over the node borders (so the data might be in different nodes).
    1554             :             // Also, a selection is invalidated.
    1555           0 :             pEnd->nContent = pStt->nContent;
    1556           0 :             rPam.DeleteMark();
    1557           0 :             GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( 0,
    1558           0 :                 rNodes.IsDocNodes() ? SWFMTFLD_INSERTED : SWFMTFLD_REMOVED ) );
    1559           0 :             return;
    1560             :         }
    1561             : 
    1562           1 :         ++aSttIdx;
    1563             :     }
    1564           0 :     else if( pDestNd )
    1565             :     {
    1566           0 :         if( rPos.nContent.GetIndex() )
    1567             :         {
    1568           0 :             if( rPos.nContent.GetIndex() == pDestNd->Len() )
    1569             :             {
    1570           0 :                 rPos.nNode++;
    1571             :             }
    1572           0 :             else if( rPos.nContent.GetIndex() )
    1573             :             {
    1574             :                 // if the EndNode is split than correct the EndIdx
    1575           0 :                 const bool bCorrEnd = aEndIdx == rPos.nNode;
    1576             : 
    1577             :                 // if no text is attached to the TextNode, split it
    1578           0 :                 if( rNodes.IsDocNodes() )
    1579             :                 {
    1580           0 :                     SwDoc* const pInsDoc = pDestNd->GetDoc();
    1581           0 :                     ::sw::UndoGuard const ug(pInsDoc->GetIDocumentUndoRedo());
    1582           0 :                     pInsDoc->SplitNode( rPos, false );
    1583             :                 }
    1584             :                 else
    1585             :                 {
    1586           0 :                     pDestNd->SplitCntntNode( rPos );
    1587             :                 }
    1588             : 
    1589           0 :                 pDestNd = rPos.nNode.GetNode().GetTxtNode();
    1590             : 
    1591           0 :                 if ( bCorrEnd )
    1592             :                 {
    1593           0 :                     aEndIdx--;
    1594             :                 }
    1595             :             }
    1596             :         }
    1597             :         // at the end only an empty TextNode is left over
    1598           0 :         bSplitDestNd = true;
    1599             :     }
    1600             : 
    1601           1 :     SwTxtNode* const pEndSrcNd = aEndIdx.GetNode().GetTxtNode();
    1602           1 :     if ( pEndSrcNd )
    1603             :     {
    1604             :         {
    1605             :             // at the end of this range a new TextNode will be created
    1606           1 :             if( !bSplitDestNd )
    1607             :             {
    1608           0 :                 if( rPos.nNode < rNodes.GetEndOfContent().GetIndex() )
    1609             :                 {
    1610           0 :                     rPos.nNode++;
    1611             :                 }
    1612             : 
    1613             :                 pDestNd =
    1614           0 :                     rNodes.MakeTxtNode( rPos.nNode, pEndSrcNd->GetTxtColl() );
    1615           0 :                 rPos.nNode--;
    1616           0 :                 rPos.nContent.Assign( pDestNd, 0 );
    1617             :             }
    1618             :             else
    1619             :             {
    1620           1 :                 pDestNd = rPos.nNode.GetNode().GetTxtNode();
    1621             :             }
    1622             : 
    1623           1 :             if( pDestNd && pEnd->nContent.GetIndex() )
    1624             :             {
    1625             :                 // move the content into the new node
    1626           1 :                 SwIndex aIdx( pEndSrcNd, 0 );
    1627             :                 pEndSrcNd->CutText( pDestNd, rPos.nContent, aIdx,
    1628           1 :                                 pEnd->nContent.GetIndex());
    1629             :             }
    1630             : 
    1631           1 :             if( bCopyCollFmt )
    1632             :             {
    1633           0 :                 SwDoc* const pInsDoc = pDestNd->GetDoc();
    1634           0 :                 ::sw::UndoGuard const ug(pInsDoc->GetIDocumentUndoRedo());
    1635           0 :                 pEndSrcNd->CopyCollFmt( *pDestNd );
    1636             :             }
    1637             :         }
    1638             :     }
    1639             :     else
    1640             :     {
    1641           0 :         if ( pSrcNd && aEndIdx.GetNode().IsCntntNode() )
    1642             :         {
    1643           0 :             ++aEndIdx;
    1644             :         }
    1645           0 :         if( !bSplitDestNd )
    1646             :         {
    1647           0 :             rPos.nNode++;
    1648           0 :             rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), 0 );
    1649             :         }
    1650             :     }
    1651             : 
    1652           1 :     if( aEndIdx != aSttIdx )
    1653             :     {
    1654             :         // move the nodes into the NodesArary
    1655           0 :         const sal_uLong nSttDiff = aSttIdx.GetIndex() - pStt->nNode.GetIndex();
    1656           0 :         SwNodeRange aRg( aSttIdx, aEndIdx );
    1657           0 :         _MoveNodes( aRg, rNodes, rPos.nNode );
    1658             : 
    1659             :         // if in the same node array, all indices are now at new positions (so correct them)
    1660           0 :         if( &rNodes == this )
    1661             :         {
    1662           0 :             pStt->nNode = aRg.aEnd.GetIndex() - nSttDiff;
    1663           0 :         }
    1664             :     }
    1665             : 
    1666             :     // if the StartNode was moved to whom the the cursor pointed, so
    1667             :     // the content must be registered in the current content!
    1668           1 :     if ( &pStt->nNode.GetNode() == &GetEndOfContent() )
    1669             :     {
    1670           0 :         const bool bSuccess = GoPrevious( &pStt->nNode );
    1671             :         OSL_ENSURE( bSuccess, "Move() - no ContentNode here" );
    1672             :         (void) bSuccess;
    1673             :     }
    1674           1 :     pStt->nContent.Assign( pStt->nNode.GetNode().GetCntntNode(),
    1675           2 :                             pStt->nContent.GetIndex() );
    1676             :     // Correct the PaM, because it might have happened that the move
    1677             :     // went over the node borders (so the data might be in different nodes).
    1678             :     // Also, a selection is invalidated.
    1679           1 :     *pEnd = *pStt;
    1680           1 :     rPam.DeleteMark();
    1681           1 :     GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( 0,
    1682           3 :                 rNodes.IsDocNodes() ? SWFMTFLD_INSERTED : SWFMTFLD_REMOVED ) );
    1683             : }
    1684             : 
    1685             : ///@see SwNodes::_MoveNodes (TODO: seems to be C&P programming here)
    1686        2402 : void SwNodes::_CopyNodes( const SwNodeRange& rRange,
    1687             :             const SwNodeIndex& rIndex, sal_Bool bNewFrms, sal_Bool bTblInsDummyNode ) const
    1688             : {
    1689        2402 :     SwDoc* pDoc = rIndex.GetNode().GetDoc();
    1690             : 
    1691             :     SwNode * pAktNode;
    1692        4804 :     if( rIndex == 0 ||
    1693        2402 :         ( (pAktNode = &rIndex.GetNode())->GetStartNode() &&
    1694           0 :           !pAktNode->StartOfSectionIndex() ))
    1695           0 :         return;
    1696             : 
    1697        2402 :     SwNodeRange aRg( rRange );
    1698             : 
    1699             :     // skip "simple" StartNodes or EndNodes
    1700       11430 :     while( ND_STARTNODE == (pAktNode = & aRg.aStart.GetNode())->GetNodeType()
    1701        9028 :             || ( pAktNode->IsEndNode() &&
    1702           0 :                 !pAktNode->pStartOfSection->IsSectionNode() ) )
    1703        2112 :         aRg.aStart++;
    1704             : 
    1705             :     // if aEnd-1 points to no ContentNode, search previous one
    1706        2402 :     aRg.aEnd--;
    1707             :     // #i107142#: if aEnd is start node of a special section, do nothing.
    1708             :     // Otherwise this could lead to crash: going through all previous
    1709             :     // special section nodes and then one before the first.
    1710        2402 :     if (aRg.aEnd.GetNode().StartOfSectionIndex() != 0)
    1711             :     {
    1712        7600 :         while( ((pAktNode = & aRg.aEnd.GetNode())->GetStartNode() &&
    1713        7994 :                 !pAktNode->IsSectionNode() ) ||
    1714        2830 :                 ( pAktNode->IsEndNode() &&
    1715         231 :                 ND_STARTNODE == pAktNode->pStartOfSection->GetNodeType()) )
    1716             :         {
    1717         197 :             aRg.aEnd--;
    1718             :         }
    1719             :     }
    1720        2402 :     aRg.aEnd++;
    1721             : 
    1722             :     // if in same array, check insertion position
    1723        2402 :     if( aRg.aStart >= aRg.aEnd )
    1724           0 :         return;
    1725             : 
    1726             :     // when inserting into the source range, nothing need to be done
    1727             :     OSL_ENSURE( &aRg.aStart.GetNodes() == this,
    1728             :                 "aRg should use thisnodes array" );
    1729             :     OSL_ENSURE( &aRg.aStart.GetNodes() == &aRg.aEnd.GetNodes(),
    1730             :                "Range across different nodes arrays? You deserve punishment!");
    1731        7199 :     if( &rIndex.GetNodes() == &aRg.aStart.GetNodes() &&
    1732        4719 :         rIndex.GetIndex() >= aRg.aStart.GetIndex() &&
    1733        2317 :         rIndex.GetIndex() < aRg.aEnd.GetIndex() )
    1734           0 :             return;
    1735             : 
    1736        4804 :     SwNodeIndex aInsPos( rIndex );
    1737        4804 :     SwNodeIndex aOrigInsPos( rIndex, -1 ); // original insertion position
    1738        2402 :     sal_uInt16 nLevel = 0;                 // level counter
    1739             : 
    1740        7731 :     for( sal_uLong nNodeCnt = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex();
    1741             :             nNodeCnt > 0; --nNodeCnt )
    1742             :     {
    1743        5329 :         pAktNode = &aRg.aStart.GetNode();
    1744        5329 :         switch( pAktNode->GetNodeType() )
    1745             :         {
    1746             :         case ND_TABLENODE:
    1747             :             // Does it copy a table in(to) a footnote?
    1748         197 :             if( aInsPos < pDoc->GetNodes().GetEndOfInserts().GetIndex() &&
    1749           0 :                     pDoc->GetNodes().GetEndOfInserts().StartOfSectionIndex()
    1750           0 :                     < aInsPos.GetIndex() )
    1751             :             {
    1752             :                 sal_uLong nDistance =
    1753           0 :                     ( pAktNode->EndOfSectionIndex() -
    1754           0 :                         aRg.aStart.GetIndex() );
    1755           0 :                 if (nDistance < nNodeCnt)
    1756           0 :                     nNodeCnt -= nDistance;
    1757             :                 else
    1758           0 :                     nNodeCnt = 1;
    1759             : 
    1760             :                 // insert a DummyNode for a TableNode
    1761           0 :                 if( bTblInsDummyNode )
    1762           0 :                     new SwDummySectionNode( aInsPos );
    1763             : 
    1764             :                 // copy all of the table's nodes into the current cell
    1765           0 :                 for( aRg.aStart++; aRg.aStart.GetIndex() <
    1766           0 :                     pAktNode->EndOfSectionIndex();
    1767             :                     aRg.aStart++ )
    1768             :                 {
    1769             :                     // insert a DummyNode for the box-StartNode?
    1770           0 :                     if( bTblInsDummyNode )
    1771           0 :                         new SwDummySectionNode( aInsPos );
    1772             : 
    1773           0 :                     SwStartNode* pSttNd = aRg.aStart.GetNode().GetStartNode();
    1774             :                     _CopyNodes( SwNodeRange( *pSttNd, + 1,
    1775           0 :                                             *pSttNd->EndOfSectionNode() ),
    1776           0 :                                 aInsPos, bNewFrms, sal_False );
    1777             : 
    1778             :                     // insert a DummyNode for the box-EndNode?
    1779           0 :                     if( bTblInsDummyNode )
    1780           0 :                         new SwDummySectionNode( aInsPos );
    1781           0 :                     aRg.aStart = *pSttNd->EndOfSectionNode();
    1782             :                 }
    1783             :                 // insert a DummyNode for the table-EndNode
    1784           0 :                 if( bTblInsDummyNode )
    1785           0 :                     new SwDummySectionNode( aInsPos );
    1786           0 :                 aRg.aStart = *pAktNode->EndOfSectionNode();
    1787             :             }
    1788             :             else
    1789             :             {
    1790         197 :                 SwNodeIndex nStt( aInsPos, -1 );
    1791             :                 SwTableNode* pTblNd = ((SwTableNode*)pAktNode)->
    1792         197 :                                         MakeCopy( pDoc, aInsPos );
    1793         197 :                 sal_uLong nDistance = aInsPos.GetIndex() - nStt.GetIndex() - 2;
    1794         197 :                 if (nDistance < nNodeCnt)
    1795         197 :                     nNodeCnt -= nDistance;
    1796             :                 else
    1797           0 :                     nNodeCnt = 1;
    1798             : 
    1799         197 :                 aRg.aStart = pAktNode->EndOfSectionIndex();
    1800             : 
    1801         197 :                 if( bNewFrms && pTblNd )
    1802             :                 {
    1803         163 :                     nStt = aInsPos;
    1804         163 :                     pTblNd->MakeFrms( &nStt );
    1805         197 :                 }
    1806             :             }
    1807         197 :             break;
    1808             : 
    1809             :         case ND_SECTIONNODE:
    1810             :             // If the end of the section is outside the copy range,
    1811             :             // the section node will skipped, not copied!
    1812             :             // If someone want to change this behaviour, he has to adjust the function
    1813             :             // lcl_NonCopyCount(..) in ndcopy.cxx which relies on it.
    1814           0 :             if( pAktNode->EndOfSectionIndex() < aRg.aEnd.GetIndex() )
    1815             :             {
    1816             :                 // copy of the whole section, so create a new SectionNode
    1817           0 :                 SwNodeIndex nStt( aInsPos, -1 );
    1818             :                 SwSectionNode* pSectNd = ((SwSectionNode*)pAktNode)->
    1819           0 :                                     MakeCopy( pDoc, aInsPos );
    1820             : 
    1821           0 :                 sal_uLong nDistance = aInsPos.GetIndex() - nStt.GetIndex() - 2;
    1822           0 :                 if (nDistance < nNodeCnt)
    1823           0 :                     nNodeCnt -= nDistance;
    1824             :                 else
    1825           0 :                     nNodeCnt = 1;
    1826           0 :                 aRg.aStart = pAktNode->EndOfSectionIndex();
    1827             : 
    1828           0 :                 if( bNewFrms && pSectNd &&
    1829           0 :                     !pSectNd->GetSection().IsHidden() )
    1830           0 :                     pSectNd->MakeFrms( &nStt );
    1831             :             }
    1832           0 :             break;
    1833             : 
    1834             :         case ND_STARTNODE:
    1835             :             {
    1836             :                 SwStartNode* pTmp = new SwStartNode( aInsPos, ND_STARTNODE,
    1837         734 :                             ((SwStartNode*)pAktNode)->GetStartNodeType() );
    1838         734 :                 new SwEndNode( aInsPos, *pTmp );
    1839         734 :                 aInsPos--;
    1840         734 :                 nLevel++;
    1841             :             }
    1842         734 :             break;
    1843             : 
    1844             :         case ND_ENDNODE:
    1845         734 :             if( nLevel ) // complete section
    1846             :             {
    1847         550 :                 --nLevel;
    1848         550 :                 ++aInsPos; // EndNode already exists
    1849             :             }
    1850         184 :             else if( !pAktNode->pStartOfSection->IsSectionNode() )
    1851             :             {
    1852             :                 // create a section at the original InsertPosition
    1853         184 :                 SwNodeRange aTmpRg( aOrigInsPos, 1, aInsPos );
    1854         184 :                 pDoc->GetNodes().SectionDown( &aTmpRg,
    1855         368 :                         pAktNode->pStartOfSection->GetStartNodeType() );
    1856             :             }
    1857         734 :             break;
    1858             : 
    1859             :         case ND_TEXTNODE:
    1860             :         case ND_GRFNODE:
    1861             :         case ND_OLENODE:
    1862             :             {
    1863        3664 :                 SwCntntNode* pNew = ((SwCntntNode*)pAktNode)->MakeCopy(
    1864        3664 :                                             pDoc, aInsPos );
    1865             :                 // frames are always created as default, so delete if needed
    1866        3664 :                 if( !bNewFrms )
    1867        1632 :                     pNew->DelFrms();
    1868             :             }
    1869        3664 :             break;
    1870             : 
    1871             :         case ND_SECTIONDUMMY:
    1872           0 :             if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(*this))
    1873             :             {
    1874             :                 // than a SectionNode (start/end) is needed at the current
    1875             :                 // InsPos; if so skip it, otherwise ignore current node
    1876           0 :                 SwNode *const pTmpNd = & aInsPos.GetNode();
    1877           0 :                 if( pTmpNd->IsSectionNode() ||
    1878           0 :                     pTmpNd->StartOfSectionNode()->IsSectionNode() )
    1879           0 :                     ++aInsPos;  // skip
    1880             :             }
    1881             :             else {
    1882             :                 OSL_FAIL( "How can this node be in the node array?" );
    1883             :             }
    1884           0 :             break;
    1885             : 
    1886             :         default:
    1887             :             OSL_FAIL( "Unknown node type" );
    1888             :         }
    1889        5329 :         aRg.aStart++;
    1890        2402 :     }
    1891             : }
    1892             : 
    1893         289 : void SwNodes::_DelDummyNodes( const SwNodeRange& rRg )
    1894             : {
    1895         289 :     SwNodeIndex aIdx( rRg.aStart );
    1896        1733 :     while( aIdx.GetIndex() < rRg.aEnd.GetIndex() )
    1897             :     {
    1898        1155 :         if( ND_SECTIONDUMMY == aIdx.GetNode().GetNodeType() )
    1899           0 :             RemoveNode( aIdx.GetIndex(), 1, sal_True );
    1900             :         else
    1901        1155 :             ++aIdx;
    1902         289 :     }
    1903         289 : }
    1904             : 
    1905        2136 : SwStartNode* SwNodes::MakeEmptySection( const SwNodeIndex& rIdx,
    1906             :                                         SwStartNodeType eSttNdTyp )
    1907             : {
    1908        2136 :     SwStartNode* pSttNd = new SwStartNode( rIdx, ND_STARTNODE, eSttNdTyp );
    1909        2136 :     new SwEndNode( rIdx, *pSttNd );
    1910        2136 :     return pSttNd;
    1911             : }
    1912             : 
    1913        1521 : SwStartNode* SwNodes::MakeTextSection( const SwNodeIndex & rWhere,
    1914             :                                         SwStartNodeType eSttNdTyp,
    1915             :                                         SwTxtFmtColl *pColl,
    1916             :                                         SwAttrSet* pAutoAttr )
    1917             : {
    1918        1521 :     SwStartNode* pSttNd = new SwStartNode( rWhere, ND_STARTNODE, eSttNdTyp );
    1919        1521 :     new SwEndNode( rWhere, *pSttNd );
    1920        1521 :     MakeTxtNode( SwNodeIndex( rWhere, - 1 ), pColl, pAutoAttr );
    1921        1521 :     return pSttNd;
    1922             : }
    1923             : 
    1924             : //TODO: provide better documentation
    1925             : /** go to next section that is not protected nor hidden
    1926             :  *
    1927             :  * @note if !bSkipHidden and !bSkipProtect, use GoNext/GoPrevious
    1928             :  *
    1929             :  * @param pIdx
    1930             :  * @param bSkipHidden
    1931             :  * @param bSkipProtect
    1932             :  * @return
    1933             :  * @see SwNodes::GoNext
    1934             :  * @see SwNodes::GoPrevious
    1935             :  * @see SwNodes::GoNextSection (TODO: seems to be C&P programming here)
    1936             : */
    1937        2056 : SwCntntNode* SwNodes::GoNextSection( SwNodeIndex * pIdx,
    1938             :                             bool bSkipHidden, bool bSkipProtect ) const
    1939             : {
    1940        2056 :     bool bFirst = true;
    1941        2056 :     SwNodeIndex aTmp( *pIdx );
    1942             :     const SwNode* pNd;
    1943        6842 :     while( aTmp < Count() - 1 )
    1944             :     {
    1945        4784 :         pNd = & aTmp.GetNode();
    1946        4784 :         if (ND_SECTIONNODE == pNd->GetNodeType())
    1947             :         {
    1948          77 :             const SwSection& rSect = ((SwSectionNode*)pNd)->GetSection();
    1949          83 :             if( (bSkipHidden && rSect.IsHiddenFlag()) ||
    1950           6 :                 (bSkipProtect && rSect.IsProtectFlag()) )
    1951             :                 // than skip the section
    1952           6 :                 aTmp = *pNd->EndOfSectionNode();
    1953          77 :             bFirst = false;
    1954             :         }
    1955        4707 :         else if( bFirst )
    1956             :         {
    1957        2028 :             bFirst = false;
    1958        2028 :             if( pNd->pStartOfSection->IsSectionNode() )
    1959             :             {
    1960             :                 const SwSection& rSect = ((SwSectionNode*)pNd->
    1961          23 :                                 pStartOfSection)->GetSection();
    1962          32 :                 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
    1963           4 :                     (bSkipProtect && rSect.IsProtectFlag()) )
    1964             :                     // than skip the section
    1965           9 :                     aTmp = *pNd->EndOfSectionNode();
    1966             :             }
    1967             :         }
    1968        2679 :         else if( ND_CONTENTNODE & pNd->GetNodeType() )
    1969             :         {
    1970             :             const SwSectionNode* pSectNd;
    1971        2054 :             if( ( bSkipHidden || bSkipProtect ) &&
    1972        2121 :                 0 != (pSectNd = pNd->FindSectionNode() ) &&
    1973          67 :                 ( ( bSkipHidden && pSectNd->GetSection().IsHiddenFlag() ) ||
    1974           6 :                   ( bSkipProtect && pSectNd->GetSection().IsProtectFlag() )) )
    1975             :             {
    1976           0 :                 aTmp = *pSectNd->EndOfSectionNode();
    1977             :             }
    1978             :             else
    1979             :             {
    1980        2054 :                 (*pIdx) = aTmp;
    1981        2054 :                 return (SwCntntNode*)pNd;
    1982             :             }
    1983             :         }
    1984        2730 :         ++aTmp;
    1985        2730 :         bFirst = false;
    1986             :     }
    1987           2 :     return 0;
    1988             : }
    1989             : 
    1990             : ///@see SwNodes::GoNextSection (TODO: seems to be C&P programming here)
    1991         154 : SwCntntNode* SwNodes::GoPrevSection( SwNodeIndex * pIdx,
    1992             :                             bool bSkipHidden, bool bSkipProtect ) const
    1993             : {
    1994         154 :     bool bFirst = true;
    1995         154 :     SwNodeIndex aTmp( *pIdx );
    1996             :     const SwNode* pNd;
    1997        1032 :     while( aTmp > 0 )
    1998             :     {
    1999         797 :         pNd = & aTmp.GetNode();
    2000         797 :         if (ND_ENDNODE == pNd->GetNodeType())
    2001             :         {
    2002         370 :             if( pNd->pStartOfSection->IsSectionNode() )
    2003             :             {
    2004             :                 const SwSection& rSect = ((SwSectionNode*)pNd->
    2005          16 :                                             pStartOfSection)->GetSection();
    2006          16 :                 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
    2007           0 :                     (bSkipProtect && rSect.IsProtectFlag()) )
    2008             :                     // than skip section
    2009           0 :                     aTmp = *pNd->StartOfSectionNode();
    2010             :             }
    2011         370 :             bFirst = false;
    2012             :         }
    2013         427 :         else if( bFirst )
    2014             :         {
    2015         104 :             bFirst = false;
    2016         104 :             if( pNd->pStartOfSection->IsSectionNode() )
    2017             :             {
    2018             :                 const SwSection& rSect = ((SwSectionNode*)pNd->
    2019          11 :                                 pStartOfSection)->GetSection();
    2020          11 :                 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
    2021           0 :                     (bSkipProtect && rSect.IsProtectFlag()) )
    2022             :                     // than skip section
    2023           0 :                     aTmp = *pNd->StartOfSectionNode();
    2024             :             }
    2025             :         }
    2026         323 :         else if( ND_CONTENTNODE & pNd->GetNodeType() )
    2027             :         {
    2028             :             const SwSectionNode* pSectNd;
    2029          73 :             if( ( bSkipHidden || bSkipProtect ) &&
    2030         110 :                 0 != (pSectNd = pNd->FindSectionNode() ) &&
    2031          37 :                 ( ( bSkipHidden && pSectNd->GetSection().IsHiddenFlag() ) ||
    2032           0 :                   ( bSkipProtect && pSectNd->GetSection().IsProtectFlag() )) )
    2033             :             {
    2034           0 :                 aTmp = *pSectNd;
    2035             :             }
    2036             :             else
    2037             :             {
    2038          73 :                 (*pIdx) = aTmp;
    2039          73 :                 return (SwCntntNode*)pNd;
    2040             :             }
    2041             :         }
    2042         724 :         aTmp--;
    2043             :     }
    2044          81 :     return 0;
    2045             : }
    2046             : 
    2047             : //TODO: improve documentation
    2048             : //TODO: The inventor of the "single responsibility principle" will be crying if you ever show this code to him!
    2049             : /** find the next/previous ContentNode or a table node with frames
    2050             :  *
    2051             :  * If no pEnd is given, search is started with FrameIndex; otherwise
    2052             :  * search is started with the one before rFrmIdx and after pEnd.
    2053             :  *
    2054             :  * @param rFrmIdx node with frames to search in
    2055             :  * @param pEnd ???
    2056             :  * @return result node; 0 (!!!) if not found
    2057             :  */
    2058         447 : SwNode* SwNodes::FindPrvNxtFrmNode( SwNodeIndex& rFrmIdx,
    2059             :                                     const SwNode* pEnd ) const
    2060             : {
    2061         447 :     SwNode* pFrmNd = 0;
    2062             : 
    2063             :     // no layout -> skip
    2064         447 :     if( GetDoc()->GetCurrentViewShell() )
    2065             :     {
    2066         197 :         SwNode* pSttNd = &rFrmIdx.GetNode();
    2067             : 
    2068             :         // move of a hidden section?
    2069         197 :         SwSectionNode* pSectNd = pSttNd->IsSectionNode()
    2070          68 :                     ? pSttNd->StartOfSectionNode()->FindSectionNode()
    2071         265 :                     : pSttNd->FindSectionNode();
    2072         197 :         if( !( pSectNd && pSectNd->GetSection().CalcHiddenFlag() ) )
    2073             :         {
    2074             :             // in a table in table situation we have to assure that we don't leave the
    2075             :             // outer table cell when the inner table is looking for a PrvNxt...
    2076         197 :             SwTableNode* pTableNd = pSttNd->IsTableNode()
    2077          67 :                     ? pSttNd->StartOfSectionNode()->FindTableNode()
    2078         264 :                     : pSttNd->FindTableNode();
    2079         197 :             SwNodeIndex aIdx( rFrmIdx );
    2080             :             SwNode* pNd;
    2081         197 :             if( pEnd )
    2082             :             {
    2083         197 :                 aIdx--;
    2084         197 :                 pNd = &aIdx.GetNode();
    2085             :             }
    2086             :             else
    2087           0 :                 pNd = pSttNd;
    2088             : 
    2089         197 :             if( ( pFrmNd = pNd )->IsCntntNode() )
    2090          82 :                 rFrmIdx = aIdx;
    2091             : 
    2092             :             // search forward or backward for a content node
    2093         286 :             else if( 0 != ( pFrmNd = GoPrevSection( &aIdx, true, false )) &&
    2094         106 :                     ::CheckNodesRange( aIdx, rFrmIdx, true ) &&
    2095             :                     // Never out of the table at the start
    2096          84 :                     pFrmNd->FindTableNode() == pTableNd &&
    2097             :                     // Bug 37652: Never out of the table at the end
    2098          70 :                     (!pFrmNd->FindTableNode() || pFrmNd->FindTableBoxStartNode()
    2099         201 :                         == pSttNd->FindTableBoxStartNode() ) &&
    2100           4 :                      (!pSectNd || pSttNd->IsSectionNode() ||
    2101           0 :                       pSectNd->GetIndex() < pFrmNd->GetIndex())
    2102             :                     )
    2103             :             {
    2104          34 :                 rFrmIdx = aIdx;
    2105             :             }
    2106             :             else
    2107             :             {
    2108          81 :                 if( pEnd )
    2109          81 :                     aIdx = pEnd->GetIndex() + 1;
    2110             :                 else
    2111           0 :                     aIdx = rFrmIdx;
    2112             : 
    2113             :                 // NEVER leave the section when doing this!
    2114         164 :                 if( ( pEnd && ( pFrmNd = &aIdx.GetNode())->IsCntntNode() ) ||
    2115           4 :                     ( 0 != ( pFrmNd = GoNextSection( &aIdx, true, false )) &&
    2116           4 :                     ::CheckNodesRange( aIdx, rFrmIdx, true ) &&
    2117           4 :                     ( pFrmNd->FindTableNode() == pTableNd &&
    2118             :                         // NEVER go out of the table cell at the end
    2119           2 :                         (!pFrmNd->FindTableNode() || pFrmNd->FindTableBoxStartNode()
    2120           2 :                         == pSttNd->FindTableBoxStartNode() ) ) &&
    2121           0 :                      (!pSectNd || pSttNd->IsSectionNode() ||
    2122           0 :                       pSectNd->EndOfSectionIndex() > pFrmNd->GetIndex())
    2123             :                     ))
    2124             :                 {
    2125             :                     // Undo when merging a table with one before, if there is also one after it.
    2126             :                     // However, if the node is in a table, it needs to be returned if the
    2127             :                     // SttNode is a section or a table!
    2128             :                     SwTableNode* pTblNd;
    2129         210 :                     if( pSttNd->IsTableNode() &&
    2130          81 :                         0 != ( pTblNd = pFrmNd->FindTableNode() ) &&
    2131             :                         // TABLE IN TABLE:
    2132           0 :                         pTblNd != pSttNd->StartOfSectionNode()->FindTableNode() )
    2133             :                     {
    2134           0 :                         pFrmNd = pTblNd;
    2135           0 :                         rFrmIdx = *pFrmNd;
    2136             :                     }
    2137             :                     else
    2138          81 :                         rFrmIdx = aIdx;
    2139             :                 }
    2140           0 :                 else if( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsTableNode() )
    2141             :                 {
    2142           0 :                     pFrmNd = pNd->StartOfSectionNode();
    2143           0 :                     rFrmIdx = *pFrmNd;
    2144             :                 }
    2145             :                 else
    2146             :                 {
    2147           0 :                     if( pEnd )
    2148           0 :                         aIdx = pEnd->GetIndex() + 1;
    2149             :                     else
    2150           0 :                         aIdx = rFrmIdx.GetIndex() + 1;
    2151             : 
    2152           0 :                     if( (pFrmNd = &aIdx.GetNode())->IsTableNode() )
    2153           0 :                         rFrmIdx = aIdx;
    2154             :                     else
    2155             :                     {
    2156           0 :                         pFrmNd = 0;
    2157             : 
    2158             :                         // is there some sectionnodes before a tablenode?
    2159           0 :                         while( aIdx.GetNode().IsSectionNode() )
    2160             :                         {
    2161           0 :                             const SwSection& rSect = aIdx.GetNode().
    2162           0 :                                 GetSectionNode()->GetSection();
    2163           0 :                             if( rSect.IsHiddenFlag() )
    2164           0 :                                 aIdx = aIdx.GetNode().EndOfSectionIndex()+1;
    2165             :                             else
    2166           0 :                                 ++aIdx;
    2167             :                         }
    2168           0 :                         if( aIdx.GetNode().IsTableNode() )
    2169             :                         {
    2170           0 :                             rFrmIdx = aIdx;
    2171           0 :                             pFrmNd = &aIdx.GetNode();
    2172             :                         }
    2173             :                     }
    2174             :                 }
    2175         197 :             }
    2176             :         }
    2177             :     }
    2178         447 :     return pFrmNd;
    2179             : }
    2180             : 
    2181       63582 : void SwNodes::ForEach( const SwNodeIndex& rStart, const SwNodeIndex& rEnd,
    2182             :                     FnForEach_SwNodes fnForEach, void* pArgs )
    2183             : {
    2184             :     BigPtrArray::ForEach( rStart.GetIndex(), rEnd.GetIndex(),
    2185       63582 :                             (FnForEach) fnForEach, pArgs );
    2186       63582 : }
    2187             : 
    2188             : namespace {
    2189             : 
    2190             : //TODO: seems to be not/wrongly used
    2191       67589 : struct TempBigPtrEntry : public BigPtrEntry
    2192             : {
    2193       67589 :     TempBigPtrEntry() {}
    2194             : };
    2195             : 
    2196             : }
    2197             : 
    2198       10884 : void SwNodes::RemoveNode( sal_uLong nDelPos, sal_uLong nSz, sal_Bool bDel )
    2199             : {
    2200       10884 :     sal_uLong nEnd = nDelPos + nSz;
    2201       10884 :     SwNode* pNew = (*this)[ nEnd ];
    2202             : 
    2203       10884 :     if( pRoot )
    2204             :     {
    2205       10884 :         SwNodeIndex *p = pRoot;
    2206      976528 :         while( p )
    2207             :         {
    2208      954760 :             sal_uLong nIdx = p->GetIndex();
    2209      954760 :             SwNodeIndex* pNext = p->pNext;
    2210      954760 :             if( nDelPos <= nIdx && nIdx < nEnd )
    2211       17078 :                 (*p) = *pNew;
    2212             : 
    2213      954760 :             p = pNext;
    2214             :         }
    2215             : 
    2216       10884 :         p = pRoot->pPrev;
    2217       21768 :         while( p )
    2218             :         {
    2219           0 :             sal_uLong nIdx = p->GetIndex();
    2220           0 :             SwNodeIndex* pPrev = p->pPrev;
    2221           0 :             if( nDelPos <= nIdx && nIdx < nEnd )
    2222           0 :                 (*p) = *pNew;
    2223             : 
    2224           0 :             p = pPrev;
    2225             :         }
    2226             :     }
    2227             : 
    2228             :     {
    2229       78900 :         for (sal_uLong nCnt = 0; nCnt < nSz; nCnt++)
    2230             :         {
    2231       68016 :             SwNode* pNode = ((*this)[ nDelPos + nCnt ]);
    2232       68016 :             SwTxtNode * pTxtNd = pNode->GetTxtNode();
    2233             : 
    2234       68016 :             if (pTxtNd)
    2235             :             {
    2236       37281 :                 pTxtNd->RemoveFromList();
    2237             :             }
    2238       68016 :             SwTableNode* pTableNode = pNode->GetTableNode();
    2239       68016 :             if (pTableNode)
    2240             :             {
    2241             :                 // The node that is deleted is a table node.
    2242             :                 // Need to make sure that all the redlines that are
    2243             :                 // related to this table are removed from the
    2244             :                 // 'Extra Redlines' array
    2245         719 :                 pTableNode->RemoveRedlines();
    2246             :             }
    2247             :         }
    2248             :     }
    2249             : 
    2250       10884 :     std::vector<TempBigPtrEntry> aTempEntries;
    2251       10884 :     if( bDel )
    2252             :     {
    2253       10457 :         sal_uLong nCnt = nSz;
    2254       10457 :         SwNode *pDel = (*this)[ nDelPos+nCnt-1 ], *pPrev = (*this)[ nDelPos+nCnt-2 ];
    2255             : 
    2256             :         // set temporary object
    2257             :         // JP 24.08.98: this should actually be removed because one could
    2258             :         // call Remove recursively, e.g. for character bound frames. However,
    2259             :         // since there happens way too much here, this temporary object was
    2260             :         // inserted that will be deleted in Remove again (see Bug 55406)
    2261       10457 :         aTempEntries.resize(nCnt);
    2262             : 
    2263       88503 :         while( nCnt-- )
    2264             :         {
    2265       67589 :             delete pDel;
    2266       67589 :             pDel = pPrev;
    2267       67589 :             sal_uLong nPrevNdIdx = pPrev->GetIndex();
    2268       67589 :             BigPtrEntry* pTempEntry = &aTempEntries[nCnt];
    2269       67589 :             BigPtrArray::Replace( nPrevNdIdx+1, pTempEntry );
    2270       67589 :             if( nCnt )
    2271       57132 :                 pPrev = (*this)[ nPrevNdIdx  - 1 ];
    2272             :         }
    2273       10457 :         nDelPos = pDel->GetIndex() + 1;
    2274             :     }
    2275             : 
    2276       10884 :     BigPtrArray::Remove( nDelPos, nSz );
    2277       10884 : }
    2278             : 
    2279     4384904 : void SwNodes::RegisterIndex( SwNodeIndex& rIdx )
    2280             : {
    2281     4384904 :     if( !pRoot ) // no root set, yet?
    2282             :     {
    2283        9374 :         pRoot = &rIdx;
    2284        9374 :         pRoot->pPrev = 0;
    2285        9374 :         pRoot->pNext = 0;
    2286             :     }
    2287             :     else
    2288             :     {
    2289             :         // add always after root
    2290     4375530 :         rIdx.pNext = pRoot->pNext;
    2291     4375530 :         pRoot->pNext = &rIdx;
    2292     4375530 :         rIdx.pPrev = pRoot;
    2293     4375530 :         if( rIdx.pNext )
    2294     4373484 :             rIdx.pNext->pPrev = &rIdx;
    2295             :     }
    2296     4384904 : }
    2297             : 
    2298     4384855 : void SwNodes::DeRegisterIndex( SwNodeIndex& rIdx )
    2299             : {
    2300     4384855 :     SwNodeIndex* pN = rIdx.pNext;
    2301     4384855 :     SwNodeIndex* pP = rIdx.pPrev;
    2302             : 
    2303     4384855 :     if( pRoot == &rIdx )
    2304       15151 :         pRoot = pP ? pP : pN;
    2305             : 
    2306     4384855 :     if( pP )
    2307     4369704 :         pP->pNext = pN;
    2308     4384855 :     if( pN )
    2309     4365537 :         pN->pPrev = pP;
    2310             : 
    2311     4384855 :     rIdx.pNext = 0;
    2312     4384855 :     rIdx.pPrev = 0;
    2313     4384855 : }
    2314             : 
    2315       68072 : void SwNodes::InsertNode( const SwNodePtr pNode,
    2316             :                           const SwNodeIndex& rPos )
    2317             : {
    2318       68072 :     const ElementPtr pIns = pNode;
    2319       68072 :     BigPtrArray::Insert( pIns, rPos.GetIndex() );
    2320       68072 : }
    2321             : 
    2322       37044 : void SwNodes::InsertNode( const SwNodePtr pNode,
    2323             :                           sal_uLong nPos )
    2324             : {
    2325       37044 :     const ElementPtr pIns = pNode;
    2326       37044 :     BigPtrArray::Insert( pIns, nPos );
    2327       37044 : }
    2328             : 
    2329             : // ->#112139#
    2330        1974 : SwNode * SwNodes::DocumentSectionStartNode(SwNode * pNode) const
    2331             : {
    2332        1974 :     if (NULL != pNode)
    2333             :     {
    2334        1974 :         SwNodeIndex aIdx(*pNode);
    2335             : 
    2336        1974 :         if (aIdx <= (*this)[0]->EndOfSectionIndex())
    2337           0 :             pNode = (*this)[0];
    2338             :         else
    2339             :         {
    2340        7888 :             while ((*this)[0] != pNode->StartOfSectionNode())
    2341        3940 :                 pNode = pNode->StartOfSectionNode();
    2342        1974 :         }
    2343             :     }
    2344             : 
    2345        1974 :     return pNode;
    2346             : }
    2347             : 
    2348         950 : SwNode * SwNodes::DocumentSectionEndNode(SwNode * pNode) const
    2349             : {
    2350         950 :     return DocumentSectionStartNode(pNode)->EndOfSectionNode();
    2351             : }
    2352             : 
    2353      326936 : sal_Bool SwNodes::IsDocNodes() const
    2354             : {
    2355      326936 :     return this == &pMyDoc->GetNodes();
    2356             : }
    2357             : 
    2358             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10