bump product version to 5.0.4.1
[LibreOffice.git] / editeng / source / items / numitem.cxx
blob6b846e74491fba284b7377322cb00c6495b1451a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <editeng/numitem.hxx>
23 #include <com/sun/star/text/HoriOrientation.hpp>
24 #include <com/sun/star/text/VertOrientation.hpp>
25 #include <com/sun/star/text/RelOrientation.hpp>
26 #include <editeng/brushitem.hxx>
27 #include <vcl/font.hxx>
28 #include <vcl/settings.hxx>
29 #include <editeng/editids.hrc>
30 #include <editeng/editrids.hrc>
31 #include <editeng/numdef.hxx>
32 #include <editeng/eeitem.hxx>
33 #include <vcl/graph.hxx>
34 #include <vcl/window.hxx>
35 #include <vcl/svapp.hxx>
36 #include <editeng/unolingu.hxx>
37 #include <com/sun/star/text/XNumberingFormatter.hpp>
38 #include <com/sun/star/text/DefaultNumberingProvider.hpp>
39 #include <com/sun/star/text/XDefaultNumberingProvider.hpp>
40 #include <com/sun/star/style/NumberingType.hpp>
41 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
42 #include <com/sun/star/beans/PropertyValue.hpp>
43 #include <comphelper/processfactory.hxx>
44 #include <tools/mapunit.hxx>
46 #include <editeng/unonrule.hxx>
48 #define DEF_WRITER_LSPACE 500 //Standard Indentation
49 #define DEF_DRAW_LSPACE 800 //Standard Indentation
51 #define NUMITEM_VERSION_03 0x03
52 #define NUMITEM_VERSION_04 0x04
54 using namespace ::com::sun::star;
55 using namespace ::com::sun::star::lang;
56 using namespace ::com::sun::star::uno;
57 using namespace ::com::sun::star::text;
58 using namespace ::com::sun::star::beans;
59 using namespace ::com::sun::star::style;
61 sal_Int32 SvxNumberType::nRefCount = 0;
62 com::sun::star::uno::Reference<com::sun::star::text::XNumberingFormatter> SvxNumberType::xFormatter = 0;
63 static void lcl_getFormatter(com::sun::star::uno::Reference<com::sun::star::text::XNumberingFormatter>& _xFormatter)
65 if(!_xFormatter.is())
67 try
69 Reference<XComponentContext> xContext( ::comphelper::getProcessComponentContext() );
70 Reference<XDefaultNumberingProvider> xRet = text::DefaultNumberingProvider::create(xContext);
71 _xFormatter = Reference<XNumberingFormatter> (xRet, UNO_QUERY);
73 catch(const Exception&)
75 SAL_WARN("editeng", "service missing: \"com.sun.star.text.DefaultNumberingProvider\"");
80 SvxNumberType::SvxNumberType(sal_Int16 nType) :
81 nNumType(nType),
82 bShowSymbol(true)
84 nRefCount++;
87 SvxNumberType::SvxNumberType(const SvxNumberType& rType) :
88 nNumType(rType.nNumType),
89 bShowSymbol(rType.bShowSymbol)
91 nRefCount++;
94 SvxNumberType::~SvxNumberType()
96 if(!--nRefCount)
97 xFormatter = 0;
100 OUString SvxNumberType::GetNumStr( sal_uLong nNo ) const
102 const LanguageTag& rLang = Application::GetSettings().GetLanguageTag();
103 return GetNumStr( nNo, rLang.getLocale() );
106 OUString SvxNumberType::GetNumStr( sal_uLong nNo, const css::lang::Locale& rLocale ) const
108 lcl_getFormatter(xFormatter);
109 if(!xFormatter.is())
110 return OUString();
112 if(bShowSymbol)
114 switch(nNumType)
116 case NumberingType::CHAR_SPECIAL:
117 case NumberingType::BITMAP:
118 break;
119 default:
121 // '0' allowed for ARABIC numberings
122 if(NumberingType::ARABIC == nNumType && 0 == nNo )
123 return OUString('0');
124 else
126 Sequence< PropertyValue > aProperties(2);
127 PropertyValue* pValues = aProperties.getArray();
128 pValues[0].Name = "NumberingType";
129 pValues[0].Value <<= nNumType;
130 pValues[1].Name = "Value";
131 pValues[1].Value <<= (sal_Int32)nNo;
135 return xFormatter->makeNumberingString( aProperties, rLocale );
137 catch(const Exception&)
144 return OUString();
147 SvxNumberFormat::SvxNumberFormat( sal_Int16 eType,
148 SvxNumPositionAndSpaceMode ePositionAndSpaceMode )
149 : SvxNumberType(eType),
150 eNumAdjust(SVX_ADJUST_LEFT),
151 nInclUpperLevels(0),
152 nStart(1),
153 cBullet(SVX_DEF_BULLET),
154 nBulletRelSize(100),
155 nBulletColor(COL_BLACK),
156 mePositionAndSpaceMode( ePositionAndSpaceMode ),
157 nFirstLineOffset(0),
158 nAbsLSpace(0),
159 nCharTextDistance(0),
160 meLabelFollowedBy( LISTTAB ),
161 mnListtabPos( 0 ),
162 mnFirstLineIndent( 0 ),
163 mnIndentAt( 0 ),
164 pGraphicBrush(0),
165 eVertOrient(text::VertOrientation::NONE),
166 pBulletFont(0)
170 SvxNumberFormat::SvxNumberFormat(const SvxNumberFormat& rFormat) :
171 SvxNumberType(rFormat),
172 mePositionAndSpaceMode( rFormat.mePositionAndSpaceMode ),
173 pGraphicBrush(0),
174 pBulletFont(0)
176 *this = rFormat;
179 SvxNumberFormat::SvxNumberFormat( SvStream &rStream )
180 : nStart(0)
181 , nBulletRelSize(100)
182 , nFirstLineOffset(0)
183 , nAbsLSpace(0)
184 , nCharTextDistance(0)
186 sal_uInt16 nTmp16(0);
187 sal_Int32 nTmp32(0);
188 rStream.ReadUInt16( nTmp16 ); // Version number
190 rStream.ReadUInt16( nTmp16 ); SetNumberingType( nTmp16 );
191 rStream.ReadUInt16( nTmp16 ); eNumAdjust = ( SvxAdjust )nTmp16;
192 rStream.ReadUInt16( nTmp16 ); nInclUpperLevels = nTmp16;
193 rStream.ReadUInt16( nStart );
194 rStream.ReadUInt16( nTmp16 ); cBullet = (sal_Unicode)nTmp16;
196 rStream.ReadInt16( nFirstLineOffset );
197 rStream.ReadInt16( nAbsLSpace );
198 rStream.SeekRel(2); //skip old now unused nLSpace;
200 rStream.ReadInt16( nCharTextDistance );
202 sPrefix = rStream.ReadUniOrByteString( rStream.GetStreamCharSet() );
203 sSuffix = rStream.ReadUniOrByteString( rStream.GetStreamCharSet() );
204 sCharStyleName = rStream.ReadUniOrByteString( rStream.GetStreamCharSet() );
206 sal_uInt16 hasGraphicBrush = 0;
207 rStream.ReadUInt16( hasGraphicBrush );
208 if ( hasGraphicBrush )
210 pGraphicBrush = new SvxBrushItem( SID_ATTR_BRUSH );
211 pGraphicBrush = static_cast<SvxBrushItem*>(pGraphicBrush->Create( rStream, BRUSH_GRAPHIC_VERSION ));
213 else pGraphicBrush = 0;
214 rStream.ReadUInt16( nTmp16 ); eVertOrient = nTmp16;
216 sal_uInt16 hasBulletFont = 0;
217 rStream.ReadUInt16( hasBulletFont );
218 if ( hasBulletFont )
220 pBulletFont = new vcl::Font( );
221 ReadFont( rStream, *pBulletFont );
223 else pBulletFont = NULL;
224 ReadPair( rStream, aGraphicSize );
226 ReadColor( rStream, nBulletColor );
227 rStream.ReadUInt16( nBulletRelSize );
228 rStream.ReadUInt16( nTmp16 ); SetShowSymbol( nTmp16 );
230 rStream.ReadUInt16( nTmp16 ); mePositionAndSpaceMode = ( SvxNumPositionAndSpaceMode )nTmp16;
231 rStream.ReadUInt16( nTmp16 ); meLabelFollowedBy = ( LabelFollowedBy )nTmp16;
232 rStream.ReadInt32( nTmp32 ); mnListtabPos = nTmp32;
233 rStream.ReadInt32( nTmp32 ); mnFirstLineIndent = nTmp32;
234 rStream.ReadInt32( nTmp32 ); mnIndentAt = nTmp32;
237 SvxNumberFormat::~SvxNumberFormat()
239 delete pGraphicBrush;
240 delete pBulletFont;
243 SvStream& SvxNumberFormat::Store(SvStream &rStream, FontToSubsFontConverter pConverter)
245 if(pConverter && pBulletFont)
247 cBullet = ConvertFontToSubsFontChar(pConverter, cBullet);
248 OUString sFontName = GetFontToSubsFontName(pConverter);
249 pBulletFont->SetName(sFontName);
252 rStream.WriteUInt16( NUMITEM_VERSION_04 );
254 rStream.WriteUInt16( GetNumberingType() );
255 rStream.WriteUInt16( eNumAdjust );
256 rStream.WriteUInt16( nInclUpperLevels );
257 rStream.WriteUInt16( nStart );
258 rStream.WriteUInt16( cBullet );
260 rStream.WriteInt16( nFirstLineOffset );
261 rStream.WriteInt16( nAbsLSpace );
262 rStream.WriteInt16( 0 ); // write a dummy for old now unused nLSpace
264 rStream.WriteInt16( nCharTextDistance );
265 rtl_TextEncoding eEnc = osl_getThreadTextEncoding();
266 rStream.WriteUniOrByteString(sPrefix, eEnc);
267 rStream.WriteUniOrByteString(sSuffix, eEnc);
268 rStream.WriteUniOrByteString(sCharStyleName, eEnc);
269 if(pGraphicBrush)
271 rStream.WriteUInt16( 1 );
273 // in SD or SI force bullet itself to be stored,
274 // for that purpose throw away link when link and graphic
275 // are present, so Brush save is forced
276 if(!pGraphicBrush->GetGraphicLink().isEmpty() && pGraphicBrush->GetGraphic())
278 pGraphicBrush->SetGraphicLink("");
281 pGraphicBrush->Store(rStream, BRUSH_GRAPHIC_VERSION);
283 else
284 rStream.WriteUInt16( 0 );
286 rStream.WriteUInt16( eVertOrient );
287 if(pBulletFont)
289 rStream.WriteUInt16( 1 );
290 WriteFont( rStream, *pBulletFont );
292 else
293 rStream.WriteUInt16( 0 );
294 WritePair( rStream, aGraphicSize );
296 Color nTempColor = nBulletColor;
297 if(COL_AUTO == nBulletColor.GetColor())
298 nTempColor = COL_BLACK;
299 WriteColor( rStream, nTempColor );
300 rStream.WriteUInt16( nBulletRelSize );
301 rStream.WriteUInt16( sal_uInt16(IsShowSymbol()) );
303 rStream.WriteUInt16( mePositionAndSpaceMode );
304 rStream.WriteUInt16( meLabelFollowedBy );
305 rStream.WriteInt32( mnListtabPos );
306 rStream.WriteInt32( mnFirstLineIndent );
307 rStream.WriteInt32( mnIndentAt );
309 return rStream;
312 SvxNumberFormat& SvxNumberFormat::operator=( const SvxNumberFormat& rFormat )
314 if (& rFormat == this) { return *this; }
316 SetNumberingType(rFormat.GetNumberingType());
317 eNumAdjust = rFormat.eNumAdjust ;
318 nInclUpperLevels = rFormat.nInclUpperLevels ;
319 nStart = rFormat.nStart ;
320 cBullet = rFormat.cBullet ;
321 mePositionAndSpaceMode = rFormat.mePositionAndSpaceMode;
322 nFirstLineOffset = rFormat.nFirstLineOffset;
323 nAbsLSpace = rFormat.nAbsLSpace ;
324 nCharTextDistance = rFormat.nCharTextDistance ;
325 meLabelFollowedBy = rFormat.meLabelFollowedBy;
326 mnListtabPos = rFormat.mnListtabPos;
327 mnFirstLineIndent = rFormat.mnFirstLineIndent;
328 mnIndentAt = rFormat.mnIndentAt;
329 eVertOrient = rFormat.eVertOrient ;
330 sPrefix = rFormat.sPrefix ;
331 sSuffix = rFormat.sSuffix ;
332 aGraphicSize = rFormat.aGraphicSize ;
333 nBulletColor = rFormat.nBulletColor ;
334 nBulletRelSize = rFormat.nBulletRelSize;
335 SetShowSymbol(rFormat.IsShowSymbol());
336 sCharStyleName = rFormat.sCharStyleName;
337 DELETEZ(pGraphicBrush);
338 if(rFormat.pGraphicBrush)
340 pGraphicBrush = new SvxBrushItem(*rFormat.pGraphicBrush);
341 pGraphicBrush->SetDoneLink( LINK( this, SvxNumberFormat, GraphicArrived) );
343 DELETEZ(pBulletFont);
344 if(rFormat.pBulletFont)
345 pBulletFont = new vcl::Font(*rFormat.pBulletFont);
346 return *this;
349 bool SvxNumberFormat::operator==( const SvxNumberFormat& rFormat) const
351 if( GetNumberingType() != rFormat.GetNumberingType() ||
352 eNumAdjust != rFormat.eNumAdjust ||
353 nInclUpperLevels != rFormat.nInclUpperLevels ||
354 nStart != rFormat.nStart ||
355 cBullet != rFormat.cBullet ||
356 mePositionAndSpaceMode != rFormat.mePositionAndSpaceMode ||
357 nFirstLineOffset != rFormat.nFirstLineOffset ||
358 nAbsLSpace != rFormat.nAbsLSpace ||
359 nCharTextDistance != rFormat.nCharTextDistance ||
360 meLabelFollowedBy != rFormat.meLabelFollowedBy ||
361 mnListtabPos != rFormat.mnListtabPos ||
362 mnFirstLineIndent != rFormat.mnFirstLineIndent ||
363 mnIndentAt != rFormat.mnIndentAt ||
364 eVertOrient != rFormat.eVertOrient ||
365 sPrefix != rFormat.sPrefix ||
366 sSuffix != rFormat.sSuffix ||
367 aGraphicSize != rFormat.aGraphicSize ||
368 nBulletColor != rFormat.nBulletColor ||
369 nBulletRelSize != rFormat.nBulletRelSize ||
370 IsShowSymbol() != rFormat.IsShowSymbol() ||
371 sCharStyleName != rFormat.sCharStyleName
373 return false;
374 if (
375 (pGraphicBrush && !rFormat.pGraphicBrush) ||
376 (!pGraphicBrush && rFormat.pGraphicBrush) ||
377 (pGraphicBrush && *pGraphicBrush != *rFormat.pGraphicBrush)
380 return false;
382 if (
383 (pBulletFont && !rFormat.pBulletFont) ||
384 (!pBulletFont && rFormat.pBulletFont) ||
385 (pBulletFont && *pBulletFont != *rFormat.pBulletFont)
388 return false;
390 return true;
393 void SvxNumberFormat::SetGraphicBrush( const SvxBrushItem* pBrushItem,
394 const Size* pSize, const sal_Int16* pOrient)
396 if(!pBrushItem)
398 delete pGraphicBrush;
399 pGraphicBrush = 0;
401 else if ( !pGraphicBrush || (pGraphicBrush && !(*pBrushItem == *pGraphicBrush)) )
403 delete pGraphicBrush;
404 pGraphicBrush = static_cast<SvxBrushItem*>(pBrushItem->Clone());
405 pGraphicBrush->SetDoneLink( LINK( this, SvxNumberFormat, GraphicArrived) );
408 if(pOrient)
409 eVertOrient = *pOrient;
410 else
411 eVertOrient = text::VertOrientation::NONE;
412 if(pSize)
413 aGraphicSize = *pSize;
414 else
415 aGraphicSize.Width() = aGraphicSize.Height() = 0;
418 void SvxNumberFormat::SetGraphic( const OUString& rName )
420 if( pGraphicBrush && pGraphicBrush->GetGraphicLink() == rName )
421 return ;
423 delete pGraphicBrush;
424 pGraphicBrush = new SvxBrushItem( rName, "", GPOS_AREA, 0 );
425 pGraphicBrush->SetDoneLink( LINK( this, SvxNumberFormat, GraphicArrived) );
426 if( eVertOrient == text::VertOrientation::NONE )
427 eVertOrient = text::VertOrientation::TOP;
429 aGraphicSize.Width() = aGraphicSize.Height() = 0;
432 void SvxNumberFormat::SetVertOrient(sal_Int16 eSet)
434 eVertOrient = eSet;
437 sal_Int16 SvxNumberFormat::GetVertOrient() const
439 return eVertOrient;
442 void SvxNumberFormat::SetBulletFont(const vcl::Font* pFont)
444 delete pBulletFont;
445 pBulletFont = pFont ? new vcl::Font(*pFont): 0;
448 void SvxNumberFormat::SetPositionAndSpaceMode( SvxNumPositionAndSpaceMode ePositionAndSpaceMode )
450 mePositionAndSpaceMode = ePositionAndSpaceMode;
453 short SvxNumberFormat::GetAbsLSpace() const
455 return mePositionAndSpaceMode == LABEL_WIDTH_AND_POSITION
456 ? nAbsLSpace
457 : static_cast<short>( GetFirstLineIndent() + GetIndentAt() );
459 short SvxNumberFormat::GetFirstLineOffset() const
461 return mePositionAndSpaceMode == LABEL_WIDTH_AND_POSITION
462 ? nFirstLineOffset
463 : static_cast<short>( GetFirstLineIndent() );
465 short SvxNumberFormat::GetCharTextDistance() const
467 return mePositionAndSpaceMode == LABEL_WIDTH_AND_POSITION ? nCharTextDistance : 0;
470 void SvxNumberFormat::SetLabelFollowedBy( const LabelFollowedBy eLabelFollowedBy )
472 meLabelFollowedBy = eLabelFollowedBy;
474 void SvxNumberFormat::SetListtabPos( const long nListtabPos )
476 mnListtabPos = nListtabPos;
478 void SvxNumberFormat::SetFirstLineIndent( const long nFirstLineIndent )
480 mnFirstLineIndent = nFirstLineIndent;
482 void SvxNumberFormat::SetIndentAt( const long nIndentAt )
484 mnIndentAt = nIndentAt;
487 IMPL_LINK_NOARG( SvxNumberFormat, GraphicArrived )
489 // if necessary, set the GrfSize:
490 if( !aGraphicSize.Width() || !aGraphicSize.Height() )
492 const Graphic* pGrf = pGraphicBrush->GetGraphic();
493 if( pGrf )
494 aGraphicSize = SvxNumberFormat::GetGraphicSizeMM100( pGrf );
496 NotifyGraphicArrived();
497 return 0;
500 void SvxNumberFormat::NotifyGraphicArrived()
504 Size SvxNumberFormat::GetGraphicSizeMM100(const Graphic* pGraphic)
506 const MapMode aMapMM100( MAP_100TH_MM );
507 const Size& rSize = pGraphic->GetPrefSize();
508 Size aRetSize;
509 if ( pGraphic->GetPrefMapMode().GetMapUnit() == MAP_PIXEL )
511 OutputDevice* pOutDev = Application::GetDefaultDevice();
512 MapMode aOldMap( pOutDev->GetMapMode() );
513 pOutDev->SetMapMode( aMapMM100 );
514 aRetSize = pOutDev->PixelToLogic( rSize );
515 pOutDev->SetMapMode( aOldMap );
517 else
518 aRetSize = OutputDevice::LogicToLogic( rSize, pGraphic->GetPrefMapMode(), aMapMM100 );
519 return aRetSize;
522 OUString SvxNumberFormat::CreateRomanString( sal_uLong nNo, bool bUpper )
524 nNo %= 4000; // more can not be displayed
525 // i, ii, iii, iv, v, vi, vii, vii, viii, ix
526 // (Dummy),1000,500,100,50,10,5,1
527 const char *cRomanArr = bUpper
528 ? "MDCLXVI--" // +2 Dummy entries!
529 : "mdclxvi--"; // +2 Dummy entries!
531 OUString sRet;
532 sal_uInt16 nMask = 1000;
533 while( nMask )
535 sal_uInt8 nZahl = sal_uInt8(nNo / nMask);
536 sal_uInt8 nDiff = 1;
537 nNo %= nMask;
539 if( 5 < nZahl )
541 if( nZahl < 9 )
542 sRet += OUString(*(cRomanArr-1));
543 ++nDiff;
544 nZahl -= 5;
546 switch( nZahl )
548 case 3: { sRet += OUString(*cRomanArr); }
549 case 2: { sRet += OUString(*cRomanArr); }
550 case 1: { sRet += OUString(*cRomanArr); }
551 break;
553 case 4: {
554 sRet += OUString(*cRomanArr);
555 sRet += OUString(*(cRomanArr-nDiff));
557 break;
558 case 5: { sRet += OUString(*(cRomanArr-nDiff)); }
559 break;
562 nMask /= 10; // for the next decade
563 cRomanArr += 2;
565 return sRet;
568 OUString SvxNumberFormat::GetCharFormatName()const
570 return sCharStyleName;
573 sal_Int32 SvxNumRule::nRefCount = 0;
574 static SvxNumberFormat* pStdNumFmt = 0;
575 static SvxNumberFormat* pStdOutlineNumFmt = 0;
576 SvxNumRule::SvxNumRule( SvxNumRuleFlags nFeatures,
577 sal_uInt16 nLevels,
578 bool bCont,
579 SvxNumRuleType eType,
580 SvxNumberFormat::SvxNumPositionAndSpaceMode
581 eDefaultNumberFormatPositionAndSpaceMode )
582 : nLevelCount(nLevels),
583 nFeatureFlags(nFeatures),
584 eNumberingType(eType),
585 bContinuousNumbering(bCont)
587 ++nRefCount;
588 for(sal_uInt16 i = 0; i < SVX_MAX_NUM; i++)
590 if(i < nLevels)
592 aFmts[i] = new SvxNumberFormat(SVX_NUM_CHARS_UPPER_LETTER);
593 // It is a distinction between writer and draw
594 if(nFeatures & SvxNumRuleFlags::CONTINUOUS)
596 if ( eDefaultNumberFormatPositionAndSpaceMode ==
597 SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
599 aFmts[i]->SetAbsLSpace( convertMm100ToTwip(DEF_WRITER_LSPACE * (i+1)) );
600 aFmts[i]->SetFirstLineOffset(convertMm100ToTwip(-DEF_WRITER_LSPACE));
602 else if ( eDefaultNumberFormatPositionAndSpaceMode ==
603 SvxNumberFormat::LABEL_ALIGNMENT )
605 // first line indent of general numbering in inch: -0,25 inch
606 const long cFirstLineIndent = -1440/4;
607 // indent values of general numbering in inch:
608 // 0,5 0,75 1,0 1,25 1,5
609 // 1,75 2,0 2,25 2,5 2,75
610 const long cIndentAt = 1440/4;
611 aFmts[i]->SetPositionAndSpaceMode( SvxNumberFormat::LABEL_ALIGNMENT );
612 aFmts[i]->SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
613 aFmts[i]->SetListtabPos( cIndentAt * (i+2) );
614 aFmts[i]->SetFirstLineIndent( cFirstLineIndent );
615 aFmts[i]->SetIndentAt( cIndentAt * (i+2) );
618 else
620 aFmts[i]->SetAbsLSpace( DEF_DRAW_LSPACE * (i) );
623 else
624 aFmts[i] = 0;
625 aFmtsSet[i] = false;
629 SvxNumRule::SvxNumRule(const SvxNumRule& rCopy)
631 ++nRefCount;
632 aLocale = rCopy.aLocale;
633 nLevelCount = rCopy.nLevelCount ;
634 nFeatureFlags = rCopy.nFeatureFlags ;
635 bContinuousNumbering = rCopy.bContinuousNumbering;
636 eNumberingType = rCopy.eNumberingType;
637 memset( aFmts, 0, sizeof( aFmts ));
638 for(sal_uInt16 i = 0; i < SVX_MAX_NUM; i++)
640 if(rCopy.aFmts[i])
641 aFmts[i] = new SvxNumberFormat(*rCopy.aFmts[i]);
642 else
643 aFmts[i] = 0;
644 aFmtsSet[i] = rCopy.aFmtsSet[i];
648 SvxNumRule::SvxNumRule( SvStream &rStream )
649 : nLevelCount(0)
651 sal_uInt16 nTmp16(0);
652 rStream.ReadUInt16( nTmp16 ); // NUM_ITEM_VERSION
653 rStream.ReadUInt16( nLevelCount );
655 // first nFeatureFlags of old Versions
656 rStream.ReadUInt16( nTmp16 ); nFeatureFlags = static_cast<SvxNumRuleFlags>(nTmp16);
657 rStream.ReadUInt16( nTmp16 ); bContinuousNumbering = nTmp16;
658 rStream.ReadUInt16( nTmp16 ); eNumberingType = ( SvxNumRuleType )nTmp16;
660 for (sal_uInt16 i = 0; i < SVX_MAX_NUM; i++)
662 rStream.ReadUInt16( nTmp16 );
663 bool hasNumberingFormat = nTmp16 & 1;
664 aFmtsSet[i] = nTmp16 & 2; // fdo#68648 reset flag
665 if ( hasNumberingFormat ){
666 aFmts[i] = new SvxNumberFormat( rStream );
668 else
670 aFmts[i] = 0;
671 aFmtsSet[i] = false; // actually only false is valid
674 //second nFeatureFlags for new versions
675 rStream.ReadUInt16( nTmp16 ); nFeatureFlags = static_cast<SvxNumRuleFlags>(nTmp16);
678 SvStream& SvxNumRule::Store( SvStream &rStream )
680 rStream.WriteUInt16( NUMITEM_VERSION_03 );
681 rStream.WriteUInt16( nLevelCount );
682 //first save of nFeatureFlags for old versions
683 rStream.WriteUInt16( static_cast<sal_uInt16>(nFeatureFlags) );
684 rStream.WriteUInt16( sal_uInt16(bContinuousNumbering) );
685 rStream.WriteUInt16( static_cast<sal_uInt16>(eNumberingType) );
687 FontToSubsFontConverter pConverter = 0;
688 bool bConvertBulletFont = ( rStream.GetVersion() <= SOFFICE_FILEFORMAT_50 ) && ( rStream.GetVersion() );
689 for(sal_uInt16 i = 0; i < SVX_MAX_NUM; i++)
691 sal_uInt16 nSetFlag(aFmtsSet[i] ? 2 : 0); // fdo#68648 store that too
692 if(aFmts[i])
694 rStream.WriteUInt16( 1 | nSetFlag );
695 if(bConvertBulletFont && aFmts[i]->GetBulletFont())
697 if(!pConverter)
698 pConverter =
699 CreateFontToSubsFontConverter(aFmts[i]->GetBulletFont()->GetName(),
700 FontToSubsFontFlags::EXPORT|FontToSubsFontFlags::ONLYOLDSOSYMBOLFONTS);
702 aFmts[i]->Store(rStream, pConverter);
704 else
705 rStream.WriteUInt16( 0 | nSetFlag );
707 //second save of nFeatureFlags for new versions
708 rStream.WriteUInt16( static_cast<sal_uInt16>(nFeatureFlags) );
709 if(pConverter)
710 DestroyFontToSubsFontConverter(pConverter);
712 return rStream;
714 SvxNumRule::~SvxNumRule()
716 for(sal_uInt16 i = 0; i < SVX_MAX_NUM; i++)
717 delete aFmts[i];
718 if(!--nRefCount)
720 DELETEZ(pStdNumFmt);
721 DELETEZ(pStdOutlineNumFmt);
725 SvxNumRule& SvxNumRule::operator=( const SvxNumRule& rCopy )
727 nLevelCount = rCopy.nLevelCount;
728 nFeatureFlags = rCopy.nFeatureFlags;
729 bContinuousNumbering = rCopy.bContinuousNumbering;
730 eNumberingType = rCopy.eNumberingType;
731 for(sal_uInt16 i = 0; i < SVX_MAX_NUM; i++)
733 delete aFmts[i];
734 if(rCopy.aFmts[i])
735 aFmts[i] = new SvxNumberFormat(*rCopy.aFmts[i]);
736 else
737 aFmts[i] = 0;
738 aFmtsSet[i] = rCopy.aFmtsSet[i];
740 return *this;
743 bool SvxNumRule::operator==( const SvxNumRule& rCopy) const
745 if(nLevelCount != rCopy.nLevelCount ||
746 nFeatureFlags != rCopy.nFeatureFlags ||
747 bContinuousNumbering != rCopy.bContinuousNumbering ||
748 eNumberingType != rCopy.eNumberingType)
749 return false;
750 for(sal_uInt16 i = 0; i < nLevelCount; i++)
752 if (
753 (aFmtsSet[i] != rCopy.aFmtsSet[i]) ||
754 (!aFmts[i] && rCopy.aFmts[i]) ||
755 (aFmts[i] && !rCopy.aFmts[i]) ||
756 (aFmts[i] && *aFmts[i] != *rCopy.aFmts[i])
759 return false;
762 return true;
765 const SvxNumberFormat* SvxNumRule::Get(sal_uInt16 nLevel)const
767 DBG_ASSERT(nLevel < SVX_MAX_NUM, "Wrong Level" );
768 if( nLevel < SVX_MAX_NUM )
769 return aFmtsSet[nLevel] ? aFmts[nLevel] : 0;
770 else
771 return 0;
774 const SvxNumberFormat& SvxNumRule::GetLevel(sal_uInt16 nLevel)const
776 if(!pStdNumFmt)
778 pStdNumFmt = new SvxNumberFormat(SVX_NUM_ARABIC);
779 pStdOutlineNumFmt = new SvxNumberFormat(SVX_NUM_NUMBER_NONE);
782 DBG_ASSERT(nLevel < SVX_MAX_NUM, "Wrong Level" );
784 return ( ( nLevel < SVX_MAX_NUM ) && aFmts[nLevel] ) ?
785 *aFmts[nLevel] : eNumberingType == SvxNumRuleType::NUMBERING ?
786 *pStdNumFmt : *pStdOutlineNumFmt;
789 void SvxNumRule::SetLevel( sal_uInt16 i, const SvxNumberFormat& rNumFmt, bool bIsValid )
791 DBG_ASSERT(i < SVX_MAX_NUM, "Wrong Level" );
793 if( (i < SVX_MAX_NUM) )
795 bool bReplace = !aFmtsSet[i];
796 if (!bReplace)
798 const SvxNumberFormat *pFmt = Get(i);
799 bReplace = pFmt == nullptr || rNumFmt != *pFmt;
802 if (bReplace)
804 delete aFmts[i];
805 aFmts[i] = new SvxNumberFormat(rNumFmt);
806 aFmtsSet[i] = bIsValid;
811 void SvxNumRule::SetLevel(sal_uInt16 nLevel, const SvxNumberFormat* pFmt)
813 DBG_ASSERT(nLevel < SVX_MAX_NUM, "Wrong Level" );
815 if( nLevel < SVX_MAX_NUM )
817 aFmtsSet[nLevel] = 0 != pFmt;
818 if(pFmt)
819 SetLevel(nLevel, *pFmt);
820 else
822 delete aFmts[nLevel];
823 aFmts[nLevel] = 0;
828 OUString SvxNumRule::MakeNumString( const SvxNodeNum& rNum, bool bInclStrings ) const
830 OUString aStr;
831 if( SVX_NO_NUM > rNum.GetLevel() && !( SVX_NO_NUMLEVEL & rNum.GetLevel() ) )
833 const SvxNumberFormat& rMyNFmt = GetLevel( rNum.GetLevel() );
834 if( SVX_NUM_NUMBER_NONE != rMyNFmt.GetNumberingType() )
836 sal_uInt8 i = rNum.GetLevel();
838 if( !IsContinuousNumbering() &&
839 1 < rMyNFmt.GetIncludeUpperLevels() ) // only on own level?
841 sal_uInt8 n = rMyNFmt.GetIncludeUpperLevels();
842 if( 1 < n )
844 if( i+1 >= n )
845 i -= n - 1;
846 else
847 i = 0;
851 for( ; i <= rNum.GetLevel(); ++i )
853 const SvxNumberFormat& rNFmt = GetLevel( i );
854 if( SVX_NUM_NUMBER_NONE == rNFmt.GetNumberingType() )
856 continue;
859 bool bDot = true;
860 if( rNum.GetLevelVal()[ i ] )
862 if(SVX_NUM_BITMAP != rNFmt.GetNumberingType())
863 aStr += rNFmt.GetNumStr( rNum.GetLevelVal()[ i ], aLocale );
864 else
865 bDot = false;
867 else
868 aStr += "0"; // all 0-levels are a 0
869 if( i != rNum.GetLevel() && bDot)
870 aStr += ".";
874 if( bInclStrings )
876 aStr = rMyNFmt.GetPrefix() + aStr + rMyNFmt.GetSuffix();
879 return aStr;
882 // changes linked to embedded bitmaps
883 bool SvxNumRule::UnLinkGraphics()
885 bool bRet = false;
886 for(sal_uInt16 i = 0; i < GetLevelCount(); i++)
888 SvxNumberFormat aFmt(GetLevel(i));
889 const SvxBrushItem* pBrush = aFmt.GetBrush();
890 const Graphic* pGraphic = NULL;
891 if(SVX_NUM_BITMAP == aFmt.GetNumberingType())
893 if(pBrush &&
894 !pBrush->GetGraphicLink().isEmpty() &&
895 0 != (pGraphic = pBrush->GetGraphic()))
897 SvxBrushItem aTempItem(*pBrush);
898 aTempItem.SetGraphicLink("");
899 aTempItem.SetGraphic(*pGraphic);
900 sal_Int16 eOrient = aFmt.GetVertOrient();
901 aFmt.SetGraphicBrush( &aTempItem, &aFmt.GetGraphicSize(), &eOrient );
902 bRet = true;
905 else if((SVX_NUM_BITMAP|LINK_TOKEN) == aFmt.GetNumberingType())
906 aFmt.SetNumberingType(SVX_NUM_BITMAP);
907 SetLevel(i, aFmt);
909 return bRet;
912 SvxNumBulletItem::SvxNumBulletItem(SvxNumRule& rRule) :
913 SfxPoolItem(SID_ATTR_NUMBERING_RULE),
914 pNumRule(new SvxNumRule(rRule))
918 SvxNumBulletItem::SvxNumBulletItem(SvxNumRule& rRule, sal_uInt16 _nWhich ) :
919 SfxPoolItem(_nWhich),
920 pNumRule(new SvxNumRule(rRule))
924 SfxPoolItem* SvxNumBulletItem::Create(SvStream &rStream, sal_uInt16 /*nItemVersion*/ ) const
926 SvxNumRule aNumRule( rStream );
927 return new SvxNumBulletItem( aNumRule, EE_PARA_NUMBULLET );
930 SvxNumBulletItem::SvxNumBulletItem(const SvxNumBulletItem& rCopy) :
931 SfxPoolItem(rCopy.Which())
933 pNumRule = new SvxNumRule(*rCopy.pNumRule);
936 SvxNumBulletItem::~SvxNumBulletItem()
938 delete pNumRule;
941 bool SvxNumBulletItem::operator==( const SfxPoolItem& rCopy) const
943 return *pNumRule == *static_cast<const SvxNumBulletItem&>(rCopy).pNumRule;
946 SfxPoolItem* SvxNumBulletItem::Clone( SfxItemPool * ) const
948 return new SvxNumBulletItem(*this);
951 sal_uInt16 SvxNumBulletItem::GetVersion( sal_uInt16 /*nFileVersion*/ ) const
953 return NUMITEM_VERSION_03;
956 SvStream& SvxNumBulletItem::Store(SvStream &rStream, sal_uInt16 /*nItemVersion*/ )const
958 pNumRule->Store(rStream);
959 return rStream;
962 bool SvxNumBulletItem::QueryValue( com::sun::star::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const
964 rVal <<= SvxCreateNumRule( pNumRule );
965 return true;
968 bool SvxNumBulletItem::PutValue( const com::sun::star::uno::Any& rVal, sal_uInt8 /*nMemberId*/ )
970 uno::Reference< container::XIndexReplace > xRule;
971 if( rVal >>= xRule )
975 SvxNumRule* pNewRule = new SvxNumRule( SvxGetNumRule( xRule ) );
976 if( pNewRule->GetLevelCount() != pNumRule->GetLevelCount() ||
977 pNewRule->GetNumRuleType() != pNumRule->GetNumRuleType() )
979 SvxNumRule* pConverted = SvxConvertNumRule( pNewRule, pNumRule->GetLevelCount(), pNumRule->GetNumRuleType() );
980 delete pNewRule;
981 pNewRule = pConverted;
983 delete pNumRule;
984 pNumRule = pNewRule;
985 return true;
987 catch(const lang::IllegalArgumentException&)
991 return false;
994 SvxNumRule* SvxConvertNumRule( const SvxNumRule* pRule, sal_uInt16 nLevels, SvxNumRuleType eType )
996 const sal_uInt16 nSrcLevels = pRule->GetLevelCount();
997 SvxNumRule* pNewRule = new SvxNumRule( pRule->GetFeatureFlags(), nLevels, pRule->IsContinuousNumbering(), eType );
999 for( sal_uInt16 nLevel = 0; (nLevel < nLevels) && (nLevel < nSrcLevels); nLevel++ )
1000 pNewRule->SetLevel( nLevel, pRule->GetLevel( nLevel ) );
1002 return pNewRule;
1005 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */