1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <hintids.hxx>
24 #include <vcl/font.hxx>
25 #include <editeng/brushitem.hxx>
26 #include <editeng/numitem.hxx>
27 #include <svl/grabbagitem.hxx>
28 #include <fmtornt.hxx>
30 #include <charfmt.hxx>
33 #include <SwStyleNameMapper.hxx>
35 // Needed to load default bullet list configuration
36 #include <unotools/configmgr.hxx>
37 #include <unotools/configitem.hxx>
39 #include <numrule.hxx>
40 #include <SwNodeNum.hxx>
45 #include <unordered_map>
46 #include <libxml/xmlwriter.h>
48 #include <rtl/ustrbuf.hxx>
49 #include <i18nlangtag/languagetag.hxx>
50 #include <unotools/saveopt.hxx>
51 #include <osl/diagnose.h>
53 #include <IDocumentListsAccess.hxx>
54 #include <IDocumentStylePoolAccess.hxx>
55 #include <IDocumentState.hxx>
57 #include <com/sun/star/beans/PropertyValue.hpp>
60 using namespace ::com::sun::star
;
62 sal_uInt16
SwNumRule::snRefCount
= 0;
63 SwNumFormat
* SwNumRule::saBaseFormats
[ RULE_END
][ MAXLEVEL
] = {
64 {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr } };
66 SwNumFormat
* SwNumRule::saLabelAlignmentBaseFormats
[ RULE_END
][ MAXLEVEL
] = {
67 {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr } };
69 const sal_uInt16
SwNumRule::saDefNumIndents
[ MAXLEVEL
] = {
70 o3tl::toTwips(25, o3tl::Length::in100
),
71 o3tl::toTwips(50, o3tl::Length::in100
),
72 o3tl::toTwips(75, o3tl::Length::in100
),
73 o3tl::toTwips(100, o3tl::Length::in100
),
74 o3tl::toTwips(125, o3tl::Length::in100
),
75 o3tl::toTwips(150, o3tl::Length::in100
),
76 o3tl::toTwips(175, o3tl::Length::in100
),
77 o3tl::toTwips(200, o3tl::Length::in100
),
78 o3tl::toTwips(225, o3tl::Length::in100
),
79 o3tl::toTwips(250, o3tl::Length::in100
),
82 OUString
SwNumRule::GetOutlineRuleName()
87 const SwNumFormat
& SwNumRule::Get( sal_uInt16 i
) const
89 assert( i
< MAXLEVEL
&& meRuleType
< RULE_END
);
92 : ( meDefaultNumberFormatPositionAndSpaceMode
== SvxNumberFormat::LABEL_WIDTH_AND_POSITION
93 ? *saBaseFormats
[ meRuleType
][ i
]
94 : *saLabelAlignmentBaseFormats
[ meRuleType
][ i
] );
97 const SwNumFormat
* SwNumRule::GetNumFormat( sal_uInt16 i
) const
99 const SwNumFormat
* pResult
= nullptr;
101 assert( i
< MAXLEVEL
&& meRuleType
< RULE_END
);
102 if ( i
< MAXLEVEL
&& meRuleType
< RULE_END
)
104 pResult
= maFormats
[ i
].get();
111 void SwNumRule::SetName( const OUString
& rName
,
112 IDocumentListsAccess
& rDocListAccess
)
114 if ( msName
== rName
)
119 mpNumRuleMap
->erase(msName
);
120 (*mpNumRuleMap
)[rName
] = this;
122 if ( !GetDefaultListId().isEmpty() )
124 rDocListAccess
.trackChangeOfListStyleName( msName
, rName
);
131 void SwNumRule::GetTextNodeList( SwNumRule::tTextNodeList
& rTextNodeList
) const
133 rTextNodeList
= maTextNodeList
;
136 SwNumRule::tTextNodeList::size_type
SwNumRule::GetTextNodeListSize() const
138 return maTextNodeList
.size();
141 void SwNumRule::AddTextNode( SwTextNode
& rTextNode
)
143 tTextNodeList::iterator aIter
=
144 std::find( maTextNodeList
.begin(), maTextNodeList
.end(), &rTextNode
);
146 if ( aIter
== maTextNodeList
.end() )
148 maTextNodeList
.push_back( &rTextNode
);
152 void SwNumRule::RemoveTextNode( SwTextNode
& rTextNode
)
154 tTextNodeList::iterator aIter
=
155 std::find( maTextNodeList
.begin(), maTextNodeList
.end(), &rTextNode
);
157 if ( aIter
!= maTextNodeList
.end() )
159 maTextNodeList
.erase( aIter
);
163 void SwNumRule::SetNumRuleMap(std::unordered_map
<OUString
, SwNumRule
*> *
166 mpNumRuleMap
= pNumRuleMap
;
169 sal_uInt16
SwNumRule::GetNumIndent( sal_uInt8 nLvl
)
171 OSL_ENSURE( MAXLEVEL
> nLvl
, "NumLevel is out of range" );
172 return saDefNumIndents
[ nLvl
];
175 sal_uInt16
SwNumRule::GetBullIndent( sal_uInt8 nLvl
)
177 OSL_ENSURE( MAXLEVEL
> nLvl
, "NumLevel is out of range" );
178 return saDefNumIndents
[ nLvl
];
181 static void lcl_SetRuleChgd( SwTextNode
& rNd
, sal_uInt8 nLevel
)
183 if( rNd
.GetActualListLevel() == nLevel
)
187 SwNumFormat::SwNumFormat() :
188 SvxNumberFormat(SVX_NUM_ARABIC
),
190 m_aVertOrient( 0, text::VertOrientation::NONE
)
191 ,m_cGrfBulletCP(USHRT_MAX
)//For i120928,record the cp info of graphic within bullet
195 SwNumFormat::SwNumFormat( const SwNumFormat
& rFormat
) :
196 SvxNumberFormat(rFormat
),
197 SwClient( rFormat
.GetRegisteredInNonConst() ),
198 m_aVertOrient( 0, rFormat
.GetVertOrient() )
199 ,m_cGrfBulletCP(rFormat
.m_cGrfBulletCP
)//For i120928,record the cp info of graphic within bullet
201 sal_Int16 eMyVertOrient
= rFormat
.GetVertOrient();
202 SetGraphicBrush( rFormat
.GetBrush(), &rFormat
.GetGraphicSize(),
206 SwNumFormat::SwNumFormat(const SvxNumberFormat
& rNumFormat
, SwDoc
* pDoc
)
207 : SvxNumberFormat(rNumFormat
)
208 , m_aVertOrient( 0, rNumFormat
.GetVertOrient() )
209 , m_cGrfBulletCP(USHRT_MAX
)
211 sal_Int16 eMyVertOrient
= rNumFormat
.GetVertOrient();
212 SetGraphicBrush( rNumFormat
.GetBrush(), &rNumFormat
.GetGraphicSize(),
214 const OUString rCharStyleName
= rNumFormat
.SvxNumberFormat::GetCharFormatName();
215 if( !rCharStyleName
.isEmpty() )
217 SwCharFormat
* pCFormat
= pDoc
->FindCharFormatByName( rCharStyleName
);
220 sal_uInt16 nId
= SwStyleNameMapper::GetPoolIdFromUIName( rCharStyleName
,
221 SwGetPoolIdFromName::ChrFmt
);
222 pCFormat
= nId
!= USHRT_MAX
223 ? pDoc
->getIDocumentStylePoolAccess().GetCharFormatFromPool( nId
)
224 : pDoc
->MakeCharFormat( rCharStyleName
, nullptr );
226 pCFormat
->Add( this );
232 SwNumFormat::~SwNumFormat()
237 bool SwNumFormat::IsEnumeration() const
239 // #i30655# native numbering did not work any longer
240 // using this code. Therefore HBRINKM and I agreed upon defining
241 // IsEnumeration() as !IsItemize()
245 bool SwNumFormat::IsItemize() const
249 switch(GetNumberingType())
251 case SVX_NUM_CHAR_SPECIAL
:
265 SwNumFormat
& SwNumFormat::operator=( const SwNumFormat
& rNumFormat
)
267 SvxNumberFormat::operator=(rNumFormat
);
268 StartListeningToSameModifyAs(rNumFormat
);
269 //For i120928,record the cp info of graphic within bullet
270 m_cGrfBulletCP
= rNumFormat
.m_cGrfBulletCP
;
274 bool SwNumFormat::operator==( const SwNumFormat
& rNumFormat
) const
276 bool bRet
= SvxNumberFormat::operator==(rNumFormat
) &&
277 GetRegisteredIn() == rNumFormat
.GetRegisteredIn();
281 void SwNumFormat::SetCharFormat( SwCharFormat
* pChFormat
)
284 pChFormat
->Add( this );
289 void SwNumFormat::SwClientNotify(const SwModify
&, const SfxHint
& rHint
)
291 if (rHint
.GetId() != SfxHintId::SwLegacyModify
)
293 auto pLegacy
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
294 // Look for the NumRules object in the Doc where this NumFormat is set.
295 // The format does not need to exist!
296 const SwCharFormat
* pFormat
= nullptr;
297 switch(pLegacy
->GetWhich())
299 case RES_ATTRSET_CHG
:
301 pFormat
= GetCharFormat();
305 if(pFormat
&& !pFormat
->GetDoc()->IsInDtor())
306 UpdateNumNodes(*const_cast<SwDoc
*>(pFormat
->GetDoc()));
308 CheckRegistration(pLegacy
->m_pOld
);
311 OUString
SwNumFormat::GetCharFormatName() const
313 if(static_cast<const SwCharFormat
*>(GetRegisteredIn()))
314 return static_cast<const SwCharFormat
*>(GetRegisteredIn())->GetName();
319 void SwNumFormat::SetGraphicBrush( const SvxBrushItem
* pBrushItem
, const Size
* pSize
,
320 const sal_Int16
* pOrient
)
323 m_aVertOrient
.SetVertOrient( *pOrient
);
324 SvxNumberFormat::SetGraphicBrush( pBrushItem
, pSize
, pOrient
);
327 void SwNumFormat::UpdateNumNodes( SwDoc
& rDoc
)
329 bool bDocIsModified
= rDoc
.getIDocumentState().IsModified();
331 for( SwNumRuleTable::size_type n
= rDoc
.GetNumRuleTable().size(); !bFnd
&& n
; )
333 const SwNumRule
* pRule
= rDoc
.GetNumRuleTable()[ --n
];
334 for( sal_uInt8 i
= 0; i
< MAXLEVEL
; ++i
)
335 if( pRule
->GetNumFormat( i
) == this )
337 SwNumRule::tTextNodeList aTextNodeList
;
338 pRule
->GetTextNodeList( aTextNodeList
);
339 for ( auto& rpTextNode
: aTextNodeList
)
341 lcl_SetRuleChgd( *rpTextNode
, i
);
348 if( bFnd
&& !bDocIsModified
)
349 rDoc
.getIDocumentState().ResetModified();
352 const SwFormatVertOrient
* SwNumFormat::GetGraphicOrientation() const
354 sal_Int16 eOrient
= SvxNumberFormat::GetVertOrient();
355 if(text::VertOrientation::NONE
== eOrient
)
359 const_cast<SwFormatVertOrient
&>(m_aVertOrient
).SetVertOrient(eOrient
);
360 return &m_aVertOrient
;
364 SwNumRule::SwNumRule( OUString aNm
,
365 const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode
,
366 SwNumRuleType eType
)
367 : mpNumRuleMap(nullptr),
368 msName( std::move(aNm
) ),
370 mnPoolFormatId( USHRT_MAX
),
371 mnPoolHelpId( USHRT_MAX
),
372 mnPoolHlpFileId( UCHAR_MAX
),
373 mbAutoRuleFlag( true ),
374 mbInvalidRuleFlag( true ),
375 mbContinusNum( false ),
376 mbAbsSpaces( false ),
378 mbCountPhantoms( true ),
379 mbUsedByRedline( false ),
380 meDefaultNumberFormatPositionAndSpaceMode( eDefaultNumberFormatPositionAndSpaceMode
)
382 if( !snRefCount
++ ) // for the first time, initialize
384 SwNumFormat
* pFormat
;
388 // position-and-space mode LABEL_WIDTH_AND_POSITION:
389 for( n
= 0; n
< MAXLEVEL
; ++n
)
391 pFormat
= new SwNumFormat
;
392 pFormat
->SetIncludeUpperLevels( 1 );
393 pFormat
->SetStart( 1 );
394 pFormat
->SetAbsLSpace( lNumberIndent
+ SwNumRule::GetNumIndent( n
) );
395 pFormat
->SetFirstLineOffset( lNumberFirstLineOffset
);
396 pFormat
->SetListFormat("%" + OUString::number(n
+ 1) + "%.");
397 pFormat
->SetBulletChar(numfunc::GetBulletChar(n
));
398 SwNumRule::saBaseFormats
[ NUM_RULE
][ n
] = pFormat
;
400 // position-and-space mode LABEL_ALIGNMENT
401 // first line indent of general numbering in inch: -0,25 inch
402 const tools::Long cFirstLineIndent
= o3tl::toTwips(-0.25, o3tl::Length::in
);
403 // indent values of general numbering in inch:
404 const tools::Long cIndentAt
[ MAXLEVEL
] = {
405 o3tl::toTwips(50, o3tl::Length::in100
),
406 o3tl::toTwips(75, o3tl::Length::in100
),
407 o3tl::toTwips(100, o3tl::Length::in100
),
408 o3tl::toTwips(125, o3tl::Length::in100
),
409 o3tl::toTwips(150, o3tl::Length::in100
),
410 o3tl::toTwips(175, o3tl::Length::in100
),
411 o3tl::toTwips(200, o3tl::Length::in100
),
412 o3tl::toTwips(225, o3tl::Length::in100
),
413 o3tl::toTwips(250, o3tl::Length::in100
),
414 o3tl::toTwips(275, o3tl::Length::in100
),
416 for( n
= 0; n
< MAXLEVEL
; ++n
)
418 pFormat
= new SwNumFormat
;
419 pFormat
->SetIncludeUpperLevels( 1 );
420 pFormat
->SetStart( 1 );
421 pFormat
->SetPositionAndSpaceMode( SvxNumberFormat::LABEL_ALIGNMENT
);
422 pFormat
->SetLabelFollowedBy( SvxNumberFormat::LISTTAB
);
423 pFormat
->SetListtabPos( cIndentAt
[ n
] );
424 pFormat
->SetFirstLineIndent( cFirstLineIndent
);
425 pFormat
->SetIndentAt( cIndentAt
[ n
] );
426 pFormat
->SetListFormat( "%" + OUString::number(n
+ 1) + "%.");
427 pFormat
->SetBulletChar( numfunc::GetBulletChar(n
));
428 SwNumRule::saLabelAlignmentBaseFormats
[ NUM_RULE
][ n
] = pFormat
;
432 // position-and-space mode LABEL_WIDTH_AND_POSITION:
433 for( n
= 0; n
< MAXLEVEL
; ++n
)
435 pFormat
= new SwNumFormat
;
436 pFormat
->SetNumberingType(SVX_NUM_NUMBER_NONE
);
437 pFormat
->SetIncludeUpperLevels( MAXLEVEL
);
438 pFormat
->SetStart( 1 );
439 pFormat
->SetCharTextDistance( lOutlineMinTextDistance
);
440 pFormat
->SetBulletChar( numfunc::GetBulletChar(n
));
441 SwNumRule::saBaseFormats
[ OUTLINE_RULE
][ n
] = pFormat
;
443 // position-and-space mode LABEL_ALIGNMENT:
444 for( n
= 0; n
< MAXLEVEL
; ++n
)
446 pFormat
= new SwNumFormat
;
447 pFormat
->SetNumberingType(SVX_NUM_NUMBER_NONE
);
448 pFormat
->SetIncludeUpperLevels( MAXLEVEL
);
449 pFormat
->SetStart( 1 );
450 pFormat
->SetPositionAndSpaceMode( SvxNumberFormat::LABEL_ALIGNMENT
);
451 pFormat
->SetBulletChar( numfunc::GetBulletChar(n
));
452 SwNumRule::saLabelAlignmentBaseFormats
[ OUTLINE_RULE
][ n
] = pFormat
;
455 OSL_ENSURE( !msName
.isEmpty(), "NumRule without a name!" );
458 SwNumRule::SwNumRule( const SwNumRule
& rNumRule
)
459 : mpNumRuleMap(nullptr),
460 msName( rNumRule
.msName
),
461 meRuleType( rNumRule
.meRuleType
),
462 mnPoolFormatId( rNumRule
.GetPoolFormatId() ),
463 mnPoolHelpId( rNumRule
.GetPoolHelpId() ),
464 mnPoolHlpFileId( rNumRule
.GetPoolHlpFileId() ),
465 mbAutoRuleFlag( rNumRule
.mbAutoRuleFlag
),
466 mbInvalidRuleFlag( true ),
467 mbContinusNum( rNumRule
.mbContinusNum
),
468 mbAbsSpaces( rNumRule
.mbAbsSpaces
),
469 mbHidden( rNumRule
.mbHidden
),
470 mbCountPhantoms( true ),
471 mbUsedByRedline( false ),
472 meDefaultNumberFormatPositionAndSpaceMode( rNumRule
.meDefaultNumberFormatPositionAndSpaceMode
),
473 msDefaultListId( rNumRule
.msDefaultListId
)
476 for( sal_uInt16 n
= 0; n
< MAXLEVEL
; ++n
)
477 if( rNumRule
.maFormats
[ n
] )
478 Set( n
, *rNumRule
.maFormats
[ n
] );
481 SwNumRule::~SwNumRule()
483 for (auto & i
: maFormats
)
488 mpNumRuleMap
->erase(GetName());
491 if( !--snRefCount
) // the last one closes the door (?)
494 SwNumFormat
** ppFormats
= &SwNumRule::saBaseFormats
[0][0];
497 for( n
= 0; n
< MAXLEVEL
; ++n
, ++ppFormats
)
500 *ppFormats
= nullptr;
504 for( n
= 0; n
< MAXLEVEL
; ++n
, ++ppFormats
)
507 *ppFormats
= nullptr;
510 ppFormats
= &SwNumRule::saLabelAlignmentBaseFormats
[0][0];
511 for( n
= 0; n
< MAXLEVEL
; ++n
, ++ppFormats
)
514 *ppFormats
= nullptr;
516 for( n
= 0; n
< MAXLEVEL
; ++n
, ++ppFormats
)
519 *ppFormats
= nullptr;
523 maTextNodeList
.clear();
524 maParagraphStyleList
.clear();
527 void SwNumRule::CheckCharFormats( SwDoc
& rDoc
)
529 for(auto& rpNumFormat
: maFormats
)
533 SwCharFormat
* pFormat
= rpNumFormat
->GetCharFormat();
534 if( pFormat
&& pFormat
->GetDoc() != &rDoc
)
537 SwNumFormat
* pNew
= new SwNumFormat( *rpNumFormat
);
538 pNew
->SetCharFormat( rDoc
.CopyCharFormat( *pFormat
) );
539 rpNumFormat
.reset(pNew
);
545 SwNumRule
& SwNumRule::operator=( const SwNumRule
& rNumRule
)
547 if( this != &rNumRule
)
549 for( sal_uInt16 n
= 0; n
< MAXLEVEL
; ++n
)
550 Set( n
, rNumRule
.maFormats
[ n
].get() );
552 meRuleType
= rNumRule
.meRuleType
;
553 msName
= rNumRule
.msName
;
554 mbAutoRuleFlag
= rNumRule
.mbAutoRuleFlag
;
555 mbInvalidRuleFlag
= true;
556 mbContinusNum
= rNumRule
.mbContinusNum
;
557 mbAbsSpaces
= rNumRule
.mbAbsSpaces
;
558 mbHidden
= rNumRule
.mbHidden
;
559 mnPoolFormatId
= rNumRule
.GetPoolFormatId();
560 mnPoolHelpId
= rNumRule
.GetPoolHelpId();
561 mnPoolHlpFileId
= rNumRule
.GetPoolHlpFileId();
566 void SwNumRule::Reset( const OUString
& rName
)
568 for( sal_uInt16 n
= 0; n
< MAXLEVEL
; ++n
)
571 meRuleType
= NUM_RULE
;
573 mbAutoRuleFlag
= true;
574 mbInvalidRuleFlag
= true;
575 mbContinusNum
= false;
578 mnPoolFormatId
= USHRT_MAX
;
579 mnPoolHelpId
= USHRT_MAX
;
580 mnPoolHlpFileId
= UCHAR_MAX
;
583 bool SwNumRule::operator==( const SwNumRule
& rRule
) const
585 bool bRet
= meRuleType
== rRule
.meRuleType
&&
586 msName
== rRule
.msName
&&
587 mbAutoRuleFlag
== rRule
.mbAutoRuleFlag
&&
588 mbContinusNum
== rRule
.mbContinusNum
&&
589 mbAbsSpaces
== rRule
.mbAbsSpaces
&&
590 mnPoolFormatId
== rRule
.GetPoolFormatId() &&
591 mnPoolHelpId
== rRule
.GetPoolHelpId() &&
592 mnPoolHlpFileId
== rRule
.GetPoolHlpFileId();
595 for( sal_uInt8 n
= 0; n
< MAXLEVEL
; ++n
)
596 if( rRule
.Get( n
) != Get( n
) )
605 void SwNumRule::Set( sal_uInt16 i
, const SwNumFormat
& rNumFormat
)
607 OSL_ENSURE( i
< MAXLEVEL
, "Serious defect" );
610 if( !maFormats
[ i
] || (rNumFormat
!= Get( i
)) )
612 maFormats
[ i
].reset(new SwNumFormat( rNumFormat
));
613 mbInvalidRuleFlag
= true;
618 void SwNumRule::Set( sal_uInt16 i
, const SwNumFormat
* pNumFormat
)
620 OSL_ENSURE( i
< MAXLEVEL
, "Serious defect" );
623 if( !maFormats
[ i
] )
627 maFormats
[ i
].reset(new SwNumFormat( *pNumFormat
));
628 mbInvalidRuleFlag
= true;
631 else if( !pNumFormat
)
633 maFormats
[ i
].reset();
634 mbInvalidRuleFlag
= true;
636 else if( *maFormats
[i
] != *pNumFormat
)
638 *maFormats
[ i
] = *pNumFormat
;
639 mbInvalidRuleFlag
= true;
643 OUString
SwNumRule::MakeNumString( const SwNodeNum
& rNum
, bool bInclStrings
) const
645 if (rNum
.IsCounted())
646 return MakeNumString(rNum
.GetNumberVector(), bInclStrings
);
651 OUString
SwNumRule::MakeNumString( const SwNumberTree::tNumberVector
& rNumVector
,
652 const bool bInclStrings
,
653 const unsigned int _nRestrictToThisLevel
,
654 SwNumRule::Extremities
* pExtremities
,
655 LanguageType nLang
) const
659 SwNumberTree::tNumberVector::size_type nLevel
= rNumVector
.size() - 1;
662 pExtremities
->nPrefixChars
= pExtremities
->nSuffixChars
= 0;
664 if ( nLevel
> _nRestrictToThisLevel
)
666 nLevel
= _nRestrictToThisLevel
;
669 assert(nLevel
< MAXLEVEL
);
671 const SwNumFormat
& rMyNFormat
= Get( o3tl::narrowing
<sal_uInt16
>(nLevel
) );
673 if (rMyNFormat
.GetNumberingType() == SVX_NUM_NUMBER_NONE
)
675 if (!rMyNFormat
.HasListFormat())
676 return bInclStrings
? rMyNFormat
.GetPrefix() + rMyNFormat
.GetSuffix() : OUString();
678 // If numbering is disabled for this level we should emit just prefix/suffix
679 // Remove everything between first %1% and last %n% (including markers)
680 OUString sLevelFormat
= rMyNFormat
.GetListFormat(bInclStrings
);
681 sal_Int32 nFirstPosition
= sLevelFormat
.indexOf("%");
682 sal_Int32 nLastPosition
= sLevelFormat
.lastIndexOf("%");
683 if (nFirstPosition
>= 0 && nLastPosition
>= nFirstPosition
)
684 sLevelFormat
= sLevelFormat
.replaceAt(nFirstPosition
, nLastPosition
- nFirstPosition
+ 1, u
"");
688 css::lang::Locale
aLocale( LanguageTag::convertToLocale(nLang
));
690 if (rMyNFormat
.HasListFormat())
692 OUString sLevelFormat
= rMyNFormat
.GetListFormat(bInclStrings
);
694 // In this case we are ignoring GetIncludeUpperLevels: we put all
695 // level numbers requested by level format
696 for (SwNumberTree::tNumberVector::size_type i
=0; i
<= nLevel
; ++i
)
698 OUString sReplacement
;
699 const SwNumFormat
& rNFormat
= Get(i
);
700 if (rNFormat
.GetNumberingType() == SVX_NUM_NUMBER_NONE
)
702 // Numbering disabled - replacement is empty
703 // And we should skip all level string content until next level marker:
704 // so %1%.%2%.%3% with second level as NONE will result 1.1, not 1..1
705 OUString
sFind("%" + OUString::number(i
+ 1) + "%");
706 sal_Int32 nPositionToken
= sLevelFormat
.indexOf(sFind
);
707 sal_Int32 nPositionNextToken
= sLevelFormat
.indexOf('%', nPositionToken
+ sFind
.getLength());
708 if (nPositionToken
>= 0 && nPositionNextToken
>= nPositionToken
)
710 sLevelFormat
= sLevelFormat
.replaceAt(nPositionToken
, nPositionNextToken
- nPositionToken
, u
"");
713 else if (rNumVector
[i
])
714 sReplacement
= Get(i
).GetNumStr(rNumVector
[i
], aLocale
);
716 sReplacement
= "0"; // all 0 level are a 0
718 OUString
sFind("%" + OUString::number(i
+ 1) + "%");
719 sal_Int32 nPosition
= sLevelFormat
.indexOf(sFind
);
721 sLevelFormat
= sLevelFormat
.replaceAt(nPosition
, sFind
.getLength(), sReplacement
);
728 // Fallback case: level format is not defined
729 // So use old way with levels joining by dot "."
730 SwNumberTree::tNumberVector::size_type i
= nLevel
;
732 if (!IsContinusNum() &&
733 // - do not include upper levels, if level isn't numbered.
734 rMyNFormat
.GetNumberingType() != SVX_NUM_NUMBER_NONE
&&
735 rMyNFormat
.GetIncludeUpperLevels()) // Just the own level?
737 sal_uInt8 n
= rMyNFormat
.GetIncludeUpperLevels();
747 for (; i
<= nLevel
; ++i
)
749 const SwNumFormat
& rNFormat
= Get(i
);
750 if (SVX_NUM_NUMBER_NONE
== rNFormat
.GetNumberingType())
752 // Should 1.1.1 --> 2. NoNum --> 1..1 or 1.1 ??
753 // if( i != rNum.nMyLevel )
759 aStr
.append(rNFormat
.GetNumStr(rNumVector
[i
], aLocale
));
761 aStr
.append("0"); // all 0 level are a 0
762 if (i
!= nLevel
&& !aStr
.isEmpty())
766 // The type doesn't have any number, so don't append
767 // the post-/prefix string
769 SVX_NUM_CHAR_SPECIAL
!= rMyNFormat
.GetNumberingType() &&
770 SVX_NUM_BITMAP
!= rMyNFormat
.GetNumberingType())
772 const OUString
& sPrefix
= rMyNFormat
.GetPrefix();
773 const OUString
& sSuffix
= rMyNFormat
.GetSuffix();
775 aStr
.insert(0, sPrefix
);
776 aStr
.append(sSuffix
);
779 pExtremities
->nPrefixChars
= sPrefix
.getLength();
780 pExtremities
->nSuffixChars
= sSuffix
.getLength();
785 return aStr
.makeStringAndClear();
788 OUString
SwNumRule::MakeRefNumString( const SwNodeNum
& rNodeNum
,
789 const bool bInclSuperiorNumLabels
,
790 const int nRestrictInclToThisLevel
) const
794 if ( rNodeNum
.GetLevelInListTree() >= 0 )
796 bool bOldHadPrefix
= true;
798 const SwNodeNum
* pWorkingNodeNum( &rNodeNum
);
801 bool bMakeNumStringForPhantom( false );
802 if ( pWorkingNodeNum
->IsPhantom() )
804 int nListLevel
= pWorkingNodeNum
->GetLevelInListTree();
809 if (nListLevel
>= MAXLEVEL
)
810 nListLevel
= MAXLEVEL
- 1;
812 SwNumFormat
aFormat( Get( o3tl::narrowing
<sal_uInt16
>(nListLevel
) ) );
813 bMakeNumStringForPhantom
= aFormat
.IsEnumeration() &&
814 SVX_NUM_NUMBER_NONE
!= aFormat
.GetNumberingType();
817 if ( bMakeNumStringForPhantom
||
818 ( !pWorkingNodeNum
->IsPhantom() &&
819 pWorkingNodeNum
->GetTextNode() &&
820 pWorkingNodeNum
->GetTextNode()->HasNumber() ) )
822 Extremities aExtremities
;
823 OUString aPrevStr
= MakeNumString( pWorkingNodeNum
->GetNumberVector(),
826 sal_Int32 nStrip
= 0;
827 while ( nStrip
< aExtremities
.nPrefixChars
)
829 const sal_Unicode c
= aPrevStr
[nStrip
];
830 if ( c
!='\t' && c
!=' ')
837 aPrevStr
= aPrevStr
.copy( nStrip
);
838 aExtremities
.nPrefixChars
-= nStrip
;
842 aExtremities
.nSuffixChars
&&
843 !aExtremities
.nPrefixChars
846 aPrevStr
= aPrevStr
.copy(0,
847 aPrevStr
.getLength() - aExtremities
.nSuffixChars
);
850 bOldHadPrefix
= ( aExtremities
.nPrefixChars
> 0);
852 aRefNumStr
= aPrevStr
+ aRefNumStr
;
855 if ( bInclSuperiorNumLabels
&& pWorkingNodeNum
->GetLevelInListTree() > 0 )
857 sal_uInt8 n
= Get( o3tl::narrowing
<sal_uInt16
>(pWorkingNodeNum
->GetLevelInListTree()) ).GetIncludeUpperLevels();
858 pWorkingNodeNum
= dynamic_cast<SwNodeNum
*>(pWorkingNodeNum
->GetParent());
859 // skip parents, whose list label is already contained in the actual list label.
860 while ( pWorkingNodeNum
&& n
> 1 )
862 pWorkingNodeNum
= dynamic_cast<SwNodeNum
*>(pWorkingNodeNum
->GetParent());
870 } while ( pWorkingNodeNum
&&
871 pWorkingNodeNum
->GetLevelInListTree() >= 0 &&
872 pWorkingNodeNum
->GetLevelInListTree() >= nRestrictInclToThisLevel
);
875 if (aRefNumStr
.endsWith("."))
877 // tdf#144563: looks like a special case for refs by MS Word: if numbering is ending with dot, this dot is removed
878 aRefNumStr
= aRefNumStr
.copy(0, aRefNumStr
.getLength() - 1);
884 OUString
SwNumRule::MakeParagraphStyleListString() const
886 OUString aParagraphStyleListString
;
887 for (const auto& rParagraphStyle
: maParagraphStyleList
)
889 if (!aParagraphStyleListString
.isEmpty())
890 aParagraphStyleListString
+= ", ";
891 aParagraphStyleListString
+= rParagraphStyle
->GetName();
893 return aParagraphStyleListString
;
896 /** Copy method of SwNumRule
898 A kind of copy constructor, so that the num formats are attached to the
899 right CharFormats of a Document.
900 Copies the NumFormats and returns itself. */
901 SwNumRule
& SwNumRule::CopyNumRule( SwDoc
& rDoc
, const SwNumRule
& rNumRule
)
903 for( sal_uInt16 n
= 0; n
< MAXLEVEL
; ++n
)
905 Set( n
, rNumRule
.maFormats
[ n
].get() );
906 if( maFormats
[ n
] && maFormats
[ n
]->GetCharFormat() &&
907 !rDoc
.GetCharFormats()->ContainsFormat(maFormats
[n
]->GetCharFormat()))
909 // If we copy across different Documents, then copy the
910 // corresponding CharFormat into the new Document.
911 maFormats
[n
]->SetCharFormat( rDoc
.CopyCharFormat( *maFormats
[n
]->
915 meRuleType
= rNumRule
.meRuleType
;
916 msName
= rNumRule
.msName
;
917 mbAutoRuleFlag
= rNumRule
.mbAutoRuleFlag
;
918 mnPoolFormatId
= rNumRule
.GetPoolFormatId();
919 mnPoolHelpId
= rNumRule
.GetPoolHelpId();
920 mnPoolHlpFileId
= rNumRule
.GetPoolHlpFileId();
921 mbInvalidRuleFlag
= true;
925 void SwNumRule::SetSvxRule(const SvxNumRule
& rNumRule
, SwDoc
* pDoc
)
927 for( sal_uInt16 n
= 0; n
< MAXLEVEL
; ++n
)
929 const SvxNumberFormat
* pSvxFormat
= rNumRule
.Get(n
);
930 maFormats
[n
].reset( pSvxFormat
? new SwNumFormat(*pSvxFormat
, pDoc
) : nullptr );
933 mbInvalidRuleFlag
= true;
934 mbContinusNum
= rNumRule
.IsContinuousNumbering();
937 SvxNumRule
SwNumRule::MakeSvxNumRule() const
939 SvxNumRule
aRule(SvxNumRuleFlags::CONTINUOUS
| SvxNumRuleFlags::CHAR_STYLE
|
940 SvxNumRuleFlags::ENABLE_LINKED_BMP
| SvxNumRuleFlags::ENABLE_EMBEDDED_BMP
,
941 MAXLEVEL
, mbContinusNum
,
942 meRuleType
== NUM_RULE
? SvxNumRuleType::NUMBERING
: SvxNumRuleType::OUTLINE_NUMBERING
);
943 for( sal_uInt16 n
= 0; n
< MAXLEVEL
; ++n
)
945 const SwNumFormat
& rNumFormat
= Get(n
);
946 if(rNumFormat
.GetCharFormat())
948 SwNumFormat aNewFormat
= rNumFormat
;
949 aNewFormat
.SetCharFormatName(rNumFormat
.GetCharFormat()->GetName());
950 aRule
.SetLevel(n
, aNewFormat
, maFormats
[n
] != nullptr);
953 aRule
.SetLevel(n
, rNumFormat
, maFormats
[n
] != nullptr);
958 void SwNumRule::SetInvalidRule(bool bFlag
)
960 if (mbInvalidRuleFlag
== bFlag
)
965 o3tl::sorted_vector
< SwList
* > aLists
;
966 for ( const SwTextNode
* pTextNode
: maTextNodeList
)
968 // #i111681# - applying patch from cmc
969 SwList
* pList
= pTextNode
->GetDoc().getIDocumentListsAccess().getListByName( pTextNode
->GetListId() );
970 OSL_ENSURE( pList
, "<SwNumRule::SetInvalidRule(..)> - list at which the text node is registered at does not exist. This is a serious issue.");
973 aLists
.insert( pList
);
976 for ( auto aList
: aLists
)
977 aList
->InvalidateListTree();
980 mbInvalidRuleFlag
= bFlag
;
983 /// change indent of all list levels by given difference
984 void SwNumRule::ChangeIndent( const sal_Int32 nDiff
)
986 for ( sal_uInt16 i
= 0; i
< MAXLEVEL
; ++i
)
988 SwNumFormat
aTmpNumFormat( Get(i
) );
990 const SvxNumberFormat::SvxNumPositionAndSpaceMode
ePosAndSpaceMode(
991 aTmpNumFormat
.GetPositionAndSpaceMode() );
992 if ( ePosAndSpaceMode
== SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
994 auto nNewIndent
= nDiff
+
995 aTmpNumFormat
.GetAbsLSpace();
996 if ( nNewIndent
< 0 )
1000 aTmpNumFormat
.SetAbsLSpace( nNewIndent
);
1002 else if ( ePosAndSpaceMode
== SvxNumberFormat::LABEL_ALIGNMENT
)
1004 // adjust also the list tab position, if a list tab stop is applied
1005 if ( aTmpNumFormat
.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB
)
1007 const tools::Long nNewListTab
= aTmpNumFormat
.GetListtabPos() + nDiff
;
1008 aTmpNumFormat
.SetListtabPos( nNewListTab
);
1011 const tools::Long nNewIndent
= nDiff
+
1012 aTmpNumFormat
.GetIndentAt();
1013 aTmpNumFormat
.SetIndentAt( nNewIndent
);
1016 Set( i
, aTmpNumFormat
);
1019 SetInvalidRule( true );
1022 /// set indent of certain list level to given value
1023 void SwNumRule::SetIndent( const short nNewIndent
,
1024 const sal_uInt16 nListLevel
)
1026 SwNumFormat
aTmpNumFormat( Get(nListLevel
) );
1028 const SvxNumberFormat::SvxNumPositionAndSpaceMode
ePosAndSpaceMode(
1029 aTmpNumFormat
.GetPositionAndSpaceMode() );
1030 if ( ePosAndSpaceMode
== SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
1032 aTmpNumFormat
.SetAbsLSpace( nNewIndent
);
1034 else if ( ePosAndSpaceMode
== SvxNumberFormat::LABEL_ALIGNMENT
)
1036 // adjust also the list tab position, if a list tab stop is applied
1037 if ( aTmpNumFormat
.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB
)
1039 const tools::Long nNewListTab
= aTmpNumFormat
.GetListtabPos() +
1040 ( nNewIndent
- aTmpNumFormat
.GetIndentAt() );
1041 aTmpNumFormat
.SetListtabPos( nNewListTab
);
1044 aTmpNumFormat
.SetIndentAt( nNewIndent
);
1047 SetInvalidRule( true );
1050 /// set indent of first list level to given value and change other list level's
1051 /// indents accordingly
1052 void SwNumRule::SetIndentOfFirstListLevelAndChangeOthers( const short nNewIndent
)
1054 SwNumFormat
aTmpNumFormat( Get(0) );
1056 sal_Int32
nDiff( 0 );
1057 const SvxNumberFormat::SvxNumPositionAndSpaceMode
ePosAndSpaceMode(
1058 aTmpNumFormat
.GetPositionAndSpaceMode() );
1059 if ( ePosAndSpaceMode
== SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
1062 - aTmpNumFormat
.GetFirstLineOffset()
1063 - aTmpNumFormat
.GetAbsLSpace();
1065 else if ( ePosAndSpaceMode
== SvxNumberFormat::LABEL_ALIGNMENT
)
1067 nDiff
= nNewIndent
- aTmpNumFormat
.GetIndentAt();
1071 ChangeIndent( nDiff
);
1075 void SwNumRule::Validate(const SwDoc
& rDoc
)
1077 o3tl::sorted_vector
< SwList
* > aLists
;
1078 for ( const SwTextNode
* pTextNode
: maTextNodeList
)
1080 aLists
.insert( pTextNode
->GetDoc().getIDocumentListsAccess().getListByName( pTextNode
->GetListId() ) );
1082 for ( auto aList
: aLists
)
1083 aList
->ValidateListTree(rDoc
);
1085 SetInvalidRule(false);
1088 void SwNumRule::SetCountPhantoms(bool bCountPhantoms
)
1090 mbCountPhantoms
= bCountPhantoms
;
1093 SwNumRule::tParagraphStyleList::size_type
SwNumRule::GetParagraphStyleListSize() const
1095 return maParagraphStyleList
.size();
1098 void SwNumRule::AddParagraphStyle( SwTextFormatColl
& rTextFormatColl
)
1100 tParagraphStyleList::iterator aIter
=
1101 std::find( maParagraphStyleList
.begin(), maParagraphStyleList
.end(), &rTextFormatColl
);
1103 if ( aIter
== maParagraphStyleList
.end() )
1105 maParagraphStyleList
.push_back( &rTextFormatColl
);
1109 void SwNumRule::RemoveParagraphStyle( SwTextFormatColl
& rTextFormatColl
)
1111 tParagraphStyleList::iterator aIter
=
1112 std::find( maParagraphStyleList
.begin(), maParagraphStyleList
.end(), &rTextFormatColl
);
1114 if ( aIter
!= maParagraphStyleList
.end() )
1116 maParagraphStyleList
.erase( aIter
);
1120 void SwNumRule::dumpAsXml(xmlTextWriterPtr pWriter
) const
1122 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SwNumRule"));
1123 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("msName"), BAD_CAST(msName
.toUtf8().getStr()));
1124 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("mnPoolFormatId"), BAD_CAST(OString::number(mnPoolFormatId
).getStr()));
1125 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("mbAutoRuleFlag"), BAD_CAST(OString::boolean(mbAutoRuleFlag
).getStr()));
1127 for (const auto& pFormat
: maFormats
)
1134 pFormat
->dumpAsXml(pWriter
);
1137 (void)xmlTextWriterEndElement(pWriter
);
1140 void SwNumRule::GetGrabBagItem(uno::Any
& rVal
) const
1143 mpGrabBagItem
->QueryValue(rVal
);
1145 rVal
<<= uno::Sequence
<beans::PropertyValue
>();
1148 void SwNumRule::SetGrabBagItem(const uno::Any
& rVal
)
1151 mpGrabBagItem
= std::make_shared
<SfxGrabBagItem
>();
1153 mpGrabBagItem
->PutValue(rVal
, 0);
1160 /** class containing default bullet list configuration data */
1161 class SwDefBulletConfig
: private utl::ConfigItem
1164 static SwDefBulletConfig
& getInstance();
1166 const OUString
& GetFontname() const
1171 bool IsFontnameUserDefined() const
1173 return mbUserDefinedFontname
;
1176 const vcl::Font
& GetFont() const
1181 sal_Unicode
GetChar( sal_uInt8 p_nListLevel
) const
1183 if (p_nListLevel
>= MAXLEVEL
)
1185 p_nListLevel
= MAXLEVEL
- 1;
1188 return mnLevelChars
[p_nListLevel
];
1191 SwDefBulletConfig();
1194 /** sets internal default bullet configuration data to default values */
1195 void SetToDefault();
1197 /** returns sequence of default bullet configuration property names */
1198 static uno::Sequence
<OUString
> GetPropNames();
1200 /** loads default bullet configuration properties and applies
1201 values to internal data */
1204 /** initialize font instance for default bullet list */
1207 /** catches notification about changed default bullet configuration data */
1208 virtual void Notify( const uno::Sequence
<OUString
>& aPropertyNames
) override
;
1209 virtual void ImplCommit() override
;
1211 // default bullet list configuration data
1212 OUString msFontname
;
1213 bool mbUserDefinedFontname
;
1214 FontWeight meFontWeight
;
1215 FontItalic meFontItalic
;
1216 sal_Unicode mnLevelChars
[MAXLEVEL
];
1218 // default bullet list font instance
1219 std::optional
<vcl::Font
> mpFont
;
1224 SwDefBulletConfig
& SwDefBulletConfig::getInstance()
1226 static SwDefBulletConfig theSwDefBulletConfig
;
1227 return theSwDefBulletConfig
;
1230 SwDefBulletConfig::SwDefBulletConfig()
1231 : ConfigItem( "Office.Writer/Numbering/DefaultBulletList" ),
1232 // default bullet font is now OpenSymbol
1233 msFontname( OUString("OpenSymbol") ),
1234 mbUserDefinedFontname( false ),
1235 meFontWeight( WEIGHT_DONTKNOW
),
1236 meFontItalic( ITALIC_NONE
)
1242 // enable notification for changes on default bullet configuration change
1243 EnableNotification( GetPropNames() );
1246 void SwDefBulletConfig::SetToDefault()
1248 msFontname
= "OpenSymbol";
1249 mbUserDefinedFontname
= false;
1250 meFontWeight
= WEIGHT_DONTKNOW
;
1251 meFontItalic
= ITALIC_NONE
;
1253 mnLevelChars
[0] = 0x2022;
1254 mnLevelChars
[1] = 0x25e6;
1255 mnLevelChars
[2] = 0x25aa;
1256 mnLevelChars
[3] = 0x2022;
1257 mnLevelChars
[4] = 0x25e6;
1258 mnLevelChars
[5] = 0x25aa;
1259 mnLevelChars
[6] = 0x2022;
1260 mnLevelChars
[7] = 0x25e6;
1261 mnLevelChars
[8] = 0x25aa;
1262 mnLevelChars
[9] = 0x2022;
1265 uno::Sequence
<OUString
> SwDefBulletConfig::GetPropNames()
1267 uno::Sequence
<OUString
> aPropNames(13);
1268 OUString
* pNames
= aPropNames
.getArray();
1269 pNames
[0] = "BulletFont/FontFamilyname";
1270 pNames
[1] = "BulletFont/FontWeight";
1271 pNames
[2] = "BulletFont/FontItalic";
1272 pNames
[3] = "BulletCharLvl1";
1273 pNames
[4] = "BulletCharLvl2";
1274 pNames
[5] = "BulletCharLvl3";
1275 pNames
[6] = "BulletCharLvl4";
1276 pNames
[7] = "BulletCharLvl5";
1277 pNames
[8] = "BulletCharLvl6";
1278 pNames
[9] = "BulletCharLvl7";
1279 pNames
[10] = "BulletCharLvl8";
1280 pNames
[11] = "BulletCharLvl9";
1281 pNames
[12] = "BulletCharLvl10";
1286 void SwDefBulletConfig::LoadConfig()
1288 uno::Sequence
<OUString
> aPropNames
= GetPropNames();
1289 uno::Sequence
<uno::Any
> aValues
= GetProperties( aPropNames
);
1290 const uno::Any
* pValues
= aValues
.getConstArray();
1291 OSL_ENSURE( aValues
.getLength() == aPropNames
.getLength(),
1292 "<SwDefBulletConfig::SwDefBulletConfig()> - GetProperties failed");
1293 if ( aValues
.getLength() != aPropNames
.getLength() )
1296 for ( int nProp
= 0; nProp
< aPropNames
.getLength(); ++nProp
)
1298 if ( pValues
[nProp
].hasValue() )
1305 pValues
[nProp
] >>= aStr
;
1307 mbUserDefinedFontname
= true;
1314 pValues
[nProp
] >>= nTmp
;
1316 meFontWeight
= static_cast<FontWeight
>(nTmp
);
1317 else if ( nProp
== 2 )
1318 meFontItalic
= static_cast<FontItalic
>(nTmp
);
1332 sal_Unicode cChar
= sal_Unicode();
1333 pValues
[nProp
] >>= cChar
;
1334 mnLevelChars
[nProp
-3] = cChar
;
1343 void SwDefBulletConfig::InitFont()
1345 mpFont
.emplace( msFontname
, OUString(), Size( 0, 14 ) );
1346 mpFont
->SetWeight( meFontWeight
);
1347 mpFont
->SetItalic( meFontItalic
);
1348 mpFont
->SetCharSet( RTL_TEXTENCODING_SYMBOL
);
1351 void SwDefBulletConfig::Notify( const uno::Sequence
<OUString
>& )
1358 void SwDefBulletConfig::ImplCommit()
1362 OUString
const & GetDefBulletFontname()
1364 return SwDefBulletConfig::getInstance().GetFontname();
1367 bool IsDefBulletFontUserDefined()
1369 return SwDefBulletConfig::getInstance().IsFontnameUserDefined();
1372 const vcl::Font
& GetDefBulletFont()
1374 return SwDefBulletConfig::getInstance().GetFont();
1377 sal_Unicode
GetBulletChar( sal_uInt8 nLevel
)
1379 return SwDefBulletConfig::getInstance().GetChar( nLevel
);
1384 /** class containing configuration data about user interface behavior
1385 regarding lists and list items.
1386 configuration item about behavior of <TAB>/<SHIFT-TAB>-key at first
1387 position of first list item
1389 class SwNumberingUIBehaviorConfig
: private utl::ConfigItem
1392 static SwNumberingUIBehaviorConfig
& getInstance();
1394 bool ChangeIndentOnTabAtFirstPosOfFirstListItem() const
1396 return mbChangeIndentOnTabAtFirstPosOfFirstListItem
;
1399 SwNumberingUIBehaviorConfig();
1403 /** sets internal configuration data to default values */
1404 void SetToDefault();
1406 /** returns sequence of configuration property names */
1407 static css::uno::Sequence
<OUString
> GetPropNames();
1409 /** loads configuration properties and applies values to internal data */
1412 /** catches notification about changed configuration data */
1413 virtual void Notify( const css::uno::Sequence
<OUString
>& aPropertyNames
) override
;
1414 virtual void ImplCommit() override
;
1416 // configuration data
1417 bool mbChangeIndentOnTabAtFirstPosOfFirstListItem
;
1422 SwNumberingUIBehaviorConfig
& SwNumberingUIBehaviorConfig::getInstance()
1424 static SwNumberingUIBehaviorConfig theSwNumberingUIBehaviorConfig
;
1425 return theSwNumberingUIBehaviorConfig
;
1428 SwNumberingUIBehaviorConfig::SwNumberingUIBehaviorConfig()
1429 : ConfigItem( "Office.Writer/Numbering/UserInterfaceBehavior" ),
1430 mbChangeIndentOnTabAtFirstPosOfFirstListItem( true )
1435 // enable notification for changes on configuration change
1436 EnableNotification( GetPropNames() );
1439 void SwNumberingUIBehaviorConfig::SetToDefault()
1441 mbChangeIndentOnTabAtFirstPosOfFirstListItem
= true;
1444 css::uno::Sequence
<OUString
> SwNumberingUIBehaviorConfig::GetPropNames()
1446 css::uno::Sequence
<OUString
> aPropNames
{ "ChangeIndentOnTabAtFirstPosOfFirstListItem" };
1451 void SwNumberingUIBehaviorConfig::ImplCommit() {}
1453 void SwNumberingUIBehaviorConfig::LoadConfig()
1455 css::uno::Sequence
<OUString
> aPropNames
= GetPropNames();
1456 css::uno::Sequence
<css::uno::Any
> aValues
= GetProperties( aPropNames
);
1457 const css::uno::Any
* pValues
= aValues
.getConstArray();
1458 OSL_ENSURE( aValues
.getLength() == aPropNames
.getLength(),
1459 "<SwNumberingUIBehaviorConfig::LoadConfig()> - GetProperties failed");
1460 if ( aValues
.getLength() != aPropNames
.getLength() )
1463 for ( int nProp
= 0; nProp
< aPropNames
.getLength(); ++nProp
)
1465 if ( pValues
[nProp
].hasValue() )
1471 pValues
[nProp
] >>= mbChangeIndentOnTabAtFirstPosOfFirstListItem
;
1476 OSL_FAIL( "<SwNumberingUIBehaviorConfig::LoadConfig()> - unknown configuration property");
1483 void SwNumberingUIBehaviorConfig::Notify( const css::uno::Sequence
<OUString
>& )
1489 bool ChangeIndentOnTabAtFirstPosOfFirstListItem()
1491 return SwNumberingUIBehaviorConfig::getInstance().ChangeIndentOnTabAtFirstPosOfFirstListItem();
1494 bool NumDownChangesIndent(const SwWrtShell
& rShell
)
1496 SwPaM
* pCursor
= rShell
.GetCursor();
1502 SwTextNode
* pTextNode
= pCursor
->GetPointNode().GetTextNode();
1508 const SwNumRule
* pNumRule
= pTextNode
->GetNumRule();
1514 int nOldLevel
= pTextNode
->GetActualListLevel();
1515 int nNewLevel
= nOldLevel
+ 1;
1516 if (nNewLevel
>= MAXLEVEL
)
1521 const SwNumFormat
& rOldFormat
= pNumRule
->Get(nOldLevel
);
1522 if (rOldFormat
.GetNumberingType() != SVX_NUM_NUMBER_NONE
)
1527 const SwNumFormat
& rNewFormat
= pNumRule
->Get(nNewLevel
);
1528 if (rNewFormat
.GetNumberingType() != SVX_NUM_NUMBER_NONE
)
1533 // This is the case when the numbering levels don't differ, so changing between them is not
1534 // a better alternative to inserting a tab character.
1535 return rOldFormat
.GetIndentAt() != rNewFormat
.GetIndentAt();
1538 SvxNumberFormat::SvxNumPositionAndSpaceMode
GetDefaultPositionAndSpaceMode()
1540 if (utl::ConfigManager::IsFuzzing())
1541 return SvxNumberFormat::LABEL_ALIGNMENT
;
1543 SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode
;
1544 switch (GetODFSaneDefaultVersion())
1546 case SvtSaveOptions::ODFSVER_010
:
1547 case SvtSaveOptions::ODFSVER_011
:
1549 ePosAndSpaceMode
= SvxNumberFormat::LABEL_WIDTH_AND_POSITION
;
1552 default: // >= ODFSVER_012
1554 ePosAndSpaceMode
= SvxNumberFormat::LABEL_ALIGNMENT
;
1558 return ePosAndSpaceMode
;
1562 void SwNumRuleTable::dumpAsXml(xmlTextWriterPtr pWriter
) const
1564 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SwNumRuleTable"));
1565 for (SwNumRule
* pNumRule
: *this)
1566 pNumRule
->dumpAsXml(pWriter
);
1567 (void)xmlTextWriterEndElement(pWriter
);
1570 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */