Version 24.2.2.2, tag libreoffice-24.2.2.2
[LibreOffice.git] / xmloff / source / style / xmlnumi.cxx
blob0ddab1466df83ef92409e92c9727233d848fdcb0
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 .
20 #include <com/sun/star/beans/PropertyValue.hpp>
21 #include <com/sun/star/beans/XPropertySet.hpp>
22 #include <com/sun/star/awt/Size.hpp>
23 #include <com/sun/star/frame/XModel.hpp>
24 #include <com/sun/star/graphic/XGraphic.hpp>
25 #include <com/sun/star/awt/FontDescriptor.hpp>
26 #include <com/sun/star/text/HoriOrientation.hpp>
27 #include <com/sun/star/text/VertOrientation.hpp>
28 #include <com/sun/star/text/PositionAndSpaceMode.hpp>
29 #include <com/sun/star/text/LabelFollow.hpp>
30 #include <com/sun/star/container/XNameContainer.hpp>
31 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
32 #include <com/sun/star/style/XStyle.hpp>
33 #include <com/sun/star/io/XOutputStream.hpp>
34 #include <com/sun/star/awt/XBitmap.hpp>
35 #include <com/sun/star/style/NumberingType.hpp>
36 #include <com/sun/star/container/XIndexReplace.hpp>
38 #include <o3tl/any.hxx>
39 #include <o3tl/temporary.hxx>
40 #include <rtl/ustrbuf.hxx>
41 #include <sal/log.hxx>
42 #include <comphelper/diagnose_ex.hxx>
43 #include <comphelper/sequence.hxx>
44 #include <comphelper/propertyvalue.hxx>
46 #include <tools/fontenum.hxx>
47 #include <tools/color.hxx>
49 #include <sax/tools/converter.hxx>
51 #include <vcl/vclenum.hxx>
53 #include <xmloff/xmltkmap.hxx>
54 #include <xmloff/namespacemap.hxx>
55 #include <xmloff/xmlnamespace.hxx>
56 #include <xmloff/xmlimp.hxx>
57 #include <xmloff/XMLBase64ImportContext.hxx>
58 #include <xmloff/xmltoken.hxx>
60 #include <xmloff/xmluconv.hxx>
61 #include "fonthdl.hxx"
62 #include <xmloff/XMLFontStylesContext.hxx>
63 #include <xmloff/families.hxx>
64 #include <xmloff/maptype.hxx>
66 #include <xmloff/xmlnumi.hxx>
67 #include <optional>
69 using namespace ::com::sun::star;
70 using namespace ::com::sun::star::uno;
71 using namespace ::com::sun::star::style;
72 using namespace ::com::sun::star::text;
73 using namespace ::com::sun::star::beans;
74 using namespace ::com::sun::star::container;
75 using namespace ::com::sun::star::lang;
76 using namespace ::com::sun::star::frame;
77 using namespace ::xmloff::token;
78 using namespace ::com::sun::star::io;
80 class SvxXMLListLevelStyleContext_Impl;
82 namespace {
84 class SvxXMLListLevelStyleAttrContext_Impl : public SvXMLImportContext
86 SvxXMLListLevelStyleContext_Impl& rListLevel;
88 public:
90 SvxXMLListLevelStyleAttrContext_Impl(
91 SvXMLImport& rImport, sal_Int32 nElement,
92 const Reference< xml::sax::XFastAttributeList >& xAttrList,
93 SvxXMLListLevelStyleContext_Impl& rLLevel );
95 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
96 sal_Int32 nElement,
97 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
100 class SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl : public SvXMLImportContext
102 public:
104 SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl(
105 SvXMLImport& rImport, sal_Int32 nElement,
106 const Reference< xml::sax::XFastAttributeList >& xAttrList,
107 SvxXMLListLevelStyleContext_Impl& rLLevel );
112 class SvxXMLListLevelStyleContext_Impl : public SvXMLImportContext
114 friend SvxXMLListLevelStyleAttrContext_Impl;
116 OUString sPrefix;
117 OUString sSuffix;
118 std::optional<OUString> sListFormat; // It is optional to distinguish empty format string
119 // from not existing format string in old docs
120 OUString sTextStyleName;
121 OUString sNumFormat;
122 OUString sNumLetterSync;
123 OUString sBulletFontName;
124 OUString sBulletFontStyleName;
125 OUString sImageURL;
127 Reference < XOutputStream > xBase64Stream;
129 sal_Int32 nLevel;
130 sal_Int32 nSpaceBefore;
131 sal_Int32 nMinLabelWidth;
132 sal_Int32 nMinLabelDist;
133 sal_Int32 nImageWidth;
134 sal_Int32 nImageHeight;
135 sal_Int16 nNumStartValue;
136 sal_Int16 nNumDisplayLevels;
138 sal_Int16 eAdjust;
139 sal_Int16 eBulletFontFamily;
140 sal_Int16 eBulletFontPitch;
141 rtl_TextEncoding eBulletFontEncoding;
142 sal_Int16 eImageVertOrient;
144 sal_UCS4 cBullet;
146 sal_Int16 nRelSize;
147 Color m_nColor;
149 sal_Int16 ePosAndSpaceMode;
150 sal_Int16 eLabelFollowedBy;
151 sal_Int32 nListtabStopPosition;
152 sal_Int32 nFirstLineIndent;
153 sal_Int32 nIndentAt;
155 bool bBullet : 1;
156 bool bImage : 1;
157 bool bNum : 1;
158 bool bHasColor : 1;
160 bool m_bIsLegal = false;
162 void SetRelSize( sal_Int16 nRel ) { nRelSize = nRel; }
163 void SetColor( Color nColor )
164 { m_nColor = nColor; bHasColor = true; }
165 void SetSpaceBefore( sal_Int32 nSet ) { nSpaceBefore = nSet; }
166 void SetMinLabelWidth( sal_Int32 nSet ) { nMinLabelWidth = nSet; }
167 void SetMinLabelDist( sal_Int32 nSet ) { nMinLabelDist = nSet; }
168 void SetAdjust( sal_Int16 eSet ) { eAdjust = eSet; }
170 void SetBulletFontName( const OUString& rSet ) { sBulletFontName = rSet; }
171 void SetBulletFontStyleName( const OUString& rSet )
172 { sBulletFontStyleName = rSet; }
173 void SetBulletFontFamily( sal_Int16 eSet ) { eBulletFontFamily = eSet; }
174 void SetBulletFontPitch( sal_Int16 eSet ) { eBulletFontPitch = eSet; }
175 void SetBulletFontEncoding( rtl_TextEncoding eSet )
176 { eBulletFontEncoding = eSet; }
178 void SetImageWidth( sal_Int32 nSet ) { nImageWidth = nSet; }
179 void SetImageHeight( sal_Int32 nSet ) { nImageHeight = nSet; }
180 void SetImageVertOrient( sal_Int16 eSet )
181 { eImageVertOrient = eSet; }
183 public:
185 SvxXMLListLevelStyleContext_Impl(
186 SvXMLImport& rImport, sal_Int32 nElement,
187 const Reference< xml::sax::XFastAttributeList > & xAttrList );
189 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
190 sal_Int32 nElement,
191 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
193 sal_Int32 GetLevel() const { return nLevel; }
194 Sequence<beans::PropertyValue> GetProperties();
196 void SetPosAndSpaceMode( sal_Int16 eValue )
198 ePosAndSpaceMode = eValue;
200 void SetLabelFollowedBy( sal_Int16 eValue )
202 eLabelFollowedBy = eValue;
204 void SetListtabStopPosition( sal_Int32 nValue )
206 nListtabStopPosition = nValue;
208 void SetFirstLineIndent( sal_Int32 nValue )
210 nFirstLineIndent = nValue;
212 void SetIndentAt( sal_Int32 nValue )
214 nIndentAt = nValue;
218 constexpr OUStringLiteral gsStarBats( u"StarBats" );
219 constexpr OUStringLiteral gsStarMath( u"StarMath" );
221 SvxXMLListLevelStyleContext_Impl::SvxXMLListLevelStyleContext_Impl(
222 SvXMLImport& rImport, sal_Int32 nElement,
223 const Reference< xml::sax::XFastAttributeList > & xAttrList )
225 : SvXMLImportContext( rImport )
226 , sNumFormat( "1" )
227 , nLevel( -1 )
228 , nSpaceBefore( 0 )
229 , nMinLabelWidth( 0 )
230 , nMinLabelDist( 0 )
231 , nImageWidth( 0 )
232 , nImageHeight( 0 )
233 , nNumStartValue( 1 )
234 , nNumDisplayLevels( 1 )
235 , eAdjust( HoriOrientation::LEFT )
236 , eBulletFontFamily( FAMILY_DONTKNOW )
237 , eBulletFontPitch( PITCH_DONTKNOW )
238 , eBulletFontEncoding( RTL_TEXTENCODING_DONTKNOW )
239 , eImageVertOrient(0)
240 , cBullet( 0 )
241 , nRelSize(0)
242 , m_nColor(0)
243 , ePosAndSpaceMode( PositionAndSpaceMode::LABEL_WIDTH_AND_POSITION )
244 , eLabelFollowedBy( LabelFollow::LISTTAB )
245 , nListtabStopPosition( 0 )
246 , nFirstLineIndent( 0 )
247 , nIndentAt( 0 )
248 , bBullet( false )
249 , bImage( false )
250 , bNum( false )
251 , bHasColor( false )
253 switch (nElement & TOKEN_MASK)
255 case XML_LIST_LEVEL_STYLE_NUMBER:
256 case XML_OUTLINE_LEVEL_STYLE:
257 bNum = true;
258 break;
259 case XML_LIST_LEVEL_STYLE_BULLET:
260 bBullet = true;
261 break;
262 case XML_LIST_LEVEL_STYLE_IMAGE:
263 bImage = true;
264 break;
267 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
269 switch( aIter.getToken() )
271 case XML_ELEMENT(TEXT, XML_LEVEL):
272 nLevel = aIter.toInt32();
273 if( nLevel >= 1 )
274 nLevel--;
275 else
276 nLevel = 0;
277 break;
278 case XML_ELEMENT(TEXT, XML_STYLE_NAME):
279 sTextStyleName = aIter.toString();
280 break;
281 case XML_ELEMENT(TEXT, XML_BULLET_CHAR):
282 if (!aIter.isEmpty())
284 cBullet = aIter.toString().iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
286 break;
287 case XML_ELEMENT(XLINK, XML_HREF):
288 if( bImage )
289 sImageURL = aIter.toString();
290 break;
291 case XML_ELEMENT(XLINK, XML_TYPE):
292 case XML_ELEMENT(XLINK, XML_SHOW):
293 case XML_ELEMENT(XLINK, XML_ACTUATE):
294 // This properties will be ignored
295 break;
296 case XML_ELEMENT(STYLE, XML_NUM_FORMAT):
297 if( bNum )
298 sNumFormat = aIter.toString();
299 break;
300 case XML_ELEMENT(STYLE, XML_NUM_PREFIX):
301 sPrefix = aIter.toString();
302 break;
303 case XML_ELEMENT(STYLE, XML_NUM_SUFFIX):
304 sSuffix = aIter.toString();
305 break;
306 case XML_ELEMENT(STYLE, XML_NUM_LIST_FORMAT):
307 case XML_ELEMENT(LO_EXT, XML_NUM_LIST_FORMAT):
308 sListFormat = std::make_optional(aIter.toString());
309 break;
310 case XML_ELEMENT(LO_EXT, XML_IS_LEGAL):
311 m_bIsLegal = aIter.toBoolean();
312 break;
313 case XML_ELEMENT(STYLE, XML_NUM_LETTER_SYNC):
314 if( bNum )
315 sNumLetterSync = aIter.toString();
316 break;
317 case XML_ELEMENT(TEXT, XML_START_VALUE):
318 if( bNum )
320 sal_Int32 nTmp = aIter.toInt32();
321 nNumStartValue =
322 (nTmp < 0) ? 1 : ( (nTmp>SHRT_MAX) ? SHRT_MAX
323 : static_cast<sal_Int16>(nTmp) );
325 break;
326 case XML_ELEMENT(TEXT, XML_DISPLAY_LEVELS):
327 if( bNum )
329 sal_Int32 nTmp = aIter.toInt32();
330 nNumDisplayLevels =
331 (nTmp < 1) ? 1 : ( (nTmp>SHRT_MAX) ? SHRT_MAX
332 : static_cast<sal_Int16>(nTmp) );
334 break;
335 default:
336 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
341 css::uno::Reference< css::xml::sax::XFastContextHandler > SvxXMLListLevelStyleContext_Impl::createFastChildContext(
342 sal_Int32 nElement,
343 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
345 if( nElement == XML_ELEMENT(STYLE, XML_LIST_LEVEL_PROPERTIES) ||
346 nElement == XML_ELEMENT(STYLE, XML_TEXT_PROPERTIES) )
348 return new SvxXMLListLevelStyleAttrContext_Impl( GetImport(),
349 nElement,
350 xAttrList,
351 *this );
353 else if( nElement == XML_ELEMENT(OFFICE, XML_BINARY_DATA) )
355 if( bImage && sImageURL.isEmpty() && !xBase64Stream.is() )
357 xBase64Stream = GetImport().GetStreamForGraphicObjectURLFromBase64();
358 if( xBase64Stream.is() )
359 return new XMLBase64ImportContext( GetImport(), xBase64Stream );
362 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
363 return nullptr;
366 Sequence<beans::PropertyValue> SvxXMLListLevelStyleContext_Impl::GetProperties()
368 if (!bBullet && !bImage && !bNum)
370 return Sequence<beans::PropertyValue>();
373 sal_Int16 eType = NumberingType::NUMBER_NONE;
374 std::vector<beans::PropertyValue> aProperties;
376 if( bBullet )
378 eType = NumberingType::CHAR_SPECIAL;
380 if( bImage )
382 eType = NumberingType::BITMAP;
384 if( bNum )
386 eType = NumberingType::ARABIC;
387 GetImport().GetMM100UnitConverter().convertNumFormat(
388 eType, sNumFormat, sNumLetterSync, true );
391 if (bBullet && !sSuffix.isEmpty())
393 sal_uInt16 const nVersion(GetImport().getGeneratorVersion());
394 sal_Int32 nUPD;
395 sal_Int32 nBuildId;
396 if (GetImport().getBuildIds(nUPD, nBuildId)
397 && ( (SvXMLImport::OOo_1x == nVersion)
398 || (SvXMLImport::OOo_2x == nVersion)
399 || (310 == nUPD) || (320 == nUPD) || (330 == nUPD)
400 || ((300 == nUPD) && (nBuildId <= 9573))))
402 // #i93908# OOo < 3.4 wrote a bogus suffix for bullet chars
403 sSuffix.clear(); // clear it
407 if (!sListFormat.has_value())
409 // This is older document: it has no list format, but can probably contain prefix and/or suffix
410 // Generate list format string, based on this
411 sListFormat = std::make_optional(sPrefix);
413 for (int i = 1; i <= nNumDisplayLevels; i++)
415 *sListFormat += "%";
416 *sListFormat += OUString::number(nLevel - nNumDisplayLevels + i + 1);
417 *sListFormat += "%";
418 if (i != nNumDisplayLevels)
419 *sListFormat += "."; // Default separator for older ODT
422 *sListFormat += sSuffix;
425 aProperties.push_back(comphelper::makePropertyValue("NumberingType", eType));
427 aProperties.push_back(comphelper::makePropertyValue("Prefix", sPrefix));
429 aProperties.push_back(comphelper::makePropertyValue("Suffix", sSuffix));
431 aProperties.push_back(comphelper::makePropertyValue("Adjust", eAdjust));
433 sal_Int32 nLeftMargin = nSpaceBefore + nMinLabelWidth;
434 aProperties.push_back(comphelper::makePropertyValue("LeftMargin", nLeftMargin));
436 sal_Int32 nFirstLineOffset = -nMinLabelWidth;
437 aProperties.push_back(comphelper::makePropertyValue("FirstLineOffset", nFirstLineOffset));
439 aProperties.push_back(comphelper::makePropertyValue("SymbolTextDistance", static_cast<sal_Int16>(nMinLabelDist)));
441 aProperties.push_back(comphelper::makePropertyValue("PositionAndSpaceMode", ePosAndSpaceMode));
443 aProperties.push_back(comphelper::makePropertyValue("LabelFollowedBy", eLabelFollowedBy));
445 aProperties.push_back(comphelper::makePropertyValue("ListtabStopPosition", nListtabStopPosition));
447 aProperties.push_back(comphelper::makePropertyValue("FirstLineIndent", nFirstLineIndent));
449 aProperties.push_back(comphelper::makePropertyValue("IndentAt", nIndentAt));
451 OUString sDisplayTextStyleName = GetImport().GetStyleDisplayName(XmlStyleFamily::TEXT_TEXT, sTextStyleName);
452 aProperties.push_back(comphelper::makePropertyValue("CharStyleName", sDisplayTextStyleName));
454 if( bBullet )
456 awt::FontDescriptor aFDesc;
457 aFDesc.Name = sBulletFontName;
458 if( !sBulletFontName.isEmpty() )
460 aFDesc.StyleName = sBulletFontStyleName;
461 aFDesc.Family = eBulletFontFamily;
462 aFDesc.Pitch = eBulletFontPitch;
463 aFDesc.CharSet = eBulletFontEncoding;
464 aFDesc.Weight = WEIGHT_DONTKNOW;
465 bool bStarSymbol = false;
466 if( aFDesc.Name.equalsIgnoreAsciiCase( gsStarBats ) )
468 cBullet = GetImport().ConvStarBatsCharToStarSymbol( cBullet );
469 bStarSymbol = true;
471 else if( aFDesc.Name.equalsIgnoreAsciiCase( gsStarMath ) )
473 cBullet = GetImport().ConvStarMathCharToStarSymbol( cBullet );
474 bStarSymbol = true;
476 if( bStarSymbol )
477 aFDesc.Name = "StarSymbol" ;
480 // Must append 'cBullet' even if it is zero
481 // if 'bBullet' is true and 'cBullet' is zero - BulletChar property must be 0.
482 aProperties.push_back(comphelper::makePropertyValue("BulletChar", OUString(&cBullet, 1)));
483 aProperties.push_back(comphelper::makePropertyValue("BulletFont", aFDesc));
486 if( bImage )
488 uno::Reference<graphic::XGraphic> xGraphic;
489 if (!sImageURL.isEmpty())
491 xGraphic = GetImport().loadGraphicByURL(sImageURL);
493 else if( xBase64Stream.is() )
495 xGraphic = GetImport().loadGraphicFromBase64(xBase64Stream);
498 uno::Reference<awt::XBitmap> xBitmap;
499 if (xGraphic.is())
500 xBitmap.set(xGraphic, uno::UNO_QUERY);
502 if (xBitmap.is())
504 aProperties.push_back(comphelper::makePropertyValue("GraphicBitmap", xBitmap));
507 awt::Size aSize(nImageWidth, nImageHeight);
508 aProperties.push_back(comphelper::makePropertyValue("GraphicSize", aSize));
509 aProperties.push_back(comphelper::makePropertyValue("VertOrient", eImageVertOrient));
512 if( bNum )
514 aProperties.push_back(comphelper::makePropertyValue("StartWith", nNumStartValue));
515 aProperties.push_back(comphelper::makePropertyValue("ParentNumbering", nNumDisplayLevels));
518 if( ( bNum || bBullet ) && nRelSize )
520 aProperties.push_back(comphelper::makePropertyValue("BulletRelSize", nRelSize));
523 if( !bImage && bHasColor )
525 aProperties.push_back(comphelper::makePropertyValue("BulletColor", m_nColor));
528 aProperties.push_back(comphelper::makePropertyValue("ListFormat", *sListFormat));
530 if (m_bIsLegal)
531 aProperties.push_back(comphelper::makePropertyValue("IsLegal", true));
533 return comphelper::containerToSequence(aProperties);
536 SvxXMLListLevelStyleAttrContext_Impl::SvxXMLListLevelStyleAttrContext_Impl(
537 SvXMLImport& rImport, sal_Int32 /*nElement*/,
538 const Reference< xml::sax::XFastAttributeList > & xAttrList,
539 SvxXMLListLevelStyleContext_Impl& rLLevel ) :
540 SvXMLImportContext( rImport ),
541 rListLevel( rLLevel )
543 SvXMLUnitConverter& rUnitConv = GetImport().GetMM100UnitConverter();
545 OUString sFontName, sFontFamily, sFontStyleName, sFontFamilyGeneric,
546 sFontPitch, sFontCharset;
547 OUString sVerticalPos, sVerticalRel;
549 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
551 sal_Int32 nVal;
552 switch( aIter.getToken() )
554 case XML_ELEMENT(TEXT, XML_SPACE_BEFORE):
555 if (rUnitConv.convertMeasureToCore(nVal, aIter.toView(), SHRT_MIN, SHRT_MAX))
556 rListLevel.SetSpaceBefore( nVal );
557 break;
558 case XML_ELEMENT(TEXT, XML_MIN_LABEL_WIDTH):
559 if (rUnitConv.convertMeasureToCore( nVal, aIter.toView(), 0, SHRT_MAX ))
560 rListLevel.SetMinLabelWidth( nVal );
561 break;
562 case XML_ELEMENT(TEXT, XML_MIN_LABEL_DISTANCE):
563 if (rUnitConv.convertMeasureToCore( nVal, aIter.toView(), 0, USHRT_MAX ))
564 rListLevel.SetMinLabelDist( nVal );
565 break;
566 case XML_ELEMENT(FO, XML_TEXT_ALIGN):
567 case XML_ELEMENT(FO_COMPAT, XML_TEXT_ALIGN):
568 if( !aIter.isEmpty() )
570 sal_Int16 eAdjust = HoriOrientation::LEFT;
571 if( IsXMLToken( aIter, XML_CENTER ) )
572 eAdjust = HoriOrientation::CENTER;
573 else if( IsXMLToken( aIter, XML_END ) )
574 eAdjust = HoriOrientation::RIGHT;
575 rListLevel.SetAdjust( eAdjust );
577 break;
578 case XML_ELEMENT(STYLE, XML_FONT_NAME):
579 sFontName = aIter.toString();
580 break;
581 case XML_ELEMENT(FO, XML_FONT_FAMILY):
582 case XML_ELEMENT(FO_COMPAT, XML_FONT_FAMILY):
583 sFontFamily = aIter.toString();
584 break;
585 case XML_ELEMENT(STYLE, XML_FONT_FAMILY_GENERIC):
586 sFontFamilyGeneric = aIter.toString();
587 break;
588 case XML_ELEMENT(STYLE, XML_FONT_STYLE_NAME):
589 sFontStyleName = aIter.toString();
590 break;
591 case XML_ELEMENT(STYLE, XML_FONT_PITCH):
592 sFontPitch = aIter.toString();
593 break;
594 case XML_ELEMENT(STYLE, XML_FONT_CHARSET):
595 sFontCharset = aIter.toString();
596 break;
597 case XML_ELEMENT(STYLE, XML_VERTICAL_POS):
598 sVerticalPos = aIter.toString();
599 break;
600 case XML_ELEMENT(STYLE, XML_VERTICAL_REL):
601 sVerticalRel = aIter.toString();
602 break;
603 case XML_ELEMENT(FO, XML_WIDTH):
604 case XML_ELEMENT(FO_COMPAT, XML_WIDTH):
605 if (rUnitConv.convertMeasureToCore(nVal, aIter.toView()))
606 rListLevel.SetImageWidth( nVal );
607 break;
608 case XML_ELEMENT(FO, XML_HEIGHT):
609 case XML_ELEMENT(FO_COMPAT, XML_HEIGHT):
610 if (rUnitConv.convertMeasureToCore(nVal, aIter.toView()))
611 rListLevel.SetImageHeight( nVal );
612 break;
613 case XML_ELEMENT(FO, XML_COLOR):
614 case XML_ELEMENT(FO_COMPAT, XML_COLOR):
616 Color nColor;
617 if (::sax::Converter::convertColor( nColor, aIter.toView() ))
618 rListLevel.SetColor( nColor );
620 break;
621 case XML_ELEMENT(STYLE, XML_USE_WINDOW_FONT_COLOR):
623 if( IsXMLToken( aIter, XML_TRUE ) )
624 rListLevel.SetColor(COL_AUTO);
626 break;
627 case XML_ELEMENT(FO, XML_FONT_SIZE):
628 case XML_ELEMENT(FO_COMPAT, XML_FONT_SIZE):
629 if (::sax::Converter::convertPercent( nVal, aIter.toView() ))
630 rListLevel.SetRelSize( static_cast<sal_Int16>(nVal) );
631 break;
632 case XML_ELEMENT(TEXT, XML_LIST_LEVEL_POSITION_AND_SPACE_MODE):
634 sal_Int16 ePosAndSpaceMode = PositionAndSpaceMode::LABEL_WIDTH_AND_POSITION;
635 if( IsXMLToken( aIter, XML_LABEL_ALIGNMENT ) )
636 ePosAndSpaceMode = PositionAndSpaceMode::LABEL_ALIGNMENT;
637 rListLevel.SetPosAndSpaceMode( ePosAndSpaceMode );
639 break;
640 default:
641 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
645 if( !sFontName.isEmpty() )
647 const XMLFontStylesContext *pFontDecls =
648 GetImport().GetFontDecls();
649 if( pFontDecls )
651 ::std::vector < XMLPropertyState > aProps;
652 if( pFontDecls->FillProperties( sFontName, aProps, 0, 1, 2, 3, 4 ) )
654 OUString sTmp;
655 sal_Int16 nTmp = 0;
656 for( const auto& rProp : aProps )
658 switch( rProp.mnIndex )
660 case 0:
661 rProp.maValue >>= sTmp;
662 rListLevel.SetBulletFontName( sTmp);
663 break;
664 case 1:
665 rProp.maValue >>= sTmp;
666 rListLevel.SetBulletFontStyleName( sTmp );
667 break;
668 case 2:
669 rProp.maValue >>= nTmp;
670 rListLevel.SetBulletFontFamily( nTmp );
671 break;
672 case 3:
673 rProp.maValue >>= nTmp;
674 rListLevel.SetBulletFontPitch( nTmp );
675 break;
676 case 4:
677 rProp.maValue >>= nTmp;
678 rListLevel.SetBulletFontEncoding( nTmp );
679 break;
685 if( !sFontFamily.isEmpty() )
687 Any aAny;
689 XMLFontFamilyNamePropHdl aFamilyNameHdl;
690 if( aFamilyNameHdl.importXML( sFontFamily, aAny, rUnitConv ) )
692 OUString sTmp;
693 aAny >>= sTmp;
694 rListLevel.SetBulletFontName( sTmp);
697 XMLFontFamilyPropHdl aFamilyHdl;
698 if( !sFontFamilyGeneric.isEmpty() &&
699 aFamilyHdl.importXML( sFontFamilyGeneric, aAny, rUnitConv ) )
701 sal_Int16 nTmp = 0;
702 aAny >>= nTmp;
703 rListLevel.SetBulletFontFamily( nTmp );
706 if( !sFontStyleName.isEmpty() )
707 rListLevel.SetBulletFontStyleName( sFontStyleName );
709 XMLFontPitchPropHdl aPitchHdl;
710 if( !sFontPitch.isEmpty() &&
711 aPitchHdl.importXML( sFontPitch, aAny, rUnitConv ) )
713 sal_Int16 nTmp = 0;
714 aAny >>= nTmp;
715 rListLevel.SetBulletFontPitch( nTmp );
718 XMLFontEncodingPropHdl aEncHdl;
719 if( !sFontCharset.isEmpty() &&
720 aEncHdl.importXML( sFontCharset, aAny, rUnitConv ) )
722 sal_Int16 nTmp = 0;
723 aAny >>= nTmp;
724 rListLevel.SetBulletFontEncoding( nTmp );
728 sal_Int16 eVertOrient = VertOrientation::LINE_CENTER;
729 if( !sVerticalPos.isEmpty() )
731 if( IsXMLToken( sVerticalPos, XML_TOP ) )
732 eVertOrient = VertOrientation::LINE_TOP;
733 else if( IsXMLToken( sVerticalPos, XML_BOTTOM ) )
734 eVertOrient = VertOrientation::LINE_BOTTOM;
736 if( !sVerticalRel.isEmpty() )
738 if( IsXMLToken( sVerticalRel, XML_BASELINE ) )
740 // TOP and BOTTOM are exchanged for a baseline relation
741 switch( eVertOrient )
743 case VertOrientation::LINE_TOP:
744 eVertOrient = VertOrientation::BOTTOM;
745 break;
746 case VertOrientation::LINE_CENTER:
747 eVertOrient = VertOrientation::CENTER;
748 break;
749 case VertOrientation::LINE_BOTTOM:
750 eVertOrient = VertOrientation::TOP;
751 break;
754 else if( IsXMLToken( sVerticalRel, XML_CHAR ) )
756 switch( eVertOrient )
758 case VertOrientation::LINE_TOP:
759 eVertOrient = VertOrientation::CHAR_TOP;
760 break;
761 case VertOrientation::LINE_CENTER:
762 eVertOrient = VertOrientation::CHAR_CENTER;
763 break;
764 case VertOrientation::LINE_BOTTOM:
765 eVertOrient = VertOrientation::CHAR_BOTTOM;
766 break;
770 rListLevel.SetImageVertOrient( eVertOrient );
773 css::uno::Reference< css::xml::sax::XFastContextHandler > SvxXMLListLevelStyleAttrContext_Impl::createFastChildContext(
774 sal_Int32 nElement,
775 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
777 if ( nElement == XML_ELEMENT(STYLE, XML_LIST_LEVEL_LABEL_ALIGNMENT) )
779 return new SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl( GetImport(),
780 nElement,
781 xAttrList,
782 rListLevel );
784 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
785 return nullptr;
789 SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl::SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl(
790 SvXMLImport& rImport, sal_Int32 /*nElement*/,
791 const Reference< xml::sax::XFastAttributeList > & xAttrList,
792 SvxXMLListLevelStyleContext_Impl& rLLevel ) :
793 SvXMLImportContext( rImport )
795 SvXMLUnitConverter& rUnitConv = GetImport().GetMM100UnitConverter();
797 sal_Int16 eLabelFollowedBy = LabelFollow::LISTTAB;
798 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
800 sal_Int32 nVal;
801 switch( aIter.getToken() )
803 case XML_ELEMENT(TEXT, XML_LABEL_FOLLOWED_BY):
804 case XML_ELEMENT(LO_EXT, XML_LABEL_FOLLOWED_BY):
806 if( eLabelFollowedBy == LabelFollow::NEWLINE)
807 //NewLine from LO_EXT has precedence over other values of the Non LO_EXT namespace
808 break;
809 if( IsXMLToken( aIter, XML_SPACE ) )
810 eLabelFollowedBy = LabelFollow::SPACE;
811 else if( IsXMLToken( aIter, XML_NOTHING ) )
812 eLabelFollowedBy = LabelFollow::NOTHING;
813 else if( IsXMLToken( aIter, XML_NEWLINE ) )
814 eLabelFollowedBy = LabelFollow::NEWLINE;
816 break;
817 case XML_ELEMENT(TEXT, XML_LIST_TAB_STOP_POSITION):
818 if (rUnitConv.convertMeasureToCore(nVal, aIter.toView(), 0, SHRT_MAX))
819 rLLevel.SetListtabStopPosition( nVal );
820 break;
821 case XML_ELEMENT(FO, XML_TEXT_INDENT):
822 case XML_ELEMENT(FO_COMPAT, XML_TEXT_INDENT):
823 if (rUnitConv.convertMeasureToCore(nVal, aIter.toView(), SHRT_MIN, SHRT_MAX))
824 rLLevel.SetFirstLineIndent( nVal );
825 break;
826 case XML_ELEMENT(FO, XML_MARGIN_LEFT):
827 case XML_ELEMENT(FO_COMPAT, XML_MARGIN_LEFT):
828 if (rUnitConv.convertMeasureToCore(nVal, aIter.toView(), SHRT_MIN, SHRT_MAX))
829 rLLevel.SetIndentAt( nVal );
830 break;
831 default:
832 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
835 rLLevel.SetLabelFollowedBy( eLabelFollowedBy );
838 void SvxXMLListStyleContext::SetAttribute( sal_Int32 nElement,
839 const OUString& rValue )
841 if( nElement == XML_ELEMENT(TEXT, XML_CONSECUTIVE_NUMBERING) )
843 m_bConsecutive = IsXMLToken( rValue, XML_TRUE );
845 else
847 SvXMLStyleContext::SetAttribute( nElement, rValue );
851 constexpr OUString sIsPhysical( u"IsPhysical"_ustr );
852 constexpr OUString sNumberingRules( u"NumberingRules"_ustr );
853 constexpr OUString sIsContinuousNumbering( u"IsContinuousNumbering"_ustr );
855 SvxXMLListStyleContext::SvxXMLListStyleContext( SvXMLImport& rImport,
856 bool bOutl )
857 : SvXMLStyleContext( rImport, bOutl ? XmlStyleFamily::TEXT_OUTLINE : XmlStyleFamily::TEXT_LIST )
858 , m_bConsecutive( false )
859 , m_bOutline( bOutl )
863 SvxXMLListStyleContext::~SvxXMLListStyleContext() {}
865 css::uno::Reference< css::xml::sax::XFastContextHandler > SvxXMLListStyleContext::createFastChildContext(
866 sal_Int32 nElement,
867 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
869 if( m_bOutline
870 ? nElement == XML_ELEMENT(TEXT, XML_OUTLINE_LEVEL_STYLE)
871 : ( nElement == XML_ELEMENT(TEXT, XML_LIST_LEVEL_STYLE_NUMBER) ||
872 nElement == XML_ELEMENT(TEXT, XML_LIST_LEVEL_STYLE_BULLET) ||
873 nElement == XML_ELEMENT(TEXT, XML_LIST_LEVEL_STYLE_IMAGE ) ) )
875 rtl::Reference<SvxXMLListLevelStyleContext_Impl> xLevelStyle{
876 new SvxXMLListLevelStyleContext_Impl( GetImport(), nElement, xAttrList )};
877 if( !m_pLevelStyles )
878 m_pLevelStyles = std::make_unique<SvxXMLListStyle_Impl>();
879 m_pLevelStyles->push_back( xLevelStyle );
881 return xLevelStyle;
883 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
884 return nullptr;
887 void SvxXMLListStyleContext::FillUnoNumRule(
888 const Reference<container::XIndexReplace> & rNumRule) const
892 if( m_pLevelStyles && rNumRule.is() )
894 sal_Int32 l_nLevels = rNumRule->getCount();
895 for (const auto& pLevelStyle : *m_pLevelStyles)
897 sal_Int32 nLevel = pLevelStyle->GetLevel();
898 if( nLevel >= 0 && nLevel < l_nLevels )
900 Sequence<beans::PropertyValue> aProps =
901 pLevelStyle->GetProperties();
902 rNumRule->replaceByIndex( nLevel, Any(aProps) );
907 Reference < XPropertySet > xPropSet( rNumRule, UNO_QUERY );
908 Reference< XPropertySetInfo > xPropSetInfo;
909 if (xPropSet.is())
910 xPropSetInfo = xPropSet->getPropertySetInfo();
911 if( xPropSetInfo.is() &&
912 xPropSetInfo->hasPropertyByName( sIsContinuousNumbering ) )
914 xPropSet->setPropertyValue( sIsContinuousNumbering, Any(m_bConsecutive) );
917 catch (const Exception&)
919 TOOLS_WARN_EXCEPTION("xmloff.style", "" );
923 void SvxXMLListStyleContext::CreateAndInsertLate( bool bOverwrite )
925 if( m_bOutline )
927 if( bOverwrite )
929 const Reference< XIndexReplace >& rNumRule =
930 GetImport().GetTextImport()->GetChapterNumbering();
931 // We don't set xNumberingRules here, to avoid using them
932 // as numbering rules.
933 if( rNumRule.is() )
934 FillUnoNumRule(rNumRule);
937 else
939 Reference < XStyle > xStyle;
940 const OUString& rName = GetDisplayName();
941 if( rName.isEmpty() )
943 SetValid( false );
944 return;
947 const Reference < XNameContainer >& rNumStyles =
948 GetImport().GetTextImport()->GetNumberingStyles();
949 if( !rNumStyles.is() )
951 SetValid( false );
952 return;
955 bool bNew = false;
956 if( rNumStyles->hasByName( rName ) )
958 Any aAny = rNumStyles->getByName( rName );
959 aAny >>= xStyle;
961 else
963 Reference< XMultiServiceFactory > xFactory( GetImport().GetModel(),
964 UNO_QUERY );
965 SAL_WARN_IF( !xFactory.is(), "xmloff", "no factory" );
966 if( !xFactory.is() )
967 return;
969 Reference < XInterface > xIfc = xFactory->createInstance("com.sun.star.style.NumberingStyle");
970 if( !xIfc.is() )
971 return;
972 Reference < XStyle > xTmp( xIfc, UNO_QUERY );
973 xStyle = xTmp;
974 if( !xStyle.is() )
975 return;
977 rNumStyles->insertByName( rName, Any(xStyle) );
978 bNew = true;
981 Reference < XPropertySet > xPropSet( xStyle, UNO_QUERY );
982 Reference< XPropertySetInfo > xPropSetInfo =
983 xPropSet->getPropertySetInfo();
984 if( !bNew && xPropSetInfo->hasPropertyByName( sIsPhysical ) )
986 Any aAny = xPropSet->getPropertyValue( sIsPhysical );
987 bNew = !*o3tl::doAccess<bool>(aAny);
990 if ( xPropSetInfo->hasPropertyByName( "Hidden" ) )
991 xPropSet->setPropertyValue( "Hidden", uno::Any( IsHidden( ) ) );
993 if( rName != GetName() )
994 GetImport().AddStyleDisplayName( XmlStyleFamily::TEXT_LIST,
995 GetName(), rName );
997 Any aAny = xPropSet->getPropertyValue( sNumberingRules );
998 aAny >>= m_xNumRules;
999 if( bOverwrite || bNew )
1001 FillUnoNumRule(m_xNumRules);
1002 xPropSet->setPropertyValue( sNumberingRules, Any(m_xNumRules) );
1004 else
1006 SetValid( false );
1009 SetNew( bNew );
1013 void SvxXMLListStyleContext::CreateAndInsertAuto() const
1015 SAL_WARN_IF( m_bOutline, "xmloff", "Outlines cannot be inserted here" );
1016 SAL_WARN_IF( m_xNumRules.is(), "xmloff", "Numbering Rule is existing already" );
1018 const OUString& rName = GetName();
1019 if( m_bOutline || m_xNumRules.is() || rName.isEmpty() )
1021 const_cast<SvxXMLListStyleContext *>(this)->SetValid( false );
1022 return;
1025 const_cast<SvxXMLListStyleContext *>(this)->m_xNumRules = CreateNumRule(
1026 GetImport().GetModel() );
1028 FillUnoNumRule(m_xNumRules);
1031 Reference < XIndexReplace > SvxXMLListStyleContext::CreateNumRule(
1032 const Reference < XModel > & rModel )
1034 Reference<XIndexReplace> xNumRule;
1036 Reference< XMultiServiceFactory > xFactory( rModel, UNO_QUERY );
1037 SAL_WARN_IF( !xFactory.is(), "xmloff", "no factory" );
1038 if( !xFactory.is() )
1039 return xNumRule;
1041 Reference < XInterface > xIfc = xFactory->createInstance("com.sun.star.text.NumberingRules");
1042 if( !xIfc.is() )
1043 return xNumRule;
1045 xNumRule.set( xIfc, UNO_QUERY );
1046 SAL_WARN_IF( !xNumRule.is(), "xmloff", "go no numbering rule" );
1048 return xNumRule;
1051 void SvxXMLListStyleContext::SetDefaultStyle(
1052 const Reference < XIndexReplace > & rNumRule,
1053 sal_Int16 nLevel,
1054 bool bOrdered )
1056 Sequence<beans::PropertyValue> aPropSeq( bOrdered ? 1 : 4 );
1057 beans::PropertyValue *pProps = aPropSeq.getArray();
1059 pProps->Name = "NumberingType";
1060 (pProps++)->Value <<= static_cast<sal_Int16>(bOrdered ? NumberingType::ARABIC
1061 : NumberingType::CHAR_SPECIAL );
1062 if( !bOrdered )
1064 // TODO: Bullet-Font
1065 awt::FontDescriptor aFDesc;
1066 aFDesc.Name =
1067 #ifdef _WIN32
1068 "StarBats"
1069 #else
1070 "starbats"
1071 #endif
1073 aFDesc.Family = FAMILY_DONTKNOW ;
1074 aFDesc.Pitch = PITCH_DONTKNOW ;
1075 aFDesc.CharSet = RTL_TEXTENCODING_SYMBOL ;
1076 aFDesc.Weight = WEIGHT_DONTKNOW;
1077 pProps->Name = "BulletFont";
1078 (pProps++)->Value <<= aFDesc;
1080 pProps->Name = "BulletChar";
1081 (pProps++)->Value <<= OUString(sal_Unicode(0xF000 + 149));
1082 pProps->Name = "CharStyleName";
1083 (pProps++)->Value <<= OUString( "Numbering Symbols" );
1086 rNumRule->replaceByIndex( nLevel, Any(aPropSeq) );
1089 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */