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

Generated by: LCOV version 1.10