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

Generated by: LCOV version 1.10