LibreOffice Module sw (master) 1
number.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <memory>
21#include <hintids.hxx>
22
23#include <utility>
24#include <vcl/font.hxx>
25#include <editeng/brushitem.hxx>
26#include <editeng/numitem.hxx>
27#include <svl/grabbagitem.hxx>
28#include <fmtornt.hxx>
29#include <doc.hxx>
30#include <charfmt.hxx>
31#include <ndtxt.hxx>
32#include <docary.hxx>
33#include <SwStyleNameMapper.hxx>
34
35// Needed to load default bullet list configuration
38
39#include <numrule.hxx>
40#include <SwNodeNum.hxx>
41
42#include <list.hxx>
43
44#include <algorithm>
45#include <unordered_map>
46#include <libxml/xmlwriter.h>
47
48#include <rtl/ustrbuf.hxx>
50#include <unotools/saveopt.hxx>
51#include <osl/diagnose.h>
52
55#include <IDocumentState.hxx>
56
57#include <com/sun/star/beans/PropertyValue.hpp>
58#include <wrtsh.hxx>
59
60using namespace ::com::sun::star;
61
62sal_uInt16 SwNumRule::snRefCount = 0;
64 {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr } };
65
67 {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr } };
68
69const sal_uInt16 SwNumRule::saDefNumIndents[ MAXLEVEL ] = {
80};
81
83{
84 return "Outline";
85}
86
87const SwNumFormat& SwNumRule::Get( sal_uInt16 i ) const
88{
89 assert( i < MAXLEVEL && meRuleType < RULE_END );
90 return maFormats[ i ]
91 ? *maFormats[ i ]
95}
96
97const SwNumFormat* SwNumRule::GetNumFormat( sal_uInt16 i ) const
98{
99 const SwNumFormat * pResult = nullptr;
100
101 assert( i < MAXLEVEL && meRuleType < RULE_END );
102 if ( i < MAXLEVEL && meRuleType < RULE_END)
103 {
104 pResult = maFormats[ i ].get();
105 }
106
107 return pResult;
108}
109
110// #i91400#
111void SwNumRule::SetName( const OUString & rName,
112 IDocumentListsAccess& rDocListAccess)
113{
114 if ( msName == rName )
115 return;
116
117 if (mpNumRuleMap)
118 {
119 mpNumRuleMap->erase(msName);
120 (*mpNumRuleMap)[rName] = this;
121
122 if ( !GetDefaultListId().isEmpty() )
123 {
124 rDocListAccess.trackChangeOfListStyleName( msName, rName );
125 }
126 }
127
128 msName = rName;
129}
130
132{
133 rTextNodeList = maTextNodeList;
134}
135
136SwNumRule::tTextNodeList::size_type SwNumRule::GetTextNodeListSize() const
137{
138 return maTextNodeList.size();
139}
140
142{
143 tTextNodeList::iterator aIter =
144 std::find( maTextNodeList.begin(), maTextNodeList.end(), &rTextNode );
145
146 if ( aIter == maTextNodeList.end() )
147 {
148 maTextNodeList.push_back( &rTextNode );
149 }
150}
151
153{
154 tTextNodeList::iterator aIter =
155 std::find( maTextNodeList.begin(), maTextNodeList.end(), &rTextNode );
156
157 if ( aIter != maTextNodeList.end() )
158 {
159 maTextNodeList.erase( aIter );
160 }
161}
162
163void SwNumRule::SetNumRuleMap(std::unordered_map<OUString, SwNumRule *> *
164 pNumRuleMap)
165{
166 mpNumRuleMap = pNumRuleMap;
167}
168
170{
171 OSL_ENSURE( MAXLEVEL > nLvl, "NumLevel is out of range" );
172 return saDefNumIndents[ nLvl ];
173}
174
176{
177 OSL_ENSURE( MAXLEVEL > nLvl, "NumLevel is out of range" );
178 return saDefNumIndents[ nLvl ];
179}
180
181static void lcl_SetRuleChgd( SwTextNode& rNd, sal_uInt8 nLevel )
182{
183 if( rNd.GetActualListLevel() == nLevel )
184 rNd.NumRuleChgd();
185}
186
189 SwClient( nullptr ),
190 m_aVertOrient( 0, text::VertOrientation::NONE )
191 ,m_cGrfBulletCP(USHRT_MAX)//For i120928,record the cp info of graphic within bullet
192{
193}
194
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
200{
201 sal_Int16 eMyVertOrient = rFormat.GetVertOrient();
202 SetGraphicBrush( rFormat.GetBrush(), &rFormat.GetGraphicSize(),
203 &eMyVertOrient);
204}
205
207 : SvxNumberFormat(rNumFormat)
208 , m_aVertOrient( 0, rNumFormat.GetVertOrient() )
209 , m_cGrfBulletCP(USHRT_MAX)
210{
211 sal_Int16 eMyVertOrient = rNumFormat.GetVertOrient();
212 SetGraphicBrush( rNumFormat.GetBrush(), &rNumFormat.GetGraphicSize(),
213 &eMyVertOrient);
214 const OUString rCharStyleName = rNumFormat.SvxNumberFormat::GetCharFormatName();
215 if( !rCharStyleName.isEmpty() )
216 {
217 SwCharFormat* pCFormat = pDoc->FindCharFormatByName( rCharStyleName );
218 if( !pCFormat )
219 {
220 sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( rCharStyleName,
222 pCFormat = nId != USHRT_MAX
224 : pDoc->MakeCharFormat( rCharStyleName, nullptr );
225 }
226 pCFormat->Add( this );
227 }
228 else
230}
231
233{
234}
235
236// #i22362#
238{
239 // #i30655# native numbering did not work any longer
240 // using this code. Therefore HBRINKM and I agreed upon defining
241 // IsEnumeration() as !IsItemize()
242 return !IsItemize();
243}
244
246{
247 bool bResult;
248
249 switch(GetNumberingType())
250 {
252 case SVX_NUM_BITMAP:
253 bResult = true;
254
255 break;
256
257 default:
258 bResult = false;
259 }
260
261 return bResult;
262
263}
264
266{
267 SvxNumberFormat::operator=(rNumFormat);
269 //For i120928,record the cp info of graphic within bullet
270 m_cGrfBulletCP = rNumFormat.m_cGrfBulletCP;
271 return *this;
272}
273
274bool SwNumFormat::operator==( const SwNumFormat& rNumFormat) const
275{
276 bool bRet = SvxNumberFormat::operator==(rNumFormat) &&
277 GetRegisteredIn() == rNumFormat.GetRegisteredIn();
278 return bRet;
279}
280
282{
283 if( pChFormat )
284 pChFormat->Add( this );
285 else
287}
288
290{
291 if (rHint.GetId() != SfxHintId::SwLegacyModify)
292 return;
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())
298 {
299 case RES_ATTRSET_CHG:
300 case RES_FMT_CHG:
301 pFormat = GetCharFormat();
302 break;
303 }
304
305 if(pFormat && !pFormat->GetDoc()->IsInDtor())
306 UpdateNumNodes(*const_cast<SwDoc*>(pFormat->GetDoc()));
307 else
308 CheckRegistration(pLegacy->m_pOld);
309}
310
312{
313 if(static_cast<const SwCharFormat*>(GetRegisteredIn()))
314 return static_cast<const SwCharFormat*>(GetRegisteredIn())->GetName();
315
316 return OUString();
317}
318
319void SwNumFormat::SetGraphicBrush( const SvxBrushItem* pBrushItem, const Size* pSize,
320 const sal_Int16* pOrient)
321{
322 if(pOrient)
323 m_aVertOrient.SetVertOrient( *pOrient );
324 SvxNumberFormat::SetGraphicBrush( pBrushItem, pSize, pOrient);
325}
326
328{
329 bool bDocIsModified = rDoc.getIDocumentState().IsModified();
330 bool bFnd = false;
331 for( SwNumRuleTable::size_type n = rDoc.GetNumRuleTable().size(); !bFnd && n; )
332 {
333 const SwNumRule* pRule = rDoc.GetNumRuleTable()[ --n ];
334 for( sal_uInt8 i = 0; i < MAXLEVEL; ++i )
335 if( pRule->GetNumFormat( i ) == this )
336 {
337 SwNumRule::tTextNodeList aTextNodeList;
338 pRule->GetTextNodeList( aTextNodeList );
339 for ( auto& rpTextNode : aTextNodeList )
340 {
341 lcl_SetRuleChgd( *rpTextNode, i );
342 }
343 bFnd = true;
344 break;
345 }
346 }
347
348 if( bFnd && !bDocIsModified )
350}
351
353{
354 sal_Int16 eOrient = SvxNumberFormat::GetVertOrient();
355 if(text::VertOrientation::NONE == eOrient)
356 return nullptr;
357 else
358 {
359 const_cast<SwFormatVertOrient&>(m_aVertOrient).SetVertOrient(eOrient);
360 return &m_aVertOrient;
361 }
362}
363
365 const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode,
366 SwNumRuleType eType )
367 : mpNumRuleMap(nullptr),
368 msName( std::move(aNm) ),
369 meRuleType( eType ),
370 mnPoolFormatId( USHRT_MAX ),
371 mnPoolHelpId( USHRT_MAX ),
372 mnPoolHlpFileId( UCHAR_MAX ),
373 mbAutoRuleFlag( true ),
374 mbInvalidRuleFlag( true ),
375 mbContinusNum( false ),
376 mbAbsSpaces( false ),
377 mbHidden( false ),
378 mbCountPhantoms( true ),
379 mbUsedByRedline( false ),
380 meDefaultNumberFormatPositionAndSpaceMode( eDefaultNumberFormatPositionAndSpaceMode )
381{
382 if( !snRefCount++ ) // for the first time, initialize
383 {
384 SwNumFormat* pFormat;
385 sal_uInt8 n;
386
387 // numbering:
388 // position-and-space mode LABEL_WIDTH_AND_POSITION:
389 for( n = 0; n < MAXLEVEL; ++n )
390 {
391 pFormat = new SwNumFormat;
392 pFormat->SetIncludeUpperLevels( 1 );
393 pFormat->SetStart( 1 );
396 pFormat->SetListFormat("%" + OUString::number(n + 1) + "%.");
398 SwNumRule::saBaseFormats[ NUM_RULE ][ n ] = pFormat;
399 }
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 ] = {
415 };
416 for( n = 0; n < MAXLEVEL; ++n )
417 {
418 pFormat = new SwNumFormat;
419 pFormat->SetIncludeUpperLevels( 1 );
420 pFormat->SetStart( 1 );
423 pFormat->SetListtabPos( cIndentAt[ n ] );
424 pFormat->SetFirstLineIndent( cFirstLineIndent );
425 pFormat->SetIndentAt( cIndentAt[ n ] );
426 pFormat->SetListFormat( "%" + OUString::number(n + 1) + "%.");
429 }
430
431 // outline:
432 // position-and-space mode LABEL_WIDTH_AND_POSITION:
433 for( n = 0; n < MAXLEVEL; ++n )
434 {
435 pFormat = new SwNumFormat;
438 pFormat->SetStart( 1 );
442 }
443 // position-and-space mode LABEL_ALIGNMENT:
444 for( n = 0; n < MAXLEVEL; ++n )
445 {
446 pFormat = new SwNumFormat;
449 pFormat->SetStart( 1 );
453 }
454 }
455 OSL_ENSURE( !msName.isEmpty(), "NumRule without a name!" );
456}
457
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 )
474{
475 ++snRefCount;
476 for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
477 if( rNumRule.maFormats[ n ] )
478 Set( n, *rNumRule.maFormats[ n ] );
479}
480
482{
483 for (auto & i : maFormats)
484 i.reset();
485
486 if (mpNumRuleMap)
487 {
488 mpNumRuleMap->erase(GetName());
489 }
490
491 if( !--snRefCount ) // the last one closes the door (?)
492 {
493 // Numbering:
494 SwNumFormat** ppFormats = &SwNumRule::saBaseFormats[0][0];
495 int n;
496
497 for( n = 0; n < MAXLEVEL; ++n, ++ppFormats )
498 {
499 delete *ppFormats;
500 *ppFormats = nullptr;
501 }
502
503 // Outline:
504 for( n = 0; n < MAXLEVEL; ++n, ++ppFormats )
505 {
506 delete *ppFormats;
507 *ppFormats = nullptr;
508 }
509
511 for( n = 0; n < MAXLEVEL; ++n, ++ppFormats )
512 {
513 delete *ppFormats;
514 *ppFormats = nullptr;
515 }
516 for( n = 0; n < MAXLEVEL; ++n, ++ppFormats )
517 {
518 delete *ppFormats;
519 *ppFormats = nullptr;
520 }
521 }
522
523 maTextNodeList.clear();
524 maParagraphStyleList.clear();
525}
526
528{
529 for(auto& rpNumFormat : maFormats)
530 {
531 if( rpNumFormat )
532 {
533 SwCharFormat* pFormat = rpNumFormat->GetCharFormat();
534 if( pFormat && pFormat->GetDoc() != &rDoc )
535 {
536 // copy
537 SwNumFormat* pNew = new SwNumFormat( *rpNumFormat );
538 pNew->SetCharFormat( rDoc.CopyCharFormat( *pFormat ) );
539 rpNumFormat.reset(pNew);
540 }
541 }
542 }
543}
544
546{
547 if( this != &rNumRule )
548 {
549 for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
550 Set( n, rNumRule.maFormats[ n ].get() );
551
552 meRuleType = rNumRule.meRuleType;
553 msName = rNumRule.msName;
555 mbInvalidRuleFlag = true;
556 mbContinusNum = rNumRule.mbContinusNum;
557 mbAbsSpaces = rNumRule.mbAbsSpaces;
558 mbHidden = rNumRule.mbHidden;
559 mnPoolFormatId = rNumRule.GetPoolFormatId();
560 mnPoolHelpId = rNumRule.GetPoolHelpId();
562 }
563 return *this;
564}
565
566void SwNumRule::Reset( const OUString& rName )
567{
568 for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
569 Set( n, nullptr);
570
572 msName = rName;
573 mbAutoRuleFlag = true;
574 mbInvalidRuleFlag = true;
575 mbContinusNum = false;
576 mbAbsSpaces = false;
577 mbHidden = false;
578 mnPoolFormatId = USHRT_MAX;
579 mnPoolHelpId = USHRT_MAX;
580 mnPoolHlpFileId = UCHAR_MAX;
581}
582
583bool SwNumRule::operator==( const SwNumRule& rRule ) const
584{
585 bool bRet = meRuleType == rRule.meRuleType &&
586 msName == rRule.msName &&
588 mbContinusNum == rRule.mbContinusNum &&
589 mbAbsSpaces == rRule.mbAbsSpaces &&
590 mnPoolFormatId == rRule.GetPoolFormatId() &&
591 mnPoolHelpId == rRule.GetPoolHelpId() &&
593 if( bRet )
594 {
595 for( sal_uInt8 n = 0; n < MAXLEVEL; ++n )
596 if( rRule.Get( n ) != Get( n ) )
597 {
598 bRet = false;
599 break;
600 }
601 }
602 return bRet;
603}
604
605void SwNumRule::Set( sal_uInt16 i, const SwNumFormat& rNumFormat )
606{
607 OSL_ENSURE( i < MAXLEVEL, "Serious defect" );
608 if( i < MAXLEVEL )
609 {
610 if( !maFormats[ i ] || (rNumFormat != Get( i )) )
611 {
612 maFormats[ i ].reset(new SwNumFormat( rNumFormat ));
613 mbInvalidRuleFlag = true;
614 }
615 }
616}
617
618void SwNumRule::Set( sal_uInt16 i, const SwNumFormat* pNumFormat )
619{
620 OSL_ENSURE( i < MAXLEVEL, "Serious defect" );
621 if( i >= MAXLEVEL )
622 return;
623 if( !maFormats[ i ] )
624 {
625 if( pNumFormat )
626 {
627 maFormats[ i ].reset(new SwNumFormat( *pNumFormat ));
628 mbInvalidRuleFlag = true;
629 }
630 }
631 else if( !pNumFormat )
632 {
633 maFormats[ i ].reset();
634 mbInvalidRuleFlag = true;
635 }
636 else if( *maFormats[i] != *pNumFormat )
637 {
638 *maFormats[ i ] = *pNumFormat;
639 mbInvalidRuleFlag = true;
640 }
641}
642
643OUString SwNumRule::MakeNumString( const SwNodeNum& rNum, bool bInclStrings ) const
644{
645 if (rNum.IsCounted())
646 return MakeNumString(rNum.GetNumberVector(), bInclStrings);
647
648 return OUString();
649}
650
652 const bool bInclStrings,
653 const unsigned int _nRestrictToThisLevel,
654 SwNumRule::Extremities* pExtremities,
655 LanguageType nLang ) const
656{
657 OUStringBuffer aStr;
658
659 SwNumberTree::tNumberVector::size_type nLevel = rNumVector.size() - 1;
660
661 if ( pExtremities )
662 pExtremities->nPrefixChars = pExtremities->nSuffixChars = 0;
663
664 if ( nLevel > _nRestrictToThisLevel )
665 {
666 nLevel = _nRestrictToThisLevel;
667 }
668
669 assert(nLevel < MAXLEVEL);
670
671 const SwNumFormat& rMyNFormat = Get( o3tl::narrowing<sal_uInt16>(nLevel) );
672
673 if (rMyNFormat.GetNumberingType() == SVX_NUM_NUMBER_NONE)
674 {
675 if (!rMyNFormat.HasListFormat())
676 return bInclStrings ? rMyNFormat.GetPrefix() + rMyNFormat.GetSuffix() : OUString();
677
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"");
685 return sLevelFormat;
686 }
687
688 css::lang::Locale aLocale( LanguageTag::convertToLocale(nLang));
689
690 if (rMyNFormat.HasListFormat())
691 {
692 OUString sLevelFormat = rMyNFormat.GetListFormat(bInclStrings);
693
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)
697 {
698 OUString sReplacement;
699 const SwNumFormat& rNFormat = Get(i);
700 if (rNFormat.GetNumberingType() == SVX_NUM_NUMBER_NONE)
701 {
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)
709 {
710 sLevelFormat = sLevelFormat.replaceAt(nPositionToken, nPositionNextToken - nPositionToken, u"");
711 }
712 }
713 else if (rNumVector[i])
714 sReplacement = Get(i).GetNumStr(rNumVector[i], aLocale);
715 else
716 sReplacement = "0"; // all 0 level are a 0
717
718 OUString sFind("%" + OUString::number(i + 1) + "%");
719 sal_Int32 nPosition = sLevelFormat.indexOf(sFind);
720 if (nPosition >= 0)
721 sLevelFormat = sLevelFormat.replaceAt(nPosition, sFind.getLength(), sReplacement);
722 }
723
724 aStr = sLevelFormat;
725 }
726 else
727 {
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;
731
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?
736 {
737 sal_uInt8 n = rMyNFormat.GetIncludeUpperLevels();
738 if (1 < n)
739 {
740 if (i + 1 >= n)
741 i -= n - 1;
742 else
743 i = 0;
744 }
745 }
746
747 for (; i <= nLevel; ++i)
748 {
749 const SwNumFormat& rNFormat = Get(i);
750 if (SVX_NUM_NUMBER_NONE == rNFormat.GetNumberingType())
751 {
752 // Should 1.1.1 --> 2. NoNum --> 1..1 or 1.1 ??
753 // if( i != rNum.nMyLevel )
754 // aStr += ".";
755 continue;
756 }
757
758 if (rNumVector[i])
759 aStr.append(rNFormat.GetNumStr(rNumVector[i], aLocale));
760 else
761 aStr.append("0"); // all 0 level are a 0
762 if (i != nLevel && !aStr.isEmpty())
763 aStr.append(".");
764 }
765
766 // The type doesn't have any number, so don't append
767 // the post-/prefix string
768 if (bInclStrings &&
769 SVX_NUM_CHAR_SPECIAL != rMyNFormat.GetNumberingType() &&
770 SVX_NUM_BITMAP != rMyNFormat.GetNumberingType())
771 {
772 const OUString& sPrefix = rMyNFormat.GetPrefix();
773 const OUString& sSuffix = rMyNFormat.GetSuffix();
774
775 aStr.insert(0, sPrefix);
776 aStr.append(sSuffix);
777 if (pExtremities)
778 {
779 pExtremities->nPrefixChars = sPrefix.getLength();
780 pExtremities->nSuffixChars = sSuffix.getLength();
781 }
782 }
783 }
784
785 return aStr.makeStringAndClear();
786}
787
788OUString SwNumRule::MakeRefNumString( const SwNodeNum& rNodeNum,
789 const bool bInclSuperiorNumLabels,
790 const int nRestrictInclToThisLevel ) const
791{
792 OUString aRefNumStr;
793
794 if ( rNodeNum.GetLevelInListTree() >= 0 )
795 {
796 bool bOldHadPrefix = true;
797
798 const SwNodeNum* pWorkingNodeNum( &rNodeNum );
799 do
800 {
801 bool bMakeNumStringForPhantom( false );
802 if ( pWorkingNodeNum->IsPhantom() )
803 {
804 int nListLevel = pWorkingNodeNum->GetLevelInListTree();
805
806 if (nListLevel < 0)
807 nListLevel = 0;
808
809 if (nListLevel >= MAXLEVEL)
810 nListLevel = MAXLEVEL - 1;
811
812 SwNumFormat aFormat( Get( o3tl::narrowing<sal_uInt16>(nListLevel) ) );
813 bMakeNumStringForPhantom = aFormat.IsEnumeration() &&
815
816 }
817 if ( bMakeNumStringForPhantom ||
818 ( !pWorkingNodeNum->IsPhantom() &&
819 pWorkingNodeNum->GetTextNode() &&
820 pWorkingNodeNum->GetTextNode()->HasNumber() ) )
821 {
822 Extremities aExtremities;
823 OUString aPrevStr = MakeNumString( pWorkingNodeNum->GetNumberVector(),
824 true, MAXLEVEL,
825 &aExtremities);
826 sal_Int32 nStrip = 0;
827 while ( nStrip < aExtremities.nPrefixChars )
828 {
829 const sal_Unicode c = aPrevStr[nStrip];
830 if ( c!='\t' && c!=' ')
831 break;
832 ++nStrip;
833 }
834
835 if (nStrip)
836 {
837 aPrevStr = aPrevStr.copy( nStrip );
838 aExtremities.nPrefixChars -= nStrip;
839 }
840
841 if (bOldHadPrefix &&
842 aExtremities.nSuffixChars &&
843 !aExtremities.nPrefixChars
844 )
845 {
846 aPrevStr = aPrevStr.copy(0,
847 aPrevStr.getLength() - aExtremities.nSuffixChars);
848 }
849
850 bOldHadPrefix = ( aExtremities.nPrefixChars > 0);
851
852 aRefNumStr = aPrevStr + aRefNumStr;
853 }
854
855 if ( bInclSuperiorNumLabels && pWorkingNodeNum->GetLevelInListTree() > 0 )
856 {
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 )
861 {
862 pWorkingNodeNum = dynamic_cast<SwNodeNum*>(pWorkingNodeNum->GetParent());
863 --n;
864 }
865 }
866 else
867 {
868 break;
869 }
870 } while ( pWorkingNodeNum &&
871 pWorkingNodeNum->GetLevelInListTree() >= 0 &&
872 pWorkingNodeNum->GetLevelInListTree() >= nRestrictInclToThisLevel );
873 }
874
875 if (aRefNumStr.endsWith("."))
876 {
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);
879 }
880
881 return aRefNumStr;
882}
883
885{
886 OUString aParagraphStyleListString;
887 for (const auto& rParagraphStyle : maParagraphStyleList)
888 {
889 if (!aParagraphStyleListString.isEmpty())
890 aParagraphStyleListString += ", ";
891 aParagraphStyleListString += rParagraphStyle->GetName();
892 }
893 return aParagraphStyleListString;
894}
895
902{
903 for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
904 {
905 Set( n, rNumRule.maFormats[ n ].get() );
906 if( maFormats[ n ] && maFormats[ n ]->GetCharFormat() &&
907 !rDoc.GetCharFormats()->ContainsFormat(maFormats[n]->GetCharFormat()))
908 {
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]->
912 GetCharFormat() ) );
913 }
914 }
915 meRuleType = rNumRule.meRuleType;
916 msName = rNumRule.msName;
918 mnPoolFormatId = rNumRule.GetPoolFormatId();
919 mnPoolHelpId = rNumRule.GetPoolHelpId();
921 mbInvalidRuleFlag = true;
922 return *this;
923}
924
925void SwNumRule::SetSvxRule(const SvxNumRule& rNumRule, SwDoc* pDoc)
926{
927 for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
928 {
929 const SvxNumberFormat* pSvxFormat = rNumRule.Get(n);
930 maFormats[n].reset( pSvxFormat ? new SwNumFormat(*pSvxFormat, pDoc) : nullptr );
931 }
932
933 mbInvalidRuleFlag = true;
935}
936
938{
939 SvxNumRule aRule(SvxNumRuleFlags::CONTINUOUS | SvxNumRuleFlags::CHAR_STYLE |
940 SvxNumRuleFlags::ENABLE_LINKED_BMP | SvxNumRuleFlags::ENABLE_EMBEDDED_BMP,
942 meRuleType == NUM_RULE ? SvxNumRuleType::NUMBERING : SvxNumRuleType::OUTLINE_NUMBERING );
943 for( sal_uInt16 n = 0; n < MAXLEVEL; ++n )
944 {
945 const SwNumFormat & rNumFormat = Get(n);
946 if(rNumFormat.GetCharFormat())
947 {
948 SwNumFormat aNewFormat = rNumFormat;
949 aNewFormat.SetCharFormatName(rNumFormat.GetCharFormat()->GetName());
950 aRule.SetLevel(n, aNewFormat, maFormats[n] != nullptr);
951 }
952 else
953 aRule.SetLevel(n, rNumFormat, maFormats[n] != nullptr);
954 }
955 return aRule;
956}
957
959{
960 if (mbInvalidRuleFlag == bFlag)
961 return;
962
963 if (bFlag)
964 {
966 for ( const SwTextNode* pTextNode : maTextNodeList )
967 {
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.");
971 if ( pList )
972 {
973 aLists.insert( pList );
974 }
975 }
976 for ( auto aList : aLists )
977 aList->InvalidateListTree();
978 }
979
980 mbInvalidRuleFlag = bFlag;
981}
982
984void SwNumRule::ChangeIndent( const sal_Int32 nDiff )
985{
986 for ( sal_uInt16 i = 0; i < MAXLEVEL; ++i )
987 {
988 SwNumFormat aTmpNumFormat( Get(i) );
989
990 const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
991 aTmpNumFormat.GetPositionAndSpaceMode() );
992 if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
993 {
994 auto nNewIndent = nDiff +
995 aTmpNumFormat.GetAbsLSpace();
996 if ( nNewIndent < 0 )
997 {
998 nNewIndent = 0;
999 }
1000 aTmpNumFormat.SetAbsLSpace( nNewIndent );
1001 }
1002 else if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
1003 {
1004 // adjust also the list tab position, if a list tab stop is applied
1005 if ( aTmpNumFormat.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB )
1006 {
1007 const tools::Long nNewListTab = aTmpNumFormat.GetListtabPos() + nDiff;
1008 aTmpNumFormat.SetListtabPos( nNewListTab );
1009 }
1010
1011 const tools::Long nNewIndent = nDiff +
1012 aTmpNumFormat.GetIndentAt();
1013 aTmpNumFormat.SetIndentAt( nNewIndent );
1014 }
1015
1016 Set( i, aTmpNumFormat );
1017 }
1018
1019 SetInvalidRule( true );
1020}
1021
1023void SwNumRule::SetIndent( const short nNewIndent,
1024 const sal_uInt16 nListLevel )
1025{
1026 SwNumFormat aTmpNumFormat( Get(nListLevel) );
1027
1028 const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
1029 aTmpNumFormat.GetPositionAndSpaceMode() );
1030 if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
1031 {
1032 aTmpNumFormat.SetAbsLSpace( nNewIndent );
1033 }
1034 else if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
1035 {
1036 // adjust also the list tab position, if a list tab stop is applied
1037 if ( aTmpNumFormat.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB )
1038 {
1039 const tools::Long nNewListTab = aTmpNumFormat.GetListtabPos() +
1040 ( nNewIndent - aTmpNumFormat.GetIndentAt() );
1041 aTmpNumFormat.SetListtabPos( nNewListTab );
1042 }
1043
1044 aTmpNumFormat.SetIndentAt( nNewIndent );
1045 }
1046
1047 SetInvalidRule( true );
1048}
1049
1053{
1054 SwNumFormat aTmpNumFormat( Get(0) );
1055
1056 sal_Int32 nDiff( 0 );
1057 const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
1058 aTmpNumFormat.GetPositionAndSpaceMode() );
1059 if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
1060 {
1061 nDiff = nNewIndent
1062 - aTmpNumFormat.GetFirstLineOffset()
1063 - aTmpNumFormat.GetAbsLSpace();
1064 }
1065 else if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
1066 {
1067 nDiff = nNewIndent - aTmpNumFormat.GetIndentAt();
1068 }
1069 if ( nDiff != 0 )
1070 {
1071 ChangeIndent( nDiff );
1072 }
1073}
1074
1076{
1078 for ( const SwTextNode* pTextNode : maTextNodeList )
1079 {
1080 aLists.insert( pTextNode->GetDoc().getIDocumentListsAccess().getListByName( pTextNode->GetListId() ) );
1081 }
1082 for ( auto aList : aLists )
1083 aList->ValidateListTree(rDoc);
1084
1085 SetInvalidRule(false);
1086}
1087
1088void SwNumRule::SetCountPhantoms(bool bCountPhantoms)
1089{
1090 mbCountPhantoms = bCountPhantoms;
1091}
1092
1093SwNumRule::tParagraphStyleList::size_type SwNumRule::GetParagraphStyleListSize() const
1094{
1095 return maParagraphStyleList.size();
1096}
1097
1099{
1100 tParagraphStyleList::iterator aIter =
1101 std::find( maParagraphStyleList.begin(), maParagraphStyleList.end(), &rTextFormatColl );
1102
1103 if ( aIter == maParagraphStyleList.end() )
1104 {
1105 maParagraphStyleList.push_back( &rTextFormatColl );
1106 }
1107}
1108
1110{
1111 tParagraphStyleList::iterator aIter =
1112 std::find( maParagraphStyleList.begin(), maParagraphStyleList.end(), &rTextFormatColl );
1113
1114 if ( aIter != maParagraphStyleList.end() )
1115 {
1116 maParagraphStyleList.erase( aIter );
1117 }
1118}
1119
1121{
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()));
1126
1127 for (const auto& pFormat : maFormats)
1128 {
1129 if (!pFormat)
1130 {
1131 continue;
1132 }
1133
1134 pFormat->dumpAsXml(pWriter);
1135 }
1136
1137 (void)xmlTextWriterEndElement(pWriter);
1138}
1139
1141{
1142 if (mpGrabBagItem)
1143 mpGrabBagItem->QueryValue(rVal);
1144 else
1145 rVal <<= uno::Sequence<beans::PropertyValue>();
1146}
1147
1149{
1150 if (!mpGrabBagItem)
1151 mpGrabBagItem = std::make_shared<SfxGrabBagItem>();
1152
1153 mpGrabBagItem->PutValue(rVal, 0);
1154}
1155
1157{
1158 // In case all text nodes are after each other, then we won't have a later list that wants to
1159 // continue us.
1161 for (size_t i = 0; i < maTextNodeList.size(); ++i)
1162 {
1163 SwTextNode* pNode = maTextNodeList[i];
1164 if (i > 0)
1165 {
1166 if (pNode->GetIndex() != nIndex + 1)
1167 {
1168 // May have a continue list.
1169 return true;
1170 }
1171 }
1172 nIndex = pNode->GetIndex();
1173 }
1174
1175 // Definitely won't have a continue list.
1176 return false;
1177}
1178
1179namespace numfunc
1180{
1181 namespace {
1182
1184 class SwDefBulletConfig : private utl::ConfigItem
1185 {
1186 public:
1187 static SwDefBulletConfig& getInstance();
1188
1189 const OUString& GetFontname() const
1190 {
1191 return msFontname;
1192 }
1193
1194 bool IsFontnameUserDefined() const
1195 {
1196 return mbUserDefinedFontname;
1197 }
1198
1199 const vcl::Font& GetFont() const
1200 {
1201 return *mpFont;
1202 }
1203
1204 sal_Unicode GetChar( sal_uInt8 p_nListLevel ) const
1205 {
1206 if (p_nListLevel >= MAXLEVEL)
1207 {
1208 p_nListLevel = MAXLEVEL - 1;
1209 }
1210
1211 return mnLevelChars[p_nListLevel];
1212 }
1213
1214 SwDefBulletConfig();
1215
1216 private:
1218 void SetToDefault();
1219
1221 static uno::Sequence<OUString> GetPropNames();
1222
1225 void LoadConfig();
1226
1228 void InitFont();
1229
1231 virtual void Notify( const uno::Sequence<OUString>& aPropertyNames ) override;
1232 virtual void ImplCommit() override;
1233
1234 // default bullet list configuration data
1235 OUString msFontname;
1240
1241 // default bullet list font instance
1242 std::optional<vcl::Font> mpFont;
1243 };
1244
1245 }
1246
1247 SwDefBulletConfig& SwDefBulletConfig::getInstance()
1248 {
1249 static SwDefBulletConfig theSwDefBulletConfig;
1250 return theSwDefBulletConfig;
1251 }
1252
1253 SwDefBulletConfig::SwDefBulletConfig()
1254 : ConfigItem( "Office.Writer/Numbering/DefaultBulletList" ),
1255 // default bullet font is now OpenSymbol
1256 msFontname( OUString("OpenSymbol") ),
1257 mbUserDefinedFontname( false ),
1260 {
1261 SetToDefault();
1262 LoadConfig();
1263 InitFont();
1264
1265 // enable notification for changes on default bullet configuration change
1266 EnableNotification( GetPropNames() );
1267 }
1268
1269 void SwDefBulletConfig::SetToDefault()
1270 {
1271 msFontname = "OpenSymbol";
1272 mbUserDefinedFontname = false;
1275
1276 mnLevelChars[0] = 0x2022;
1277 mnLevelChars[1] = 0x25e6;
1278 mnLevelChars[2] = 0x25aa;
1279 mnLevelChars[3] = 0x2022;
1280 mnLevelChars[4] = 0x25e6;
1281 mnLevelChars[5] = 0x25aa;
1282 mnLevelChars[6] = 0x2022;
1283 mnLevelChars[7] = 0x25e6;
1284 mnLevelChars[8] = 0x25aa;
1285 mnLevelChars[9] = 0x2022;
1286 }
1287
1288 uno::Sequence<OUString> SwDefBulletConfig::GetPropNames()
1289 {
1290 uno::Sequence<OUString> aPropNames(13);
1291 OUString* pNames = aPropNames.getArray();
1292 pNames[0] = "BulletFont/FontFamilyname";
1293 pNames[1] = "BulletFont/FontWeight";
1294 pNames[2] = "BulletFont/FontItalic";
1295 pNames[3] = "BulletCharLvl1";
1296 pNames[4] = "BulletCharLvl2";
1297 pNames[5] = "BulletCharLvl3";
1298 pNames[6] = "BulletCharLvl4";
1299 pNames[7] = "BulletCharLvl5";
1300 pNames[8] = "BulletCharLvl6";
1301 pNames[9] = "BulletCharLvl7";
1302 pNames[10] = "BulletCharLvl8";
1303 pNames[11] = "BulletCharLvl9";
1304 pNames[12] = "BulletCharLvl10";
1305
1306 return aPropNames;
1307 }
1308
1309 void SwDefBulletConfig::LoadConfig()
1310 {
1311 uno::Sequence<OUString> aPropNames = GetPropNames();
1312 uno::Sequence<uno::Any> aValues = GetProperties( aPropNames );
1313 const uno::Any* pValues = aValues.getConstArray();
1314 OSL_ENSURE( aValues.getLength() == aPropNames.getLength(),
1315 "<SwDefBulletConfig::SwDefBulletConfig()> - GetProperties failed");
1316 if ( aValues.getLength() != aPropNames.getLength() )
1317 return;
1318
1319 for ( int nProp = 0; nProp < aPropNames.getLength(); ++nProp )
1320 {
1321 if ( pValues[nProp].hasValue() )
1322 {
1323 switch ( nProp )
1324 {
1325 case 0:
1326 {
1327 OUString aStr;
1328 pValues[nProp] >>= aStr;
1329 msFontname = aStr;
1330 mbUserDefinedFontname = true;
1331 }
1332 break;
1333 case 1:
1334 case 2:
1335 {
1336 sal_Int16 nTmp = 0;
1337 pValues[nProp] >>= nTmp;
1338 if ( nProp == 1 )
1339 meFontWeight = static_cast<FontWeight>(nTmp);
1340 else if ( nProp == 2 )
1341 meFontItalic = static_cast<FontItalic>(nTmp);
1342 }
1343 break;
1344 case 3:
1345 case 4:
1346 case 5:
1347 case 6:
1348 case 7:
1349 case 8:
1350 case 9:
1351 case 10:
1352 case 11:
1353 case 12:
1354 {
1355 sal_Unicode cChar = sal_Unicode();
1356 pValues[nProp] >>= cChar;
1357 mnLevelChars[nProp-3] = cChar;
1358 }
1359 break;
1360 }
1361 }
1362 }
1363
1364 }
1365
1366 void SwDefBulletConfig::InitFont()
1367 {
1368 mpFont.emplace( msFontname, OUString(), Size( 0, 14 ) );
1369 mpFont->SetWeight( meFontWeight );
1370 mpFont->SetItalic( meFontItalic );
1371 mpFont->SetCharSet( RTL_TEXTENCODING_SYMBOL );
1372 }
1373
1374 void SwDefBulletConfig::Notify( const uno::Sequence<OUString>& )
1375 {
1376 SetToDefault();
1377 LoadConfig();
1378 InitFont();
1379 }
1380
1381 void SwDefBulletConfig::ImplCommit()
1382 {
1383 }
1384
1385 OUString const & GetDefBulletFontname()
1386 {
1387 return SwDefBulletConfig::getInstance().GetFontname();
1388 }
1389
1391 {
1392 return SwDefBulletConfig::getInstance().IsFontnameUserDefined();
1393 }
1394
1396 {
1397 return SwDefBulletConfig::getInstance().GetFont();
1398 }
1399
1401 {
1402 return SwDefBulletConfig::getInstance().GetChar( nLevel );
1403 }
1404
1405 namespace {
1406
1412 class SwNumberingUIBehaviorConfig : private utl::ConfigItem
1413 {
1414 public:
1415 static SwNumberingUIBehaviorConfig& getInstance();
1416
1418 {
1420 }
1421
1422 SwNumberingUIBehaviorConfig();
1423
1424 private:
1425
1427 void SetToDefault();
1428
1430 static css::uno::Sequence<OUString> GetPropNames();
1431
1433 void LoadConfig();
1434
1436 virtual void Notify( const css::uno::Sequence<OUString>& aPropertyNames ) override;
1437 virtual void ImplCommit() override;
1438
1439 // configuration data
1441 };
1442
1443 }
1444
1445 SwNumberingUIBehaviorConfig& SwNumberingUIBehaviorConfig::getInstance()
1446 {
1447 static SwNumberingUIBehaviorConfig theSwNumberingUIBehaviorConfig;
1448 return theSwNumberingUIBehaviorConfig;
1449 }
1450
1451 SwNumberingUIBehaviorConfig::SwNumberingUIBehaviorConfig()
1452 : ConfigItem( "Office.Writer/Numbering/UserInterfaceBehavior" ),
1454 {
1455 SetToDefault();
1456 LoadConfig();
1457
1458 // enable notification for changes on configuration change
1459 EnableNotification( GetPropNames() );
1460 }
1461
1462 void SwNumberingUIBehaviorConfig::SetToDefault()
1463 {
1465 }
1466
1467 css::uno::Sequence<OUString> SwNumberingUIBehaviorConfig::GetPropNames()
1468 {
1469 css::uno::Sequence<OUString> aPropNames { "ChangeIndentOnTabAtFirstPosOfFirstListItem" };
1470
1471 return aPropNames;
1472 }
1473
1474 void SwNumberingUIBehaviorConfig::ImplCommit() {}
1475
1476 void SwNumberingUIBehaviorConfig::LoadConfig()
1477 {
1478 css::uno::Sequence<OUString> aPropNames = GetPropNames();
1479 css::uno::Sequence<css::uno::Any> aValues = GetProperties( aPropNames );
1480 const css::uno::Any* pValues = aValues.getConstArray();
1481 OSL_ENSURE( aValues.getLength() == aPropNames.getLength(),
1482 "<SwNumberingUIBehaviorConfig::LoadConfig()> - GetProperties failed");
1483 if ( aValues.getLength() != aPropNames.getLength() )
1484 return;
1485
1486 for ( int nProp = 0; nProp < aPropNames.getLength(); ++nProp )
1487 {
1488 if ( pValues[nProp].hasValue() )
1489 {
1490 switch ( nProp )
1491 {
1492 case 0:
1493 {
1495 }
1496 break;
1497 default:
1498 {
1499 OSL_FAIL( "<SwNumberingUIBehaviorConfig::LoadConfig()> - unknown configuration property");
1500 }
1501 }
1502 }
1503 }
1504 }
1505
1506 void SwNumberingUIBehaviorConfig::Notify( const css::uno::Sequence<OUString>& )
1507 {
1508 SetToDefault();
1509 LoadConfig();
1510 }
1511
1513 {
1514 return SwNumberingUIBehaviorConfig::getInstance().ChangeIndentOnTabAtFirstPosOfFirstListItem();
1515 }
1516
1518 {
1519 SwPaM* pCursor = rShell.GetCursor();
1520 if (!pCursor)
1521 {
1522 return true;
1523 }
1524
1525 SwTextNode* pTextNode = pCursor->GetPointNode().GetTextNode();
1526 if (!pTextNode)
1527 {
1528 return true;
1529 }
1530
1531 const SwNumRule* pNumRule = pTextNode->GetNumRule();
1532 if (!pNumRule)
1533 {
1534 return true;
1535 }
1536
1537 int nOldLevel = pTextNode->GetActualListLevel();
1538 int nNewLevel = nOldLevel + 1;
1539 if (nNewLevel >= MAXLEVEL)
1540 {
1541 return true;
1542 }
1543
1544 const SwNumFormat& rOldFormat = pNumRule->Get(nOldLevel);
1545 if (rOldFormat.GetNumberingType() != SVX_NUM_NUMBER_NONE)
1546 {
1547 return true;
1548 }
1549
1550 const SwNumFormat& rNewFormat = pNumRule->Get(nNewLevel);
1551 if (rNewFormat.GetNumberingType() != SVX_NUM_NUMBER_NONE)
1552 {
1553 return true;
1554 }
1555
1556 // This is the case when the numbering levels don't differ, so changing between them is not
1557 // a better alternative to inserting a tab character.
1558 return rOldFormat.GetIndentAt() != rNewFormat.GetIndentAt();
1559 }
1560
1562 {
1565
1567 switch (GetODFSaneDefaultVersion())
1568 {
1571 {
1573 }
1574 break;
1575 default: // >= ODFSVER_012
1576 {
1577 ePosAndSpaceMode = SvxNumberFormat::LABEL_ALIGNMENT;
1578 }
1579 }
1580
1581 return ePosAndSpaceMode;
1582 }
1583}
1584
1586{
1587 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwNumRuleTable"));
1588 for (SwNumRule* pNumRule : *this)
1589 pNumRule->dumpAsXml(pWriter);
1590 (void)xmlTextWriterEndElement(pWriter);
1591}
1592
1593/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const PropertyValue * pValues
struct _xmlTextWriter * xmlTextWriterPtr
Provides access to the lists of a document.
virtual void trackChangeOfListStyleName(const OUString &rListStyleName, const OUString &rNewListStyleName)=0
virtual void ResetModified()=0
virtual bool IsModified() const =0
Changes of document?
virtual SwCharFormat * GetCharFormatFromPool(sal_uInt16 nId)=0
static css::lang::Locale convertToLocale(LanguageType nLangID, bool bResolveSystem=true)
SfxHintId GetId() const
const SvxNumberFormat * Get(sal_uInt16 nLevel) const
bool IsContinuousNumbering() const
void SetLevel(sal_uInt16 nLevel, const SvxNumberFormat &rFmt, bool bIsValid=true)
void SetStart(sal_uInt16 nSet)
tools::Long GetIndentAt() const
void SetAbsLSpace(sal_Int32 nSet)
virtual void SetGraphicBrush(const SvxBrushItem *pBrushItem, const Size *pSize=nullptr, const sal_Int16 *pOrient=nullptr)
void SetPositionAndSpaceMode(SvxNumPositionAndSpaceMode ePositionAndSpaceMode)
void SetFirstLineIndent(const tools::Long nFirstLineIndent)
sal_uInt8 GetIncludeUpperLevels() const
const SvxBrushItem * GetBrush() const
bool operator==(const SvxNumberFormat &) const
OUString GetListFormat(bool bIncludePrefixSuffix=true) const
sal_Int32 GetFirstLineOffset() const
void SetCharTextDistance(short nSet)
const Size & GetGraphicSize() const
sal_Int32 GetAbsLSpace() const
LabelFollowedBy GetLabelFollowedBy() const
void SetListFormat(const OUString &rPrefix, const OUString &rSuffix, int nLevel)
tools::Long GetListtabPos() const
void SetIncludeUpperLevels(sal_uInt8 nSet)
void SetIndentAt(const tools::Long nIndentAt)
bool HasListFormat() const
void SetFirstLineOffset(sal_Int32 nSet)
SvxNumPositionAndSpaceMode GetPositionAndSpaceMode() const
SvxNumberFormat & operator=(const SvxNumberFormat &)
void SetBulletChar(sal_UCS4 cSet)
const OUString & GetPrefix() const
void SetLabelFollowedBy(const LabelFollowedBy eLabelFollowedBy)
void SetListtabPos(const tools::Long nListtabPos)
const OUString & GetSuffix() const
sal_Int16 GetVertOrient() const
void SetNumberingType(SvxNumType nSet)
SvxNumType GetNumberingType() const
OUString GetNumStr(sal_Int32 nNo) const
Represents the style of a text portion.
Definition: charfmt.hxx:27
bool ContainsFormat(const SwCharFormat *pFormat) const
fast check if given format is contained here @precond pFormat must not have been deleted
Definition: chrfmt.cxx:126
const SwModify * GetRegisteredIn() const
Definition: calbck.hxx:166
void EndListeningAll()
Definition: calbck.cxx:136
void StartListeningToSameModifyAs(const SwClient &)
Definition: calbck.cxx:128
std::optional< sw::ModifyChangedHint > CheckRegistration(const SfxPoolItem *pOldValue)
Definition: calbck.cxx:77
SwCursor * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:194
Definition: doc.hxx:194
IDocumentState const & getIDocumentState() const
Definition: doc.cxx:400
bool IsInDtor() const
Definition: doc.hxx:412
const SwNumRuleTable & GetNumRuleTable() const
Definition: doc.hxx:1074
SwCharFormat * FindCharFormatByName(const OUString &rName) const
Definition: doc.hxx:779
const SwCharFormats * GetCharFormats() const
Definition: doc.hxx:748
SwCharFormat * CopyCharFormat(const SwCharFormat &)
copy the char format
Definition: docfmt.cxx:1167
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:432
SwCharFormat * MakeCharFormat(const OUString &rFormatName, SwCharFormat *pDerivedFrom, bool bBroadcast=false)
Definition: docfmt.cxx:854
Defines the vertical position of a fly frame.
Definition: fmtornt.hxx:37
void SetVertOrient(sal_Int16 eNew)
Definition: fmtornt.hxx:59
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:139
const OUString & GetName() const
Definition: format.hxx:131
Definition: list.hxx:40
void Add(SwClient *pDepend)
Definition: calbck.cxx:172
SwTextNode * GetTextNode() const
Definition: SwNodeNum.hxx:40
virtual bool IsCounted() const override
Return if this node is counted.
Definition: SwNodeNum.cxx:170
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:897
SwNodeOffset GetIndex() const
Definition: node.hxx:312
bool IsEnumeration() const
Definition: number.cxx:237
virtual OUString GetCharFormatName() const override
Definition: number.cxx:311
SwCharFormat * GetCharFormat() const
Definition: numrule.hxx:74
virtual void SwClientNotify(const SwModify &, const SfxHint &) override
Definition: number.cxx:289
sal_Unicode m_cGrfBulletCP
Definition: numrule.hxx:54
void SetCharFormat(SwCharFormat *)
Definition: number.cxx:281
SwNumFormat & operator=(const SwNumFormat &)
Definition: number.cxx:265
const SwFormatVertOrient * GetGraphicOrientation() const
Definition: number.cxx:352
bool operator==(const SwNumFormat &) const
Definition: number.cxx:274
SAL_DLLPRIVATE void UpdateNumNodes(SwDoc &rDoc)
Definition: number.cxx:327
SwFormatVertOrient m_aVertOrient
Definition: numrule.hxx:52
virtual void SetGraphicBrush(const SvxBrushItem *pBrushItem, const Size *pSize=nullptr, const sal_Int16 *pOrient=nullptr) override
Definition: number.cxx:319
virtual ~SwNumFormat() override
Definition: number.cxx:232
void SetCharFormatName(const OUString &rSet)
bool IsItemize() const
Definition: number.cxx:245
void dumpAsXml(xmlTextWriterPtr pWriter) const
Definition: number.cxx:1585
sal_uInt16 mnPoolFormatId
Id-for NumRules created "automatically".
Definition: numrule.hxx:128
OUString MakeRefNumString(const SwNodeNum &rNodeNum, const bool bInclSuperiorNumLabels, const int nRestrictInclToThisLevel) const
Definition: number.cxx:788
bool operator==(const SwNumRule &) const
Definition: number.cxx:583
void dumpAsXml(xmlTextWriterPtr w) const
Definition: number.cxx:1120
SwNumRule(OUString aNm, const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode, SwNumRuleType=NUM_RULE)
add parameter <eDefaultNumberFormatPositionAndSpaceMode>
Definition: number.cxx:364
void AddParagraphStyle(SwTextFormatColl &rTextFormatColl)
Definition: number.cxx:1098
static SwNumFormat * saBaseFormats[RULE_END][MAXLEVEL]
Definition: numrule.hxx:109
sal_uInt16 mnPoolHelpId
HelpId for this Pool-style.
Definition: numrule.hxx:129
void RemoveParagraphStyle(SwTextFormatColl &rTextFormatColl)
Definition: number.cxx:1109
SvxNumberFormat::SvxNumPositionAndSpaceMode meDefaultNumberFormatPositionAndSpaceMode
it needs to export as part of tracked numbering change
Definition: numrule.hxx:139
sal_uInt8 GetPoolHlpFileId() const
Definition: numrule.hxx:256
std::unique_ptr< SwNumFormat > maFormats[MAXLEVEL]
Definition: numrule.hxx:115
void SetNumRuleMap(std::unordered_map< OUString, SwNumRule * > *pNumRuleMap)
Register this rule in a "name->numrule" map.
Definition: number.cxx:163
SwNumRule::tParagraphStyleList::size_type GetParagraphStyleListSize() const
Definition: number.cxx:1093
void SetSvxRule(const SvxNumRule &, SwDoc *pDoc)
Definition: number.cxx:925
SwNumRule::tTextNodeList::size_type GetTextNodeListSize() const
Definition: number.cxx:136
bool mbAutoRuleFlag
Definition: numrule.hxx:131
~SwNumRule()
Definition: number.cxx:481
static sal_uInt16 GetBullIndent(sal_uInt8 nLvl)
Definition: number.cxx:175
const SwNumFormat * GetNumFormat(sal_uInt16 i) const
Definition: number.cxx:97
void ChangeIndent(const sal_Int32 nDiff)
change indent of all list levels by given difference
Definition: number.cxx:984
void SetName(const OUString &rNm, IDocumentListsAccess &rDocListAccess)
Definition: number.cxx:111
void SetIndentOfFirstListLevelAndChangeOthers(const short nNewIndent)
set indent of first list level to given value and change other list level's indents accordingly
Definition: number.cxx:1052
bool IsContinusNum() const
Definition: numrule.hxx:235
void SetCountPhantoms(bool bCountPhantoms)
Definition: number.cxx:1088
bool mbContinusNum
Continuous numbering without levels.
Definition: numrule.hxx:133
const OUString & GetDefaultListId() const
Definition: numrule.hxx:194
static const sal_uInt16 saDefNumIndents[MAXLEVEL]
Definition: numrule.hxx:110
const SwNumFormat & Get(sal_uInt16 i) const
Definition: number.cxx:87
void RemoveTextNode(SwTextNode &rTextNode)
Definition: number.cxx:152
void Set(sal_uInt16 i, const SwNumFormat *)
Definition: number.cxx:618
void SetInvalidRule(bool bFlag)
Definition: number.cxx:958
const OUString & GetName() const
Definition: numrule.hxx:224
static OUString GetOutlineRuleName()
Definition: number.cxx:82
sal_uInt16 GetPoolFormatId() const
Query and set PoolFormat IDs.
Definition: numrule.hxx:250
static SwNumFormat * saLabelAlignmentBaseFormats[RULE_END][MAXLEVEL]
default list level properties for position-and-space mode LABEL_ALIGNMENT
Definition: numrule.hxx:112
static sal_uInt16 snRefCount
Definition: numrule.hxx:113
std::unordered_map< OUString, SwNumRule * > * mpNumRuleMap
unordered_map containing "name->rule" relation
Definition: numrule.hxx:124
void SetIndent(const short nNewIndent, const sal_uInt16 nListLevel)
set indent of certain list level to given value
Definition: number.cxx:1023
SvxNumRule MakeSvxNumRule() const
Definition: number.cxx:937
std::vector< SwTextNode * > tTextNodeList
Definition: numrule.hxx:97
OUString MakeNumString(const SwNodeNum &, bool bInclStrings=true) const
Definition: number.cxx:643
SwNumRule & operator=(const SwNumRule &)
Definition: number.cxx:545
void AddTextNode(SwTextNode &rTextNode)
Definition: number.cxx:141
void Validate(const SwDoc &rDoc)
Definition: number.cxx:1075
sal_uInt8 mnPoolHlpFileId
FilePos at Doc on style helps.
Definition: numrule.hxx:130
void GetGrabBagItem(css::uno::Any &rVal) const
Definition: number.cxx:1140
void SetGrabBagItem(const css::uno::Any &rVal)
Definition: number.cxx:1148
OUString MakeParagraphStyleListString() const
Definition: number.cxx:884
OUString msName
Definition: numrule.hxx:126
static sal_uInt16 GetNumIndent(sal_uInt8 nLvl)
Definition: number.cxx:169
void Reset(const OUString &rName)
Definition: number.cxx:566
bool HasContinueList() const
Is it possible that this numbering has multiple lists?
Definition: number.cxx:1156
tParagraphStyleList maParagraphStyleList
container for associated paragraph styles
Definition: numrule.hxx:121
bool mbHidden
Is the numbering rule to be hidden in the UI?
Definition: numrule.hxx:135
bool mbCountPhantoms
Definition: numrule.hxx:136
void CheckCharFormats(SwDoc &rDoc)
Tests whether the CharFormats are from the given doc and copies them if appropriate.
Definition: number.cxx:527
sal_uInt16 GetPoolHelpId() const
Query and set Help-IDs for document styles.
Definition: numrule.hxx:254
SwNumRuleType meRuleType
Definition: numrule.hxx:127
bool mbAbsSpaces
Levels represent absolute indents.
Definition: numrule.hxx:134
tTextNodeList maTextNodeList
container for associated text nodes
Definition: numrule.hxx:118
bool mbInvalidRuleFlag
Definition: numrule.hxx:132
void GetTextNodeList(SwNumRule::tTextNodeList &rTextNodeList) const
Definition: number.cxx:131
SwNumRule & CopyNumRule(SwDoc &, const SwNumRule &)
A kind of copy-constructor to make sure the num formats are attached to the correctCharFormats of a d...
Definition: number.cxx:901
std::shared_ptr< SfxGrabBagItem > mpGrabBagItem
Style InteropGrabBag.
Definition: numrule.hxx:141
bool IsPhantom() const
Return if this node is a phantom.
int GetLevelInListTree() const
Return level of this node.
SwNumberTree::tNumberVector GetNumberVector() const
Returns level numbers of this node.
SwNumberTreeNode * GetParent() const
Returns the parent of this node.
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:187
SwNode & GetPointNode() const
Definition: pam.hxx:283
static SW_DLLPUBLIC sal_uInt16 GetPoolIdFromUIName(const OUString &rName, SwGetPoolIdFromName)
Represents the style of a paragraph.
Definition: fmtcol.hxx:59
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:111
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2907
bool HasNumber(SwRootFrame const *pLayout=nullptr) const
Returns if this text node has a number.
Definition: ndtxt.cxx:3199
int GetActualListLevel(SwListRedlineType eRedline=SwListRedlineType::SHOW) const
Returns the actual list level of this text node, when it is a list item.
Definition: ndtxt.cxx:4228
void NumRuleChgd()
Notify this textnode that its numbering rule has changed.
Definition: ndtxt.cxx:2947
std::vector< SwNumRule * >::size_type size_type
Definition: docary.hxx:66
size_t size() const
Definition: docary.hxx:87
Used by the UI to modify the document model.
Definition: wrtsh.hxx:97
std::pair< const_iterator, bool > insert(Value &&x)
static bool IsFuzzing()
virtual OUString GetName() const override
float u
DocumentType eType
FontItalic
ITALIC_NONE
WEIGHT_DONTKNOW
void Notify(SwFlyFrame *pFly, SwPageFrame *pOld, const SwRect &rOld, const SwRect *pOldRect=nullptr)
Notify the background based on the difference between old and new rectangle.
Definition: frmtool.cxx:3243
constexpr TypedWhichId< SwFormatChg > RES_FMT_CHG(162)
constexpr TypedWhichId< SwAttrSetChg > RES_ATTRSET_CHG(163)
sal_Int32 nIndex
sal_Int64 n
OUString sSuffix
OUString sPrefix
aStr
def text(shape, orig_st)
std::vector< tSwNumTreeNumber > tNumberVector
int i
namespace for static functions and methods for numbering and bullets
Definition: number.cxx:1180
bool IsDefBulletFontUserDefined()
determine if default bullet font is user defined
Definition: number.cxx:1390
SvxNumberFormat::SvxNumPositionAndSpaceMode GetDefaultPositionAndSpaceMode()
Definition: number.cxx:1561
bool ChangeIndentOnTabAtFirstPosOfFirstListItem()
configuration, if at first position of the first list item the <TAB>-key increased the indent of the ...
Definition: number.cxx:1512
sal_Unicode GetBulletChar(sal_uInt8 nLevel)
retrieve unicode of character used for the default bullet list for the given list level
Definition: number.cxx:1400
bool NumDownChangesIndent(const SwWrtShell &rShell)
Decides if increasing ("downing") the numbering level will change the amount of indentation or not.
Definition: number.cxx:1517
OUString const & GetDefBulletFontname()
retrieve font family name used for the default bullet list characters
Definition: number.cxx:1385
const vcl::Font & GetDefBulletFont()
retrieve font used for the default bullet list characters
Definition: number.cxx:1395
constexpr auto toTwips(N number, Length from)
FontWeight
long Long
vcl::Font GetFont(vcl::Font const &rFont, DrawModeFlags nDrawMode, StyleSettings const &rStyleSettings)
std::optional< vcl::Font > mpFont
Definition: number.cxx:1242
bool mbChangeIndentOnTabAtFirstPosOfFirstListItem
Definition: number.cxx:1440
OUString msFontname
Definition: number.cxx:1235
bool mbUserDefinedFontname
Definition: number.cxx:1236
sal_Unicode mnLevelChars[MAXLEVEL]
Definition: number.cxx:1239
FontWeight meFontWeight
Definition: number.cxx:1237
FontItalic meFontItalic
Definition: number.cxx:1238
static void lcl_SetRuleChgd(SwTextNode &rNd, sal_uInt8 nLevel)
Definition: number.cxx:181
SwNumRuleType
Definition: numrule.hxx:92
@ OUTLINE_RULE
Definition: numrule.hxx:92
@ NUM_RULE
Definition: numrule.hxx:92
@ RULE_END
Definition: numrule.hxx:92
sal_Int16 nId
const PropertyStruct aPropNames[]
UNOTOOLS_DLLPUBLIC SvtSaveOptions::ODFSaneDefaultVersion GetODFSaneDefaultVersion()
static LanguageType nLang
Definition: srtdlg.cxx:51
sal_uInt16 nSuffixChars
Definition: numrule.hxx:103
sal_uInt16 nPrefixChars
Definition: numrule.hxx:102
SVX_NUM_NUMBER_NONE
SVX_NUM_ARABIC
SVX_NUM_BITMAP
SVX_NUM_CHAR_SPECIAL
constexpr sal_uInt16 lNumberIndent
Definition: swtypes.hxx:100
constexpr short lNumberFirstLineOffset
Definition: swtypes.hxx:101
constexpr short lOutlineMinTextDistance
Definition: swtypes.hxx:102
constexpr sal_uInt8 MAXLEVEL
Definition: swtypes.hxx:92
OUString msName
unsigned char sal_uInt8
sal_uInt16 sal_Unicode