LCOV - code coverage report
Current view: top level - sw/source/core/doc - docnum.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 379 1101 34.4 %
Date: 2015-06-13 12:38:46 Functions: 29 48 60.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 <hintids.hxx>
      21             : #include <rtl/random.h>
      22             : #include <tools/resid.hxx>
      23             : #include <editeng/lrspitem.hxx>
      24             : #include <ftninfo.hxx>
      25             : #include <ftnidx.hxx>
      26             : #include <doc.hxx>
      27             : #include <IDocumentUndoRedo.hxx>
      28             : #include <IDocumentListsAccess.hxx>
      29             : #include <DocumentRedlineManager.hxx>
      30             : #include <IDocumentFieldsAccess.hxx>
      31             : #include <IDocumentState.hxx>
      32             : #include <IDocumentStylePoolAccess.hxx>
      33             : #include <pam.hxx>
      34             : #include <ndtxt.hxx>
      35             : #include <doctxm.hxx>
      36             : #include <poolfmt.hxx>
      37             : #include <UndoCore.hxx>
      38             : #include <UndoRedline.hxx>
      39             : #include <UndoNumbering.hxx>
      40             : #include <swundo.hxx>
      41             : #include <SwUndoFmt.hxx>
      42             : #include <rolbck.hxx>
      43             : #include <paratr.hxx>
      44             : #include <docary.hxx>
      45             : #include <mvsave.hxx>
      46             : #include <txtfrm.hxx>
      47             : #include <pamtyp.hxx>
      48             : #include <redline.hxx>
      49             : #include <comcore.hrc>
      50             : #include <editeng/adjustitem.hxx>
      51             : #include <editeng/frmdiritem.hxx>
      52             : #include <frmatr.hxx>
      53             : #include <SwStyleNameMapper.hxx>
      54             : #include <SwNodeNum.hxx>
      55             : #include <list.hxx>
      56             : #include <calbck.hxx>
      57             : #include <comphelper/string.hxx>
      58             : #include <tools/datetimeutils.hxx>
      59             : 
      60             : #include <cstdlib>
      61             : #include <map>
      62             : 
      63             : namespace {
      64           0 :     static void lcl_ResetIndentAttrs(SwDoc *pDoc, const SwPaM &rPam, sal_uInt16 marker )
      65             :     {
      66           0 :         std::set<sal_uInt16> aResetAttrsArray;
      67           0 :         aResetAttrsArray.insert( marker );
      68             :         // #i114929#
      69             :         // On a selection setup a corresponding Point-and-Mark in order to get
      70             :         // the indentation attribute reset on all paragraphs touched by the selection
      71           0 :         if ( rPam.HasMark() &&
      72           0 :              rPam.End()->nNode.GetNode().GetTextNode() )
      73             :         {
      74           0 :             SwPaM aPam( rPam.Start()->nNode,
      75           0 :                         rPam.End()->nNode );
      76           0 :             aPam.Start()->nContent = 0;
      77           0 :             aPam.End()->nContent = rPam.End()->nNode.GetNode().GetTextNode()->Len();
      78           0 :             pDoc->ResetAttrs( aPam, false, aResetAttrsArray );
      79             :         }
      80             :         else
      81             :         {
      82           0 :             pDoc->ResetAttrs( rPam, false, aResetAttrsArray );
      83           0 :         }
      84           0 :     }
      85             : }
      86             : 
      87             : #include <stdlib.h>
      88             : 
      89        2217 : inline sal_uInt8 GetUpperLvlChg( sal_uInt8 nCurLvl, sal_uInt8 nLevel, sal_uInt16 nMask )
      90             : {
      91        2217 :     if( 1 < nLevel )
      92             :     {
      93        2217 :         if( nCurLvl + 1 >= nLevel )
      94        2217 :             nCurLvl -= nLevel - 1;
      95             :         else
      96           0 :             nCurLvl = 0;
      97             :     }
      98        2217 :     return static_cast<sal_uInt8>((nMask - 1) & ~(( 1 << nCurLvl ) - 1));
      99             : }
     100             : 
     101        6800 : void SwDoc::SetOutlineNumRule( const SwNumRule& rRule )
     102             : {
     103        6800 :     if( mpOutlineRule )
     104        6800 :         (*mpOutlineRule) = rRule;
     105             :     else
     106             :     {
     107           0 :         mpOutlineRule = new SwNumRule( rRule );
     108             : 
     109           0 :         AddNumRule(mpOutlineRule); // #i36749#
     110             :     }
     111             : 
     112        6800 :     mpOutlineRule->SetRuleType( OUTLINE_RULE );
     113        6800 :     mpOutlineRule->SetName(SwNumRule::GetOutlineRuleName(), getIDocumentListsAccess());
     114             : 
     115             :     // assure that the outline numbering rule is an automatic rule
     116        6800 :     mpOutlineRule->SetAutoRule( true );
     117             : 
     118             :     // test whether the optional CharFormats are defined in this Document
     119        6800 :     mpOutlineRule->CheckCharFormats( this );
     120             : 
     121             :     // notify text nodes, which are registered at the outline style, about the
     122             :     // changed outline style
     123        6800 :     SwNumRule::tTextNodeList aTextNodeList;
     124        6800 :     mpOutlineRule->GetTextNodeList( aTextNodeList );
     125       20526 :     for ( SwNumRule::tTextNodeList::iterator aIter = aTextNodeList.begin();
     126       13684 :           aIter != aTextNodeList.end(); ++aIter )
     127             :     {
     128          42 :         SwTextNode* pTextNd = *aIter;
     129          42 :         pTextNd->NumRuleChgd();
     130             : 
     131             :         // assure that list level corresponds to outline level
     132          44 :         if ( pTextNd->GetTextColl()->IsAssignedToListLevelOfOutlineStyle() &&
     133           2 :              pTextNd->GetAttrListLevel() != pTextNd->GetTextColl()->GetAssignedOutlineStyleLevel() )
     134             :         {
     135           0 :             pTextNd->SetAttrListLevel( pTextNd->GetTextColl()->GetAssignedOutlineStyleLevel() );
     136             :         }
     137             :     }
     138             : 
     139        6800 :     PropagateOutlineRule();
     140        6800 :     mpOutlineRule->SetInvalidRule(true);
     141        6800 :     UpdateNumRule();
     142             : 
     143             :     // update if we have foot notes && numbering by chapter
     144        6800 :     if( !GetFootnoteIdxs().empty() && FTNNUM_CHAPTER == GetFootnoteInfo().eNum )
     145           0 :         GetFootnoteIdxs().UpdateAllFootnote();
     146             : 
     147        6800 :     getIDocumentFieldsAccess().UpdateExpFields(NULL, true);
     148             : 
     149        6800 :     getIDocumentState().SetModified();
     150        6800 : }
     151             : 
     152        7218 : void SwDoc::PropagateOutlineRule()
     153             : {
     154      151962 :     for (auto pColl : *mpTextFormatCollTable)
     155             :     {
     156      144744 :         if(pColl->IsAssignedToListLevelOfOutlineStyle())
     157             :         {
     158             :             // Check only the list style, which is set at the paragraph style
     159        5614 :             const SwNumRuleItem & rCollRuleItem = pColl->GetNumRule( false );
     160             : 
     161             :             // Check on document setting OUTLINE_LEVEL_YIELDS_OUTLINE_RULE no longer needed.
     162        5614 :             if ( rCollRuleItem.GetValue().isEmpty() )
     163             :             {
     164         461 :                 SwNumRule * pMyOutlineRule = GetOutlineNumRule();
     165             : 
     166         461 :                 if (pMyOutlineRule)
     167             :                 {
     168         461 :                     SwNumRuleItem aNumItem( pMyOutlineRule->GetName() );
     169             : 
     170         461 :                     pColl->SetFormatAttr(aNumItem);
     171             :                 }
     172             :             }
     173             :         }
     174             :     }
     175        7218 : }
     176             : 
     177             : // Increase/Decrease
     178           0 : bool SwDoc::OutlineUpDown( const SwPaM& rPam, short nOffset )
     179             : {
     180           0 :     if( GetNodes().GetOutLineNds().empty() || !nOffset )
     181           0 :         return false;
     182             : 
     183             :     // calculate the range
     184           0 :     const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
     185           0 :     const SwNodePtr pSttNd = &rPam.Start()->nNode.GetNode();
     186           0 :     const SwNodePtr pEndNd = &rPam.End()->nNode.GetNode();
     187             :     sal_uInt16 nSttPos, nEndPos;
     188             : 
     189           0 :     if( !rOutlNds.Seek_Entry( pSttNd, &nSttPos ) &&
     190           0 :         !nSttPos-- )
     191             :         // we're not in an "Outline section"
     192           0 :         return false;
     193             : 
     194           0 :     if( rOutlNds.Seek_Entry( pEndNd, &nEndPos ) )
     195           0 :         ++nEndPos;
     196             : 
     197             :     // We now have the wanted range in the OutlineNodes array,
     198             :     // so check now if we're not invalidating sublevels
     199             :     // (stepping over the limits)
     200             : 
     201             :     // Here we go:
     202             :     // 1. Create the style array:
     203             :     SwTextFormatColl* aCollArr[ MAXLEVEL ];
     204           0 :     memset( aCollArr, 0, sizeof( SwTextFormatColl* ) * MAXLEVEL );
     205             : 
     206           0 :     for( auto pTextFormatColl : *mpTextFormatCollTable )
     207             :     {
     208           0 :         if (pTextFormatColl->IsAssignedToListLevelOfOutlineStyle())
     209             :         {
     210           0 :             const int nLevel = pTextFormatColl->GetAssignedOutlineStyleLevel();
     211           0 :             aCollArr[ nLevel ] = pTextFormatColl;
     212             :         }
     213             :     }
     214             : 
     215             :     int n;
     216             : 
     217             :     /* Find the last occupied level (backward). */
     218           0 :     for (n = MAXLEVEL - 1; n > 0; n--)
     219             :     {
     220           0 :         if (aCollArr[n] != 0)
     221           0 :             break;
     222             :     }
     223             : 
     224             :     /* If an occupied level is found, choose next level (which IS
     225             :        unoccupied) until a valid level is found. If no occupied level
     226             :        was found n is 0 and aCollArr[0] is 0. In this case no demoting
     227             :        is possible. */
     228           0 :     if (aCollArr[n] != 0)
     229             :     {
     230           0 :         while (n < MAXLEVEL - 1)
     231             :         {
     232           0 :             n++;
     233             : 
     234             :             SwTextFormatColl *aTmpColl =
     235           0 :                 getIDocumentStylePoolAccess().GetTextCollFromPool(static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + n));
     236             : 
     237           0 :             if( aTmpColl->IsAssignedToListLevelOfOutlineStyle() &&
     238           0 :                 aTmpColl->GetAssignedOutlineStyleLevel() == n )
     239             :             {
     240           0 :                 aCollArr[n] = aTmpColl;
     241           0 :                 break;
     242             :             }
     243             :         }
     244             :     }
     245             : 
     246             :     /* Find the first occupied level (forward). */
     247           0 :     for (n = 0; n < MAXLEVEL - 1; n++)
     248             :     {
     249           0 :         if (aCollArr[n] != 0)
     250           0 :             break;
     251             :     }
     252             : 
     253             :     /* If an occupied level is found, choose previous level (which IS
     254             :        unoccupied) until a valid level is found. If no occupied level
     255             :        was found n is MAXLEVEL - 1 and aCollArr[MAXLEVEL - 1] is 0. In
     256             :        this case no demoting is possible. */
     257           0 :     if (aCollArr[n] != 0)
     258             :     {
     259           0 :         while (n > 0)
     260             :         {
     261           0 :             n--;
     262             : 
     263             :             SwTextFormatColl *aTmpColl =
     264           0 :                 getIDocumentStylePoolAccess().GetTextCollFromPool(static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + n));
     265             : 
     266           0 :             if( aTmpColl->IsAssignedToListLevelOfOutlineStyle() &&
     267           0 :                 aTmpColl->GetAssignedOutlineStyleLevel() == n )
     268             :             {
     269           0 :                 aCollArr[n] = aTmpColl;
     270           0 :                 break;
     271             :             }
     272             :         }
     273             :     }
     274             : 
     275             :     /* --> #i13747#
     276             : 
     277             :         Build a move table that states from which level to which other level
     278             :         an outline will be moved.
     279             : 
     280             :         the move table:
     281             :         aMoveArr[n] = m: replace aCollArr[n] with aCollArr[m]
     282             :     */
     283             :     int aMoveArr[MAXLEVEL];
     284             :     int nStep; // step size for searching in aCollArr: -1 or 1
     285             :     int nNum; // amount of steps for stepping in aCollArr
     286             : 
     287           0 :     if (nOffset < 0)
     288             :     {
     289           0 :         nStep = -1;
     290           0 :         nNum = -nOffset;
     291             :     }
     292             :     else
     293             :     {
     294           0 :         nStep = 1;
     295           0 :         nNum = nOffset;
     296             :     }
     297             : 
     298             :     /* traverse aCollArr */
     299           0 :     for (n = 0; n < MAXLEVEL; n++)
     300             :     {
     301             :         /* If outline level n has an assigned paragraph style step
     302             :            nNum steps forwards (nStep == 1) or backwards (nStep ==
     303             :            -1).  One step is to go to the next non-null entry in
     304             :            aCollArr in the selected direction. If nNum steps were
     305             :            possible write the index of the entry found to aCollArr[n],
     306             :            i.e. outline level n will be replaced by outline level
     307             :            aCollArr[n].
     308             : 
     309             :            If outline level n has no assigned paragraph style
     310             :            aMoveArr[n] is set to -1.
     311             :         */
     312           0 :         if (aCollArr[n] != NULL)
     313             :         {
     314           0 :             int m = n;
     315           0 :             int nCount = nNum;
     316             : 
     317           0 :             while (nCount > 0 && m + nStep >= 0 && m + nStep < MAXLEVEL)
     318             :             {
     319           0 :                 m += nStep;
     320             : 
     321           0 :                 if (aCollArr[m] != NULL)
     322           0 :                     nCount--;
     323             :             }
     324             : 
     325           0 :             if (nCount == 0)
     326           0 :                 aMoveArr[n] = m;
     327             :             else
     328           0 :                 aMoveArr[n] = -1;
     329             :         }
     330             :         else
     331           0 :             aMoveArr[n] = -1;
     332             :     }
     333             : 
     334             :     /* If moving of the outline levels is applicable, i.e. for all
     335             :        outline levels occurring in the document there has to be a valid
     336             :        target outline level implied by aMoveArr. */
     337           0 :     bool bMoveApplicable = true;
     338           0 :     for (auto i = nSttPos; i < nEndPos; ++i)
     339             :     {
     340           0 :         SwTextNode* pTextNd = rOutlNds[ i ]->GetTextNode();
     341           0 :         SwTextFormatColl* pColl = pTextNd->GetTextColl();
     342             : 
     343           0 :         if( pColl->IsAssignedToListLevelOfOutlineStyle() )
     344             :         {
     345           0 :             const int nLevel = pColl->GetAssignedOutlineStyleLevel();
     346           0 :             if (aMoveArr[nLevel] == -1)
     347           0 :                 bMoveApplicable = false;
     348             :         }
     349             : 
     350             :         // Check on outline level attribute of text node, if text node is
     351             :         // not an outline via a to outline style assigned paragraph style.
     352             :         else
     353             :         {
     354           0 :             const int nNewOutlineLevel = pTextNd->GetAttrOutlineLevel() + nOffset;
     355           0 :             if ( nNewOutlineLevel < 1 || nNewOutlineLevel > MAXLEVEL )
     356             :             {
     357           0 :                 bMoveApplicable = false;
     358             :             }
     359             :         }
     360             :     }
     361             : 
     362           0 :     if (! bMoveApplicable )
     363           0 :         return false;
     364             : 
     365           0 :     if (GetIDocumentUndoRedo().DoesUndo())
     366             :     {
     367           0 :         GetIDocumentUndoRedo().StartUndo(UNDO_OUTLINE_LR, NULL);
     368           0 :         SwUndo *const pUndoOLR( new SwUndoOutlineLeftRight( rPam, nOffset ) );
     369           0 :         GetIDocumentUndoRedo().AppendUndo(pUndoOLR);
     370             :     }
     371             : 
     372             :     // 2. Apply the new style to all Nodes
     373           0 :     for (auto i = nSttPos; i < nEndPos; ++i)
     374             :     {
     375           0 :         SwTextNode* pTextNd = rOutlNds[ i ]->GetTextNode();
     376           0 :         SwTextFormatColl* pColl = pTextNd->GetTextColl();
     377             : 
     378           0 :         if( pColl->IsAssignedToListLevelOfOutlineStyle() )
     379             :         {
     380           0 :             const int nLevel = pColl->GetAssignedOutlineStyleLevel();
     381             : 
     382             :             OSL_ENSURE(aMoveArr[nLevel] >= 0,
     383             :                 "move table: current TextColl not found when building table!");
     384             : 
     385           0 :             if (nLevel < MAXLEVEL && aMoveArr[nLevel] >= 0)
     386             :             {
     387           0 :                 pColl = aCollArr[ aMoveArr[nLevel] ];
     388             : 
     389           0 :                 if (pColl != NULL)
     390           0 :                     pTextNd->ChgFormatColl( pColl );
     391             :             }
     392             : 
     393             :         }
     394           0 :         else if( pTextNd->GetAttrOutlineLevel() > 0)
     395             :         {
     396           0 :             int nLevel = pTextNd->GetAttrOutlineLevel() + nOffset;
     397           0 :             if( 0 <= nLevel && nLevel <= MAXLEVEL)
     398           0 :                 pTextNd->SetAttrOutlineLevel( nLevel );
     399             : 
     400             :         }
     401             :         // Undo ???
     402             :     }
     403           0 :     if (GetIDocumentUndoRedo().DoesUndo())
     404             :     {
     405           0 :         GetIDocumentUndoRedo().EndUndo(UNDO_OUTLINE_LR, NULL);
     406             :     }
     407             : 
     408           0 :     ChkCondColls();
     409           0 :     getIDocumentState().SetModified();
     410             : 
     411           0 :     return true;
     412             : }
     413             : 
     414             : // Move up/down
     415           0 : bool SwDoc::MoveOutlinePara( const SwPaM& rPam, short nOffset )
     416             : {
     417             :     // Do not move to special sections in the nodes array
     418           0 :     const SwPosition& rStt = *rPam.Start(),
     419           0 :                     & rEnd = &rStt == rPam.GetPoint() ? *rPam.GetMark()
     420           0 :                                                       : *rPam.GetPoint();
     421           0 :     if( GetNodes().GetOutLineNds().empty() || !nOffset ||
     422           0 :         (rStt.nNode.GetIndex() < GetNodes().GetEndOfExtras().GetIndex()) ||
     423           0 :         (rEnd.nNode.GetIndex() < GetNodes().GetEndOfExtras().GetIndex()))
     424             :     {
     425           0 :         return false;
     426             :     }
     427             : 
     428           0 :     sal_uInt16 nAktPos = 0;
     429           0 :     SwNodeIndex aSttRg( rStt.nNode ), aEndRg( rEnd.nNode );
     430             : 
     431           0 :     int nOutLineLevel = MAXLEVEL;
     432           0 :     SwNode* pSrch = &aSttRg.GetNode();
     433             : 
     434           0 :    if( pSrch->IsTextNode())
     435           0 :         nOutLineLevel = static_cast<sal_uInt8>(pSrch->GetTextNode()->GetAttrOutlineLevel()-1);
     436           0 :     SwNode* pEndSrch = &aEndRg.GetNode();
     437           0 :     if( !GetNodes().GetOutLineNds().Seek_Entry( pSrch, &nAktPos ) )
     438             :     {
     439           0 :         if( !nAktPos )
     440           0 :             return false; // Promoting or demoting before the first outline => no.
     441           0 :         if( --nAktPos )
     442           0 :             aSttRg = *GetNodes().GetOutLineNds()[ nAktPos ];
     443           0 :         else if( 0 > nOffset )
     444           0 :             return false; // Promoting at the top of document?!
     445             :         else
     446           0 :             aSttRg = *GetNodes().GetEndOfContent().StartOfSectionNode();
     447             :     }
     448           0 :     sal_uInt16 nTmpPos = 0;
     449             :     // If the given range ends at an outlined text node we have to decide if it has to be a part of
     450             :     // the moving range or not. Normally it will be a sub outline of our chapter
     451             :     // and has to be moved, too. But if the chapter ends with a table(or a section end),
     452             :     // the next text node will be chosen and this could be the next outline of the same level.
     453             :     // The criteria has to be the outline level: sub level => incorporate, same/higher level => no.
     454           0 :     if( GetNodes().GetOutLineNds().Seek_Entry( pEndSrch, &nTmpPos ) )
     455             :     {
     456           0 :         if( !pEndSrch->IsTextNode() || pEndSrch == pSrch ||
     457           0 :             nOutLineLevel < pEndSrch->GetTextNode()->GetAttrOutlineLevel()-1 )
     458           0 :             ++nTmpPos; // For sub outlines only!
     459             :     }
     460             : 
     461           0 :     aEndRg = nTmpPos < GetNodes().GetOutLineNds().size()
     462           0 :                     ? *GetNodes().GetOutLineNds()[ nTmpPos ]
     463           0 :                     : GetNodes().GetEndOfContent();
     464           0 :     if( nOffset >= 0 )
     465           0 :         nAktPos = nTmpPos;
     466           0 :     if( aEndRg == aSttRg )
     467             :     {
     468             :         OSL_FAIL( "Moving outlines: Surprising selection" );
     469           0 :         ++aEndRg;
     470             :     }
     471             : 
     472             :     const SwNode* pNd;
     473             :     // The following code corrects the range to handle sections (start/end nodes)
     474             :     // The range will be extended if the least node before the range is a start node
     475             :     // which ends inside the range => The complete section will be moved.
     476             :     // The range will be shrunk if the last position is a start node.
     477             :     // The range will be shrunk if the last node is an end node which starts before the range.
     478           0 :     --aSttRg;
     479           0 :     while( aSttRg.GetNode().IsStartNode() )
     480             :     {
     481           0 :         pNd = aSttRg.GetNode().EndOfSectionNode();
     482           0 :         if( pNd->GetIndex() >= aEndRg.GetIndex() )
     483           0 :             break;
     484           0 :        --aSttRg;
     485             :     }
     486           0 :     ++aSttRg;
     487             : 
     488           0 :     --aEndRg;
     489           0 :     while( aEndRg.GetNode().IsStartNode() )
     490           0 :         --aEndRg;
     491             : 
     492           0 :     while( aEndRg.GetNode().IsEndNode() )
     493             :     {
     494           0 :         pNd = aEndRg.GetNode().StartOfSectionNode();
     495           0 :         if( pNd->GetIndex() >= aSttRg.GetIndex() )
     496           0 :             break;
     497           0 :         --aEndRg;
     498             :     }
     499           0 :     ++aEndRg;
     500             : 
     501             :     // calculation of the new position
     502           0 :     if( nOffset < 0 && nAktPos < sal_uInt16(-nOffset) )
     503           0 :         pNd = GetNodes().GetEndOfContent().StartOfSectionNode();
     504           0 :     else if( nAktPos + nOffset >= (sal_uInt16)GetNodes().GetOutLineNds().size() )
     505           0 :         pNd = &GetNodes().GetEndOfContent();
     506             :     else
     507           0 :         pNd = GetNodes().GetOutLineNds()[ nAktPos + nOffset ];
     508             : 
     509           0 :     sal_uLong nNewPos = pNd->GetIndex();
     510             : 
     511             :     // And now a correction of the insert position if necessary...
     512           0 :     SwNodeIndex aInsertPos( *pNd, -1 );
     513           0 :     while( aInsertPos.GetNode().IsStartNode() )
     514             :     {
     515             :         // Just before the insert position starts a section:
     516             :         // when I'm moving forward I do not want to enter the section,
     517             :         // when I'm moving backward I want to stay in the section if I'm already a part of,
     518             :         // I want to stay outside if I was outside before.
     519           0 :         if( nOffset < 0 )
     520             :         {
     521           0 :             pNd = aInsertPos.GetNode().EndOfSectionNode();
     522           0 :             if( pNd->GetIndex() >= aEndRg.GetIndex() )
     523           0 :                 break;
     524             :         }
     525           0 :         --aInsertPos;
     526           0 :         --nNewPos;
     527             :     }
     528             : 
     529           0 :     if( nOffset >= 0 )
     530             :     {
     531             :         // When just before the insert position a section ends, it is okay when I'm moving backward
     532             :         // because I want to stay outside the section.
     533             :         // When moving forward I've to check if I started inside or outside the section
     534             :         // because I don't want to enter of leave such a section
     535           0 :         while( aInsertPos.GetNode().IsEndNode() )
     536             :         {
     537           0 :             pNd = aInsertPos.GetNode().StartOfSectionNode();
     538           0 :             if( pNd->GetIndex() >= aSttRg.GetIndex() )
     539           0 :                 break;
     540           0 :             --aInsertPos;
     541           0 :             --nNewPos;
     542             :         }
     543             :     }
     544             :     // We do not want to move into tables (at the moment)
     545           0 :     ++aInsertPos;
     546           0 :     pNd = &aInsertPos.GetNode();
     547           0 :     if( pNd->IsTableNode() )
     548           0 :         pNd = pNd->StartOfSectionNode();
     549           0 :     if( pNd->FindTableNode() )
     550           0 :         return false;
     551             : 
     552             :     OSL_ENSURE( aSttRg.GetIndex() > nNewPos || nNewPos >= aEndRg.GetIndex(),
     553             :                 "Position lies within Move range" );
     554             : 
     555             :     // If a Position inside the special nodes array sections was calculated,
     556             :     // set it to document start instead.
     557             :     // Sections or Tables at the document start will be pushed backwards.
     558           0 :     nNewPos = std::max( nNewPos, GetNodes().GetEndOfExtras().GetIndex() + 2 );
     559             : 
     560           0 :     long nOffs = nNewPos - ( 0 < nOffset ? aEndRg.GetIndex() : aSttRg.GetIndex());
     561           0 :     SwPaM aPam( aSttRg, aEndRg, 0, -1 );
     562           0 :     return MoveParagraph( aPam, nOffs, true );
     563             : }
     564             : 
     565          24 : static SwTextNode* lcl_FindOutlineName( const SwOutlineNodes& rOutlNds, const OUString& rName,
     566             :                             bool bExact )
     567             : {
     568          24 :     SwTextNode* pSavedNode = nullptr;
     569         170 :     for( auto pOutlNd : rOutlNds )
     570             :     {
     571         160 :         SwTextNode* pTextNd = pOutlNd->GetTextNode();
     572         160 :         const OUString sText( pTextNd->GetExpandText() );
     573         160 :         if (sText.startsWith(rName))
     574             :         {
     575          14 :             if (sText.getLength() == rName.getLength())
     576             :             {
     577             :                 // Found "exact", set Pos to the Node
     578          14 :                 return pTextNd;
     579             :             }
     580           0 :             if( !bExact && !pSavedNode )
     581             :             {
     582             :                 // maybe we just found the text's first part
     583           0 :                 pSavedNode = pTextNd;
     584             :             }
     585             :         }
     586         146 :     }
     587             : 
     588          10 :     return pSavedNode;
     589             : }
     590             : 
     591          28 : static SwTextNode* lcl_FindOutlineNum( const SwOutlineNodes& rOutlNds, OUString& rName )
     592             : {
     593             :     // Valid numbers are (always just offsets!):
     594             :     //  ([Number]+\.)+  (as a regular expression!)
     595             :     //  (Number follwed by a period, with 5 repetitions)
     596             :     //  i.e.: "1.1.", "1.", "1.1.1."
     597          28 :     sal_Int32 nPos = 0;
     598          28 :     OUString sNum = rName.getToken( 0, '.', nPos );
     599          28 :     if( -1 == nPos )
     600           0 :         return nullptr;           // invalid number!
     601             : 
     602             :     sal_uInt16 nLevelVal[ MAXLEVEL ];       // numbers of all levels
     603          28 :     memset( nLevelVal, 0, MAXLEVEL * sizeof( nLevelVal[0] ));
     604          28 :     int nLevel = 0;
     605          56 :     OUString sName( rName );
     606             : 
     607          28 :     while( -1 != nPos )
     608             :     {
     609          76 :         sal_uInt16 nVal = 0;
     610         312 :         for( sal_Int32 n = 0; n < sNum.getLength(); ++n )
     611             :         {
     612          80 :             const sal_Unicode c {sNum[ n ]};
     613          80 :             if( '0' <= c && c <= '9' )
     614             :             {
     615          80 :                 nVal *= 10;
     616          80 :                 nVal += c - '0';
     617             :             }
     618           0 :             else if( nLevel )
     619           0 :                 break;                      // "almost" valid number
     620             :             else
     621           0 :                 return nullptr;             // invalid number!
     622             :         }
     623             : 
     624          76 :         if( MAXLEVEL > nLevel )
     625          76 :             nLevelVal[ nLevel++ ] = nVal;
     626             : 
     627          76 :         sName = sName.copy( nPos );
     628          76 :         nPos = 0;
     629          76 :         sNum = sName.getToken( 0, '.', nPos );
     630             :         // #i4533# without this check all parts delimited by a dot are treated as outline numbers
     631          76 :         if(!comphelper::string::isdigitAsciiString(sNum))
     632          28 :             break;
     633             :     }
     634          28 :     rName = sName;      // that's the follow-up text
     635             : 
     636             :     // read all levels, so search the document for this outline
     637             : 
     638             :     // Without OutlineNodes searching doesn't pay off
     639             :     // and we save a crash
     640          28 :     if( rOutlNds.empty() )
     641           5 :         return nullptr;
     642             : 
     643             :     // search in the existing outline nodes for the required outline num array
     644         144 :     for( auto pOutlNd : rOutlNds )
     645             :     {
     646         144 :         SwTextNode* pNd = pOutlNd->GetTextNode();
     647         144 :         if ( pNd->GetAttrOutlineLevel() == nLevel )
     648             :         {
     649             :             // #i51089#, #i68289#
     650             :             // Assure, that text node has the correct numbering level. Otherwise,
     651             :             // its number vector will not fit to the searched level.
     652          33 :             if ( pNd->GetNum() && pNd->GetActualListLevel() == nLevel - 1 )
     653             :             {
     654          33 :                 const SwNodeNum & rNdNum = *(pNd->GetNum());
     655          33 :                 SwNumberTree::tNumberVector aLevelVal = rNdNum.GetNumberVector();
     656             :                 // now compare with the one searched for
     657          43 :                 for( int n = 0; n < nLevel; ++n )
     658             :                 {
     659          33 :                     if ( aLevelVal[n] == nLevelVal[n] )
     660             :                     {
     661          23 :                         return pNd;
     662             :                     }
     663          10 :                 }
     664             :             }
     665             :             else
     666             :             {
     667             :                 // A text node, which has an outline paragraph style applied and
     668             :                 // has as hard attribute 'no numbering' set, has an outline level,
     669             :                 // but no numbering tree node. Thus, consider this situation in
     670             :                 // the assertion condition.
     671             :                 OSL_ENSURE( !pNd->GetNumRule(),
     672             :                         "<lcl_FindOutlineNum(..)> - text node with outline level and numbering rule, but without numbering tree node. This is a serious defect -> inform OD" );
     673             :             }
     674             :         }
     675             :     }
     676             : 
     677          28 :     return nullptr;
     678             : }
     679             : 
     680             : // Add this bullet point:
     681             : 
     682             : // A Name can contain a Number and/or the Text.
     683             : 
     684             : // First, we try to find the correct Entry via the Number.
     685             : // If it exists, we compare the Text, to see if it's the right one.
     686             : // If that's not the case, we search again via the Text. If it is
     687             : // found, we got the right entry. Or else we use the one found by
     688             : // searching for the Number.
     689             : // If we don't have a Number, we search via the Text only.
     690          28 : bool SwDoc::GotoOutline( SwPosition& rPos, const OUString& rName ) const
     691             : {
     692          28 :     if( !rName.isEmpty() )
     693             :     {
     694          28 :         const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
     695             : 
     696             :         // 1. step: via the Number:
     697          28 :         OUString sName( rName );
     698          28 :         SwTextNode* pNd = ::lcl_FindOutlineNum( rOutlNds, sName );
     699          28 :         if ( pNd )
     700             :         {
     701          23 :             OUString sExpandedText = pNd->GetExpandText();
     702             :             //#i4533# leading numbers followed by a dot have been remove while
     703             :             //searching for the outline position
     704             :             //to compensate this they must be removed from the paragraphs text content, too
     705          23 :             sal_Int32 nPos = 0;
     706          46 :             OUString sTempNum;
     707         115 :             while(!sExpandedText.isEmpty() && !(sTempNum = sExpandedText.getToken(0, '.', nPos)).isEmpty() &&
     708          69 :                     -1 != nPos &&
     709           0 :                     comphelper::string::isdigitAsciiString(sTempNum))
     710             :             {
     711           0 :                 sExpandedText = sExpandedText.copy(nPos);
     712           0 :                 nPos = 0;
     713             :             }
     714             : 
     715          23 :             if( sExpandedText != sName )
     716             :             {
     717          14 :                 SwTextNode *pTmpNd = ::lcl_FindOutlineName( rOutlNds, sName, true );
     718          14 :                 if ( pTmpNd )             // found via the Name
     719             :                 {
     720          14 :                     pNd = pTmpNd;
     721             :                 }
     722             :             }
     723          23 :             rPos.nNode = *pNd;
     724          23 :             rPos.nContent.Assign( pNd, 0 );
     725          46 :             return true;
     726             :         }
     727             : 
     728           5 :         pNd = ::lcl_FindOutlineName( rOutlNds, rName, false );
     729           5 :         if ( pNd )
     730             :         {
     731           0 :             rPos.nNode = *pNd;
     732           0 :             rPos.nContent.Assign( pNd, 0 );
     733           0 :             return true;
     734             :         }
     735             : 
     736             :         // #i68289# additional search on hyperlink URL without its outline numbering part
     737           5 :         if ( sName != rName )
     738             :         {
     739           5 :             pNd = ::lcl_FindOutlineName( rOutlNds, sName, false );
     740           5 :             if ( pNd )
     741             :             {
     742           0 :                 rPos.nNode = *pNd;
     743           0 :                 rPos.nContent.Assign( pNd, 0 );
     744           0 :                 return true;
     745             :             }
     746           5 :         }
     747             :     }
     748           5 :     return false;
     749             : }
     750             : 
     751      297326 : static void lcl_ChgNumRule( SwDoc& rDoc, const SwNumRule& rRule )
     752             : {
     753      297326 :     SwNumRule* pOld = rDoc.FindNumRulePtr( rRule.GetName() );
     754      297326 :     if (!pOld) //we cannot proceed without the old NumRule
     755      152793 :         return;
     756             : 
     757      297326 :     sal_uInt16 nChgFormatLevel = 0;
     758      297326 :     sal_uInt16 nMask = 1;
     759             : 
     760     3270586 :     for ( sal_uInt8 n = 0; n < MAXLEVEL; ++n, nMask <<= 1 )
     761             :     {
     762     2973260 :         const SwNumFormat& rOldFormat = pOld->Get( n ), &rNewFormat = rRule.Get( n );
     763             : 
     764     2973260 :         if ( rOldFormat != rNewFormat )
     765             :         {
     766      188624 :             nChgFormatLevel |= nMask;
     767             :         }
     768     5569272 :         else if ( SVX_NUM_NUMBER_NONE > rNewFormat.GetNumberingType()
     769     1268578 :                   && 1 < rNewFormat.GetIncludeUpperLevels()
     770     2786853 :                   && 0 != ( nChgFormatLevel & GetUpperLvlChg( n, rNewFormat.GetIncludeUpperLevels(), nMask ) ) )
     771             :         {
     772         149 :             nChgFormatLevel |= nMask;
     773             :         }
     774             :     }
     775             : 
     776      297326 :     if( !nChgFormatLevel )         // Nothing has been changed?
     777             :     {
     778      152793 :         const bool bInvalidateNumRule( pOld->IsContinusNum() != rRule.IsContinusNum() );
     779      152793 :         pOld->CheckCharFormats( &rDoc );
     780      152793 :         pOld->SetContinusNum( rRule.IsContinusNum() );
     781             : 
     782      152793 :         if ( bInvalidateNumRule )
     783             :         {
     784           0 :             pOld->SetInvalidRule(true);
     785             :         }
     786             : 
     787      152793 :         return ;
     788             :     }
     789             : 
     790      144533 :     SwNumRule::tTextNodeList aTextNodeList;
     791      144533 :     pOld->GetTextNodeList( aTextNodeList );
     792      144533 :     sal_uInt8 nLvl( 0 );
     793      433599 :     for ( SwNumRule::tTextNodeList::iterator aIter = aTextNodeList.begin();
     794      289066 :           aIter != aTextNodeList.end(); ++aIter )
     795             :     {
     796           0 :         SwTextNode* pTextNd = *aIter;
     797           0 :         nLvl = static_cast<sal_uInt8>(pTextNd->GetActualListLevel());
     798             : 
     799           0 :         if( nLvl < MAXLEVEL )
     800             :         {
     801           0 :             if( nChgFormatLevel & ( 1 << nLvl ))
     802             :             {
     803           0 :                 pTextNd->NumRuleChgd();
     804             :             }
     805             :         }
     806             :     }
     807             : 
     808     1589863 :     for ( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
     809     1445330 :         if ( nChgFormatLevel & ( 1 << n ) )
     810      188773 :             pOld->Set( n, rRule.GetNumFormat( n ) );
     811             : 
     812      144533 :     pOld->CheckCharFormats( &rDoc );
     813      144533 :     pOld->SetInvalidRule( true );
     814      144533 :     pOld->SetContinusNum( rRule.IsContinusNum() );
     815             : 
     816      144533 :     rDoc.UpdateNumRule();
     817             : }
     818             : 
     819        2681 : OUString SwDoc::SetNumRule( const SwPaM& rPam,
     820             :                         const SwNumRule& rRule,
     821             :                         const bool bCreateNewList,
     822             :                         const OUString& sContinuedListId,
     823             :                         bool bSetItem,
     824             :                         const bool bResetIndentAttrs )
     825             : {
     826        2681 :     OUString sListId;
     827             : 
     828        2681 :     SwUndoInsNum * pUndo = NULL;
     829        2681 :     if (GetIDocumentUndoRedo().DoesUndo())
     830             :     {
     831             :         // Start/End for attributes!
     832          70 :         GetIDocumentUndoRedo().StartUndo( UNDO_INSNUM, NULL );
     833          70 :         pUndo = new SwUndoInsNum( rPam, rRule );
     834          70 :         GetIDocumentUndoRedo().AppendUndo(pUndo);
     835             :     }
     836             : 
     837        2681 :     SwNumRule* pNewOrChangedNumRule = FindNumRulePtr( rRule.GetName() );
     838        2681 :     bool bNewNumRuleCreated = false;
     839        2681 :     if ( pNewOrChangedNumRule == NULL )
     840             :     {
     841             :         // create new numbering rule based on given one
     842           0 :         pNewOrChangedNumRule = ( *mpNumRuleTable )[MakeNumRule( rRule.GetName(), &rRule )];
     843           0 :         bNewNumRuleCreated = true;
     844             :     }
     845        2681 :     else if ( rRule != *pNewOrChangedNumRule )
     846             :     {
     847             :         // change existing numbering rule
     848         181 :         if (pUndo)
     849             :         {
     850           0 :             pUndo->SaveOldNumRule( *pNewOrChangedNumRule );
     851             :         }
     852         181 :         ::lcl_ChgNumRule( *this, rRule );
     853         181 :         if (pUndo)
     854             :         {
     855           0 :             pUndo->SetLRSpaceEndPos();
     856             :         }
     857             :     }
     858             : 
     859        2681 :     if ( bSetItem )
     860             :     {
     861        2681 :         if ( bCreateNewList )
     862             :         {
     863           0 :             if ( bNewNumRuleCreated )
     864             :             {
     865             :                 // apply list id of list, which has been created for the new list style
     866           0 :                 sListId = pNewOrChangedNumRule->GetDefaultListId();
     867             :             }
     868             :             else
     869             :             {
     870             :                 // create new list and apply its list id
     871           0 :                 const SwList* pNewList = getIDocumentListsAccess().createList( OUString(), pNewOrChangedNumRule->GetName() );
     872             :                 OSL_ENSURE( pNewList,
     873             :                         "<SwDoc::SetNumRule(..)> - could not create new list. Serious defect -> please inform OD." );
     874           0 :                 sListId = pNewList->GetListId();
     875             :             }
     876             :         }
     877        2681 :         else if ( !sContinuedListId.isEmpty() )
     878             :         {
     879             :             // apply given list id
     880          40 :             sListId = sContinuedListId;
     881             :         }
     882        2681 :         if (!sListId.isEmpty())
     883             :         {
     884          40 :             getIDocumentContentOperations().InsertPoolItem( rPam, SfxStringItem( RES_PARATR_LIST_ID, sListId ) );
     885             :         }
     886             :     }
     887             : 
     888        2681 :     if ( !rPam.HasMark() )
     889             :     {
     890        2466 :         SwTextNode * pTextNd = rPam.GetPoint()->nNode.GetNode().GetTextNode();
     891             :         // robust code: consider case that the PaM doesn't denote a text node - e.g. it denotes a graphic node
     892        2466 :         if ( pTextNd != NULL )
     893             :         {
     894        2466 :             SwNumRule * pRule = pTextNd->GetNumRule();
     895             : 
     896        2466 :             if (pRule && pRule->GetName() == pNewOrChangedNumRule->GetName())
     897             :             {
     898          40 :                 bSetItem = false;
     899          40 :                 if ( !pTextNd->IsInList() )
     900             :                 {
     901           0 :                     pTextNd->AddToList();
     902             :                 }
     903             :             }
     904             :             // Only clear numbering attribute at text node, if at paragraph
     905             :             // style the new numbering rule is found.
     906        2426 :             else if ( !pRule )
     907             :             {
     908        2404 :                 SwTextFormatColl* pColl = pTextNd->GetTextColl();
     909        2404 :                 if ( pColl )
     910             :                 {
     911        2404 :                     SwNumRule* pCollRule = FindNumRulePtr(pColl->GetNumRule().GetValue());
     912        2404 :                     if ( pCollRule && pCollRule->GetName() == pNewOrChangedNumRule->GetName() )
     913             :                     {
     914           0 :                         pTextNd->ResetAttr( RES_PARATR_NUMRULE );
     915           0 :                         bSetItem = false;
     916             :                     }
     917             :                 }
     918             :             }
     919             :         }
     920             :     }
     921             : 
     922        2681 :     if ( bSetItem )
     923             :     {
     924        2641 :         getIDocumentContentOperations().InsertPoolItem( rPam, SwNumRuleItem( pNewOrChangedNumRule->GetName() ) );
     925             :     }
     926             : 
     927        2681 :     if ( bResetIndentAttrs
     928        2681 :          && pNewOrChangedNumRule->Get( 0 ).GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
     929             :     {
     930           0 :         ::lcl_ResetIndentAttrs(this, rPam, RES_LR_SPACE);
     931             :     }
     932             : 
     933        2681 :     if (GetIDocumentUndoRedo().DoesUndo())
     934             :     {
     935          70 :         GetIDocumentUndoRedo().EndUndo( UNDO_INSNUM, NULL );
     936             :     }
     937             : 
     938        2681 :     getIDocumentState().SetModified();
     939             : 
     940        2681 :     return sListId;
     941             : }
     942             : 
     943           0 : void SwDoc::SetCounted(const SwPaM & rPam, bool bCounted)
     944             : {
     945           0 :     if ( bCounted )
     946             :     {
     947           0 :         ::lcl_ResetIndentAttrs(this, rPam, RES_PARATR_LIST_ISCOUNTED);
     948             :     }
     949             :     else
     950             :     {
     951           0 :         getIDocumentContentOperations().InsertPoolItem( rPam, SfxBoolItem( RES_PARATR_LIST_ISCOUNTED, false ) );
     952             :     }
     953           0 : }
     954             : 
     955          27 : void SwDoc::SetNumRuleStart( const SwPosition& rPos, bool bFlag )
     956             : {
     957          27 :     SwTextNode* pTextNd = rPos.nNode.GetNode().GetTextNode();
     958             : 
     959          27 :     if (pTextNd)
     960             :     {
     961          27 :         const SwNumRule* pRule = pTextNd->GetNumRule();
     962          27 :         if( pRule && !bFlag != !pTextNd->IsListRestart())
     963             :         {
     964          23 :             if (GetIDocumentUndoRedo().DoesUndo())
     965             :             {
     966          12 :                 SwUndo *const pUndo( new SwUndoNumRuleStart(rPos, bFlag) );
     967          12 :                 GetIDocumentUndoRedo().AppendUndo(pUndo);
     968             :             }
     969             : 
     970          23 :             pTextNd->SetListRestart(bFlag);
     971             : 
     972          23 :             getIDocumentState().SetModified();
     973             :         }
     974             :     }
     975          27 : }
     976             : 
     977          10 : void SwDoc::SetNodeNumStart( const SwPosition& rPos, sal_uInt16 nStt )
     978             : {
     979          10 :     SwTextNode* pTextNd = rPos.nNode.GetNode().GetTextNode();
     980             : 
     981          10 :     if (pTextNd)
     982             :     {
     983          10 :         if ( !pTextNd->HasAttrListRestartValue() ||
     984           0 :              pTextNd->GetAttrListRestartValue() != nStt )
     985             :         {
     986          10 :             if (GetIDocumentUndoRedo().DoesUndo())
     987             :             {
     988           2 :                 SwUndo *const pUndo( new SwUndoNumRuleStart(rPos, nStt) );
     989           2 :                 GetIDocumentUndoRedo().AppendUndo(pUndo);
     990             :             }
     991          10 :             pTextNd->SetAttrListRestartValue( nStt );
     992             : 
     993          10 :             getIDocumentState().SetModified();
     994             :         }
     995             :     }
     996          10 : }
     997             : 
     998             : // We can only delete if the Rule is unused!
     999          60 : bool SwDoc::DelNumRule( const OUString& rName, bool bBroadcast )
    1000             : {
    1001          60 :     sal_uInt16 nPos = FindNumRule( rName );
    1002             : 
    1003          60 :     if (nPos == USHRT_MAX)
    1004           0 :         return false;
    1005             : 
    1006          60 :     if ( (*mpNumRuleTable)[ nPos ] == GetOutlineNumRule() )
    1007             :     {
    1008             :         OSL_FAIL( "<SwDoc::DelNumRule(..)> - No deletion of outline list style. This is serious defect - please inform OD" );
    1009           0 :         return false;
    1010             :     }
    1011             : 
    1012          60 :     if( !IsUsed( *(*mpNumRuleTable)[ nPos ] ))
    1013             :     {
    1014          26 :         if (GetIDocumentUndoRedo().DoesUndo())
    1015             :         {
    1016             :             SwUndo * pUndo =
    1017           0 :                 new SwUndoNumruleDelete(*(*mpNumRuleTable)[nPos], this);
    1018           0 :             GetIDocumentUndoRedo().AppendUndo(pUndo);
    1019             :         }
    1020             : 
    1021          26 :         if (bBroadcast)
    1022             :             BroadcastStyleOperation(rName, SFX_STYLE_FAMILY_PSEUDO,
    1023           0 :                                     SfxStyleSheetHintId::ERASED);
    1024             : 
    1025          26 :         getIDocumentListsAccess().deleteListForListStyle( rName );
    1026          26 :         getIDocumentListsAccess().deleteListsByDefaultListStyle( rName );
    1027             :         // #i34097# DeleteAndDestroy deletes rName if
    1028             :         // rName is directly taken from the numrule.
    1029          26 :         const OUString aTmpName( rName );
    1030          26 :         delete (*mpNumRuleTable)[ nPos ];
    1031          26 :         mpNumRuleTable->erase( mpNumRuleTable->begin() + nPos );
    1032          26 :         maNumRuleMap.erase(aTmpName);
    1033             : 
    1034          26 :         getIDocumentState().SetModified();
    1035          26 :         return true;
    1036             :     }
    1037          34 :     return false;
    1038             : }
    1039             : 
    1040      297145 : void SwDoc::ChgNumRuleFormats( const SwNumRule& rRule )
    1041             : {
    1042      297145 :     SwNumRule* pRule = FindNumRulePtr( rRule.GetName() );
    1043      297145 :     if( pRule )
    1044             :     {
    1045      297145 :         SwUndoInsNum* pUndo = 0;
    1046      297145 :         if (GetIDocumentUndoRedo().DoesUndo())
    1047             :         {
    1048           0 :             pUndo = new SwUndoInsNum( *pRule, rRule );
    1049           0 :             pUndo->GetHistory();
    1050           0 :             GetIDocumentUndoRedo().AppendUndo( pUndo );
    1051             :         }
    1052      297145 :         ::lcl_ChgNumRule( *this, rRule );
    1053      297145 :         if (pUndo)
    1054             :         {
    1055           0 :             pUndo->SetLRSpaceEndPos();
    1056             :         }
    1057             : 
    1058      297145 :         getIDocumentState().SetModified();
    1059             :     }
    1060      297145 : }
    1061             : 
    1062           0 : bool SwDoc::RenameNumRule(const OUString & rOldName, const OUString & rNewName,
    1063             :                               bool bBroadcast)
    1064             : {
    1065           0 :     bool bResult = false;
    1066           0 :     SwNumRule * pNumRule = FindNumRulePtr(rOldName);
    1067             : 
    1068           0 :     if (pNumRule)
    1069             :     {
    1070           0 :         if (GetIDocumentUndoRedo().DoesUndo())
    1071             :         {
    1072           0 :             SwUndo * pUndo = new SwUndoNumruleRename(rOldName, rNewName, this);
    1073           0 :             GetIDocumentUndoRedo().AppendUndo(pUndo);
    1074             :         }
    1075             : 
    1076           0 :         SwNumRule::tTextNodeList aTextNodeList;
    1077           0 :         pNumRule->GetTextNodeList( aTextNodeList );
    1078             : 
    1079           0 :         pNumRule->SetName( rNewName, getIDocumentListsAccess() );
    1080             : 
    1081           0 :         SwNumRuleItem aItem(rNewName);
    1082             : 
    1083           0 :         for ( SwNumRule::tTextNodeList::iterator aIter = aTextNodeList.begin();
    1084           0 :               aIter != aTextNodeList.end(); ++aIter )
    1085             :         {
    1086           0 :             SwTextNode * pTextNd = *aIter;
    1087           0 :             pTextNd->SetAttr(aItem);
    1088             :         }
    1089             : 
    1090           0 :         bResult = true;
    1091             : 
    1092           0 :         if (bBroadcast)
    1093             :             BroadcastStyleOperation(rOldName, SFX_STYLE_FAMILY_PSEUDO,
    1094           0 :                                     SfxStyleSheetHintId::MODIFIED);
    1095             :     }
    1096             : 
    1097           0 :     return bResult;
    1098             : }
    1099             : 
    1100        2757 : void SwDoc::StopNumRuleAnimations( OutputDevice* pOut )
    1101             : {
    1102       27271 :     for( sal_uInt16 n = GetNumRuleTable().size(); n; )
    1103             :     {
    1104       21757 :         SwNumRule::tTextNodeList aTextNodeList;
    1105       21757 :         GetNumRuleTable()[ --n ]->GetTextNodeList( aTextNodeList );
    1106       74322 :         for ( SwNumRule::tTextNodeList::iterator aTextNodeIter = aTextNodeList.begin();
    1107       49548 :               aTextNodeIter != aTextNodeList.end(); ++aTextNodeIter )
    1108             :         {
    1109        3017 :             SwTextNode* pTNd = *aTextNodeIter;
    1110        3017 :             SwIterator<SwTextFrm,SwTextNode> aIter(*pTNd);
    1111        5999 :             for(SwTextFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
    1112        2982 :                 if( pFrm->HasAnimation() )
    1113           0 :                     pFrm->StopAnimation( pOut );
    1114        3017 :         }
    1115       21757 :     }
    1116        2757 : }
    1117             : 
    1118           0 : bool SwDoc::ReplaceNumRule( const SwPosition& rPos,
    1119             :                             const OUString& rOldRule, const OUString& rNewRule )
    1120             : {
    1121           0 :     bool bRet = false;
    1122           0 :     SwNumRule *pOldRule = FindNumRulePtr( rOldRule ),
    1123           0 :               *pNewRule = FindNumRulePtr( rNewRule );
    1124           0 :     if( pOldRule && pNewRule && pOldRule != pNewRule )
    1125             :     {
    1126           0 :         SwUndoInsNum* pUndo = 0;
    1127           0 :         if (GetIDocumentUndoRedo().DoesUndo())
    1128             :         {
    1129             :             // Start/End for attributes!
    1130           0 :             GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
    1131           0 :             pUndo = new SwUndoInsNum( rPos, *pNewRule, rOldRule );
    1132           0 :             GetIDocumentUndoRedo().AppendUndo(pUndo);
    1133             :         }
    1134             : 
    1135           0 :         SwNumRule::tTextNodeList aTextNodeList;
    1136           0 :         pOldRule->GetTextNodeList( aTextNodeList );
    1137           0 :         if ( aTextNodeList.size() > 0 )
    1138             :         {
    1139           0 :             SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 );
    1140           0 :             sal_uInt16 nChgFormatLevel = 0;
    1141           0 :             for( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
    1142             :             {
    1143           0 :                 const SwNumFormat& rOldFormat = pOldRule->Get( n ),
    1144           0 :                     & rNewFormat = pNewRule->Get( n );
    1145             : 
    1146           0 :                 if( rOldFormat.GetAbsLSpace() != rNewFormat.GetAbsLSpace() ||
    1147           0 :                     rOldFormat.GetFirstLineOffset() != rNewFormat.GetFirstLineOffset() )
    1148           0 :                     nChgFormatLevel |= ( 1 << n );
    1149             :             }
    1150             : 
    1151           0 :             const SwTextNode* pGivenTextNode = rPos.nNode.GetNode().GetTextNode();
    1152           0 :             SwNumRuleItem aRule( rNewRule );
    1153           0 :             for ( SwNumRule::tTextNodeList::iterator aIter = aTextNodeList.begin();
    1154           0 :                   aIter != aTextNodeList.end(); ++aIter )
    1155             :             {
    1156           0 :                 SwTextNode* pTextNd = *aIter;
    1157             : 
    1158           0 :                 if ( pGivenTextNode &&
    1159           0 :                      pGivenTextNode->GetListId() == pTextNd->GetListId() )
    1160             :                 {
    1161           0 :                     aRegH.RegisterInModify( pTextNd, *pTextNd );
    1162             : 
    1163           0 :                     pTextNd->SetAttr( aRule );
    1164           0 :                     pTextNd->NumRuleChgd();
    1165             :                 }
    1166             :             }
    1167           0 :             GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
    1168           0 :             getIDocumentState().SetModified();
    1169             : 
    1170           0 :             bRet = true;
    1171           0 :         }
    1172             :     }
    1173             : 
    1174           0 :     return bRet;
    1175             : }
    1176             : 
    1177             : namespace
    1178             : {
    1179         120 :     struct ListStyleData
    1180             :     {
    1181             :         SwNumRule* pReplaceNumRule;
    1182             :         bool bCreateNewList;
    1183             :         OUString sListId;
    1184             : 
    1185          20 :         ListStyleData()
    1186             :             : pReplaceNumRule( 0 ),
    1187             :               bCreateNewList( false ),
    1188          20 :               sListId()
    1189          20 :         {}
    1190             :     };
    1191             : }
    1192             : 
    1193          92 : void SwDoc::MakeUniqueNumRules(const SwPaM & rPaM)
    1194             : {
    1195             :     OSL_ENSURE( rPaM.GetDoc() == this, "need same doc" );
    1196             : 
    1197          92 :     ::std::map<SwNumRule *, ListStyleData> aMyNumRuleMap;
    1198             : 
    1199          92 :     bool bFirst = true;
    1200             : 
    1201          92 :     const sal_uLong nStt = rPaM.Start()->nNode.GetIndex();
    1202          92 :     const sal_uLong nEnd = rPaM.End()->nNode.GetIndex();
    1203         479 :     for (sal_uLong n = nStt; n <= nEnd; n++)
    1204             :     {
    1205         387 :         SwTextNode * pCNd = GetNodes()[n]->GetTextNode();
    1206             : 
    1207         387 :         if (pCNd)
    1208             :         {
    1209         373 :             SwNumRule * pRule = pCNd->GetNumRule();
    1210             : 
    1211         373 :             if (pRule && pRule->IsAutoRule() && ! pRule->IsOutlineRule())
    1212             :             {
    1213          40 :                 ListStyleData aListStyleData = aMyNumRuleMap[pRule];
    1214             : 
    1215          40 :                 if ( aListStyleData.pReplaceNumRule == 0 )
    1216             :                 {
    1217          20 :                     if (bFirst)
    1218             :                     {
    1219          20 :                         SwPosition aPos(*pCNd);
    1220             :                         aListStyleData.pReplaceNumRule =
    1221             :                             const_cast<SwNumRule *>
    1222          20 :                             (SearchNumRule( aPos, false, pCNd->HasNumber(),
    1223             :                                             false, 0,
    1224          20 :                                             aListStyleData.sListId, true ));
    1225             :                     }
    1226             : 
    1227          20 :                     if ( aListStyleData.pReplaceNumRule == 0 )
    1228             :                     {
    1229           0 :                         aListStyleData.pReplaceNumRule = new SwNumRule(*pRule);
    1230           0 :                         aListStyleData.pReplaceNumRule->SetName( GetUniqueNumRuleName(), getIDocumentListsAccess() );
    1231           0 :                         aListStyleData.bCreateNewList = true;
    1232             :                     }
    1233             : 
    1234          20 :                     aMyNumRuleMap[pRule] = aListStyleData;
    1235             :                 }
    1236             : 
    1237          80 :                 SwPaM aPam(*pCNd);
    1238             : 
    1239             :                 SetNumRule( aPam,
    1240             :                             *aListStyleData.pReplaceNumRule,
    1241             :                             aListStyleData.bCreateNewList,
    1242          40 :                             aListStyleData.sListId );
    1243          40 :                 if ( aListStyleData.bCreateNewList )
    1244             :                 {
    1245           0 :                     aListStyleData.bCreateNewList = false;
    1246           0 :                     aListStyleData.sListId = pCNd->GetListId();
    1247           0 :                     aMyNumRuleMap[pRule] = aListStyleData;
    1248             :                 }
    1249             : 
    1250          80 :                 bFirst = false;
    1251             :             }
    1252             :         }
    1253          92 :     }
    1254          92 : }
    1255             : 
    1256           0 : bool SwDoc::NoNum( const SwPaM& rPam )
    1257             : {
    1258             : 
    1259           0 :     bool bRet = getIDocumentContentOperations().SplitNode( *rPam.GetPoint(), false );
    1260             :     // Do we actually use Numbering at all?
    1261           0 :     if( bRet )
    1262             :     {
    1263             :         // Set NoNum and Upate
    1264           0 :         const SwNodeIndex& rIdx = rPam.GetPoint()->nNode;
    1265           0 :         SwTextNode* pNd = rIdx.GetNode().GetTextNode();
    1266           0 :         const SwNumRule* pRule = pNd->GetNumRule();
    1267           0 :         if( pRule )
    1268             :         {
    1269           0 :             pNd->SetCountedInList(false);
    1270             : 
    1271           0 :             getIDocumentState().SetModified();
    1272             :         }
    1273             :         else
    1274           0 :             bRet = false;   // no Numbering or just always true?
    1275             :     }
    1276           0 :     return bRet;
    1277             : }
    1278             : 
    1279           0 : void SwDoc::DelNumRules( const SwPaM& rPam )
    1280             : {
    1281           0 :     sal_uLong nStt = rPam.GetPoint()->nNode.GetIndex(),
    1282           0 :             nEnd = rPam.GetMark()->nNode.GetIndex();
    1283           0 :     if( nStt > nEnd )
    1284             :     {
    1285           0 :         sal_uLong nTmp = nStt; nStt = nEnd; nEnd = nTmp;
    1286             :     }
    1287             : 
    1288             :     SwUndoDelNum* pUndo;
    1289           0 :     if (GetIDocumentUndoRedo().DoesUndo())
    1290             :     {
    1291           0 :         pUndo = new SwUndoDelNum( rPam );
    1292           0 :         GetIDocumentUndoRedo().AppendUndo(pUndo);
    1293             :     }
    1294             :     else
    1295           0 :         pUndo = 0;
    1296             : 
    1297           0 :     SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 );
    1298             : 
    1299           0 :     SwNumRuleItem aEmptyRule( aEmptyOUStr );
    1300           0 :     const SwNode* pOutlNd = 0;
    1301           0 :     for( ; nStt <= nEnd; ++nStt )
    1302             :     {
    1303           0 :         SwTextNode* pTNd = GetNodes()[ nStt ]->GetTextNode();
    1304           0 :         SwNumRule* pNumRuleOfTextNode = pTNd ? pTNd->GetNumRule() : 0;
    1305           0 :         if ( pTNd && pNumRuleOfTextNode )
    1306             :         {
    1307             :             // recognize changes of attribute for undo
    1308           0 :             aRegH.RegisterInModify( pTNd, *pTNd );
    1309             : 
    1310           0 :             if( pUndo )
    1311           0 :                 pUndo->AddNode( *pTNd, false );
    1312             : 
    1313             :             // directly set list style attribute is reset, otherwise empty
    1314             :             // list style is applied
    1315           0 :             const SfxItemSet* pAttrSet = pTNd->GetpSwAttrSet();
    1316           0 :             if ( pAttrSet &&
    1317           0 :                  pAttrSet->GetItemState( RES_PARATR_NUMRULE, false ) == SfxItemState::SET )
    1318           0 :                 pTNd->ResetAttr( RES_PARATR_NUMRULE );
    1319             :             else
    1320           0 :                 pTNd->SetAttr( aEmptyRule );
    1321             : 
    1322           0 :             pTNd->ResetAttr( RES_PARATR_LIST_ID );
    1323           0 :             pTNd->ResetAttr( RES_PARATR_LIST_LEVEL );
    1324           0 :             pTNd->ResetAttr( RES_PARATR_LIST_ISRESTART );
    1325           0 :             pTNd->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
    1326           0 :             pTNd->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
    1327             : 
    1328           0 :             if( RES_CONDTXTFMTCOLL == pTNd->GetFormatColl()->Which() )
    1329             :             {
    1330           0 :                 pTNd->ChkCondColl();
    1331             :             }
    1332           0 :             else if( !pOutlNd &&
    1333           0 :                      static_cast<SwTextFormatColl*>(pTNd->GetFormatColl())->IsAssignedToListLevelOfOutlineStyle() )
    1334             :             {
    1335           0 :                 pOutlNd = pTNd;
    1336             :             }
    1337             :         }
    1338             :     }
    1339             : 
    1340             :     // Finally, update all
    1341           0 :     UpdateNumRule();
    1342             : 
    1343           0 :     if( pOutlNd )
    1344           0 :         GetNodes().UpdateOutlineIdx( *pOutlNd );
    1345           0 : }
    1346             : 
    1347         440 : void SwDoc::InvalidateNumRules()
    1348             : {
    1349        1886 :     for (size_t n = 0; n < mpNumRuleTable->size(); ++n)
    1350        1446 :         (*mpNumRuleTable)[n]->SetInvalidRule(true);
    1351         440 : }
    1352             : 
    1353             : // To the next/preceding Bullet at the same Level
    1354           0 : static bool lcl_IsNumOk( sal_uInt8 nSrchNum, sal_uInt8& rLower, sal_uInt8& rUpper,
    1355             :                     bool bOverUpper, sal_uInt8 nNumber )
    1356             : {
    1357             :     OSL_ENSURE( nNumber < MAXLEVEL,
    1358             :             "<lcl_IsNumOk(..)> - misusage of method" );
    1359             : 
    1360           0 :     bool bRet = false;
    1361             :     {
    1362           0 :         if( bOverUpper ? nSrchNum == nNumber : nSrchNum >= nNumber )
    1363           0 :             bRet = true;
    1364           0 :         else if( nNumber > rLower )
    1365           0 :             rLower = nNumber;
    1366           0 :         else if( nNumber < rUpper )
    1367           0 :             rUpper = nNumber;
    1368             :     }
    1369           0 :     return bRet;
    1370             : }
    1371             : 
    1372           0 : static bool lcl_IsValidPrevNextNumNode( const SwNodeIndex& rIdx )
    1373             : {
    1374           0 :     bool bRet = false;
    1375           0 :     const SwNode& rNd = rIdx.GetNode();
    1376           0 :     switch( rNd.GetNodeType() )
    1377             :     {
    1378             :     case ND_ENDNODE:
    1379           0 :         bRet = SwTableBoxStartNode == rNd.StartOfSectionNode()->GetStartNodeType() ||
    1380           0 :                 rNd.StartOfSectionNode()->IsSectionNode();
    1381           0 :         break;
    1382             : 
    1383             :     case ND_STARTNODE:
    1384           0 :         bRet = SwTableBoxStartNode == static_cast<const SwStartNode&>(rNd).GetStartNodeType();
    1385           0 :         break;
    1386             : 
    1387             :     case ND_SECTIONNODE:            // that one's valid, so proceed
    1388           0 :         bRet = true;
    1389           0 :         break;
    1390             :     }
    1391           0 :     return bRet;
    1392             : }
    1393             : 
    1394           0 : static bool lcl_GotoNextPrevNum( SwPosition& rPos, bool bNext,
    1395             :                             bool bOverUpper, sal_uInt8* pUpper, sal_uInt8* pLower )
    1396             : {
    1397           0 :     const SwTextNode* pNd = rPos.nNode.GetNode().GetTextNode();
    1398           0 :     if( !pNd || 0 == pNd->GetNumRule() )
    1399           0 :         return false;
    1400             : 
    1401           0 :     sal_uInt8 nSrchNum = static_cast<sal_uInt8>(pNd->GetActualListLevel());
    1402             : 
    1403           0 :     SwNodeIndex aIdx( rPos.nNode );
    1404           0 :     if( ! pNd->IsCountedInList() )
    1405             :     {
    1406             :         // If NO_NUMLEVEL is switched on, we search the preceding Node with Numbering
    1407           0 :         bool bError = false;
    1408           0 :         do {
    1409           0 :             --aIdx;
    1410           0 :             if( aIdx.GetNode().IsTextNode() )
    1411             :             {
    1412           0 :                 pNd = aIdx.GetNode().GetTextNode();
    1413           0 :                 const SwNumRule* pRule = pNd->GetNumRule();
    1414             : 
    1415             :                 sal_uInt8 nTmpNum;
    1416             : 
    1417           0 :                 if( pRule  )
    1418             :                 {
    1419           0 :                     nTmpNum = static_cast<sal_uInt8>(pNd->GetActualListLevel());
    1420           0 :                     if( !( ! pNd->IsCountedInList() &&
    1421           0 :                          (nTmpNum >= nSrchNum )) )
    1422           0 :                         break;      // found it!
    1423             :                 }
    1424             :                 else
    1425           0 :                     bError = true;
    1426             :             }
    1427             :             else
    1428           0 :                 bError = !lcl_IsValidPrevNextNumNode( aIdx );
    1429             : 
    1430           0 :         } while( !bError );
    1431           0 :         if( bError )
    1432           0 :             return false;
    1433             :     }
    1434             : 
    1435           0 :     sal_uInt8 nLower = nSrchNum, nUpper = nSrchNum;
    1436           0 :     bool bRet = false;
    1437             : 
    1438             :     const SwTextNode* pLast;
    1439           0 :     if( bNext )
    1440           0 :         ++aIdx, pLast = pNd;
    1441             :     else
    1442           0 :         --aIdx, pLast = 0;
    1443             : 
    1444           0 :     while( bNext ? ( aIdx.GetIndex() < aIdx.GetNodes().Count() - 1 )
    1445           0 :                  : aIdx.GetIndex() != 0 )
    1446             :     {
    1447           0 :         if( aIdx.GetNode().IsTextNode() )
    1448             :         {
    1449           0 :             pNd = aIdx.GetNode().GetTextNode();
    1450           0 :             const SwNumRule* pRule = pNd->GetNumRule();
    1451           0 :             if( pRule )
    1452             :             {
    1453           0 :                 if( ::lcl_IsNumOk( nSrchNum, nLower, nUpper, bOverUpper,
    1454           0 :                                     static_cast<sal_uInt8>(pNd->GetActualListLevel()) ))
    1455             :                 {
    1456           0 :                     rPos.nNode = aIdx;
    1457           0 :                     rPos.nContent.Assign( const_cast<SwTextNode*>(pNd), 0 );
    1458           0 :                     bRet = true;
    1459           0 :                     break;
    1460             :                 }
    1461             :                 else
    1462           0 :                     pLast = pNd;
    1463             :             }
    1464             :             else
    1465           0 :                 break;
    1466             :         }
    1467           0 :         else if( !lcl_IsValidPrevNextNumNode( aIdx ))
    1468           0 :             break;
    1469             : 
    1470           0 :         if( bNext )
    1471           0 :             ++aIdx;
    1472             :         else
    1473           0 :             --aIdx;
    1474             :     }
    1475             : 
    1476           0 :     if( !bRet && !bOverUpper && pLast )     // do not iterate over higher numbers, but still to the end
    1477             :     {
    1478           0 :         if( bNext )
    1479             :         {
    1480           0 :             rPos.nNode = aIdx;
    1481           0 :             if( aIdx.GetNode().IsContentNode() )
    1482           0 :                 rPos.nContent.Assign( aIdx.GetNode().GetContentNode(), 0 );
    1483             :         }
    1484             :         else
    1485             :         {
    1486           0 :             rPos.nNode.Assign( *pLast );
    1487           0 :             rPos.nContent.Assign( const_cast<SwTextNode*>(pLast), 0 );
    1488             :         }
    1489           0 :         bRet = true;
    1490             :     }
    1491             : 
    1492           0 :     if( bRet )
    1493             :     {
    1494           0 :         if( pUpper )
    1495           0 :             *pUpper = nUpper;
    1496           0 :         if( pLower )
    1497           0 :             *pLower = nLower;
    1498             :     }
    1499           0 :     return bRet;
    1500             : }
    1501             : 
    1502           0 : bool SwDoc::GotoNextNum( SwPosition& rPos, bool bOverUpper,
    1503             :                             sal_uInt8* pUpper, sal_uInt8* pLower  )
    1504             : {
    1505           0 :    return ::lcl_GotoNextPrevNum( rPos, true, bOverUpper, pUpper, pLower );
    1506             : }
    1507             : 
    1508         610 : const SwNumRule *  SwDoc::SearchNumRule(const SwPosition & rPos,
    1509             :                                         const bool bForward,
    1510             :                                         const bool bNum,
    1511             :                                         const bool bOutline,
    1512             :                                         int nNonEmptyAllowed,
    1513             :                                         OUString& sListId,
    1514             :                                         const bool bInvestigateStartNode)
    1515             : {
    1516         610 :     const SwNumRule * pResult = NULL;
    1517         610 :     SwTextNode * pTextNd = rPos.nNode.GetNode().GetTextNode();
    1518         610 :     SwNode * pStartFromNode = pTextNd;
    1519             : 
    1520         610 :     if (pTextNd)
    1521             :     {
    1522         428 :         SwNodeIndex aIdx(rPos.nNode);
    1523             : 
    1524             :         // - the start node has also been investigated, if requested.
    1525         428 :         const SwNode * pNode = NULL;
    1526        1870 :         do
    1527             :         {
    1528        2198 :             if ( !bInvestigateStartNode )
    1529             :             {
    1530           0 :                 if (bForward)
    1531           0 :                     ++aIdx;
    1532             :                 else
    1533           0 :                     --aIdx;
    1534             :             }
    1535             : 
    1536        2198 :             if (aIdx.GetNode().IsTextNode())
    1537             :             {
    1538         986 :                 pTextNd = aIdx.GetNode().GetTextNode();
    1539             : 
    1540         986 :                 const SwNumRule * pNumRule = pTextNd->GetNumRule();
    1541         986 :                 if (pNumRule)
    1542             :                 {
    1543          46 :                     if ( ( pNumRule->IsOutlineRule() == bOutline ) &&
    1544          26 :                          ( ( bNum && pNumRule->Get(0).IsEnumeration()) ||
    1545          46 :                            ( !bNum && pNumRule->Get(0).IsItemize() ) ) ) // #i22362#, #i29560#
    1546             :                     {
    1547          22 :                         pResult = pTextNd->GetNumRule();
    1548             :                         // provide also the list id, to which the text node belongs.
    1549          22 :                         sListId = pTextNd->GetListId();
    1550             :                     }
    1551             : 
    1552          24 :                     break;
    1553             :                 }
    1554         962 :                 else if (pTextNd->Len() > 0 || NULL != pTextNd->GetNumRule())
    1555             :                 {
    1556         304 :                     if (nNonEmptyAllowed == 0)
    1557         304 :                         break;
    1558             : 
    1559           0 :                     nNonEmptyAllowed--;
    1560             : 
    1561           0 :                     if (nNonEmptyAllowed < 0)
    1562           0 :                         nNonEmptyAllowed = -1;
    1563             :                 }
    1564             :             }
    1565             : 
    1566        1870 :             if ( bInvestigateStartNode )
    1567             :             {
    1568        1870 :                 if (bForward)
    1569           0 :                     ++aIdx;
    1570             :                 else
    1571        1870 :                     --aIdx;
    1572             :             }
    1573             : 
    1574        1870 :             pNode = &aIdx.GetNode();
    1575             :         }
    1576        1870 :         while (!(pNode == GetNodes().DocumentSectionStartNode(pStartFromNode) ||
    1577        2298 :                  pNode == GetNodes().DocumentSectionEndNode(pStartFromNode)));
    1578             :     }
    1579             : 
    1580         610 :     return pResult;
    1581             : }
    1582             : 
    1583           0 : bool SwDoc::GotoPrevNum( SwPosition& rPos, bool bOverUpper,
    1584             :                             sal_uInt8* pUpper, sal_uInt8* pLower  )
    1585             : {
    1586           0 :    return ::lcl_GotoNextPrevNum( rPos, false, bOverUpper, pUpper, pLower );
    1587             : }
    1588             : 
    1589           0 : bool SwDoc::NumUpDown( const SwPaM& rPam, bool bDown )
    1590             : {
    1591           0 :     sal_uLong nStt = rPam.GetPoint()->nNode.GetIndex(),
    1592           0 :             nEnd = rPam.GetMark()->nNode.GetIndex();
    1593           0 :     if( nStt > nEnd )
    1594             :     {
    1595           0 :         sal_uLong nTmp = nStt; nStt = nEnd; nEnd = nTmp;
    1596             :     }
    1597             : 
    1598             :     // -> outline nodes are promoted or demoted differently
    1599           0 :     bool bOnlyOutline = true;
    1600           0 :     bool bOnlyNonOutline = true;
    1601           0 :     for (sal_uLong n = nStt; n <= nEnd; n++)
    1602             :     {
    1603           0 :         SwTextNode * pTextNd = GetNodes()[n]->GetTextNode();
    1604             : 
    1605           0 :         if (pTextNd)
    1606             :         {
    1607           0 :             SwNumRule * pRule = pTextNd->GetNumRule();
    1608             : 
    1609           0 :             if (pRule)
    1610             :             {
    1611           0 :                 if (pRule->IsOutlineRule())
    1612           0 :                     bOnlyNonOutline = false;
    1613             :                 else
    1614           0 :                     bOnlyOutline = false;
    1615             :             }
    1616             :         }
    1617             :     }
    1618             : 
    1619           0 :     bool bRet = true;
    1620           0 :     sal_Int8 nDiff = bDown ? 1 : -1;
    1621             : 
    1622           0 :     if (bOnlyOutline)
    1623           0 :         bRet = OutlineUpDown(rPam, nDiff);
    1624           0 :     else if (bOnlyNonOutline)
    1625             :     {
    1626             :         /* #i24560#
    1627             :         Only promote or demote if all selected paragraphs are
    1628             :         promotable resp. demotable.
    1629             :         */
    1630           0 :         for (sal_uLong nTmp = nStt; nTmp <= nEnd; ++nTmp)
    1631             :         {
    1632           0 :             SwTextNode* pTNd = GetNodes()[ nTmp ]->GetTextNode();
    1633             : 
    1634             :             // Make code robust: consider case that the node doesn't denote a
    1635             :             // text node.
    1636           0 :             if ( pTNd )
    1637             :             {
    1638           0 :                 SwNumRule * pRule = pTNd->GetNumRule();
    1639             : 
    1640           0 :                 if (pRule)
    1641             :                 {
    1642           0 :                     sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel());
    1643           0 :                     if( (-1 == nDiff && 0 >= nLevel) ||
    1644           0 :                         (1 == nDiff && MAXLEVEL - 1 <= nLevel))
    1645           0 :                         bRet = false;
    1646             :                 }
    1647             :             }
    1648             :         }
    1649             : 
    1650           0 :         if( bRet )
    1651             :         {
    1652           0 :             if (GetIDocumentUndoRedo().DoesUndo())
    1653             :             {
    1654           0 :                 SwUndo *const pUndo( new SwUndoNumUpDown(rPam, nDiff) );
    1655           0 :                 GetIDocumentUndoRedo().AppendUndo(pUndo);
    1656             :             }
    1657             : 
    1658           0 :             for(sal_uLong nTmp = nStt; nTmp <= nEnd; ++nTmp )
    1659             :             {
    1660           0 :                 SwTextNode* pTNd = GetNodes()[ nTmp ]->GetTextNode();
    1661             : 
    1662           0 :                 if( pTNd)
    1663             :                 {
    1664           0 :                     SwNumRule * pRule = pTNd->GetNumRule();
    1665             : 
    1666           0 :                     if (pRule)
    1667             :                     {
    1668           0 :                         sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel());
    1669           0 :                         nLevel = nLevel + nDiff;
    1670             : 
    1671           0 :                         pTNd->SetAttrListLevel(nLevel);
    1672             :                     }
    1673             :                 }
    1674             :             }
    1675             : 
    1676           0 :             ChkCondColls();
    1677           0 :             getIDocumentState().SetModified();
    1678             :         }
    1679             :     }
    1680             : 
    1681           0 :     return bRet;
    1682             : }
    1683             : 
    1684           0 : bool SwDoc::MoveParagraph( const SwPaM& rPam, long nOffset, bool bIsOutlMv )
    1685             : {
    1686           0 :     const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
    1687             : 
    1688           0 :     sal_uLong nStIdx = pStt->nNode.GetIndex();
    1689           0 :     sal_uLong nEndIdx = pEnd->nNode.GetIndex();
    1690             : 
    1691             :     // Here are some sophisticated checks whether the wished PaM will be moved or not.
    1692             :     // For moving outlines (bIsOutlMv) I've already done some checks, so here are two different
    1693             :     // checks...
    1694             :     SwNode *pTmp1;
    1695             :     SwNode *pTmp2;
    1696           0 :     if( bIsOutlMv )
    1697             :     {
    1698             :         // For moving chapters (outline) the following reason will deny the move:
    1699             :         // if a start node is inside the moved range and its end node outside or vice versa.
    1700             :         // If a start node is the first moved paragraph, its end node has to be within the moved
    1701             :         // range, too (e.g. as last node).
    1702             :         // If an end node is the last node of the moved range, its start node has to be a part of
    1703             :         // the moved section, too.
    1704           0 :         pTmp1 = GetNodes()[ nStIdx ];
    1705           0 :         if( pTmp1->IsStartNode() )
    1706             :         {   // First is a start node
    1707           0 :             pTmp2 = pTmp1->EndOfSectionNode();
    1708           0 :             if( pTmp2->GetIndex() > nEndIdx )
    1709           0 :                 return false; // Its end node is behind the moved range
    1710             :         }
    1711           0 :         pTmp1 = pTmp1->StartOfSectionNode()->EndOfSectionNode();
    1712           0 :         if( pTmp1->GetIndex() <= nEndIdx )
    1713           0 :             return false; // End node inside but start node before moved range => no.
    1714           0 :         pTmp1 = GetNodes()[ nEndIdx ];
    1715           0 :         if( pTmp1->IsEndNode() )
    1716             :         {   // The last one is an end node
    1717           0 :             pTmp1 = pTmp1->StartOfSectionNode();
    1718           0 :             if( pTmp1->GetIndex() < nStIdx )
    1719           0 :                 return false; // Its start node is before the moved range.
    1720             :         }
    1721           0 :         pTmp1 = pTmp1->StartOfSectionNode();
    1722           0 :         if( pTmp1->GetIndex() >= nStIdx )
    1723           0 :             return false; // A start node which ends behind the moved range => no.
    1724             :     }
    1725             : 
    1726             :     sal_uLong nInStIdx, nInEndIdx;
    1727           0 :     long nOffs = nOffset;
    1728           0 :     if( nOffset > 0 )
    1729             :     {
    1730           0 :         nInEndIdx = nEndIdx;
    1731           0 :         nEndIdx += nOffset;
    1732           0 :         ++nOffs;
    1733             :     }
    1734             :     else
    1735             :     {
    1736             :         // Impossible to move to negative index
    1737           0 :         if( sal_uLong(std::abs( nOffset )) > nStIdx)
    1738           0 :             return false;
    1739             : 
    1740           0 :         nInEndIdx = nStIdx - 1;
    1741           0 :         nStIdx += nOffset;
    1742             :     }
    1743           0 :     nInStIdx = nInEndIdx + 1;
    1744             :     // The following paragraphs shall be swapped:
    1745             :     // Swap [ nStIdx, nInEndIdx ] with [ nInStIdx, nEndIdx ]
    1746             : 
    1747           0 :     if( nEndIdx >= GetNodes().GetEndOfContent().GetIndex() )
    1748           0 :         return false;
    1749             : 
    1750           0 :     if( !bIsOutlMv )
    1751             :     {   // And here the restrictions for moving paragraphs other than chapters (outlines)
    1752             :         // The plan is to exchange [nStIdx,nInEndIdx] and [nStartIdx,nEndIdx]
    1753             :         // It will checked if the both "start" nodes as well as the both "end" notes belongs to
    1754             :         // the same start-end-section. This is more restrictive than the conditions checked above.
    1755             :         // E.g. a paragraph will not escape from a section or be inserted to another section.
    1756           0 :         pTmp1 = GetNodes()[ nStIdx ]->StartOfSectionNode();
    1757           0 :         pTmp2 = GetNodes()[ nInStIdx ]->StartOfSectionNode();
    1758           0 :         if( pTmp1 != pTmp2 )
    1759           0 :             return false; // "start" nodes in different sections
    1760           0 :         pTmp1 = GetNodes()[ nEndIdx ];
    1761           0 :         bool bIsEndNode = pTmp1->IsEndNode();
    1762           0 :         if( !pTmp1->IsStartNode() )
    1763             :         {
    1764           0 :             pTmp1 = pTmp1->StartOfSectionNode();
    1765           0 :             if( bIsEndNode ) // For end nodes the first start node is of course inside the range,
    1766           0 :                 pTmp1 = pTmp1->StartOfSectionNode(); // I've to check the start node of the start node.
    1767             :         }
    1768           0 :         pTmp1 = pTmp1->EndOfSectionNode();
    1769           0 :         pTmp2 = GetNodes()[ nInEndIdx ];
    1770           0 :         if( !pTmp2->IsStartNode() )
    1771             :         {
    1772           0 :             bIsEndNode = pTmp2->IsEndNode();
    1773           0 :             pTmp2 = pTmp2->StartOfSectionNode();
    1774           0 :             if( bIsEndNode )
    1775           0 :                 pTmp2 = pTmp2->StartOfSectionNode();
    1776             :         }
    1777           0 :         pTmp2 = pTmp2->EndOfSectionNode();
    1778           0 :         if( pTmp1 != pTmp2 )
    1779           0 :             return false; // The "end" notes are in different sections
    1780             :     }
    1781             : 
    1782             :     // Test for Redlining - Can the Selection be moved at all, actually?
    1783           0 :     if( !getIDocumentRedlineAccess().IsIgnoreRedline() )
    1784             :     {
    1785           0 :         sal_uInt16 nRedlPos = getIDocumentRedlineAccess().GetRedlinePos( pStt->nNode.GetNode(), nsRedlineType_t::REDLINE_DELETE );
    1786           0 :         if( USHRT_MAX != nRedlPos )
    1787             :         {
    1788           0 :             SwPosition aStPos( *pStt ), aEndPos( *pEnd );
    1789           0 :             aStPos.nContent = 0;
    1790           0 :             SwContentNode* pCNd = pEnd->nNode.GetNode().GetContentNode();
    1791           0 :             aEndPos.nContent = pCNd ? pCNd->Len() : 1;
    1792           0 :             bool bCheckDel = true;
    1793             : 
    1794             :             // There is a some Redline Delete Object for the range
    1795           0 :             for( ; nRedlPos < getIDocumentRedlineAccess().GetRedlineTable().size(); ++nRedlPos )
    1796             :             {
    1797           0 :                 const SwRangeRedline* pTmp = getIDocumentRedlineAccess().GetRedlineTable()[ nRedlPos ];
    1798           0 :                 if( !bCheckDel || nsRedlineType_t::REDLINE_DELETE == pTmp->GetType() )
    1799             :                 {
    1800           0 :                     const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
    1801           0 :                     switch( ComparePosition( *pRStt, *pREnd, aStPos, aEndPos ))
    1802             :                     {
    1803             :                     case POS_COLLIDE_START:
    1804             :                     case POS_BEHIND:            // Pos1 comes after Pos2
    1805           0 :                         nRedlPos = getIDocumentRedlineAccess().GetRedlineTable().size();
    1806           0 :                         break;
    1807             : 
    1808             :                     case POS_COLLIDE_END:
    1809             :                     case POS_BEFORE:            // Pos1 comes before Pos2
    1810           0 :                         break;
    1811             :                     case POS_INSIDE:            // Pos1 is completely inside Pos2
    1812             :                         // that's valid, but check all following for overlapping
    1813           0 :                         bCheckDel = false;
    1814           0 :                         break;
    1815             : 
    1816             :                     case POS_OUTSIDE:           // Pos2 is completely inside Pos1
    1817             :                     case POS_EQUAL:             // Pos1 is equal to Pos2
    1818             :                     case POS_OVERLAP_BEFORE:    // Pos1 overlaps Pos2 in the beginning
    1819             :                     case POS_OVERLAP_BEHIND:    // Pos1 overlaps Pos2 at the end
    1820           0 :                         return false;
    1821             :                     }
    1822             :                 }
    1823           0 :             }
    1824             :         }
    1825             :     }
    1826             : 
    1827             :     {
    1828             :         // Send DataChanged before moving. We then can detect
    1829             :         // which objects are still in the range.
    1830             :         // After the move they could come before/after the
    1831             :         // Position.
    1832           0 :         SwDataChanged aTmp( rPam );
    1833             :     }
    1834             : 
    1835           0 :     SwNodeIndex aIdx( nOffset > 0 ? pEnd->nNode : pStt->nNode, nOffs );
    1836           0 :     SwNodeRange aMvRg( pStt->nNode, 0, pEnd->nNode, +1 );
    1837             : 
    1838           0 :     SwRangeRedline* pOwnRedl = 0;
    1839           0 :     if( getIDocumentRedlineAccess().IsRedlineOn() )
    1840             :     {
    1841             :         // If the range is completely in the own Redline, we can move it!
    1842           0 :         sal_uInt16 nRedlPos = getIDocumentRedlineAccess().GetRedlinePos( pStt->nNode.GetNode(), nsRedlineType_t::REDLINE_INSERT );
    1843           0 :         if( USHRT_MAX != nRedlPos )
    1844             :         {
    1845           0 :             SwRangeRedline* pTmp = getIDocumentRedlineAccess().GetRedlineTable()[ nRedlPos ];
    1846           0 :             const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
    1847           0 :             SwRangeRedline aTmpRedl( nsRedlineType_t::REDLINE_INSERT, rPam );
    1848           0 :             const SwContentNode* pCEndNd = pEnd->nNode.GetNode().GetContentNode();
    1849             :             // Is completely in the range and is the own Redline too?
    1850           0 :             if( aTmpRedl.IsOwnRedline( *pTmp ) &&
    1851           0 :                 (pRStt->nNode < pStt->nNode ||
    1852           0 :                 (pRStt->nNode == pStt->nNode && !pRStt->nContent.GetIndex()) ) &&
    1853           0 :                 (pEnd->nNode < pREnd->nNode ||
    1854           0 :                 (pEnd->nNode == pREnd->nNode &&
    1855           0 :                  pCEndNd ? pREnd->nContent.GetIndex() == pCEndNd->Len()
    1856           0 :                          : !pREnd->nContent.GetIndex() )) )
    1857             :             {
    1858           0 :                 pOwnRedl = pTmp;
    1859           0 :                 if( nRedlPos + 1 < (sal_uInt16)getIDocumentRedlineAccess().GetRedlineTable().size() )
    1860             :                 {
    1861           0 :                     pTmp = getIDocumentRedlineAccess().GetRedlineTable()[ nRedlPos+1 ];
    1862           0 :                     if( *pTmp->Start() == *pREnd )
    1863             :                         // then don't!
    1864           0 :                         pOwnRedl = 0;
    1865             :                 }
    1866             : 
    1867           0 :                 if( pOwnRedl &&
    1868           0 :                     !( pRStt->nNode <= aIdx && aIdx <= pREnd->nNode ))
    1869             :                 {
    1870             :                     // it's not in itself, so don't move it
    1871           0 :                     pOwnRedl = 0;
    1872             :                 }
    1873           0 :             }
    1874             :         }
    1875             : 
    1876           0 :         if( !pOwnRedl )
    1877             :         {
    1878           0 :             GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
    1879             : 
    1880             :             // First the Insert, then the Delete
    1881           0 :             SwPosition aInsPos( aIdx );
    1882           0 :             aInsPos.nContent.Assign( aIdx.GetNode().GetContentNode(), 0 );
    1883             : 
    1884           0 :             SwPaM aPam( pStt->nNode, aMvRg.aEnd );
    1885             : 
    1886           0 :             SwPaM& rOrigPam = (SwPaM&)rPam;
    1887           0 :             rOrigPam.DeleteMark();
    1888           0 :             rOrigPam.GetPoint()->nNode = aIdx.GetIndex() - 1;
    1889             : 
    1890           0 :             bool bDelLastPara = !aInsPos.nNode.GetNode().IsContentNode();
    1891             : 
    1892             :             /* When copying to a non-content node Copy will
    1893             :                insert a paragraph before that node and insert before
    1894             :                that inserted node. Copy creates an SwUndoInserts that
    1895             :                does not cover the extra paragraph. Thus we insert the
    1896             :                extra paragraph ourselves, _with_ correct undo
    1897             :                information. */
    1898           0 :             if (bDelLastPara)
    1899             :             {
    1900             :                 /* aInsPos points to the non-content node. Move it to
    1901             :                    the previous content node. */
    1902           0 :                 SwPaM aInsPam(aInsPos);
    1903           0 :                 const bool bMoved = aInsPam.Move(fnMoveBackward);
    1904             :                 OSL_ENSURE(bMoved, "No content node found!");
    1905             : 
    1906           0 :                 if (bMoved)
    1907             :                 {
    1908             :                     /* Append the new node after the content node
    1909             :                        found. The new position to insert the moved
    1910             :                        paragraph at is before the inserted
    1911             :                        paragraph. */
    1912           0 :                     getIDocumentContentOperations().AppendTextNode(*aInsPam.GetPoint());
    1913           0 :                     aInsPos = *aInsPam.GetPoint();
    1914           0 :                 }
    1915             :             }
    1916             : 
    1917           0 :             getIDocumentContentOperations().CopyRange( aPam, aInsPos, /*bCopyAll=*/false, /*bCheckPos=*/true );
    1918           0 :             if( bDelLastPara )
    1919             :             {
    1920             :                 // We need to remove the last empty Node again
    1921           0 :                 aIdx = aInsPos.nNode;
    1922           0 :                 SwContentNode* pCNd = SwNodes::GoPrevious( &aInsPos.nNode );
    1923           0 :                 aInsPos.nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 );
    1924             : 
    1925             :                 // All, that are in the to-be-deleted Node, need to be
    1926             :                 // moved to the next Node
    1927           0 :                 for( size_t n = 0; n < getIDocumentRedlineAccess().GetRedlineTable().size(); ++n )
    1928             :                 {
    1929           0 :                     SwRangeRedline* pTmp = getIDocumentRedlineAccess().GetRedlineTable()[ n ];
    1930             : 
    1931             :                     SwPosition* pPos;
    1932           0 :                     if( ( pPos = &pTmp->GetBound(true))->nNode == aIdx )
    1933             :                     {
    1934           0 :                         ++pPos->nNode;
    1935           0 :                         pPos->nContent.Assign( pPos->nNode.GetNode().GetContentNode(),0);
    1936             :                     }
    1937           0 :                     if( ( pPos = &pTmp->GetBound(false))->nNode == aIdx )
    1938             :                     {
    1939           0 :                         ++pPos->nNode;
    1940           0 :                         pPos->nContent.Assign( pPos->nNode.GetNode().GetContentNode(),0);
    1941             :                     }
    1942             :                 }
    1943           0 :                 CorrRel( aIdx, aInsPos, 0, false );
    1944             : 
    1945           0 :                 if (pCNd)
    1946           0 :                     pCNd->JoinNext();
    1947             :             }
    1948             : 
    1949           0 :             ++rOrigPam.GetPoint()->nNode;
    1950           0 :             rOrigPam.GetPoint()->nContent.Assign( rOrigPam.GetContentNode(), 0 );
    1951             : 
    1952           0 :             RedlineMode_t eOld = getIDocumentRedlineAccess().GetRedlineMode();
    1953           0 :             GetDocumentRedlineManager().checkRedlining(eOld);
    1954           0 :             if (GetIDocumentUndoRedo().DoesUndo())
    1955             :             {
    1956             :                 // Still NEEDS to be optimized (even after 14 years)
    1957           0 :                 getIDocumentRedlineAccess().SetRedlineMode(
    1958           0 :                    (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE));
    1959           0 :                 SwUndo *const pUndo(new SwUndoRedlineDelete(aPam, UNDO_DELETE));
    1960           0 :                 GetIDocumentUndoRedo().AppendUndo(pUndo);
    1961             :             }
    1962             : 
    1963           0 :             SwRangeRedline* pNewRedline = new SwRangeRedline( nsRedlineType_t::REDLINE_DELETE, aPam );
    1964             : 
    1965             :             // prevent assertion from aPam's target being deleted
    1966             :             // (Alternatively, one could just let aPam go out of scope, but
    1967             :             // that requires touching a lot of code.)
    1968           0 :             aPam.GetBound(true).nContent.Assign( NULL, 0 );
    1969           0 :             aPam.GetBound(false).nContent.Assign( NULL, 0 );
    1970             : 
    1971           0 :             getIDocumentRedlineAccess().AppendRedline( pNewRedline, true );
    1972             : 
    1973             :             // Still NEEDS to be optimized!
    1974           0 :             getIDocumentRedlineAccess().SetRedlineMode( eOld );
    1975           0 :             GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
    1976           0 :             getIDocumentState().SetModified();
    1977             : 
    1978           0 :             return true;
    1979             :         }
    1980             :     }
    1981             : 
    1982           0 :     if( !pOwnRedl && !getIDocumentRedlineAccess().IsIgnoreRedline() && !getIDocumentRedlineAccess().GetRedlineTable().empty() )
    1983             :     {
    1984           0 :         SwPaM aTemp(aIdx);
    1985           0 :         getIDocumentRedlineAccess().SplitRedline(aTemp);
    1986             :     }
    1987             : 
    1988           0 :     sal_uLong nRedlSttNd(0), nRedlEndNd(0);
    1989           0 :     if( pOwnRedl )
    1990             :     {
    1991           0 :         const SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End();
    1992           0 :         nRedlSttNd = pRStt->nNode.GetIndex();
    1993           0 :         nRedlEndNd = pREnd->nNode.GetIndex();
    1994             :     }
    1995             : 
    1996           0 :     SwUndoMoveNum* pUndo = 0;
    1997           0 :     sal_uLong nMoved = 0;
    1998           0 :     if (GetIDocumentUndoRedo().DoesUndo())
    1999             :     {
    2000           0 :         pUndo = new SwUndoMoveNum( rPam, nOffset, bIsOutlMv );
    2001           0 :         nMoved = rPam.End()->nNode.GetIndex() - rPam.Start()->nNode.GetIndex() + 1;
    2002             :     }
    2003             : 
    2004           0 :     getIDocumentContentOperations().MoveNodeRange( aMvRg, aIdx, SwMoveFlags::REDLINES );
    2005             : 
    2006           0 :     if( pUndo )
    2007             :     {
    2008             :         // i57907: Under circumstances (sections at the end of a chapter)
    2009             :         // the rPam.Start() is not moved to the new position.
    2010             :         // But aIdx should be at the new end position and as long as the
    2011             :         // number of moved paragraphs is nMoved, I know, where the new
    2012             :         // position is.
    2013           0 :         pUndo->SetStartNode( aIdx.GetIndex() - nMoved );
    2014           0 :         GetIDocumentUndoRedo().AppendUndo(pUndo);
    2015             :     }
    2016             : 
    2017           0 :     if( pOwnRedl )
    2018             :     {
    2019           0 :         SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End();
    2020           0 :         if( pRStt->nNode.GetIndex() != nRedlSttNd )
    2021             :         {
    2022           0 :             pRStt->nNode = nRedlSttNd;
    2023           0 :             pRStt->nContent.Assign( pRStt->nNode.GetNode().GetContentNode(),0);
    2024             :         }
    2025           0 :         if( pREnd->nNode.GetIndex() != nRedlEndNd )
    2026             :         {
    2027           0 :             pREnd->nNode = nRedlEndNd;
    2028           0 :             SwContentNode* pCNd = pREnd->nNode.GetNode().GetContentNode();
    2029           0 :             pREnd->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 );
    2030             :         }
    2031             :     }
    2032             : 
    2033           0 :     getIDocumentState().SetModified();
    2034           0 :     return true;
    2035             : }
    2036             : 
    2037           0 : bool SwDoc::NumOrNoNum( const SwNodeIndex& rIdx, bool bDel )
    2038             : {
    2039           0 :     bool bResult = false;
    2040           0 :     SwTextNode * pTextNd = rIdx.GetNode().GetTextNode();
    2041             : 
    2042           0 :     if (pTextNd && pTextNd->GetNumRule() != NULL &&
    2043           0 :         (pTextNd->HasNumber() || pTextNd->HasBullet()))
    2044             :     {
    2045           0 :         if ( !pTextNd->IsCountedInList() == !bDel)
    2046             :         {
    2047           0 :             bool bOldNum = bDel;
    2048           0 :             bool bNewNum = !bDel;
    2049           0 :             pTextNd->SetCountedInList(bNewNum);
    2050             : 
    2051           0 :             getIDocumentState().SetModified();
    2052             : 
    2053           0 :             bResult = true;
    2054             : 
    2055           0 :             if (GetIDocumentUndoRedo().DoesUndo())
    2056             :             {
    2057             :                 SwUndoNumOrNoNum * pUndo =
    2058           0 :                     new SwUndoNumOrNoNum(rIdx, bOldNum, bNewNum);
    2059             : 
    2060           0 :                 GetIDocumentUndoRedo().AppendUndo(pUndo);
    2061             :             }
    2062             :         }
    2063           0 :         else if (bDel && pTextNd->GetNumRule(false) &&
    2064           0 :                  pTextNd->GetActualListLevel() >= 0 &&
    2065           0 :                  pTextNd->GetActualListLevel() < MAXLEVEL)
    2066             :         {
    2067           0 :             SwPaM aPam(*pTextNd);
    2068           0 :             DelNumRules(aPam);
    2069             : 
    2070           0 :             bResult = true;
    2071             :         }
    2072             :     }
    2073             : 
    2074           0 :     return bResult;
    2075             : }
    2076             : 
    2077       28316 : SwNumRule* SwDoc::GetNumRuleAtPos( const SwPosition& rPos )
    2078             : {
    2079       28316 :     SwNumRule* pRet = NULL;
    2080       28316 :     SwTextNode* pTNd = rPos.nNode.GetNode().GetTextNode();
    2081             : 
    2082       28316 :     if ( pTNd != NULL )
    2083             :     {
    2084       28314 :         pRet = pTNd->GetNumRule();
    2085             :     }
    2086             : 
    2087       28316 :     return pRet;
    2088             : }
    2089             : 
    2090          60 : sal_uInt16 SwDoc::FindNumRule( const OUString& rName ) const
    2091             : {
    2092         234 :     for( sal_uInt16 n = mpNumRuleTable->size(); n; )
    2093         174 :         if( (*mpNumRuleTable)[ --n ]->GetName() == rName )
    2094          60 :             return n;
    2095             : 
    2096           0 :     return USHRT_MAX;
    2097             : }
    2098             : 
    2099     1032192 : SwNumRule* SwDoc::FindNumRulePtr( const OUString& rName ) const
    2100             : {
    2101     1032192 :     SwNumRule * pResult = 0;
    2102             : 
    2103     1032192 :     pResult = maNumRuleMap[rName];
    2104             : 
    2105     1032192 :     if ( !pResult )
    2106             :     {
    2107    98632759 :         for (size_t n = 0; n < mpNumRuleTable->size(); ++n)
    2108             :         {
    2109    98556844 :             if ((*mpNumRuleTable)[n]->GetName() == rName)
    2110             :             {
    2111           0 :                 pResult = (*mpNumRuleTable)[n];
    2112             : 
    2113           0 :                 break;
    2114             :             }
    2115             :         }
    2116             :     }
    2117             : 
    2118     1032192 :     return pResult;
    2119             : }
    2120             : 
    2121       22610 : void SwDoc::AddNumRule(SwNumRule * pRule)
    2122             : {
    2123       22610 :     if ((SAL_MAX_UINT16 - 1) <= mpNumRuleTable->size())
    2124             :     {
    2125             :         OSL_ENSURE(false, "SwDoc::AddNumRule: table full.");
    2126           0 :         abort(); // this should never happen on real documents
    2127             :     }
    2128       22610 :     mpNumRuleTable->push_back(pRule);
    2129       22610 :     maNumRuleMap[pRule->GetName()] = pRule;
    2130       22610 :     pRule->SetNumRuleMap(&maNumRuleMap);
    2131             : 
    2132       22610 :     getIDocumentListsAccess().createListForListStyle( pRule->GetName() );
    2133       22610 : }
    2134             : 
    2135       19631 : sal_uInt16 SwDoc::MakeNumRule( const OUString &rName,
    2136             :             const SwNumRule* pCpy,
    2137             :             bool bBroadcast,
    2138             :             const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode )
    2139             : {
    2140             :     SwNumRule* pNew;
    2141       19631 :     if( pCpy )
    2142             :     {
    2143          26 :         pNew = new SwNumRule( *pCpy );
    2144             : 
    2145          26 :         pNew->SetName( GetUniqueNumRuleName( &rName ), getIDocumentListsAccess() );
    2146             : 
    2147          26 :         if( pNew->GetName() != rName )
    2148             :         {
    2149           0 :             pNew->SetPoolFormatId( USHRT_MAX );
    2150           0 :             pNew->SetPoolHelpId( USHRT_MAX );
    2151           0 :             pNew->SetPoolHlpFileId( UCHAR_MAX );
    2152           0 :             pNew->SetDefaultListId( OUString() );
    2153             :         }
    2154          26 :         pNew->CheckCharFormats( this );
    2155             :     }
    2156             :     else
    2157             :     {
    2158             :         pNew = new SwNumRule( GetUniqueNumRuleName( &rName ),
    2159       19605 :                               eDefaultNumberFormatPositionAndSpaceMode );
    2160             :     }
    2161             : 
    2162       19631 :     sal_uInt16 nRet = mpNumRuleTable->size();
    2163             : 
    2164       19631 :     AddNumRule(pNew);
    2165             : 
    2166       19631 :     if (GetIDocumentUndoRedo().DoesUndo())
    2167             :     {
    2168          12 :         SwUndo * pUndo = new SwUndoNumruleCreate(pNew, this);
    2169          12 :         GetIDocumentUndoRedo().AppendUndo(pUndo);
    2170             :     }
    2171             : 
    2172       19631 :     if (bBroadcast)
    2173             :         BroadcastStyleOperation(pNew->GetName(), SFX_STYLE_FAMILY_PSEUDO,
    2174           0 :                                 SfxStyleSheetHintId::CREATED);
    2175             : 
    2176       19631 :     return nRet;
    2177             : }
    2178             : 
    2179       20333 : OUString SwDoc::GetUniqueNumRuleName( const OUString* pChkStr, bool bAutoNum ) const
    2180             : {
    2181             :     // If we got pChkStr, then the caller expects that in case it's not yet
    2182             :     // used, it'll be returned.
    2183       20333 :     if( IsInMailMerge() && !pChkStr )
    2184             :     {
    2185             :         OUString newName = "MailMergeNumRule"
    2186           0 :             + OStringToOUString( DateTimeToOString( DateTime( DateTime::SYSTEM )), RTL_TEXTENCODING_ASCII_US )
    2187           0 :             + OUString::number( mpNumRuleTable->size() + 1 );
    2188           0 :         return newName;
    2189             :     }
    2190             : 
    2191       20333 :     OUString aName;
    2192       20333 :     if( bAutoNum )
    2193             :     {
    2194       20332 :         static bool bHack = (getenv("LIBO_ONEWAY_STABLE_ODF_EXPORT") != NULL);
    2195             : 
    2196       20332 :         if (bHack)
    2197             :         {
    2198             :             static sal_Int64 nIdCounter = SAL_CONST_INT64(8000000000);
    2199           0 :             aName = OUString::number(nIdCounter++);
    2200             :         }
    2201             :         else
    2202             :         {
    2203       20332 :             static rtlRandomPool s_RandomPool( rtl_random_createPool() );
    2204             :             sal_Int64 n;
    2205       20332 :             rtl_random_getBytes( s_RandomPool, &n, sizeof(n) );
    2206       20332 :             aName = OUString::number( (n < 0 ? -n : n) );
    2207             :         }
    2208       20332 :         if( pChkStr && pChkStr->isEmpty() )
    2209           0 :             pChkStr = 0;
    2210             :     }
    2211           1 :     else if( pChkStr && !pChkStr->isEmpty() )
    2212           1 :         aName = *pChkStr;
    2213             :     else
    2214             :     {
    2215           0 :         pChkStr = 0;
    2216           0 :         aName = SW_RESSTR( STR_NUMRULE_DEFNAME );
    2217             :     }
    2218             : 
    2219       20333 :     sal_uInt16 nNum(0), nTmp, nFlagSize = ( mpNumRuleTable->size() / 8 ) +2;
    2220       20333 :     sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
    2221       20333 :     memset( pSetFlags, 0, nFlagSize );
    2222             : 
    2223       20333 :     sal_Int32 nNmLen = aName.getLength();
    2224       20333 :     if( !bAutoNum && pChkStr )
    2225             :     {
    2226           1 :         while( nNmLen-- && '0' <= aName[nNmLen] && aName[nNmLen] <= '9' )
    2227             :             ; //nop
    2228             : 
    2229           1 :         if( ++nNmLen < aName.getLength() )
    2230             :         {
    2231           0 :             aName = aName.copy(0, nNmLen );
    2232           0 :             pChkStr = 0;
    2233             :         }
    2234             :     }
    2235             : 
    2236             :     const SwNumRule* pNumRule;
    2237             :     sal_uInt16 n;
    2238             : 
    2239    24874449 :     for( n = 0; n < mpNumRuleTable->size(); ++n )
    2240    24854116 :         if( 0 != ( pNumRule = (*mpNumRuleTable)[ n ] ) )
    2241             :         {
    2242    24854116 :             const OUString sNm = pNumRule->GetName();
    2243    24854116 :             if( sNm.startsWith( aName ) )
    2244             :             {
    2245             :                 // Determine Number and set the Flag
    2246           0 :                 nNum = (sal_uInt16)sNm.copy( nNmLen ).toInt32();
    2247           0 :                 if( nNum-- && nNum < mpNumRuleTable->size() )
    2248           0 :                     pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
    2249             :             }
    2250    24854116 :             if( pChkStr && *pChkStr==sNm )
    2251           0 :                 pChkStr = 0;
    2252             :         }
    2253             : 
    2254       20333 :     if( !pChkStr )
    2255             :     {
    2256             :         // All Numbers have been flagged accordingly, so identify the right Number
    2257          61 :         nNum = mpNumRuleTable->size();
    2258          61 :         for( n = 0; n < nFlagSize; ++n )
    2259          61 :             if( 0xff != ( nTmp = pSetFlags[ n ] ))
    2260             :             {
    2261             :                 // identify the Number
    2262          61 :                 nNum = n * 8;
    2263         122 :                 while( nTmp & 1 )
    2264           0 :                     ++nNum, nTmp >>= 1;
    2265          61 :                 break;
    2266             :             }
    2267             :     }
    2268       20333 :     delete [] pSetFlags;
    2269       20333 :     if( pChkStr && !pChkStr->isEmpty() )
    2270       20272 :         return *pChkStr;
    2271          61 :     return aName + OUString::number( ++nNum );
    2272             : }
    2273             : 
    2274      192036 : void SwDoc::UpdateNumRule()
    2275             : {
    2276      192036 :     const SwNumRuleTable& rNmTable = GetNumRuleTable();
    2277   244304565 :     for( size_t n = 0; n < rNmTable.size(); ++n )
    2278   244112529 :         if( rNmTable[ n ]->IsInvalidRule() )
    2279      155956 :             rNmTable[ n ]->Validate();
    2280      192036 : }
    2281             : 
    2282           0 : void SwDoc::MarkListLevel( const OUString& sListId,
    2283             :                            const int nListLevel,
    2284             :                            const bool bValue )
    2285             : {
    2286           0 :     SwList* pList = getIDocumentListsAccess().getListByName( sListId );
    2287             : 
    2288           0 :     if ( pList )
    2289             :     {
    2290           0 :         MarkListLevel( *pList, nListLevel, bValue );
    2291             :     }
    2292           0 : }
    2293             : 
    2294           0 : void SwDoc::MarkListLevel( SwList& rList,
    2295             :                            const int nListLevel,
    2296             :                            const bool bValue )
    2297             : {
    2298             :     // Set new marked list level and notify all affected nodes of the changed mark.
    2299           0 :     rList.MarkListLevel( nListLevel, bValue );
    2300           0 : }
    2301             : 
    2302           0 : bool SwDoc::IsFirstOfNumRuleAtPos( const SwPosition & rPos )
    2303             : {
    2304           0 :     bool bResult = false;
    2305             : 
    2306           0 :     const SwTextNode* pTextNode = rPos.nNode.GetNode().GetTextNode();
    2307           0 :     if ( pTextNode != NULL )
    2308             :     {
    2309           0 :         bResult = pTextNode->IsFirstOfNumRule();
    2310             :     }
    2311             : 
    2312           0 :     return bResult;
    2313         177 : }
    2314             : 
    2315             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11