xref: /aoo4110/main/sw/source/core/doc/docnum.cxx (revision b1cdbd2c)
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 
GetUpperLvlChg(sal_uInt8 nCurLvl,sal_uInt8 nLevel,sal_uInt16 nMask)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 
SetOutlineNumRule(const SwNumRule & rRule)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 
PropagateOutlineRule()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
OutlineUpDown(const SwPaM & rPam,short nOffset)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 !
MoveOutlinePara(const SwPaM & rPam,short nOffset)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 
lcl_FindOutlineName(const SwNodes & rNds,const String & rName,sal_Bool bExact)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 
lcl_FindOutlineNum(const SwNodes & rNds,String & rName)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 
GotoOutline(SwPosition & rPos,const String & rName) const723 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 
lcl_ChgNumRule(SwDoc & rDoc,const SwNumRule & rRule)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#
SetNumRule(const SwPaM & rPam,const SwNumRule & rRule,const bool bCreateNewList,const String sContinuedListId,sal_Bool bSetItem,const bool bResetIndentAttrs)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     if ( bSetItem )
1015     {
1016         if ( bCreateNewList )
1017         {
1018             String sListId;
1019             if ( !bUpdateRule )
1020             {
1021                 // apply list id of list, which has been created for the new list style
1022                 sListId = pNew->GetDefaultListId();
1023             }
1024             else
1025             {
1026                 // create new list and apply its list id
1027                 SwList* pNewList = createList( String(), pNew->GetName() );
1028                 ASSERT( pNewList,
1029                         "<SwDoc::SetNumRule(..)> - could not create new list. Serious defect -> please inform OD." );
1030                 sListId = pNewList->GetListId();
1031             }
1032             InsertPoolItem( rPam, SfxStringItem( RES_PARATR_LIST_ID, sListId ), 0 );
1033         }
1034         else if ( sContinuedListId.Len() > 0 )
1035         {
1036             // apply given list id
1037             InsertPoolItem( rPam, SfxStringItem( RES_PARATR_LIST_ID, sContinuedListId ), 0 );
1038         }
1039     }
1040 
1041     if ( ! rPam.HasMark())
1042     {
1043         SwTxtNode * pTxtNd = rPam.GetPoint()->nNode.GetNode().GetTxtNode();
1044         // consider case that the PaM doesn't denote a text node - e.g. it denotes a graphic node
1045         if ( pTxtNd )
1046         {
1047             SwNumRule * pRule = pTxtNd->GetNumRule();
1048 
1049             if (pRule && pRule->GetName() == pNew->GetName())
1050             {
1051                 bSetItem = sal_False;
1052                 if ( !pTxtNd->IsInList() )
1053                 {
1054                     pTxtNd->AddToList();
1055                 }
1056             }
1057             // only clear numbering attribute at text node,
1058             // if at paragraph style the new numbering rule is found.
1059             else if ( !pRule )
1060             {
1061                 SwTxtFmtColl* pColl = pTxtNd->GetTxtColl();
1062                 if ( pColl )
1063                 {
1064                     SwNumRule* pCollRule = FindNumRulePtr(pColl->GetNumRule().GetValue());
1065                     if ( pCollRule && pCollRule->GetName() == pNew->GetName() )
1066                     {
1067                         pTxtNd->ResetAttr( RES_PARATR_NUMRULE );
1068                         bSetItem = sal_False;
1069                     }
1070                 }
1071             }
1072         }
1073     }
1074 
1075     if ( bSetItem )
1076     {
1077         InsertPoolItem( rPam, SwNumRuleItem( pNew->GetName() ), 0 );
1078     }
1079 
1080     if ( bResetIndentAttrs &&
1081          pNew && pNew->Get( 0 ).GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
1082     {
1083         SvUShortsSort aResetAttrsArray;
1084         aResetAttrsArray.Insert( RES_LR_SPACE );
1085         // On a selection setup a corresponding Point-and-Mark in order to get
1086         // the indentation attribute reset on all paragraphs touched by the selection
1087         if ( rPam.HasMark() &&
1088              rPam.End()->nNode.GetNode().GetTxtNode() )
1089         {
1090             SwPaM aPam( rPam.Start()->nNode,
1091                         rPam.End()->nNode );
1092             aPam.Start()->nContent = 0;
1093             aPam.End()->nContent = rPam.End()->nNode.GetNode().GetTxtNode()->Len();
1094             ResetAttrs( aPam, sal_False, &aResetAttrsArray );
1095         }
1096         else
1097         {
1098             ResetAttrs( rPam, sal_False, &aResetAttrsArray );
1099         }
1100     }
1101 
1102     if (GetIDocumentUndoRedo().DoesUndo())
1103     {
1104         GetIDocumentUndoRedo().EndUndo( UNDO_INSNUM, NULL );
1105     }
1106 
1107     SetModified();
1108 }
1109 
SetCounted(const SwPaM & rPam,bool bCounted)1110 void SwDoc::SetCounted(const SwPaM & rPam, bool bCounted)
1111 {
1112     if ( bCounted )
1113     {
1114         SvUShortsSort aResetAttrsArray;
1115         aResetAttrsArray.Insert( RES_PARATR_LIST_ISCOUNTED );
1116         // On a selection setup a corresponding Point-and-Mark in order to get
1117         // the list-is-counted attribute reset on all paragraphs touched by the selection
1118         if ( rPam.HasMark() &&
1119              rPam.End()->nNode.GetNode().GetTxtNode() )
1120         {
1121             SwPaM aPam( rPam.Start()->nNode,
1122                         rPam.End()->nNode );
1123             aPam.Start()->nContent = 0;
1124             aPam.End()->nContent = rPam.End()->nNode.GetNode().GetTxtNode()->Len();
1125             ResetAttrs( aPam, sal_False, &aResetAttrsArray );
1126         }
1127         else
1128         {
1129             ResetAttrs( rPam, sal_False, &aResetAttrsArray );
1130         }
1131     }
1132     else
1133     {
1134         InsertPoolItem( rPam, SfxBoolItem( RES_PARATR_LIST_ISCOUNTED, sal_False ), 0 );
1135     }
1136 }
1137 
SetNumRuleStart(const SwPosition & rPos,sal_Bool bFlag)1138 void SwDoc::SetNumRuleStart( const SwPosition& rPos, sal_Bool bFlag )
1139 {
1140 	SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
1141 
1142     if (pTxtNd)
1143     {
1144         const SwNumRule* pRule = pTxtNd->GetNumRule();
1145         if( pRule && !bFlag != !pTxtNd->IsListRestart())
1146         {
1147             if (GetIDocumentUndoRedo().DoesUndo())
1148             {
1149                 SwUndo *const pUndo( new SwUndoNumRuleStart(rPos, bFlag) );
1150                 GetIDocumentUndoRedo().AppendUndo(pUndo);
1151             }
1152 
1153             pTxtNd->SetListRestart(bFlag ? true : false);
1154 
1155             SetModified();
1156         }
1157 	}
1158 }
1159 
SetNodeNumStart(const SwPosition & rPos,sal_uInt16 nStt)1160 void SwDoc::SetNodeNumStart( const SwPosition& rPos, sal_uInt16 nStt )
1161 {
1162 	SwTxtNode* pTxtNd = rPos.nNode.GetNode().GetTxtNode();
1163 
1164     if (pTxtNd)
1165     {
1166         // --> OD 2008-02-27 #refactorlists#
1167 //        const SwNumRule* pRule = pTxtNd->GetNumRule();
1168 //        if( pRule && nStt != pTxtNd->GetListRestartValue() )
1169 //        {
1170 //            if( DoesUndo() )
1171 //            {
1172 //                ClearRedo();
1173 //                AppendUndo( new SwUndoNumRuleStart( rPos, nStt ));
1174 //            }
1175 //        }
1176 //        pTxtNd->SetListRestartValue(nStt);
1177 
1178 //        SetModified();
1179         if ( !pTxtNd->HasAttrListRestartValue() ||
1180              pTxtNd->GetAttrListRestartValue() != nStt )
1181         {
1182             if (GetIDocumentUndoRedo().DoesUndo())
1183             {
1184                 SwUndo *const pUndo( new SwUndoNumRuleStart(rPos, nStt) );
1185                 GetIDocumentUndoRedo().AppendUndo(pUndo);
1186             }
1187             pTxtNd->SetAttrListRestartValue( nStt );
1188 
1189             SetModified();
1190         }
1191         // <--
1192 	}
1193 }
1194 
1195 	// loeschen geht nur, wenn die Rule niemand benutzt!
DelNumRule(const String & rName,sal_Bool bBroadcast)1196 sal_Bool SwDoc::DelNumRule( const String& rName, sal_Bool bBroadcast )
1197 {
1198 	sal_uInt16 nPos = FindNumRule( rName );
1199 
1200     // --> OD 2007-12-17 #151213#
1201     if ( (*pNumRuleTbl)[ nPos ] == GetOutlineNumRule() )
1202     {
1203         ASSERT( false,
1204                 "<SwDoc::DelNumRule(..)> - No deletion of outline list style. This is serious defect - please inform OD" );
1205         return sal_False;
1206     }
1207     // <--
1208 
1209     if( USHRT_MAX != nPos && !IsUsed( *(*pNumRuleTbl)[ nPos ] ))
1210 	{
1211         if (GetIDocumentUndoRedo().DoesUndo())
1212         {
1213             SwUndo * pUndo =
1214                 new SwUndoNumruleDelete(*(*pNumRuleTbl)[nPos], this);
1215             GetIDocumentUndoRedo().AppendUndo(pUndo);
1216         }
1217 
1218         if (bBroadcast)
1219             BroadcastStyleOperation(rName, SFX_STYLE_FAMILY_PSEUDO,
1220                                     SFX_STYLESHEET_ERASED);
1221 
1222         // --> OD 2008-04-02 #refactorlists#
1223         deleteListForListStyle( rName );
1224         {
1225             // delete further list, which have the deleted list style as default list style
1226             std::vector< SwList* > aListsForDeletion;
1227             tHashMapForLists::iterator aListIter = maLists.begin();
1228             while ( aListIter != maLists.end() )
1229             {
1230                 SwList* pList = (*aListIter).second;
1231                 if ( pList->GetDefaultListStyleName() == rName )
1232                 {
1233                     aListsForDeletion.push_back( pList );
1234                 }
1235 
1236                 ++aListIter;
1237             }
1238             while ( aListsForDeletion.size() > 0 )
1239             {
1240                 SwList* pList = aListsForDeletion.back();
1241                 aListsForDeletion.pop_back();
1242                 deleteList( pList->GetListId() );
1243             }
1244         }
1245         // <--
1246         // --> FME 2004-11-02 #i34097# DeleteAndDestroy deletes rName if
1247         // rName is directly taken from the numrule.
1248         const String aTmpName( rName );
1249         // <--
1250         pNumRuleTbl->DeleteAndDestroy( nPos );
1251         maNumRuleMap.erase(aTmpName);
1252 
1253 		SetModified();
1254 		return sal_True;
1255 	}
1256 	return sal_False;
1257 }
1258 
1259 // #106897#
ChgNumRuleFmts(const SwNumRule & rRule,const String * pName)1260 void SwDoc::ChgNumRuleFmts( const SwNumRule& rRule, const String * pName )
1261 {
1262     // #106897#
1263 	SwNumRule* pRule = FindNumRulePtr( pName ? *pName : rRule.GetName() );
1264 	if( pRule )
1265 	{
1266 		SwUndoInsNum* pUndo = 0;
1267         if (GetIDocumentUndoRedo().DoesUndo())
1268         {
1269 			pUndo = new SwUndoInsNum( *pRule, rRule );
1270 			pUndo->GetHistory();
1271             GetIDocumentUndoRedo().AppendUndo( pUndo );
1272         }
1273 		::lcl_ChgNumRule( *this, rRule );
1274 
1275 		if( pUndo )
1276 			pUndo->SetLRSpaceEndPos();
1277 
1278 		SetModified();
1279 	}
1280 }
1281 
RenameNumRule(const String & rOldName,const String & rNewName,sal_Bool bBroadcast)1282 sal_Bool SwDoc::RenameNumRule(const String & rOldName, const String & rNewName,
1283                               sal_Bool bBroadcast)
1284 {
1285     sal_Bool bResult = sal_False;
1286     SwNumRule * pNumRule = FindNumRulePtr(rOldName);
1287 
1288     if (pNumRule)
1289     {
1290         if (GetIDocumentUndoRedo().DoesUndo())
1291         {
1292             SwUndo * pUndo = new SwUndoNumruleRename(rOldName, rNewName, this);
1293             GetIDocumentUndoRedo().AppendUndo(pUndo);
1294         }
1295 
1296         // --> OD 2008-02-19 #refactorlists#
1297 //        SwNumRuleInfo aInfo(rOldName);
1298 //        aInfo.MakeList(*this);
1299         SwNumRule::tTxtNodeList aTxtNodeList;
1300         pNumRule->GetTxtNodeList( aTxtNodeList );
1301         // <--
1302 
1303         // --> OD 2008-07-08 #i91400#
1304         pNumRule->SetName( rNewName, *this );
1305         // <--
1306 
1307         SwNumRuleItem aItem(rNewName);
1308         // --> OD 2008-02-19 #refactorlists#
1309 //        for (sal_uLong nI = 0; nI < aInfo.GetList().Count(); ++nI)
1310 //        {
1311 //            SwTxtNode * pTxtNd = aInfo.GetList().GetObject(nI);
1312 //            pTxtNd->SwCntntNode::SetAttr(aItem);
1313 //        }
1314         for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
1315               aIter != aTxtNodeList.end(); ++aIter )
1316         {
1317             SwTxtNode * pTxtNd = *aIter;
1318             pTxtNd->SetAttr(aItem);
1319         }
1320         // <--
1321 
1322         bResult = sal_True;
1323 
1324         if (bBroadcast)
1325             BroadcastStyleOperation(rOldName, SFX_STYLE_FAMILY_PSEUDO,
1326                                     SFX_STYLESHEET_MODIFIED);
1327     }
1328 
1329     return bResult;
1330 }
1331 
StopNumRuleAnimations(OutputDevice * pOut)1332 void SwDoc::StopNumRuleAnimations( OutputDevice* pOut )
1333 {
1334 	for( sal_uInt16 n = GetNumRuleTbl().Count(); n; )
1335 	{
1336         SwNumRule::tTxtNodeList aTxtNodeList;
1337         GetNumRuleTbl()[ --n ]->GetTxtNodeList( aTxtNodeList );
1338         for ( SwNumRule::tTxtNodeList::iterator aTxtNodeIter = aTxtNodeList.begin();
1339               aTxtNodeIter != aTxtNodeList.end(); ++aTxtNodeIter )
1340         {
1341             SwTxtNode* pTNd = *aTxtNodeIter;
1342             SwIterator<SwTxtFrm,SwTxtNode> aIter(*pTNd);
1343             for(SwTxtFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
1344                 if( pFrm->HasAnimation() )
1345                     pFrm->StopAnimation( pOut );
1346         }
1347 	}
1348 }
1349 
ReplaceNumRule(const SwPosition & rPos,const String & rOldRule,const String & rNewRule)1350 sal_Bool SwDoc::ReplaceNumRule( const SwPosition& rPos,
1351 							const String& rOldRule, const String& rNewRule )
1352 {
1353 	sal_Bool bRet = sal_False;
1354 	SwNumRule *pOldRule = FindNumRulePtr( rOldRule ),
1355 			  *pNewRule = FindNumRulePtr( rNewRule );
1356 	if( pOldRule && pNewRule && pOldRule != pNewRule )
1357 	{
1358         // --> OD 2008-02-19 #refactorlists#
1359         SwUndoInsNum* pUndo = 0;
1360         if (GetIDocumentUndoRedo().DoesUndo())
1361         {
1362             // Start/End for attributes!
1363             GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
1364             pUndo = new SwUndoInsNum( rPos, *pNewRule, rOldRule );
1365             GetIDocumentUndoRedo().AppendUndo(pUndo);
1366         }
1367 
1368         // --> OD 2008-02-19 #refactorlists#
1369         // apply new list style <pNewRule> to all text nodes, which have the
1370         // old list style <pOldNRule> applied and belong to the same list as
1371         // the text node of the given <SwPosition>.
1372 //        SwNumRuleInfo aUpd( rOldRule );
1373 //        aUpd.MakeList( *this );
1374 
1375 //        if (aUpd.GetList().Count() > 0)    // #106897#
1376         SwNumRule::tTxtNodeList aTxtNodeList;
1377         pOldRule->GetTxtNodeList( aTxtNodeList );
1378         if ( aTxtNodeList.size() > 0 )
1379         {
1380 //            // Position suchen und bestimme ob ein Node davor oder dahinter
1381 //            // einen Start erzwingt
1382 //            SwTxtNode* pTxtNd;
1383 //            sal_uLong nFndPos, nFirst, nLast;
1384 
1385 //            if( TABLE_ENTRY_NOTFOUND != aUpd.GetList().SearchKey(
1386 //                                                                 rPos.nNode.GetIndex(), &nFndPos ))
1387 //                ++nFndPos;
1388 
1389 //            for( nLast = nFndPos; nLast < aUpd.GetList().Count(); ++nLast )
1390 //            {
1391 //                pTxtNd = aUpd.GetList().GetObject( nLast );
1392 //                if(pTxtNd->IsRestart())
1393 //                    break;
1394 //            }
1395 //            for( nFirst = nFndPos; nFirst; )
1396 //            {
1397 //                pTxtNd = aUpd.GetList().GetObject( --nFirst );
1398 //                if( pTxtNd->IsRestart() )
1399 //                    break;
1400 //            }
1401 //            // dann neue Numerierung ueber diesen Bereich
1402 //            // definieren und den Start am Anfang/Ende zurueck setzen
1403 //            pTxtNd = aUpd.GetList().GetObject( nFirst );
1404 //            if( pTxtNd->IsRestart() )
1405 //            {
1406 //                pTxtNd->SetRestart(false);
1407 //                if( pUndo )
1408 //                    pUndo->SetSttNum( pTxtNd->GetIndex() );
1409 //            }
1410 
1411             SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 );
1412             sal_uInt16 nChgFmtLevel = 0;
1413             for( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
1414             {
1415                 const SwNumFmt& rOldFmt = pOldRule->Get( n ),
1416                     & rNewFmt = pNewRule->Get( n );
1417 
1418                 if( rOldFmt.GetAbsLSpace() != rNewFmt.GetAbsLSpace() ||
1419                     rOldFmt.GetFirstLineOffset() != rNewFmt.GetFirstLineOffset() )
1420                     nChgFmtLevel |= ( 1 << n );
1421             }
1422 
1423             const SwTxtNode* pGivenTxtNode = rPos.nNode.GetNode().GetTxtNode();
1424             SwNumRuleItem aRule( rNewRule );
1425 //            for( ; nFirst < nLast; ++nFirst )
1426 //            {
1427 //                pTxtNd = aUpd.GetList().GetObject( nFirst );
1428 
1429 //                aRegH.RegisterInModify( pTxtNd, *pTxtNd );
1430 
1431 //                pTxtNd->SwCntntNode::SetAttr( aRule );
1432 //                pTxtNd->NumRuleChgd();
1433 //            }
1434             for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
1435                   aIter != aTxtNodeList.end(); ++aIter )
1436             {
1437                 SwTxtNode* pTxtNd = *aIter;
1438 
1439                 if ( pGivenTxtNode &&
1440                      pGivenTxtNode->GetListId() == pTxtNd->GetListId() )
1441                 {
1442                     aRegH.RegisterInModify( pTxtNd, *pTxtNd );
1443 
1444                     pTxtNd->SetAttr( aRule );
1445                     pTxtNd->NumRuleChgd();
1446                 }
1447             }
1448             GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
1449             SetModified();
1450 
1451             bRet = sal_True;     // #106897#
1452         }
1453     }
1454 
1455 	return bRet;
1456 }
1457 
1458 // --> OD 2008-03-18 #refactorlists#
1459 namespace
1460 {
1461     struct ListStyleData
1462     {
1463         SwNumRule* pReplaceNumRule;
1464         bool bCreateNewList;
1465         String sListId;
1466 
ListStyleData__anon38c91a5c0111::ListStyleData1467         ListStyleData()
1468             : pReplaceNumRule( 0 ),
1469               bCreateNewList( false ),
1470               sListId()
1471         {}
1472     };
1473 }
1474 // <--
1475 
MakeUniqueNumRules(const SwPaM & rPaM)1476 void SwDoc::MakeUniqueNumRules(const SwPaM & rPaM)
1477 {
1478     ASSERT( rPaM.GetDoc() == this, "need same doc" );
1479 
1480     // --> OD 2008-03-18 #refactorlists#
1481 //    map<SwNumRule *, SwNumRule *> aMyNumRuleMap;
1482     ::std::map<SwNumRule *, ListStyleData> aMyNumRuleMap;
1483     // <--
1484 
1485  	sal_uLong nStt = rPaM.Start()->nNode.GetIndex();
1486 	sal_uLong nEnd = rPaM.End()->nNode.GetIndex();
1487 
1488     bool bFirst = true;
1489 
1490     for (sal_uLong n = nStt; n <= nEnd; n++)
1491     {
1492         SwTxtNode * pCNd = GetNodes()[n]->GetTxtNode();
1493 
1494         if (pCNd)
1495         {
1496             SwNumRule * pRule = pCNd->GetNumRule();
1497 
1498             if (pRule && pRule->IsAutoRule() && ! pRule->IsOutlineRule())
1499             {
1500                 // --> OD 2008-03-18 #refactorlists#
1501 //                SwNumRule * pReplaceNumRule = aMyNumRuleMap[pRule];
1502                 ListStyleData aListStyleData = aMyNumRuleMap[pRule];
1503 
1504 //                if (! pReplaceNumRule)
1505                 if ( aListStyleData.pReplaceNumRule == 0 )
1506                 {
1507                     if (bFirst)
1508                     {
1509                         SwPosition aPos(*pCNd);
1510                         aListStyleData.pReplaceNumRule =
1511                             const_cast<SwNumRule *>
1512                             (SearchNumRule( aPos, false, pCNd->HasNumber(),
1513                                             false, 0,
1514                                             aListStyleData.sListId, true ));
1515                     }
1516 
1517 //                    if (! pReplaceNumRule)
1518                     if ( aListStyleData.pReplaceNumRule == 0 )
1519                     {
1520 //                        pReplaceNumRule = new SwNumRule(*pRule);
1521 //                        pReplaceNumRule->SetName(GetUniqueNumRuleName());
1522                         aListStyleData.pReplaceNumRule = new SwNumRule(*pRule);
1523                         // --> OD 2008-07-08 #i91400#
1524                         aListStyleData.pReplaceNumRule->SetName(
1525                                                 GetUniqueNumRuleName(), *this );
1526                         // <--
1527                         aListStyleData.bCreateNewList = true;
1528                     }
1529 
1530 //                    aMyNumRuleMap[pRule] = pReplaceNumRule;
1531                     aMyNumRuleMap[pRule] = aListStyleData;
1532                 }
1533 
1534                 SwPaM aPam(*pCNd);
1535 
1536                 SetNumRule( aPam, *aListStyleData.pReplaceNumRule,
1537                             aListStyleData.bCreateNewList,
1538                             aListStyleData.sListId );
1539                 if ( aListStyleData.bCreateNewList )
1540                 {
1541                     aListStyleData.bCreateNewList = false;
1542                     aListStyleData.sListId = pCNd->GetListId();
1543                     aMyNumRuleMap[pRule] = aListStyleData;
1544                 }
1545                 // <--
1546 
1547                 bFirst = false;
1548             }
1549         }
1550     }
1551 }
1552 
NoNum(const SwPaM & rPam)1553 sal_Bool SwDoc::NoNum( const SwPaM& rPam )
1554 {
1555 
1556 	sal_Bool bRet = SplitNode( *rPam.GetPoint(), false );
1557 	// ist ueberhaupt Nummerierung im Spiel ?
1558 	if( bRet )
1559 	{
1560 		// NoNum setzen und Upaten
1561 		const SwNodeIndex& rIdx = rPam.GetPoint()->nNode;
1562 		SwTxtNode* pNd = rIdx.GetNode().GetTxtNode();
1563 		const SwNumRule* pRule = pNd->GetNumRule();
1564 		if( pRule )
1565 		{
1566             pNd->SetCountedInList(false);
1567 
1568 			SetModified();
1569 		}
1570 		else
1571 			bRet = sal_False;	// keine Nummerierung , ?? oder immer sal_True ??
1572 	}
1573 	return bRet;
1574 }
1575 
DelNumRules(const SwPaM & rPam)1576 void SwDoc::DelNumRules( const SwPaM& rPam )
1577 {
1578 	sal_uLong nStt = rPam.GetPoint()->nNode.GetIndex(),
1579 			nEnd = rPam.GetMark()->nNode.GetIndex();
1580 	if( nStt > nEnd )
1581 	{
1582 		sal_uLong nTmp = nStt; nStt = nEnd; nEnd = nTmp;
1583 	}
1584 
1585 	SwUndoDelNum* pUndo;
1586     if (GetIDocumentUndoRedo().DoesUndo())
1587     {
1588         pUndo = new SwUndoDelNum( rPam );
1589         GetIDocumentUndoRedo().AppendUndo(pUndo);
1590     }
1591     else
1592 		pUndo = 0;
1593 
1594     SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : 0 );
1595 
1596 	SwNumRuleItem aEmptyRule( aEmptyStr );
1597 	const SwNode* pOutlNd = 0;
1598 	for( ; nStt <= nEnd; ++nStt )
1599 	{
1600 		SwTxtNode* pTNd = GetNodes()[ nStt ]->GetTxtNode();
1601         // --> OD 2008-03-13 #refactorlists#
1602 //        if( pTNd && 0 != ( pItem = pTNd->GetNoCondAttr(
1603 //            RES_PARATR_NUMRULE, sal_True ) ) &&
1604 //            ( pName = &((SwNumRuleItem*)pItem)->GetValue())->Len() )
1605         SwNumRule* pNumRuleOfTxtNode = pTNd ? pTNd->GetNumRule() : 0;
1606         if ( pTNd && pNumRuleOfTxtNode )
1607         // <--
1608 		{
1609             // recognize changes of attribute for undo
1610 			aRegH.RegisterInModify( pTNd, *pTNd );
1611 
1612 			if( pUndo )
1613                 pUndo->AddNode( *pTNd, sal_False );
1614 
1615             // directly set list style attribute is reset, otherwise empty
1616             // list style is applied
1617             const SfxItemSet* pAttrSet = pTNd->GetpSwAttrSet();
1618             if ( pAttrSet &&
1619                  pAttrSet->GetItemState( RES_PARATR_NUMRULE, sal_False ) == SFX_ITEM_SET )
1620                 pTNd->ResetAttr( RES_PARATR_NUMRULE );
1621 			else
1622                 pTNd->SetAttr( aEmptyRule );
1623 
1624             // --> OD 2008-03-26 #refactorlists#
1625             pTNd->ResetAttr( RES_PARATR_LIST_ID );
1626             pTNd->ResetAttr( RES_PARATR_LIST_LEVEL );
1627             pTNd->ResetAttr( RES_PARATR_LIST_ISRESTART );
1628             pTNd->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
1629             pTNd->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
1630             // <--
1631 
1632 			if( RES_CONDTXTFMTCOLL == pTNd->GetFmtColl()->Which() )
1633 				pTNd->ChkCondColl();
1634 			//else if( !pOutlNd && NO_NUMBERING != //#outline level,zhaojianwei
1635 			//	((SwTxtFmtColl*)pTNd->GetFmtColl())->GetOutlineLevel() )
1636 			else if( !pOutlNd &&
1637 				((SwTxtFmtColl*)pTNd->GetFmtColl())->IsAssignedToListLevelOfOutlineStyle() )//<-end,zhaojianwei
1638 				pOutlNd = pTNd;
1639 		}
1640 	}
1641 
1642 	// dann noch alle Updaten
1643 	UpdateNumRule();
1644 
1645 	if( pOutlNd )
1646 		GetNodes().UpdtOutlineIdx( *pOutlNd );
1647 }
1648 
InvalidateNumRules()1649 void SwDoc::InvalidateNumRules()
1650 {
1651     for (sal_uInt16 n = 0; n < pNumRuleTbl->Count(); ++n)
1652         (*pNumRuleTbl)[n]->SetInvalidRule(sal_True);
1653 }
1654 
1655 	// zum naechsten/vorhergehenden Punkt auf gleicher Ebene
1656 
lcl_IsNumOk(sal_uInt8 nSrchNum,sal_uInt8 & rLower,sal_uInt8 & rUpper,sal_Bool bOverUpper,sal_uInt8 nNumber)1657 sal_Bool lcl_IsNumOk( sal_uInt8 nSrchNum, sal_uInt8& rLower, sal_uInt8& rUpper,
1658 					sal_Bool bOverUpper, sal_uInt8 nNumber )
1659 {
1660     // --> OD 2008-04-02 #refactorlists#
1661     ASSERT( nNumber < MAXLEVEL,
1662             "<lcl_IsNumOk(..)> - misusage of method" );
1663     // <--
1664 
1665     sal_Bool bRet = sal_False;
1666 	{
1667 		if( bOverUpper ? nSrchNum == nNumber : nSrchNum >= nNumber )
1668 			bRet = sal_True;
1669 		else if( nNumber > rLower )
1670 			rLower = nNumber;
1671 		else if( nNumber < rUpper )
1672 			rUpper = nNumber;
1673 	}
1674 	return bRet;
1675 }
1676 
lcl_IsValidPrevNextNumNode(const SwNodeIndex & rIdx)1677 sal_Bool lcl_IsValidPrevNextNumNode( const SwNodeIndex& rIdx )
1678 {
1679 	sal_Bool bRet = sal_False;
1680 	const SwNode& rNd = rIdx.GetNode();
1681 	switch( rNd.GetNodeType() )
1682 	{
1683 	case ND_ENDNODE:
1684         bRet = SwTableBoxStartNode == rNd.StartOfSectionNode()->GetStartNodeType() ||
1685                 rNd.StartOfSectionNode()->IsSectionNode();
1686 		break;
1687 
1688 	case ND_STARTNODE:
1689 		bRet = SwTableBoxStartNode == ((SwStartNode&)rNd).GetStartNodeType();
1690 		break;
1691 
1692 	case ND_SECTIONNODE:			// der ist erlaubt, also weiter
1693 		bRet = sal_True;
1694 		break;
1695 	}
1696 	return bRet;
1697 }
1698 
lcl_GotoNextPrevNum(SwPosition & rPos,sal_Bool bNext,sal_Bool bOverUpper,sal_uInt8 * pUpper,sal_uInt8 * pLower)1699 sal_Bool lcl_GotoNextPrevNum( SwPosition& rPos, sal_Bool bNext,
1700 							sal_Bool bOverUpper, sal_uInt8* pUpper, sal_uInt8* pLower )
1701 {
1702 	const SwTxtNode* pNd = rPos.nNode.GetNode().GetTxtNode();
1703 	const SwNumRule* pRule;
1704 	if( !pNd || 0 == ( pRule = pNd->GetNumRule()))
1705 		return sal_False;
1706 
1707     sal_uInt8 nSrchNum = static_cast<sal_uInt8>(pNd->GetActualListLevel());
1708 
1709 	SwNodeIndex aIdx( rPos.nNode );
1710     if( ! pNd->IsCountedInList() )
1711 	{
1712 		// falls gerade mal NO_NUMLEVEL an ist, so such den vorherigen Node
1713 		// mit Nummerierung
1714 		sal_Bool bError = sal_False;
1715 		do {
1716 			aIdx--;
1717 			if( aIdx.GetNode().IsTxtNode() )
1718 			{
1719 				pNd = aIdx.GetNode().GetTxtNode();
1720                 pRule = pNd->GetNumRule();
1721 
1722                 sal_uInt8 nTmpNum;
1723 
1724 				if( pRule  )
1725 				{
1726                     nTmpNum = static_cast<sal_uInt8>(pNd->GetActualListLevel());
1727                     if( !( ! pNd->IsCountedInList() &&
1728 						 (nTmpNum >= nSrchNum )) )
1729 						break;		// gefunden
1730 				}
1731 				else
1732 					bError = sal_True;
1733 			}
1734 			else
1735 				bError = !lcl_IsValidPrevNextNumNode( aIdx );
1736 
1737 		} while( !bError );
1738 		if( bError )
1739 			return sal_False;
1740 	}
1741 
1742 	sal_uInt8 nLower = nSrchNum, nUpper = nSrchNum;
1743 	sal_Bool bRet = sal_False;
1744 
1745 	const SwTxtNode* pLast;
1746 	if( bNext )
1747 		aIdx++, pLast = pNd;
1748 	else
1749 		aIdx--, pLast = 0;
1750 
1751 	while( bNext ? ( aIdx.GetIndex() < aIdx.GetNodes().Count() - 1 )
1752 				 : aIdx.GetIndex() )
1753 	{
1754 		if( aIdx.GetNode().IsTxtNode() )
1755 		{
1756 			pNd = aIdx.GetNode().GetTxtNode();
1757             pRule = pNd->GetNumRule();
1758 			if( pRule )
1759 			{
1760 				if( ::lcl_IsNumOk( nSrchNum, nLower, nUpper, bOverUpper,
1761                                     static_cast<sal_uInt8>(pNd->GetActualListLevel()) ))
1762 				{
1763 					rPos.nNode = aIdx;
1764 					rPos.nContent.Assign( (SwTxtNode*)pNd, 0 );
1765 					bRet = sal_True;
1766 					break;
1767 				}
1768 				else
1769 					pLast = pNd;
1770 			}
1771 			else
1772 				break;
1773 		}
1774 		else if( !lcl_IsValidPrevNextNumNode( aIdx ))
1775 			break;
1776 
1777 		if( bNext )
1778 			aIdx++;
1779 		else
1780 			aIdx--;
1781 	}
1782 
1783 	if( !bRet && !bOverUpper && pLast )		// nicht ueber hoehere Nummmern, aber bis Ende
1784 	{
1785 		if( bNext )
1786 		{
1787 			rPos.nNode = aIdx;
1788 			if( aIdx.GetNode().IsCntntNode() )
1789 				rPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), 0 );
1790 		}
1791 		else
1792 		{
1793 			rPos.nNode.Assign( *pLast );
1794 			rPos.nContent.Assign( (SwTxtNode*)pLast, 0 );
1795 		}
1796 		bRet = sal_True;
1797 	}
1798 
1799 	if( bRet )
1800 	{
1801 		if( pUpper )
1802 			*pUpper = nUpper;
1803 		if( pLower )
1804 			*pLower = nLower;
1805 	}
1806 	return bRet;
1807 }
1808 
GotoNextNum(SwPosition & rPos,sal_Bool bOverUpper,sal_uInt8 * pUpper,sal_uInt8 * pLower)1809 sal_Bool SwDoc::GotoNextNum( SwPosition& rPos, sal_Bool bOverUpper,
1810 							sal_uInt8* pUpper, sal_uInt8* pLower  )
1811 {
1812    return ::lcl_GotoNextPrevNum( rPos, sal_True, bOverUpper, pUpper, pLower );
1813 }
1814 
1815 // -> #i23731#
1816 // --> OD 2008-03-18 #refactorlists# - add output parameter <sListId>
SearchNumRule(const SwPosition & rPos,const bool bForward,const bool bNum,const bool bOutline,int nNonEmptyAllowed,String & sListId,const bool bInvestigateStartNode)1817 const SwNumRule *  SwDoc::SearchNumRule(const SwPosition & rPos,
1818                                         const bool bForward,
1819                                         const bool bNum,
1820                                         const bool bOutline,
1821                                         int nNonEmptyAllowed,
1822                                         String& sListId,
1823                                         const bool bInvestigateStartNode)
1824 {
1825     const SwNumRule * pResult = NULL;
1826     SwTxtNode * pTxtNd = rPos.nNode.GetNode().GetTxtNode();
1827     SwNode * pStartFromNode = pTxtNd;
1828 
1829     if (pTxtNd)
1830     {
1831         SwNodeIndex aIdx(rPos.nNode);
1832 
1833         // --> OD 2005-10-20 #i55391#
1834         // - the start node has also been investigated, if requested.
1835         const SwNode * pNode = NULL;
1836         do
1837         {
1838             // --> OD 2005-10-20 #i55391#
1839             if ( !bInvestigateStartNode )
1840             {
1841                 if (bForward)
1842                     aIdx++;
1843                 else
1844                     aIdx--;
1845             }
1846             // <--
1847             if (aIdx.GetNode().IsTxtNode())
1848             {
1849                 pTxtNd = aIdx.GetNode().GetTxtNode();
1850 
1851                 const SwNumRule * pNumRule = pTxtNd->GetNumRule();
1852                 if (pNumRule)
1853                 {
1854                     if ( ( pNumRule->IsOutlineRule() == ( bOutline ? sal_True : sal_False ) ) && // #115901#
1855                          ( ( bNum && pNumRule->Get(0).IsEnumeration()) ||
1856                            ( !bNum && pNumRule->Get(0).IsItemize() ) ) ) // #i22362#, #i29560#
1857                     {
1858                         pResult = pTxtNd->GetNumRule();
1859                         // --> OD 2008-03-18 #refactorlists#
1860                         // provide also the list id, to which the text node belongs.
1861                         sListId = pTxtNd->GetListId();
1862                     }
1863 
1864                     break;
1865                 }
1866                 else if (pTxtNd->Len() > 0 || NULL != pTxtNd->GetNumRule())
1867                 {
1868                     if (nNonEmptyAllowed == 0)
1869                         break;
1870 
1871                     nNonEmptyAllowed--;
1872 
1873                     if (nNonEmptyAllowed < 0)
1874                         nNonEmptyAllowed = -1;
1875                 }
1876             }
1877 
1878             // --> OD 2005-10-20 #i55391#
1879             if ( bInvestigateStartNode )
1880             {
1881                 if (bForward)
1882                     aIdx++;
1883                 else
1884                     aIdx--;
1885             }
1886             // <--
1887 
1888             pNode = &aIdx.GetNode();
1889         }
1890         while (!(pNode == GetNodes().DocumentSectionStartNode(pStartFromNode) ||
1891                  pNode == GetNodes().DocumentSectionEndNode(pStartFromNode)));
1892         // <--
1893     }
1894 
1895     return pResult;
1896 }
1897 // <- #i23731#
1898 
GotoPrevNum(SwPosition & rPos,sal_Bool bOverUpper,sal_uInt8 * pUpper,sal_uInt8 * pLower)1899 sal_Bool SwDoc::GotoPrevNum( SwPosition& rPos, sal_Bool bOverUpper,
1900 							sal_uInt8* pUpper, sal_uInt8* pLower  )
1901 {
1902    return ::lcl_GotoNextPrevNum( rPos, sal_False, bOverUpper, pUpper, pLower );
1903 }
1904 
NumUpDown(const SwPaM & rPam,sal_Bool bDown)1905 sal_Bool SwDoc::NumUpDown( const SwPaM& rPam, sal_Bool bDown )
1906 {
1907 	sal_uLong nStt = rPam.GetPoint()->nNode.GetIndex(),
1908 			nEnd = rPam.GetMark()->nNode.GetIndex();
1909 	if( nStt > nEnd )
1910 	{
1911 		sal_uLong nTmp = nStt; nStt = nEnd; nEnd = nTmp;
1912 	}
1913 
1914     // -> #115901# outline nodes are promoted or demoted differently
1915     bool bOnlyOutline = true;
1916     bool bOnlyNonOutline = true;
1917     for (sal_uLong n = nStt; n <= nEnd; n++)
1918     {
1919         SwTxtNode * pTxtNd = GetNodes()[n]->GetTxtNode();
1920 
1921         if (pTxtNd)
1922         {
1923             SwNumRule * pRule = pTxtNd->GetNumRule();
1924 
1925             if (pRule)
1926             {
1927                 if (pRule->IsOutlineRule())
1928                     bOnlyNonOutline = false;
1929                 else
1930                     bOnlyOutline = false;
1931             }
1932         }
1933     }
1934     // <- #115901#
1935 
1936     sal_Bool bRet = sal_True;
1937     char nDiff = bDown ? 1 : -1;
1938 
1939     // ->#115901#
1940     if (bOnlyOutline)
1941         bRet = OutlineUpDown(rPam, nDiff);
1942     else if (bOnlyNonOutline)
1943     {
1944         /* --> #i24560#
1945 
1946         Only promote or demote if all selected paragraphs are
1947         promotable resp. demotable.
1948 
1949         */
1950         for (sal_uLong nTmp = nStt; nTmp <= nEnd; ++nTmp)
1951         {
1952             SwTxtNode* pTNd = GetNodes()[ nTmp ]->GetTxtNode();
1953 
1954             // --> OD 2006-10-19 #134160# - make code robust:
1955             // consider case that the node doesn't denote a text node.
1956             if ( pTNd )
1957             {
1958                 SwNumRule * pRule = pTNd->GetNumRule();
1959 
1960                 if (pRule)
1961                 {
1962                     sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel());
1963                     if( (-1 == nDiff && 0 >= nLevel) ||
1964                         (1 == nDiff && MAXLEVEL - 1 <= nLevel))
1965                         bRet = sal_False;
1966                 }
1967             }
1968             // <--
1969         }
1970 
1971         if( bRet )
1972         {
1973             /* <-- #i24560# */
1974             if (GetIDocumentUndoRedo().DoesUndo())
1975             {
1976                 SwUndo *const pUndo( new SwUndoNumUpDown(rPam, nDiff) );
1977                 GetIDocumentUndoRedo().AppendUndo(pUndo);
1978             }
1979 
1980             String sNumRule;
1981 
1982             for(sal_uLong nTmp = nStt; nTmp <= nEnd; ++nTmp )
1983             {
1984                 SwTxtNode* pTNd = GetNodes()[ nTmp ]->GetTxtNode();
1985 
1986                 if( pTNd)
1987                 {
1988                     SwNumRule * pRule = pTNd->GetNumRule();
1989 
1990                     if (pRule)
1991                     {
1992                         sal_uInt8 nLevel = static_cast<sal_uInt8>(pTNd->GetActualListLevel());
1993                         nLevel = nLevel + nDiff;
1994 
1995                         pTNd->SetAttrListLevel(nLevel);
1996                     }
1997                 }
1998             }
1999 
2000             ChkCondColls();
2001             SetModified();
2002         }
2003     }
2004 
2005 	return bRet;
2006 }
2007 
MoveParagraph(const SwPaM & rPam,long nOffset,sal_Bool bIsOutlMv)2008 sal_Bool SwDoc::MoveParagraph( const SwPaM& rPam, long nOffset, sal_Bool bIsOutlMv )
2009 {
2010 	const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
2011 
2012 	sal_uLong nStIdx = pStt->nNode.GetIndex();
2013 	sal_uLong nEndIdx = pEnd->nNode.GetIndex();
2014 
2015     // Here are some sophisticated checks whether the wished PaM will be moved or not.
2016     // For moving outlines (bIsOutlMv) I've already done some checks, so here are two different
2017     // checks...
2018     SwNode *pTmp1;
2019     SwNode *pTmp2;
2020     if( bIsOutlMv )
2021     {
2022         // For moving chapters (outline) the following reason will deny the move:
2023         // if a start node is inside the moved area and its end node outside or vice versa.
2024         // If a start node is the first moved paragraph, its end node has to be within the moved
2025         // area, too (e.g. as last node).
2026         // If an end node is the last node of the moved area, its start node has to be a part of
2027         // the moved section, too.
2028         pTmp1 = GetNodes()[ nStIdx ];
2029         if( pTmp1->IsStartNode() )
2030         {   // First is a start node
2031             pTmp2 = pTmp1->EndOfSectionNode();
2032             if( pTmp2->GetIndex() > nEndIdx )
2033                 return sal_False; // Its end node is behind the moved range
2034         }
2035         pTmp1 = pTmp1->StartOfSectionNode()->EndOfSectionNode();
2036         if( pTmp1->GetIndex() <= nEndIdx )
2037             return sal_False; // End node inside but start node before moved range => no.
2038         pTmp1 = GetNodes()[ nEndIdx ];
2039         if( pTmp1->IsEndNode() )
2040         {   // The last one is an end node
2041             pTmp1 = pTmp1->StartOfSectionNode();
2042             if( pTmp1->GetIndex() < nStIdx )
2043                 return sal_False; // Its start node is before the moved range.
2044         }
2045         pTmp1 = pTmp1->StartOfSectionNode();
2046         if( pTmp1->GetIndex() >= nStIdx )
2047             return sal_False; // A start node which ends behind the moved area => no.
2048     }
2049 
2050 	sal_uLong nInStIdx, nInEndIdx;
2051 	long nOffs = nOffset;
2052 	if( nOffset > 0 )
2053 	{
2054 		nInEndIdx = nEndIdx;
2055 		nEndIdx += nOffset;
2056 		++nOffs;
2057 	}
2058 	else
2059 	{
2060         //Impossible to move to negative index
2061         if( sal_uLong(abs( nOffset )) > nStIdx)
2062             return sal_False;
2063 
2064 		nInEndIdx = nStIdx - 1;
2065 		nStIdx += nOffset;
2066 	}
2067 	nInStIdx = nInEndIdx + 1;
2068 	// Folgende Absatzbloecke sollen vertauscht werden:
2069 	// [ nStIdx, nInEndIdx ] mit [ nInStIdx, nEndIdx ]
2070 
2071     if( nEndIdx >= GetNodes().GetEndOfContent().GetIndex() )
2072         return sal_False;
2073 
2074     if( !bIsOutlMv )
2075     {   // And here the restrictions for moving paragraphs other than chapters (outlines)
2076         // The plan is to exchange [nStIdx,nInEndIdx] and [nStartIdx,nEndIdx]
2077         // It will checked if the both "start" nodes as well as the both "end" notes belongs to
2078         // the same start-end-section. This is more restrictive than the conditions checked above.
2079         // E.g. a paragraph will not escape from a section or be inserted to another section.
2080         pTmp1 = GetNodes()[ nStIdx ]->StartOfSectionNode();
2081         pTmp2 = GetNodes()[ nInStIdx ]->StartOfSectionNode();
2082         if( pTmp1 != pTmp2 )
2083             return sal_False; // "start" nodes in different sections
2084         pTmp1 = GetNodes()[ nEndIdx ];
2085         bool bIsEndNode = pTmp1->IsEndNode();
2086         if( !pTmp1->IsStartNode() )
2087         {
2088             pTmp1 = pTmp1->StartOfSectionNode();
2089             if( bIsEndNode ) // For end nodes the first start node is of course inside the range,
2090                 pTmp1 = pTmp1->StartOfSectionNode(); // I've to check the start node of the start node.
2091         }
2092         pTmp1 = pTmp1->EndOfSectionNode();
2093         pTmp2 = GetNodes()[ nInEndIdx ];
2094         if( !pTmp2->IsStartNode() )
2095         {
2096             bIsEndNode = pTmp2->IsEndNode();
2097             pTmp2 = pTmp2->StartOfSectionNode();
2098             if( bIsEndNode )
2099                 pTmp2 = pTmp2->StartOfSectionNode();
2100         }
2101         pTmp2 = pTmp2->EndOfSectionNode();
2102         if( pTmp1 != pTmp2 )
2103             return sal_False; // The "end" notes are in different sections
2104     }
2105 
2106     // auf Redlining testen - darf die Selektion ueberhaupt verschoben
2107     // werden?
2108 	if( !IsIgnoreRedline() )
2109 	{
2110 		sal_uInt16 nRedlPos = GetRedlinePos( pStt->nNode.GetNode(), nsRedlineType_t::REDLINE_DELETE );
2111 		if( USHRT_MAX != nRedlPos )
2112 		{
2113 			SwPosition aStPos( *pStt ), aEndPos( *pEnd );
2114 			aStPos.nContent = 0;
2115 			SwCntntNode* pCNd = pEnd->nNode.GetNode().GetCntntNode();
2116 			aEndPos.nContent = pCNd ? pCNd->Len() : 1;
2117 			sal_Bool bCheckDel = sal_True;
2118 
2119 			// es existiert fuer den Bereich irgendein Redline-Delete-Object
2120 			for( ; nRedlPos < GetRedlineTbl().Count(); ++nRedlPos )
2121 			{
2122 				const SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
2123 				if( !bCheckDel || nsRedlineType_t::REDLINE_DELETE == pTmp->GetType() )
2124 				{
2125 					const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
2126 					switch( ComparePosition( *pRStt, *pREnd, aStPos, aEndPos ))
2127 					{
2128 					case POS_COLLIDE_START:
2129 					case POS_BEHIND:			// Pos1 liegt hinter Pos2
2130 						nRedlPos = GetRedlineTbl().Count();
2131 						break;
2132 
2133 					case POS_COLLIDE_END:
2134 					case POS_BEFORE:			// Pos1 liegt vor Pos2
2135 						break;
2136 					case POS_INSIDE:			// Pos1 liegt vollstaendig in Pos2
2137 						// ist erlaubt, aber checke dann alle nachfolgenden
2138 						// auf Ueberlappungen
2139 						bCheckDel = sal_False;
2140 						break;
2141 
2142 					case POS_OUTSIDE:			// Pos2 liegt vollstaendig in Pos1
2143 					case POS_EQUAL:				// Pos1 ist genauso gross wie Pos2
2144 					case POS_OVERLAP_BEFORE:	// Pos1 ueberlappt Pos2 am Anfang
2145 					case POS_OVERLAP_BEHIND:	// Pos1 ueberlappt Pos2 am Ende
2146 						return sal_False;
2147 					}
2148 				}
2149 			}
2150 		}
2151 	}
2152 
2153 	{
2154 		// DataChanged vorm verschieben verschicken, dann bekommt
2155 		// man noch mit, welche Objecte sich im Bereich befinden.
2156 		// Danach koennen sie vor/hinter der Position befinden.
2157 		SwDataChanged aTmp( rPam, 0 );
2158 	}
2159 
2160 	SwNodeIndex aIdx( nOffset > 0 ? pEnd->nNode : pStt->nNode, nOffs );
2161 	SwNodeRange aMvRg( pStt->nNode, 0, pEnd->nNode, +1 );
2162 
2163 	SwRedline* pOwnRedl = 0;
2164 	if( IsRedlineOn() )
2165 	{
2166 		// wenn der Bereich komplett im eigenen Redline liegt, kann es
2167 		// verschoben werden!
2168 		sal_uInt16 nRedlPos = GetRedlinePos( pStt->nNode.GetNode(), nsRedlineType_t::REDLINE_INSERT );
2169 		if( USHRT_MAX != nRedlPos )
2170 		{
2171 			SwRedline* pTmp = GetRedlineTbl()[ nRedlPos ];
2172 			const SwPosition *pRStt = pTmp->Start(), *pREnd = pTmp->End();
2173 			SwRedline aTmpRedl( nsRedlineType_t::REDLINE_INSERT, rPam );
2174 			const SwCntntNode* pCEndNd = pEnd->nNode.GetNode().GetCntntNode();
2175 			// liegt komplett im Bereich, und ist auch der eigene Redline?
2176 			if( aTmpRedl.IsOwnRedline( *pTmp ) &&
2177 				(pRStt->nNode < pStt->nNode ||
2178 				(pRStt->nNode == pStt->nNode && !pRStt->nContent.GetIndex()) ) &&
2179 				(pEnd->nNode < pREnd->nNode ||
2180 				(pEnd->nNode == pREnd->nNode &&
2181 				 pCEndNd ? pREnd->nContent.GetIndex() == pCEndNd->Len()
2182 						 : !pREnd->nContent.GetIndex() )) )
2183 			{
2184 				pOwnRedl = pTmp;
2185 				if( nRedlPos + 1 < GetRedlineTbl().Count() )
2186 				{
2187 					pTmp = GetRedlineTbl()[ nRedlPos+1 ];
2188 					if( *pTmp->Start() == *pREnd )
2189 						// dann doch nicht!
2190 						pOwnRedl = 0;
2191 				}
2192 
2193 				if( pOwnRedl &&
2194 					!( pRStt->nNode <= aIdx && aIdx <= pREnd->nNode ))
2195 				{
2196 					// nicht in sich selbst, dann auch nicht moven
2197 					pOwnRedl = 0;
2198 				}
2199 			}
2200 		}
2201 
2202 		if( !pOwnRedl )
2203         {
2204             GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
2205 
2206 			// zuerst das Insert, dann das Loeschen
2207 			SwPosition aInsPos( aIdx );
2208 			aInsPos.nContent.Assign( aIdx.GetNode().GetCntntNode(), 0 );
2209 
2210 			SwPaM aPam( pStt->nNode, aMvRg.aEnd );
2211 
2212 			SwPaM& rOrigPam = (SwPaM&)rPam;
2213 			rOrigPam.DeleteMark();
2214 			rOrigPam.GetPoint()->nNode = aIdx.GetIndex() - 1;
2215 
2216 			sal_Bool bDelLastPara = !aInsPos.nNode.GetNode().IsCntntNode();
2217 
2218             /* #101076# When copying to a non-content node Copy will
2219                insert a paragraph before that node and insert before
2220                that inserted node. Copy creates an SwUndoInserts that
2221                does not cover the extra paragraph. Thus we insert the
2222                extra paragraph ourselves, _with_ correct undo
2223                information. */
2224             if (bDelLastPara)
2225             {
2226                 /* aInsPos points to the non-content node. Move it to
2227                    the previous content node. */
2228                 SwPaM aInsPam(aInsPos);
2229                 sal_Bool bMoved = aInsPam.Move(fnMoveBackward);
2230                 ASSERT(bMoved, "No content node found!");
2231 
2232                 if (bMoved)
2233                 {
2234                     /* Append the new node after the content node
2235                        found. The new position to insert the moved
2236                        paragraph at is before the inserted
2237                        paragraph. */
2238                     AppendTxtNode(*aInsPam.GetPoint());
2239                     aInsPos = *aInsPam.GetPoint();
2240                 }
2241             }
2242 
2243             CopyRange( aPam, aInsPos, false );
2244 			if( bDelLastPara )
2245 			{
2246 				// dann muss der letzte leere Node wieder entfernt werden
2247 				aIdx = aInsPos.nNode;
2248 				SwCntntNode* pCNd = GetNodes().GoPrevious( &aInsPos.nNode );
2249 				xub_StrLen nCLen = 0; if( pCNd ) nCLen = pCNd->Len();
2250 				aInsPos.nContent.Assign( pCNd, nCLen );
2251 
2252 				// alle die im zu loeschenden Node stehen, mussen auf den
2253 				// naechsten umgestezt werden
2254 				SwPosition* pPos;
2255 				for( sal_uInt16 n = 0; n < GetRedlineTbl().Count(); ++n )
2256 				{
2257 					SwRedline* pTmp = GetRedlineTbl()[ n ];
2258 					if( ( pPos = &pTmp->GetBound(sal_True))->nNode == aIdx )
2259 					{
2260 						pPos->nNode++;
2261 						pPos->nContent.Assign( pPos->nNode.GetNode().GetCntntNode(),0);
2262 					}
2263 					if( ( pPos = &pTmp->GetBound(sal_False))->nNode == aIdx )
2264 					{
2265 						pPos->nNode++;
2266 						pPos->nContent.Assign( pPos->nNode.GetNode().GetCntntNode(),0);
2267 					}
2268 				}
2269 				CorrRel( aIdx, aInsPos, 0, sal_False );
2270 
2271 				pCNd->JoinNext();
2272 			}
2273 
2274 			rOrigPam.GetPoint()->nNode++;
2275 			rOrigPam.GetPoint()->nContent.Assign( rOrigPam.GetCntntNode(), 0 );
2276 
2277 			RedlineMode_t eOld = GetRedlineMode();
2278 			checkRedlining(eOld);
2279             if (GetIDocumentUndoRedo().DoesUndo())
2280             {
2281                 //JP 06.01.98: MUSS noch optimiert werden!!!
2282                 SetRedlineMode(
2283 			       (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE));
2284                 SwUndo *const pUndo(new SwUndoRedlineDelete(aPam, UNDO_DELETE));
2285                 GetIDocumentUndoRedo().AppendUndo(pUndo);
2286             }
2287 
2288             SwRedline* pNewRedline = new SwRedline( nsRedlineType_t::REDLINE_DELETE, aPam );
2289 
2290             // #101654# prevent assertion from aPam's target being deleted
2291             // (Alternatively, one could just let aPam go out of scope, but
2292             //  that requires touching a lot of code.)
2293             aPam.GetBound(sal_True).nContent.Assign( NULL, 0 );
2294             aPam.GetBound(sal_False).nContent.Assign( NULL, 0 );
2295 
2296             AppendRedline( pNewRedline, true );
2297 
2298 //JP 06.01.98: MUSS noch optimiert werden!!!
2299 SetRedlineMode( eOld );
2300             GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
2301 			SetModified();
2302 
2303 			return sal_True;
2304 		}
2305 	}
2306 
2307 	if( !pOwnRedl && !IsIgnoreRedline() && GetRedlineTbl().Count() )
2308 	{
2309 		SwPaM aTemp(aIdx);
2310 		SplitRedline(aTemp);
2311 	}
2312 
2313 	sal_uLong nRedlSttNd(0), nRedlEndNd(0);
2314 	if( pOwnRedl )
2315 	{
2316 		const SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End();
2317 		nRedlSttNd = pRStt->nNode.GetIndex();
2318 		nRedlEndNd = pREnd->nNode.GetIndex();
2319 	}
2320 
2321 	SwUndoMoveNum* pUndo = 0;
2322     sal_uLong nMoved = 0;
2323     if (GetIDocumentUndoRedo().DoesUndo())
2324     {
2325 		pUndo = new SwUndoMoveNum( rPam, nOffset, bIsOutlMv );
2326         nMoved = rPam.End()->nNode.GetIndex() - rPam.Start()->nNode.GetIndex() + 1;
2327     }
2328 
2329 
2330     MoveNodeRange( aMvRg, aIdx, DOC_MOVEREDLINES );
2331 
2332 	if( pUndo )
2333 	{
2334         // i57907: Under circumstances (sections at the end of a chapter)
2335         // the rPam.Start() is not moved to the new position.
2336         // But aIdx should be at the new end position and as long as the number of moved paragraphs
2337         // is nMoved, I know, where the new position is.
2338 		pUndo->SetStartNode( aIdx.GetIndex() - nMoved );
2339         GetIDocumentUndoRedo().AppendUndo(pUndo);
2340     }
2341 
2342 	if( pOwnRedl )
2343 	{
2344 		SwPosition *pRStt = pOwnRedl->Start(), *pREnd = pOwnRedl->End();
2345 		if( pRStt->nNode.GetIndex() != nRedlSttNd )
2346 		{
2347 			pRStt->nNode = nRedlSttNd;
2348 			pRStt->nContent.Assign( pRStt->nNode.GetNode().GetCntntNode(),0);
2349 		}
2350 		if( pREnd->nNode.GetIndex() != nRedlEndNd )
2351 		{
2352 			pREnd->nNode = nRedlEndNd;
2353 			SwCntntNode* pCNd = pREnd->nNode.GetNode().GetCntntNode();
2354 			xub_StrLen nL = 0; if( pCNd ) nL = pCNd->Len();
2355 			pREnd->nContent.Assign( pCNd, nL );
2356 		}
2357 	}
2358 
2359 	SetModified();
2360 	return sal_True;
2361 }
2362 
NumOrNoNum(const SwNodeIndex & rIdx,sal_Bool bDel)2363 sal_Bool SwDoc::NumOrNoNum( const SwNodeIndex& rIdx, sal_Bool bDel )
2364 {
2365     sal_Bool bResult = sal_False;
2366     SwTxtNode * pTxtNd = rIdx.GetNode().GetTxtNode();
2367 
2368     if (pTxtNd && pTxtNd->GetNumRule() != NULL &&
2369         (pTxtNd->HasNumber() || pTxtNd->HasBullet()))
2370     {
2371         if ( !pTxtNd->IsCountedInList() == !bDel)
2372         {
2373             sal_Bool bOldNum = bDel; // == pTxtNd->IsCounted();
2374             sal_Bool bNewNum = bDel ? sal_False : sal_True;
2375             pTxtNd->SetCountedInList(bNewNum ? true : false);
2376 
2377             SetModified();
2378 
2379             bResult = sal_True;
2380 
2381             if (GetIDocumentUndoRedo().DoesUndo())
2382             {
2383                 SwUndoNumOrNoNum * pUndo =
2384                     new SwUndoNumOrNoNum(rIdx, bOldNum, bNewNum);
2385 
2386                 GetIDocumentUndoRedo().AppendUndo(pUndo);
2387             }
2388         }
2389         else if (bDel && pTxtNd->GetNumRule(sal_False) &&
2390                  pTxtNd->GetActualListLevel() >= 0 &&
2391                  pTxtNd->GetActualListLevel() < MAXLEVEL)
2392         {
2393             SwPaM aPam(*pTxtNd);
2394 
2395             DelNumRules(aPam);
2396 
2397             bResult = sal_True;
2398         }
2399     }
2400 
2401     return bResult;
2402 }
2403 
GetCurrNumRule(const SwPosition & rPos) const2404 SwNumRule* SwDoc::GetCurrNumRule( const SwPosition& rPos ) const
2405 {
2406 	SwNumRule* pRet = 0;
2407 	SwTxtNode* pTNd = rPos.nNode.GetNode().GetTxtNode();
2408 
2409 	if( pTNd )
2410     {
2411         // --> OD 2008-02-20 #refactorlists#
2412 //        pTNd->SyncNumberAndNumRule();
2413         // <--
2414 		pRet = pTNd->GetNumRule();
2415     }
2416 
2417 	return pRet;
2418 }
2419 
FindNumRule(const String & rName) const2420 sal_uInt16 SwDoc::FindNumRule( const String& rName ) const
2421 {
2422 	for( sal_uInt16 n = pNumRuleTbl->Count(); n; )
2423 		if( (*pNumRuleTbl)[ --n ]->GetName() == rName )
2424 			return n;
2425 
2426     return USHRT_MAX;
2427 }
2428 
FindNumRulePtr(const String & rName) const2429 SwNumRule* SwDoc::FindNumRulePtr( const String& rName ) const
2430 {
2431     SwNumRule * pResult = 0;
2432 
2433     pResult = maNumRuleMap[rName];
2434 
2435     if ( !pResult )
2436     {
2437         for (sal_uInt16 n = 0; n < pNumRuleTbl->Count(); ++n)
2438         {
2439             if ((*pNumRuleTbl)[n]->GetName() == rName)
2440             {
2441                 pResult = (*pNumRuleTbl)[n];
2442 
2443                 break;
2444             }
2445         }
2446     }
2447 
2448 	return pResult;
2449 }
2450 
2451 // #i36749#
AddNumRule(SwNumRule * pRule)2452 void SwDoc::AddNumRule(SwNumRule * pRule)
2453 {
2454     if ((SAL_MAX_UINT16 - 1) <= pNumRuleTbl->Count())
2455     {
2456         OSL_ENSURE(false, "SwDoc::AddNumRule: table full.");
2457         abort(); // this should never happen on real documents
2458     }
2459     pNumRuleTbl->Insert(pRule, pNumRuleTbl->Count());
2460     maNumRuleMap[pRule->GetName()] = pRule;
2461     pRule->SetNumRuleMap(&maNumRuleMap);
2462 
2463     // --> OD 2008-03-26 #refactorlists#
2464     createListForListStyle( pRule->GetName() );
2465     // <--
2466 }
2467 
2468 // --> OD 2008-02-11 #newlistlevelattrs#
MakeNumRule(const String & rName,const SwNumRule * pCpy,sal_Bool bBroadcast,const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode)2469 sal_uInt16 SwDoc::MakeNumRule( const String &rName,
2470             const SwNumRule* pCpy,
2471             sal_Bool bBroadcast,
2472             const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode )
2473 {
2474 	SwNumRule* pNew;
2475 	if( pCpy )
2476 	{
2477 		pNew = new SwNumRule( *pCpy );
2478 
2479         // --> OD 2008-07-08 #i91400#
2480         pNew->SetName( GetUniqueNumRuleName( &rName ), *this );
2481         // <--
2482 		if( pNew->GetName() != rName )
2483 		{
2484 			pNew->SetPoolFmtId( USHRT_MAX );
2485 			pNew->SetPoolHelpId( USHRT_MAX );
2486 			pNew->SetPoolHlpFileId( UCHAR_MAX );
2487             // --> OD 2008-04-03 #refactorlists#
2488             pNew->SetDefaultListId( String() );
2489             // <--
2490 		}
2491 		pNew->CheckCharFmts( this );
2492 	}
2493 	else
2494     {
2495         // --> OD 2008-02-11 #newlistlevelattrs#
2496         pNew = new SwNumRule( GetUniqueNumRuleName( &rName ),
2497                               eDefaultNumberFormatPositionAndSpaceMode );
2498         // <--
2499     }
2500 
2501 	sal_uInt16 nRet = pNumRuleTbl->Count();
2502 
2503     AddNumRule(pNew); // #i36749#
2504 
2505     if (GetIDocumentUndoRedo().DoesUndo())
2506     {
2507         SwUndo * pUndo = new SwUndoNumruleCreate(pNew, this);
2508         GetIDocumentUndoRedo().AppendUndo(pUndo);
2509     }
2510 
2511     if (bBroadcast)
2512         BroadcastStyleOperation(pNew->GetName(), SFX_STYLE_FAMILY_PSEUDO,
2513                                 SFX_STYLESHEET_CREATED);
2514 
2515 	return nRet;
2516 }
2517 
GetUniqueNumRuleName(const String * pChkStr,sal_Bool bAutoNum) const2518 String SwDoc::GetUniqueNumRuleName( const String* pChkStr, sal_Bool bAutoNum ) const
2519 {
2520 	String aName;
2521 	if( bAutoNum )
2522 	{
2523         // --> OD #o12311627#
2524         static rtlRandomPool s_RandomPool( rtl_random_createPool() );
2525         sal_Int64 n;
2526         rtl_random_getBytes( s_RandomPool, &n, sizeof(n) );
2527         aName = String::CreateFromInt64( (n < 0 ? -n : n) );
2528         // <--
2529 		if( pChkStr && !pChkStr->Len() )
2530 			pChkStr = 0;
2531 	}
2532 	else if( pChkStr && pChkStr->Len() )
2533 		aName = *pChkStr;
2534 	else
2535 	{
2536 		pChkStr = 0;
2537 		aName = SW_RESSTR( STR_NUMRULE_DEFNAME );
2538 	}
2539 
2540 	sal_uInt16 nNum(0), nTmp, nFlagSize = ( pNumRuleTbl->Count() / 8 ) +2;
2541 	sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
2542 	memset( pSetFlags, 0, nFlagSize );
2543 
2544 	xub_StrLen nNmLen = aName.Len();
2545 	if( !bAutoNum && pChkStr )
2546 	{
2547 		while( nNmLen-- && '0' <= aName.GetChar( nNmLen ) &&
2548 						   '9' >= aName.GetChar( nNmLen ) )
2549 			; //nop
2550 
2551 		if( ++nNmLen < aName.Len() )
2552 		{
2553 			aName.Erase( nNmLen );
2554 			pChkStr = 0;
2555 		}
2556 	}
2557 
2558 	const SwNumRule* pNumRule;
2559 	sal_uInt16 n;
2560 
2561 	for( n = 0; n < pNumRuleTbl->Count(); ++n )
2562 		if( 0 != ( pNumRule = (*pNumRuleTbl)[ n ] ) )
2563 		{
2564 			const String& rNm = pNumRule->GetName();
2565 			if( rNm.Match( aName ) == nNmLen )
2566 			{
2567 				// Nummer bestimmen und das Flag setzen
2568                 nNum = (sal_uInt16)rNm.Copy( nNmLen ).ToInt32();
2569 				if( nNum-- && nNum < pNumRuleTbl->Count() )
2570 					pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
2571 			}
2572 			if( pChkStr && pChkStr->Equals( rNm ) )
2573 				pChkStr = 0;
2574 		}
2575 
2576 	if( !pChkStr )
2577 	{
2578 		// alle Nummern entsprechend geflag, also bestimme die richtige Nummer
2579 		nNum = pNumRuleTbl->Count();
2580 		for( n = 0; n < nFlagSize; ++n )
2581 			if( 0xff != ( nTmp = pSetFlags[ n ] ))
2582 			{
2583 				// also die Nummer bestimmen
2584 				nNum = n * 8;
2585 				while( nTmp & 1 )
2586 					++nNum, nTmp >>= 1;
2587 				break;
2588 			}
2589 
2590 	}
2591 	delete [] pSetFlags;
2592 	if( pChkStr && pChkStr->Len() )
2593 		return *pChkStr;
2594 	return aName += String::CreateFromInt32( ++nNum );
2595 }
2596 
UpdateNumRule()2597 void SwDoc::UpdateNumRule()
2598 {
2599 	const SwNumRuleTbl& rNmTbl = GetNumRuleTbl();
2600 	for( sal_uInt16 n = 0; n < rNmTbl.Count(); ++n )
2601 		if( rNmTbl[ n ]->IsInvalidRule() )
2602 			rNmTbl[ n ]->Validate();
2603 }
2604 
2605 // --> OD 2008-04-02 #refactorlists#
MarkListLevel(const String & sListId,const int nListLevel,const sal_Bool bValue)2606 void SwDoc::MarkListLevel( const String& sListId,
2607                            const int nListLevel,
2608                            const sal_Bool bValue )
2609 {
2610     SwList* pList = getListByName( sListId );
2611 
2612     if ( pList )
2613     {
2614         MarkListLevel( *pList, nListLevel, bValue );
2615     }
2616 }
2617 
MarkListLevel(SwList & rList,const int nListLevel,const sal_Bool bValue)2618 void SwDoc::MarkListLevel( SwList& rList,
2619                            const int nListLevel,
2620                            const sal_Bool bValue )
2621 {
2622     // Set new marked list level and notify all affected nodes of the changed mark.
2623     rList.MarkListLevel( nListLevel, bValue );
2624 }
2625 // <- #i27615#
2626 // <--
2627 
2628 // #i23726#
IsFirstOfNumRule(SwPosition & rPos)2629 sal_Bool SwDoc::IsFirstOfNumRule(SwPosition & rPos)
2630 {
2631     sal_Bool bResult = sal_False;
2632     SwTxtNode * pTxtNode = rPos.nNode.GetNode().GetTxtNode();
2633 
2634     if (pTxtNode)
2635     {
2636         SwNumRule * pNumRule = pTxtNode->GetNumRule();
2637 
2638         if (pNumRule)
2639             bResult = pTxtNode->IsFirstOfNumRule();
2640     }
2641 
2642     return bResult;
2643 }
2644 
2645 // --> OD 2007-10-26 #i83479#
2646 // implementation for interface <IDocumentListItems>
operator ()(const SwNodeNum * pNodeNumOne,const SwNodeNum * pNodeNumTwo) const2647 bool SwDoc::lessThanNodeNum::operator()( const SwNodeNum* pNodeNumOne,
2648                                          const SwNodeNum* pNodeNumTwo ) const
2649 {
2650     return pNodeNumOne->LessThan( *pNodeNumTwo );
2651 }
2652 
addListItem(const SwNodeNum & rNodeNum)2653 void SwDoc::addListItem( const SwNodeNum& rNodeNum )
2654 {
2655     if ( mpListItemsList == 0 )
2656     {
2657         return;
2658     }
2659 
2660     const bool bAlreadyInserted(
2661             mpListItemsList->find( &rNodeNum ) != mpListItemsList->end() );
2662     ASSERT( !bAlreadyInserted,
2663             "<SwDoc::InsertListItem(..)> - <SwNodeNum> instance already registered as numbered item!" );
2664     if ( !bAlreadyInserted )
2665     {
2666         mpListItemsList->insert( &rNodeNum );
2667     }
2668 }
2669 
removeListItem(const SwNodeNum & rNodeNum)2670 void SwDoc::removeListItem( const SwNodeNum& rNodeNum )
2671 {
2672     if ( mpListItemsList == 0 )
2673     {
2674         return;
2675     }
2676 
2677     const tImplSortedNodeNumList::size_type nDeleted = mpListItemsList->erase( &rNodeNum );
2678     if ( nDeleted > 1 )
2679     {
2680         ASSERT( false,
2681                 "<SwDoc::RemoveListItem(..)> - <SwNodeNum> was registered more than once as numbered item!" );
2682     }
2683 }
2684 
getListItemText(const SwNodeNum & rNodeNum,const bool bWithNumber,const bool bWithSpacesForLevel) const2685 String SwDoc::getListItemText( const SwNodeNum& rNodeNum,
2686                                const bool bWithNumber,
2687                                const bool bWithSpacesForLevel ) const
2688 {
2689     return rNodeNum.GetTxtNode()
2690            ? rNodeNum.GetTxtNode()->GetExpandTxt( 0, STRING_LEN, bWithNumber,
2691                                                   bWithNumber, bWithSpacesForLevel )
2692            : String();
2693 }
2694 
getListItems(tSortedNodeNumList & orNodeNumList) const2695 void SwDoc::getListItems( tSortedNodeNumList& orNodeNumList ) const
2696 {
2697     orNodeNumList.clear();
2698     orNodeNumList.reserve( mpListItemsList->size() );
2699 
2700     tImplSortedNodeNumList::iterator aIter;
2701     tImplSortedNodeNumList::iterator aEndIter = mpListItemsList->end();
2702     for ( aIter = mpListItemsList->begin(); aIter != aEndIter; ++aIter )
2703     {
2704         orNodeNumList.push_back( (*aIter) );
2705     }
2706 }
2707 
getNumItems(tSortedNodeNumList & orNodeNumList) const2708 void SwDoc::getNumItems( tSortedNodeNumList& orNodeNumList ) const
2709 {
2710     orNodeNumList.clear();
2711     orNodeNumList.reserve( mpListItemsList->size() );
2712 
2713     tImplSortedNodeNumList::iterator aIter;
2714     tImplSortedNodeNumList::iterator aEndIter = mpListItemsList->end();
2715     for ( aIter = mpListItemsList->begin(); aIter != aEndIter; ++aIter )
2716     {
2717         const SwNodeNum* pNodeNum = (*aIter);
2718         if ( pNodeNum->IsCounted() &&
2719              pNodeNum->GetTxtNode() && pNodeNum->GetTxtNode()->HasNumber() )
2720         {
2721             orNodeNumList.push_back( pNodeNum );
2722         }
2723     }
2724 }
2725 // <--
2726 
2727 // --> OD 2007-11-15 #i83479#
2728 // implementation for interface <IDocumentOutlineNodes>
getOutlineNodesCount() const2729 sal_Int32 SwDoc::getOutlineNodesCount() const
2730 {
2731     return GetNodes().GetOutLineNds().Count();
2732 }
2733 
getOutlineLevel(const sal_Int32 nIdx) const2734 int SwDoc::getOutlineLevel( const sal_Int32 nIdx ) const
2735 {
2736     return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]->
2737                                            // GetTxtNode()->GetOutlineLevel();				//#outline level,zhaojianwei
2738 								GetTxtNode()->GetAttrOutlineLevel()-1;	//<-end,zhaojianwei
2739 }
2740 
getOutlineText(const sal_Int32 nIdx,const bool bWithNumber,const bool bWithSpacesForLevel) const2741 String SwDoc::getOutlineText( const sal_Int32 nIdx,
2742                               const bool bWithNumber,
2743                               const bool bWithSpacesForLevel ) const
2744 {
2745     return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]->
2746                 GetTxtNode()->GetExpandTxt( 0, STRING_LEN, bWithNumber,
2747                                             bWithNumber, bWithSpacesForLevel );
2748 }
2749 
getOutlineNode(const sal_Int32 nIdx) const2750 SwTxtNode* SwDoc::getOutlineNode( const sal_Int32 nIdx ) const
2751 {
2752     return GetNodes().GetOutLineNds()[ static_cast<sal_uInt16>(nIdx) ]->GetTxtNode();
2753 }
2754 
getOutlineNodes(IDocumentOutlineNodes::tSortedOutlineNodeList & orOutlineNodeList) const2755 void SwDoc::getOutlineNodes( IDocumentOutlineNodes::tSortedOutlineNodeList& orOutlineNodeList ) const
2756 {
2757     orOutlineNodeList.clear();
2758     orOutlineNodeList.reserve( getOutlineNodesCount() );
2759 
2760     const sal_uInt16 nOutlCount( static_cast<sal_uInt16>(getOutlineNodesCount()) );
2761     for ( sal_uInt16 i = 0; i < nOutlCount; ++i )
2762     {
2763         orOutlineNodeList.push_back(
2764             GetNodes().GetOutLineNds()[i]->GetTxtNode() );
2765     }
2766 }
2767 // <--
2768 
2769 // --> OD 2008-03-26 #refactorlists#
2770 // implementation of interface IDocumentListsAccess
createList(String sListId,const String sDefaultListStyleName)2771 SwList* SwDoc::createList( String sListId,
2772                            const String sDefaultListStyleName )
2773 {
2774     if ( sListId.Len() == 0 )
2775     {
2776         sListId = listfunc::CreateUniqueListId( *this );
2777     }
2778 
2779     if ( getListByName( sListId ) )
2780     {
2781         ASSERT( false,
2782                 "<SwDoc::createList(..)> - provided list id already used. Serious defect -> please inform OD." );
2783         return 0;
2784     }
2785 
2786     SwNumRule* pDefaultNumRuleForNewList = FindNumRulePtr( sDefaultListStyleName );
2787     if ( !pDefaultNumRuleForNewList )
2788     {
2789         ASSERT( false,
2790                 "<SwDoc::createList(..)> - for provided default list style name no list style is found. Serious defect -> please inform OD." );
2791         return 0;
2792     }
2793 
2794     SwList* pNewList = new SwList( sListId, *pDefaultNumRuleForNewList, GetNodes() );
2795     maLists[sListId] = pNewList;
2796 
2797     return pNewList;
2798 }
2799 
deleteList(const String sListId)2800 void SwDoc::deleteList( const String sListId )
2801 {
2802     SwList* pList = getListByName( sListId );
2803     if ( pList )
2804     {
2805         maLists.erase( sListId );
2806         delete pList;
2807     }
2808 }
2809 
getListByName(const String sListId) const2810 SwList* SwDoc::getListByName( const String sListId ) const
2811 {
2812     SwList* pList = 0;
2813 
2814     std::hash_map< String, SwList*, StringHash >::const_iterator
2815                                             aListIter = maLists.find( sListId );
2816     if ( aListIter != maLists.end() )
2817     {
2818         pList = (*aListIter).second;
2819     }
2820 
2821     return pList;
2822 }
2823 
createListForListStyle(const String sListStyleName)2824 SwList* SwDoc::createListForListStyle( const String sListStyleName )
2825 {
2826     if ( sListStyleName.Len() == 0 )
2827     {
2828         ASSERT( false,
2829                 "<SwDoc::createListForListStyle(..)> - no list style name provided. Serious defect -> please inform OD." );
2830         return 0;
2831     }
2832 
2833     if ( getListForListStyle( sListStyleName ) )
2834     {
2835         ASSERT( false,
2836                 "<SwDoc::createListForListStyle(..)> - a list for the provided list style name already exists. Serious defect -> please inform OD." );
2837         return 0;
2838     }
2839 
2840     SwNumRule* pNumRule = FindNumRulePtr( sListStyleName );
2841     if ( !pNumRule )
2842     {
2843         ASSERT( false,
2844                 "<SwDoc::createListForListStyle(..)> - for provided list style name no list style is found. Serious defect -> please inform OD." );
2845         return 0;
2846     }
2847 
2848     String sListId( pNumRule->GetDefaultListId() ); // can be empty String
2849     if ( getListByName( sListId ) )
2850     {
2851         sListId = String();
2852     }
2853     SwList* pNewList = createList( sListId, sListStyleName );
2854     maListStyleLists[sListStyleName] = pNewList;
2855     pNumRule->SetDefaultListId( pNewList->GetListId() );
2856 
2857     return pNewList;
2858 }
2859 
getListForListStyle(const String sListStyleName) const2860 SwList* SwDoc::getListForListStyle( const String sListStyleName ) const
2861 {
2862     SwList* pList = 0;
2863 
2864     std::hash_map< String, SwList*, StringHash >::const_iterator
2865                             aListIter = maListStyleLists.find( sListStyleName );
2866     if ( aListIter != maListStyleLists.end() )
2867     {
2868         pList = (*aListIter).second;
2869     }
2870 
2871     return pList;
2872 }
2873 
deleteListForListStyle(const String sListStyleName)2874 void SwDoc::deleteListForListStyle( const String sListStyleName )
2875 {
2876     String sListId;
2877     {
2878         SwList* pList = getListForListStyle( sListStyleName );
2879         ASSERT( pList,
2880                 "<SwDoc::deleteListForListStyle(..)> - misusage of method: no list found for given list style name" );
2881         if ( pList )
2882         {
2883             sListId = pList->GetListId();
2884         }
2885     }
2886     if ( sListId.Len() > 0 )
2887     {
2888         maListStyleLists.erase( sListStyleName );
2889         deleteList( sListId );
2890     }
2891 }
2892 // <--
2893 // --> OD 2008-07-08 #i91400#
trackChangeOfListStyleName(const String sListStyleName,const String sNewListStyleName)2894 void SwDoc::trackChangeOfListStyleName( const String sListStyleName,
2895                                         const String sNewListStyleName )
2896 {
2897     SwList* pList = getListForListStyle( sListStyleName );
2898     ASSERT( pList,
2899             "<SwDoc::changeOfListStyleName(..)> - misusage of method: no list found for given list style name" );
2900 
2901     if ( pList != 0 )
2902     {
2903         maListStyleLists.erase( sListStyleName );
2904         maListStyleLists[sNewListStyleName] = pList;
2905     }
2906 }
2907 // <--
2908 
2909 // --> OD 2008-03-13 #refactorlists#
2910 namespace listfunc
2911 {
MakeListIdUnique(const SwDoc & rDoc,const String aSuggestedUniqueListId)2912     const String MakeListIdUnique( const SwDoc& rDoc,
2913                                    const String aSuggestedUniqueListId )
2914     {
2915         long nHitCount = 0;
2916         String aTmpStr = aSuggestedUniqueListId;
2917         while ( rDoc.getListByName( aTmpStr ) )
2918         {
2919             ++nHitCount;
2920             aTmpStr = aSuggestedUniqueListId;
2921             aTmpStr += String::CreateFromInt32( nHitCount );
2922         }
2923 
2924         return aTmpStr;
2925     }
CreateUniqueListId(const SwDoc & rDoc)2926     const String CreateUniqueListId( const SwDoc& rDoc )
2927     {
2928         // --> OD 2008-08-06 #i92478#
2929         String aNewListId = String::CreateFromAscii( "list" );
2930         // <--
2931         // --> OD #o12311627#
2932         static rtlRandomPool s_RandomPool( rtl_random_createPool() );
2933         sal_Int64 n;
2934         rtl_random_getBytes( s_RandomPool, &n, sizeof(n) );
2935         aNewListId += String::CreateFromInt64( (n < 0 ? -n : n) );
2936         // <--
2937 
2938         return MakeListIdUnique( rDoc, aNewListId );
2939     }
2940 }
2941 // <--
2942