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

Generated by: LCOV version 1.11