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

Generated by: LCOV version 1.10