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