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 .
20 #include <sal/config.h>
24 #include <editeng/numitem.hxx>
26 #include <com/sun/star/text/HoriOrientation.hpp>
27 #include <com/sun/star/text/VertOrientation.hpp>
28 #include <com/sun/star/text/RelOrientation.hpp>
29 #include <editeng/brushitem.hxx>
30 #include <vcl/font.hxx>
31 #include <vcl/settings.hxx>
32 #include <editeng/editids.hrc>
33 #include <editeng/numdef.hxx>
34 #include <editeng/eeitem.hxx>
35 #include <vcl/graph.hxx>
36 #include <vcl/window.hxx>
37 #include <vcl/svapp.hxx>
38 #include <editeng/unolingu.hxx>
39 #include <com/sun/star/text/XNumberingFormatter.hpp>
40 #include <com/sun/star/text/DefaultNumberingProvider.hpp>
41 #include <com/sun/star/text/XDefaultNumberingProvider.hpp>
42 #include <com/sun/star/style/NumberingType.hpp>
43 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
44 #include <com/sun/star/lang/IllegalArgumentException.hpp>
45 #include <com/sun/star/beans/PropertyValue.hpp>
46 #include <comphelper/fileformat.h>
47 #include <comphelper/processfactory.hxx>
48 #include <tools/mapunit.hxx>
49 #include <tools/stream.hxx>
50 #include <tools/debug.hxx>
51 #include <tools/GenericTypeSerializer.hxx>
52 #include <unotools/configmgr.hxx>
53 #include <libxml/xmlwriter.h>
54 #include <editeng/unonrule.hxx>
55 #include <sal/log.hxx>
56 #include <i18nlangtag/languagetag.hxx>
57 #include <editeng/legacyitem.hxx>
59 #define DEF_WRITER_LSPACE 500 //Standard Indentation
60 #define DEF_DRAW_LSPACE 800 //Standard Indentation
62 #define NUMITEM_VERSION_03 0x03
63 #define NUMITEM_VERSION_04 0x04
65 using namespace ::com::sun::star
;
66 using namespace ::com::sun::star::lang
;
67 using namespace ::com::sun::star::uno
;
68 using namespace ::com::sun::star::text
;
69 using namespace ::com::sun::star::beans
;
70 using namespace ::com::sun::star::style
;
72 sal_Int32
SvxNumberType::nRefCount
= 0;
73 css::uno::Reference
<css::text::XNumberingFormatter
> SvxNumberType::xFormatter
;
74 static void lcl_getFormatter(css::uno::Reference
<css::text::XNumberingFormatter
>& _xFormatter
)
80 Reference
<XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
81 Reference
<XDefaultNumberingProvider
> xRet
= text::DefaultNumberingProvider::create(xContext
);
82 _xFormatter
.set(xRet
, UNO_QUERY
);
84 catch(const Exception
&)
86 SAL_WARN("editeng", "service missing: \"com.sun.star.text.DefaultNumberingProvider\"");
91 SvxNumberType::SvxNumberType(SvxNumType nType
) :
98 SvxNumberType::SvxNumberType(const SvxNumberType
& rType
) :
99 nNumType(rType
.nNumType
),
100 bShowSymbol(rType
.bShowSymbol
)
105 SvxNumberType::~SvxNumberType()
108 xFormatter
= nullptr;
111 OUString
SvxNumberType::GetNumStr( sal_Int32 nNo
) const
113 LanguageTag aLang
= utl::ConfigManager::IsFuzzing() ?
114 LanguageTag("en-US") :
115 Application::GetSettings().GetLanguageTag();
116 return GetNumStr( nNo
, aLang
.getLocale() );
119 OUString
SvxNumberType::GetNumStr( sal_Int32 nNo
, const css::lang::Locale
& rLocale
) const
121 lcl_getFormatter(xFormatter
);
129 case NumberingType::CHAR_SPECIAL
:
130 case NumberingType::BITMAP
:
134 // '0' allowed for ARABIC numberings
135 if(NumberingType::ARABIC
== nNumType
&& 0 == nNo
)
136 return OUString('0');
139 Sequence
< PropertyValue
> aProperties(2);
140 PropertyValue
* pValues
= aProperties
.getArray();
141 pValues
[0].Name
= "NumberingType";
142 pValues
[0].Value
<<= static_cast<sal_uInt16
>(nNumType
);
143 pValues
[1].Name
= "Value";
144 pValues
[1].Value
<<= nNo
;
148 return xFormatter
->makeNumberingString( aProperties
, rLocale
);
150 catch(const Exception
&)
160 SvxNumberFormat::SvxNumberFormat( SvxNumType eType
)
161 : SvxNumberType(eType
),
162 eNumAdjust(SvxAdjust::Left
),
165 cBullet(SVX_DEF_BULLET
),
167 nBulletColor(COL_BLACK
),
168 mePositionAndSpaceMode( LABEL_WIDTH_AND_POSITION
),
171 nCharTextDistance(0),
172 meLabelFollowedBy( LISTTAB
),
174 mnFirstLineIndent( 0 ),
176 eVertOrient(text::VertOrientation::NONE
)
180 SvxNumberFormat::SvxNumberFormat(const SvxNumberFormat
& rFormat
) :
181 SvxNumberType(rFormat
),
182 mePositionAndSpaceMode( rFormat
.mePositionAndSpaceMode
)
187 SvxNumberFormat::SvxNumberFormat( SvStream
&rStream
)
189 , nBulletRelSize(100)
190 , nFirstLineOffset(0)
192 , nCharTextDistance(0)
194 sal_uInt16
nTmp16(0);
196 rStream
.ReadUInt16( nTmp16
); // Version number
198 rStream
.ReadUInt16( nTmp16
); SetNumberingType( static_cast<SvxNumType
>(nTmp16
) );
199 rStream
.ReadUInt16( nTmp16
); eNumAdjust
= static_cast<SvxAdjust
>(nTmp16
);
200 rStream
.ReadUInt16( nTmp16
); nInclUpperLevels
= nTmp16
;
201 rStream
.ReadUInt16( nStart
);
202 rStream
.ReadUInt16( nTmp16
); cBullet
= static_cast<sal_Unicode
>(nTmp16
);
205 rStream
.ReadInt16( temp
);
206 nFirstLineOffset
= temp
;
208 rStream
.ReadInt16( temp
);
210 rStream
.SeekRel(2); //skip old now unused nLSpace;
212 rStream
.ReadInt16( nCharTextDistance
);
214 sPrefix
= rStream
.ReadUniOrByteString( rStream
.GetStreamCharSet() );
215 sSuffix
= rStream
.ReadUniOrByteString( rStream
.GetStreamCharSet() );
216 sCharStyleName
= rStream
.ReadUniOrByteString( rStream
.GetStreamCharSet() );
218 sal_uInt16 hasGraphicBrush
= 0;
219 rStream
.ReadUInt16( hasGraphicBrush
);
220 if ( hasGraphicBrush
)
222 pGraphicBrush
.reset(new SvxBrushItem(SID_ATTR_BRUSH
));
223 legacy::SvxBrush::Create(*pGraphicBrush
, rStream
, BRUSH_GRAPHIC_VERSION
);
225 else pGraphicBrush
= nullptr;
226 rStream
.ReadUInt16( nTmp16
); eVertOrient
= nTmp16
;
228 sal_uInt16 hasBulletFont
= 0;
229 rStream
.ReadUInt16( hasBulletFont
);
232 pBulletFont
.reset( new vcl::Font() );
233 ReadFont( rStream
, *pBulletFont
);
235 else pBulletFont
= nullptr;
237 tools::GenericTypeSerializer
aSerializer(rStream
);
238 aSerializer
.readSize(aGraphicSize
);
239 aSerializer
.readColor(nBulletColor
);
241 rStream
.ReadUInt16( nBulletRelSize
);
242 rStream
.ReadUInt16( nTmp16
); SetShowSymbol( nTmp16
!= 0 );
244 rStream
.ReadUInt16( nTmp16
); mePositionAndSpaceMode
= static_cast<SvxNumPositionAndSpaceMode
>(nTmp16
);
245 rStream
.ReadUInt16( nTmp16
); meLabelFollowedBy
= static_cast<LabelFollowedBy
>(nTmp16
);
246 rStream
.ReadInt32( nTmp32
); mnListtabPos
= nTmp32
;
247 rStream
.ReadInt32( nTmp32
); mnFirstLineIndent
= nTmp32
;
248 rStream
.ReadInt32( nTmp32
); mnIndentAt
= nTmp32
;
251 SvxNumberFormat::~SvxNumberFormat()
255 void SvxNumberFormat::Store(SvStream
&rStream
, FontToSubsFontConverter pConverter
)
257 if(pConverter
&& pBulletFont
)
259 cBullet
= ConvertFontToSubsFontChar(pConverter
, cBullet
);
260 OUString sFontName
= GetFontToSubsFontName(pConverter
);
261 pBulletFont
->SetFamilyName(sFontName
);
264 tools::GenericTypeSerializer
aSerializer(rStream
);
266 rStream
.WriteUInt16( NUMITEM_VERSION_04
);
268 rStream
.WriteUInt16( GetNumberingType() );
269 rStream
.WriteUInt16( static_cast<sal_uInt16
>(eNumAdjust
) );
270 rStream
.WriteUInt16( nInclUpperLevels
);
271 rStream
.WriteUInt16( nStart
);
272 rStream
.WriteUInt16( cBullet
);
275 sal_Int16(std::clamp
<sal_Int32
>(nFirstLineOffset
, SAL_MIN_INT16
, SAL_MAX_INT16
)) );
276 //TODO: better way to handle out-of-bounds value?
278 sal_Int16(std::clamp
<sal_Int32
>(nAbsLSpace
, SAL_MIN_INT16
, SAL_MAX_INT16
)) );
279 //TODO: better way to handle out-of-bounds value?
280 rStream
.WriteInt16( 0 ); // write a dummy for old now unused nLSpace
282 rStream
.WriteInt16( nCharTextDistance
);
283 rtl_TextEncoding eEnc
= osl_getThreadTextEncoding();
284 rStream
.WriteUniOrByteString(sPrefix
, eEnc
);
285 rStream
.WriteUniOrByteString(sSuffix
, eEnc
);
286 rStream
.WriteUniOrByteString(sCharStyleName
, eEnc
);
289 rStream
.WriteUInt16( 1 );
291 // in SD or SI force bullet itself to be stored,
292 // for that purpose throw away link when link and graphic
293 // are present, so Brush save is forced
294 if(!pGraphicBrush
->GetGraphicLink().isEmpty() && pGraphicBrush
->GetGraphic())
296 pGraphicBrush
->SetGraphicLink("");
299 legacy::SvxBrush::Store(*pGraphicBrush
, rStream
, BRUSH_GRAPHIC_VERSION
);
302 rStream
.WriteUInt16( 0 );
304 rStream
.WriteUInt16( eVertOrient
);
307 rStream
.WriteUInt16( 1 );
308 WriteFont( rStream
, *pBulletFont
);
311 rStream
.WriteUInt16( 0 );
313 aSerializer
.writeSize(aGraphicSize
);
315 Color nTempColor
= nBulletColor
;
316 if(COL_AUTO
== nBulletColor
)
317 nTempColor
= COL_BLACK
;
319 aSerializer
.writeColor(nTempColor
);
320 rStream
.WriteUInt16( nBulletRelSize
);
321 rStream
.WriteUInt16( sal_uInt16(IsShowSymbol()) );
323 rStream
.WriteUInt16( mePositionAndSpaceMode
);
324 rStream
.WriteUInt16( meLabelFollowedBy
);
325 rStream
.WriteInt32( mnListtabPos
);
326 rStream
.WriteInt32( mnFirstLineIndent
);
327 rStream
.WriteInt32( mnIndentAt
);
330 SvxNumberFormat
& SvxNumberFormat::operator=( const SvxNumberFormat
& rFormat
)
332 if (& rFormat
== this) { return *this; }
334 SvxNumberType::SetNumberingType(rFormat
.GetNumberingType());
335 eNumAdjust
= rFormat
.eNumAdjust
;
336 nInclUpperLevels
= rFormat
.nInclUpperLevels
;
337 nStart
= rFormat
.nStart
;
338 cBullet
= rFormat
.cBullet
;
339 mePositionAndSpaceMode
= rFormat
.mePositionAndSpaceMode
;
340 nFirstLineOffset
= rFormat
.nFirstLineOffset
;
341 nAbsLSpace
= rFormat
.nAbsLSpace
;
342 nCharTextDistance
= rFormat
.nCharTextDistance
;
343 meLabelFollowedBy
= rFormat
.meLabelFollowedBy
;
344 mnListtabPos
= rFormat
.mnListtabPos
;
345 mnFirstLineIndent
= rFormat
.mnFirstLineIndent
;
346 mnIndentAt
= rFormat
.mnIndentAt
;
347 eVertOrient
= rFormat
.eVertOrient
;
348 sPrefix
= rFormat
.sPrefix
;
349 sSuffix
= rFormat
.sSuffix
;
350 aGraphicSize
= rFormat
.aGraphicSize
;
351 nBulletColor
= rFormat
.nBulletColor
;
352 nBulletRelSize
= rFormat
.nBulletRelSize
;
353 SetShowSymbol(rFormat
.IsShowSymbol());
354 sCharStyleName
= rFormat
.sCharStyleName
;
355 pGraphicBrush
.reset();
356 if(rFormat
.pGraphicBrush
)
358 pGraphicBrush
.reset( new SvxBrushItem(*rFormat
.pGraphicBrush
) );
361 if(rFormat
.pBulletFont
)
362 pBulletFont
.reset( new vcl::Font(*rFormat
.pBulletFont
) );
366 bool SvxNumberFormat::operator==( const SvxNumberFormat
& rFormat
) const
368 if( GetNumberingType() != rFormat
.GetNumberingType() ||
369 eNumAdjust
!= rFormat
.eNumAdjust
||
370 nInclUpperLevels
!= rFormat
.nInclUpperLevels
||
371 nStart
!= rFormat
.nStart
||
372 cBullet
!= rFormat
.cBullet
||
373 mePositionAndSpaceMode
!= rFormat
.mePositionAndSpaceMode
||
374 nFirstLineOffset
!= rFormat
.nFirstLineOffset
||
375 nAbsLSpace
!= rFormat
.nAbsLSpace
||
376 nCharTextDistance
!= rFormat
.nCharTextDistance
||
377 meLabelFollowedBy
!= rFormat
.meLabelFollowedBy
||
378 mnListtabPos
!= rFormat
.mnListtabPos
||
379 mnFirstLineIndent
!= rFormat
.mnFirstLineIndent
||
380 mnIndentAt
!= rFormat
.mnIndentAt
||
381 eVertOrient
!= rFormat
.eVertOrient
||
382 sPrefix
!= rFormat
.sPrefix
||
383 sSuffix
!= rFormat
.sSuffix
||
384 aGraphicSize
!= rFormat
.aGraphicSize
||
385 nBulletColor
!= rFormat
.nBulletColor
||
386 nBulletRelSize
!= rFormat
.nBulletRelSize
||
387 IsShowSymbol() != rFormat
.IsShowSymbol() ||
388 sCharStyleName
!= rFormat
.sCharStyleName
392 (pGraphicBrush
&& !rFormat
.pGraphicBrush
) ||
393 (!pGraphicBrush
&& rFormat
.pGraphicBrush
) ||
394 (pGraphicBrush
&& *pGraphicBrush
!= *rFormat
.pGraphicBrush
)
400 (pBulletFont
&& !rFormat
.pBulletFont
) ||
401 (!pBulletFont
&& rFormat
.pBulletFont
) ||
402 (pBulletFont
&& *pBulletFont
!= *rFormat
.pBulletFont
)
410 void SvxNumberFormat::SetGraphicBrush( const SvxBrushItem
* pBrushItem
,
411 const Size
* pSize
, const sal_Int16
* pOrient
)
415 pGraphicBrush
.reset();
417 else if ( !pGraphicBrush
|| (*pBrushItem
!= *pGraphicBrush
) )
419 pGraphicBrush
.reset( static_cast<SvxBrushItem
*>(pBrushItem
->Clone()) );
423 eVertOrient
= *pOrient
;
425 eVertOrient
= text::VertOrientation::NONE
;
427 aGraphicSize
= *pSize
;
430 aGraphicSize
.setWidth(0);
431 aGraphicSize
.setHeight(0);
435 void SvxNumberFormat::SetGraphic( const OUString
& rName
)
437 if( pGraphicBrush
&& pGraphicBrush
->GetGraphicLink() == rName
)
440 pGraphicBrush
.reset( new SvxBrushItem( rName
, "", GPOS_AREA
, 0 ) );
441 if( eVertOrient
== text::VertOrientation::NONE
)
442 eVertOrient
= text::VertOrientation::TOP
;
444 aGraphicSize
.setWidth(0);
445 aGraphicSize
.setHeight(0);
448 sal_Int16
SvxNumberFormat::GetVertOrient() const
453 void SvxNumberFormat::SetBulletFont(const vcl::Font
* pFont
)
455 pBulletFont
.reset( pFont
? new vcl::Font(*pFont
): nullptr );
458 void SvxNumberFormat::SetPositionAndSpaceMode( SvxNumPositionAndSpaceMode ePositionAndSpaceMode
)
460 mePositionAndSpaceMode
= ePositionAndSpaceMode
;
463 sal_Int32
SvxNumberFormat::GetAbsLSpace() const
465 return mePositionAndSpaceMode
== LABEL_WIDTH_AND_POSITION
467 : static_cast<sal_Int32
>( GetFirstLineIndent() + GetIndentAt() );
469 sal_Int32
SvxNumberFormat::GetFirstLineOffset() const
471 return mePositionAndSpaceMode
== LABEL_WIDTH_AND_POSITION
473 : static_cast<sal_Int32
>( GetFirstLineIndent() );
475 short SvxNumberFormat::GetCharTextDistance() const
477 return mePositionAndSpaceMode
== LABEL_WIDTH_AND_POSITION
? nCharTextDistance
: 0;
480 void SvxNumberFormat::SetLabelFollowedBy( const LabelFollowedBy eLabelFollowedBy
)
482 meLabelFollowedBy
= eLabelFollowedBy
;
484 void SvxNumberFormat::SetListtabPos( const long nListtabPos
)
486 mnListtabPos
= nListtabPos
;
488 void SvxNumberFormat::SetFirstLineIndent( const long nFirstLineIndent
)
490 mnFirstLineIndent
= nFirstLineIndent
;
492 void SvxNumberFormat::SetIndentAt( const long nIndentAt
)
494 mnIndentAt
= nIndentAt
;
497 Size
SvxNumberFormat::GetGraphicSizeMM100(const Graphic
* pGraphic
)
499 const MapMode
aMapMM100( MapUnit::Map100thMM
);
500 const Size
& rSize
= pGraphic
->GetPrefSize();
502 if ( pGraphic
->GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel
)
504 OutputDevice
* pOutDev
= Application::GetDefaultDevice();
505 MapMode
aOldMap( pOutDev
->GetMapMode() );
506 pOutDev
->SetMapMode( aMapMM100
);
507 aRetSize
= pOutDev
->PixelToLogic( rSize
);
508 pOutDev
->SetMapMode( aOldMap
);
511 aRetSize
= OutputDevice::LogicToLogic( rSize
, pGraphic
->GetPrefMapMode(), aMapMM100
);
515 OUString
SvxNumberFormat::CreateRomanString( sal_uLong nNo
, bool bUpper
)
517 nNo
%= 4000; // more can not be displayed
518 // i, ii, iii, iv, v, vi, vii, vii, viii, ix
519 // (Dummy),1000,500,100,50,10,5,1
520 const char *cRomanArr
= bUpper
521 ? "MDCLXVI--" // +2 Dummy entries!
522 : "mdclxvi--"; // +2 Dummy entries!
525 sal_uInt16 nMask
= 1000;
528 sal_uInt8 nNumber
= sal_uInt8(nNo
/ nMask
);
535 sRet
.append(*(cRomanArr
-1));
541 case 3: { sRet
.append(*cRomanArr
); [[fallthrough
]]; }
542 case 2: { sRet
.append(*cRomanArr
); [[fallthrough
]]; }
543 case 1: { sRet
.append(*cRomanArr
); }
547 sRet
.append(*cRomanArr
);
548 sRet
.append(*(cRomanArr
-nDiff
));
551 case 5: { sRet
.append(*(cRomanArr
-nDiff
)); }
555 nMask
/= 10; // for the next decade
558 return sRet
.makeStringAndClear();
561 OUString
SvxNumberFormat::GetCharFormatName()const
563 return sCharStyleName
;
566 sal_Int32
SvxNumRule::nRefCount
= 0;
567 static SvxNumberFormat
* pStdNumFmt
= nullptr;
568 static SvxNumberFormat
* pStdOutlineNumFmt
= nullptr;
569 SvxNumRule::SvxNumRule( SvxNumRuleFlags nFeatures
,
572 SvxNumRuleType eType
,
573 SvxNumberFormat::SvxNumPositionAndSpaceMode
574 eDefaultNumberFormatPositionAndSpaceMode
)
575 : nLevelCount(nLevels
),
576 nFeatureFlags(nFeatures
),
577 eNumberingType(eType
),
578 bContinuousNumbering(bCont
)
581 for(sal_uInt16 i
= 0; i
< SVX_MAX_NUM
; i
++)
585 aFmts
[i
].reset( new SvxNumberFormat(SVX_NUM_CHARS_UPPER_LETTER
) );
586 // It is a distinction between writer and draw
587 if(nFeatures
& SvxNumRuleFlags::CONTINUOUS
)
589 if ( eDefaultNumberFormatPositionAndSpaceMode
==
590 SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
592 aFmts
[i
]->SetAbsLSpace( convertMm100ToTwip(DEF_WRITER_LSPACE
* (i
+1)) );
593 aFmts
[i
]->SetFirstLineOffset(convertMm100ToTwip(-DEF_WRITER_LSPACE
));
595 else if ( eDefaultNumberFormatPositionAndSpaceMode
==
596 SvxNumberFormat::LABEL_ALIGNMENT
)
598 // first line indent of general numbering in inch: -0,25 inch
599 const long cFirstLineIndent
= -1440/4;
600 // indent values of general numbering in inch:
601 // 0,5 0,75 1,0 1,25 1,5
602 // 1,75 2,0 2,25 2,5 2,75
603 const long cIndentAt
= 1440/4;
604 aFmts
[i
]->SetPositionAndSpaceMode( SvxNumberFormat::LABEL_ALIGNMENT
);
605 aFmts
[i
]->SetLabelFollowedBy( SvxNumberFormat::LISTTAB
);
606 aFmts
[i
]->SetListtabPos( cIndentAt
* (i
+2) );
607 aFmts
[i
]->SetFirstLineIndent( cFirstLineIndent
);
608 aFmts
[i
]->SetIndentAt( cIndentAt
* (i
+2) );
613 aFmts
[i
]->SetAbsLSpace( DEF_DRAW_LSPACE
* i
);
622 SvxNumRule::SvxNumRule(const SvxNumRule
& rCopy
)
625 nLevelCount
= rCopy
.nLevelCount
;
626 nFeatureFlags
= rCopy
.nFeatureFlags
;
627 bContinuousNumbering
= rCopy
.bContinuousNumbering
;
628 eNumberingType
= rCopy
.eNumberingType
;
629 for(sal_uInt16 i
= 0; i
< SVX_MAX_NUM
; i
++)
632 aFmts
[i
].reset( new SvxNumberFormat(*rCopy
.aFmts
[i
]) );
635 aFmtsSet
[i
] = rCopy
.aFmtsSet
[i
];
639 SvxNumRule::SvxNumRule( SvStream
&rStream
)
642 sal_uInt16
nTmp16(0);
643 rStream
.ReadUInt16( nTmp16
); // NUM_ITEM_VERSION
644 rStream
.ReadUInt16( nLevelCount
);
646 // first nFeatureFlags of old Versions
647 rStream
.ReadUInt16( nTmp16
); nFeatureFlags
= static_cast<SvxNumRuleFlags
>(nTmp16
);
648 rStream
.ReadUInt16( nTmp16
); bContinuousNumbering
= nTmp16
;
649 rStream
.ReadUInt16( nTmp16
); eNumberingType
= static_cast<SvxNumRuleType
>(nTmp16
);
651 for (sal_uInt16 i
= 0; i
< SVX_MAX_NUM
; i
++)
653 rStream
.ReadUInt16( nTmp16
);
654 bool hasNumberingFormat
= nTmp16
& 1;
655 aFmtsSet
[i
] = nTmp16
& 2; // fdo#68648 reset flag
656 if ( hasNumberingFormat
){
657 aFmts
[i
].reset( new SvxNumberFormat( rStream
) );
662 aFmtsSet
[i
] = false; // actually only false is valid
665 //second nFeatureFlags for new versions
666 rStream
.ReadUInt16( nTmp16
); nFeatureFlags
= static_cast<SvxNumRuleFlags
>(nTmp16
);
669 void SvxNumRule::Store( SvStream
&rStream
)
671 rStream
.WriteUInt16( NUMITEM_VERSION_03
);
672 rStream
.WriteUInt16( nLevelCount
);
673 //first save of nFeatureFlags for old versions
674 rStream
.WriteUInt16( static_cast<sal_uInt16
>(nFeatureFlags
) );
675 rStream
.WriteUInt16( sal_uInt16(bContinuousNumbering
) );
676 rStream
.WriteUInt16( static_cast<sal_uInt16
>(eNumberingType
) );
678 FontToSubsFontConverter pConverter
= nullptr;
679 bool bConvertBulletFont
= ( rStream
.GetVersion() <= SOFFICE_FILEFORMAT_50
) && ( rStream
.GetVersion() );
680 for(sal_uInt16 i
= 0; i
< SVX_MAX_NUM
; i
++)
682 sal_uInt16
nSetFlag(aFmtsSet
[i
] ? 2 : 0); // fdo#68648 store that too
685 rStream
.WriteUInt16( 1 | nSetFlag
);
686 if(bConvertBulletFont
&& aFmts
[i
]->GetBulletFont())
690 CreateFontToSubsFontConverter(aFmts
[i
]->GetBulletFont()->GetFamilyName(),
691 FontToSubsFontFlags::EXPORT
);
693 aFmts
[i
]->Store(rStream
, pConverter
);
696 rStream
.WriteUInt16( 0 | nSetFlag
);
698 //second save of nFeatureFlags for new versions
699 rStream
.WriteUInt16( static_cast<sal_uInt16
>(nFeatureFlags
) );
702 void SvxNumRule::dumpAsXml(xmlTextWriterPtr pWriter
) const
704 xmlTextWriterStartElement(pWriter
, BAD_CAST("SvxNumRule"));
705 xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("levelCount"), BAD_CAST(OString::number(nLevelCount
).getStr()));
706 xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("continuousNumbering"), BAD_CAST(OString::boolean(bContinuousNumbering
).getStr()));
707 xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("numberingType"), BAD_CAST(OString::number(static_cast<int>(eNumberingType
)).getStr()));
708 xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("featureFlags"), BAD_CAST(OString::number(static_cast<int>(nFeatureFlags
)).getStr()));
709 for(sal_uInt16 i
= 0; i
< SVX_MAX_NUM
; i
++)
713 xmlTextWriterStartElement(pWriter
, BAD_CAST("aFmts"));
714 xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("i"), BAD_CAST(OString::number(i
).getStr()));
715 xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", aFmts
[i
].get());
716 xmlTextWriterEndElement(pWriter
);
719 xmlTextWriterEndElement(pWriter
);
723 SvxNumRule::~SvxNumRule()
728 DELETEZ(pStdOutlineNumFmt
);
732 SvxNumRule
& SvxNumRule::operator=( const SvxNumRule
& rCopy
)
736 nLevelCount
= rCopy
.nLevelCount
;
737 nFeatureFlags
= rCopy
.nFeatureFlags
;
738 bContinuousNumbering
= rCopy
.bContinuousNumbering
;
739 eNumberingType
= rCopy
.eNumberingType
;
740 for(sal_uInt16 i
= 0; i
< SVX_MAX_NUM
; i
++)
743 aFmts
[i
].reset( new SvxNumberFormat(*rCopy
.aFmts
[i
]) );
746 aFmtsSet
[i
] = rCopy
.aFmtsSet
[i
];
752 bool SvxNumRule::operator==( const SvxNumRule
& rCopy
) const
754 if(nLevelCount
!= rCopy
.nLevelCount
||
755 nFeatureFlags
!= rCopy
.nFeatureFlags
||
756 bContinuousNumbering
!= rCopy
.bContinuousNumbering
||
757 eNumberingType
!= rCopy
.eNumberingType
)
759 for(sal_uInt16 i
= 0; i
< nLevelCount
; i
++)
762 (aFmtsSet
[i
] != rCopy
.aFmtsSet
[i
]) ||
763 (!aFmts
[i
] && rCopy
.aFmts
[i
]) ||
764 (aFmts
[i
] && !rCopy
.aFmts
[i
]) ||
765 (aFmts
[i
] && *aFmts
[i
] != *rCopy
.aFmts
[i
])
774 const SvxNumberFormat
* SvxNumRule::Get(sal_uInt16 nLevel
)const
776 DBG_ASSERT(nLevel
< SVX_MAX_NUM
, "Wrong Level" );
777 if( nLevel
< SVX_MAX_NUM
)
778 return aFmtsSet
[nLevel
] ? aFmts
[nLevel
].get() : nullptr;
783 const SvxNumberFormat
& SvxNumRule::GetLevel(sal_uInt16 nLevel
)const
787 pStdNumFmt
= new SvxNumberFormat(SVX_NUM_ARABIC
);
788 pStdOutlineNumFmt
= new SvxNumberFormat(SVX_NUM_NUMBER_NONE
);
791 DBG_ASSERT(nLevel
< SVX_MAX_NUM
, "Wrong Level" );
793 return ( ( nLevel
< SVX_MAX_NUM
) && aFmts
[nLevel
] ) ?
794 *aFmts
[nLevel
] : eNumberingType
== SvxNumRuleType::NUMBERING
?
795 *pStdNumFmt
: *pStdOutlineNumFmt
;
798 void SvxNumRule::SetLevel( sal_uInt16 i
, const SvxNumberFormat
& rNumFmt
, bool bIsValid
)
800 DBG_ASSERT(i
< SVX_MAX_NUM
, "Wrong Level" );
802 if( i
< SVX_MAX_NUM
)
804 bool bReplace
= !aFmtsSet
[i
];
807 const SvxNumberFormat
*pFmt
= Get(i
);
808 bReplace
= pFmt
== nullptr || rNumFmt
!= *pFmt
;
813 aFmts
[i
].reset( new SvxNumberFormat(rNumFmt
) );
814 aFmtsSet
[i
] = bIsValid
;
819 void SvxNumRule::SetLevel(sal_uInt16 nLevel
, const SvxNumberFormat
* pFmt
)
821 DBG_ASSERT(nLevel
< SVX_MAX_NUM
, "Wrong Level" );
823 if( nLevel
< SVX_MAX_NUM
)
825 aFmtsSet
[nLevel
] = nullptr != pFmt
;
827 SetLevel(nLevel
, *pFmt
);
830 aFmts
[nLevel
].reset();
835 OUString
SvxNumRule::MakeNumString( const SvxNodeNum
& rNum
) const
838 if( SVX_NO_NUM
> rNum
.GetLevel() && !( SVX_NO_NUMLEVEL
& rNum
.GetLevel() ) )
840 const SvxNumberFormat
& rMyNFmt
= GetLevel( rNum
.GetLevel() );
841 aStr
.append(rMyNFmt
.GetPrefix());
842 if( SVX_NUM_NUMBER_NONE
!= rMyNFmt
.GetNumberingType() )
844 sal_uInt8 i
= rNum
.GetLevel();
846 if( !IsContinuousNumbering() &&
847 1 < rMyNFmt
.GetIncludeUpperLevels() ) // only on own level?
849 sal_uInt8 n
= rMyNFmt
.GetIncludeUpperLevels();
859 for( ; i
<= rNum
.GetLevel(); ++i
)
861 const SvxNumberFormat
& rNFmt
= GetLevel( i
);
862 if( SVX_NUM_NUMBER_NONE
== rNFmt
.GetNumberingType() )
868 if( rNum
.GetLevelVal()[ i
] )
870 if(SVX_NUM_BITMAP
!= rNFmt
.GetNumberingType())
872 const LanguageTag
& rLang
= Application::GetSettings().GetLanguageTag();
873 aStr
.append(rNFmt
.GetNumStr( rNum
.GetLevelVal()[ i
], rLang
.getLocale() ));
879 aStr
.append("0"); // all 0-levels are a 0
880 if( i
!= rNum
.GetLevel() && bDot
)
885 aStr
.append(rMyNFmt
.GetSuffix());
887 return aStr
.makeStringAndClear();
890 // changes linked to embedded bitmaps
891 void SvxNumRule::UnLinkGraphics()
893 for(sal_uInt16 i
= 0; i
< GetLevelCount(); i
++)
895 SvxNumberFormat
aFmt(GetLevel(i
));
896 const SvxBrushItem
* pBrush
= aFmt
.GetBrush();
897 if(SVX_NUM_BITMAP
== aFmt
.GetNumberingType())
899 const Graphic
* pGraphic
= nullptr;
901 !pBrush
->GetGraphicLink().isEmpty() &&
902 nullptr != (pGraphic
= pBrush
->GetGraphic()))
904 SvxBrushItem
aTempItem(*pBrush
);
905 aTempItem
.SetGraphicLink("");
906 aTempItem
.SetGraphic(*pGraphic
);
907 sal_Int16 eOrient
= aFmt
.GetVertOrient();
908 aFmt
.SetGraphicBrush( &aTempItem
, &aFmt
.GetGraphicSize(), &eOrient
);
911 else if((SVX_NUM_BITMAP
|LINK_TOKEN
) == static_cast<int>(aFmt
.GetNumberingType()))
912 aFmt
.SetNumberingType(SVX_NUM_BITMAP
);
917 SvxNumBulletItem::SvxNumBulletItem(SvxNumRule
const & rRule
) :
918 SfxPoolItem(SID_ATTR_NUMBERING_RULE
),
919 pNumRule(new SvxNumRule(rRule
))
923 SvxNumBulletItem::SvxNumBulletItem(SvxNumRule
const & rRule
, sal_uInt16 _nWhich
) :
924 SfxPoolItem(_nWhich
),
925 pNumRule(new SvxNumRule(rRule
))
929 SvxNumBulletItem::SvxNumBulletItem(const SvxNumBulletItem
& rCopy
) :
931 pNumRule(new SvxNumRule(*rCopy
.pNumRule
))
935 SvxNumBulletItem::~SvxNumBulletItem()
939 bool SvxNumBulletItem::operator==( const SfxPoolItem
& rCopy
) const
941 return SfxPoolItem::operator==(rCopy
) &&
942 *pNumRule
== *static_cast<const SvxNumBulletItem
&>(rCopy
).pNumRule
;
945 SfxPoolItem
* SvxNumBulletItem::Clone( SfxItemPool
* ) const
947 return new SvxNumBulletItem(*this);
950 bool SvxNumBulletItem::QueryValue( css::uno::Any
& rVal
, sal_uInt8
/*nMemberId*/ ) const
952 rVal
<<= SvxCreateNumRule( pNumRule
.get() );
956 bool SvxNumBulletItem::PutValue( const css::uno::Any
& rVal
, sal_uInt8
/*nMemberId*/ )
958 uno::Reference
< container::XIndexReplace
> xRule
;
963 std::unique_ptr
<SvxNumRule
> pNewRule(new SvxNumRule( SvxGetNumRule( xRule
) ));
964 if( pNewRule
->GetLevelCount() != pNumRule
->GetLevelCount() ||
965 pNewRule
->GetNumRuleType() != pNumRule
->GetNumRuleType() )
967 std::unique_ptr
<SvxNumRule
> pConverted
= SvxConvertNumRule( pNewRule
.get(), pNumRule
->GetLevelCount(), pNumRule
->GetNumRuleType() );
968 pNewRule
= std::move(pConverted
);
970 pNumRule
= std::move( pNewRule
);
973 catch(const lang::IllegalArgumentException
&)
980 void SvxNumBulletItem::dumpAsXml(xmlTextWriterPtr pWriter
) const
982 xmlTextWriterStartElement(pWriter
, BAD_CAST("SvxNumBulletItem"));
983 xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
984 pNumRule
->dumpAsXml(pWriter
);
985 xmlTextWriterEndElement(pWriter
);
988 std::unique_ptr
<SvxNumRule
> SvxConvertNumRule( const SvxNumRule
* pRule
, sal_uInt16 nLevels
, SvxNumRuleType eType
)
990 const sal_uInt16 nSrcLevels
= pRule
->GetLevelCount();
991 std::unique_ptr
<SvxNumRule
> pNewRule(new SvxNumRule( pRule
->GetFeatureFlags(), nLevels
, pRule
->IsContinuousNumbering(), eType
));
993 for( sal_uInt16 nLevel
= 0; (nLevel
< nLevels
) && (nLevel
< nSrcLevels
); nLevel
++ )
994 pNewRule
->SetLevel( nLevel
, pRule
->GetLevel( nLevel
) );
999 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */