/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fonthdl.hxx" #include #include #include #include #include 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 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 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(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(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 SvxXMLListLevelStyleContext_Impl::GetProperties() { if (!bBullet && !bImage && !bNum) { return Sequence(); } sal_Int16 eType = NumberingType::NUMBER_NONE; std::vector 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(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 xGraphic; if (!sImageURL.isEmpty()) { xGraphic = GetImport().loadGraphicByURL(sImageURL); } else if( xBase64Stream.is() ) { xGraphic = GetImport().loadGraphicFromBase64(xBase64Stream); } uno::Reference 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(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 xLevelStyle{ new SvxXMLListLevelStyleContext_Impl( GetImport(), nElement, xAttrList )}; if( !m_pLevelStyles ) m_pLevelStyles = std::make_unique(); m_pLevelStyles->push_back( xLevelStyle ); return xLevelStyle; } XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement); return nullptr; } void SvxXMLListStyleContext::FillUnoNumRule( const Reference & 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 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(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(this)->SetValid( false ); return; } const_cast(this)->m_xNumRules = CreateNumRule( GetImport().GetModel() ); FillUnoNumRule(m_xNumRules); } Reference < XIndexReplace > SvxXMLListStyleContext::CreateNumRule( const Reference < XModel > & rModel ) { Reference 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 aPropSeq( bOrdered ? 1 : 4 ); beans::PropertyValue *pProps = aPropSeq.getArray(); pProps->Name = "NumberingType"; (pProps++)->Value <<= static_cast(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: */