xref: /aoo42x/main/sw/source/core/doc/number.cxx (revision 41623124)
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 
28 #include <hintids.hxx>
29 
30 #include <string.h>
31 #include <vcl/font.hxx>
32 #include <editeng/brshitem.hxx>
33 #include <editeng/lrspitem.hxx>
34 #include <editeng/numitem.hxx>
35 #include <fmtornt.hxx>
36 #include <doc.hxx>
37 #include <pam.hxx>
38 #include <charfmt.hxx>
39 #include <paratr.hxx>
40 #include <frmfmt.hxx>
41 #include <ndtxt.hxx>
42 #include <docary.hxx>
43 #ifndef _DOCSH_HXX
44 #include <docsh.hxx>
45 #endif
46 #include <SwStyleNameMapper.hxx>
47 // --> OD 2006-06-28 #b6440955#
48 // Needed to load default bullet list configuration
49 #include <unotools/configitem.hxx>
50 // <--
51 #include <numrule.hxx>
52 #include <SwNodeNum.hxx>
53 
54 #include <hash_map>
55 // --> OD 2008-02-19 #refactorlists#
56 #include <list.hxx>
57 #include <algorithm>
58 // <--
59 // --> OD 2008-06-06 #i89178#
60 #include <unotools/saveopt.hxx>
61 // <--
62 // --> OD 2008-07-08 #i91400#
63 #include <IDocumentListsAccess.hxx>
64 // <--
65 
66 using namespace ::com::sun::star;
67 
68 
69 sal_uInt16 SwNumRule::nRefCount = 0;
70 SwNumFmt* SwNumRule::aBaseFmts[ RULE_END ][ MAXLEVEL ] = {
71     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
72 // --> OD 2008-02-11 #newlistlevelattrs#
73 SwNumFmt* SwNumRule::aLabelAlignmentBaseFmts[ RULE_END ][ MAXLEVEL ] = {
74     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
75 
76 char sOutline[] = "Outline";
77 char* SwNumRule::pDefOutlineName = sOutline;
78 
79 // #i30312#
80 sal_uInt16 SwNumRule::aDefNumIndents[ MAXLEVEL ] = {
81 //inch:   0,5  1,0  1,5  2,0   2,5   3,0   3,5   4,0   4,5   5,0
82 		1440/4, 1440/2, 1440*3/4, 1440, 1440*5/4, 1440*3/2, 1440*7/4, 1440*2,
83         1440*9/4, 1440*5/2
84 };
85 
Get(sal_uInt16 i) const86 const SwNumFmt& SwNumRule::Get( sal_uInt16 i ) const
87 {
88 	ASSERT_ID( i < MAXLEVEL && eRuleType < RULE_END, ERR_NUMLEVEL);
89     return aFmts[ i ]
90            ? *aFmts[ i ]
91            // --> OD 2008-02-11 #newlistlevelattrs#
92            : ( meDefaultNumberFormatPositionAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
93                ? *aBaseFmts[ eRuleType ][ i ]
94                : *aLabelAlignmentBaseFmts[ eRuleType ][ i ] );
95            // <--
96 }
97 
GetNumFmt(sal_uInt16 i) const98 const SwNumFmt* SwNumRule::GetNumFmt( sal_uInt16 i ) const
99 {
100     const SwNumFmt * pResult = NULL;
101 
102     ASSERT_ID( i < MAXLEVEL && eRuleType < RULE_END, ERR_NUMLEVEL);
103     if ( i < MAXLEVEL && eRuleType < RULE_END)
104     {
105         pResult = aFmts[ i ];
106     }
107 
108     return pResult;
109 }
110 
111 // --> OD 2008-07-08 #i91400#
SetName(const String & rName,IDocumentListsAccess & rDocListAccess)112 void SwNumRule::SetName( const String & rName,
113                          IDocumentListsAccess& rDocListAccess)
114 // <--
115 {
116     if ( sName != rName )
117     {
118         if (pNumRuleMap)
119         {
120             pNumRuleMap->erase(sName);
121             (*pNumRuleMap)[rName] = this;
122 
123             // --> OD 2008-07-08 #i91400#
124             if ( GetDefaultListId().Len() > 0 )
125             {
126                 rDocListAccess.trackChangeOfListStyleName( sName, rName );
127             }
128             // <--
129         }
130 
131         sName = rName;
132     }
133 }
134 
135 // --> OD 2008-02-19 #refactorlists#
GetTxtNodeList(SwNumRule::tTxtNodeList & rTxtNodeList) const136 void SwNumRule::GetTxtNodeList( SwNumRule::tTxtNodeList& rTxtNodeList ) const
137 {
138     rTxtNodeList = maTxtNodeList;
139 }
140 
GetTxtNodeListSize() const141 SwNumRule::tTxtNodeList::size_type SwNumRule::GetTxtNodeListSize() const
142 {
143     return maTxtNodeList.size();
144 }
145 
AddTxtNode(SwTxtNode & rTxtNode)146 void SwNumRule::AddTxtNode( SwTxtNode& rTxtNode )
147 {
148     tTxtNodeList::iterator aIter =
149         std::find( maTxtNodeList.begin(), maTxtNodeList.end(), &rTxtNode );
150 
151     if ( aIter == maTxtNodeList.end() )
152     {
153         maTxtNodeList.push_back( &rTxtNode );
154     }
155 }
156 
RemoveTxtNode(SwTxtNode & rTxtNode)157 void SwNumRule::RemoveTxtNode( SwTxtNode& rTxtNode )
158 {
159     tTxtNodeList::iterator aIter =
160         std::find( maTxtNodeList.begin(), maTxtNodeList.end(), &rTxtNode );
161 
162     if ( aIter != maTxtNodeList.end() )
163     {
164         maTxtNodeList.erase( aIter );
165     }
166 }
167 // <--
168 
SetNumRuleMap(std::hash_map<String,SwNumRule *,StringHash> * _pNumRuleMap)169 void SwNumRule::SetNumRuleMap(std::hash_map<String, SwNumRule *, StringHash> *
170                               _pNumRuleMap)
171 {
172     pNumRuleMap = _pNumRuleMap;
173 }
174 
GetNumIndent(sal_uInt8 nLvl)175 sal_uInt16 SwNumRule::GetNumIndent( sal_uInt8 nLvl )
176 {
177 	ASSERT( MAXLEVEL > nLvl, "NumLevel is out of range" );
178 	return aDefNumIndents[ nLvl ];
179 }
180 
GetBullIndent(sal_uInt8 nLvl)181 sal_uInt16 SwNumRule::GetBullIndent( sal_uInt8 nLvl )
182 {
183 	ASSERT( MAXLEVEL > nLvl, "NumLevel is out of range" );
184 	return aDefNumIndents[ nLvl ];
185 }
186 
187 
188 
lcl_SetRuleChgd(SwTxtNode & rNd,sal_uInt8 nLevel)189 static void lcl_SetRuleChgd( SwTxtNode& rNd, sal_uInt8 nLevel )
190 {
191     if( rNd.GetActualListLevel() == nLevel )
192 		rNd.NumRuleChgd();
193 }
194 /* -----------------------------22.02.01 13:41--------------------------------
195 
196  ---------------------------------------------------------------------------*/
SwNumFmt()197 SwNumFmt::SwNumFmt() :
198 	SvxNumberFormat(SVX_NUM_ARABIC),
199 	SwClient( 0 ),
200     pVertOrient(new SwFmtVertOrient( 0, text::VertOrientation::NONE))
201     ,cGrfBulletCP(USHRT_MAX)//For i120928,record the cp info of graphic within bullet
202 {
203 }
204 /* -----------------------------22.02.01 13:42--------------------------------
205 
206  ---------------------------------------------------------------------------*/
SwNumFmt(const SwNumFmt & rFmt)207 SwNumFmt::SwNumFmt( const SwNumFmt& rFmt) :
208 	SvxNumberFormat(rFmt),
209 	SwClient( rFmt.GetRegisteredInNonConst() ),
210     pVertOrient(new SwFmtVertOrient( 0, rFmt.GetVertOrient()))
211 	,cGrfBulletCP(rFmt.cGrfBulletCP)//For i120928,record the cp info of graphic within bullet
212 {
213     sal_Int16 eMyVertOrient = rFmt.GetVertOrient();
214 	SetGraphicBrush( rFmt.GetBrush(), &rFmt.GetGraphicSize(),
215 												&eMyVertOrient);
216 }
217 /* -----------------------------22.02.01 13:58--------------------------------
218 
219  ---------------------------------------------------------------------------*/
SwNumFmt(const SvxNumberFormat & rNumFmt,SwDoc * pDoc)220 SwNumFmt::SwNumFmt(const SvxNumberFormat& rNumFmt, SwDoc* pDoc) :
221 	SvxNumberFormat(rNumFmt),
222     pVertOrient(new SwFmtVertOrient( 0, rNumFmt.GetVertOrient()))
223 {
224     sal_Int16 eMyVertOrient = rNumFmt.GetVertOrient();
225     SetGraphicBrush( rNumFmt.GetBrush(), &rNumFmt.GetGraphicSize(),
226 												&eMyVertOrient);
227     const String& rCharStyleName = rNumFmt.SvxNumberFormat::GetCharFmtName();
228 	if( rCharStyleName.Len() )
229 	{
230 		SwCharFmt* pCFmt = pDoc->FindCharFmtByName( rCharStyleName );
231 		if( !pCFmt )
232 		{
233 			sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( rCharStyleName,
234 											nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
235 			pCFmt = nId != USHRT_MAX
236 						? pDoc->GetCharFmtFromPool( nId )
237 						: pDoc->MakeCharFmt( rCharStyleName, 0 );
238 		}
239 		pCFmt->Add( this );
240 	}
241 	else if( GetRegisteredIn() )
242 		GetRegisteredInNonConst()->Remove( this );
243 
244 }
245 /* -----------------------------22.02.01 13:42--------------------------------
246 
247  ---------------------------------------------------------------------------*/
~SwNumFmt()248 SwNumFmt::~SwNumFmt()
249 {
250 	delete pVertOrient;
251 }
252 /* -----------------------------02.07.01 15:37--------------------------------
253 
254  ---------------------------------------------------------------------------*/
NotifyGraphicArrived()255 void SwNumFmt::NotifyGraphicArrived()
256 {
257     if( GetCharFmt() )
258         UpdateNumNodes( (SwDoc*)GetCharFmt()->GetDoc() );
259 }
260 
261 // #i22362#
IsEnumeration() const262 sal_Bool SwNumFmt::IsEnumeration() const
263 {
264     // --> FME 2004-08-12 #i30655# native numbering did not work any longer
265     // using this code. Therefore HBRINKM and I agreed upon defining
266     // IsEnumeration() as !IsItemize()
267     return !IsItemize();
268     // <--
269 
270     /*
271     sal_Bool bResult;
272 
273     switch(GetNumberingType())
274     {
275     case SVX_NUM_CHARS_UPPER_LETTER:
276 	case SVX_NUM_CHARS_LOWER_LETTER:
277 	case SVX_NUM_ROMAN_UPPER:
278 	case SVX_NUM_ROMAN_LOWER:
279 	case SVX_NUM_ARABIC:
280 	case SVX_NUM_PAGEDESC:
281 	case SVX_NUM_CHARS_UPPER_LETTER_N:
282     case SVX_NUM_CHARS_LOWER_LETTER_N:
283         bResult = sal_True;
284 
285         break;
286 
287     default:
288         bResult = sal_False;
289     }
290 
291     return bResult;
292      */
293 }
294 
295 // #i29560#
IsItemize() const296 sal_Bool SwNumFmt::IsItemize() const
297 {
298     sal_Bool bResult;
299 
300     switch(GetNumberingType())
301     {
302 	case SVX_NUM_CHAR_SPECIAL:
303 	case SVX_NUM_BITMAP:
304         bResult = sal_True;
305 
306         break;
307 
308     default:
309         bResult = sal_False;
310     }
311 
312     return bResult;
313 
314 }
315 
316 
317 /* -----------------------------23.02.01 09:28--------------------------------
318 
319  ---------------------------------------------------------------------------*/
operator =(const SwNumFmt & rNumFmt)320 SwNumFmt& SwNumFmt::operator=( const SwNumFmt& rNumFmt)
321 {
322 	SvxNumberFormat::operator=(rNumFmt);
323 	if( rNumFmt.GetRegisteredIn() )
324 		rNumFmt.GetRegisteredInNonConst()->Add( this );
325 	else if( GetRegisteredIn() )
326 		GetRegisteredInNonConst()->Remove( this );
327 	//For i120928,record the cp info of graphic within bullet
328 	cGrfBulletCP = rNumFmt.cGrfBulletCP;
329 	return *this;
330 }
331 /* -----------------------------23.02.01 09:28--------------------------------
332 
333  ---------------------------------------------------------------------------*/
operator ==(const SwNumFmt & rNumFmt) const334 sal_Bool SwNumFmt::operator==( const SwNumFmt& rNumFmt) const
335 {
336 	sal_Bool bRet = SvxNumberFormat::operator==(rNumFmt) &&
337 		GetRegisteredIn() == rNumFmt.GetRegisteredIn();
338     return bRet;
339 }
340 
341 /* -----------------------------22.02.01 13:44--------------------------------
342 
343  ---------------------------------------------------------------------------*/
SetCharFmt(SwCharFmt * pChFmt)344 void SwNumFmt::SetCharFmt( SwCharFmt* pChFmt)
345 {
346 	if( pChFmt )
347 		pChFmt->Add( this );
348 	else if( GetRegisteredIn() )
349 		GetRegisteredInNonConst()->Remove( this );
350 }
351 /* -----------------------------22.02.01 13:45--------------------------------
352 
353  ---------------------------------------------------------------------------*/
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)354 void SwNumFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
355 {
356 	// dann suche mal in dem Doc nach dem NumRules-Object, in dem dieses
357 	// NumFormat gesetzt ist. Das Format muss es nicht geben!
358 	const SwCharFmt* pFmt = 0;
359     sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
360 	switch( nWhich )
361 	{
362 	case RES_ATTRSET_CHG:
363 	case RES_FMT_CHG:
364 		pFmt = GetCharFmt();
365 		break;
366 	}
367 
368 	if( pFmt && !pFmt->GetDoc()->IsInDtor() )
369 		UpdateNumNodes( (SwDoc*)pFmt->GetDoc() );
370 	else
371 		CheckRegistration( pOld, pNew );
372 }
373 /* -----------------------------23.02.01 11:08--------------------------------
374 
375  ---------------------------------------------------------------------------*/
SetCharFmtName(const String & rSet)376 void SwNumFmt::SetCharFmtName(const String& rSet)
377 {
378 	SvxNumberFormat::SetCharFmtName(rSet);
379 }
380 /* -----------------------------22.02.01 13:47--------------------------------
381 
382  ---------------------------------------------------------------------------*/
GetCharFmtName() const383 const String&	SwNumFmt::GetCharFmtName() const
384 {
385 	if((SwCharFmt*)GetRegisteredIn())
386 		return ((SwCharFmt*)GetRegisteredIn())->GetName();
387 	else
388 		return aEmptyStr;
389 }
390 
ForgetCharFmt()391 void SwNumFmt::ForgetCharFmt()
392 {
393     if ( GetRegisteredIn() )
394         GetRegisteredInNonConst()->Remove( this );
395 }
396 
397 /* -----------------------------22.02.01 16:05--------------------------------
398 
399  ---------------------------------------------------------------------------*/
SetGraphicBrush(const SvxBrushItem * pBrushItem,const Size * pSize,const sal_Int16 * pOrient)400 void	SwNumFmt::SetGraphicBrush( const SvxBrushItem* pBrushItem, const Size* pSize,
401     const sal_Int16* pOrient)
402 {
403     if(pOrient)
404         pVertOrient->SetVertOrient( *pOrient );
405 	SvxNumberFormat::SetGraphicBrush( pBrushItem, pSize, pOrient);
406 }
407 /* -----------------------------22.02.01 16:05--------------------------------
408 
409  ---------------------------------------------------------------------------*/
SetVertOrient(sal_Int16 eSet)410 void    SwNumFmt::SetVertOrient(sal_Int16 eSet)
411 {
412 	SvxNumberFormat::SetVertOrient(eSet);
413 }
414 /* -----------------------------22.02.01 16:05--------------------------------
415 
416  ---------------------------------------------------------------------------*/
GetVertOrient() const417 sal_Int16   SwNumFmt::GetVertOrient() const
418 {
419     return SvxNumberFormat::GetVertOrient();
420 }
421 /* -----------------------------22.02.01 13:54--------------------------------
422 
423  ---------------------------------------------------------------------------*/
UpdateNumNodes(SwDoc * pDoc)424 void SwNumFmt::UpdateNumNodes( SwDoc* pDoc )
425 {
426 	sal_Bool bDocIsModified = pDoc->IsModified();
427 	sal_Bool bFnd = sal_False;
428 	const SwNumRule* pRule;
429 	for( sal_uInt16 n = pDoc->GetNumRuleTbl().Count(); !bFnd && n; )
430 	{
431 		pRule = pDoc->GetNumRuleTbl()[ --n ];
432 		for( sal_uInt8 i = 0; i < MAXLEVEL; ++i )
433 			if( pRule->GetNumFmt( i ) == this )
434 			{
435                 // --> OD 2008-02-19 #refactorlists#
436 //                const String& rRuleNm = pRule->GetName();
437 
438 //                SwModify* pMod;
439 //                const SfxPoolItem* pItem;
440 //                sal_uInt16 k, nMaxItems = pDoc->GetAttrPool().GetItemCount(
441 //                                                    RES_PARATR_NUMRULE );
442 //                for( k = 0; k < nMaxItems; ++k )
443 //                    if( 0 != (pItem = pDoc->GetAttrPool().GetItem(
444 //                        RES_PARATR_NUMRULE, k ) ) &&
445 //                        0 != ( pMod = (SwModify*)((SwNumRuleItem*)pItem)->
446 //                                GetDefinedIn()) &&
447 //                        ((SwNumRuleItem*)pItem)->GetValue() == rRuleNm )
448 //                    {
449 //                        if( pMod->IsA( TYPE( SwFmt )) )
450 //                        {
451 //                            SwNumRuleInfo aInfo( rRuleNm );
452 //                            pMod->GetInfo( aInfo );
453 
454 //                            for( sal_uLong nFirst = 0, nLast = aInfo.GetList().Count();
455 //                                nFirst < nLast; ++nFirst )
456 //                                lcl_SetRuleChgd(
457 //                                    *aInfo.GetList().GetObject( nFirst ), i );
458 //                        }
459 //                        else if( ((SwTxtNode*)pMod)->GetNodes().IsDocNodes() )
460 //                            lcl_SetRuleChgd( *(SwTxtNode*)pMod, i );
461 //                    }
462                 SwNumRule::tTxtNodeList aTxtNodeList;
463                 pRule->GetTxtNodeList( aTxtNodeList );
464                 for ( SwNumRule::tTxtNodeList::iterator aIter = aTxtNodeList.begin();
465                       aIter != aTxtNodeList.end(); ++aIter )
466                 {
467                     lcl_SetRuleChgd( *(*aIter), i );
468                 }
469                 // <--
470 				bFnd = sal_True;
471 				break;
472 			}
473 	}
474 
475 	if( bFnd && !bDocIsModified )
476 		pDoc->ResetModified();
477 }
478 /* -----------------------------31.05.01 16:08--------------------------------
479 
480  ---------------------------------------------------------------------------*/
GetGraphicOrientation() const481 const SwFmtVertOrient*      SwNumFmt::GetGraphicOrientation() const
482 {
483     sal_Int16  eOrient = SvxNumberFormat::GetVertOrient();
484     if(text::VertOrientation::NONE == eOrient)
485         return 0;
486     else
487     {
488         pVertOrient->SetVertOrient(eOrient);
489         return pVertOrient;
490     }
491 }
492 
493 #ifdef DBG_UTIL
494 long int SwNumRule::nInstances = 0;
495 #endif
496 
497 // --> OD 2008-02-11 #newlistlevelattrs#
498 // handle new parameter <eDefaultNumberFormatPositionAndSpaceMode>
SwNumRule(const String & rNm,const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode,SwNumRuleType eType,sal_Bool bAutoFlg)499 SwNumRule::SwNumRule( const String& rNm,
500                       const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode,
501                       SwNumRuleType eType,
502                       sal_Bool bAutoFlg )
503     : maTxtNodeList(),
504       // --> OD 2008-03-03 #refactorlists#
505       maParagraphStyleList(),
506       // <--
507     pNumRuleMap(0),
508     sName( rNm ),
509     eRuleType( eType ),
510 	nPoolFmtId( USHRT_MAX ),
511 	nPoolHelpId( USHRT_MAX ),
512     nPoolHlpFileId( UCHAR_MAX ),
513 	bAutoRuleFlag( bAutoFlg ),
514 	bInvalidRuleFlag( sal_True ),
515 	bContinusNum( sal_False ),
516 	bAbsSpaces( sal_False ),
517     // --> OD 2005-10-21 - initialize member <mbCountPhantoms>
518     mbCountPhantoms( true ),
519     // <--
520     // --> OD 2008-02-11 #newlistlevelattrs#
521     meDefaultNumberFormatPositionAndSpaceMode( eDefaultNumberFormatPositionAndSpaceMode ),
522     // <--
523     // --> OD 2008-04-03 #refactorlists#
524     msDefaultListId()
525     // <--
526 {
527 #ifdef DBG_UTIL
528     nSerial = nInstances++;
529 #endif
530 
531 	if( !nRefCount++ )			// zum erstmal, also initialisiern
532 	{
533 		SwNumFmt* pFmt;
534 		sal_uInt8 n;
535 
536         // numbering:
537         // position-and-space mode LABEL_WIDTH_AND_POSITION:
538         for( n = 0; n < MAXLEVEL; ++n )
539         {
540             pFmt = new SwNumFmt;
541             pFmt->SetIncludeUpperLevels( 1 );
542             pFmt->SetStart( 1 );
543             pFmt->SetLSpace( lNumIndent );
544             pFmt->SetAbsLSpace( lNumIndent + SwNumRule::GetNumIndent( n ) );
545             pFmt->SetFirstLineOffset( lNumFirstLineOffset );
546             pFmt->SetSuffix( aDotStr );
547             // --> OD 2006-06-29 #b6440955#
548             pFmt->SetBulletChar( numfunc::GetBulletChar(n));
549             // <--
550             SwNumRule::aBaseFmts[ NUM_RULE ][ n ] = pFmt;
551         }
552         // --> OD 2008-02-11 #newlistlevelattrs#
553         // position-and-space mode LABEL_ALIGNMENT
554         // first line indent of general numbering in inch: -0,25 inch
555         const long cFirstLineIndent = -1440/4;
556         // indent values of general numbering in inch:
557         //  0,5         0,75        1,0         1,25        1,5
558         //  1,75        2,0         2,25        2,5         2,75
559         const long cIndentAt[ MAXLEVEL ] = {
560             1440/2,     1440*3/4,   1440,       1440*5/4,   1440*3/2,
561             1440*7/4,   1440*2,     1440*9/4,   1440*5/2,   1440*11/4 };
562 		for( n = 0; n < MAXLEVEL; ++n )
563 		{
564 			pFmt = new SwNumFmt;
565 			pFmt->SetIncludeUpperLevels( 1 );
566 			pFmt->SetStart( 1 );
567             // --> OD 2008-01-15 #newlistlevelattrs#
568             pFmt->SetPositionAndSpaceMode( SvxNumberFormat::LABEL_ALIGNMENT );
569             pFmt->SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
570             pFmt->SetListtabPos( cIndentAt[ n ] );
571             pFmt->SetFirstLineIndent( cFirstLineIndent );
572             pFmt->SetIndentAt( cIndentAt[ n ] );
573             // <--
574             pFmt->SetSuffix( aDotStr );
575             pFmt->SetBulletChar( numfunc::GetBulletChar(n));
576             SwNumRule::aLabelAlignmentBaseFmts[ NUM_RULE ][ n ] = pFmt;
577 		}
578         // <--
579 
580         // outline:
581         // position-and-space mode LABEL_WIDTH_AND_POSITION:
582         for( n = 0; n < MAXLEVEL; ++n )
583         {
584             pFmt = new SwNumFmt;
585             pFmt->SetNumberingType(SVX_NUM_NUMBER_NONE);
586             pFmt->SetIncludeUpperLevels( MAXLEVEL );
587             pFmt->SetStart( 1 );
588             pFmt->SetCharTextDistance( lOutlineMinTextDistance );
589             // --> OD 2006-06-29 #b6440955#
590             pFmt->SetBulletChar( numfunc::GetBulletChar(n));
591             // <--
592             SwNumRule::aBaseFmts[ OUTLINE_RULE ][ n ] = pFmt;
593         }
594         // --> OD 2008-02-11 #newlistlevelattrs#
595         // position-and-space mode LABEL_ALIGNMENT:
596         // indent values of default outline numbering in inch:
597         //  0,3         0,4         0,5         0,6         0,7
598         //  0,8         0,9         1,0         1,1         1,2
599         const long cOutlineIndentAt[ MAXLEVEL ] = {
600             1440*3/10,  1440*2/5,   1440/2,     1440*3/5,   1440*7/10,
601             1440*4/5,   1440*9/10,  1440,       1440*11/10, 1440*6/5 };
602 		for( n = 0; n < MAXLEVEL; ++n )
603 		{
604 			pFmt = new SwNumFmt;
605 			pFmt->SetNumberingType(SVX_NUM_NUMBER_NONE);
606 			pFmt->SetIncludeUpperLevels( MAXLEVEL );
607 			pFmt->SetStart( 1 );
608             pFmt->SetPositionAndSpaceMode( SvxNumberFormat::LABEL_ALIGNMENT );
609             pFmt->SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
610             pFmt->SetListtabPos( cOutlineIndentAt[ n ] );
611             pFmt->SetFirstLineIndent( -cOutlineIndentAt[ n ] );
612             pFmt->SetIndentAt( cOutlineIndentAt[ n ] );
613             pFmt->SetBulletChar( numfunc::GetBulletChar(n));
614             SwNumRule::aLabelAlignmentBaseFmts[ OUTLINE_RULE ][ n ] = pFmt;
615 		}
616         // <--
617 	}
618 	memset( aFmts, 0, sizeof( aFmts ));
619 	ASSERT( sName.Len(), "NumRule ohne Namen!" );
620 }
621 
SwNumRule(const SwNumRule & rNumRule)622 SwNumRule::SwNumRule( const SwNumRule& rNumRule )
623     : maTxtNodeList(),
624       // --> OD 2008-03-03 #refactorlists#
625       maParagraphStyleList(),
626       // <--
627       pNumRuleMap(0),
628       sName( rNumRule.sName ),
629       eRuleType( rNumRule.eRuleType ),
630       nPoolFmtId( rNumRule.GetPoolFmtId() ),
631       nPoolHelpId( rNumRule.GetPoolHelpId() ),
632       nPoolHlpFileId( rNumRule.GetPoolHlpFileId() ),
633       bAutoRuleFlag( rNumRule.bAutoRuleFlag ),
634       bInvalidRuleFlag( sal_True ),
635       bContinusNum( rNumRule.bContinusNum ),
636       bAbsSpaces( rNumRule.bAbsSpaces ),
637       // --> OD 2005-10-21 - initialize member <mbCountPhantoms>
638       mbCountPhantoms( true ),
639       // <--
640       // --> OD 2008-02-11 #newlistlevelattrs#
641       meDefaultNumberFormatPositionAndSpaceMode( rNumRule.meDefaultNumberFormatPositionAndSpaceMode ),
642       // <--
643       // --> OD 2008-04-03 #refactorlists#
644       msDefaultListId( rNumRule.msDefaultListId )
645       // <--
646 {
647 #ifdef DBG_UTIL
648     nSerial = nInstances++;
649 #endif
650 
651 	++nRefCount;
652 	memset( aFmts, 0, sizeof( aFmts ));
653 	for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
654 		if( rNumRule.aFmts[ n ] )
655 			Set( n, *rNumRule.aFmts[ n ] );
656 }
657 
~SwNumRule()658 SwNumRule::~SwNumRule()
659 {
660 	for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
661 		delete aFmts[ n ];
662 
663     if (pNumRuleMap)
664     {
665         pNumRuleMap->erase(GetName());
666     }
667 
668 	if( !--nRefCount )			// der letzte macht die Tuer zu
669 	{
670 			// Nummerierung:
671 			SwNumFmt** ppFmts = (SwNumFmt**)SwNumRule::aBaseFmts;
672 			int n;
673 
674 			for( n = 0; n < MAXLEVEL; ++n, ++ppFmts )
675 				delete *ppFmts, *ppFmts = 0;
676 
677 			// Gliederung:
678 			for( n = 0; n < MAXLEVEL; ++n, ++ppFmts )
679 				delete *ppFmts, *ppFmts = 0;
680 
681             // --> OD 2008-02-11 #newlistlevelattrs#
682             ppFmts = (SwNumFmt**)SwNumRule::aLabelAlignmentBaseFmts;
683             for( n = 0; n < MAXLEVEL; ++n, ++ppFmts )
684                 delete *ppFmts, *ppFmts = 0;
685             for( n = 0; n < MAXLEVEL; ++n, ++ppFmts )
686                 delete *ppFmts, *ppFmts = 0;
687             // <--
688     }
689 
690     // --> OD 2008-02-19 #refactorlists#
691     maTxtNodeList.clear();
692     maParagraphStyleList.clear();
693     // <--
694 }
695 
CheckCharFmts(SwDoc * pDoc)696 void SwNumRule::CheckCharFmts( SwDoc* pDoc )
697 {
698 	SwCharFmt* pFmt;
699 	for( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
700 		if( aFmts[ n ] && 0 != ( pFmt = aFmts[ n ]->GetCharFmt() ) &&
701 			pFmt->GetDoc() != pDoc )
702 		{
703 			// dann kopieren!
704 			SwNumFmt* pNew = new SwNumFmt( *aFmts[ n ] );
705 			pNew->SetCharFmt( pDoc->CopyCharFmt( *pFmt ) );
706 			delete aFmts[ n ];
707 			aFmts[ n ] = pNew;
708 		}
709 }
710 
operator =(const SwNumRule & rNumRule)711 SwNumRule& SwNumRule::operator=( const SwNumRule& rNumRule )
712 {
713 	if( this != &rNumRule )
714 	{
715 		for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
716 			Set( n, rNumRule.aFmts[ n ] );
717 
718 		eRuleType = rNumRule.eRuleType;
719 		sName = rNumRule.sName;
720 		bAutoRuleFlag = rNumRule.bAutoRuleFlag;
721 		bInvalidRuleFlag = sal_True;
722 		bContinusNum = rNumRule.bContinusNum;
723 		bAbsSpaces = rNumRule.bAbsSpaces;
724 		nPoolFmtId = rNumRule.GetPoolFmtId();
725 		nPoolHelpId = rNumRule.GetPoolHelpId();
726 		nPoolHlpFileId = rNumRule.GetPoolHlpFileId();
727 	}
728 	return *this;
729 }
730 
731 
operator ==(const SwNumRule & rRule) const732 sal_Bool SwNumRule::operator==( const SwNumRule& rRule ) const
733 {
734 	sal_Bool bRet = eRuleType == rRule.eRuleType &&
735 				sName == rRule.sName &&
736 				bAutoRuleFlag == rRule.bAutoRuleFlag &&
737 				bContinusNum == rRule.bContinusNum &&
738 				bAbsSpaces == rRule.bAbsSpaces &&
739 				nPoolFmtId == rRule.GetPoolFmtId() &&
740 				nPoolHelpId == rRule.GetPoolHelpId() &&
741 				nPoolHlpFileId == rRule.GetPoolHlpFileId();
742 	if( bRet )
743 	{
744 		for( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
745 			if( !( rRule.Get( n ) == Get( n ) ))
746 			{
747 				bRet = sal_False;
748 				break;
749 			}
750 	}
751 	return bRet;
752 }
753 
754 
Set(sal_uInt16 i,const SwNumFmt & rNumFmt)755 void SwNumRule::Set( sal_uInt16 i, const SwNumFmt& rNumFmt )
756 {
757     ASSERT( i < MAXLEVEL, "Serious defect, please inform OD" )
758     if( i < MAXLEVEL )
759     {
760         if( !aFmts[ i ] || !(rNumFmt == Get( i )) )
761         {
762             delete aFmts[ i ];
763             aFmts[ i ] = new SwNumFmt( rNumFmt );
764             bInvalidRuleFlag = sal_True;
765         }
766 	}
767 }
768 
Set(sal_uInt16 i,const SwNumFmt * pNumFmt)769 void SwNumRule::Set( sal_uInt16 i, const SwNumFmt* pNumFmt )
770 {
771     ASSERT( i < MAXLEVEL, "Serious defect, please inform OD" )
772     if( i >= MAXLEVEL )
773         return;
774 	SwNumFmt* pOld = aFmts[ i ];
775 	if( !pOld )
776 	{
777 		if( pNumFmt )
778 		{
779 			aFmts[ i ] = new SwNumFmt( *pNumFmt );
780 			bInvalidRuleFlag = sal_True;
781 		}
782 	}
783 	else if( !pNumFmt )
784 		delete pOld, aFmts[ i ] = 0, bInvalidRuleFlag = sal_True;
785 	else if( *pOld != *pNumFmt )
786 		*pOld = *pNumFmt, bInvalidRuleFlag = sal_True;
787 }
788 
789 
MakeNumString(const SwNodeNum & rNum,sal_Bool bInclStrings,sal_Bool bOnlyArabic) const790 String SwNumRule::MakeNumString( const SwNodeNum& rNum, sal_Bool bInclStrings,
791 								sal_Bool bOnlyArabic ) const
792 {
793     String aStr;
794 
795     if (rNum.IsCounted())
796         aStr = MakeNumString(rNum.GetNumberVector(),
797                              bInclStrings, bOnlyArabic, MAXLEVEL);
798 
799     return aStr;
800 }
801 
MakeNumString(const SwNumberTree::tNumberVector & rNumVector,const sal_Bool bInclStrings,const sal_Bool bOnlyArabic,const unsigned int _nRestrictToThisLevel) const802 String SwNumRule::MakeNumString( const SwNumberTree::tNumberVector & rNumVector,
803                                  const sal_Bool bInclStrings,
804                                  const sal_Bool bOnlyArabic,
805                                  const unsigned int _nRestrictToThisLevel ) const
806 {
807 	String aStr;
808 
809     unsigned int nLevel = rNumVector.size() - 1;
810     // --> OD 2005-10-17 #126238#
811     if ( nLevel > _nRestrictToThisLevel )
812     {
813         nLevel = _nRestrictToThisLevel;
814     }
815     // <--
816 
817     if (nLevel < MAXLEVEL)
818     {
819         const SwNumFmt& rMyNFmt = Get( static_cast<sal_uInt16>(nLevel) );
820         // --> OD 2006-06-02 #b6432095#
821         // - levels with numbering none has to provide prefix and suffix string
822 //        if( SVX_NUM_NUMBER_NONE != rMyNFmt.GetNumberingType() )
823         // <--
824         {
825             sal_uInt8 i = static_cast<sal_uInt8>(nLevel);
826 
827             if( !IsContinusNum() &&
828                 // --> OD 2006-09-19 #i69672#
829                 // - do not include upper levels, if level isn't numbered.
830                 rMyNFmt.GetNumberingType() != SVX_NUM_NUMBER_NONE &&
831                 // <--
832                 rMyNFmt.GetIncludeUpperLevels() )  // nur der eigene Level ?
833             {
834                 sal_uInt8 n = rMyNFmt.GetIncludeUpperLevels();
835                 if( 1 < n )
836                 {
837                     if( i+1 >= n )
838                         i -= n - 1;
839                     else
840                         i = 0;
841                 }
842             }
843 
844             for( ; i <= nLevel; ++i )
845             {
846                 const SwNumFmt& rNFmt = Get( i );
847                 if( SVX_NUM_NUMBER_NONE == rNFmt.GetNumberingType() )
848                 {
849                     // Soll aus 1.1.1 --> 2. NoNum --> 1..1 oder 1.1 ??
850                     //                 if( i != rNum.nMyLevel )
851                     //                    aStr += aDotStr;
852                     continue;
853                 }
854 
855                 if( rNumVector[ i ] )
856                 {
857                     if( bOnlyArabic )
858                         aStr += String::CreateFromInt32( rNumVector[ i ] );
859                     else
860                         aStr += rNFmt.GetNumStr( rNumVector[ i ] );
861                 }
862                 else
863                     aStr += '0';		// alle 0-Level sind eine 0
864                 if( i != nLevel && aStr.Len() )
865                     aStr += aDotStr;
866             }
867 
868             //JP 14.12.99: the type dont have any number, so dont append
869             //				the Post-/Prefix String
870             if( bInclStrings && !bOnlyArabic &&
871                 SVX_NUM_CHAR_SPECIAL != rMyNFmt.GetNumberingType() &&
872                 SVX_NUM_BITMAP != rMyNFmt.GetNumberingType() )
873             {
874                 aStr.Insert( rMyNFmt.GetPrefix(), 0 );
875                 aStr += rMyNFmt.GetSuffix();
876             }
877         }
878     }
879 
880 	return aStr;
881 }
882 
883 // --> OD 2007-09-07 #i81002#
MakeRefNumString(const SwNodeNum & rNodeNum,const bool bInclSuperiorNumLabels,const sal_uInt8 nRestrictInclToThisLevel) const884 String SwNumRule::MakeRefNumString( const SwNodeNum& rNodeNum,
885                                     const bool bInclSuperiorNumLabels,
886                                     const sal_uInt8 nRestrictInclToThisLevel ) const
887 {
888     String aRefNumStr;
889 
890     if ( rNodeNum.GetLevelInListTree() >= 0 )
891     {
892         const SwNodeNum* pWorkingNodeNum( &rNodeNum );
893         do
894         {
895             bool bMakeNumStringForPhantom( false );
896             if ( pWorkingNodeNum->IsPhantom() )
897             {
898                 SwNumFmt aFmt( Get( static_cast<sal_uInt16>(pWorkingNodeNum->GetLevelInListTree()) ) );
899                 bMakeNumStringForPhantom = aFmt.IsEnumeration() &&
900                                            SVX_NUM_NUMBER_NONE != aFmt.GetNumberingType();
901 
902             }
903             if ( bMakeNumStringForPhantom ||
904                  ( !pWorkingNodeNum->IsPhantom() &&
905                    pWorkingNodeNum->GetTxtNode() &&
906                    pWorkingNodeNum->GetTxtNode()->HasNumber() ) )
907             {
908                 aRefNumStr.Insert( MakeNumString( pWorkingNodeNum->GetNumberVector() ), 0 );
909             }
910             else if ( aRefNumStr.Len() > 0 )
911             {
912                 aRefNumStr.Insert( String::CreateFromAscii(" "), 0 );
913             }
914 
915             if ( bInclSuperiorNumLabels && pWorkingNodeNum->GetLevelInListTree() > 0 )
916             {
917                 sal_uInt8 n = Get( static_cast<sal_uInt16>(pWorkingNodeNum->GetLevelInListTree()) ).GetIncludeUpperLevels();
918                 pWorkingNodeNum = dynamic_cast<SwNodeNum*>(pWorkingNodeNum->GetParent());
919                 // skip parents, whose list label is already contained in the actual list label.
920                 while ( pWorkingNodeNum && n > 1 )
921                 {
922                     pWorkingNodeNum = dynamic_cast<SwNodeNum*>(pWorkingNodeNum->GetParent());
923                     --n;
924                 }
925             }
926             else
927             {
928                 break;
929             }
930         } while ( pWorkingNodeNum &&
931                   pWorkingNodeNum->GetLevelInListTree() >= 0 &&
932                   static_cast<sal_uInt8>(pWorkingNodeNum->GetLevelInListTree()) >= nRestrictInclToThisLevel );
933     }
934 
935     return aRefNumStr;
936 }
937 
938 //  ----- Copy-Methode vom SwNumRule ------
939 
940 	// eine Art Copy-Constructor, damit die Num-Formate auch an den
941 	// richtigen CharFormaten eines Dokumentes haengen !!
942 	// (Kopiert die NumFormate und returnt sich selbst)
943 
CopyNumRule(SwDoc * pDoc,const SwNumRule & rNumRule)944 SwNumRule& SwNumRule::CopyNumRule( SwDoc* pDoc, const SwNumRule& rNumRule )
945 {
946 	for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
947 	{
948 		Set( n, rNumRule.aFmts[ n ] );
949 		if( aFmts[ n ] && aFmts[ n ]->GetCharFmt() &&
950 			USHRT_MAX == pDoc->GetCharFmts()->GetPos( aFmts[n]->GetCharFmt() ))
951 			// ueber unterschiedliche Dokumente kopieren, dann
952 			// kopiere das entsprechende Char-Format ins neue
953 			// Dokument.
954 			aFmts[n]->SetCharFmt( pDoc->CopyCharFmt( *aFmts[n]->
955 										GetCharFmt() ) );
956 	}
957 	eRuleType = rNumRule.eRuleType;
958 	sName = rNumRule.sName;
959 	bAutoRuleFlag = rNumRule.bAutoRuleFlag;
960 	nPoolFmtId = rNumRule.GetPoolFmtId();
961 	nPoolHelpId = rNumRule.GetPoolHelpId();
962 	nPoolHlpFileId = rNumRule.GetPoolHlpFileId();
963 	bInvalidRuleFlag = sal_True;
964 	return *this;
965 }
966 /* -----------------30.10.98 08:33-------------------
967  *
968  * --------------------------------------------------*/
SetSvxRule(const SvxNumRule & rNumRule,SwDoc * pDoc)969 void SwNumRule::SetSvxRule(const SvxNumRule& rNumRule, SwDoc* pDoc)
970 {
971 	for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
972 	{
973 		const SvxNumberFormat* pSvxFmt = rNumRule.Get(n);
974 		delete aFmts[n];
975 		aFmts[n] = pSvxFmt ? new SwNumFmt(*pSvxFmt, pDoc) : 0;
976 	}
977 
978 	bInvalidRuleFlag = sal_True;
979 	bContinusNum = rNumRule.IsContinuousNumbering();
980 }
981 /* -----------------30.10.98 08:33-------------------
982  *
983  * --------------------------------------------------*/
MakeSvxNumRule() const984 SvxNumRule SwNumRule::MakeSvxNumRule() const
985 {
986 	SvxNumRule aRule(NUM_CONTINUOUS|NUM_CHAR_TEXT_DISTANCE|NUM_CHAR_STYLE|
987 						NUM_ENABLE_LINKED_BMP|NUM_ENABLE_EMBEDDED_BMP,
988 						MAXLEVEL, bContinusNum,
989 						eRuleType ==
990 							NUM_RULE ?
991 								SVX_RULETYPE_NUMBERING :
992 									SVX_RULETYPE_OUTLINE_NUMBERING );
993 	for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
994 	{
995         SwNumFmt aNumFmt = Get(n);
996         if(aNumFmt.GetCharFmt())
997             aNumFmt.SetCharFmtName(aNumFmt.GetCharFmt()->GetName());
998         aRule.SetLevel(n, aNumFmt, aFmts[n] != 0);
999 	}
1000 	return aRule;
1001 }
1002 
SetInvalidRule(sal_Bool bFlag)1003 void SwNumRule::SetInvalidRule(sal_Bool bFlag)
1004 {
1005     if (bFlag)
1006     {
1007         // --> OD 2008-03-13 #refactorlists#
1008 //        tPamAndNums::iterator aIt;
1009 //        for (aIt = aNumberRanges.begin(); aIt != aNumberRanges.end(); aIt++)
1010 //            (*aIt).second->InvalidateTree();
1011         std::set< SwList* > aLists;
1012         tTxtNodeList::iterator aIter;
1013         for ( aIter = maTxtNodeList.begin(); aIter != maTxtNodeList.end(); ++aIter )
1014         {
1015             const SwTxtNode* pTxtNode = *aIter;
1016             // --> OD 2010-06-04 #i111681# - applying patch from cmc
1017 //            aLists.insert( pTxtNode->GetDoc()->getListByName( pTxtNode->GetListId() ) );
1018             SwList* pList = pTxtNode->GetDoc()->getListByName( pTxtNode->GetListId() );
1019             ASSERT( pList, "<SwNumRule::SetInvalidRule(..)> - list at which the text node is registered at does not exist. This is a serious issue --> please inform OD.");
1020             if ( pList )
1021             {
1022                 aLists.insert( pList );
1023             }
1024             // <--
1025         }
1026         std::for_each( aLists.begin(), aLists.end(),
1027                        std::mem_fun( &SwList::InvalidateListTree ) );
1028         // <--
1029     }
1030 
1031     bInvalidRuleFlag = bFlag;
1032 }
1033 
1034 // --> OD 2008-06-16 #i90078#
1035 // #i23725#, #i23726#
1036 //void SwNumRule::Indent(short nAmount, int nLevel, int nReferenceLevel,
1037 //                       sal_Bool bRelative, sal_Bool bFirstLine, sal_Bool bCheckGtZero)
1038 //{
1039 //    int nStartLevel = 0;
1040 //    int nEndLevel = MAXLEVEL - 1;
1041 //    sal_Bool bGotInvalid = sal_False;
1042 
1043 //    if (nLevel >= 0)
1044 //        nStartLevel = nEndLevel = nLevel;
1045 
1046 //    int i;
1047 //    short nRealAmount =  nAmount;
1048 
1049 //    if (! bRelative)
1050 //    {
1051 //        if (bFirstLine)
1052 //        {
1053 //            if (nReferenceLevel >= 0)
1054 //                nAmount = nAmount - Get(static_cast<sal_uInt16>(nReferenceLevel)).GetFirstLineOffset();
1055 //            else
1056 //                nAmount = nAmount - Get(static_cast<sal_uInt16>(nStartLevel)).GetFirstLineOffset();
1057 //        }
1058 
1059 //        sal_Bool bFirst = sal_True;
1060 
1061 //        if (nReferenceLevel >= 0)
1062 //            nRealAmount = nAmount - Get(static_cast<sal_uInt16>(nReferenceLevel)).GetAbsLSpace();
1063 //        else
1064 //            for (i = nStartLevel; i < nEndLevel + 1; i++)
1065 //            {
1066 //                short nTmp = nAmount - Get(static_cast<sal_uInt16>(i)).GetAbsLSpace();
1067 
1068 //                if (bFirst || nTmp > nRealAmount)
1069 //                {
1070 //                    nRealAmount = nTmp;
1071 //                    bFirst = sal_False;
1072 //                }
1073 //            }
1074 //    }
1075 
1076 //    if (nRealAmount < 0)
1077 //        for (i = nStartLevel; i < nEndLevel + 1; i++)
1078 //            if (Get(static_cast<sal_uInt16>(i)).GetAbsLSpace() + nRealAmount < 0)
1079 //                nRealAmount = -Get(static_cast<sal_uInt16>(i)).GetAbsLSpace();
1080 
1081 //    for (i = nStartLevel; i < nEndLevel + 1; i++)
1082 //    {
1083 //        short nNew = Get(static_cast<sal_uInt16>(i)).GetAbsLSpace() + nRealAmount;
1084 
1085 //        if (bCheckGtZero && nNew < 0)
1086 //            nNew = 0;
1087 
1088 //        SwNumFmt aTmpNumFmt(Get(static_cast<sal_uInt16>(i)));
1089 //        aTmpNumFmt.SetAbsLSpace(nNew);
1090 
1091 //        Set(static_cast<sal_uInt16>(i), aTmpNumFmt);
1092 
1093 //        bGotInvalid = sal_True;
1094 //    }
1095 
1096 //    if (bGotInvalid)
1097 //        SetInvalidRule(bGotInvalid);
1098 //}
1099 
1100 // change indent of all list levels by given difference
ChangeIndent(const short nDiff)1101 void SwNumRule::ChangeIndent( const short nDiff )
1102 {
1103     for ( sal_uInt16 i = 0; i < MAXLEVEL; ++i )
1104     {
1105         SwNumFmt aTmpNumFmt( Get(i) );
1106 
1107         const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
1108                                         aTmpNumFmt.GetPositionAndSpaceMode() );
1109         if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
1110         {
1111             short nNewIndent = nDiff +
1112                                aTmpNumFmt.GetAbsLSpace();
1113             if ( nNewIndent < 0 )
1114             {
1115                 nNewIndent = 0;
1116             }
1117             aTmpNumFmt.SetAbsLSpace( nNewIndent );
1118         }
1119         else if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
1120         {
1121             // --> OD 2009-01-20 #i93399#
1122             // adjust also the list tab position, if a list tab stop is applied
1123             if ( aTmpNumFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB )
1124             {
1125                 const long nNewListTab = aTmpNumFmt.GetListtabPos() +  nDiff;
1126                 aTmpNumFmt.SetListtabPos( nNewListTab );
1127             }
1128             // <--
1129             const long nNewIndent = nDiff +
1130                               aTmpNumFmt.GetIndentAt();
1131             aTmpNumFmt.SetIndentAt( nNewIndent );
1132         }
1133 
1134         Set( i, aTmpNumFmt );
1135     }
1136 
1137     SetInvalidRule( sal_True );
1138 }
1139 
1140 // set indent of certain list level to given value
SetIndent(const short nNewIndent,const sal_uInt16 nListLevel)1141 void SwNumRule::SetIndent( const short nNewIndent,
1142                            const sal_uInt16 nListLevel )
1143 {
1144     SwNumFmt aTmpNumFmt( Get(nListLevel) );
1145 
1146     const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
1147                                         aTmpNumFmt.GetPositionAndSpaceMode() );
1148     if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
1149     {
1150         aTmpNumFmt.SetAbsLSpace( nNewIndent );
1151     }
1152     else if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
1153     {
1154         // --> OD 2009-01-20 #i93399#
1155         // adjust also the list tab position, if a list tab stop is applied
1156         if ( aTmpNumFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB )
1157         {
1158             const long nNewListTab = aTmpNumFmt.GetListtabPos() +
1159                                      ( nNewIndent - aTmpNumFmt.GetIndentAt() );
1160             aTmpNumFmt.SetListtabPos( nNewListTab );
1161         }
1162         // <--
1163         aTmpNumFmt.SetIndentAt( nNewIndent );
1164     }
1165 
1166     SetInvalidRule( sal_True );
1167 }
1168 
1169 // set indent of first list level to given value and change other list level's
1170 // indents accordingly
SetIndentOfFirstListLevelAndChangeOthers(const short nNewIndent)1171 void SwNumRule::SetIndentOfFirstListLevelAndChangeOthers( const short nNewIndent )
1172 {
1173     SwNumFmt aTmpNumFmt( Get(0) );
1174 
1175     short nDiff( 0 );
1176     const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
1177                                         aTmpNumFmt.GetPositionAndSpaceMode() );
1178     if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
1179     {
1180         nDiff = nNewIndent
1181                 - aTmpNumFmt.GetFirstLineOffset()
1182                 - aTmpNumFmt.GetAbsLSpace();
1183     }
1184     else if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
1185     {
1186         nDiff = static_cast<short>(nNewIndent
1187                                    - aTmpNumFmt.GetIndentAt());
1188     }
1189     if ( nDiff != 0  )
1190     {
1191         ChangeIndent( nDiff );
1192     }
1193 }
1194 // <--
1195 
Validate()1196 void SwNumRule::Validate()
1197 {
1198     // --> OD 2008-03-13 #refactorlists#
1199 //    tPamAndNums::iterator aIt;
1200 //    for (aIt = aNumberRanges.begin(); aIt != aNumberRanges.end(); aIt++)
1201 //        (*aIt).second->NotifyInvalidChildren();
1202     std::set< SwList* > aLists;
1203     tTxtNodeList::iterator aIter;
1204     for ( aIter = maTxtNodeList.begin(); aIter != maTxtNodeList.end(); ++aIter )
1205     {
1206         const SwTxtNode* pTxtNode = *aIter;
1207         aLists.insert( pTxtNode->GetDoc()->getListByName( pTxtNode->GetListId() ) );
1208     }
1209     std::for_each( aLists.begin(), aLists.end(),
1210                    std::mem_fun( &SwList::ValidateListTree ) );
1211     // <--
1212 
1213     SetInvalidRule(sal_False);
1214 }
1215 
IsCountPhantoms() const1216 bool SwNumRule::IsCountPhantoms() const
1217 {
1218     return mbCountPhantoms;
1219 }
1220 
SetCountPhantoms(bool bCountPhantoms)1221 void SwNumRule::SetCountPhantoms(bool bCountPhantoms)
1222 {
1223     mbCountPhantoms = bCountPhantoms;
1224 }
1225 
1226 // --> OD 2008-03-03 #refactorlists#
GetParagraphStyleListSize() const1227 SwNumRule::tParagraphStyleList::size_type SwNumRule::GetParagraphStyleListSize() const
1228 {
1229     return maParagraphStyleList.size();
1230 }
1231 
AddParagraphStyle(SwTxtFmtColl & rTxtFmtColl)1232 void SwNumRule::AddParagraphStyle( SwTxtFmtColl& rTxtFmtColl )
1233 {
1234     tParagraphStyleList::iterator aIter =
1235         std::find( maParagraphStyleList.begin(), maParagraphStyleList.end(), &rTxtFmtColl );
1236 
1237     if ( aIter == maParagraphStyleList.end() )
1238     {
1239         maParagraphStyleList.push_back( &rTxtFmtColl );
1240     }
1241 }
1242 
RemoveParagraphStyle(SwTxtFmtColl & rTxtFmtColl)1243 void SwNumRule::RemoveParagraphStyle( SwTxtFmtColl& rTxtFmtColl )
1244 {
1245     tParagraphStyleList::iterator aIter =
1246         std::find( maParagraphStyleList.begin(), maParagraphStyleList.end(), &rTxtFmtColl );
1247 
1248     if ( aIter != maParagraphStyleList.end() )
1249     {
1250         maParagraphStyleList.erase( aIter );
1251     }
1252 }
1253 // <--
1254 
1255 // --> OD 2006-06-27 #b6440955#
1256 namespace numfunc
1257 {
1258     /** class containing default bullet list configuration data
1259 
1260         @author OD
1261     */
1262     class SwDefBulletConfig : private utl::ConfigItem
1263     {
1264         public:
getInstance()1265             static SwDefBulletConfig* getInstance()
1266             {
1267                 if ( mpInstance == 0 )
1268                 {
1269                     mpInstance = new SwDefBulletConfig;
1270                 }
1271 
1272                 return mpInstance;
1273             }
1274 
GetFontname() const1275             inline const String& GetFontname() const
1276             {
1277                 return msFontname;
1278             }
1279             // --> OD 2008-06-02 #i63395#
IsFontnameUserDefined() const1280             inline bool IsFontnameUserDefined() const
1281             {
1282                 return mbUserDefinedFontname;
1283             }
1284             // <--
GetFont() const1285             inline const Font& GetFont() const
1286             {
1287                 return *mpFont;
1288             }
GetFontWeight() const1289             inline short GetFontWeight() const
1290             {
1291                 return static_cast<short>(meFontWeight);
1292             }
GetFontItalic() const1293             inline short GetFontItalic() const
1294             {
1295                 return static_cast<short>(meFontItalic);
1296             }
GetChar(sal_uInt8 p_nListLevel) const1297             inline sal_Unicode GetChar( sal_uInt8 p_nListLevel ) const
1298             {
1299                 if (p_nListLevel >= MAXLEVEL)
1300                 {
1301                     p_nListLevel = MAXLEVEL - 1;
1302                 }
1303 
1304                 return mnLevelChars[p_nListLevel];
1305             }
1306 
1307         private:
1308             SwDefBulletConfig();
1309 
1310             /** sets internal default bullet configuration data to default values
1311 
1312                 @author OD
1313             */
1314             void SetToDefault();
1315 
1316             /** returns sequence of default bullet configuration property names
1317 
1318                 @author OD
1319             */
1320             uno::Sequence<rtl::OUString> GetPropNames() const;
1321 
1322             /** loads default bullet configuration properties and applies
1323                 values to internal data
1324 
1325                 @author OD
1326             */
1327             void LoadConfig();
1328 
1329             /** initialize font instance for default bullet list
1330 
1331                 @author OD
1332             */
1333             void InitFont();
1334 
1335             /** catches notification about changed default bullet configuration data
1336 
1337                 @author OD
1338             */
1339             virtual void Notify( const uno::Sequence<rtl::OUString>& aPropertyNames );
1340 			virtual void Commit();
1341 
1342             static SwDefBulletConfig* mpInstance;
1343 
1344             // default bullet list configuration data
1345             String msFontname;
1346             // --> OD 2008-06-02 #i63395#
1347             bool mbUserDefinedFontname;
1348             // <--
1349             FontWeight meFontWeight;
1350             FontItalic meFontItalic;
1351             sal_Unicode mnLevelChars[MAXLEVEL];
1352 
1353             // default bullet list font instance
1354             Font* mpFont;
1355     };
1356 
1357     SwDefBulletConfig* SwDefBulletConfig::mpInstance = 0;
1358 
SwDefBulletConfig()1359     SwDefBulletConfig::SwDefBulletConfig()
1360         : ConfigItem( rtl::OUString::createFromAscii("Office.Writer/Numbering/DefaultBulletList") ),
1361           // --> OD 2008-06-02 #i63395#
1362           // default bullet font is now OpenSymbol
1363           msFontname( String::CreateFromAscii("OpenSymbol") ),
1364           mbUserDefinedFontname( false ),
1365           // <--
1366           meFontWeight( WEIGHT_DONTKNOW ),
1367           meFontItalic( ITALIC_NONE ),
1368           mpFont( 0 )
1369     {
1370         SetToDefault();
1371         LoadConfig();
1372         InitFont();
1373 
1374         // enable notification for changes on default bullet configuration change
1375         EnableNotification( GetPropNames() );
1376     }
1377 
SetToDefault()1378     void SwDefBulletConfig::SetToDefault()
1379     {
1380         // --> OD 2008-06-02 #i63395#
1381         // default bullet font name is now OpenSymbol
1382 //        msFontname = String::CreateFromAscii("StarSymbol");
1383         msFontname = String::CreateFromAscii("OpenSymbol");
1384         mbUserDefinedFontname = false;
1385         // <--
1386         meFontWeight = WEIGHT_DONTKNOW;
1387         meFontItalic = ITALIC_NONE;
1388 
1389         // --> OD 2008-06-03 #i63395#
1390         // new bullet characters
1391 //        mnLevelChars[0] = 0x25cf;
1392 //        mnLevelChars[1] = 0x25cb;
1393 //        mnLevelChars[2] = 0x25a0;
1394 //        mnLevelChars[3] = 0x25cf;
1395 //        mnLevelChars[4] = 0x25cb;
1396 //        mnLevelChars[5] = 0x25a0;
1397 //        mnLevelChars[6] = 0x25cf;
1398 //        mnLevelChars[7] = 0x25cb;
1399 //        mnLevelChars[8] = 0x25a0;
1400 //        mnLevelChars[9] = 0x25cf;
1401         mnLevelChars[0] = 0x2022;
1402         mnLevelChars[1] = 0x25e6;
1403         mnLevelChars[2] = 0x25aa;
1404         mnLevelChars[3] = 0x2022;
1405         mnLevelChars[4] = 0x25e6;
1406         mnLevelChars[5] = 0x25aa;
1407         mnLevelChars[6] = 0x2022;
1408         mnLevelChars[7] = 0x25e6;
1409         mnLevelChars[8] = 0x25aa;
1410         mnLevelChars[9] = 0x2022;
1411         // <--
1412     }
1413 
GetPropNames() const1414     uno::Sequence<rtl::OUString> SwDefBulletConfig::GetPropNames() const
1415     {
1416         uno::Sequence<rtl::OUString> aPropNames(13);
1417         rtl::OUString* pNames = aPropNames.getArray();
1418         pNames[0] = rtl::OUString::createFromAscii("BulletFont/FontFamilyname");
1419         pNames[1] = rtl::OUString::createFromAscii("BulletFont/FontWeight");
1420         pNames[2] = rtl::OUString::createFromAscii("BulletFont/FontItalic");
1421         pNames[3] = rtl::OUString::createFromAscii("BulletCharLvl1");
1422         pNames[4] = rtl::OUString::createFromAscii("BulletCharLvl2");
1423         pNames[5] = rtl::OUString::createFromAscii("BulletCharLvl3");
1424         pNames[6] = rtl::OUString::createFromAscii("BulletCharLvl4");
1425         pNames[7] = rtl::OUString::createFromAscii("BulletCharLvl5");
1426         pNames[8] = rtl::OUString::createFromAscii("BulletCharLvl6");
1427         pNames[9] = rtl::OUString::createFromAscii("BulletCharLvl7");
1428         pNames[10] = rtl::OUString::createFromAscii("BulletCharLvl8");
1429         pNames[11] = rtl::OUString::createFromAscii("BulletCharLvl9");
1430         pNames[12] = rtl::OUString::createFromAscii("BulletCharLvl10");
1431 
1432         return aPropNames;
1433     }
1434 
LoadConfig()1435     void SwDefBulletConfig::LoadConfig()
1436     {
1437         uno::Sequence<rtl::OUString> aPropNames = GetPropNames();
1438         uno::Sequence<uno::Any> aValues =
1439                                                     GetProperties( aPropNames );
1440         const uno::Any* pValues = aValues.getConstArray();
1441         ASSERT( aValues.getLength() == aPropNames.getLength(),
1442                 "<SwDefBulletConfig::SwDefBulletConfig()> - GetProperties failed")
1443         if ( aValues.getLength() == aPropNames.getLength() )
1444         {
1445             for ( int nProp = 0; nProp < aPropNames.getLength(); ++nProp )
1446             {
1447                 if ( pValues[nProp].hasValue() )
1448                 {
1449                     switch ( nProp )
1450                     {
1451                         case 0:
1452                         {
1453                             rtl::OUString aStr;
1454                             pValues[nProp] >>= aStr;
1455                             msFontname = aStr;
1456                             // --> OD 2008-06-02 #i63395#
1457                             mbUserDefinedFontname = true;
1458                             // <--
1459                         }
1460                         break;
1461                         case 1:
1462                         case 2:
1463                         {
1464                             sal_uInt8 nTmp = 0;
1465                             pValues[nProp] >>= nTmp;
1466                             if ( nProp == 1 )
1467                                 meFontWeight = static_cast<FontWeight>(nTmp);
1468                             else if ( nProp == 2 )
1469                                 meFontItalic = static_cast<FontItalic>(nTmp);
1470                         }
1471                         break;
1472                         case 3:
1473                         case 4:
1474                         case 5:
1475                         case 6:
1476                         case 7:
1477                         case 8:
1478                         case 9:
1479                         case 10:
1480                         case 11:
1481                         case 12:
1482                         {
1483                             sal_Unicode cChar = sal_Unicode();
1484                             pValues[nProp] >>= cChar;
1485                             mnLevelChars[nProp-3] = cChar;
1486                         }
1487                         break;
1488                     }
1489                 }
1490             }
1491         }
1492 
1493     }
1494 
InitFont()1495     void SwDefBulletConfig::InitFont()
1496     {
1497         delete mpFont;
1498 
1499         mpFont = new Font( msFontname, aEmptyStr, Size( 0, 14 ) );
1500         mpFont->SetWeight( meFontWeight );
1501         mpFont->SetItalic( meFontItalic );
1502     }
1503 
Notify(const uno::Sequence<rtl::OUString> &)1504     void SwDefBulletConfig::Notify( const uno::Sequence<rtl::OUString>& )
1505     {
1506         SetToDefault();
1507         LoadConfig();
1508         InitFont();
1509     }
1510 
Commit()1511 	void SwDefBulletConfig::Commit()
1512 	{
1513 	}
1514 
GetDefBulletFontname()1515     const String& GetDefBulletFontname()
1516     {
1517         return SwDefBulletConfig::getInstance()->GetFontname();
1518     }
1519 
1520     // --> OD 2008-06-02 #i63395#
IsDefBulletFontUserDefined()1521     bool IsDefBulletFontUserDefined()
1522     {
1523         return SwDefBulletConfig::getInstance()->IsFontnameUserDefined();
1524     }
1525     // <--
1526 
GetDefBulletFont()1527     const Font& GetDefBulletFont()
1528     {
1529         return SwDefBulletConfig::getInstance()->GetFont();
1530     }
1531 
GetBulletChar(sal_uInt8 nLevel)1532     sal_Unicode GetBulletChar( sal_uInt8 nLevel )
1533     {
1534         return SwDefBulletConfig::getInstance()->GetChar( nLevel );
1535     }
1536 
1537     /** class containing configuration data about user interface behavior
1538         regarding lists and list items.
1539 
1540         OD 2007-10-01 #b660435#
1541         configuration item about behavior of <TAB>/<SHIFT-TAB>-key at first
1542         position of first list item
1543 
1544         @author OD
1545     */
1546     class SwNumberingUIBehaviorConfig : private utl::ConfigItem
1547     {
1548         public:
getInstance()1549             static SwNumberingUIBehaviorConfig* getInstance()
1550             {
1551                 if ( mpInstance == 0 )
1552                 {
1553                     mpInstance = new SwNumberingUIBehaviorConfig();
1554                 }
1555 
1556                 return mpInstance;
1557             }
1558 
ChangeIndentOnTabAtFirstPosOfFirstListItem() const1559             inline sal_Bool ChangeIndentOnTabAtFirstPosOfFirstListItem() const
1560             {
1561                 return mbChangeIndentOnTabAtFirstPosOfFirstListItem;
1562             }
1563 
1564         private:
1565             SwNumberingUIBehaviorConfig();
1566 
1567             /** sets internal configuration data to default values
1568 
1569                 @author OD
1570             */
1571             void SetToDefault();
1572 
1573             /** returns sequence of configuration property names
1574 
1575                 @author OD
1576             */
1577             com::sun::star::uno::Sequence<rtl::OUString> GetPropNames() const;
1578 
1579             /** loads configuration properties and applies values to internal data
1580 
1581                 @author OD
1582             */
1583             void LoadConfig();
1584 
1585             /** catches notification about changed configuration data
1586 
1587                 @author OD
1588             */
1589             virtual void Notify( const com::sun::star::uno::Sequence<rtl::OUString>& aPropertyNames );
1590 			virtual void Commit();
1591 
1592             static SwNumberingUIBehaviorConfig* mpInstance;
1593 
1594             // configuration data
1595             sal_Bool mbChangeIndentOnTabAtFirstPosOfFirstListItem;
1596     };
1597 
1598     SwNumberingUIBehaviorConfig* SwNumberingUIBehaviorConfig::mpInstance = 0;
1599 
SwNumberingUIBehaviorConfig()1600     SwNumberingUIBehaviorConfig::SwNumberingUIBehaviorConfig()
1601         : ConfigItem( rtl::OUString::createFromAscii("Office.Writer/Numbering/UserInterfaceBehavior") ),
1602           mbChangeIndentOnTabAtFirstPosOfFirstListItem( sal_True )
1603     {
1604         SetToDefault();
1605         LoadConfig();
1606 
1607         // enable notification for changes on configuration change
1608         EnableNotification( GetPropNames() );
1609     }
1610 
SetToDefault()1611     void SwNumberingUIBehaviorConfig::SetToDefault()
1612     {
1613         mbChangeIndentOnTabAtFirstPosOfFirstListItem = sal_True;
1614     }
1615 
GetPropNames() const1616     com::sun::star::uno::Sequence<rtl::OUString> SwNumberingUIBehaviorConfig::GetPropNames() const
1617     {
1618         com::sun::star::uno::Sequence<rtl::OUString> aPropNames(1);
1619         rtl::OUString* pNames = aPropNames.getArray();
1620         pNames[0] = rtl::OUString::createFromAscii("ChangeIndentOnTabAtFirstPosOfFirstListItem");
1621 
1622         return aPropNames;
1623     }
1624 
Commit()1625 	void SwNumberingUIBehaviorConfig::Commit() {}
1626 
LoadConfig()1627     void SwNumberingUIBehaviorConfig::LoadConfig()
1628     {
1629         com::sun::star::uno::Sequence<rtl::OUString> aPropNames = GetPropNames();
1630         com::sun::star::uno::Sequence<com::sun::star::uno::Any> aValues =
1631                                                     GetProperties( aPropNames );
1632         const com::sun::star::uno::Any* pValues = aValues.getConstArray();
1633         ASSERT( aValues.getLength() == aPropNames.getLength(),
1634                 "<SwNumberingUIBehaviorConfig::LoadConfig()> - GetProperties failed")
1635         if ( aValues.getLength() == aPropNames.getLength() )
1636         {
1637             for ( int nProp = 0; nProp < aPropNames.getLength(); ++nProp )
1638             {
1639                 if ( pValues[nProp].hasValue() )
1640                 {
1641                     switch ( nProp )
1642                     {
1643                         case 0:
1644                         {
1645                             pValues[nProp] >>= mbChangeIndentOnTabAtFirstPosOfFirstListItem;
1646                         }
1647                         break;
1648                         default:
1649                         {
1650                             ASSERT( false,
1651                                     "<SwNumberingUIBehaviorConfig::LoadConfig()> - unknown configuration property")
1652                         }
1653                     }
1654                 }
1655             }
1656         }
1657     }
1658 
Notify(const com::sun::star::uno::Sequence<rtl::OUString> & aPropertyNames)1659     void SwNumberingUIBehaviorConfig::Notify( const com::sun::star::uno::Sequence<rtl::OUString>& aPropertyNames )
1660     {
1661         (void) aPropertyNames;
1662         SetToDefault();
1663         LoadConfig();
1664     }
1665 
ChangeIndentOnTabAtFirstPosOfFirstListItem()1666     sal_Bool ChangeIndentOnTabAtFirstPosOfFirstListItem()
1667     {
1668         return SwNumberingUIBehaviorConfig::getInstance()->ChangeIndentOnTabAtFirstPosOfFirstListItem();
1669     }
1670 
1671     // --> OD 2008-06-06 #i89178#
GetDefaultPositionAndSpaceMode()1672     SvxNumberFormat::SvxNumPositionAndSpaceMode GetDefaultPositionAndSpaceMode()
1673     {
1674         SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode;
1675         SvtSaveOptions aSaveOptions;
1676         switch ( aSaveOptions.GetODFDefaultVersion() )
1677         {
1678             case SvtSaveOptions::ODFVER_010:
1679             case SvtSaveOptions::ODFVER_011:
1680             {
1681                 ePosAndSpaceMode = SvxNumberFormat::LABEL_WIDTH_AND_POSITION;
1682             }
1683             break;
1684             default: // ODFVER_UNKNOWN or ODFVER_012
1685             {
1686                 ePosAndSpaceMode = SvxNumberFormat::LABEL_ALIGNMENT;
1687             }
1688         }
1689 
1690         return ePosAndSpaceMode;
1691     }
1692     // <--
1693 }
1694 // <--
1695