diff options
Diffstat (limited to '')
-rw-r--r-- | xmloff/source/style/xmlnumi.cxx | 1089 |
1 files changed, 1089 insertions, 0 deletions
diff --git a/xmloff/source/style/xmlnumi.cxx b/xmloff/source/style/xmlnumi.cxx new file mode 100644 index 0000000000..0ddab1466d --- /dev/null +++ b/xmloff/source/style/xmlnumi.cxx @@ -0,0 +1,1089 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/awt/FontDescriptor.hpp> +#include <com/sun/star/text/HoriOrientation.hpp> +#include <com/sun/star/text/VertOrientation.hpp> +#include <com/sun/star/text/PositionAndSpaceMode.hpp> +#include <com/sun/star/text/LabelFollow.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/style/XStyle.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/awt/XBitmap.hpp> +#include <com/sun/star/style/NumberingType.hpp> +#include <com/sun/star/container/XIndexReplace.hpp> + +#include <o3tl/any.hxx> +#include <o3tl/temporary.hxx> +#include <rtl/ustrbuf.hxx> +#include <sal/log.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/propertyvalue.hxx> + +#include <tools/fontenum.hxx> +#include <tools/color.hxx> + +#include <sax/tools/converter.hxx> + +#include <vcl/vclenum.hxx> + +#include <xmloff/xmltkmap.hxx> +#include <xmloff/namespacemap.hxx> +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/xmlimp.hxx> +#include <xmloff/XMLBase64ImportContext.hxx> +#include <xmloff/xmltoken.hxx> + +#include <xmloff/xmluconv.hxx> +#include "fonthdl.hxx" +#include <xmloff/XMLFontStylesContext.hxx> +#include <xmloff/families.hxx> +#include <xmloff/maptype.hxx> + +#include <xmloff/xmlnumi.hxx> +#include <optional> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::style; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::xmloff::token; +using namespace ::com::sun::star::io; + +class SvxXMLListLevelStyleContext_Impl; + +namespace { + +class SvxXMLListLevelStyleAttrContext_Impl : public SvXMLImportContext +{ + SvxXMLListLevelStyleContext_Impl& rListLevel; + +public: + + SvxXMLListLevelStyleAttrContext_Impl( + SvXMLImport& rImport, sal_Int32 nElement, + const Reference< xml::sax::XFastAttributeList >& xAttrList, + SvxXMLListLevelStyleContext_Impl& rLLevel ); + + virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( + sal_Int32 nElement, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override; +}; + +class SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl : public SvXMLImportContext +{ +public: + + SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl( + SvXMLImport& rImport, sal_Int32 nElement, + const Reference< xml::sax::XFastAttributeList >& xAttrList, + SvxXMLListLevelStyleContext_Impl& rLLevel ); +}; + +} + +class SvxXMLListLevelStyleContext_Impl : public SvXMLImportContext +{ + friend SvxXMLListLevelStyleAttrContext_Impl; + + OUString sPrefix; + OUString sSuffix; + std::optional<OUString> sListFormat; // It is optional to distinguish empty format string + // from not existing format string in old docs + OUString sTextStyleName; + OUString sNumFormat; + OUString sNumLetterSync; + OUString sBulletFontName; + OUString sBulletFontStyleName; + OUString sImageURL; + + Reference < XOutputStream > xBase64Stream; + + sal_Int32 nLevel; + sal_Int32 nSpaceBefore; + sal_Int32 nMinLabelWidth; + sal_Int32 nMinLabelDist; + sal_Int32 nImageWidth; + sal_Int32 nImageHeight; + sal_Int16 nNumStartValue; + sal_Int16 nNumDisplayLevels; + + sal_Int16 eAdjust; + sal_Int16 eBulletFontFamily; + sal_Int16 eBulletFontPitch; + rtl_TextEncoding eBulletFontEncoding; + sal_Int16 eImageVertOrient; + + sal_UCS4 cBullet; + + sal_Int16 nRelSize; + Color m_nColor; + + sal_Int16 ePosAndSpaceMode; + sal_Int16 eLabelFollowedBy; + sal_Int32 nListtabStopPosition; + sal_Int32 nFirstLineIndent; + sal_Int32 nIndentAt; + + bool bBullet : 1; + bool bImage : 1; + bool bNum : 1; + bool bHasColor : 1; + + bool m_bIsLegal = false; + + void SetRelSize( sal_Int16 nRel ) { nRelSize = nRel; } + void SetColor( Color nColor ) + { m_nColor = nColor; bHasColor = true; } + void SetSpaceBefore( sal_Int32 nSet ) { nSpaceBefore = nSet; } + void SetMinLabelWidth( sal_Int32 nSet ) { nMinLabelWidth = nSet; } + void SetMinLabelDist( sal_Int32 nSet ) { nMinLabelDist = nSet; } + void SetAdjust( sal_Int16 eSet ) { eAdjust = eSet; } + + void SetBulletFontName( const OUString& rSet ) { sBulletFontName = rSet; } + void SetBulletFontStyleName( const OUString& rSet ) + { sBulletFontStyleName = rSet; } + void SetBulletFontFamily( sal_Int16 eSet ) { eBulletFontFamily = eSet; } + void SetBulletFontPitch( sal_Int16 eSet ) { eBulletFontPitch = eSet; } + void SetBulletFontEncoding( rtl_TextEncoding eSet ) + { eBulletFontEncoding = eSet; } + + void SetImageWidth( sal_Int32 nSet ) { nImageWidth = nSet; } + void SetImageHeight( sal_Int32 nSet ) { nImageHeight = nSet; } + void SetImageVertOrient( sal_Int16 eSet ) + { eImageVertOrient = eSet; } + +public: + + SvxXMLListLevelStyleContext_Impl( + SvXMLImport& rImport, sal_Int32 nElement, + const Reference< xml::sax::XFastAttributeList > & xAttrList ); + + virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( + sal_Int32 nElement, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override; + + sal_Int32 GetLevel() const { return nLevel; } + Sequence<beans::PropertyValue> GetProperties(); + + void SetPosAndSpaceMode( sal_Int16 eValue ) + { + ePosAndSpaceMode = eValue; + } + void SetLabelFollowedBy( sal_Int16 eValue ) + { + eLabelFollowedBy = eValue; + } + void SetListtabStopPosition( sal_Int32 nValue ) + { + nListtabStopPosition = nValue; + } + void SetFirstLineIndent( sal_Int32 nValue ) + { + nFirstLineIndent = nValue; + } + void SetIndentAt( sal_Int32 nValue ) + { + nIndentAt = nValue; + } +}; + +constexpr OUStringLiteral gsStarBats( u"StarBats" ); +constexpr OUStringLiteral gsStarMath( u"StarMath" ); + +SvxXMLListLevelStyleContext_Impl::SvxXMLListLevelStyleContext_Impl( + SvXMLImport& rImport, sal_Int32 nElement, + const Reference< xml::sax::XFastAttributeList > & xAttrList ) + +: SvXMLImportContext( rImport ) +, sNumFormat( "1" ) +, nLevel( -1 ) +, nSpaceBefore( 0 ) +, nMinLabelWidth( 0 ) +, nMinLabelDist( 0 ) +, nImageWidth( 0 ) +, nImageHeight( 0 ) +, nNumStartValue( 1 ) +, nNumDisplayLevels( 1 ) +, eAdjust( HoriOrientation::LEFT ) +, eBulletFontFamily( FAMILY_DONTKNOW ) +, eBulletFontPitch( PITCH_DONTKNOW ) +, eBulletFontEncoding( RTL_TEXTENCODING_DONTKNOW ) +, eImageVertOrient(0) +, cBullet( 0 ) +, nRelSize(0) +, m_nColor(0) +, ePosAndSpaceMode( PositionAndSpaceMode::LABEL_WIDTH_AND_POSITION ) +, eLabelFollowedBy( LabelFollow::LISTTAB ) +, nListtabStopPosition( 0 ) +, nFirstLineIndent( 0 ) +, nIndentAt( 0 ) +, bBullet( false ) +, bImage( false ) +, bNum( false ) +, bHasColor( false ) +{ + switch (nElement & TOKEN_MASK) + { + case XML_LIST_LEVEL_STYLE_NUMBER: + case XML_OUTLINE_LEVEL_STYLE: + bNum = true; + break; + case XML_LIST_LEVEL_STYLE_BULLET: + bBullet = true; + break; + case XML_LIST_LEVEL_STYLE_IMAGE: + bImage = true; + break; + } + + for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) ) + { + switch( aIter.getToken() ) + { + case XML_ELEMENT(TEXT, XML_LEVEL): + nLevel = aIter.toInt32(); + if( nLevel >= 1 ) + nLevel--; + else + nLevel = 0; + break; + case XML_ELEMENT(TEXT, XML_STYLE_NAME): + sTextStyleName = aIter.toString(); + break; + case XML_ELEMENT(TEXT, XML_BULLET_CHAR): + if (!aIter.isEmpty()) + { + cBullet = aIter.toString().iterateCodePoints(&o3tl::temporary(sal_Int32(0))); + } + break; + case XML_ELEMENT(XLINK, XML_HREF): + if( bImage ) + sImageURL = aIter.toString(); + break; + case XML_ELEMENT(XLINK, XML_TYPE): + case XML_ELEMENT(XLINK, XML_SHOW): + case XML_ELEMENT(XLINK, XML_ACTUATE): + // This properties will be ignored + break; + case XML_ELEMENT(STYLE, XML_NUM_FORMAT): + if( bNum ) + sNumFormat = aIter.toString(); + break; + case XML_ELEMENT(STYLE, XML_NUM_PREFIX): + sPrefix = aIter.toString(); + break; + case XML_ELEMENT(STYLE, XML_NUM_SUFFIX): + sSuffix = aIter.toString(); + break; + case XML_ELEMENT(STYLE, XML_NUM_LIST_FORMAT): + case XML_ELEMENT(LO_EXT, XML_NUM_LIST_FORMAT): + sListFormat = std::make_optional(aIter.toString()); + break; + case XML_ELEMENT(LO_EXT, XML_IS_LEGAL): + m_bIsLegal = aIter.toBoolean(); + break; + case XML_ELEMENT(STYLE, XML_NUM_LETTER_SYNC): + if( bNum ) + sNumLetterSync = aIter.toString(); + break; + case XML_ELEMENT(TEXT, XML_START_VALUE): + if( bNum ) + { + sal_Int32 nTmp = aIter.toInt32(); + nNumStartValue = + (nTmp < 0) ? 1 : ( (nTmp>SHRT_MAX) ? SHRT_MAX + : static_cast<sal_Int16>(nTmp) ); + } + break; + case XML_ELEMENT(TEXT, XML_DISPLAY_LEVELS): + if( bNum ) + { + sal_Int32 nTmp = aIter.toInt32(); + nNumDisplayLevels = + (nTmp < 1) ? 1 : ( (nTmp>SHRT_MAX) ? SHRT_MAX + : static_cast<sal_Int16>(nTmp) ); + } + break; + default: + XMLOFF_WARN_UNKNOWN("xmloff", aIter); + } + } +} + +css::uno::Reference< css::xml::sax::XFastContextHandler > SvxXMLListLevelStyleContext_Impl::createFastChildContext( + sal_Int32 nElement, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) +{ + if( nElement == XML_ELEMENT(STYLE, XML_LIST_LEVEL_PROPERTIES) || + nElement == XML_ELEMENT(STYLE, XML_TEXT_PROPERTIES) ) + { + return new SvxXMLListLevelStyleAttrContext_Impl( GetImport(), + nElement, + xAttrList, + *this ); + } + else if( nElement == XML_ELEMENT(OFFICE, XML_BINARY_DATA) ) + { + if( bImage && sImageURL.isEmpty() && !xBase64Stream.is() ) + { + xBase64Stream = GetImport().GetStreamForGraphicObjectURLFromBase64(); + if( xBase64Stream.is() ) + return new XMLBase64ImportContext( GetImport(), xBase64Stream ); + } + } + XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement); + return nullptr; +} + +Sequence<beans::PropertyValue> SvxXMLListLevelStyleContext_Impl::GetProperties() +{ + if (!bBullet && !bImage && !bNum) + { + return Sequence<beans::PropertyValue>(); + } + + sal_Int16 eType = NumberingType::NUMBER_NONE; + std::vector<beans::PropertyValue> aProperties; + + if( bBullet ) + { + eType = NumberingType::CHAR_SPECIAL; + } + if( bImage ) + { + eType = NumberingType::BITMAP; + } + if( bNum ) + { + eType = NumberingType::ARABIC; + GetImport().GetMM100UnitConverter().convertNumFormat( + eType, sNumFormat, sNumLetterSync, true ); + } + + if (bBullet && !sSuffix.isEmpty()) + { + sal_uInt16 const nVersion(GetImport().getGeneratorVersion()); + sal_Int32 nUPD; + sal_Int32 nBuildId; + if (GetImport().getBuildIds(nUPD, nBuildId) + && ( (SvXMLImport::OOo_1x == nVersion) + || (SvXMLImport::OOo_2x == nVersion) + || (310 == nUPD) || (320 == nUPD) || (330 == nUPD) + || ((300 == nUPD) && (nBuildId <= 9573)))) + { + // #i93908# OOo < 3.4 wrote a bogus suffix for bullet chars + sSuffix.clear(); // clear it + } + } + + if (!sListFormat.has_value()) + { + // This is older document: it has no list format, but can probably contain prefix and/or suffix + // Generate list format string, based on this + sListFormat = std::make_optional(sPrefix); + + for (int i = 1; i <= nNumDisplayLevels; i++) + { + *sListFormat += "%"; + *sListFormat += OUString::number(nLevel - nNumDisplayLevels + i + 1); + *sListFormat += "%"; + if (i != nNumDisplayLevels) + *sListFormat += "."; // Default separator for older ODT + } + + *sListFormat += sSuffix; + } + + aProperties.push_back(comphelper::makePropertyValue("NumberingType", eType)); + + aProperties.push_back(comphelper::makePropertyValue("Prefix", sPrefix)); + + aProperties.push_back(comphelper::makePropertyValue("Suffix", sSuffix)); + + aProperties.push_back(comphelper::makePropertyValue("Adjust", eAdjust)); + + sal_Int32 nLeftMargin = nSpaceBefore + nMinLabelWidth; + aProperties.push_back(comphelper::makePropertyValue("LeftMargin", nLeftMargin)); + + sal_Int32 nFirstLineOffset = -nMinLabelWidth; + aProperties.push_back(comphelper::makePropertyValue("FirstLineOffset", nFirstLineOffset)); + + aProperties.push_back(comphelper::makePropertyValue("SymbolTextDistance", static_cast<sal_Int16>(nMinLabelDist))); + + aProperties.push_back(comphelper::makePropertyValue("PositionAndSpaceMode", ePosAndSpaceMode)); + + aProperties.push_back(comphelper::makePropertyValue("LabelFollowedBy", eLabelFollowedBy)); + + aProperties.push_back(comphelper::makePropertyValue("ListtabStopPosition", nListtabStopPosition)); + + aProperties.push_back(comphelper::makePropertyValue("FirstLineIndent", nFirstLineIndent)); + + aProperties.push_back(comphelper::makePropertyValue("IndentAt", nIndentAt)); + + OUString sDisplayTextStyleName = GetImport().GetStyleDisplayName(XmlStyleFamily::TEXT_TEXT, sTextStyleName); + aProperties.push_back(comphelper::makePropertyValue("CharStyleName", sDisplayTextStyleName)); + + if( bBullet ) + { + awt::FontDescriptor aFDesc; + aFDesc.Name = sBulletFontName; + if( !sBulletFontName.isEmpty() ) + { + aFDesc.StyleName = sBulletFontStyleName; + aFDesc.Family = eBulletFontFamily; + aFDesc.Pitch = eBulletFontPitch; + aFDesc.CharSet = eBulletFontEncoding; + aFDesc.Weight = WEIGHT_DONTKNOW; + bool bStarSymbol = false; + if( aFDesc.Name.equalsIgnoreAsciiCase( gsStarBats ) ) + { + cBullet = GetImport().ConvStarBatsCharToStarSymbol( cBullet ); + bStarSymbol = true; + } + else if( aFDesc.Name.equalsIgnoreAsciiCase( gsStarMath ) ) + { + cBullet = GetImport().ConvStarMathCharToStarSymbol( cBullet ); + bStarSymbol = true; + } + if( bStarSymbol ) + aFDesc.Name = "StarSymbol" ; + } + + // Must append 'cBullet' even if it is zero + // if 'bBullet' is true and 'cBullet' is zero - BulletChar property must be 0. + aProperties.push_back(comphelper::makePropertyValue("BulletChar", OUString(&cBullet, 1))); + aProperties.push_back(comphelper::makePropertyValue("BulletFont", aFDesc)); + } + + if( bImage ) + { + uno::Reference<graphic::XGraphic> xGraphic; + if (!sImageURL.isEmpty()) + { + xGraphic = GetImport().loadGraphicByURL(sImageURL); + } + else if( xBase64Stream.is() ) + { + xGraphic = GetImport().loadGraphicFromBase64(xBase64Stream); + } + + uno::Reference<awt::XBitmap> xBitmap; + if (xGraphic.is()) + xBitmap.set(xGraphic, uno::UNO_QUERY); + + if (xBitmap.is()) + { + aProperties.push_back(comphelper::makePropertyValue("GraphicBitmap", xBitmap)); + } + + awt::Size aSize(nImageWidth, nImageHeight); + aProperties.push_back(comphelper::makePropertyValue("GraphicSize", aSize)); + aProperties.push_back(comphelper::makePropertyValue("VertOrient", eImageVertOrient)); + } + + if( bNum ) + { + aProperties.push_back(comphelper::makePropertyValue("StartWith", nNumStartValue)); + aProperties.push_back(comphelper::makePropertyValue("ParentNumbering", nNumDisplayLevels)); + } + + if( ( bNum || bBullet ) && nRelSize ) + { + aProperties.push_back(comphelper::makePropertyValue("BulletRelSize", nRelSize)); + } + + if( !bImage && bHasColor ) + { + aProperties.push_back(comphelper::makePropertyValue("BulletColor", m_nColor)); + } + + aProperties.push_back(comphelper::makePropertyValue("ListFormat", *sListFormat)); + + if (m_bIsLegal) + aProperties.push_back(comphelper::makePropertyValue("IsLegal", true)); + + return comphelper::containerToSequence(aProperties); +} + +SvxXMLListLevelStyleAttrContext_Impl::SvxXMLListLevelStyleAttrContext_Impl( + SvXMLImport& rImport, sal_Int32 /*nElement*/, + const Reference< xml::sax::XFastAttributeList > & xAttrList, + SvxXMLListLevelStyleContext_Impl& rLLevel ) : + SvXMLImportContext( rImport ), + rListLevel( rLLevel ) +{ + SvXMLUnitConverter& rUnitConv = GetImport().GetMM100UnitConverter(); + + OUString sFontName, sFontFamily, sFontStyleName, sFontFamilyGeneric, + sFontPitch, sFontCharset; + OUString sVerticalPos, sVerticalRel; + + for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) ) + { + sal_Int32 nVal; + switch( aIter.getToken() ) + { + case XML_ELEMENT(TEXT, XML_SPACE_BEFORE): + if (rUnitConv.convertMeasureToCore(nVal, aIter.toView(), SHRT_MIN, SHRT_MAX)) + rListLevel.SetSpaceBefore( nVal ); + break; + case XML_ELEMENT(TEXT, XML_MIN_LABEL_WIDTH): + if (rUnitConv.convertMeasureToCore( nVal, aIter.toView(), 0, SHRT_MAX )) + rListLevel.SetMinLabelWidth( nVal ); + break; + case XML_ELEMENT(TEXT, XML_MIN_LABEL_DISTANCE): + if (rUnitConv.convertMeasureToCore( nVal, aIter.toView(), 0, USHRT_MAX )) + rListLevel.SetMinLabelDist( nVal ); + break; + case XML_ELEMENT(FO, XML_TEXT_ALIGN): + case XML_ELEMENT(FO_COMPAT, XML_TEXT_ALIGN): + if( !aIter.isEmpty() ) + { + sal_Int16 eAdjust = HoriOrientation::LEFT; + if( IsXMLToken( aIter, XML_CENTER ) ) + eAdjust = HoriOrientation::CENTER; + else if( IsXMLToken( aIter, XML_END ) ) + eAdjust = HoriOrientation::RIGHT; + rListLevel.SetAdjust( eAdjust ); + } + break; + case XML_ELEMENT(STYLE, XML_FONT_NAME): + sFontName = aIter.toString(); + break; + case XML_ELEMENT(FO, XML_FONT_FAMILY): + case XML_ELEMENT(FO_COMPAT, XML_FONT_FAMILY): + sFontFamily = aIter.toString(); + break; + case XML_ELEMENT(STYLE, XML_FONT_FAMILY_GENERIC): + sFontFamilyGeneric = aIter.toString(); + break; + case XML_ELEMENT(STYLE, XML_FONT_STYLE_NAME): + sFontStyleName = aIter.toString(); + break; + case XML_ELEMENT(STYLE, XML_FONT_PITCH): + sFontPitch = aIter.toString(); + break; + case XML_ELEMENT(STYLE, XML_FONT_CHARSET): + sFontCharset = aIter.toString(); + break; + case XML_ELEMENT(STYLE, XML_VERTICAL_POS): + sVerticalPos = aIter.toString(); + break; + case XML_ELEMENT(STYLE, XML_VERTICAL_REL): + sVerticalRel = aIter.toString(); + break; + case XML_ELEMENT(FO, XML_WIDTH): + case XML_ELEMENT(FO_COMPAT, XML_WIDTH): + if (rUnitConv.convertMeasureToCore(nVal, aIter.toView())) + rListLevel.SetImageWidth( nVal ); + break; + case XML_ELEMENT(FO, XML_HEIGHT): + case XML_ELEMENT(FO_COMPAT, XML_HEIGHT): + if (rUnitConv.convertMeasureToCore(nVal, aIter.toView())) + rListLevel.SetImageHeight( nVal ); + break; + case XML_ELEMENT(FO, XML_COLOR): + case XML_ELEMENT(FO_COMPAT, XML_COLOR): + { + Color nColor; + if (::sax::Converter::convertColor( nColor, aIter.toView() )) + rListLevel.SetColor( nColor ); + } + break; + case XML_ELEMENT(STYLE, XML_USE_WINDOW_FONT_COLOR): + { + if( IsXMLToken( aIter, XML_TRUE ) ) + rListLevel.SetColor(COL_AUTO); + } + break; + case XML_ELEMENT(FO, XML_FONT_SIZE): + case XML_ELEMENT(FO_COMPAT, XML_FONT_SIZE): + if (::sax::Converter::convertPercent( nVal, aIter.toView() )) + rListLevel.SetRelSize( static_cast<sal_Int16>(nVal) ); + break; + case XML_ELEMENT(TEXT, XML_LIST_LEVEL_POSITION_AND_SPACE_MODE): + { + sal_Int16 ePosAndSpaceMode = PositionAndSpaceMode::LABEL_WIDTH_AND_POSITION; + if( IsXMLToken( aIter, XML_LABEL_ALIGNMENT ) ) + ePosAndSpaceMode = PositionAndSpaceMode::LABEL_ALIGNMENT; + rListLevel.SetPosAndSpaceMode( ePosAndSpaceMode ); + } + break; + default: + XMLOFF_WARN_UNKNOWN("xmloff", aIter); + } + } + + if( !sFontName.isEmpty() ) + { + const XMLFontStylesContext *pFontDecls = + GetImport().GetFontDecls(); + if( pFontDecls ) + { + ::std::vector < XMLPropertyState > aProps; + if( pFontDecls->FillProperties( sFontName, aProps, 0, 1, 2, 3, 4 ) ) + { + OUString sTmp; + sal_Int16 nTmp = 0; + for( const auto& rProp : aProps ) + { + switch( rProp.mnIndex ) + { + case 0: + rProp.maValue >>= sTmp; + rListLevel.SetBulletFontName( sTmp); + break; + case 1: + rProp.maValue >>= sTmp; + rListLevel.SetBulletFontStyleName( sTmp ); + break; + case 2: + rProp.maValue >>= nTmp; + rListLevel.SetBulletFontFamily( nTmp ); + break; + case 3: + rProp.maValue >>= nTmp; + rListLevel.SetBulletFontPitch( nTmp ); + break; + case 4: + rProp.maValue >>= nTmp; + rListLevel.SetBulletFontEncoding( nTmp ); + break; + } + } + } + } + } + if( !sFontFamily.isEmpty() ) + { + Any aAny; + + XMLFontFamilyNamePropHdl aFamilyNameHdl; + if( aFamilyNameHdl.importXML( sFontFamily, aAny, rUnitConv ) ) + { + OUString sTmp; + aAny >>= sTmp; + rListLevel.SetBulletFontName( sTmp); + } + + XMLFontFamilyPropHdl aFamilyHdl; + if( !sFontFamilyGeneric.isEmpty() && + aFamilyHdl.importXML( sFontFamilyGeneric, aAny, rUnitConv ) ) + { + sal_Int16 nTmp = 0; + aAny >>= nTmp; + rListLevel.SetBulletFontFamily( nTmp ); + } + + if( !sFontStyleName.isEmpty() ) + rListLevel.SetBulletFontStyleName( sFontStyleName ); + + XMLFontPitchPropHdl aPitchHdl; + if( !sFontPitch.isEmpty() && + aPitchHdl.importXML( sFontPitch, aAny, rUnitConv ) ) + { + sal_Int16 nTmp = 0; + aAny >>= nTmp; + rListLevel.SetBulletFontPitch( nTmp ); + } + + XMLFontEncodingPropHdl aEncHdl; + if( !sFontCharset.isEmpty() && + aEncHdl.importXML( sFontCharset, aAny, rUnitConv ) ) + { + sal_Int16 nTmp = 0; + aAny >>= nTmp; + rListLevel.SetBulletFontEncoding( nTmp ); + } + } + + sal_Int16 eVertOrient = VertOrientation::LINE_CENTER; + if( !sVerticalPos.isEmpty() ) + { + if( IsXMLToken( sVerticalPos, XML_TOP ) ) + eVertOrient = VertOrientation::LINE_TOP; + else if( IsXMLToken( sVerticalPos, XML_BOTTOM ) ) + eVertOrient = VertOrientation::LINE_BOTTOM; + } + if( !sVerticalRel.isEmpty() ) + { + if( IsXMLToken( sVerticalRel, XML_BASELINE ) ) + { + // TOP and BOTTOM are exchanged for a baseline relation + switch( eVertOrient ) + { + case VertOrientation::LINE_TOP: + eVertOrient = VertOrientation::BOTTOM; + break; + case VertOrientation::LINE_CENTER: + eVertOrient = VertOrientation::CENTER; + break; + case VertOrientation::LINE_BOTTOM: + eVertOrient = VertOrientation::TOP; + break; + } + } + else if( IsXMLToken( sVerticalRel, XML_CHAR ) ) + { + switch( eVertOrient ) + { + case VertOrientation::LINE_TOP: + eVertOrient = VertOrientation::CHAR_TOP; + break; + case VertOrientation::LINE_CENTER: + eVertOrient = VertOrientation::CHAR_CENTER; + break; + case VertOrientation::LINE_BOTTOM: + eVertOrient = VertOrientation::CHAR_BOTTOM; + break; + } + } + } + rListLevel.SetImageVertOrient( eVertOrient ); +} + +css::uno::Reference< css::xml::sax::XFastContextHandler > SvxXMLListLevelStyleAttrContext_Impl::createFastChildContext( + sal_Int32 nElement, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) +{ + if ( nElement == XML_ELEMENT(STYLE, XML_LIST_LEVEL_LABEL_ALIGNMENT) ) + { + return new SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl( GetImport(), + nElement, + xAttrList, + rListLevel ); + } + XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement); + return nullptr; +} + + +SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl::SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl( + SvXMLImport& rImport, sal_Int32 /*nElement*/, + const Reference< xml::sax::XFastAttributeList > & xAttrList, + SvxXMLListLevelStyleContext_Impl& rLLevel ) : + SvXMLImportContext( rImport ) +{ + SvXMLUnitConverter& rUnitConv = GetImport().GetMM100UnitConverter(); + + sal_Int16 eLabelFollowedBy = LabelFollow::LISTTAB; + for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) ) + { + sal_Int32 nVal; + switch( aIter.getToken() ) + { + case XML_ELEMENT(TEXT, XML_LABEL_FOLLOWED_BY): + case XML_ELEMENT(LO_EXT, XML_LABEL_FOLLOWED_BY): + { + if( eLabelFollowedBy == LabelFollow::NEWLINE) + //NewLine from LO_EXT has precedence over other values of the Non LO_EXT namespace + break; + if( IsXMLToken( aIter, XML_SPACE ) ) + eLabelFollowedBy = LabelFollow::SPACE; + else if( IsXMLToken( aIter, XML_NOTHING ) ) + eLabelFollowedBy = LabelFollow::NOTHING; + else if( IsXMLToken( aIter, XML_NEWLINE ) ) + eLabelFollowedBy = LabelFollow::NEWLINE; + } + break; + case XML_ELEMENT(TEXT, XML_LIST_TAB_STOP_POSITION): + if (rUnitConv.convertMeasureToCore(nVal, aIter.toView(), 0, SHRT_MAX)) + rLLevel.SetListtabStopPosition( nVal ); + break; + case XML_ELEMENT(FO, XML_TEXT_INDENT): + case XML_ELEMENT(FO_COMPAT, XML_TEXT_INDENT): + if (rUnitConv.convertMeasureToCore(nVal, aIter.toView(), SHRT_MIN, SHRT_MAX)) + rLLevel.SetFirstLineIndent( nVal ); + break; + case XML_ELEMENT(FO, XML_MARGIN_LEFT): + case XML_ELEMENT(FO_COMPAT, XML_MARGIN_LEFT): + if (rUnitConv.convertMeasureToCore(nVal, aIter.toView(), SHRT_MIN, SHRT_MAX)) + rLLevel.SetIndentAt( nVal ); + break; + default: + XMLOFF_WARN_UNKNOWN("xmloff", aIter); + } + } + rLLevel.SetLabelFollowedBy( eLabelFollowedBy ); +} + +void SvxXMLListStyleContext::SetAttribute( sal_Int32 nElement, + const OUString& rValue ) +{ + if( nElement == XML_ELEMENT(TEXT, XML_CONSECUTIVE_NUMBERING) ) + { + m_bConsecutive = IsXMLToken( rValue, XML_TRUE ); + } + else + { + SvXMLStyleContext::SetAttribute( nElement, rValue ); + } +} + +constexpr OUString sIsPhysical( u"IsPhysical"_ustr ); +constexpr OUString sNumberingRules( u"NumberingRules"_ustr ); +constexpr OUString sIsContinuousNumbering( u"IsContinuousNumbering"_ustr ); + +SvxXMLListStyleContext::SvxXMLListStyleContext( SvXMLImport& rImport, + bool bOutl ) +: SvXMLStyleContext( rImport, bOutl ? XmlStyleFamily::TEXT_OUTLINE : XmlStyleFamily::TEXT_LIST ) +, m_bConsecutive( false ) +, m_bOutline( bOutl ) +{ +} + +SvxXMLListStyleContext::~SvxXMLListStyleContext() {} + +css::uno::Reference< css::xml::sax::XFastContextHandler > SvxXMLListStyleContext::createFastChildContext( + sal_Int32 nElement, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) +{ + if( m_bOutline + ? nElement == XML_ELEMENT(TEXT, XML_OUTLINE_LEVEL_STYLE) + : ( nElement == XML_ELEMENT(TEXT, XML_LIST_LEVEL_STYLE_NUMBER) || + nElement == XML_ELEMENT(TEXT, XML_LIST_LEVEL_STYLE_BULLET) || + nElement == XML_ELEMENT(TEXT, XML_LIST_LEVEL_STYLE_IMAGE ) ) ) + { + rtl::Reference<SvxXMLListLevelStyleContext_Impl> xLevelStyle{ + new SvxXMLListLevelStyleContext_Impl( GetImport(), nElement, xAttrList )}; + if( !m_pLevelStyles ) + m_pLevelStyles = std::make_unique<SvxXMLListStyle_Impl>(); + m_pLevelStyles->push_back( xLevelStyle ); + + return xLevelStyle; + } + XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement); + return nullptr; +} + +void SvxXMLListStyleContext::FillUnoNumRule( + const Reference<container::XIndexReplace> & rNumRule) const +{ + try + { + if( m_pLevelStyles && rNumRule.is() ) + { + sal_Int32 l_nLevels = rNumRule->getCount(); + for (const auto& pLevelStyle : *m_pLevelStyles) + { + sal_Int32 nLevel = pLevelStyle->GetLevel(); + if( nLevel >= 0 && nLevel < l_nLevels ) + { + Sequence<beans::PropertyValue> aProps = + pLevelStyle->GetProperties(); + rNumRule->replaceByIndex( nLevel, Any(aProps) ); + } + } + } + + Reference < XPropertySet > xPropSet( rNumRule, UNO_QUERY ); + Reference< XPropertySetInfo > xPropSetInfo; + if (xPropSet.is()) + xPropSetInfo = xPropSet->getPropertySetInfo(); + if( xPropSetInfo.is() && + xPropSetInfo->hasPropertyByName( sIsContinuousNumbering ) ) + { + xPropSet->setPropertyValue( sIsContinuousNumbering, Any(m_bConsecutive) ); + } + } + catch (const Exception&) + { + TOOLS_WARN_EXCEPTION("xmloff.style", "" ); + } +} + +void SvxXMLListStyleContext::CreateAndInsertLate( bool bOverwrite ) +{ + if( m_bOutline ) + { + if( bOverwrite ) + { + const Reference< XIndexReplace >& rNumRule = + GetImport().GetTextImport()->GetChapterNumbering(); + // We don't set xNumberingRules here, to avoid using them + // as numbering rules. + if( rNumRule.is() ) + FillUnoNumRule(rNumRule); + } + } + else + { + Reference < XStyle > xStyle; + const OUString& rName = GetDisplayName(); + if( rName.isEmpty() ) + { + SetValid( false ); + return; + } + + const Reference < XNameContainer >& rNumStyles = + GetImport().GetTextImport()->GetNumberingStyles(); + if( !rNumStyles.is() ) + { + SetValid( false ); + return; + } + + bool bNew = false; + if( rNumStyles->hasByName( rName ) ) + { + Any aAny = rNumStyles->getByName( rName ); + aAny >>= xStyle; + } + else + { + Reference< XMultiServiceFactory > xFactory( GetImport().GetModel(), + UNO_QUERY ); + SAL_WARN_IF( !xFactory.is(), "xmloff", "no factory" ); + if( !xFactory.is() ) + return; + + Reference < XInterface > xIfc = xFactory->createInstance("com.sun.star.style.NumberingStyle"); + if( !xIfc.is() ) + return; + Reference < XStyle > xTmp( xIfc, UNO_QUERY ); + xStyle = xTmp; + if( !xStyle.is() ) + return; + + rNumStyles->insertByName( rName, Any(xStyle) ); + bNew = true; + } + + Reference < XPropertySet > xPropSet( xStyle, UNO_QUERY ); + Reference< XPropertySetInfo > xPropSetInfo = + xPropSet->getPropertySetInfo(); + if( !bNew && xPropSetInfo->hasPropertyByName( sIsPhysical ) ) + { + Any aAny = xPropSet->getPropertyValue( sIsPhysical ); + bNew = !*o3tl::doAccess<bool>(aAny); + } + + if ( xPropSetInfo->hasPropertyByName( "Hidden" ) ) + xPropSet->setPropertyValue( "Hidden", uno::Any( IsHidden( ) ) ); + + if( rName != GetName() ) + GetImport().AddStyleDisplayName( XmlStyleFamily::TEXT_LIST, + GetName(), rName ); + + Any aAny = xPropSet->getPropertyValue( sNumberingRules ); + aAny >>= m_xNumRules; + if( bOverwrite || bNew ) + { + FillUnoNumRule(m_xNumRules); + xPropSet->setPropertyValue( sNumberingRules, Any(m_xNumRules) ); + } + else + { + SetValid( false ); + } + + SetNew( bNew ); + } +} + +void SvxXMLListStyleContext::CreateAndInsertAuto() const +{ + SAL_WARN_IF( m_bOutline, "xmloff", "Outlines cannot be inserted here" ); + SAL_WARN_IF( m_xNumRules.is(), "xmloff", "Numbering Rule is existing already" ); + + const OUString& rName = GetName(); + if( m_bOutline || m_xNumRules.is() || rName.isEmpty() ) + { + const_cast<SvxXMLListStyleContext *>(this)->SetValid( false ); + return; + } + + const_cast<SvxXMLListStyleContext *>(this)->m_xNumRules = CreateNumRule( + GetImport().GetModel() ); + + FillUnoNumRule(m_xNumRules); +} + +Reference < XIndexReplace > SvxXMLListStyleContext::CreateNumRule( + const Reference < XModel > & rModel ) +{ + Reference<XIndexReplace> xNumRule; + + Reference< XMultiServiceFactory > xFactory( rModel, UNO_QUERY ); + SAL_WARN_IF( !xFactory.is(), "xmloff", "no factory" ); + if( !xFactory.is() ) + return xNumRule; + + Reference < XInterface > xIfc = xFactory->createInstance("com.sun.star.text.NumberingRules"); + if( !xIfc.is() ) + return xNumRule; + + xNumRule.set( xIfc, UNO_QUERY ); + SAL_WARN_IF( !xNumRule.is(), "xmloff", "go no numbering rule" ); + + return xNumRule; +} + +void SvxXMLListStyleContext::SetDefaultStyle( + const Reference < XIndexReplace > & rNumRule, + sal_Int16 nLevel, + bool bOrdered ) +{ + Sequence<beans::PropertyValue> aPropSeq( bOrdered ? 1 : 4 ); + beans::PropertyValue *pProps = aPropSeq.getArray(); + + pProps->Name = "NumberingType"; + (pProps++)->Value <<= static_cast<sal_Int16>(bOrdered ? NumberingType::ARABIC + : NumberingType::CHAR_SPECIAL ); + if( !bOrdered ) + { + // TODO: Bullet-Font + awt::FontDescriptor aFDesc; + aFDesc.Name = +#ifdef _WIN32 + "StarBats" +#else + "starbats" +#endif + ; + aFDesc.Family = FAMILY_DONTKNOW ; + aFDesc.Pitch = PITCH_DONTKNOW ; + aFDesc.CharSet = RTL_TEXTENCODING_SYMBOL ; + aFDesc.Weight = WEIGHT_DONTKNOW; + pProps->Name = "BulletFont"; + (pProps++)->Value <<= aFDesc; + + pProps->Name = "BulletChar"; + (pProps++)->Value <<= OUString(sal_Unicode(0xF000 + 149)); + pProps->Name = "CharStyleName"; + (pProps++)->Value <<= OUString( "Numbering Symbols" ); + } + + rNumRule->replaceByIndex( nLevel, Any(aPropSeq) ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |