Version 7.5.1.1, tag libreoffice-7.5.1.1
[LibreOffice.git] / xmloff / source / style / xmlnumi.cxx
blobf75a325ba0de116f5d987fb98f0899b0ffbbbeba
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 void SetRelSize( sal_Int16 nRel ) { nRelSize = nRel; }
161 void SetColor( Color nColor )
162 { m_nColor = nColor; bHasColor = true; }
163 void SetSpaceBefore( sal_Int32 nSet ) { nSpaceBefore = nSet; }
164 void SetMinLabelWidth( sal_Int32 nSet ) { nMinLabelWidth = nSet; }
165 void SetMinLabelDist( sal_Int32 nSet ) { nMinLabelDist = nSet; }
166 void SetAdjust( sal_Int16 eSet ) { eAdjust = eSet; }
168 void SetBulletFontName( const OUString& rSet ) { sBulletFontName = rSet; }
169 void SetBulletFontStyleName( const OUString& rSet )
170 { sBulletFontStyleName = rSet; }
171 void SetBulletFontFamily( sal_Int16 eSet ) { eBulletFontFamily = eSet; }
172 void SetBulletFontPitch( sal_Int16 eSet ) { eBulletFontPitch = eSet; }
173 void SetBulletFontEncoding( rtl_TextEncoding eSet )
174 { eBulletFontEncoding = eSet; }
176 void SetImageWidth( sal_Int32 nSet ) { nImageWidth = nSet; }
177 void SetImageHeight( sal_Int32 nSet ) { nImageHeight = nSet; }
178 void SetImageVertOrient( sal_Int16 eSet )
179 { eImageVertOrient = eSet; }
181 public:
183 SvxXMLListLevelStyleContext_Impl(
184 SvXMLImport& rImport, sal_Int32 nElement,
185 const Reference< xml::sax::XFastAttributeList > & xAttrList );
187 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
188 sal_Int32 nElement,
189 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
191 sal_Int32 GetLevel() const { return nLevel; }
192 Sequence<beans::PropertyValue> GetProperties();
194 void SetPosAndSpaceMode( sal_Int16 eValue )
196 ePosAndSpaceMode = eValue;
198 void SetLabelFollowedBy( sal_Int16 eValue )
200 eLabelFollowedBy = eValue;
202 void SetListtabStopPosition( sal_Int32 nValue )
204 nListtabStopPosition = nValue;
206 void SetFirstLineIndent( sal_Int32 nValue )
208 nFirstLineIndent = nValue;
210 void SetIndentAt( sal_Int32 nValue )
212 nIndentAt = nValue;
216 constexpr OUStringLiteral gsStarBats( u"StarBats" );
217 constexpr OUStringLiteral gsStarMath( u"StarMath" );
219 SvxXMLListLevelStyleContext_Impl::SvxXMLListLevelStyleContext_Impl(
220 SvXMLImport& rImport, sal_Int32 nElement,
221 const Reference< xml::sax::XFastAttributeList > & xAttrList )
223 : SvXMLImportContext( rImport )
224 , sNumFormat( "1" )
225 , nLevel( -1 )
226 , nSpaceBefore( 0 )
227 , nMinLabelWidth( 0 )
228 , nMinLabelDist( 0 )
229 , nImageWidth( 0 )
230 , nImageHeight( 0 )
231 , nNumStartValue( 1 )
232 , nNumDisplayLevels( 1 )
233 , eAdjust( HoriOrientation::LEFT )
234 , eBulletFontFamily( FAMILY_DONTKNOW )
235 , eBulletFontPitch( PITCH_DONTKNOW )
236 , eBulletFontEncoding( RTL_TEXTENCODING_DONTKNOW )
237 , eImageVertOrient(0)
238 , cBullet( 0 )
239 , nRelSize(0)
240 , m_nColor(0)
241 , ePosAndSpaceMode( PositionAndSpaceMode::LABEL_WIDTH_AND_POSITION )
242 , eLabelFollowedBy( LabelFollow::LISTTAB )
243 , nListtabStopPosition( 0 )
244 , nFirstLineIndent( 0 )
245 , nIndentAt( 0 )
246 , bBullet( false )
247 , bImage( false )
248 , bNum( false )
249 , bHasColor( false )
251 switch (nElement & TOKEN_MASK)
253 case XML_LIST_LEVEL_STYLE_NUMBER:
254 case XML_OUTLINE_LEVEL_STYLE:
255 bNum = true;
256 break;
257 case XML_LIST_LEVEL_STYLE_BULLET:
258 bBullet = true;
259 break;
260 case XML_LIST_LEVEL_STYLE_IMAGE:
261 bImage = true;
262 break;
265 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
267 switch( aIter.getToken() )
269 case XML_ELEMENT(TEXT, XML_LEVEL):
270 nLevel = aIter.toInt32();
271 if( nLevel >= 1 )
272 nLevel--;
273 else
274 nLevel = 0;
275 break;
276 case XML_ELEMENT(TEXT, XML_STYLE_NAME):
277 sTextStyleName = aIter.toString();
278 break;
279 case XML_ELEMENT(TEXT, XML_BULLET_CHAR):
280 if (!aIter.isEmpty())
282 cBullet = aIter.toString().iterateCodePoints(&o3tl::temporary(sal_Int32(0)));
284 break;
285 case XML_ELEMENT(XLINK, XML_HREF):
286 if( bImage )
287 sImageURL = aIter.toString();
288 break;
289 case XML_ELEMENT(XLINK, XML_TYPE):
290 case XML_ELEMENT(XLINK, XML_SHOW):
291 case XML_ELEMENT(XLINK, XML_ACTUATE):
292 // This properties will be ignored
293 break;
294 case XML_ELEMENT(STYLE, XML_NUM_FORMAT):
295 if( bNum )
296 sNumFormat = aIter.toString();
297 break;
298 case XML_ELEMENT(STYLE, XML_NUM_PREFIX):
299 sPrefix = aIter.toString();
300 break;
301 case XML_ELEMENT(STYLE, XML_NUM_SUFFIX):
302 sSuffix = aIter.toString();
303 break;
304 case XML_ELEMENT(STYLE, XML_NUM_LIST_FORMAT):
305 case XML_ELEMENT(LO_EXT, XML_NUM_LIST_FORMAT):
306 sListFormat = std::make_optional(aIter.toString());
307 break;
308 case XML_ELEMENT(STYLE, XML_NUM_LETTER_SYNC):
309 if( bNum )
310 sNumLetterSync = aIter.toString();
311 break;
312 case XML_ELEMENT(TEXT, XML_START_VALUE):
313 if( bNum )
315 sal_Int32 nTmp = aIter.toInt32();
316 nNumStartValue =
317 (nTmp < 0) ? 1 : ( (nTmp>SHRT_MAX) ? SHRT_MAX
318 : static_cast<sal_Int16>(nTmp) );
320 break;
321 case XML_ELEMENT(TEXT, XML_DISPLAY_LEVELS):
322 if( bNum )
324 sal_Int32 nTmp = aIter.toInt32();
325 nNumDisplayLevels =
326 (nTmp < 1) ? 1 : ( (nTmp>SHRT_MAX) ? SHRT_MAX
327 : static_cast<sal_Int16>(nTmp) );
329 break;
330 default:
331 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
336 css::uno::Reference< css::xml::sax::XFastContextHandler > SvxXMLListLevelStyleContext_Impl::createFastChildContext(
337 sal_Int32 nElement,
338 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
340 if( nElement == XML_ELEMENT(STYLE, XML_LIST_LEVEL_PROPERTIES) ||
341 nElement == XML_ELEMENT(STYLE, XML_TEXT_PROPERTIES) )
343 return new SvxXMLListLevelStyleAttrContext_Impl( GetImport(),
344 nElement,
345 xAttrList,
346 *this );
348 else if( nElement == XML_ELEMENT(OFFICE, XML_BINARY_DATA) )
350 if( bImage && sImageURL.isEmpty() && !xBase64Stream.is() )
352 xBase64Stream = GetImport().GetStreamForGraphicObjectURLFromBase64();
353 if( xBase64Stream.is() )
354 return new XMLBase64ImportContext( GetImport(), xBase64Stream );
357 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
358 return nullptr;
361 Sequence<beans::PropertyValue> SvxXMLListLevelStyleContext_Impl::GetProperties()
363 if (!bBullet && !bImage && !bNum)
365 return Sequence<beans::PropertyValue>();
368 sal_Int16 eType = NumberingType::NUMBER_NONE;
369 std::vector<beans::PropertyValue> aProperties;
371 if( bBullet )
373 eType = NumberingType::CHAR_SPECIAL;
375 if( bImage )
377 eType = NumberingType::BITMAP;
379 if( bNum )
381 eType = NumberingType::ARABIC;
382 GetImport().GetMM100UnitConverter().convertNumFormat(
383 eType, sNumFormat, sNumLetterSync, true );
386 if (bBullet && !sSuffix.isEmpty())
388 sal_uInt16 const nVersion(GetImport().getGeneratorVersion());
389 sal_Int32 nUPD;
390 sal_Int32 nBuildId;
391 if (GetImport().getBuildIds(nUPD, nBuildId)
392 && ( (SvXMLImport::OOo_1x == nVersion)
393 || (SvXMLImport::OOo_2x == nVersion)
394 || (310 == nUPD) || (320 == nUPD) || (330 == nUPD)
395 || ((300 == nUPD) && (nBuildId <= 9573))))
397 // #i93908# OOo < 3.4 wrote a bogus suffix for bullet chars
398 sSuffix.clear(); // clear it
402 if (!sListFormat.has_value())
404 // This is older document: it has no list format, but can probably contain prefix and/or suffix
405 // Generate list format string, based on this
406 sListFormat = std::make_optional(sPrefix);
408 for (int i = 1; i <= nNumDisplayLevels; i++)
410 *sListFormat += "%";
411 *sListFormat += OUString::number(nLevel - nNumDisplayLevels + i + 1);
412 *sListFormat += "%";
413 if (i != nNumDisplayLevels)
414 *sListFormat += "."; // Default separator for older ODT
417 *sListFormat += sSuffix;
420 aProperties.push_back(comphelper::makePropertyValue("NumberingType", eType));
422 aProperties.push_back(comphelper::makePropertyValue("Prefix", sPrefix));
424 aProperties.push_back(comphelper::makePropertyValue("Suffix", sSuffix));
426 aProperties.push_back(comphelper::makePropertyValue("Adjust", eAdjust));
428 sal_Int32 nLeftMargin = nSpaceBefore + nMinLabelWidth;
429 aProperties.push_back(comphelper::makePropertyValue("LeftMargin", nLeftMargin));
431 sal_Int32 nFirstLineOffset = -nMinLabelWidth;
432 aProperties.push_back(comphelper::makePropertyValue("FirstLineOffset", nFirstLineOffset));
434 aProperties.push_back(comphelper::makePropertyValue("SymbolTextDistance", static_cast<sal_Int16>(nMinLabelDist)));
436 aProperties.push_back(comphelper::makePropertyValue("PositionAndSpaceMode", ePosAndSpaceMode));
438 aProperties.push_back(comphelper::makePropertyValue("LabelFollowedBy", eLabelFollowedBy));
440 aProperties.push_back(comphelper::makePropertyValue("ListtabStopPosition", nListtabStopPosition));
442 aProperties.push_back(comphelper::makePropertyValue("FirstLineIndent", nFirstLineIndent));
444 aProperties.push_back(comphelper::makePropertyValue("IndentAt", nIndentAt));
446 OUString sDisplayTextStyleName = GetImport().GetStyleDisplayName(XmlStyleFamily::TEXT_TEXT, sTextStyleName);
447 aProperties.push_back(comphelper::makePropertyValue("CharStyleName", sDisplayTextStyleName));
449 if( bBullet )
451 awt::FontDescriptor aFDesc;
452 aFDesc.Name = sBulletFontName;
453 if( !sBulletFontName.isEmpty() )
455 aFDesc.StyleName = sBulletFontStyleName;
456 aFDesc.Family = eBulletFontFamily;
457 aFDesc.Pitch = eBulletFontPitch;
458 aFDesc.CharSet = eBulletFontEncoding;
459 aFDesc.Weight = WEIGHT_DONTKNOW;
460 bool bStarSymbol = false;
461 if( aFDesc.Name.equalsIgnoreAsciiCase( gsStarBats ) )
463 cBullet = GetImport().ConvStarBatsCharToStarSymbol( cBullet );
464 bStarSymbol = true;
466 else if( aFDesc.Name.equalsIgnoreAsciiCase( gsStarMath ) )
468 cBullet = GetImport().ConvStarMathCharToStarSymbol( cBullet );
469 bStarSymbol = true;
471 if( bStarSymbol )
472 aFDesc.Name = "StarSymbol" ;
475 // Must append 'cBullet' even if it is zero
476 // if 'bBullet' is true and 'cBullet' is zero - BulletChar property must be 0.
477 aProperties.push_back(comphelper::makePropertyValue("BulletChar", OUString(&cBullet, 1)));
478 aProperties.push_back(comphelper::makePropertyValue("BulletFont", aFDesc));
481 if( bImage )
483 uno::Reference<graphic::XGraphic> xGraphic;
484 if (!sImageURL.isEmpty())
486 xGraphic = GetImport().loadGraphicByURL(sImageURL);
488 else if( xBase64Stream.is() )
490 xGraphic = GetImport().loadGraphicFromBase64(xBase64Stream);
493 uno::Reference<awt::XBitmap> xBitmap;
494 if (xGraphic.is())
495 xBitmap.set(xGraphic, uno::UNO_QUERY);
497 if (xBitmap.is())
499 aProperties.push_back(comphelper::makePropertyValue("GraphicBitmap", xBitmap));
502 awt::Size aSize(nImageWidth, nImageHeight);
503 aProperties.push_back(comphelper::makePropertyValue("GraphicSize", aSize));
504 aProperties.push_back(comphelper::makePropertyValue("VertOrient", eImageVertOrient));
507 if( bNum )
509 aProperties.push_back(comphelper::makePropertyValue("StartWith", nNumStartValue));
510 aProperties.push_back(comphelper::makePropertyValue("ParentNumbering", nNumDisplayLevels));
513 if( ( bNum || bBullet ) && nRelSize )
515 aProperties.push_back(comphelper::makePropertyValue("BulletRelSize", nRelSize));
518 if( !bImage && bHasColor )
520 aProperties.push_back(comphelper::makePropertyValue("BulletColor", m_nColor));
523 aProperties.push_back(comphelper::makePropertyValue("ListFormat", *sListFormat));
525 return comphelper::containerToSequence(aProperties);
528 SvxXMLListLevelStyleAttrContext_Impl::SvxXMLListLevelStyleAttrContext_Impl(
529 SvXMLImport& rImport, sal_Int32 /*nElement*/,
530 const Reference< xml::sax::XFastAttributeList > & xAttrList,
531 SvxXMLListLevelStyleContext_Impl& rLLevel ) :
532 SvXMLImportContext( rImport ),
533 rListLevel( rLLevel )
535 SvXMLUnitConverter& rUnitConv = GetImport().GetMM100UnitConverter();
537 OUString sFontName, sFontFamily, sFontStyleName, sFontFamilyGeneric,
538 sFontPitch, sFontCharset;
539 OUString sVerticalPos, sVerticalRel;
541 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
543 sal_Int32 nVal;
544 switch( aIter.getToken() )
546 case XML_ELEMENT(TEXT, XML_SPACE_BEFORE):
547 if (rUnitConv.convertMeasureToCore(nVal, aIter.toView(), SHRT_MIN, SHRT_MAX))
548 rListLevel.SetSpaceBefore( nVal );
549 break;
550 case XML_ELEMENT(TEXT, XML_MIN_LABEL_WIDTH):
551 if (rUnitConv.convertMeasureToCore( nVal, aIter.toView(), 0, SHRT_MAX ))
552 rListLevel.SetMinLabelWidth( nVal );
553 break;
554 case XML_ELEMENT(TEXT, XML_MIN_LABEL_DISTANCE):
555 if (rUnitConv.convertMeasureToCore( nVal, aIter.toView(), 0, USHRT_MAX ))
556 rListLevel.SetMinLabelDist( nVal );
557 break;
558 case XML_ELEMENT(FO, XML_TEXT_ALIGN):
559 case XML_ELEMENT(FO_COMPAT, XML_TEXT_ALIGN):
560 if( !aIter.isEmpty() )
562 sal_Int16 eAdjust = HoriOrientation::LEFT;
563 if( IsXMLToken( aIter, XML_CENTER ) )
564 eAdjust = HoriOrientation::CENTER;
565 else if( IsXMLToken( aIter, XML_END ) )
566 eAdjust = HoriOrientation::RIGHT;
567 rListLevel.SetAdjust( eAdjust );
569 break;
570 case XML_ELEMENT(STYLE, XML_FONT_NAME):
571 sFontName = aIter.toString();
572 break;
573 case XML_ELEMENT(FO, XML_FONT_FAMILY):
574 case XML_ELEMENT(FO_COMPAT, XML_FONT_FAMILY):
575 sFontFamily = aIter.toString();
576 break;
577 case XML_ELEMENT(STYLE, XML_FONT_FAMILY_GENERIC):
578 sFontFamilyGeneric = aIter.toString();
579 break;
580 case XML_ELEMENT(STYLE, XML_FONT_STYLE_NAME):
581 sFontStyleName = aIter.toString();
582 break;
583 case XML_ELEMENT(STYLE, XML_FONT_PITCH):
584 sFontPitch = aIter.toString();
585 break;
586 case XML_ELEMENT(STYLE, XML_FONT_CHARSET):
587 sFontCharset = aIter.toString();
588 break;
589 case XML_ELEMENT(STYLE, XML_VERTICAL_POS):
590 sVerticalPos = aIter.toString();
591 break;
592 case XML_ELEMENT(STYLE, XML_VERTICAL_REL):
593 sVerticalRel = aIter.toString();
594 break;
595 case XML_ELEMENT(FO, XML_WIDTH):
596 case XML_ELEMENT(FO_COMPAT, XML_WIDTH):
597 if (rUnitConv.convertMeasureToCore(nVal, aIter.toView()))
598 rListLevel.SetImageWidth( nVal );
599 break;
600 case XML_ELEMENT(FO, XML_HEIGHT):
601 case XML_ELEMENT(FO_COMPAT, XML_HEIGHT):
602 if (rUnitConv.convertMeasureToCore(nVal, aIter.toView()))
603 rListLevel.SetImageHeight( nVal );
604 break;
605 case XML_ELEMENT(FO, XML_COLOR):
606 case XML_ELEMENT(FO_COMPAT, XML_COLOR):
608 Color nColor;
609 if (::sax::Converter::convertColor( nColor, aIter.toView() ))
610 rListLevel.SetColor( nColor );
612 break;
613 case XML_ELEMENT(STYLE, XML_USE_WINDOW_FONT_COLOR):
615 if( IsXMLToken( aIter, XML_TRUE ) )
616 rListLevel.SetColor(COL_AUTO);
618 break;
619 case XML_ELEMENT(FO, XML_FONT_SIZE):
620 case XML_ELEMENT(FO_COMPAT, XML_FONT_SIZE):
621 if (::sax::Converter::convertPercent( nVal, aIter.toView() ))
622 rListLevel.SetRelSize( static_cast<sal_Int16>(nVal) );
623 break;
624 case XML_ELEMENT(TEXT, XML_LIST_LEVEL_POSITION_AND_SPACE_MODE):
626 sal_Int16 ePosAndSpaceMode = PositionAndSpaceMode::LABEL_WIDTH_AND_POSITION;
627 if( IsXMLToken( aIter, XML_LABEL_ALIGNMENT ) )
628 ePosAndSpaceMode = PositionAndSpaceMode::LABEL_ALIGNMENT;
629 rListLevel.SetPosAndSpaceMode( ePosAndSpaceMode );
631 break;
632 default:
633 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
637 if( !sFontName.isEmpty() )
639 const XMLFontStylesContext *pFontDecls =
640 GetImport().GetFontDecls();
641 if( pFontDecls )
643 ::std::vector < XMLPropertyState > aProps;
644 if( pFontDecls->FillProperties( sFontName, aProps, 0, 1, 2, 3, 4 ) )
646 OUString sTmp;
647 sal_Int16 nTmp = 0;
648 for( const auto& rProp : aProps )
650 switch( rProp.mnIndex )
652 case 0:
653 rProp.maValue >>= sTmp;
654 rListLevel.SetBulletFontName( sTmp);
655 break;
656 case 1:
657 rProp.maValue >>= sTmp;
658 rListLevel.SetBulletFontStyleName( sTmp );
659 break;
660 case 2:
661 rProp.maValue >>= nTmp;
662 rListLevel.SetBulletFontFamily( nTmp );
663 break;
664 case 3:
665 rProp.maValue >>= nTmp;
666 rListLevel.SetBulletFontPitch( nTmp );
667 break;
668 case 4:
669 rProp.maValue >>= nTmp;
670 rListLevel.SetBulletFontEncoding( nTmp );
671 break;
677 if( !sFontFamily.isEmpty() )
679 Any aAny;
681 XMLFontFamilyNamePropHdl aFamilyNameHdl;
682 if( aFamilyNameHdl.importXML( sFontFamily, aAny, rUnitConv ) )
684 OUString sTmp;
685 aAny >>= sTmp;
686 rListLevel.SetBulletFontName( sTmp);
689 XMLFontFamilyPropHdl aFamilyHdl;
690 if( !sFontFamilyGeneric.isEmpty() &&
691 aFamilyHdl.importXML( sFontFamilyGeneric, aAny, rUnitConv ) )
693 sal_Int16 nTmp = 0;
694 aAny >>= nTmp;
695 rListLevel.SetBulletFontFamily( nTmp );
698 if( !sFontStyleName.isEmpty() )
699 rListLevel.SetBulletFontStyleName( sFontStyleName );
701 XMLFontPitchPropHdl aPitchHdl;
702 if( !sFontPitch.isEmpty() &&
703 aPitchHdl.importXML( sFontPitch, aAny, rUnitConv ) )
705 sal_Int16 nTmp = 0;
706 aAny >>= nTmp;
707 rListLevel.SetBulletFontPitch( nTmp );
710 XMLFontEncodingPropHdl aEncHdl;
711 if( !sFontCharset.isEmpty() &&
712 aEncHdl.importXML( sFontCharset, aAny, rUnitConv ) )
714 sal_Int16 nTmp = 0;
715 aAny >>= nTmp;
716 rListLevel.SetBulletFontEncoding( nTmp );
720 sal_Int16 eVertOrient = VertOrientation::LINE_CENTER;
721 if( !sVerticalPos.isEmpty() )
723 if( IsXMLToken( sVerticalPos, XML_TOP ) )
724 eVertOrient = VertOrientation::LINE_TOP;
725 else if( IsXMLToken( sVerticalPos, XML_BOTTOM ) )
726 eVertOrient = VertOrientation::LINE_BOTTOM;
728 if( !sVerticalRel.isEmpty() )
730 if( IsXMLToken( sVerticalRel, XML_BASELINE ) )
732 // TOP and BOTTOM are exchanged for a baseline relation
733 switch( eVertOrient )
735 case VertOrientation::LINE_TOP:
736 eVertOrient = VertOrientation::BOTTOM;
737 break;
738 case VertOrientation::LINE_CENTER:
739 eVertOrient = VertOrientation::CENTER;
740 break;
741 case VertOrientation::LINE_BOTTOM:
742 eVertOrient = VertOrientation::TOP;
743 break;
746 else if( IsXMLToken( sVerticalRel, XML_CHAR ) )
748 switch( eVertOrient )
750 case VertOrientation::LINE_TOP:
751 eVertOrient = VertOrientation::CHAR_TOP;
752 break;
753 case VertOrientation::LINE_CENTER:
754 eVertOrient = VertOrientation::CHAR_CENTER;
755 break;
756 case VertOrientation::LINE_BOTTOM:
757 eVertOrient = VertOrientation::CHAR_BOTTOM;
758 break;
762 rListLevel.SetImageVertOrient( eVertOrient );
765 css::uno::Reference< css::xml::sax::XFastContextHandler > SvxXMLListLevelStyleAttrContext_Impl::createFastChildContext(
766 sal_Int32 nElement,
767 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
769 if ( nElement == XML_ELEMENT(STYLE, XML_LIST_LEVEL_LABEL_ALIGNMENT) )
771 return new SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl( GetImport(),
772 nElement,
773 xAttrList,
774 rListLevel );
776 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
777 return nullptr;
781 SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl::SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl(
782 SvXMLImport& rImport, sal_Int32 /*nElement*/,
783 const Reference< xml::sax::XFastAttributeList > & xAttrList,
784 SvxXMLListLevelStyleContext_Impl& rLLevel ) :
785 SvXMLImportContext( rImport )
787 SvXMLUnitConverter& rUnitConv = GetImport().GetMM100UnitConverter();
789 sal_Int16 eLabelFollowedBy = LabelFollow::LISTTAB;
790 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
792 sal_Int32 nVal;
793 switch( aIter.getToken() )
795 case XML_ELEMENT(TEXT, XML_LABEL_FOLLOWED_BY):
796 case XML_ELEMENT(LO_EXT, XML_LABEL_FOLLOWED_BY):
798 if( eLabelFollowedBy == LabelFollow::NEWLINE)
799 //NewLine from LO_EXT has precedence over other values of the Non LO_EXT namespace
800 break;
801 if( IsXMLToken( aIter, XML_SPACE ) )
802 eLabelFollowedBy = LabelFollow::SPACE;
803 else if( IsXMLToken( aIter, XML_NOTHING ) )
804 eLabelFollowedBy = LabelFollow::NOTHING;
805 else if( IsXMLToken( aIter, XML_NEWLINE ) )
806 eLabelFollowedBy = LabelFollow::NEWLINE;
808 break;
809 case XML_ELEMENT(TEXT, XML_LIST_TAB_STOP_POSITION):
810 if (rUnitConv.convertMeasureToCore(nVal, aIter.toView(), 0, SHRT_MAX))
811 rLLevel.SetListtabStopPosition( nVal );
812 break;
813 case XML_ELEMENT(FO, XML_TEXT_INDENT):
814 case XML_ELEMENT(FO_COMPAT, XML_TEXT_INDENT):
815 if (rUnitConv.convertMeasureToCore(nVal, aIter.toView(), SHRT_MIN, SHRT_MAX))
816 rLLevel.SetFirstLineIndent( nVal );
817 break;
818 case XML_ELEMENT(FO, XML_MARGIN_LEFT):
819 case XML_ELEMENT(FO_COMPAT, XML_MARGIN_LEFT):
820 if (rUnitConv.convertMeasureToCore(nVal, aIter.toView(), SHRT_MIN, SHRT_MAX))
821 rLLevel.SetIndentAt( nVal );
822 break;
823 default:
824 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
827 rLLevel.SetLabelFollowedBy( eLabelFollowedBy );
830 void SvxXMLListStyleContext::SetAttribute( sal_Int32 nElement,
831 const OUString& rValue )
833 if( nElement == XML_ELEMENT(TEXT, XML_CONSECUTIVE_NUMBERING) )
835 bConsecutive = IsXMLToken( rValue, XML_TRUE );
837 else
839 SvXMLStyleContext::SetAttribute( nElement, rValue );
843 constexpr OUStringLiteral sIsPhysical( u"IsPhysical" );
844 constexpr OUStringLiteral sNumberingRules( u"NumberingRules" );
845 constexpr OUStringLiteral sIsContinuousNumbering( u"IsContinuousNumbering" );
847 SvxXMLListStyleContext::SvxXMLListStyleContext( SvXMLImport& rImport,
848 bool bOutl )
849 : SvXMLStyleContext( rImport, bOutl ? XmlStyleFamily::TEXT_OUTLINE : XmlStyleFamily::TEXT_LIST )
850 , bConsecutive( false )
851 , bOutline( bOutl )
855 SvxXMLListStyleContext::~SvxXMLListStyleContext() {}
857 css::uno::Reference< css::xml::sax::XFastContextHandler > SvxXMLListStyleContext::createFastChildContext(
858 sal_Int32 nElement,
859 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
861 if( bOutline
862 ? nElement == XML_ELEMENT(TEXT, XML_OUTLINE_LEVEL_STYLE)
863 : ( nElement == XML_ELEMENT(TEXT, XML_LIST_LEVEL_STYLE_NUMBER) ||
864 nElement == XML_ELEMENT(TEXT, XML_LIST_LEVEL_STYLE_BULLET) ||
865 nElement == XML_ELEMENT(TEXT, XML_LIST_LEVEL_STYLE_IMAGE ) ) )
867 rtl::Reference<SvxXMLListLevelStyleContext_Impl> xLevelStyle{
868 new SvxXMLListLevelStyleContext_Impl( GetImport(), nElement, xAttrList )};
869 if( !pLevelStyles )
870 pLevelStyles = std::make_unique<SvxXMLListStyle_Impl>();
871 pLevelStyles->push_back( xLevelStyle );
873 return xLevelStyle;
875 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
876 return nullptr;
879 void SvxXMLListStyleContext::FillUnoNumRule(
880 const Reference<container::XIndexReplace> & rNumRule) const
884 if( pLevelStyles && rNumRule.is() )
886 sal_Int32 l_nLevels = rNumRule->getCount();
887 for (const auto& pLevelStyle : *pLevelStyles)
889 sal_Int32 nLevel = pLevelStyle->GetLevel();
890 if( nLevel >= 0 && nLevel < l_nLevels )
892 Sequence<beans::PropertyValue> aProps =
893 pLevelStyle->GetProperties();
894 rNumRule->replaceByIndex( nLevel, Any(aProps) );
899 Reference < XPropertySet > xPropSet( rNumRule, UNO_QUERY );
900 Reference< XPropertySetInfo > xPropSetInfo;
901 if (xPropSet.is())
902 xPropSetInfo = xPropSet->getPropertySetInfo();
903 if( xPropSetInfo.is() &&
904 xPropSetInfo->hasPropertyByName( sIsContinuousNumbering ) )
906 xPropSet->setPropertyValue( sIsContinuousNumbering, Any(bConsecutive) );
909 catch (const Exception&)
911 TOOLS_WARN_EXCEPTION("xmloff.style", "" );
915 void SvxXMLListStyleContext::CreateAndInsertLate( bool bOverwrite )
917 if( bOutline )
919 if( bOverwrite )
921 const Reference< XIndexReplace >& rNumRule =
922 GetImport().GetTextImport()->GetChapterNumbering();
923 // We don't set xNumberingRules here, to avoid using them
924 // as numbering rules.
925 if( rNumRule.is() )
926 FillUnoNumRule(rNumRule);
929 else
931 Reference < XStyle > xStyle;
932 const OUString& rName = GetDisplayName();
933 if( rName.isEmpty() )
935 SetValid( false );
936 return;
939 const Reference < XNameContainer >& rNumStyles =
940 GetImport().GetTextImport()->GetNumberingStyles();
941 if( !rNumStyles.is() )
943 SetValid( false );
944 return;
947 bool bNew = false;
948 if( rNumStyles->hasByName( rName ) )
950 Any aAny = rNumStyles->getByName( rName );
951 aAny >>= xStyle;
953 else
955 Reference< XMultiServiceFactory > xFactory( GetImport().GetModel(),
956 UNO_QUERY );
957 SAL_WARN_IF( !xFactory.is(), "xmloff", "no factory" );
958 if( !xFactory.is() )
959 return;
961 Reference < XInterface > xIfc = xFactory->createInstance("com.sun.star.style.NumberingStyle");
962 if( !xIfc.is() )
963 return;
964 Reference < XStyle > xTmp( xIfc, UNO_QUERY );
965 xStyle = xTmp;
966 if( !xStyle.is() )
967 return;
969 rNumStyles->insertByName( rName, Any(xStyle) );
970 bNew = true;
973 Reference < XPropertySet > xPropSet( xStyle, UNO_QUERY );
974 Reference< XPropertySetInfo > xPropSetInfo =
975 xPropSet->getPropertySetInfo();
976 if( !bNew && xPropSetInfo->hasPropertyByName( sIsPhysical ) )
978 Any aAny = xPropSet->getPropertyValue( sIsPhysical );
979 bNew = !*o3tl::doAccess<bool>(aAny);
982 if ( xPropSetInfo->hasPropertyByName( "Hidden" ) )
983 xPropSet->setPropertyValue( "Hidden", uno::Any( IsHidden( ) ) );
985 if( rName != GetName() )
986 GetImport().AddStyleDisplayName( XmlStyleFamily::TEXT_LIST,
987 GetName(), rName );
989 Any aAny = xPropSet->getPropertyValue( sNumberingRules );
990 aAny >>= xNumRules;
991 if( bOverwrite || bNew )
993 FillUnoNumRule(xNumRules);
994 xPropSet->setPropertyValue( sNumberingRules, Any(xNumRules) );
996 else
998 SetValid( false );
1001 SetNew( bNew );
1005 void SvxXMLListStyleContext::CreateAndInsertAuto() const
1007 SAL_WARN_IF( bOutline, "xmloff", "Outlines cannot be inserted here" );
1008 SAL_WARN_IF( xNumRules.is(), "xmloff", "Numbering Rule is existing already" );
1010 const OUString& rName = GetName();
1011 if( bOutline || xNumRules.is() || rName.isEmpty() )
1013 const_cast<SvxXMLListStyleContext *>(this)->SetValid( false );
1014 return;
1017 const_cast<SvxXMLListStyleContext *>(this)->xNumRules = CreateNumRule(
1018 GetImport().GetModel() );
1020 FillUnoNumRule(xNumRules);
1023 Reference < XIndexReplace > SvxXMLListStyleContext::CreateNumRule(
1024 const Reference < XModel > & rModel )
1026 Reference<XIndexReplace> xNumRule;
1028 Reference< XMultiServiceFactory > xFactory( rModel, UNO_QUERY );
1029 SAL_WARN_IF( !xFactory.is(), "xmloff", "no factory" );
1030 if( !xFactory.is() )
1031 return xNumRule;
1033 Reference < XInterface > xIfc = xFactory->createInstance("com.sun.star.text.NumberingRules");
1034 if( !xIfc.is() )
1035 return xNumRule;
1037 xNumRule.set( xIfc, UNO_QUERY );
1038 SAL_WARN_IF( !xNumRule.is(), "xmloff", "go no numbering rule" );
1040 return xNumRule;
1043 void SvxXMLListStyleContext::SetDefaultStyle(
1044 const Reference < XIndexReplace > & rNumRule,
1045 sal_Int16 nLevel,
1046 bool bOrdered )
1048 Sequence<beans::PropertyValue> aPropSeq( bOrdered ? 1 : 4 );
1049 beans::PropertyValue *pProps = aPropSeq.getArray();
1051 pProps->Name = "NumberingType";
1052 (pProps++)->Value <<= static_cast<sal_Int16>(bOrdered ? NumberingType::ARABIC
1053 : NumberingType::CHAR_SPECIAL );
1054 if( !bOrdered )
1056 // TODO: Bullet-Font
1057 awt::FontDescriptor aFDesc;
1058 aFDesc.Name =
1059 #ifdef _WIN32
1060 "StarBats"
1061 #else
1062 "starbats"
1063 #endif
1065 aFDesc.Family = FAMILY_DONTKNOW ;
1066 aFDesc.Pitch = PITCH_DONTKNOW ;
1067 aFDesc.CharSet = RTL_TEXTENCODING_SYMBOL ;
1068 aFDesc.Weight = WEIGHT_DONTKNOW;
1069 pProps->Name = "BulletFont";
1070 (pProps++)->Value <<= aFDesc;
1072 pProps->Name = "BulletChar";
1073 (pProps++)->Value <<= OUString(sal_Unicode(0xF000 + 149));
1074 pProps->Name = "CharStyleName";
1075 (pProps++)->Value <<= OUString( "Numbering Symbols" );
1078 rNumRule->replaceByIndex( nLevel, Any(aPropSeq) );
1081 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */