Bump version to 4.1-6
[LibreOffice.git] / editeng / source / items / numitem.cxx
blob7090abc4b268f5d407b6e76c057270188715b253
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 <editeng/editids.hrc>
29 #include <editeng/editrids.hrc>
30 #include <editeng/numdef.hxx>
31 #include <editeng/eeitem.hxx>
32 #include <vcl/graph.hxx>
33 #include <vcl/window.hxx>
34 #include <vcl/svapp.hxx>
35 #include <editeng/unolingu.hxx>
36 #include <com/sun/star/text/XNumberingFormatter.hpp>
37 #include <com/sun/star/text/DefaultNumberingProvider.hpp>
38 #include <com/sun/star/text/XDefaultNumberingProvider.hpp>
39 #include <com/sun/star/style/NumberingType.hpp>
40 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <com/sun/star/beans/PropertyValue.hpp>
42 #include <comphelper/processfactory.hxx>
44 #include <editeng/unonrule.hxx>
46 #define MM100_TO_TWIP(MM100) ((MM100*72L+63L)/127L)
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(sal_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 String SvxNumberType::GetNumStr( sal_uLong nNo ) const
102 const LanguageTag& rLang = Application::GetSettings().GetLanguageTag();
103 return GetNumStr( nNo, rLang.getLocale() );
106 String SvxNumberType::GetNumStr( sal_uLong nNo, const Locale& rLocale ) const
108 lcl_getFormatter(xFormatter);
109 String aTmpStr;
110 if(!xFormatter.is())
111 return aTmpStr;
113 if(bShowSymbol)
115 switch(nNumType)
117 case NumberingType::CHAR_SPECIAL:
118 case NumberingType::BITMAP:
119 break;
120 default:
122 // '0' allowed for ARABIC numberings
123 if(NumberingType::ARABIC == nNumType && 0 == nNo )
124 aTmpStr = '0';
125 else
127 Sequence< PropertyValue > aProperties(2);
128 PropertyValue* pValues = aProperties.getArray();
129 pValues[0].Name = OUString("NumberingType");
130 pValues[0].Value <<= nNumType;
131 pValues[1].Name = OUString("Value");
132 pValues[1].Value <<= (sal_Int32)nNo;
136 aTmpStr = xFormatter->makeNumberingString( aProperties, rLocale );
138 catch(const Exception&)
145 return aTmpStr;
148 SvxNumberFormat::SvxNumberFormat( sal_Int16 eType,
149 SvxNumPositionAndSpaceMode ePositionAndSpaceMode )
150 : SvxNumberType(eType),
151 eNumAdjust(SVX_ADJUST_LEFT),
152 nInclUpperLevels(0),
153 nStart(1),
154 cBullet(SVX_DEF_BULLET),
155 nBulletRelSize(100),
156 nBulletColor(COL_BLACK),
157 mePositionAndSpaceMode( ePositionAndSpaceMode ),
158 nFirstLineOffset(0),
159 nAbsLSpace(0),
160 nLSpace(0),
161 nCharTextDistance(0),
162 meLabelFollowedBy( LISTTAB ),
163 mnListtabPos( 0 ),
164 mnFirstLineIndent( 0 ),
165 mnIndentAt( 0 ),
166 pGraphicBrush(0),
167 eVertOrient(text::VertOrientation::NONE),
168 pBulletFont(0)
172 SvxNumberFormat::SvxNumberFormat(const SvxNumberFormat& rFormat) :
173 SvxNumberType(rFormat),
174 mePositionAndSpaceMode( rFormat.mePositionAndSpaceMode ),
175 pGraphicBrush(0),
176 pBulletFont(0)
178 *this = rFormat;
181 SvxNumberFormat::SvxNumberFormat( SvStream &rStream )
183 sal_uInt16 nTmp16;
184 sal_Int32 nTmp32;
185 rStream >> nTmp16; // Version number
187 rStream >> nTmp16; SetNumberingType( nTmp16 );
188 rStream >> nTmp16; eNumAdjust = ( SvxAdjust )nTmp16;
189 rStream >> nTmp16; nInclUpperLevels = nTmp16;
190 rStream >> nStart;
191 rStream >> nTmp16; cBullet = (sal_Unicode)nTmp16;
193 rStream >> nFirstLineOffset;
194 rStream >> nAbsLSpace;
195 rStream >> nLSpace;
197 rStream >> nCharTextDistance;
199 sPrefix = rStream.ReadUniOrByteString( rStream.GetStreamCharSet() );
200 sSuffix = rStream.ReadUniOrByteString( rStream.GetStreamCharSet() );
201 sCharStyleName = rStream.ReadUniOrByteString( rStream.GetStreamCharSet() );
203 sal_uInt16 hasGraphicBrush = 0;
204 rStream >> hasGraphicBrush;
205 if ( hasGraphicBrush )
207 pGraphicBrush = new SvxBrushItem( SID_ATTR_BRUSH );
208 pGraphicBrush = (SvxBrushItem*)(pGraphicBrush->Create( rStream, BRUSH_GRAPHIC_VERSION ));
210 else pGraphicBrush = 0;
211 rStream >> nTmp16; eVertOrient = nTmp16;
213 sal_uInt16 hasBulletFont = 0;
214 rStream >> hasBulletFont;
215 if ( hasBulletFont )
217 pBulletFont = new Font( );
218 rStream >> *pBulletFont;
220 else pBulletFont = NULL;
221 rStream >> aGraphicSize;
223 rStream >> nBulletColor;
224 rStream >> nBulletRelSize;
225 rStream >> nTmp16; SetShowSymbol( nTmp16 );
227 rStream >> nTmp16; mePositionAndSpaceMode = ( SvxNumPositionAndSpaceMode )nTmp16;
228 rStream >> nTmp16; meLabelFollowedBy = ( LabelFollowedBy )nTmp16;
229 rStream >> nTmp32; mnListtabPos = nTmp32;
230 rStream >> nTmp32; mnFirstLineIndent = nTmp32;
231 rStream >> nTmp32; mnIndentAt = nTmp32;
234 SvxNumberFormat::~SvxNumberFormat()
236 delete pGraphicBrush;
237 delete pBulletFont;
240 SvStream& SvxNumberFormat::Store(SvStream &rStream, FontToSubsFontConverter pConverter)
242 if(pConverter && pBulletFont)
244 cBullet = ConvertFontToSubsFontChar(pConverter, cBullet);
245 String sFontName = GetFontToSubsFontName(pConverter);
246 pBulletFont->SetName(sFontName);
249 rStream << (sal_uInt16)NUMITEM_VERSION_04;
251 rStream << (sal_uInt16)GetNumberingType();
252 rStream << (sal_uInt16)eNumAdjust;
253 rStream << (sal_uInt16)nInclUpperLevels;
254 rStream << nStart;
255 rStream << (sal_uInt16)cBullet;
257 rStream << nFirstLineOffset;
258 rStream << nAbsLSpace;
259 rStream << nLSpace;
261 rStream << nCharTextDistance;
262 rtl_TextEncoding eEnc = osl_getThreadTextEncoding();
263 rStream.WriteUniOrByteString(sPrefix, eEnc);
264 rStream.WriteUniOrByteString(sSuffix, eEnc);
265 rStream.WriteUniOrByteString(sCharStyleName, eEnc);
266 if(pGraphicBrush)
268 rStream << (sal_uInt16)1;
270 // in SD or SI force bullet itself to be stored,
271 // for that purpose throw away link when link and graphic
272 // are present, so Brush save is forced
273 if(pGraphicBrush->GetGraphicLink() && pGraphicBrush->GetGraphic())
275 String aEmpty;
276 pGraphicBrush->SetGraphicLink(aEmpty);
279 pGraphicBrush->Store(rStream, BRUSH_GRAPHIC_VERSION);
281 else
282 rStream << (sal_uInt16)0;
284 rStream << (sal_uInt16)eVertOrient;
285 if(pBulletFont)
287 rStream << (sal_uInt16)1;
288 rStream << *pBulletFont;
290 else
291 rStream << (sal_uInt16)0;
292 rStream << aGraphicSize;
294 Color nTempColor = nBulletColor;
295 if(COL_AUTO == nBulletColor.GetColor())
296 nTempColor = COL_BLACK;
297 rStream << nTempColor;
298 rStream << nBulletRelSize;
299 rStream << (sal_uInt16)IsShowSymbol();
301 rStream << ( sal_uInt16 ) mePositionAndSpaceMode;
302 rStream << ( sal_uInt16 ) meLabelFollowedBy;
303 rStream << ( sal_Int32 ) mnListtabPos;
304 rStream << ( sal_Int32 ) mnFirstLineIndent;
305 rStream << ( sal_Int32 ) mnIndentAt;
307 return rStream;
310 SvxNumberFormat* SvxNumberFormat::Create( SvStream &rStream )
312 return new SvxNumberFormat( rStream );
315 SvxNumberFormat& SvxNumberFormat::operator=( const SvxNumberFormat& rFormat )
317 if (& rFormat == this) { return *this; }
319 SetNumberingType(rFormat.GetNumberingType());
320 eNumAdjust = rFormat.eNumAdjust ;
321 nInclUpperLevels = rFormat.nInclUpperLevels ;
322 nStart = rFormat.nStart ;
323 cBullet = rFormat.cBullet ;
324 mePositionAndSpaceMode = rFormat.mePositionAndSpaceMode;
325 nFirstLineOffset = rFormat.nFirstLineOffset;
326 nAbsLSpace = rFormat.nAbsLSpace ;
327 nLSpace = rFormat.nLSpace ;
328 nCharTextDistance = rFormat.nCharTextDistance ;
329 meLabelFollowedBy = rFormat.meLabelFollowedBy;
330 mnListtabPos = rFormat.mnListtabPos;
331 mnFirstLineIndent = rFormat.mnFirstLineIndent;
332 mnIndentAt = rFormat.mnIndentAt;
333 eVertOrient = rFormat.eVertOrient ;
334 sPrefix = rFormat.sPrefix ;
335 sSuffix = rFormat.sSuffix ;
336 aGraphicSize = rFormat.aGraphicSize ;
337 nBulletColor = rFormat.nBulletColor ;
338 nBulletRelSize = rFormat.nBulletRelSize;
339 SetShowSymbol(rFormat.IsShowSymbol());
340 sCharStyleName = rFormat.sCharStyleName;
341 DELETEZ(pGraphicBrush);
342 if(rFormat.pGraphicBrush)
344 pGraphicBrush = new SvxBrushItem(*rFormat.pGraphicBrush);
345 pGraphicBrush->SetDoneLink( STATIC_LINK( this, SvxNumberFormat, GraphicArrived) );
347 DELETEZ(pBulletFont);
348 if(rFormat.pBulletFont)
349 pBulletFont = new Font(*rFormat.pBulletFont);
350 return *this;
353 sal_Bool SvxNumberFormat::operator==( const SvxNumberFormat& rFormat) const
355 if( GetNumberingType() != rFormat.GetNumberingType() ||
356 eNumAdjust != rFormat.eNumAdjust ||
357 nInclUpperLevels != rFormat.nInclUpperLevels ||
358 nStart != rFormat.nStart ||
359 cBullet != rFormat.cBullet ||
360 mePositionAndSpaceMode != rFormat.mePositionAndSpaceMode ||
361 nFirstLineOffset != rFormat.nFirstLineOffset ||
362 nAbsLSpace != rFormat.nAbsLSpace ||
363 nLSpace != rFormat.nLSpace ||
364 nCharTextDistance != rFormat.nCharTextDistance ||
365 meLabelFollowedBy != rFormat.meLabelFollowedBy ||
366 mnListtabPos != rFormat.mnListtabPos ||
367 mnFirstLineIndent != rFormat.mnFirstLineIndent ||
368 mnIndentAt != rFormat.mnIndentAt ||
369 eVertOrient != rFormat.eVertOrient ||
370 sPrefix != rFormat.sPrefix ||
371 sSuffix != rFormat.sSuffix ||
372 aGraphicSize != rFormat.aGraphicSize ||
373 nBulletColor != rFormat.nBulletColor ||
374 nBulletRelSize != rFormat.nBulletRelSize ||
375 IsShowSymbol() != rFormat.IsShowSymbol() ||
376 sCharStyleName != rFormat.sCharStyleName
378 return sal_False;
379 if (
380 (pGraphicBrush && !rFormat.pGraphicBrush) ||
381 (!pGraphicBrush && rFormat.pGraphicBrush) ||
382 (pGraphicBrush && *pGraphicBrush != *rFormat.pGraphicBrush)
385 return sal_False;
387 if (
388 (pBulletFont && !rFormat.pBulletFont) ||
389 (!pBulletFont && rFormat.pBulletFont) ||
390 (pBulletFont && *pBulletFont != *rFormat.pBulletFont)
393 return sal_False;
395 return sal_True;
398 void SvxNumberFormat::SetGraphicBrush( const SvxBrushItem* pBrushItem,
399 const Size* pSize, const sal_Int16* pOrient)
401 if(!pBrushItem)
403 delete pGraphicBrush;
404 pGraphicBrush = 0;
406 else if ( !pGraphicBrush || (pGraphicBrush && !(*pBrushItem == *pGraphicBrush)) )
408 delete pGraphicBrush;
409 pGraphicBrush = (SvxBrushItem*)pBrushItem->Clone();
410 pGraphicBrush->SetDoneLink( STATIC_LINK( this, SvxNumberFormat, GraphicArrived) );
413 if(pOrient)
414 eVertOrient = *pOrient;
415 else
416 eVertOrient = text::VertOrientation::NONE;
417 if(pSize)
418 aGraphicSize = *pSize;
419 else
420 aGraphicSize.Width() = aGraphicSize.Height() = 0;
423 void SvxNumberFormat::SetGraphic( const String& rName )
425 const String* pName;
426 if( pGraphicBrush &&
427 0 != (pName = pGraphicBrush->GetGraphicLink())
428 && *pName == rName )
429 return ;
431 delete pGraphicBrush;
432 String sTmp;
433 pGraphicBrush = new SvxBrushItem( rName, sTmp, GPOS_AREA, 0 );
434 pGraphicBrush->SetDoneLink( STATIC_LINK( this, SvxNumberFormat, GraphicArrived) );
435 if( eVertOrient == text::VertOrientation::NONE )
436 eVertOrient = text::VertOrientation::TOP;
438 aGraphicSize.Width() = aGraphicSize.Height() = 0;
441 void SvxNumberFormat::SetVertOrient(sal_Int16 eSet)
443 eVertOrient = eSet;
446 sal_Int16 SvxNumberFormat::GetVertOrient() const
448 return eVertOrient;
451 void SvxNumberFormat::SetBulletFont(const Font* pFont)
453 delete pBulletFont;
454 pBulletFont = pFont ? new Font(*pFont): 0;
457 SvxNumberFormat::SvxNumPositionAndSpaceMode SvxNumberFormat::GetPositionAndSpaceMode() const
459 return mePositionAndSpaceMode;
461 void SvxNumberFormat::SetPositionAndSpaceMode( SvxNumPositionAndSpaceMode ePositionAndSpaceMode )
463 mePositionAndSpaceMode = ePositionAndSpaceMode;
466 short SvxNumberFormat::GetLSpace() const
468 return mePositionAndSpaceMode == LABEL_WIDTH_AND_POSITION ? nLSpace : 0;
470 short SvxNumberFormat::GetAbsLSpace() const
472 return mePositionAndSpaceMode == LABEL_WIDTH_AND_POSITION
473 ? nAbsLSpace
474 : static_cast<short>( GetFirstLineIndent() + GetIndentAt() );
476 short SvxNumberFormat::GetFirstLineOffset() const
478 return mePositionAndSpaceMode == LABEL_WIDTH_AND_POSITION
479 ? nFirstLineOffset
480 : static_cast<short>( GetFirstLineIndent() );
482 short SvxNumberFormat::GetCharTextDistance() const
484 return mePositionAndSpaceMode == LABEL_WIDTH_AND_POSITION ? nCharTextDistance : 0;
487 void SvxNumberFormat::SetLabelFollowedBy( const LabelFollowedBy eLabelFollowedBy )
489 meLabelFollowedBy = eLabelFollowedBy;
491 SvxNumberFormat::LabelFollowedBy SvxNumberFormat::GetLabelFollowedBy() const
493 return meLabelFollowedBy;
495 void SvxNumberFormat::SetListtabPos( const long nListtabPos )
497 mnListtabPos = nListtabPos;
499 long SvxNumberFormat::GetListtabPos() const
501 return mnListtabPos;
503 void SvxNumberFormat::SetFirstLineIndent( const long nFirstLineIndent )
505 mnFirstLineIndent = nFirstLineIndent;
507 long SvxNumberFormat::GetFirstLineIndent() const
509 return mnFirstLineIndent;
511 void SvxNumberFormat::SetIndentAt( const long nIndentAt )
513 mnIndentAt = nIndentAt;
515 long SvxNumberFormat::GetIndentAt() const
517 return mnIndentAt;
520 IMPL_STATIC_LINK( SvxNumberFormat, GraphicArrived, void *, EMPTYARG )
522 // if necessary, set the GrfSize:
523 if( !pThis->aGraphicSize.Width() || !pThis->aGraphicSize.Height() )
525 const Graphic* pGrf = pThis->pGraphicBrush->GetGraphic();
526 if( pGrf )
527 pThis->aGraphicSize = SvxNumberFormat::GetGraphicSizeMM100( pGrf );
529 pThis->NotifyGraphicArrived();
530 return 0;
533 void SvxNumberFormat::NotifyGraphicArrived()
537 Size SvxNumberFormat::GetGraphicSizeMM100(const Graphic* pGraphic)
539 const MapMode aMapMM100( MAP_100TH_MM );
540 const Size& rSize = pGraphic->GetPrefSize();
541 Size aRetSize;
542 if ( pGraphic->GetPrefMapMode().GetMapUnit() == MAP_PIXEL )
544 OutputDevice* pOutDev = Application::GetDefaultDevice();
545 MapMode aOldMap( pOutDev->GetMapMode() );
546 pOutDev->SetMapMode( aMapMM100 );
547 aRetSize = pOutDev->PixelToLogic( rSize );
548 pOutDev->SetMapMode( aOldMap );
550 else
551 aRetSize = OutputDevice::LogicToLogic( rSize, pGraphic->GetPrefMapMode(), aMapMM100 );
552 return aRetSize;
555 String SvxNumberFormat::CreateRomanString( sal_uLong nNo, sal_Bool bUpper )
557 nNo %= 4000; // more can not be displayed
558 // i, ii, iii, iv, v, vi, vii, vii, viii, ix
559 // (Dummy),1000,500,100,50,10,5,1
560 const char *cRomanArr = bUpper
561 ? "MDCLXVI--" // +2 Dummy entries!
562 : "mdclxvi--"; // +2 Dummy entries!
564 String sRet;
565 sal_uInt16 nMask = 1000;
566 while( nMask )
568 sal_uInt8 nZahl = sal_uInt8(nNo / nMask);
569 sal_uInt8 nDiff = 1;
570 nNo %= nMask;
572 if( 5 < nZahl )
574 if( nZahl < 9 )
575 sRet += sal_Unicode(*(cRomanArr-1));
576 ++nDiff;
577 nZahl -= 5;
579 switch( nZahl )
581 case 3: { sRet += sal_Unicode(*cRomanArr); }
582 case 2: { sRet += sal_Unicode(*cRomanArr); }
583 case 1: { sRet += sal_Unicode(*cRomanArr); }
584 break;
586 case 4: {
587 sRet += sal_Unicode(*cRomanArr);
588 sRet += sal_Unicode(*(cRomanArr-nDiff));
590 break;
591 case 5: { sRet += sal_Unicode(*(cRomanArr-nDiff)); }
592 break;
595 nMask /= 10; // for the next decade
596 cRomanArr += 2;
598 return sRet;
601 const String& SvxNumberFormat::GetCharFmtName()const
603 return sCharStyleName;
606 sal_Int32 SvxNumRule::nRefCount = 0;
607 static SvxNumberFormat* pStdNumFmt = 0;
608 static SvxNumberFormat* pStdOutlineNumFmt = 0;
609 SvxNumRule::SvxNumRule( sal_uLong nFeatures,
610 sal_uInt16 nLevels,
611 sal_Bool bCont,
612 SvxNumRuleType eType,
613 SvxNumberFormat::SvxNumPositionAndSpaceMode
614 eDefaultNumberFormatPositionAndSpaceMode )
615 : nLevelCount(nLevels),
616 nFeatureFlags(nFeatures),
617 eNumberingType(eType),
618 bContinuousNumbering(bCont)
620 ++nRefCount;
621 for(sal_uInt16 i = 0; i < SVX_MAX_NUM; i++)
623 if(i < nLevels)
625 aFmts[i] = new SvxNumberFormat(SVX_NUM_CHARS_UPPER_LETTER);
626 // It is a distinction between writer and draw
627 if(nFeatures & NUM_CONTINUOUS)
629 if ( eDefaultNumberFormatPositionAndSpaceMode ==
630 SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
632 aFmts[i]->SetLSpace( MM100_TO_TWIP(DEF_WRITER_LSPACE) );
633 aFmts[i]->SetAbsLSpace( MM100_TO_TWIP(DEF_WRITER_LSPACE * (i+1)) );
634 aFmts[i]->SetFirstLineOffset(MM100_TO_TWIP(-DEF_WRITER_LSPACE));
636 else if ( eDefaultNumberFormatPositionAndSpaceMode ==
637 SvxNumberFormat::LABEL_ALIGNMENT )
639 // first line indent of general numbering in inch: -0,25 inch
640 const long cFirstLineIndent = -1440/4;
641 // indent values of general numbering in inch:
642 // 0,5 0,75 1,0 1,25 1,5
643 // 1,75 2,0 2,25 2,5 2,75
644 const long cIndentAt = 1440/4;
645 aFmts[i]->SetPositionAndSpaceMode( SvxNumberFormat::LABEL_ALIGNMENT );
646 aFmts[i]->SetLabelFollowedBy( SvxNumberFormat::LISTTAB );
647 aFmts[i]->SetListtabPos( cIndentAt * (i+2) );
648 aFmts[i]->SetFirstLineIndent( cFirstLineIndent );
649 aFmts[i]->SetIndentAt( cIndentAt * (i+2) );
652 else
654 aFmts[i]->SetLSpace( DEF_DRAW_LSPACE );
655 aFmts[i]->SetAbsLSpace( DEF_DRAW_LSPACE * (i) );
658 else
659 aFmts[i] = 0;
660 aFmtsSet[i] = sal_False;
664 SvxNumRule::SvxNumRule(const SvxNumRule& rCopy)
666 ++nRefCount;
667 aLocale = rCopy.aLocale;
668 nLevelCount = rCopy.nLevelCount ;
669 nFeatureFlags = rCopy.nFeatureFlags ;
670 bContinuousNumbering = rCopy.bContinuousNumbering;
671 eNumberingType = rCopy.eNumberingType;
672 memset( aFmts, 0, sizeof( aFmts ));
673 for(sal_uInt16 i = 0; i < SVX_MAX_NUM; i++)
675 if(rCopy.aFmts[i])
676 aFmts[i] = new SvxNumberFormat(*rCopy.aFmts[i]);
677 else
678 aFmts[i] = 0;
679 aFmtsSet[i] = rCopy.aFmtsSet[i];
683 SvxNumRule::SvxNumRule( SvStream &rStream )
685 sal_uInt16 nTmp16;
686 rStream >> nTmp16; // NUM_ITEM_VERSION
687 rStream >> nLevelCount;
689 // first nFeatureFlags of old Versions
690 rStream >> nTmp16; nFeatureFlags = nTmp16;
691 rStream >> nTmp16; bContinuousNumbering = nTmp16;
692 rStream >> nTmp16; eNumberingType = ( SvxNumRuleType )nTmp16;
694 for (sal_uInt16 i = 0; i < SVX_MAX_NUM; i++)
696 rStream >> nTmp16;
697 sal_Bool hasNumberingFormat = nTmp16 & 1;
698 aFmtsSet[i] = nTmp16 & 2; // fdo#68648 reset flag
699 if ( hasNumberingFormat ){
700 aFmts[i] = new SvxNumberFormat( rStream );
702 else
704 aFmts[i] = 0;
705 aFmtsSet[i] = sal_False; // actually only false is valid
708 //second nFeatureFlags for new versions
709 rStream >> nTmp16; nFeatureFlags = nTmp16;
712 SvxNumRule* SvxNumRule::Create( SvStream & rStream )
714 return new SvxNumRule( rStream );
717 SvStream& SvxNumRule::Store( SvStream &rStream )
719 rStream<<(sal_uInt16)NUMITEM_VERSION_03;
720 rStream<<nLevelCount;
721 //first save of nFeatureFlags for old versions
722 rStream<<(sal_uInt16)nFeatureFlags;
723 rStream<<(sal_uInt16)bContinuousNumbering;
724 rStream<<(sal_uInt16)eNumberingType;
726 FontToSubsFontConverter pConverter = 0;
727 sal_Bool bConvertBulletFont = ( rStream.GetVersion() <= SOFFICE_FILEFORMAT_50 ) && ( rStream.GetVersion() );
728 for(sal_uInt16 i = 0; i < SVX_MAX_NUM; i++)
730 sal_uInt16 nSetFlag(aFmtsSet[i] ? 2 : 0); // fdo#68648 store that too
731 if(aFmts[i])
733 rStream << sal_uInt16(1 | nSetFlag);
734 if(bConvertBulletFont && aFmts[i]->GetBulletFont())
736 if(!pConverter)
737 pConverter =
738 CreateFontToSubsFontConverter(aFmts[i]->GetBulletFont()->GetName(),
739 FONTTOSUBSFONT_EXPORT|FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS);
741 aFmts[i]->Store(rStream, pConverter);
743 else
744 rStream << sal_uInt16(0 | nSetFlag);
746 //second save of nFeatureFlags for new versions
747 rStream<<(sal_uInt16)nFeatureFlags;
748 if(pConverter)
749 DestroyFontToSubsFontConverter(pConverter);
751 return rStream;
753 SvxNumRule::~SvxNumRule()
755 for(sal_uInt16 i = 0; i < SVX_MAX_NUM; i++)
756 delete aFmts[i];
757 if(!--nRefCount)
759 DELETEZ(pStdNumFmt);
760 DELETEZ(pStdOutlineNumFmt);
764 SvxNumRule& SvxNumRule::operator=( const SvxNumRule& rCopy )
766 nLevelCount = rCopy.nLevelCount;
767 nFeatureFlags = rCopy.nFeatureFlags;
768 bContinuousNumbering = rCopy.bContinuousNumbering;
769 eNumberingType = rCopy.eNumberingType;
770 for(sal_uInt16 i = 0; i < SVX_MAX_NUM; i++)
772 delete aFmts[i];
773 if(rCopy.aFmts[i])
774 aFmts[i] = new SvxNumberFormat(*rCopy.aFmts[i]);
775 else
776 aFmts[i] = 0;
777 aFmtsSet[i] = rCopy.aFmtsSet[i];
779 return *this;
782 int SvxNumRule::operator==( const SvxNumRule& rCopy) const
784 if(nLevelCount != rCopy.nLevelCount ||
785 nFeatureFlags != rCopy.nFeatureFlags ||
786 bContinuousNumbering != rCopy.bContinuousNumbering ||
787 eNumberingType != rCopy.eNumberingType)
788 return sal_False;
789 for(sal_uInt16 i = 0; i < nLevelCount; i++)
791 if (
792 (aFmtsSet[i] != rCopy.aFmtsSet[i]) ||
793 (!aFmts[i] && rCopy.aFmts[i]) ||
794 (aFmts[i] && !rCopy.aFmts[i]) ||
795 (aFmts[i] && *aFmts[i] != *rCopy.aFmts[i])
798 return sal_False;
801 return sal_True;
804 const SvxNumberFormat* SvxNumRule::Get(sal_uInt16 nLevel)const
806 DBG_ASSERT(nLevel < SVX_MAX_NUM, "Wrong Level" );
807 if( nLevel < SVX_MAX_NUM )
808 return aFmtsSet[nLevel] ? aFmts[nLevel] : 0;
809 else
810 return 0;
813 const SvxNumberFormat& SvxNumRule::GetLevel(sal_uInt16 nLevel)const
815 if(!pStdNumFmt)
817 pStdNumFmt = new SvxNumberFormat(SVX_NUM_ARABIC);
818 pStdOutlineNumFmt = new SvxNumberFormat(SVX_NUM_NUMBER_NONE);
821 DBG_ASSERT(nLevel < SVX_MAX_NUM, "Wrong Level" );
823 return ( ( nLevel < SVX_MAX_NUM ) && aFmts[nLevel] ) ?
824 *aFmts[nLevel] : eNumberingType == SVX_RULETYPE_NUMBERING ?
825 *pStdNumFmt : *pStdOutlineNumFmt;
828 void SvxNumRule::SetLevel( sal_uInt16 i, const SvxNumberFormat& rNumFmt, sal_Bool bIsValid )
830 DBG_ASSERT(i < SVX_MAX_NUM, "Wrong Level" );
832 if( (i < SVX_MAX_NUM) && (!aFmtsSet[i] || !(rNumFmt == *Get( i ))) )
834 delete aFmts[ i ];
835 aFmts[ i ] = new SvxNumberFormat( rNumFmt );
836 aFmtsSet[i] = bIsValid;
840 void SvxNumRule::SetLevel(sal_uInt16 nLevel, const SvxNumberFormat* pFmt)
842 DBG_ASSERT(nLevel < SVX_MAX_NUM, "Wrong Level" );
844 if( nLevel < SVX_MAX_NUM )
846 aFmtsSet[nLevel] = 0 != pFmt;
847 if(pFmt)
848 SetLevel(nLevel, *pFmt);
849 else
851 delete aFmts[nLevel];
852 aFmts[nLevel] = 0;
857 String SvxNumRule::MakeNumString( const SvxNodeNum& rNum, sal_Bool bInclStrings ) const
859 String aStr;
860 if( SVX_NO_NUM > rNum.GetLevel() && !( SVX_NO_NUMLEVEL & rNum.GetLevel() ) )
862 const SvxNumberFormat& rMyNFmt = GetLevel( rNum.GetLevel() );
863 if( SVX_NUM_NUMBER_NONE != rMyNFmt.GetNumberingType() )
865 sal_uInt8 i = rNum.GetLevel();
867 if( !IsContinuousNumbering() &&
868 1 < rMyNFmt.GetIncludeUpperLevels() ) // only on own level?
870 sal_uInt8 n = rMyNFmt.GetIncludeUpperLevels();
871 if( 1 < n )
873 if( i+1 >= n )
874 i -= n - 1;
875 else
876 i = 0;
880 for( ; i <= rNum.GetLevel(); ++i )
882 const SvxNumberFormat& rNFmt = GetLevel( i );
883 if( SVX_NUM_NUMBER_NONE == rNFmt.GetNumberingType() )
885 continue;
888 sal_Bool bDot = sal_True;
889 if( rNum.GetLevelVal()[ i ] )
891 if(SVX_NUM_BITMAP != rNFmt.GetNumberingType())
892 aStr += rNFmt.GetNumStr( rNum.GetLevelVal()[ i ], aLocale );
893 else
894 bDot = sal_False;
896 else
897 aStr += sal_Unicode('0'); // all 0-levels are a 0
898 if( i != rNum.GetLevel() && bDot)
899 aStr += sal_Unicode('.');
903 if( bInclStrings )
905 aStr.Insert( rMyNFmt.GetPrefix(), 0 );
906 aStr += rMyNFmt.GetSuffix();
909 return aStr;
912 // changes linked to embedded bitmaps
913 sal_Bool SvxNumRule::UnLinkGraphics()
915 sal_Bool bRet = sal_False;
916 for(sal_uInt16 i = 0; i < GetLevelCount(); i++)
918 SvxNumberFormat aFmt(GetLevel(i));
919 const SvxBrushItem* pBrush = aFmt.GetBrush();
920 const String* pLinkStr;
921 const Graphic* pGraphic;
922 if(SVX_NUM_BITMAP == aFmt.GetNumberingType())
924 if(pBrush &&
925 0 != (pLinkStr = pBrush->GetGraphicLink()) &&
926 pLinkStr->Len() &&
927 0 !=(pGraphic = pBrush->GetGraphic()))
929 SvxBrushItem aTempItem(*pBrush);
930 aTempItem.SetGraphicLink( String());
931 aTempItem.SetGraphic(*pGraphic);
932 sal_Int16 eOrient = aFmt.GetVertOrient();
933 aFmt.SetGraphicBrush( &aTempItem, &aFmt.GetGraphicSize(), &eOrient );
934 bRet = sal_True;
937 else if((SVX_NUM_BITMAP|LINK_TOKEN) == aFmt.GetNumberingType())
938 aFmt.SetNumberingType(SVX_NUM_BITMAP);
939 SetLevel(i, aFmt);
941 return bRet;
944 SvxNumBulletItem::SvxNumBulletItem(SvxNumRule& rRule) :
945 SfxPoolItem(SID_ATTR_NUMBERING_RULE),
946 pNumRule(new SvxNumRule(rRule))
950 SvxNumBulletItem::SvxNumBulletItem(SvxNumRule& rRule, sal_uInt16 _nWhich ) :
951 SfxPoolItem(_nWhich),
952 pNumRule(new SvxNumRule(rRule))
956 SfxPoolItem* SvxNumBulletItem::Create(SvStream &rStream, sal_uInt16 /*nItemVersion*/ ) const
958 SvxNumRule aNumRule( rStream );
959 return new SvxNumBulletItem( aNumRule, EE_PARA_NUMBULLET );
962 SvxNumBulletItem::SvxNumBulletItem(const SvxNumBulletItem& rCopy) :
963 SfxPoolItem(rCopy.Which())
965 pNumRule = new SvxNumRule(*rCopy.pNumRule);
968 SvxNumBulletItem::~SvxNumBulletItem()
970 delete pNumRule;
973 int SvxNumBulletItem::operator==( const SfxPoolItem& rCopy) const
975 return *pNumRule == *((SvxNumBulletItem&)rCopy).pNumRule;
978 SfxPoolItem* SvxNumBulletItem::Clone( SfxItemPool * ) const
980 return new SvxNumBulletItem(*this);
983 sal_uInt16 SvxNumBulletItem::GetVersion( sal_uInt16 /*nFileVersion*/ ) const
985 return NUMITEM_VERSION_03;
988 SvStream& SvxNumBulletItem::Store(SvStream &rStream, sal_uInt16 /*nItemVersion*/ )const
990 pNumRule->Store(rStream);
991 return rStream;
994 bool SvxNumBulletItem::QueryValue( com::sun::star::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const
996 rVal <<= SvxCreateNumRule( pNumRule );
997 return true;
1000 bool SvxNumBulletItem::PutValue( const com::sun::star::uno::Any& rVal, sal_uInt8 /*nMemberId*/ )
1002 uno::Reference< container::XIndexReplace > xRule;
1003 if( rVal >>= xRule )
1007 SvxNumRule* pNewRule = new SvxNumRule( SvxGetNumRule( xRule ) );
1008 if( pNewRule->GetLevelCount() != pNumRule->GetLevelCount() ||
1009 pNewRule->GetNumRuleType() != pNumRule->GetNumRuleType() )
1011 SvxNumRule* pConverted = SvxConvertNumRule( pNewRule, pNumRule->GetLevelCount(), pNumRule->GetNumRuleType() );
1012 delete pNewRule;
1013 pNewRule = pConverted;
1015 delete pNumRule;
1016 pNumRule = pNewRule;
1017 return true;
1019 catch(const lang::IllegalArgumentException&)
1023 return false;
1026 SvxNumRule* SvxConvertNumRule( const SvxNumRule* pRule, sal_uInt16 nLevels, SvxNumRuleType eType )
1028 const sal_uInt16 nSrcLevels = pRule->GetLevelCount();
1029 SvxNumRule* pNewRule = new SvxNumRule( pRule->GetFeatureFlags(), nLevels, pRule->IsContinuousNumbering(), eType );
1031 for( sal_uInt16 nLevel = 0; (nLevel < nLevels) && (nLevel < nSrcLevels); nLevel++ )
1032 pNewRule->SetLevel( nLevel, pRule->GetLevel( nLevel ) );
1034 return pNewRule;
1037 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */