xref: /aoo41x/main/sw/source/core/doc/docnum.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 #include <hintids.hxx>
32 #include <tools/date.hxx>
33 #include <tools/time.hxx>
34 #include <tools/resid.hxx>
35 #include <editeng/lrspitem.hxx>
36 #include <ftninfo.hxx>
37 #include <ftnidx.hxx>
38 #include <doc.hxx>
39 #include <IDocumentUndoRedo.hxx>
40 #include <pam.hxx>
41 #include <ndtxt.hxx>
42 #include <doctxm.hxx>		// pTOXBaseRing
43 #include <poolfmt.hxx>
44 #include <UndoCore.hxx>
45 #include <UndoRedline.hxx>
46 #include <UndoNumbering.hxx>
47 #include <swundo.hxx>
48 #include <SwUndoFmt.hxx>
49 #include <rolbck.hxx>
50 #include <paratr.hxx>
51 #include <docary.hxx>
52 #include <mvsave.hxx>
53 #include <txtfrm.hxx>
54 #include <pamtyp.hxx>
55 #include <redline.hxx>
56 #include <comcore.hrc>
57 #include <editeng/adjitem.hxx>
58 #include <editeng/frmdiritem.hxx>
59 #include <frmatr.hxx>
60 #include <SwStyleNameMapper.hxx>
61 #include <SwNodeNum.hxx>
62 #include <list.hxx>
63 #include <listfunc.hxx>
64 #include <switerator.hxx>
65 
66 #include <map>
67 
68 inline sal_uInt8 GetUpperLvlChg( sal_uInt8 nCurLvl, sal_uInt8 nLevel, sal_uInt16 nMask )
69 {
70 	if( 1 < nLevel )
71 	{
72 		if( nCurLvl + 1 >= nLevel )
73 			nCurLvl -= nLevel - 1;
74 		else
75 			nCurLvl = 0;
76 	}
77 	return static_cast<sal_uInt8>((nMask - 1) & ~(( 1 << nCurLvl ) - 1));
78 }
79 
80 void SwDoc::SetOutlineNumRule( const SwNumRule& rRule )
81 {
82     if( pOutlineRule )
83 		(*pOutlineRule) = rRule;
84 	else
85 	{
86 		pOutlineRule = new SwNumRule( rRule );
87 
88         AddNumRule(pOutlineRule); // #i36749#
89 	}
90 
91 	pOutlineRule->SetRuleType( OUTLINE_RULE );
92     // --> OD 2008-07-08 #i91400#
93 	pOutlineRule->SetName( String::CreateFromAscii(
94                                         SwNumRule::GetOutlineRuleName() ),
95                            *this);
96     // <--
97     // --> OD 2006-09-21 #i69522#
98     // assure that the outline numbering rule is an automatic rule
99     pOutlineRule->SetAutoRule( sal_True );
100     // <--
101 
102 	// teste ob die evt. gesetzen CharFormate in diesem Document
103 	// definiert sind
104 	pOutlineRule->CheckCharFmts( this );
105 
106     // --> OD 2008-05-13 #refactorlists#
107     // notify text nodes, which are registered at the outline style, about the
108     // changed outline style
109     SwNumRule::tTxtNodeList aTxtNodeList;
110     pOutlineRule->GetTxtNodeList( aTxtNodeList );
111     for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
112           aIter != aTxtNodeList.end(); ++aIter )
113     {
114         SwTxtNode* pTxtNd = *aIter;
115         pTxtNd->NumRuleChgd();
116         // --> OD 2009-01-20 #i94152#
117         // assure that list level corresponds to outline level
118         if ( pTxtNd->GetTxtColl()->IsAssignedToListLevelOfOutlineStyle() &&
119              pTxtNd->GetAttrListLevel() != pTxtNd->GetTxtColl()->GetAssignedOutlineStyleLevel() )
120         {
121             pTxtNd->SetAttrListLevel( pTxtNd->GetTxtColl()->GetAssignedOutlineStyleLevel() );
122         }
123         // <--
124     }
125     // <--
126 
127     PropagateOutlineRule();
128     pOutlineRule->SetInvalidRule(sal_True);
129     UpdateNumRule();
130 
131     // gibt es Fussnoten && gilt Kapitelweises Nummerieren, dann updaten
132     if( GetFtnIdxs().Count() && FTNNUM_CHAPTER == GetFtnInfo().eNum )
133         GetFtnIdxs().UpdateAllFtn();
134 
135 	UpdateExpFlds(NULL, true);
136 
137 	SetModified();
138 }
139 
140 void SwDoc::PropagateOutlineRule()
141 {
142     for (sal_uInt16 n = 0; n < pTxtFmtCollTbl->Count(); n++)
143     {
144         SwTxtFmtColl *pColl = (*pTxtFmtCollTbl)[n];
145 
146        // if (NO_NUMBERING != pColl->GetOutlineLevel())//#outline level,zhaojianwei
147 		if(pColl->IsAssignedToListLevelOfOutlineStyle())//<-end,zhaojianwei
148         {
149             // --> OD 2006-11-20 #i71764#
150             // Check only the list style, which is set at the paragraph style
151             const SwNumRuleItem & rCollRuleItem = pColl->GetNumRule( sal_False );
152             // <--
153 
154             // --> OD 2006-11-20 #i71764#
155             // Check on document setting OUTLINE_LEVEL_YIELDS_OUTLINE_RULE no longer needed.
156             if ( rCollRuleItem.GetValue().Len() == 0 )
157             // <--
158             {
159                 SwNumRule * pMyOutlineRule = GetOutlineNumRule();
160 
161                 if (pMyOutlineRule)
162                 {
163                     SwNumRuleItem aNumItem( pMyOutlineRule->GetName() );
164 
165                     pColl->SetFmtAttr(aNumItem);
166                 }
167 			}
168         }
169     }
170 }
171 
172 	// Hoch-/Runterstufen
173 sal_Bool SwDoc::OutlineUpDown( const SwPaM& rPam, short nOffset )
174 {
175 	if( !GetNodes().GetOutLineNds().Count() || !nOffset )
176 		return sal_False;
177 
178 	// den Bereich feststellen
179 	const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
180 	const SwNodePtr pSttNd = (SwNodePtr)&rPam.Start()->nNode.GetNode();
181 	const SwNodePtr pEndNd = (SwNodePtr)&rPam.End()->nNode.GetNode();
182 	sal_uInt16 nSttPos, nEndPos;
183 
184 	if( !rOutlNds.Seek_Entry( pSttNd, &nSttPos ) &&
185 		!nSttPos-- )
186 		// wir stehen in keiner "Outline-Section"
187 		return sal_False;
188 
189 	if( rOutlNds.Seek_Entry( pEndNd, &nEndPos ) )
190 		++nEndPos;
191 
192 	// jetzt haben wir unseren Bereich im OutlineNodes-Array
193 	// dann prufe ersmal, ob nicht unterebenen aufgehoben werden
194 	// (Stufung ueber die Grenzen)
195 	sal_uInt16 n;
196 
197 	// so, dann koennen wir:
198 	// 1. Vorlagen-Array anlegen
199 	SwTxtFmtColl* aCollArr[ MAXLEVEL ];
200 	memset( aCollArr, 0, sizeof( SwTxtFmtColl* ) * MAXLEVEL );
201 
202 	for( n = 0; n < pTxtFmtCollTbl->Count(); ++n )
203 	{
204 		//sal_uInt8 nLevel = (*pTxtFmtCollTbl)[ n ]->GetOutlineLevel();//#outline level,zhaojianwei
205 		//if( nLevel < MAXLEVEL )
206 		//	aCollArr[ nLevel ] = (*pTxtFmtCollTbl)[ n ];
207 		if((*pTxtFmtCollTbl)[ n ]->IsAssignedToListLevelOfOutlineStyle())
208 		{
209             const int nLevel = (*pTxtFmtCollTbl)[ n ]->GetAssignedOutlineStyleLevel();
210 			aCollArr[ nLevel ] = (*pTxtFmtCollTbl)[ n ];
211 		}//<-end,zhaojianwei
212 	}
213 
214     /* --> #111107# */
215     /* Find the last occupied level (backward). */
216     for (n = MAXLEVEL - 1; n > 0; n--)
217     {
218         if (aCollArr[n] != 0)
219             break;
220     }
221 
222     /* If an occupied level is found, choose next level (which IS
223        unoccupied) until a valid level is found. If no occupied level
224        was found n is 0 and aCollArr[0] is 0. In this case no demoting
225        is possible. */
226     if (aCollArr[n] != 0)
227     {
228         while (n < MAXLEVEL - 1)
229         {
230             n++;
231 
232             SwTxtFmtColl *aTmpColl =
233                 GetTxtCollFromPool(static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + n));
234 
235             //if (aTmpColl->GetOutlineLevel() == n)//#outline level,zhaojianwei
236 			if( aTmpColl->IsAssignedToListLevelOfOutlineStyle() &&
237 				aTmpColl->GetAssignedOutlineStyleLevel() == n )//<-end,zhaojianwei
238             {
239                 aCollArr[n] = aTmpColl;
240                 break;
241             }
242         }
243     }
244 
245     /* Find the first occupied level (forward). */
246     for (n = 0; n < MAXLEVEL - 1; n++)
247     {
248         if (aCollArr[n] != 0)
249             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     if (aCollArr[n] != 0)
257     {
258         while (n > 0)
259         {
260             n--;
261 
262             SwTxtFmtColl *aTmpColl =
263                 GetTxtCollFromPool(static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + n));
264 
265             //if (aTmpColl->GetOutlineLevel() == n)//#outline level,zhaojianwei
266 			if( aTmpColl->IsAssignedToListLevelOfOutlineStyle() &&
267 				aTmpColl->GetAssignedOutlineStyleLevel() == n )//<-end,zhaojianwei
268             {
269                 aCollArr[n] = aTmpColl;
270                 break;
271             }
272         }
273     }
274     /* <-- #111107# */
275 
276     /* --> #i13747#
277 
278        Build a move table that states from which level an outline will
279 
280   be moved to which other level. */
281 
282     /* the move table
283 
284        aMoveArr[n] = m: replace aCollArr[n] with aCollArr[m]
285     */
286     int aMoveArr[MAXLEVEL];
287     int nStep; // step size for searching in aCollArr: -1 or 1
288     int nNum; // amount of steps for stepping in aCollArr
289 
290     if (nOffset < 0)
291     {
292         nStep = -1;
293         nNum = -nOffset;
294     }
295     else
296     {
297         nStep = 1;
298         nNum = nOffset;
299     }
300 
301     /* traverse aCollArr */
302     for (n = 0; n < MAXLEVEL; n++)
303     {
304         /* If outline level n has an assigned paragraph style step
305            nNum steps forwards (nStep == 1) or backwards (nStep ==
306            -1).  One step is to go to the next non-null entry in
307            aCollArr in the selected direction. If nNum steps were
308            possible write the index of the entry found to aCollArr[n],
309            i.e. outline level n will be replaced by outline level
310            aCollArr[n].
311 
312            If outline level n has no assigned paragraph style
313            aMoveArr[n] is set to -1.
314         */
315         if (aCollArr[n] != NULL)
316         {
317             sal_uInt16 m = n;
318             int nCount = nNum;
319 
320             while (nCount > 0 && m + nStep >= 0 && m + nStep < MAXLEVEL)
321             {
322                 m = static_cast<sal_uInt16>(m + nStep);
323 
324                 if (aCollArr[m] != NULL)
325                     nCount--;
326             }
327 
328             if (nCount == 0)
329                 aMoveArr[n] = m;
330 			else
331 				aMoveArr[n] = -1;
332 
333         }
334         else
335             aMoveArr[n] = -1;
336     }
337 
338     /* If moving of the outline levels is applicable, i.e. for all
339        outline levels occuring in the document there has to be a valid
340        target outline level implied by aMoveArr. */
341     bool bMoveApplicable = true;
342 	for (n = nSttPos; n < nEndPos; n++)
343 	{
344 		SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
345         SwTxtFmtColl* pColl = pTxtNd->GetTxtColl();
346 //        int nLevel = pColl->GetOutlineLevel();//#outline level,zhaojianwei
347 //        if (aMoveArr[nLevel] == -1)
348 //          bMoveApplicable = false;
349         if( pColl->IsAssignedToListLevelOfOutlineStyle() )
350         {
351             const int nLevel = pColl->GetAssignedOutlineStyleLevel();
352             if (aMoveArr[nLevel] == -1)
353                 bMoveApplicable = false;
354         }//<-end,zhaojianwei
355         // --> OD 2008-12-16 #i70748#
356         // Check on outline level attribute of text node, if text node is
357         // not an outline via a to outline style assigned paragraph style.
358         else
359         {
360             const int nNewOutlineLevel = pTxtNd->GetAttrOutlineLevel() + nOffset;
361             if ( nNewOutlineLevel < 1 || nNewOutlineLevel > MAXLEVEL )
362             {
363                 bMoveApplicable = false;
364             }
365         }
366         // <--
367 	}
368 
369 	if (! bMoveApplicable )
370 		return sal_False;
371 
372     /* <-- #i13747 # */
373     if (GetIDocumentUndoRedo().DoesUndo())
374     {
375         GetIDocumentUndoRedo().StartUndo(UNDO_OUTLINE_LR, NULL);
376         SwUndo *const pUndoOLR( new SwUndoOutlineLeftRight( rPam, nOffset ) );
377         GetIDocumentUndoRedo().AppendUndo(pUndoOLR);
378     }
379 
380 	// 2. allen Nodes die neue Vorlage zuweisen
381 
382 	n = nSttPos;
383 	while( n < nEndPos)
384 	{
385 		SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
386 		SwTxtFmtColl* pColl = pTxtNd->GetTxtColl();
387 
388 		if( pColl->IsAssignedToListLevelOfOutlineStyle() )
389 		{
390 		// ASSERT(pColl->GetOutlineLevel() < MAXLEVEL,	//#outline level,removed by zhaojianwei
391         //         "non outline node in outline nodes?");
392         //int nLevel = pColl->GetOutlineLevel();
393             const int nLevel = pColl->GetAssignedOutlineStyleLevel();//#outline level,add by zhaojianwei
394 
395 			ASSERT(aMoveArr[nLevel] >= 0,
396 				"move table: current TxtColl not found when building table!");
397 
398 
399 			if (nLevel < MAXLEVEL && aMoveArr[nLevel] >= 0)
400 			{
401 				pColl = aCollArr[ aMoveArr[nLevel] ];
402 
403 				if (pColl != NULL)
404 					pColl = (SwTxtFmtColl*)pTxtNd->ChgFmtColl( pColl );
405 			}
406 
407 		}
408 		else if( pTxtNd->GetAttrOutlineLevel() > 0)	//#outline level,add by zhaojianwei
409 		{
410 			int nLevel = pTxtNd->GetAttrOutlineLevel() + nOffset;
411 			if( 0 <= nLevel && nLevel <= MAXLEVEL)
412 				pTxtNd->SetAttrOutlineLevel( nLevel );
413 
414 		}//<-end,zhaojianwei
415 
416         n++;
417 		// Undo ???
418 	}
419     if (GetIDocumentUndoRedo().DoesUndo())
420     {
421         GetIDocumentUndoRedo().EndUndo(UNDO_OUTLINE_LR, NULL);
422     }
423 
424     ChkCondColls();
425 	SetModified();
426 
427 	return sal_True;
428 }
429 
430 
431 
432 	// Hoch-/Runter - Verschieben !
433 sal_Bool SwDoc::MoveOutlinePara( const SwPaM& rPam, short nOffset )
434 {
435 	// kein Verschiebung in den Sonderbereichen
436 	const SwPosition& rStt = *rPam.Start(),
437 					& rEnd = &rStt == rPam.GetPoint() ? *rPam.GetMark()
438 													  : *rPam.GetPoint();
439 	if( !GetNodes().GetOutLineNds().Count() || !nOffset ||
440         (rStt.nNode.GetIndex() < GetNodes().GetEndOfExtras().GetIndex()) ||
441         (rEnd.nNode.GetIndex() < GetNodes().GetEndOfExtras().GetIndex()))
442     {
443 		return sal_False;
444     }
445 
446 	sal_uInt16 nAktPos = 0;
447 	SwNodeIndex aSttRg( rStt.nNode ), aEndRg( rEnd.nNode );
448 
449     //sal_uInt8 nOutLineLevel = NO_NUMBERING;	//#outline level,zhaojianwei
450     int nOutLineLevel = MAXLEVEL;			//<-end,zhaojianwei
451 	SwNode* pSrch = &aSttRg.GetNode();
452     //if( pSrch->IsTxtNode() )				//#outline level,zhaojianwei
453     //     nOutLineLevel = static_cast<sal_uInt8>(((SwTxtNode*)pSrch)->GetOutlineLevel());
454    if( pSrch->IsTxtNode())
455         nOutLineLevel = static_cast<sal_uInt8>(((SwTxtNode*)pSrch)->GetAttrOutlineLevel()-1);//<-end,zhaojianwei
456 	SwNode* pEndSrch = &aEndRg.GetNode();
457     if( !GetNodes().GetOutLineNds().Seek_Entry( pSrch, &nAktPos ) )
458     {
459         if( !nAktPos )
460             return sal_False; // Promoting or demoting before the first outline => no.
461         if( --nAktPos )
462             aSttRg = *GetNodes().GetOutLineNds()[ nAktPos ];
463         else if( 0 > nOffset )
464             return sal_False; // Promoting at the top of document?!
465         else
466             aSttRg = *GetNodes().GetEndOfContent().StartOfSectionNode();
467     }
468     sal_uInt16 nTmpPos = 0;
469     // If the given range ends at an outlined text node we have to decide if it has to be a part of
470     // the moving range or not. Normally it will be a sub outline of our chapter
471     // and has to be moved, too. But if the chapter ends with a table(or a section end),
472     // the next text node will be choosen and this could be the next outline of the same level.
473     // The criteria has to be the outline level: sub level => incorporate, same/higher level => no.
474     if( GetNodes().GetOutLineNds().Seek_Entry( pEndSrch, &nTmpPos ) )
475     {
476         if( !pEndSrch->IsTxtNode() || pEndSrch == pSrch ||
477             //nOutLineLevel < ((SwTxtNode*)pEndSrch)->GetOutlineLevel() )//#outline level,zhaojianwei
478 			nOutLineLevel < ((SwTxtNode*)pEndSrch)->GetAttrOutlineLevel()-1 )//<-end,zhaojianwei
479             ++nTmpPos; // For sub outlines only!
480     }
481 
482     aEndRg = nTmpPos < GetNodes().GetOutLineNds().Count()
483                     ? *GetNodes().GetOutLineNds()[ nTmpPos ]
484                     : GetNodes().GetEndOfContent();
485     if( nOffset >= 0 )
486         nAktPos = nTmpPos;
487     if( aEndRg == aSttRg )
488     {
489         ASSERT( false, "Moving outlines: Surprising selection" );
490         aEndRg++;
491     }
492 
493 	const SwNode* pNd;
494     // The following code corrects the range to handle sections (start/end nodes)
495     // The range will be extended if the least node before the range is a start node
496     // which ends inside the range => The complete section will be moved.
497     // The range will be shrinked if the last position is a start node.
498     // The range will be shrinked if the last node is an end node which starts before the range.
499     aSttRg--;
500     while( aSttRg.GetNode().IsStartNode() )
501     {
502         pNd = aSttRg.GetNode().EndOfSectionNode();
503         if( pNd->GetIndex() >= aEndRg.GetIndex() )
504             break;
505         aSttRg--;
506     }
507     aSttRg++;
508 
509     aEndRg--;
510     while( aEndRg.GetNode().IsStartNode() )
511         aEndRg--;
512     while( aEndRg.GetNode().IsEndNode() )
513     {
514         pNd = aEndRg.GetNode().StartOfSectionNode();
515         if( pNd->GetIndex() >= aSttRg.GetIndex() )
516             break;
517         aEndRg--;
518     }
519     aEndRg++;
520 
521 	// calculation of the new position
522 	if( nOffset < 0 && nAktPos < sal_uInt16(-nOffset) )
523 		pNd = GetNodes().GetEndOfContent().StartOfSectionNode();
524 	else if( nAktPos + nOffset >= GetNodes().GetOutLineNds().Count() )
525 		pNd = &GetNodes().GetEndOfContent();
526 	else
527 		pNd = GetNodes().GetOutLineNds()[ nAktPos + nOffset ];
528 
529 	sal_uLong nNewPos = pNd->GetIndex();
530 
531     // And now a correction of the insert position if necessary...
532     SwNodeIndex aInsertPos( *pNd, -1 );
533     while( aInsertPos.GetNode().IsStartNode() )
534     {
535         // Just before the insert position starts a section:
536         // when I'm moving forward I do not want to enter the section,
537         // when I'm moving backward I want to stay in the section if I'm already a part of,
538         // I want to stay outside if I was outside before.
539         if( nOffset < 0 )
540         {
541             pNd = aInsertPos.GetNode().EndOfSectionNode();
542             if( pNd->GetIndex() >= aEndRg.GetIndex() )
543                 break;
544         }
545         aInsertPos--;
546         --nNewPos;
547     }
548     if( nOffset >= 0 )
549     {
550         // When just before the insert position a section ends, it is okay when I'm moving backward
551         // because I want to stay outside the section.
552         // When moving forward I've to check if I started inside or outside the section
553         // because I don't want to enter of leave such a section
554         while( aInsertPos.GetNode().IsEndNode() )
555         {
556             pNd = aInsertPos.GetNode().StartOfSectionNode();
557             if( pNd->GetIndex() >= aSttRg.GetIndex() )
558                 break;
559             aInsertPos--;
560             --nNewPos;
561         }
562     }
563     // We do not want to move into tables (at the moment)
564     aInsertPos++;
565     pNd = &aInsertPos.GetNode();
566     if( pNd->IsTableNode() )
567         pNd = pNd->StartOfSectionNode();
568     if( pNd->FindTableNode() )
569         return sal_False;
570 
571 	ASSERT( aSttRg.GetIndex() > nNewPos || nNewPos >= aEndRg.GetIndex(),
572 				"Position liegt im MoveBereich" );
573 
574 	// wurde ein Position in den Sonderbereichen errechnet, dann
575 	// setze die Position auf den Dokumentanfang.
576 	// Sollten da Bereiche oder Tabellen stehen, so werden sie nach
577 	// hinten verschoben.
578     nNewPos = Max( nNewPos, GetNodes().GetEndOfExtras().GetIndex() + 2 );
579 
580 	long nOffs = nNewPos - ( 0 < nOffset ? aEndRg.GetIndex() : aSttRg.GetIndex());
581 	SwPaM aPam( aSttRg, aEndRg, 0, -1 );
582 	return MoveParagraph( aPam, nOffs, sal_True );
583 }
584 
585 
586 sal_uInt16 lcl_FindOutlineName( const SwNodes& rNds, const String& rName,
587 							sal_Bool bExact )
588 {
589 	sal_uInt16 nSavePos = USHRT_MAX;
590 	const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
591 	for( sal_uInt16 n = 0; n < rOutlNds.Count(); ++n )
592 	{
593 		SwTxtNode* pTxtNd = rOutlNds[ n ]->GetTxtNode();
594 		String sTxt( pTxtNd->GetExpandTxt() );
595 		if( sTxt.Equals( rName ) )
596 		{
597 			// "exact" gefunden, setze Pos auf den Node
598 			nSavePos = n;
599 			break;
600 		}
601 		else if( !bExact && USHRT_MAX == nSavePos &&
602 					COMPARE_EQUAL == sTxt.CompareTo( rName, rName.Len()) )
603 		{
604 			// dann vielleicht nur den den 1.Teil vom Text gefunden
605 			nSavePos = n;
606 		}
607 	}
608 
609 	return nSavePos;
610 }
611 
612 
613 
614 sal_uInt16 lcl_FindOutlineNum( const SwNodes& rNds, String& rName )
615 {
616 	// Gueltig Nummern sind (immer nur Offsets!!!):
617 	// 	([Nummer]+\.)+	(als regulaerer Ausdruck!)
618 	//	(Nummer gefolgt von Punkt, zum 5 Wiederholungen)
619 	//	also: "1.1.", "1.", "1.1.1."
620 	xub_StrLen nPos = 0;
621 	String sNum = rName.GetToken( 0, '.', nPos );
622 	if( STRING_NOTFOUND == nPos )
623 		return USHRT_MAX;			// ungueltige Nummer!!!
624 
625 	sal_uInt16 nLevelVal[ MAXLEVEL ];		// Nummern aller Levels
626 	memset( nLevelVal, 0, MAXLEVEL * sizeof( nLevelVal[0] ));
627 	sal_uInt8 nLevel = 0;
628 	String sName( rName );
629 
630 	while( STRING_NOTFOUND != nPos )
631 	{
632 		sal_uInt16 nVal = 0;
633 		sal_Unicode c;
634 		for( sal_uInt16 n = 0; n < sNum.Len(); ++n )
635 			if( '0' <= ( c = sNum.GetChar( n )) && c <= '9' )
636 			{
637 				nVal *= 10;  nVal += c - '0';
638 			}
639 			else if( nLevel )
640 				break;						// "fast" gueltige Nummer
641 			else
642 				return USHRT_MAX;			// ungueltige Nummer!!!
643 
644 		if( MAXLEVEL > nLevel )
645 			nLevelVal[ nLevel++ ] = nVal;
646 
647 		sName.Erase( 0, nPos );
648 		nPos = 0;
649 		sNum = sName.GetToken( 0, '.', nPos );
650         // #i4533# without this check all parts delimited by a dot are treated as outline numbers
651         if(!ByteString(sNum, gsl_getSystemTextEncoding()).IsNumericAscii())
652             nPos = STRING_NOTFOUND;
653 	}
654 	rName = sName;		// das ist der nachfolgende Text.
655 
656 	// alle Levels gelesen, dann suche mal im Document nach dieser
657 	// Gliederung:
658 	const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
659 	// OS: ohne OutlineNodes lohnt die Suche nicht
660 	// und man spart sich einen Absturz #42958#
661 	if(!rOutlNds.Count())
662 		return USHRT_MAX;
663 	SwTxtNode* pNd;
664     nPos = 0;
665     //search in the existing outline nodes for the required outline num array
666     for( ; nPos < rOutlNds.Count(); ++nPos )
667     {
668         pNd = rOutlNds[ nPos ]->GetTxtNode();
669         //sal_uInt8 nLvl = pNd->GetTxtColl()->GetOutlineLevel();	//#outline level,zhaojianwei
670         const int nLvl = pNd->GetAttrOutlineLevel()-1;   //<-end,zhaojianwei
671         if( nLvl == nLevel - 1)
672         {
673             // check for the outline num
674             // --> OD 2005-11-02 #i51089 - TUNING#
675             // --> OD 2006-09-22 #i68289#
676             // Assure, that text node has the correct numbering level. Otherwise,
677             // its number vector will not fit to the searched level.
678 //            if ( pNd->GetNum() )
679             if ( pNd->GetNum() &&
680                  pNd->GetActualListLevel() == ( nLevel - 1 ) )
681             // <--
682             {
683                 const SwNodeNum & rNdNum = *(pNd->GetNum());
684                 SwNumberTree::tNumberVector aLevelVal = rNdNum.GetNumberVector();
685                 //now compare with the one searched for
686                 bool bEqual = true;
687                 for( sal_uInt8 n = 0; (n < nLevel) && bEqual; ++n )
688                 {
689                     bEqual = aLevelVal[n] == nLevelVal[n];
690                 }
691                 if(bEqual)
692                 {
693                     break;
694                 }
695             }
696             else
697             {
698                 // --> OD 2006-01-12 #126588#
699                 // A text node, which has an outline paragraph style applied and
700                 // has as hard attribute 'no numbering' set, has an outline level,
701                 // but no numbering tree node. Thus, consider this situation in
702                 // the assertion condition.
703                 ASSERT( !pNd->GetNumRule(),
704                         "<lcl_FindOutlineNum(..)> - text node with outline level and numbering rule, but without numbering tree node. This is a serious defect -> inform OD" );
705             }
706         }
707     }
708     if( nPos >= rOutlNds.Count() )
709         nPos = USHRT_MAX;
710     return nPos;
711 }
712 
713 	// zu diesem Gliederungspunkt
714 
715 
716 	// JP 13.06.96:
717 	// im Namen kann eine Nummer oder/und der Text stehen.
718 	// zuerst wird ueber die Nummer versucht den richtigen Eintrag zu finden.
719 	// Gibt es diesen, dann wird ueber den Text verglichen, od es der
720 	// gewuenschte ist. Ist das nicht der Fall, wird noch mal nur ueber den
721 	// Text gesucht. Wird dieser gefunden ist es der Eintrag. Ansonsten der,
722 	// der ueber die Nummer gefunden wurde.
723 	// Ist keine Nummer angegeben, dann nur den Text suchen.
724 
725 sal_Bool SwDoc::GotoOutline( SwPosition& rPos, const String& rName ) const
726 {
727 	if( rName.Len() )
728 	{
729 		const SwOutlineNodes& rOutlNds = GetNodes().GetOutLineNds();
730 
731 		// 1. Schritt: ueber die Nummer:
732 		String sName( rName );
733 		sal_uInt16 nFndPos = ::lcl_FindOutlineNum( GetNodes(), sName );
734 		if( USHRT_MAX != nFndPos )
735 		{
736 			SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode();
737             String sExpandedText = pNd->GetExpandTxt();
738             //#i4533# leading numbers followed by a dot have been remove while
739             //searching for the outline position
740             //to compensate this they must be removed from the paragraphs text content, too
741             sal_uInt16 nPos = 0;
742             String sTempNum;
743             while(sExpandedText.Len() && (sTempNum = sExpandedText.GetToken(0, '.', nPos)).Len() &&
744                     STRING_NOTFOUND != nPos &&
745                     ByteString(sTempNum, gsl_getSystemTextEncoding()).IsNumericAscii())
746             {
747                 sExpandedText.Erase(0, nPos);
748                 nPos = 0;
749             }
750 
751             if( !sExpandedText.Equals( sName ) )
752 			{
753 				sal_uInt16 nTmp = ::lcl_FindOutlineName( GetNodes(), sName, sal_True );
754 				if( USHRT_MAX != nTmp )				// ueber den Namen gefunden
755 				{
756 					nFndPos = nTmp;
757 					pNd = rOutlNds[ nFndPos ]->GetTxtNode();
758 				}
759 			}
760 			rPos.nNode = *pNd;
761 			rPos.nContent.Assign( pNd, 0 );
762 			return sal_True;
763 		}
764 
765 		nFndPos = ::lcl_FindOutlineName( GetNodes(), rName, sal_False );
766 		if( USHRT_MAX != nFndPos )
767 		{
768 			SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode();
769 			rPos.nNode = *pNd;
770 			rPos.nContent.Assign( pNd, 0 );
771 			return sal_True;
772 		}
773 
774         // --> OD 2006-09-22 #i68289#
775         // additional search on hyperlink URL without its outline numbering part
776         if ( !sName.Equals( rName ) )
777         {
778             nFndPos = ::lcl_FindOutlineName( GetNodes(), sName, sal_False );
779             if( USHRT_MAX != nFndPos )
780             {
781                 SwTxtNode* pNd = rOutlNds[ nFndPos ]->GetTxtNode();
782                 rPos.nNode = *pNd;
783                 rPos.nContent.Assign( pNd, 0 );
784                 return sal_True;
785             }
786         }
787         // <--
788 	}
789 	return sal_False;
790 }
791 
792 /*  */
793 
794 // --- Nummerierung -----------------------------------------
795 
796 // --> OD 2008-02-19 #refactorlists#
797 //void SwNumRuleInfo::MakeList( SwDoc& rDoc, sal_Bool )
798 //{
799 //    SwNumRule* pRule = rDoc.FindNumRulePtr(rName);
800 
801 //    // no rule, no fun.
802 //    if ( !pRule )
803 //        return;
804 
805 //    //
806 //    // 1. Case: Information already available at pRule:
807 //    //
808 //    if (pRule->GetTxtNodeList())
809 //    {
810 //        // copy list to own pList pointer:
811 //        aList = *pRule->GetTxtNodeList();
812 //        return;
813 //    }
814 
815 //    //
816 //    // 2. Case: Information has to be generated from scratch:
817 //    //
818 
819 //    if (pRule->IsOutlineRule())
820 //    {
821 //        const SwOutlineNodes & rOutlineNodes = rDoc.GetNodes().GetOutLineNds();
822 
823 //        for (sal_uInt16 i = 0; i < rOutlineNodes.Count(); ++i)
824 //        {
825 //            SwTxtNode & aNode = *((SwTxtNode *) rOutlineNodes[i]);
826 
827 //            if (pRule == aNode.GetNumRule())
828 //                AddNode(aNode);
829 //        }
830 //    }
831 //    {
832 //        SwModify* pMod;
833 //        const SfxPoolItem* pItem;
834 //        sal_uInt16 i, nMaxItems = rDoc.GetAttrPool().GetItemCount
835 //            ( RES_PARATR_NUMRULE);
836 //        for( i = 0; i < nMaxItems; ++i )
837 //        {
838 //            pItem = rDoc.GetAttrPool().GetItem( RES_PARATR_NUMRULE, i );
839 //            if( 0 != pItem)
840 //            {
841 //                pMod = (SwModify*)((SwNumRuleItem*)pItem)->GetDefinedIn();
842 //                if (0 != pMod &&
843 //                    ((SwNumRuleItem*)pItem)->GetValue().Len() &&
844 //                    ((SwNumRuleItem*)pItem)->GetValue() == rName )
845 //                {
846 //                    if( pMod->IsA( TYPE( SwFmt )) )
847 //                        pMod->GetInfo( *this );
848 //                    else
849 //                    {
850 //                        SwTxtNode* pModTxtNode = (SwTxtNode*)pMod;
851 
852 //                        // #115901#
853 //                        if( pModTxtNode->GetNodes().IsDocNodes())
854 //                        {
855 //                            AddNode( *pModTxtNode );
856 //                        }
857 //                    }
858 //                }
859 //            }
860 //        }
861 //    }
862 
863 //    // --> FME 2004-11-03 #i36571# The numrule and this info structure should
864 //    // have different instances of the list:
865 //    // --> OD 2006-09-12 #i69145#
866 //    // method <SwNumRule::SetList(..)> copies content of list provided by the parameter
867 //    pRule->SetTxtNodeList( aList );
868 //    // <--
869 //}
870 // <--
871 
872 
873 void lcl_ChgNumRule( SwDoc& rDoc, const SwNumRule& rRule )
874 {
875 	SwNumRule* pOld = rDoc.FindNumRulePtr( rRule.GetName() );
876 	ASSERT( pOld, "ohne die alte NumRule geht gar nichts" );
877 
878     sal_uInt16 nChgFmtLevel = 0, nMask = 1;
879 	sal_uInt8 n;
880 
881 	for( n = 0; n < MAXLEVEL; ++n, nMask <<= 1 )
882 	{
883 		const SwNumFmt& rOldFmt = pOld->Get( n ),
884 					  & rNewFmt = rRule.Get( n );
885 
886 		if( rOldFmt != rNewFmt )
887 		{
888 			nChgFmtLevel |= nMask;
889 		}
890 		else if( SVX_NUM_NUMBER_NONE > rNewFmt.GetNumberingType() && 1 < rNewFmt.GetIncludeUpperLevels() &&
891 				0 != (nChgFmtLevel & GetUpperLvlChg( n, rNewFmt.GetIncludeUpperLevels(),nMask )) )
892 			nChgFmtLevel |= nMask;
893 	}
894 
895     if( !nChgFmtLevel )         // es wurde nichts veraendert?
896     {
897         // --> OD 2006-04-27 #i64311#
898         const bool bInvalidateNumRule( pOld->IsContinusNum() != rRule.IsContinusNum() );
899         // <--
900         pOld->CheckCharFmts( &rDoc );
901         pOld->SetContinusNum( rRule.IsContinusNum() );
902         // --> OD 2008-06-17 #i87166#
903         // Do NOT change list style type
904 //        pOld->SetRuleType( rRule.GetRuleType() );
905         // <--
906         // --> OD 2006-04-27 #i64311#
907         if ( bInvalidateNumRule )
908         {
909             pOld->SetInvalidRule(sal_True);
910         }
911         // <--
912         return ;
913 	}
914 
915     // --> OD 2008-02-19 #refactorlists#
916 //    SwNumRuleInfo* pUpd = new SwNumRuleInfo( rRule.GetName() );
917 //    pUpd->MakeList( rDoc );
918 
919 //    sal_uInt8 nLvl;
920 //    for( sal_uLong nFirst = 0, nLast = pUpd->GetList().Count();
921 //        nFirst < nLast; ++nFirst )
922 //    {
923 //        SwTxtNode* pTxtNd = pUpd->GetList().GetObject( nFirst );
924 //        nLvl = static_cast<sal_uInt8>(pTxtNd->GetLevel());
925 
926 //        if( nLvl < MAXLEVEL )
927 //        {
928 //            if( nChgFmtLevel & ( 1 << nLvl ))
929 //            {
930 //                pTxtNd->NumRuleChgd();
931 //            }
932 //        }
933 //    }
934     SwNumRule::tTxtNodeList aTxtNodeList;
935     pOld->GetTxtNodeList( aTxtNodeList );
936     sal_uInt8 nLvl( 0 );
937     for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
938           aIter != aTxtNodeList.end(); ++aIter )
939     {
940         SwTxtNode* pTxtNd = *aIter;
941         nLvl = static_cast<sal_uInt8>(pTxtNd->GetActualListLevel());
942 
943         if( nLvl < MAXLEVEL )
944         {
945             if( nChgFmtLevel & ( 1 << nLvl ))
946             {
947                 pTxtNd->NumRuleChgd();
948             }
949         }
950     }
951     // <--
952 
953 	for( n = 0; n < MAXLEVEL; ++n )
954 		if( nChgFmtLevel & ( 1 << n ))
955 			pOld->Set( n, rRule.GetNumFmt( n ));
956 
957 	pOld->CheckCharFmts( &rDoc );
958 	pOld->SetInvalidRule(sal_True);
959 	pOld->SetContinusNum( rRule.IsContinusNum() );
960     // --> OD 2008-06-17 #i87166#
961     // Do NOT change list style type
962 //    pOld->SetRuleType( rRule.GetRuleType() );
963     // <--
964 
965     // --> OD 2008-02-19 #refactorlists#
966 //    delete pUpd;
967     // <--
968 
969     rDoc.UpdateNumRule();
970 }
971 
972 // OD 2008-02-08 #newlistlevelattrs# - add handling of parameter <bResetIndentAttrs>
973 // --> OD 2008-03-17 #refactorlists#
974 void SwDoc::SetNumRule( const SwPaM& rPam,
975                         const SwNumRule& rRule,
976                         const bool bCreateNewList,
977                         const String sContinuedListId,
978                         sal_Bool bSetItem,
979                         const bool bResetIndentAttrs )
980 {
981     SwUndoInsNum * pUndo = NULL;
982     if (GetIDocumentUndoRedo().DoesUndo())
983     {
984         // Start/End for attributes!
985         GetIDocumentUndoRedo().StartUndo( UNDO_INSNUM, NULL );
986         pUndo = new SwUndoInsNum( rPam, rRule );
987         GetIDocumentUndoRedo().AppendUndo(pUndo);
988     }
989 
990 	SwNumRule * pNew = FindNumRulePtr( rRule.GetName() );
991     bool bUpdateRule = false;
992 
993 	if( !pNew )
994     {
995 		pNew = (*pNumRuleTbl)[ MakeNumRule( rRule.GetName(), &rRule ) ];
996     }
997     else if (rRule != *pNew)
998     {
999         bUpdateRule = true;
1000     }
1001 
1002     if (bUpdateRule)
1003     {
1004         if( pUndo )
1005         {
1006         	pUndo->SaveOldNumRule( *pNew );
1007 			::lcl_ChgNumRule( *this, rRule );
1008 			pUndo->SetLRSpaceEndPos();
1009         }
1010         else
1011         {
1012 			::lcl_ChgNumRule( *this, rRule );
1013         }
1014     }
1015 
1016     // --> OD 2008-03-17 #refactorlists#
1017     if ( bSetItem )
1018     {
1019         if ( bCreateNewList )
1020         {
1021             String sListId;
1022             if ( !bUpdateRule )
1023             {
1024                 // apply list id of list, which has been created for the new list style
1025                 sListId = pNew->GetDefaultListId();
1026             }
1027             else
1028             {
1029                 // create new list and apply its list id
1030                 SwList* pNewList = createList( String(), pNew->GetName() );
1031                 ASSERT( pNewList,
1032                         "<SwDoc::SetNumRule(..)> - could not create new list. Serious defect -> please inform OD." );
1033                 sListId = pNewList->GetListId();
1034             }
1035             InsertPoolItem( rPam,
1036                 SfxStringItem( RES_PARATR_LIST_ID, sListId ), 0 );
1037         }
1038         else if ( sContinuedListId.Len() > 0 )
1039         {
1040             // apply given list id
1041             InsertPoolItem( rPam,
1042                 SfxStringItem( RES_PARATR_LIST_ID, sContinuedListId ), 0 );
1043         }
1044     }
1045     // <--
1046 
1047     if ( ! rPam.HasMark())
1048     {
1049         SwTxtNode * pTxtNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
1050         // --> OD 2006-10-19 #134160#
1051         // consider case that the PaM doesn't denote a text node - e.g. it denotes a graphic node
1052         if ( pTxtNd )
1053         {
1054             SwNumRule * pRule = pTxtNd->GetNumRule();
1055 
1056             if (pRule && pRule->GetName() == pNew->GetName())
1057             {
1058                 bSetItem = sal_False;
1059                 // --> OD 2008-06-02 #refactorlists#
1060                 if ( !pTxtNd->IsInList() )
1061                 {
1062                     pTxtNd->AddToList();
1063                 }
1064                 // <--
1065             }
1066             // --> OD 2005-10-26 #b6340308# - only clear numbering attribute at
1067             // text node, if at paragraph style the new numbering rule is found.
1068             else if ( !pRule )
1069             {
1070                 SwTxtFmtColl* pColl = pTxtNd->GetTxtColl();
1071                 if ( pColl )
1072                 {
1073                     SwNumRule* pCollRule = FindNumRulePtr(pColl->GetNumRule().GetValue());
1074                     if ( pCollRule && pCollRule->GetName() == pNew->GetName() )
1075                     {
1076                         pTxtNd->ResetAttr( RES_PARATR_NUMRULE );
1077                         bSetItem = sal_False;
1078                     }
1079                 }
1080             }
1081             // <--
1082         }
1083         // <--
1084     }
1085 
1086     // --> OD 2009-08-18 #i103817#
1087     if ( bSetItem )
1088     // <--
1089     {
1090         InsertPoolItem( rPam, SwNumRuleItem( pNew->GetName() ), 0 );
1091     }
1092 
1093     // --> OD 2008-02-08 #newlistlevelattrs#
1094     if ( bResetIndentAttrs &&
1095          pNew && pNew->Get( 0 ).GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
1096     {
1097         SvUShortsSort aResetAttrsArray;
1098         aResetAttrsArray.Insert( RES_LR_SPACE );
1099         // --> OD 2010-10-05 #i114929#
1100         // On a selection setup a corresponding Point-and-Mark in order to get
1101         // the indentation attribute reset on all paragraphs touched by the selection
1102         if ( rPam.HasMark() &&
1103              rPam.End()->nNode.GetNode().GetTxtNode() )
1104         {
1105             SwPaM aPam( rPam.Start()->nNode,
1106                         rPam.End()->nNode );
1107             aPam.Start()->nContent = 0;
1108             aPam.End()->nContent = rPam.End()->nNode.GetNode().GetTxtNode()->Len();
1109             ResetAttrs( aPam, sal_False, &aResetAttrsArray );
1110         }
1111         else
1112         {
1113             ResetAttrs( rPam, sal_False, &aResetAttrsArray );
1114         }
1115         // <--
1116     }
1117     // <--
1118 
1119     if (GetIDocumentUndoRedo().DoesUndo())
1120     {
1121         GetIDocumentUndoRedo().EndUndo( UNDO_INSNUM, NULL );
1122     }
1123 
1124 	SetModified();
1125 }
1126 
1127 void SwDoc::SetCounted(const SwPaM & rPam, bool bCounted)
1128 {
1129     if ( bCounted )
1130     {
1131         SvUShortsSort aResetAttrsArray;
1132         aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED );
1133         // --> OD 2010-10-05 #i114929#
1134         // On a selection setup a corresponding Point-and-Mark in order to get
1135         // the list-is-counted attribute reset on all paragraphs touched by the selection
1136         if ( rPam.HasMark() &&
1137              rPam.End()->nNode.GetNode().GetTxtNode() )
1138         {
1139             SwPaM aPam( rPam.Start()->nNode,
1140                         rPam.End()->nNode );
1141             aPam.Start()->nContent = 0;
1142             aPam.End()->nContent = rPam.End()->nNode.GetNode().GetTxtNode()->Len();
1143             ResetAttrs( aPam, sal_False, &aResetAttrsArray );
1144         }
1145         else
1146         {
1147             ResetAttrs( rPam, sal_False, &aResetAttrsArray );
1148         }
1149         // <--
1150     }
1151     else
1152     {
1153         InsertPoolItem( rPam,
1154             SfxBoolItem( RES_PARATR_LIST_ISCOUNTED, sal_False ), 0 );
1155     }
1156 }
1157 
1158 void SwDoc::SetNumRuleStart( const SwPosition& rPos, sal_Bool bFlag )
1159 {
1160 	SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
1161 
1162     if (pTxtNd)
1163     {
1164         const SwNumRule* pRule = pTxtNd->GetNumRule();
1165         if( pRule && !bFlag != !pTxtNd->IsListRestart())
1166         {
1167             if (GetIDocumentUndoRedo().DoesUndo())
1168             {
1169                 SwUndo *const pUndo( new SwUndoNumRuleStart(rPos, bFlag) );
1170                 GetIDocumentUndoRedo().AppendUndo(pUndo);
1171             }
1172 
1173             pTxtNd->SetListRestart(bFlag ? true : false);
1174 
1175             SetModified();
1176         }
1177 	}
1178 }
1179 
1180 void SwDoc::SetNodeNumStart( const SwPosition& rPos, sal_uInt16 nStt )
1181 {
1182 	SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
1183 
1184     if (pTxtNd)
1185     {
1186         // --> OD 2008-02-27 #refactorlists#
1187 //        const SwNumRule* pRule = pTxtNd->GetNumRule();
1188 //        if( pRule && nStt != pTxtNd->GetListRestartValue() )
1189 //        {
1190 //            if( DoesUndo() )
1191 //            {
1192 //                ClearRedo();
1193 //                AppendUndo( new SwUndoNumRuleStart( rPos, nStt ));
1194 //            }
1195 //        }
1196 //        pTxtNd->SetListRestartValue(nStt);
1197 
1198 //        SetModified();
1199         if ( !pTxtNd->HasAttrListRestartValue() ||
1200              pTxtNd->GetAttrListRestartValue() != nStt )
1201         {
1202             if (GetIDocumentUndoRedo().DoesUndo())
1203             {
1204                 SwUndo *const pUndo( new SwUndoNumRuleStart(rPos, nStt) );
1205                 GetIDocumentUndoRedo().AppendUndo(pUndo);
1206             }
1207             pTxtNd->SetAttrListRestartValue( nStt );
1208 
1209             SetModified();
1210         }
1211         // <--
1212 	}
1213 }
1214 
1215 	// loeschen geht nur, wenn die Rule niemand benutzt!
1216 sal_Bool SwDoc::DelNumRule( const String& rName, sal_Bool bBroadcast )
1217 {
1218 	sal_uInt16 nPos = FindNumRule( rName );
1219 
1220     // --> OD 2007-12-17 #151213#
1221     if ( (*pNumRuleTbl)[ nPos ] == GetOutlineNumRule() )
1222     {
1223         ASSERT( false,
1224                 "<SwDoc::DelNumRule(..)> - No deletion of outline list style. This is serious defect - please inform OD" );
1225         return sal_False;
1226     }
1227     // <--
1228 
1229     if( USHRT_MAX != nPos && !IsUsed( *(*pNumRuleTbl)[ nPos ] ))
1230 	{
1231         if (GetIDocumentUndoRedo().DoesUndo())
1232         {
1233             SwUndo * pUndo =
1234                 new SwUndoNumruleDelete(*(*pNumRuleTbl)[nPos], this);
1235             GetIDocumentUndoRedo().AppendUndo(pUndo);
1236         }
1237 
1238         if (bBroadcast)
1239             BroadcastStyleOperation(rName, SFX_STYLE_FAMILY_PSEUDO,
1240                                     SFX_STYLESHEET_ERASED);
1241 
1242         // --> OD 2008-04-02 #refactorlists#
1243         deleteListForListStyle( rName );
1244         {
1245             // delete further list, which have the deleted list style as default list style
1246             std::vector< SwList* > aListsForDeletion;
1247             tHashMapForLists::iterator aListIter = maLists.begin();
1248             while ( aListIter != maLists.end() )
1249             {
1250                 SwList* pList = (*aListIter).second;
1251                 if ( pList->GetDefaultListStyleName() == rName )
1252                 {
1253                     aListsForDeletion.push_back( pList );
1254                 }
1255 
1256                 ++aListIter;
1257             }
1258             while ( aListsForDeletion.size() > 0 )
1259             {
1260                 SwList* pList = aListsForDeletion.back();
1261                 aListsForDeletion.pop_back();
1262                 deleteList( pList->GetListId() );
1263             }
1264         }
1265         // <--
1266         // --> FME 2004-11-02 #i34097# DeleteAndDestroy deletes rName if
1267         // rName is directly taken from the numrule.
1268         const String aTmpName( rName );
1269         // <--
1270         pNumRuleTbl->DeleteAndDestroy( nPos );
1271         maNumRuleMap.erase(aTmpName);
1272 
1273 		SetModified();
1274 		return sal_True;
1275 	}
1276 	return sal_False;
1277 }
1278 
1279 // #106897#
1280 void SwDoc::ChgNumRuleFmts( const SwNumRule& rRule, const String * pName )
1281 {
1282     // #106897#
1283 	SwNumRule* pRule = FindNumRulePtr( pName ? *pName : rRule.GetName() );
1284 	if( pRule )
1285 	{
1286 		SwUndoInsNum* pUndo = 0;
1287         if (GetIDocumentUndoRedo().DoesUndo())
1288         {
1289 			pUndo = new SwUndoInsNum( *pRule, rRule );
1290 			pUndo->GetHistory();
1291             GetIDocumentUndoRedo().AppendUndo( pUndo );
1292         }
1293 		::lcl_ChgNumRule( *this, rRule );
1294 
1295 		if( pUndo )
1296 			pUndo->SetLRSpaceEndPos();
1297 
1298 		SetModified();
1299 	}
1300 }
1301 
1302 sal_Bool SwDoc::RenameNumRule(const String & rOldName, const String & rNewName,
1303                               sal_Bool bBroadcast)
1304 {
1305     sal_Bool bResult = sal_False;
1306     SwNumRule * pNumRule = FindNumRulePtr(rOldName);
1307 
1308     if (pNumRule)
1309     {
1310         if (GetIDocumentUndoRedo().DoesUndo())
1311         {
1312             SwUndo * pUndo = new SwUndoNumruleRename(rOldName, rNewName, this);
1313             GetIDocumentUndoRedo().AppendUndo(pUndo);
1314         }
1315 
1316         // --> OD 2008-02-19 #refactorlists#
1317 //        SwNumRuleInfo aInfo(rOldName);
1318 //        aInfo.MakeList(*this);
1319         SwNumRule::tTxtNodeList aTxtNodeList;
1320         pNumRule->GetTxtNodeList( aTxtNodeList );
1321         // <--
1322 
1323         // --> OD 2008-07-08 #i91400#
1324         pNumRule->SetName( rNewName, *this );
1325         // <--
1326 
1327         SwNumRuleItem aItem(rNewName);
1328         // --> OD 2008-02-19 #refactorlists#
1329 //        for (sal_uLong nI = 0; nI < aInfo.GetList().Count(); ++nI)
1330 //        {
1331 //            SwTxtNode * pTxtNd = aInfo.GetList().GetObject(nI);
1332 //            pTxtNd->SwCntntNode::SetAttr(aItem);
1333 //        }
1334         for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
1335               aIter != aTxtNodeList.end(); ++aIter )
1336         {
1337             SwTxtNode * pTxtNd = *aIter;
1338             pTxtNd->SetAttr(aItem);
1339         }
1340         // <--
1341 
1342         bResult = sal_True;
1343 
1344         if (bBroadcast)
1345             BroadcastStyleOperation(rOldName, SFX_STYLE_FAMILY_PSEUDO,
1346                                     SFX_STYLESHEET_MODIFIED);
1347     }
1348 
1349     return bResult;
1350 }
1351 
1352 void SwDoc::StopNumRuleAnimations( OutputDevice* pOut )
1353 {
1354 	for( sal_uInt16 n = GetNumRuleTbl().Count(); n; )
1355 	{
1356         SwNumRule::tTxtNodeList aTxtNodeList;
1357         GetNumRuleTbl()[ --n ]->GetTxtNodeList( aTxtNodeList );
1358         for ( SwNumRule::tTxtNodeList::iterator aTxtNodeIter = aTxtNodeList.begin();
1359               aTxtNodeIter != aTxtNodeList.end(); ++aTxtNodeIter )
1360         {
1361             SwTxtNode* pTNd = *aTxtNodeIter;
1362             SwIterator<SwTxtFrm,SwTxtNode> aIter(*pTNd);
1363             for(SwTxtFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
1364                 if( pFrm->HasAnimation() )
1365                     pFrm->StopAnimation( pOut );
1366         }
1367 	}
1368 }
1369 
1370 sal_Bool SwDoc::ReplaceNumRule( const SwPosition& rPos,
1371 							const String& rOldRule, const String& rNewRule )
1372 {
1373 	sal_Bool bRet = sal_False;
1374 	SwNumRule *pOldRule = FindNumRulePtr( rOldRule ),
1375 			  *pNewRule = FindNumRulePtr( rNewRule );
1376 	if( pOldRule && pNewRule && pOldRule != pNewRule )
1377 	{
1378         // --> OD 2008-02-19 #refactorlists#
1379         SwUndoInsNum* pUndo = 0;
1380         if (GetIDocumentUndoRedo().DoesUndo())
1381         {
1382             // Start/End for attributes!
1383             GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
1384             pUndo = new SwUndoInsNum( rPos, *pNewRule, rOldRule );
1385             GetIDocumentUndoRedo().AppendUndo(pUndo);
1386         }
1387 
1388         // --> OD 2008-02-19 #refactorlists#
1389         // apply new list style <pNewRule> to all text nodes, which have the
1390         // old list style <pOldNRule> applied and belong to the same list as
1391         // the text node of the given <SwPosition>.
1392 //        SwNumRuleInfo aUpd( rOldRule );
1393 //        aUpd.MakeList( *this );
1394 
1395 //        if (aUpd.GetList().Count() > 0)    // #106897#
1396         SwNumRule::tTxtNodeList aTxtNodeList;
1397         pOldRule->GetTxtNodeList( aTxtNodeList );
1398         if ( aTxtNodeList.size() > 0 )
1399         {
1400 //            // Position suchen und bestimme ob ein Node davor oder dahinter
1401 //            // einen Start erzwingt
1402 //            SwTxtNode* pTxtNd;
1403 //            sal_uLong nFndPos, nFirst, nLast;
1404 
1405 //            if( TABLE_ENTRY_NOTFOUND != aUpd.GetList().SearchKey(
1406 //                                                                 rPos.nNode.GetIndex(), &nFndPos ))
1407 //                ++nFndPos;
1408 
1409 //            for( nLast = nFndPos; nLast < aUpd.GetList().Count(); ++nLast )
1410 //            {
1411 //                pTxtNd = aUpd.GetList().GetObject( nLast );
1412 //                if(pTxtNd->IsRestart())
1413 //                    break;
1414 //            }
1415 //            for( nFirst = nFndPos; nFirst; )
1416 //            {
1417 //                pTxtNd = aUpd.GetList().GetObject( --nFirst );
1418 //                if( pTxtNd->IsRestart() )
1419 //                    break;
1420 //            }
1421 //            // dann neue Numerierung ueber diesen Bereich
1422 //            // definieren und den Start am Anfang/Ende zurueck setzen
1423 //            pTxtNd = aUpd.GetList().GetObject( nFirst );
1424 //            if( pTxtNd->IsRestart() )
1425 //            {
1426 //                pTxtNd->SetRestart(false);
1427 //                if( pUndo )
1428 //                    pUndo->SetSttNum( pTxtNd->GetIndex() );
1429 //            }
1430 
1431             SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 );
1432             sal_uInt16 nChgFmtLevel = 0;
1433             for( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
1434             {
1435                 const SwNumFmt& rOldFmt = pOldRule->Get( n ),
1436                     & rNewFmt = pNewRule->Get( n );
1437 
1438                 if( rOldFmt.GetAbsLSpace() != rNewFmt.GetAbsLSpace() ||
1439                     rOldFmt.GetFirstLineOffset() != rNewFmt.GetFirstLineOffset() )
1440                     nChgFmtLevel |= ( 1 << n );
1441             }
1442 
1443             const SwTxtNode* pGivenTxtNode = rPos.nNode.GetNode().GetTxtNode();
1444             SwNumRuleItem aRule( rNewRule );
1445 //            for( ; nFirst < nLast; ++nFirst )
1446 //            {
1447 //                pTxtNd = aUpd.GetList().GetObject( nFirst );
1448 
1449 //                aRegH.RegisterInModify( pTxtNd, *pTxtNd );
1450 
1451 //                pTxtNd->SwCntntNode::SetAttr( aRule );
1452 //                pTxtNd->NumRuleChgd();
1453 //            }
1454             for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
1455                   aIter != aTxtNodeList.end(); ++aIter )
1456             {
1457                 SwTxtNode* pTxtNd = *aIter;
1458 
1459                 if ( pGivenTxtNode &&
1460                      pGivenTxtNode->GetListId() == pTxtNd->GetListId() )
1461                 {
1462                     aRegH.RegisterInModify( pTxtNd, *pTxtNd );
1463 
1464                     pTxtNd->SetAttr( aRule );
1465                     pTxtNd->NumRuleChgd();
1466                 }
1467             }
1468             GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
1469             SetModified();
1470 
1471             bRet = sal_True;     // #106897#
1472         }
1473     }
1474 
1475 	return bRet;
1476 }
1477 
1478 // --> OD 2008-03-18 #refactorlists#
1479 namespace
1480 {
1481     struct ListStyleData
1482     {
1483         SwNumRule* pReplaceNumRule;
1484         bool bCreateNewList;
1485         String sListId;
1486 
1487         ListStyleData()
1488             : pReplaceNumRule( 0 ),
1489               bCreateNewList( false ),
1490               sListId()
1491         {}
1492     };
1493 }
1494 // <--
1495 
1496 void SwDoc::MakeUniqueNumRules(const SwPaM & rPaM)
1497 {
1498     ASSERT( rPaM.GetDoc() == this, "need same doc" );
1499 
1500     // --> OD 2008-03-18 #refactorlists#
1501 //    map<SwNumRule *, SwNumRule *> aMyNumRuleMap;
1502     ::std::map<SwNumRule *, ListStyleData> aMyNumRuleMap;
1503     // <--
1504 
1505  	sal_uLong nStt = rPaM.Start()->nNode.GetIndex();
1506 	sal_uLong nEnd = rPaM.End()->nNode.GetIndex();
1507 
1508     bool bFirst = true;
1509 
1510     for (sal_uLong n = nStt; n <= nEnd; n++)
1511     {
1512         SwTxtNode * pCNd = GetNodes()[n]->GetTxtNode();
1513 
1514         if (pCNd)
1515         {
1516             SwNumRule * pRule = pCNd->GetNumRule();
1517 
1518             if (pRule && pRule->IsAutoRule() && ! pRule->IsOutlineRule())
1519             {
1520                 // --> OD 2008-03-18 #refactorlists#
1521 //                SwNumRule * pReplaceNumRule = aMyNumRuleMap[pRule];
1522                 ListStyleData aListStyleData = aMyNumRuleMap[pRule];
1523 
1524 //                if (! pReplaceNumRule)
1525                 if ( aListStyleData.pReplaceNumRule == 0 )
1526                 {
1527                     if (bFirst)
1528                     {
1529                         SwPosition aPos(*pCNd);
1530                         aListStyleData.pReplaceNumRule =
1531                             const_cast<SwNumRule *>
1532                             (SearchNumRule( aPos, false, pCNd->HasNumber(),
1533                                             false, 0,
1534                                             aListStyleData.sListId, true ));
1535                     }
1536 
1537 //                    if (! pReplaceNumRule)
1538                     if ( aListStyleData.pReplaceNumRule == 0 )
1539                     {
1540 //                        pReplaceNumRule = new SwNumRule(*pRule);
1541 //                        pReplaceNumRule->SetName(GetUniqueNumRuleName());
1542                         aListStyleData.pReplaceNumRule = new SwNumRule(*pRule);
1543                         // --> OD 2008-07-08 #i91400#
1544                         aListStyleData.pReplaceNumRule->SetName(
1545                                                 GetUniqueNumRuleName(), *this );
1546                         // <--
1547                         aListStyleData.bCreateNewList = true;
1548                     }
1549 
1550 //                    aMyNumRuleMap[pRule] = pReplaceNumRule;
1551                     aMyNumRuleMap[pRule] = aListStyleData;
1552                 }
1553 
1554                 SwPaM aPam(*pCNd);
1555 
1556                 SetNumRule( aPam, *aListStyleData.pReplaceNumRule,
1557                             aListStyleData.bCreateNewList,
1558                             aListStyleData.sListId );
1559                 if ( aListStyleData.bCreateNewList )
1560                 {
1561                     aListStyleData.bCreateNewList = false;
1562                     aListStyleData.sListId = pCNd->GetListId();
1563                     aMyNumRuleMap[pRule] = aListStyleData;
1564                 }
1565                 // <--
1566 
1567                 bFirst = false;
1568             }
1569         }
1570     }
1571 }
1572 
1573 sal_Bool SwDoc::NoNum( const SwPaM& rPam )
1574 {
1575 
1576 	sal_Bool bRet = SplitNode( *rPam.GetPoint(), false );
1577 	// ist ueberhaupt Nummerierung im Spiel ?
1578 	if( bRet )
1579 	{
1580 		// NoNum setzen und Upaten
1581 		const SwNodeIndex& rIdx = rPam.GetPoint()->nNode;
1582 		SwTxtNode* pNd = rIdx.GetNode().GetTxtNode();
1583 		const SwNumRule* pRule = pNd->GetNumRule();
1584 		if( pRule )
1585 		{
1586             pNd->SetCountedInList(false);
1587 
1588 			SetModified();
1589 		}
1590 		else
1591 			bRet = sal_False;	// keine Nummerierung , ?? oder immer sal_True ??
1592 	}
1593 	return bRet;
1594 }
1595 
1596 void SwDoc::DelNumRules( const SwPaM& rPam )
1597 {
1598 	sal_uLong nStt = rPam.GetPoint()->nNode.GetIndex(),
1599 			nEnd = rPam.GetMark()->nNode.GetIndex();
1600 	if( nStt > nEnd )
1601 	{
1602 		sal_uLong nTmp = nStt; nStt = nEnd; nEnd = nTmp;
1603 	}
1604 
1605 	SwUndoDelNum* pUndo;
1606     if (GetIDocumentUndoRedo().DoesUndo())
1607     {
1608         pUndo = new SwUndoDelNum( rPam );
1609         GetIDocumentUndoRedo().AppendUndo(pUndo);
1610     }
1611     else
1612 		pUndo = 0;
1613 
1614     SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 );
1615 
1616 	SwNumRuleItem aEmptyRule( aEmptyStr );
1617 	const SwNode* pOutlNd = 0;
1618 	for( ; nStt <= nEnd; ++nStt )
1619 	{
1620 		SwTxtNode* pTNd = GetNodes()[ nStt ]->GetTxtNode();
1621         // --> OD 2008-03-13 #refactorlists#
1622 //        if( pTNd && 0 != ( pItem = pTNd->GetNoCondAttr(
1623 //            RES_PARATR_NUMRULE, sal_True ) ) &&
1624 //            ( pName = &((SwNumRuleItem*)pItem)->GetValue())->Len() )
1625         SwNumRule* pNumRuleOfTxtNode = pTNd ? pTNd->GetNumRule() : 0;
1626         if ( pTNd && pNumRuleOfTxtNode )
1627         // <--
1628 		{
1629             // recognize changes of attribute for undo
1630 			aRegH.RegisterInModify( pTNd, *pTNd );
1631 
1632 			if( pUndo )
1633                 pUndo->AddNode( *pTNd, sal_False );
1634 
1635             // directly set list style attribute is reset, otherwise empty
1636             // list style is applied
1637             const SfxItemSet* pAttrSet = pTNd->GetpSwAttrSet();
1638             if ( pAttrSet &&
1639                  pAttrSet->GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET )
1640                 pTNd->ResetAttr( RES_PARATR_NUMRULE );
1641 			else
1642                 pTNd->SetAttr( aEmptyRule );
1643 
1644             // --> OD 2008-03-26 #refactorlists#
1645             pTNd->ResetAttr( RES_PARATR_LIST_ID );
1646             pTNd->ResetAttr( RES_PARATR_LIST_LEVEL );
1647             pTNd->ResetAttr( RES_PARATR_LIST_ISRESTART );
1648             pTNd->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
1649             pTNd->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
1650             // <--
1651 
1652 			if( RES_CONDTXTFMTCOLL == pTNd->GetFmtColl()->Which() )
1653 				pTNd->ChkCondColl();
1654 			//else if( !pOutlNd && NO_NUMBERING != //#outline level,zhaojianwei
1655 			//	((SwTxtFmtColl*)pTNd->GetFmtColl())->GetOutlineLevel() )
1656 			else if( !pOutlNd &&
1657 				((SwTxtFmtColl*)pTNd->GetFmtColl())->IsAssignedToListLevelOfOutlineStyle() )//<-end,zhaojianwei
1658 				pOutlNd = pTNd;
1659 		}
1660 	}
1661 
1662 	// dann noch alle Updaten
1663 	UpdateNumRule();
1664 
1665 	if( pOutlNd )
1666 		GetNodes().UpdtOutlineIdx( *pOutlNd );
1667 }
1668 
1669 void SwDoc::InvalidateNumRules()
1670 {
1671     for (sal_uInt16 n = 0; n < pNumRuleTbl->Count(); ++n)
1672         (*pNumRuleTbl)[n]->SetInvalidRule(sal_True);
1673 }
1674 
1675 	// zum naechsten/vorhergehenden Punkt auf gleicher Ebene
1676 
1677 sal_Bool lcl_IsNumOk( sal_uInt8 nSrchNum, sal_uInt8& rLower, sal_uInt8& rUpper,
1678 					sal_Bool bOverUpper, sal_uInt8 nNumber )
1679 {
1680     // --> OD 2008-04-02 #refactorlists#
1681     ASSERT( nNumber < MAXLEVEL,
1682             "<lcl_IsNumOk(..)> - misusage of method" );
1683     // <--
1684 
1685     sal_Bool bRet = sal_False;
1686 	{
1687 		if( bOverUpper ? nSrchNum == nNumber : nSrchNum >= nNumber )
1688 			bRet = sal_True;
1689 		else if( nNumber > rLower )
1690 			rLower = nNumber;
1691 		else if( nNumber < rUpper )
1692 			rUpper = nNumber;
1693 	}
1694 	return bRet;
1695 }
1696 
1697 sal_Bool lcl_IsValidPrevNextNumNode( const SwNodeIndex& rIdx )
1698 {
1699 	sal_Bool bRet = sal_False;
1700 	const SwNode& rNd = rIdx.GetNode();
1701 	switch( rNd.GetNodeType() )
1702 	{
1703 	case ND_ENDNODE:
1704         bRet = SwTableBoxStartNode == rNd.StartOfSectionNode()->GetStartNodeType() ||
1705                 rNd.StartOfSectionNode()->IsSectionNode();
1706 		break;
1707 
1708 	case ND_STARTNODE:
1709 		bRet = SwTableBoxStartNode == ((SwStartNode&)rNd).GetStartNodeType();
1710 		break;
1711 
1712 	case ND_SECTIONNODE:			// der ist erlaubt, also weiter
1713 		bRet = sal_True;
1714 		break;
1715 	}
1716 	return bRet;
1717 }
1718 
1719 sal_Bool lcl_GotoNextPrevNum( SwPosition& rPos, sal_Bool bNext,
1720 							sal_Bool bOverUpper, sal_uInt8* pUpper, sal_uInt8* pLower )
1721 {
1722 	const SwTxtNode* pNd = rPos.nNode.GetNode().GetTxtNode();
1723 	const SwNumRule* pRule;
1724 	if( !pNd || 0 == ( pRule = pNd->GetNumRule()))
1725 		return sal_False;
1726 
1727     sal_uInt8 nSrchNum = static_cast<sal_uInt8>(pNd->GetActualListLevel());
1728 
1729 	SwNodeIndex aIdx( rPos.nNode );
1730     if( ! pNd->IsCountedInList() )
1731 	{
1732 		// falls gerade mal NO_NUMLEVEL an ist, so such den vorherigen Node
1733 		// mit Nummerierung
1734 		sal_Bool bError = sal_False;
1735 		do {
1736 			aIdx--;
1737 			if( aIdx.GetNode().IsTxtNode() )
1738 			{
1739 				pNd = aIdx.GetNode().GetTxtNode();
1740                 pRule = pNd->GetNumRule();
1741 
1742                 sal_uInt8 nTmpNum;
1743 
1744 				if( pRule  )
1745 				{
1746                     nTmpNum = static_cast<sal_uInt8>(pNd->GetActualListLevel());
1747                     if( !( ! pNd->IsCountedInList() &&
1748 						 (nTmpNum >= nSrchNum )) )
1749 						break;		// gefunden
1750 				}
1751 				else
1752 					bError = sal_True;
1753 			}
1754 			else
1755 				bError = !lcl_IsValidPrevNextNumNode( aIdx );
1756 
1757 		} while( !bError );
1758 		if( bError )
1759 			return sal_False;
1760 	}
1761 
1762 	sal_uInt8 nLower = nSrchNum, nUpper = nSrchNum;
1763 	sal_Bool bRet = sal_False;
1764 
1765 	const SwTxtNode* pLast;
1766 	if( bNext )
1767 		aIdx++, pLast = pNd;
1768 	else
1769 		aIdx--, pLast = 0;
1770 
1771 	while( bNext ? ( aIdx.GetIndex() < aIdx.GetNodes().Count() - 1 )
1772 				 : aIdx.GetIndex() )
1773 	{
1774 		if( aIdx.GetNode().IsTxtNode() )
1775 		{
1776 			pNd = aIdx.GetNode().GetTxtNode();
1777             pRule = pNd->GetNumRule();
1778 			if( pRule )
1779 			{
1780 				if( ::lcl_IsNumOk( nSrchNum, nLower, nUpper, bOverUpper,
1781                                     static_cast<sal_uInt8>(pNd->GetActualListLevel()) ))
1782 				{
1783 					rPos.nNode = aIdx;
1784 					rPos.nContent.Assign( (SwTxtNode*)pNd, 0 );
1785 					bRet = sal_True;
1786 					break;
1787 				}
1788 				else
1789 					pLast = pNd;
1790 			}
1791 			else
1792 				break;
1793 		}
1794 		else if( !lcl_IsValidPrevNextNumNode( aIdx ))
1795 			break;
1796 
1797 		if( bNext )
1798 			aIdx++;
1799 		else
1800 			aIdx--;
1801 	}
1802 
1803 	if( !bRet && !bOverUpper && pLast )		// nicht ueber hoehere Nummmern, aber bis Ende
1804 	{
1805 		if( bNext )
1806 		{
1807 			rPos.nNode = aIdx;
1808 			if( aIdx.GetNode().IsCntntNode() )
1809 				rPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), 0 );
1810 		}
1811 		else
1812 		{
1813 			rPos.nNode.Assign( *pLast );
1814 			rPos.nContent.Assign( (SwTxtNode*)pLast, 0 );
1815 		}
1816 		bRet = sal_True;
1817 	}
1818 
1819 	if( bRet )
1820 	{
1821 		if( pUpper )
1822 			*pUpper = nUpper;
1823 		if( pLower )
1824 			*pLower = nLower;
1825 	}
1826 	return bRet;
1827 }
1828 
1829 sal_Bool SwDoc::GotoNextNum( SwPosition& rPos, sal_Bool bOverUpper,
1830 							sal_uInt8* pUpper, sal_uInt8* pLower  )
1831 {
1832    return ::lcl_GotoNextPrevNum( rPos, sal_True, bOverUpper, pUpper, pLower );
1833 }
1834 
1835 // -> #i23731#
1836 // --> OD 2008-03-18 #refactorlists# - add output parameter <sListId>
1837 const SwNumRule *  SwDoc::SearchNumRule(const SwPosition & rPos,
1838                                         const bool bForward,
1839                                         const bool bNum,
1840                                         const bool bOutline,
1841                                         int nNonEmptyAllowed,
1842                                         String& sListId,
1843                                         const bool bInvestigateStartNode)
1844 {
1845     const SwNumRule * pResult = NULL;
1846     SwTxtNode * pTxtNd = rPos.nNode.GetNode().GetTxtNode();
1847     SwNode * pStartFromNode = pTxtNd;
1848 
1849     if (pTxtNd)
1850     {
1851         SwNodeIndex aIdx(rPos.nNode);
1852 
1853         // --> OD 2005-10-20 #i55391#
1854         // - the start node has also been investigated, if requested.
1855         const SwNode * pNode = NULL;
1856         do
1857         {
1858             // --> OD 2005-10-20 #i55391#
1859             if ( !bInvestigateStartNode )
1860             {
1861                 if (bForward)
1862                     aIdx++;
1863                 else
1864                     aIdx--;
1865             }
1866             // <--
1867             if (aIdx.GetNode().IsTxtNode())
1868             {
1869                 pTxtNd = aIdx.GetNode().GetTxtNode();
1870 
1871                 const SwNumRule * pNumRule = pTxtNd->GetNumRule();
1872                 if (pNumRule)
1873                 {
1874                     if ( ( pNumRule->IsOutlineRule() == ( bOutline ? sal_True : sal_False ) ) && // #115901#
1875                          ( ( bNum && pNumRule->Get(0).IsEnumeration()) ||
1876                            ( !bNum && pNumRule->Get(0).IsItemize() ) ) ) // #i22362#, #i29560#
1877                     {
1878                         pResult = pTxtNd->GetNumRule();
1879                         // --> OD 2008-03-18 #refactorlists#
1880                         // provide also the list id, to which the text node belongs.
1881                         sListId = pTxtNd->GetListId();
1882                     }
1883 
1884                     break;
1885                 }
1886                 else if (pTxtNd->Len() > 0 || NULL != pTxtNd->GetNumRule())
1887                 {
1888                     if (nNonEmptyAllowed == 0)
1889                         break;
1890 
1891                     nNonEmptyAllowed--;
1892 
1893                     if (nNonEmptyAllowed < 0)
1894                         nNonEmptyAllowed = -1;
1895                 }
1896             }
1897 
1898             // --> OD 2005-10-20 #i55391#
1899             if ( bInvestigateStartNode )
1900             {
1901                 if (bForward)
1902                     aIdx++;
1903                 else
1904                     aIdx--;
1905             }
1906             // <--
1907 
1908             pNode = &aIdx.GetNode();
1909         }
1910         while (!(pNode == GetNodes().DocumentSectionStartNode(pStartFromNode) ||
1911                  pNode == GetNodes().DocumentSectionEndNode(pStartFromNode)));
1912         // <--
1913     }
1914 
1915     return pResult;
1916 }
1917 // <- #i23731#
1918 
1919 sal_Bool SwDoc::GotoPrevNum( SwPosition& rPos, sal_Bool bOverUpper,
1920 							sal_uInt8* pUpper, sal_uInt8* pLower  )
1921 {
1922    return ::lcl_GotoNextPrevNum( rPos, sal_False, bOverUpper, pUpper, pLower );
1923 }
1924 
1925 sal_Bool SwDoc::NumUpDown( const SwPaM& rPam, sal_Bool bDown )
1926 {
1927 	sal_uLong nStt = rPam.GetPoint()->nNode.GetIndex(),
1928 			nEnd = rPam.GetMark()->nNode.GetIndex();
1929 	if( nStt > nEnd )
1930 	{
1931 		sal_uLong nTmp = nStt; nStt = nEnd; nEnd = nTmp;
1932 	}
1933 
1934     // -> #115901# outline nodes are promoted or demoted differently
1935     bool bOnlyOutline = true;
1936     bool bOnlyNonOutline = true;
1937     for (sal_uLong n = nStt; n <= nEnd; n++)
1938     {
1939         SwTxtNode * pTxtNd = GetNodes()[n]->GetTxtNode();
1940 
1941         if (pTxtNd)
1942         {
1943             SwNumRule * pRule = pTxtNd->GetNumRule();
1944 
1945             if (pRule)
1946             {
1947                 if (pRule->IsOutlineRule())
1948                     bOnlyNonOutline = false;
1949                 else
1950                     bOnlyOutline = false;
1951             }
1952         }
1953     }
1954     // <- #115901#
1955 
1956     sal_Bool bRet = sal_True;
1957     char nDiff = bDown ? 1 : -1;
1958 
1959     // ->#115901#
1960     if (bOnlyOutline)
1961         bRet = OutlineUpDown(rPam, nDiff);
1962     else if (bOnlyNonOutline)
1963     {
1964         /* --> #i24560#
1965 
1966         Only promote or demote if all selected paragraphs are
1967         promotable resp. demotable.
1968 
1969         */
1970         for (sal_uLong nTmp = nStt; nTmp <= nEnd; ++nTmp)
1971         {
1972             SwTxtNode* pTNd = GetNodes()[ nTmp ]->GetTxtNode();
1973 
1974             // --> OD 2006-10-19 #134160# - make code robust:
1975             // consider case that the node doesn't denote a text node.
1976             if ( pTNd )
1977             {
1978                 SwNumRule * pRule = pTNd->GetNumRule();
1979 
1980                 if (pRule)
1981                 {
1982                     sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel());
1983                     if( (-1 == nDiff && 0 >= nLevel) ||
1984                         (1 == nDiff && MAXLEVEL - 1 <= nLevel))
1985                         bRet = sal_False;
1986                 }
1987             }
1988             // <--
1989         }
1990 
1991         if( bRet )
1992         {
1993             /* <-- #i24560# */
1994             if (GetIDocumentUndoRedo().DoesUndo())
1995             {
1996                 SwUndo *const pUndo( new SwUndoNumUpDown(rPam, nDiff) );
1997                 GetIDocumentUndoRedo().AppendUndo(pUndo);
1998             }
1999 
2000             String sNumRule;
2001 
2002             for(sal_uLong nTmp = nStt; nTmp <= nEnd; ++nTmp )
2003             {
2004                 SwTxtNode* pTNd = GetNodes()[ nTmp ]->GetTxtNode();
2005 
2006                 if( pTNd)
2007                 {
2008                     SwNumRule * pRule = pTNd->GetNumRule();
2009 
2010                     if (pRule)
2011                     {
2012                         sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel());
2013                         nLevel = nLevel + nDiff;
2014 
2015                         pTNd->SetAttrListLevel(nLevel);
2016                     }
2017                 }
2018             }
2019 
2020             ChkCondColls();
2021             SetModified();
2022         }
2023     }
2024 
2025 	return bRet;
2026 }
2027 
2028 sal_Bool SwDoc::MoveParagraph( const SwPaM& rPam, long nOffset, sal_Bool bIsOutlMv )
2029 {
2030 	const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
2031 
2032 	sal_uLong nStIdx = pStt->nNode.GetIndex();
2033 	sal_uLong nEndIdx = pEnd->nNode.GetIndex();
2034 
2035     // Here are some sophisticated checks whether the wished PaM will be moved or not.
2036     // For moving outlines (bIsOutlMv) I've already done some checks, so here are two different
2037     // checks...
2038     SwNode *pTmp1;
2039     SwNode *pTmp2;
2040     if( bIsOutlMv )
2041     {
2042         // For moving chapters (outline) the following reason will deny the move:
2043         // if a start node is inside the moved area and its end node outside or vice versa.
2044         // If a start node is the first moved paragraph, its end node has to be within the moved
2045         // area, too (e.g. as last node).
2046         // If an end node is the last node of the moved area, its start node has to be a part of
2047         // the moved section, too.
2048         pTmp1 = GetNodes()[ nStIdx ];
2049         if( pTmp1->IsStartNode() )
2050         {   // First is a start node
2051             pTmp2 = pTmp1->EndOfSectionNode();
2052             if( pTmp2->GetIndex() > nEndIdx )
2053                 return sal_False; // Its end node is behind the moved range
2054         }
2055         pTmp1 = pTmp1->StartOfSectionNode()->EndOfSectionNode();
2056         if( pTmp1->GetIndex() <= nEndIdx )
2057             return sal_False; // End node inside but start node before moved range => no.
2058         pTmp1 = GetNodes()[ nEndIdx ];
2059         if( pTmp1->IsEndNode() )
2060         {   // The last one is an end node
2061             pTmp1 = pTmp1->StartOfSectionNode();
2062             if( pTmp1->GetIndex() < nStIdx )
2063                 return sal_False; // Its start node is before the moved range.
2064         }
2065         pTmp1 = pTmp1->StartOfSectionNode();
2066         if( pTmp1->GetIndex() >= nStIdx )
2067             return sal_False; // A start node which ends behind the moved area => no.
2068     }
2069 
2070 	sal_uLong nInStIdx, nInEndIdx;
2071 	long nOffs = nOffset;
2072 	if( nOffset > 0 )
2073 	{
2074 		nInEndIdx = nEndIdx;
2075 		nEndIdx += nOffset;
2076 		++nOffs;
2077 	}
2078 	else
2079 	{
2080         //Impossible to move to negative index
2081         if( sal_uLong(abs( nOffset )) > nStIdx)
2082             return sal_False;
2083 
2084 		nInEndIdx = nStIdx - 1;
2085 		nStIdx += nOffset;
2086 	}
2087 	nInStIdx = nInEndIdx + 1;
2088 	// Folgende Absatzbloecke sollen vertauscht werden:
2089 	// [ nStIdx, nInEndIdx ] mit [ nInStIdx, nEndIdx ]
2090 
2091     if( nEndIdx >= GetNodes().GetEndOfContent().GetIndex() )
2092         return sal_False;
2093 
2094     if( !bIsOutlMv )
2095     {   // And here the restrictions for moving paragraphs other than chapters (outlines)
2096         // The plan is to exchange [nStIdx,nInEndIdx] and [nStartIdx,nEndIdx]
2097         // It will checked if the both "start" nodes as well as the both "end" notes belongs to
2098         // the same start-end-section. This is more restrictive than the conditions checked above.
2099         // E.g. a paragraph will not escape from a section or be inserted to another section.
2100         pTmp1 = GetNodes()[ nStIdx ]->StartOfSectionNode();
2101         pTmp2 = GetNodes()[ nInStIdx ]->StartOfSectionNode();
2102         if( pTmp1 != pTmp2 )
2103             return sal_False; // "start" nodes in different sections
2104         pTmp1 = GetNodes()[ nEndIdx ];
2105         bool bIsEndNode = pTmp1->IsEndNode();
2106         if( !pTmp1->IsStartNode() )
2107         {
2108             pTmp1 = pTmp1->StartOfSectionNode();
2109             if( bIsEndNode ) // For end nodes the first start node is of course inside the range,
2110                 pTmp1 = pTmp1->StartOfSectionNode(); // I've to check the start node of the start node.
2111         }
2112         pTmp1 = pTmp1->EndOfSectionNode();
2113         pTmp2 = GetNodes()[ nInEndIdx ];
2114         if( !pTmp2->IsStartNode() )
2115         {
2116             bIsEndNode = pTmp2->IsEndNode();
2117             pTmp2 = pTmp2->StartOfSectionNode();
2118             if( bIsEndNode )
2119                 pTmp2 = pTmp2->StartOfSectionNode();
2120         }
2121         pTmp2 = pTmp2->EndOfSectionNode();
2122         if( pTmp1 != pTmp2 )
2123             return sal_False; // The "end" notes are in different sections
2124     }
2125 
2126     // auf Redlining testen - darf die Selektion ueberhaupt verschoben
2127     // werden?
2128 	if( !IsIgnoreRedline() )
2129 	{
2130 		sal_uInt16 nRedlPos = GetRedlinePos( pStt->nNode.GetNode(), nsRedlineType_t::REDLINE_DELETE );
2131 		if( USHRT_MAX != nRedlPos )
2132 		{
2133 			SwPosition aStPos( *pStt ), aEndPos( *pEnd );
2134 			aStPos.nContent = 0;
2135 			SwCntntNode* pCNd = pEnd->nNode.GetNode().GetCntntNode();
2136 			aEndPos.nContent = pCNd ? pCNd->Len() : 1;
2137 			sal_Bool bCheckDel = sal_True;
2138 
2139 			// es existiert fuer den Bereich irgendein Redline-Delete-Object
2140 			for( ; nRedlPos < GetRedlineTbl().Count(); ++nRedlPos )
2141 			{
2142 				const SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
2143 				if( !bCheckDel || nsRedlineType_t::REDLINE_DELETE == pTmp->GetType() )
2144 				{
2145 					const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
2146 					switch( ComparePosition( *pRStt, *pREnd, aStPos, aEndPos ))
2147 					{
2148 					case POS_COLLIDE_START:
2149 					case POS_BEHIND:			// Pos1 liegt hinter Pos2
2150 						nRedlPos = GetRedlineTbl().Count();
2151 						break;
2152 
2153 					case POS_COLLIDE_END:
2154 					case POS_BEFORE:			// Pos1 liegt vor Pos2
2155 						break;
2156 					case POS_INSIDE:			// Pos1 liegt vollstaendig in Pos2
2157 						// ist erlaubt, aber checke dann alle nachfolgenden
2158 						// auf Ueberlappungen
2159 						bCheckDel = sal_False;
2160 						break;
2161 
2162 					case POS_OUTSIDE:			// Pos2 liegt vollstaendig in Pos1
2163 					case POS_EQUAL:				// Pos1 ist genauso gross wie Pos2
2164 					case POS_OVERLAP_BEFORE:	// Pos1 ueberlappt Pos2 am Anfang
2165 					case POS_OVERLAP_BEHIND:	// Pos1 ueberlappt Pos2 am Ende
2166 						return sal_False;
2167 					}
2168 				}
2169 			}
2170 		}
2171 	}
2172 
2173 	{
2174 		// DataChanged vorm verschieben verschicken, dann bekommt
2175 		// man noch mit, welche Objecte sich im Bereich befinden.
2176 		// Danach koennen sie vor/hinter der Position befinden.
2177 		SwDataChanged aTmp( rPam, 0 );
2178 	}
2179 
2180 	SwNodeIndex aIdx( nOffset > 0 ? pEnd->nNode : pStt->nNode, nOffs );
2181 	SwNodeRange aMvRg( pStt->nNode, 0, pEnd->nNode, +1 );
2182 
2183 	SwRedline* pOwnRedl = 0;
2184 	if( IsRedlineOn() )
2185 	{
2186 		// wenn der Bereich komplett im eigenen Redline liegt, kann es
2187 		// verschoben werden!
2188 		sal_uInt16 nRedlPos = GetRedlinePos( pStt->nNode.GetNode(), nsRedlineType_t::REDLINE_INSERT );
2189 		if( USHRT_MAX != nRedlPos )
2190 		{
2191 			SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
2192 			const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
2193 			SwRedline aTmpRedl( nsRedlineType_t::REDLINE_INSERT, rPam );
2194 			const SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
2195 			// liegt komplett im Bereich, und ist auch der eigene Redline?
2196 			if( aTmpRedl.IsOwnRedline( *pTmp ) &&
2197 				(pRStt->nNode < pStt->nNode ||
2198 				(pRStt->nNode == pStt->nNode && !pRStt->nContent.GetIndex()) ) &&
2199 				(pEnd->nNode < pREnd->nNode ||
2200 				(pEnd->nNode == pREnd->nNode &&
2201 				 pCEndNd ? pREnd->nContent.GetIndex() == pCEndNd->Len()
2202 						 : !pREnd->nContent.GetIndex() )) )
2203 			{
2204 				pOwnRedl = pTmp;
2205 				if( nRedlPos + 1 < GetRedlineTbl().Count() )
2206 				{
2207 					pTmp = GetRedlineTbl()[ nRedlPos+1 ];
2208 					if( *pTmp->Start() == *pREnd )
2209 						// dann doch nicht!
2210 						pOwnRedl = 0;
2211 				}
2212 
2213 				if( pOwnRedl &&
2214 					!( pRStt->nNode <= aIdx && aIdx <= pREnd->nNode ))
2215 				{
2216 					// nicht in sich selbst, dann auch nicht moven
2217 					pOwnRedl = 0;
2218 				}
2219 			}
2220 		}
2221 
2222 		if( !pOwnRedl )
2223         {
2224             GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
2225 
2226 			// zuerst das Insert, dann das Loeschen
2227 			SwPosition aInsPos( aIdx );
2228 			aInsPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), 0 );
2229 
2230 			SwPaM aPam( pStt->nNode, aMvRg.aEnd );
2231 
2232 			SwPaM& rOrigPam = (SwPaM&)rPam;
2233 			rOrigPam.DeleteMark();
2234 			rOrigPam.GetPoint()->nNode = aIdx.GetIndex() - 1;
2235 
2236 			sal_Bool bDelLastPara = !aInsPos.nNode.GetNode().IsCntntNode();
2237 
2238             /* #101076# When copying to a non-content node Copy will
2239                insert a paragraph before that node and insert before
2240                that inserted node. Copy creates an SwUndoInserts that
2241                does not cover the extra paragraph. Thus we insert the
2242                extra paragraph ourselves, _with_ correct undo
2243                information. */
2244             if (bDelLastPara)
2245             {
2246                 /* aInsPos points to the non-content node. Move it to
2247                    the previous content node. */
2248                 SwPaM aInsPam(aInsPos);
2249                 sal_Bool bMoved = aInsPam.Move(fnMoveBackward);
2250                 ASSERT(bMoved, "No content node found!");
2251 
2252                 if (bMoved)
2253                 {
2254                     /* Append the new node after the content node
2255                        found. The new position to insert the moved
2256                        paragraph at is before the inserted
2257                        paragraph. */
2258                     AppendTxtNode(*aInsPam.GetPoint());
2259                     aInsPos = *aInsPam.GetPoint();
2260                 }
2261             }
2262 
2263             CopyRange( aPam, aInsPos, false );
2264 			if( bDelLastPara )
2265 			{
2266 				// dann muss der letzte leere Node wieder entfernt werden
2267 				aIdx = aInsPos.nNode;
2268 				SwCntntNode* pCNd = GetNodes().GoPrevious( &aInsPos.nNode );
2269 				xub_StrLen nCLen = 0; if( pCNd ) nCLen = pCNd->Len();
2270 				aInsPos.nContent.Assign( pCNd, nCLen );
2271 
2272 				// alle die im zu loeschenden Node stehen, mussen auf den
2273 				// naechsten umgestezt werden
2274 				SwPosition* pPos;
2275 				for( sal_uInt16 n = 0; n < GetRedlineTbl().Count(); ++n )
2276 				{
2277 					SwRedline* pTmp = GetRedlineTbl()[ n ];
2278 					if( ( pPos = &pTmp->GetBound(sal_True))->nNode == aIdx )
2279 					{
2280 						pPos->nNode++;
2281 						pPos->nContent.Assign( pPos->nNode.GetNode().GetCntntNode(),0);
2282 					}
2283 					if( ( pPos = &pTmp->GetBound(sal_False))->nNode == aIdx )
2284 					{
2285 						pPos->nNode++;
2286 						pPos->nContent.Assign( pPos->nNode.GetNode().GetCntntNode(),0);
2287 					}
2288 				}
2289 				CorrRel( aIdx, aInsPos, 0, sal_False );
2290 
2291 				pCNd->JoinNext();
2292 			}
2293 
2294 			rOrigPam.GetPoint()->nNode++;
2295 			rOrigPam.GetPoint()->nContent.Assign( rOrigPam.GetCntntNode(), 0 );
2296 
2297 			RedlineMode_t eOld = GetRedlineMode();
2298 			checkRedlining(eOld);
2299             if (GetIDocumentUndoRedo().DoesUndo())
2300             {
2301                 //JP 06.01.98: MUSS noch optimiert werden!!!
2302                 SetRedlineMode(
2303 			       (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE));
2304                 SwUndo *const pUndo(new SwUndoRedlineDelete(aPam, UNDO_DELETE));
2305                 GetIDocumentUndoRedo().AppendUndo(pUndo);
2306             }
2307 
2308             SwRedline* pNewRedline = new SwRedline( nsRedlineType_t::REDLINE_DELETE, aPam );
2309 
2310             // #101654# prevent assertion from aPam's target being deleted
2311             // (Alternatively, one could just let aPam go out of scope, but
2312             //  that requires touching a lot of code.)
2313             aPam.GetBound(sal_True).nContent.Assign( NULL, 0 );
2314             aPam.GetBound(sal_False).nContent.Assign( NULL, 0 );
2315 
2316             AppendRedline( pNewRedline, true );
2317 
2318 //JP 06.01.98: MUSS noch optimiert werden!!!
2319 SetRedlineMode( eOld );
2320             GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
2321 			SetModified();
2322 
2323 			return sal_True;
2324 		}
2325 	}
2326 
2327 	if( !pOwnRedl && !IsIgnoreRedline() && GetRedlineTbl().Count() )
2328 	{
2329 		SwPaM aTemp(aIdx);
2330 		SplitRedline(aTemp);
2331 	}
2332 
2333 	sal_uLong nRedlSttNd(0), nRedlEndNd(0);
2334 	if( pOwnRedl )
2335 	{
2336 		const SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End();
2337 		nRedlSttNd = pRStt->nNode.GetIndex();
2338 		nRedlEndNd = pREnd->nNode.GetIndex();
2339 	}
2340 
2341 	SwUndoMoveNum* pUndo = 0;
2342     sal_uLong nMoved = 0;
2343     if (GetIDocumentUndoRedo().DoesUndo())
2344     {
2345 		pUndo = new SwUndoMoveNum( rPam, nOffset, bIsOutlMv );
2346         nMoved = rPam.End()->nNode.GetIndex() - rPam.Start()->nNode.GetIndex() + 1;
2347     }
2348 
2349 
2350     MoveNodeRange( aMvRg, aIdx, DOC_MOVEREDLINES );
2351 
2352 	if( pUndo )
2353 	{
2354         // i57907: Under circumstances (sections at the end of a chapter)
2355         // the rPam.Start() is not moved to the new position.
2356         // But aIdx should be at the new end position and as long as the number of moved paragraphs
2357         // is nMoved, I know, where the new position is.
2358 		pUndo->SetStartNode( aIdx.GetIndex() - nMoved );
2359         GetIDocumentUndoRedo().AppendUndo(pUndo);
2360     }
2361 
2362 	if( pOwnRedl )
2363 	{
2364 		SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End();
2365 		if( pRStt->nNode.GetIndex() != nRedlSttNd )
2366 		{
2367 			pRStt->nNode = nRedlSttNd;
2368 			pRStt->nContent.Assign( pRStt->nNode.GetNode().GetCntntNode(),0);
2369 		}
2370 		if( pREnd->nNode.GetIndex() != nRedlEndNd )
2371 		{
2372 			pREnd->nNode = nRedlEndNd;
2373 			SwCntntNode* pCNd = pREnd->nNode.GetNode().GetCntntNode();
2374 			xub_StrLen nL = 0; if( pCNd ) nL = pCNd->Len();
2375 			pREnd->nContent.Assign( pCNd, nL );
2376 		}
2377 	}
2378 
2379 	SetModified();
2380 	return sal_True;
2381 }
2382 
2383 sal_Bool SwDoc::NumOrNoNum( const SwNodeIndex& rIdx, sal_Bool bDel )
2384 {
2385     sal_Bool bResult = sal_False;
2386     SwTxtNode * pTxtNd = rIdx.GetNode().GetTxtNode();
2387 
2388     if (pTxtNd && pTxtNd->GetNumRule() != NULL &&
2389         (pTxtNd->HasNumber() || pTxtNd->HasBullet()))
2390     {
2391         if ( !pTxtNd->IsCountedInList() == !bDel)
2392         {
2393             sal_Bool bOldNum = bDel; // == pTxtNd->IsCounted();
2394             sal_Bool bNewNum = bDel ? sal_False : sal_True;
2395             pTxtNd->SetCountedInList(bNewNum ? true : false);
2396 
2397             SetModified();
2398 
2399             bResult = sal_True;
2400 
2401             if (GetIDocumentUndoRedo().DoesUndo())
2402             {
2403                 SwUndoNumOrNoNum * pUndo =
2404                     new SwUndoNumOrNoNum(rIdx, bOldNum, bNewNum);
2405 
2406                 GetIDocumentUndoRedo().AppendUndo(pUndo);
2407             }
2408         }
2409         else if (bDel && pTxtNd->GetNumRule(sal_False) &&
2410                  pTxtNd->GetActualListLevel() >= 0 &&
2411                  pTxtNd->GetActualListLevel() < MAXLEVEL)
2412         {
2413             SwPaM aPam(*pTxtNd);
2414 
2415             DelNumRules(aPam);
2416 
2417             bResult = sal_True;
2418         }
2419     }
2420 
2421     return bResult;
2422 }
2423 
2424 SwNumRule* SwDoc::GetCurrNumRule( const SwPosition& rPos ) const
2425 {
2426 	SwNumRule* pRet = 0;
2427 	SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
2428 
2429 	if( pTNd )
2430     {
2431         // --> OD 2008-02-20 #refactorlists#
2432 //        pTNd->SyncNumberAndNumRule();
2433         // <--
2434 		pRet = pTNd->GetNumRule();
2435     }
2436 
2437 	return pRet;
2438 }
2439 
2440 sal_uInt16 SwDoc::FindNumRule( const String& rName ) const
2441 {
2442 	for( sal_uInt16 n = pNumRuleTbl->Count(); n; )
2443 		if( (*pNumRuleTbl)[ --n ]->GetName() == rName )
2444 			return n;
2445 
2446     return USHRT_MAX;
2447 }
2448 
2449 SwNumRule* SwDoc::FindNumRulePtr( const String& rName ) const
2450 {
2451     SwNumRule * pResult = 0;
2452 
2453     pResult = maNumRuleMap[rName];
2454 
2455     if ( !pResult )
2456     {
2457         for (sal_uInt16 n = 0; n < pNumRuleTbl->Count(); ++n)
2458         {
2459             if ((*pNumRuleTbl)[n]->GetName() == rName)
2460             {
2461                 pResult = (*pNumRuleTbl)[n];
2462 
2463                 break;
2464             }
2465         }
2466     }
2467 
2468 	return pResult;
2469 }
2470 
2471 // #i36749#
2472 void SwDoc::AddNumRule(SwNumRule * pRule)
2473 {
2474     pNumRuleTbl->Insert(pRule, pNumRuleTbl->Count());
2475     maNumRuleMap[pRule->GetName()] = pRule;
2476     pRule->SetNumRuleMap(&maNumRuleMap);
2477 
2478     // --> OD 2008-03-26 #refactorlists#
2479     createListForListStyle( pRule->GetName() );
2480     // <--
2481 }
2482 
2483 // --> OD 2008-02-11 #newlistlevelattrs#
2484 sal_uInt16 SwDoc::MakeNumRule( const String &rName,
2485             const SwNumRule* pCpy,
2486             sal_Bool bBroadcast,
2487             const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode )
2488 {
2489 	SwNumRule* pNew;
2490 	if( pCpy )
2491 	{
2492 		pNew = new SwNumRule( *pCpy );
2493 
2494         // --> OD 2008-07-08 #i91400#
2495         pNew->SetName( GetUniqueNumRuleName( &rName ), *this );
2496         // <--
2497 		if( pNew->GetName() != rName )
2498 		{
2499 			pNew->SetPoolFmtId( USHRT_MAX );
2500 			pNew->SetPoolHelpId( USHRT_MAX );
2501 			pNew->SetPoolHlpFileId( UCHAR_MAX );
2502             // --> OD 2008-04-03 #refactorlists#
2503             pNew->SetDefaultListId( String() );
2504             // <--
2505 		}
2506 		pNew->CheckCharFmts( this );
2507 	}
2508 	else
2509     {
2510         // --> OD 2008-02-11 #newlistlevelattrs#
2511         pNew = new SwNumRule( GetUniqueNumRuleName( &rName ),
2512                               eDefaultNumberFormatPositionAndSpaceMode );
2513         // <--
2514     }
2515 
2516 	sal_uInt16 nRet = pNumRuleTbl->Count();
2517 
2518     AddNumRule(pNew); // #i36749#
2519 
2520     if (GetIDocumentUndoRedo().DoesUndo())
2521     {
2522         SwUndo * pUndo = new SwUndoNumruleCreate(pNew, this);
2523         GetIDocumentUndoRedo().AppendUndo(pUndo);
2524     }
2525 
2526     if (bBroadcast)
2527         BroadcastStyleOperation(pNew->GetName(), SFX_STYLE_FAMILY_PSEUDO,
2528                                 SFX_STYLESHEET_CREATED);
2529 
2530 	return nRet;
2531 }
2532 
2533 String SwDoc::GetUniqueNumRuleName( const String* pChkStr, sal_Bool bAutoNum ) const
2534 {
2535 	String aName;
2536 	if( bAutoNum )
2537 	{
2538 		long n = Time().GetTime();
2539 		n += Date().GetDate();
2540 		aName = String::CreateFromInt32( n );
2541 		if( pChkStr && !pChkStr->Len() )
2542 			pChkStr = 0;
2543 	}
2544 	else if( pChkStr && pChkStr->Len() )
2545 		aName = *pChkStr;
2546 	else
2547 	{
2548 		pChkStr = 0;
2549 		aName = SW_RESSTR( STR_NUMRULE_DEFNAME );
2550 	}
2551 
2552 	sal_uInt16 nNum(0), nTmp, nFlagSize = ( pNumRuleTbl->Count() / 8 ) +2;
2553 	sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
2554 	memset( pSetFlags, 0, nFlagSize );
2555 
2556 	xub_StrLen nNmLen = aName.Len();
2557 	if( !bAutoNum && pChkStr )
2558 	{
2559 		while( nNmLen-- && '0' <= aName.GetChar( nNmLen ) &&
2560 						   '9' >= aName.GetChar( nNmLen ) )
2561 			; //nop
2562 
2563 		if( ++nNmLen < aName.Len() )
2564 		{
2565 			aName.Erase( nNmLen );
2566 			pChkStr = 0;
2567 		}
2568 	}
2569 
2570 	const SwNumRule* pNumRule;
2571 	sal_uInt16 n;
2572 
2573 	for( n = 0; n < pNumRuleTbl->Count(); ++n )
2574 		if( 0 != ( pNumRule = (*pNumRuleTbl)[ n ] ) )
2575 		{
2576 			const String& rNm = pNumRule->GetName();
2577 			if( rNm.Match( aName ) == nNmLen )
2578 			{
2579 				// Nummer bestimmen und das Flag setzen
2580                 nNum = (sal_uInt16)rNm.Copy( nNmLen ).ToInt32();
2581 				if( nNum-- && nNum < pNumRuleTbl->Count() )
2582 					pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
2583 			}
2584 			if( pChkStr && pChkStr->Equals( rNm ) )
2585 				pChkStr = 0;
2586 		}
2587 
2588 	if( !pChkStr )
2589 	{
2590 		// alle Nummern entsprechend geflag, also bestimme die richtige Nummer
2591 		nNum = pNumRuleTbl->Count();
2592 		for( n = 0; n < nFlagSize; ++n )
2593 			if( 0xff != ( nTmp = pSetFlags[ n ] ))
2594 			{
2595 				// also die Nummer bestimmen
2596 				nNum = n * 8;
2597 				while( nTmp & 1 )
2598 					++nNum, nTmp >>= 1;
2599 				break;
2600 			}
2601 
2602 	}
2603 	delete [] pSetFlags;
2604 	if( pChkStr && pChkStr->Len() )
2605 		return *pChkStr;
2606 	return aName += String::CreateFromInt32( ++nNum );
2607 }
2608 
2609 void SwDoc::UpdateNumRule()
2610 {
2611 	const SwNumRuleTbl& rNmTbl = GetNumRuleTbl();
2612 	for( sal_uInt16 n = 0; n < rNmTbl.Count(); ++n )
2613 		if( rNmTbl[ n ]->IsInvalidRule() )
2614 			rNmTbl[ n ]->Validate();
2615 }
2616 
2617 // --> OD 2008-04-02 #refactorlists#
2618 void SwDoc::MarkListLevel( const String& sListId,
2619                            const int nListLevel,
2620                            const sal_Bool bValue )
2621 {
2622     SwList* pList = getListByName( sListId );
2623 
2624     if ( pList )
2625     {
2626         MarkListLevel( *pList, nListLevel, bValue );
2627     }
2628 }
2629 
2630 void SwDoc::MarkListLevel( SwList& rList,
2631                            const int nListLevel,
2632                            const sal_Bool bValue )
2633 {
2634     // Set new marked list level and notify all affected nodes of the changed mark.
2635     rList.MarkListLevel( nListLevel, bValue );
2636 }
2637 // <- #i27615#
2638 // <--
2639 
2640 // #i23726#
2641 sal_Bool SwDoc::IsFirstOfNumRule(SwPosition & rPos)
2642 {
2643     sal_Bool bResult = sal_False;
2644     SwTxtNode * pTxtNode = rPos.nNode.GetNode().GetTxtNode();
2645 
2646     if (pTxtNode)
2647     {
2648         SwNumRule * pNumRule = pTxtNode->GetNumRule();
2649 
2650         if (pNumRule)
2651             bResult = pTxtNode->IsFirstOfNumRule();
2652     }
2653 
2654     return bResult;
2655 }
2656 
2657 // --> OD 2007-10-26 #i83479#
2658 // implementation for interface <IDocumentListItems>
2659 bool SwDoc::lessThanNodeNum::operator()( const SwNodeNum* pNodeNumOne,
2660                                          const SwNodeNum* pNodeNumTwo ) const
2661 {
2662     return pNodeNumOne->LessThan( *pNodeNumTwo );
2663 }
2664 
2665 void SwDoc::addListItem( const SwNodeNum& rNodeNum )
2666 {
2667     if ( mpListItemsList == 0 )
2668     {
2669         return;
2670     }
2671 
2672     const bool bAlreadyInserted(
2673             mpListItemsList->find( &rNodeNum ) != mpListItemsList->end() );
2674     ASSERT( !bAlreadyInserted,
2675             "<SwDoc::InsertListItem(..)> - <SwNodeNum> instance already registered as numbered item!" );
2676     if ( !bAlreadyInserted )
2677     {
2678         mpListItemsList->insert( &rNodeNum );
2679     }
2680 }
2681 
2682 void SwDoc::removeListItem( const SwNodeNum& rNodeNum )
2683 {
2684     if ( mpListItemsList == 0 )
2685     {
2686         return;
2687     }
2688 
2689     const tImplSortedNodeNumList::size_type nDeleted = mpListItemsList->erase( &rNodeNum );
2690     if ( nDeleted > 1 )
2691     {
2692         ASSERT( false,
2693                 "<SwDoc::RemoveListItem(..)> - <SwNodeNum> was registered more than once as numbered item!" );
2694     }
2695 }
2696 
2697 String SwDoc::getListItemText( const SwNodeNum& rNodeNum,
2698                                const bool bWithNumber,
2699                                const bool bWithSpacesForLevel ) const
2700 {
2701     return rNodeNum.GetTxtNode()
2702            ? rNodeNum.GetTxtNode()->GetExpandTxt( 0, STRING_LEN, bWithNumber,
2703                                                   bWithNumber, bWithSpacesForLevel )
2704            : String();
2705 }
2706 
2707 void SwDoc::getListItems( tSortedNodeNumList& orNodeNumList ) const
2708 {
2709     orNodeNumList.clear();
2710     orNodeNumList.reserve( mpListItemsList->size() );
2711 
2712     tImplSortedNodeNumList::iterator aIter;
2713     tImplSortedNodeNumList::iterator aEndIter = mpListItemsList->end();
2714     for ( aIter = mpListItemsList->begin(); aIter != aEndIter; ++aIter )
2715     {
2716         orNodeNumList.push_back( (*aIter) );
2717     }
2718 }
2719 
2720 void SwDoc::getNumItems( tSortedNodeNumList& orNodeNumList ) const
2721 {
2722     orNodeNumList.clear();
2723     orNodeNumList.reserve( mpListItemsList->size() );
2724 
2725     tImplSortedNodeNumList::iterator aIter;
2726     tImplSortedNodeNumList::iterator aEndIter = mpListItemsList->end();
2727     for ( aIter = mpListItemsList->begin(); aIter != aEndIter; ++aIter )
2728     {
2729         const SwNodeNum* pNodeNum = (*aIter);
2730         if ( pNodeNum->IsCounted() &&
2731              pNodeNum->GetTxtNode() && pNodeNum->GetTxtNode()->HasNumber() )
2732         {
2733             orNodeNumList.push_back( pNodeNum );
2734         }
2735     }
2736 }
2737 // <--
2738 
2739 // --> OD 2007-11-15 #i83479#
2740 // implementation for interface <IDocumentOutlineNodes>
2741 sal_Int32 SwDoc::getOutlineNodesCount() const
2742 {
2743     return GetNodes().GetOutLineNds().Count();
2744 }
2745 
2746 int SwDoc::getOutlineLevel( const sal_Int32 nIdx ) const
2747 {
2748     return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]->
2749                                            // GetTxtNode()->GetOutlineLevel();				//#outline level,zhaojianwei
2750 								GetTxtNode()->GetAttrOutlineLevel()-1;	//<-end,zhaojianwei
2751 }
2752 
2753 String SwDoc::getOutlineText( const sal_Int32 nIdx,
2754                               const bool bWithNumber,
2755                               const bool bWithSpacesForLevel ) const
2756 {
2757     return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]->
2758                 GetTxtNode()->GetExpandTxt( 0, STRING_LEN, bWithNumber,
2759                                             bWithNumber, bWithSpacesForLevel );
2760 }
2761 
2762 SwTxtNode* SwDoc::getOutlineNode( const sal_Int32 nIdx ) const
2763 {
2764     return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]->GetTxtNode();
2765 }
2766 
2767 void SwDoc::getOutlineNodes( IDocumentOutlineNodes::tSortedOutlineNodeList& orOutlineNodeList ) const
2768 {
2769     orOutlineNodeList.clear();
2770     orOutlineNodeList.reserve( getOutlineNodesCount() );
2771 
2772     const sal_uInt16 nOutlCount( static_cast<sal_uInt16>(getOutlineNodesCount()) );
2773     for ( sal_uInt16 i = 0; i < nOutlCount; ++i )
2774     {
2775         orOutlineNodeList.push_back(
2776             GetNodes().GetOutLineNds()[i]->GetTxtNode() );
2777     }
2778 }
2779 // <--
2780 
2781 // --> OD 2008-03-26 #refactorlists#
2782 // implementation of interface IDocumentListsAccess
2783 SwList* SwDoc::createList( String sListId,
2784                            const String sDefaultListStyleName )
2785 {
2786     if ( sListId.Len() == 0 )
2787     {
2788         sListId = listfunc::CreateUniqueListId( *this );
2789     }
2790 
2791     if ( getListByName( sListId ) )
2792     {
2793         ASSERT( false,
2794                 "<SwDoc::createList(..)> - provided list id already used. Serious defect -> please inform OD." );
2795         return 0;
2796     }
2797 
2798     SwNumRule* pDefaultNumRuleForNewList = FindNumRulePtr( sDefaultListStyleName );
2799     if ( !pDefaultNumRuleForNewList )
2800     {
2801         ASSERT( false,
2802                 "<SwDoc::createList(..)> - for provided default list style name no list style is found. Serious defect -> please inform OD." );
2803         return 0;
2804     }
2805 
2806     SwList* pNewList = new SwList( sListId, *pDefaultNumRuleForNewList, GetNodes() );
2807     maLists[sListId] = pNewList;
2808 
2809     return pNewList;
2810 }
2811 
2812 void SwDoc::deleteList( const String sListId )
2813 {
2814     SwList* pList = getListByName( sListId );
2815     if ( pList )
2816     {
2817         maLists.erase( sListId );
2818         delete pList;
2819     }
2820 }
2821 
2822 SwList* SwDoc::getListByName( const String sListId ) const
2823 {
2824     SwList* pList = 0;
2825 
2826     std::hash_map< String, SwList*, StringHash >::const_iterator
2827                                             aListIter = maLists.find( sListId );
2828     if ( aListIter != maLists.end() )
2829     {
2830         pList = (*aListIter).second;
2831     }
2832 
2833     return pList;
2834 }
2835 
2836 SwList* SwDoc::createListForListStyle( const String sListStyleName )
2837 {
2838     if ( sListStyleName.Len() == 0 )
2839     {
2840         ASSERT( false,
2841                 "<SwDoc::createListForListStyle(..)> - no list style name provided. Serious defect -> please inform OD." );
2842         return 0;
2843     }
2844 
2845     if ( getListForListStyle( sListStyleName ) )
2846     {
2847         ASSERT( false,
2848                 "<SwDoc::createListForListStyle(..)> - a list for the provided list style name already exists. Serious defect -> please inform OD." );
2849         return 0;
2850     }
2851 
2852     SwNumRule* pNumRule = FindNumRulePtr( sListStyleName );
2853     if ( !pNumRule )
2854     {
2855         ASSERT( false,
2856                 "<SwDoc::createListForListStyle(..)> - for provided list style name no list style is found. Serious defect -> please inform OD." );
2857         return 0;
2858     }
2859 
2860     String sListId( pNumRule->GetDefaultListId() ); // can be empty String
2861     if ( getListByName( sListId ) )
2862     {
2863         sListId = String();
2864     }
2865     SwList* pNewList = createList( sListId, sListStyleName );
2866     maListStyleLists[sListStyleName] = pNewList;
2867     pNumRule->SetDefaultListId( pNewList->GetListId() );
2868 
2869     return pNewList;
2870 }
2871 
2872 SwList* SwDoc::getListForListStyle( const String sListStyleName ) const
2873 {
2874     SwList* pList = 0;
2875 
2876     std::hash_map< String, SwList*, StringHash >::const_iterator
2877                             aListIter = maListStyleLists.find( sListStyleName );
2878     if ( aListIter != maListStyleLists.end() )
2879     {
2880         pList = (*aListIter).second;
2881     }
2882 
2883     return pList;
2884 }
2885 
2886 void SwDoc::deleteListForListStyle( const String sListStyleName )
2887 {
2888     String sListId;
2889     {
2890         SwList* pList = getListForListStyle( sListStyleName );
2891         ASSERT( pList,
2892                 "<SwDoc::deleteListForListStyle(..)> - misusage of method: no list found for given list style name" );
2893         if ( pList )
2894         {
2895             sListId = pList->GetListId();
2896         }
2897     }
2898     if ( sListId.Len() > 0 )
2899     {
2900         maListStyleLists.erase( sListStyleName );
2901         deleteList( sListId );
2902     }
2903 }
2904 // <--
2905 // --> OD 2008-07-08 #i91400#
2906 void SwDoc::trackChangeOfListStyleName( const String sListStyleName,
2907                                         const String sNewListStyleName )
2908 {
2909     SwList* pList = getListForListStyle( sListStyleName );
2910     ASSERT( pList,
2911             "<SwDoc::changeOfListStyleName(..)> - misusage of method: no list found for given list style name" );
2912 
2913     if ( pList != 0 )
2914     {
2915         maListStyleLists.erase( sListStyleName );
2916         maListStyleLists[sNewListStyleName] = pList;
2917     }
2918 }
2919 // <--
2920 
2921 // --> OD 2008-03-13 #refactorlists#
2922 namespace listfunc
2923 {
2924     const String MakeListIdUnique( const SwDoc& rDoc,
2925                                    const String aSuggestedUniqueListId )
2926     {
2927         long nHitCount = 0;
2928         String aTmpStr = aSuggestedUniqueListId;
2929         while ( rDoc.getListByName( aTmpStr ) )
2930         {
2931             ++nHitCount;
2932             aTmpStr = aSuggestedUniqueListId;
2933             aTmpStr += String::CreateFromInt32( nHitCount );
2934         }
2935 
2936         return aTmpStr;
2937     }
2938     const String CreateUniqueListId( const SwDoc& rDoc )
2939     {
2940         // --> OD 2008-08-06 #i92478#
2941         String aNewListId = String::CreateFromAscii( "list" );
2942         // <--
2943         sal_Int64 n = Time().GetTime();
2944         n += Date().GetDate();
2945         n += rand();
2946         // --> OD 2008-08-06 #i92478#
2947         aNewListId += String::CreateFromInt64( n );
2948         // <--
2949 
2950         return MakeListIdUnique( rDoc, aNewListId );
2951     }
2952 }
2953 // <--
2954