/* -*- 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 "fonthdl.hxx" #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_uInt16 nPrfx, const OUString& rLName, const Reference< xml::sax::XAttributeList >& xAttrList, SvxXMLListLevelStyleContext_Impl& rLLevel ); virtual SvXMLImportContextRef CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< xml::sax::XAttributeList > & xAttrList ) override; }; class SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl : public SvXMLImportContext { public: SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl( SvXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, const Reference< xml::sax::XAttributeList >& xAttrList, SvxXMLListLevelStyleContext_Impl& rLLevel ); }; enum SvxXMLTextListLevelStyleAttrTokens { XML_TOK_TEXT_LEVEL_ATTR_LEVEL, XML_TOK_TEXT_LEVEL_ATTR_STYLE_NAME, XML_TOK_TEXT_LEVEL_ATTR_BULLET_CHAR, XML_TOK_TEXT_LEVEL_ATTR_HREF, XML_TOK_TEXT_LEVEL_ATTR_TYPE, XML_TOK_TEXT_LEVEL_ATTR_SHOW, XML_TOK_TEXT_LEVEL_ATTR_ACTUATE, XML_TOK_TEXT_LEVEL_ATTR_NUM_FORMAT, XML_TOK_TEXT_LEVEL_ATTR_NUM_PREFIX, XML_TOK_TEXT_LEVEL_ATTR_NUM_SUFFIX, XML_TOK_TEXT_LEVEL_ATTR_NUM_LETTER_SYNC, XML_TOK_TEXT_LEVEL_ATTR_START_VALUE, XML_TOK_TEXT_LEVEL_ATTR_DISPLAY_LEVELS }; } static const SvXMLTokenMapEntry* lcl_getLevelAttrTokenMap() { static const SvXMLTokenMapEntry aLevelAttrTokenMap[] = { { XML_NAMESPACE_TEXT, XML_LEVEL, XML_TOK_TEXT_LEVEL_ATTR_LEVEL }, { XML_NAMESPACE_TEXT, XML_STYLE_NAME, XML_TOK_TEXT_LEVEL_ATTR_STYLE_NAME }, { XML_NAMESPACE_TEXT, XML_BULLET_CHAR, XML_TOK_TEXT_LEVEL_ATTR_BULLET_CHAR }, { XML_NAMESPACE_XLINK, XML_HREF, XML_TOK_TEXT_LEVEL_ATTR_HREF }, { XML_NAMESPACE_XLINK, XML_TYPE, XML_TOK_TEXT_LEVEL_ATTR_TYPE }, { XML_NAMESPACE_XLINK, XML_SHOW, XML_TOK_TEXT_LEVEL_ATTR_SHOW }, { XML_NAMESPACE_XLINK, XML_ACTUATE, XML_TOK_TEXT_LEVEL_ATTR_ACTUATE }, { XML_NAMESPACE_STYLE, XML_NUM_FORMAT, XML_TOK_TEXT_LEVEL_ATTR_NUM_FORMAT }, { XML_NAMESPACE_STYLE, XML_NUM_PREFIX, XML_TOK_TEXT_LEVEL_ATTR_NUM_PREFIX }, { XML_NAMESPACE_STYLE, XML_NUM_SUFFIX, XML_TOK_TEXT_LEVEL_ATTR_NUM_SUFFIX }, { XML_NAMESPACE_STYLE, XML_NUM_LETTER_SYNC, XML_TOK_TEXT_LEVEL_ATTR_NUM_LETTER_SYNC }, { XML_NAMESPACE_TEXT, XML_START_VALUE, XML_TOK_TEXT_LEVEL_ATTR_START_VALUE }, { XML_NAMESPACE_TEXT, XML_DISPLAY_LEVELS, XML_TOK_TEXT_LEVEL_ATTR_DISPLAY_LEVELS }, XML_TOKEN_MAP_END }; return aLevelAttrTokenMap; } class SvxXMLListLevelStyleContext_Impl : public SvXMLImportContext { friend SvxXMLListLevelStyleAttrContext_Impl; OUString sPrefix; OUString sSuffix; 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_Unicode 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; 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_uInt16 nPrfx, const OUString& rLName, const Reference< xml::sax::XAttributeList > & xAttrList ); virtual SvXMLImportContextRef CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< xml::sax::XAttributeList > & 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; } }; static const OUStringLiteral gsStarBats( "StarBats" ); static const OUStringLiteral gsStarMath( "StarMath" ); SvxXMLListLevelStyleContext_Impl::SvxXMLListLevelStyleContext_Impl( SvXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, const Reference< xml::sax::XAttributeList > & xAttrList ) : SvXMLImportContext( rImport, nPrfx, rLName ) , 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 ) { if( IsXMLToken( rLName, XML_LIST_LEVEL_STYLE_NUMBER ) || IsXMLToken( rLName, XML_OUTLINE_LEVEL_STYLE ) ) bNum = true; else if( IsXMLToken( rLName, XML_LIST_LEVEL_STYLE_BULLET ) ) bBullet = true; else if( IsXMLToken( rLName, XML_LIST_LEVEL_STYLE_IMAGE ) ) bImage = true; static const SvXMLTokenMap aTokenMap( lcl_getLevelAttrTokenMap() ); sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; for( sal_Int16 i=0; i < nAttrCount; i++ ) { const OUString& rAttrName = xAttrList->getNameByIndex( i ); OUString aLocalName; sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName ); const OUString& rValue = xAttrList->getValueByIndex( i ); switch( aTokenMap.Get( nPrefix, aLocalName ) ) { case XML_TOK_TEXT_LEVEL_ATTR_LEVEL: nLevel = rValue.toInt32(); if( nLevel >= 1 ) nLevel--; else nLevel = 0; break; case XML_TOK_TEXT_LEVEL_ATTR_STYLE_NAME: sTextStyleName = rValue; break; case XML_TOK_TEXT_LEVEL_ATTR_BULLET_CHAR: if (!rValue.isEmpty()) cBullet = rValue[0]; break; case XML_TOK_TEXT_LEVEL_ATTR_HREF: if( bImage ) sImageURL = rValue; break; case XML_TOK_TEXT_LEVEL_ATTR_TYPE: case XML_TOK_TEXT_LEVEL_ATTR_SHOW: case XML_TOK_TEXT_LEVEL_ATTR_ACTUATE: // This properties will be ignored break; case XML_TOK_TEXT_LEVEL_ATTR_NUM_FORMAT: if( bNum ) sNumFormat = rValue; break; case XML_TOK_TEXT_LEVEL_ATTR_NUM_PREFIX: sPrefix = rValue; break; case XML_TOK_TEXT_LEVEL_ATTR_NUM_SUFFIX: sSuffix = rValue; break; case XML_TOK_TEXT_LEVEL_ATTR_NUM_LETTER_SYNC: if( bNum ) sNumLetterSync = rValue; break; case XML_TOK_TEXT_LEVEL_ATTR_START_VALUE: if( bNum ) { sal_Int32 nTmp = rValue.toInt32(); nNumStartValue = (nTmp < 0) ? 1 : ( (nTmp>SHRT_MAX) ? SHRT_MAX : static_cast(nTmp) ); } break; case XML_TOK_TEXT_LEVEL_ATTR_DISPLAY_LEVELS: if( bNum ) { sal_Int32 nTmp = rValue.toInt32(); nNumDisplayLevels = (nTmp < 1) ? 1 : ( (nTmp>SHRT_MAX) ? SHRT_MAX : static_cast(nTmp) ); } break; } } } SvXMLImportContextRef SvxXMLListLevelStyleContext_Impl::CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< xml::sax::XAttributeList > & xAttrList ) { SvXMLImportContext *pContext = nullptr; if( XML_NAMESPACE_STYLE == nPrefix && ( IsXMLToken( rLocalName, XML_LIST_LEVEL_PROPERTIES ) || IsXMLToken( rLocalName, XML_TEXT_PROPERTIES ) ) ) { pContext = new SvxXMLListLevelStyleAttrContext_Impl( GetImport(), nPrefix, rLocalName, xAttrList, *this ); } else if( (XML_NAMESPACE_OFFICE == nPrefix) && xmloff::token::IsXMLToken( rLocalName, xmloff::token::XML_BINARY_DATA ) ) { if( bImage && sImageURL.isEmpty() && !xBase64Stream.is() ) { xBase64Stream = GetImport().GetStreamForGraphicObjectURLFromBase64(); if( xBase64Stream.is() ) pContext = new XMLBase64ImportContext( GetImport(), nPrefix, rLocalName, xAttrList, xBase64Stream ); } } return pContext; } Sequence SvxXMLListLevelStyleContext_Impl::GetProperties() { sal_Int16 eType = NumberingType::NUMBER_NONE; sal_Int32 nCount = 0; if( bBullet ) { eType = NumberingType::CHAR_SPECIAL; nCount = 15; // 'cBullet' will be written anyway if 'bBullet' is true } if( bImage ) { eType = NumberingType::BITMAP; nCount = 15; if( !sImageURL.isEmpty() || xBase64Stream.is() ) nCount++; } if( bNum ) { eType = NumberingType::ARABIC; GetImport().GetMM100UnitConverter().convertNumFormat( eType, sNumFormat, sNumLetterSync, true ); nCount = 15; } if( ( bBullet || bNum ) && nRelSize ) nCount++; if( !bImage && bHasColor ) { nCount++; } 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 } } Sequence aPropSeq( nCount ); if( nCount > 0 ) { beans::PropertyValue *pProps = aPropSeq.getArray(); sal_Int32 nPos = 0; pProps[nPos].Name = "NumberingType"; pProps[nPos++].Value <<= eType ; pProps[nPos].Name = "Prefix"; pProps[nPos++].Value <<= sPrefix; pProps[nPos].Name = "Suffix"; pProps[nPos++].Value <<= sSuffix; pProps[nPos].Name = "Adjust"; pProps[nPos++].Value <<= eAdjust; sal_Int32 nLeftMargin = nSpaceBefore + nMinLabelWidth; pProps[nPos].Name = "LeftMargin"; pProps[nPos++].Value <<= nLeftMargin; sal_Int32 nFirstLineOffset = -nMinLabelWidth; pProps[nPos].Name = "FirstLineOffset"; pProps[nPos++].Value <<= nFirstLineOffset; pProps[nPos].Name = "SymbolTextDistance"; pProps[nPos++].Value <<= static_cast(nMinLabelDist); pProps[nPos].Name = "PositionAndSpaceMode"; pProps[nPos++].Value <<= ePosAndSpaceMode; pProps[nPos].Name = "LabelFollowedBy"; pProps[nPos++].Value <<= eLabelFollowedBy; pProps[nPos].Name = "ListtabStopPosition"; pProps[nPos++].Value <<= nListtabStopPosition; pProps[nPos].Name = "FirstLineIndent"; pProps[nPos++].Value <<= nFirstLineIndent; pProps[nPos].Name = "IndentAt"; pProps[nPos++].Value <<= nIndentAt; OUString sDisplayTextStyleName = GetImport().GetStyleDisplayName( XmlStyleFamily::TEXT_TEXT, sTextStyleName ); pProps[nPos].Name = "CharStyleName"; pProps[nPos++].Value <<= 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. OUString sTmp = OUStringChar( cBullet ); pProps[nPos].Name = "BulletChar"; pProps[nPos++].Value <<= sTmp; pProps[nPos].Name = "BulletFont"; pProps[nPos++].Value <<= 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()) { pProps[nPos].Name = "GraphicBitmap"; pProps[nPos++].Value <<= xBitmap; } awt::Size aSize(nImageWidth, nImageHeight); pProps[nPos].Name = "GraphicSize"; pProps[nPos++].Value <<= aSize; pProps[nPos].Name = "VertOrient"; pProps[nPos++].Value <<= eImageVertOrient; } if( bNum ) { pProps[nPos].Name = "StartWith"; pProps[nPos++].Value <<= nNumStartValue; pProps[nPos].Name = "ParentNumbering"; pProps[nPos++].Value <<= nNumDisplayLevels; } if( ( bNum || bBullet ) && nRelSize ) { pProps[nPos].Name = "BulletRelSize"; pProps[nPos++].Value <<= nRelSize; } if( !bImage && bHasColor ) { pProps[nPos].Name = "BulletColor"; pProps[nPos++].Value <<= m_nColor; } SAL_WARN_IF( nPos != nCount, "xmloff", "array under/overflow" ); } return aPropSeq; } namespace { enum SvxXMLStyleAttributesAttrTokens { XML_TOK_STYLE_ATTRIBUTES_ATTR_SPACE_BEFORE, XML_TOK_STYLE_ATTRIBUTES_ATTR_MIN_LABEL_WIDTH, XML_TOK_STYLE_ATTRIBUTES_ATTR_MIN_LABEL_DIST, XML_TOK_STYLE_ATTRIBUTES_ATTR_TEXT_ALIGN, XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_NAME, XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_FAMILY, XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_FAMILY_GENERIC, XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_STYLENAME, XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_PITCH, XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_CHARSET, XML_TOK_STYLE_ATTRIBUTES_ATTR_VERTICAL_POS, XML_TOK_STYLE_ATTRIBUTES_ATTR_VERTICAL_REL, XML_TOK_STYLE_ATTRIBUTES_ATTR_WIDTH, XML_TOK_STYLE_ATTRIBUTES_ATTR_HEIGHT, XML_TOK_STYLE_ATTRIBUTES_ATTR_COLOR, XML_TOK_STYLE_ATTRIBUTES_ATTR_WINDOW_FONT_COLOR, XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_SIZE, XML_TOK_STYLE_ATTRIBUTES_ATTR_POSITION_AND_SPACE_MODE }; } static const SvXMLTokenMapEntry* lcl_getStyleAttributesAttrTokenMap() { static const SvXMLTokenMapEntry aStyleAttributesAttrTokenMap[] = { { XML_NAMESPACE_TEXT, XML_SPACE_BEFORE, XML_TOK_STYLE_ATTRIBUTES_ATTR_SPACE_BEFORE }, { XML_NAMESPACE_TEXT, XML_MIN_LABEL_WIDTH, XML_TOK_STYLE_ATTRIBUTES_ATTR_MIN_LABEL_WIDTH }, { XML_NAMESPACE_TEXT, XML_MIN_LABEL_DISTANCE, XML_TOK_STYLE_ATTRIBUTES_ATTR_MIN_LABEL_DIST }, { XML_NAMESPACE_FO, XML_TEXT_ALIGN, XML_TOK_STYLE_ATTRIBUTES_ATTR_TEXT_ALIGN }, { XML_NAMESPACE_STYLE, XML_FONT_NAME, XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_NAME }, { XML_NAMESPACE_FO, XML_FONT_FAMILY, XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_FAMILY }, { XML_NAMESPACE_STYLE, XML_FONT_FAMILY_GENERIC, XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_FAMILY_GENERIC }, { XML_NAMESPACE_STYLE, XML_FONT_STYLE_NAME, XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_STYLENAME }, { XML_NAMESPACE_STYLE, XML_FONT_PITCH, XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_PITCH }, { XML_NAMESPACE_STYLE, XML_FONT_CHARSET, XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_CHARSET }, { XML_NAMESPACE_STYLE, XML_VERTICAL_POS, XML_TOK_STYLE_ATTRIBUTES_ATTR_VERTICAL_POS }, { XML_NAMESPACE_STYLE, XML_VERTICAL_REL, XML_TOK_STYLE_ATTRIBUTES_ATTR_VERTICAL_REL }, { XML_NAMESPACE_FO, XML_WIDTH, XML_TOK_STYLE_ATTRIBUTES_ATTR_WIDTH }, { XML_NAMESPACE_FO, XML_HEIGHT, XML_TOK_STYLE_ATTRIBUTES_ATTR_HEIGHT }, { XML_NAMESPACE_FO, XML_COLOR, XML_TOK_STYLE_ATTRIBUTES_ATTR_COLOR }, { XML_NAMESPACE_STYLE, XML_USE_WINDOW_FONT_COLOR, XML_TOK_STYLE_ATTRIBUTES_ATTR_WINDOW_FONT_COLOR }, { XML_NAMESPACE_FO, XML_FONT_SIZE, XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_SIZE }, { XML_NAMESPACE_TEXT, XML_LIST_LEVEL_POSITION_AND_SPACE_MODE, XML_TOK_STYLE_ATTRIBUTES_ATTR_POSITION_AND_SPACE_MODE }, XML_TOKEN_MAP_END }; return aStyleAttributesAttrTokenMap; } SvxXMLListLevelStyleAttrContext_Impl::SvxXMLListLevelStyleAttrContext_Impl( SvXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, const Reference< xml::sax::XAttributeList > & xAttrList, SvxXMLListLevelStyleContext_Impl& rLLevel ) : SvXMLImportContext( rImport, nPrfx, rLName ), rListLevel( rLLevel ) { static const SvXMLTokenMap aTokenMap( lcl_getStyleAttributesAttrTokenMap() ); SvXMLUnitConverter& rUnitConv = GetImport().GetMM100UnitConverter(); OUString sFontName, sFontFamily, sFontStyleName, sFontFamilyGeneric, sFontPitch, sFontCharset; OUString sVerticalPos, sVerticalRel; sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; for( sal_Int16 i=0; i < nAttrCount; i++ ) { const OUString& rAttrName = xAttrList->getNameByIndex( i ); OUString aLocalName; sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName ); const OUString& rValue = xAttrList->getValueByIndex( i ); sal_Int32 nVal; switch( aTokenMap.Get( nPrefix, aLocalName ) ) { case XML_TOK_STYLE_ATTRIBUTES_ATTR_SPACE_BEFORE: if (rUnitConv.convertMeasureToCore(nVal, rValue, SHRT_MIN, SHRT_MAX)) rListLevel.SetSpaceBefore( nVal ); break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_MIN_LABEL_WIDTH: if (rUnitConv.convertMeasureToCore( nVal, rValue, 0, SHRT_MAX )) rListLevel.SetMinLabelWidth( nVal ); break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_MIN_LABEL_DIST: if (rUnitConv.convertMeasureToCore( nVal, rValue, 0, USHRT_MAX )) rListLevel.SetMinLabelDist( nVal ); break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_TEXT_ALIGN: if( !rValue.isEmpty() ) { sal_Int16 eAdjust = HoriOrientation::LEFT; if( IsXMLToken( rValue, XML_CENTER ) ) eAdjust = HoriOrientation::CENTER; else if( IsXMLToken( rValue, XML_END ) ) eAdjust = HoriOrientation::RIGHT; rListLevel.SetAdjust( eAdjust ); } break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_NAME: sFontName = rValue; break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_FAMILY: sFontFamily = rValue; break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_FAMILY_GENERIC: sFontFamilyGeneric = rValue; break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_STYLENAME: sFontStyleName = rValue; break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_PITCH: sFontPitch = rValue; break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_CHARSET: sFontCharset = rValue; break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_VERTICAL_POS: sVerticalPos = rValue; break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_VERTICAL_REL: sVerticalRel = rValue; break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_WIDTH: if (rUnitConv.convertMeasureToCore(nVal, rValue)) rListLevel.SetImageWidth( nVal ); break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_HEIGHT: if (rUnitConv.convertMeasureToCore(nVal, rValue)) rListLevel.SetImageHeight( nVal ); break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_COLOR: { sal_Int32 nColor(0); if (::sax::Converter::convertColor( nColor, rValue )) { rListLevel.SetColor( Color(nColor) ); } } break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_WINDOW_FONT_COLOR: { if( IsXMLToken( rValue, XML_TRUE ) ) rListLevel.SetColor( Color(0xffffffff) ); } break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_FONT_SIZE: if (::sax::Converter::convertPercent( nVal, rValue )) rListLevel.SetRelSize( static_cast(nVal) ); break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_POSITION_AND_SPACE_MODE: { sal_Int16 ePosAndSpaceMode = PositionAndSpaceMode::LABEL_WIDTH_AND_POSITION; if( IsXMLToken( rValue, XML_LABEL_ALIGNMENT ) ) ePosAndSpaceMode = PositionAndSpaceMode::LABEL_ALIGNMENT; rListLevel.SetPosAndSpaceMode( ePosAndSpaceMode ); } break; } } 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 ); } SvXMLImportContextRef SvxXMLListLevelStyleAttrContext_Impl::CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< xml::sax::XAttributeList > & xAttrList ) { SvXMLImportContext *pContext = nullptr; if ( XML_NAMESPACE_STYLE == nPrefix && IsXMLToken( rLocalName, XML_LIST_LEVEL_LABEL_ALIGNMENT ) ) { pContext = new SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl( GetImport(), nPrefix, rLocalName, xAttrList, rListLevel ); } return pContext; } namespace { enum SvxXMLStyleAttributesLabelAlignmentAttrTokens { XML_TOK_STYLE_ATTRIBUTES_ATTR_LABEL_FOLLOWED_BY, XML_TOK_STYLE_ATTRIBUTES_ATTR_LISTTAB_STOP_POSITION, XML_TOK_STYLE_ATTRIBUTES_ATTR_FIRST_LINE_INDENT, XML_TOK_STYLE_ATTRIBUTES_ATTR_INDENT_AT }; } static const SvXMLTokenMapEntry* lcl_getStyleAlignmentAttributesAttrTokenMap() { static const SvXMLTokenMapEntry aStyleAlignmentAttributesAttrTokenMap[] = { { XML_NAMESPACE_TEXT, XML_LABEL_FOLLOWED_BY, XML_TOK_STYLE_ATTRIBUTES_ATTR_LABEL_FOLLOWED_BY }, { XML_NAMESPACE_LO_EXT, XML_LABEL_FOLLOWED_BY, XML_TOK_STYLE_ATTRIBUTES_ATTR_LABEL_FOLLOWED_BY }, { XML_NAMESPACE_TEXT, XML_LIST_TAB_STOP_POSITION, XML_TOK_STYLE_ATTRIBUTES_ATTR_LISTTAB_STOP_POSITION }, { XML_NAMESPACE_FO, XML_TEXT_INDENT, XML_TOK_STYLE_ATTRIBUTES_ATTR_FIRST_LINE_INDENT }, { XML_NAMESPACE_FO, XML_MARGIN_LEFT, XML_TOK_STYLE_ATTRIBUTES_ATTR_INDENT_AT }, XML_TOKEN_MAP_END }; return aStyleAlignmentAttributesAttrTokenMap; } SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl::SvxXMLListLevelStyleLabelAlignmentAttrContext_Impl( SvXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, const Reference< xml::sax::XAttributeList > & xAttrList, SvxXMLListLevelStyleContext_Impl& rLLevel ) : SvXMLImportContext( rImport, nPrfx, rLName ) { static const SvXMLTokenMap aTokenMap( lcl_getStyleAlignmentAttributesAttrTokenMap() ); SvXMLUnitConverter& rUnitConv = GetImport().GetMM100UnitConverter(); sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; sal_Int16 eLabelFollowedBy = LabelFollow::LISTTAB; for( sal_Int16 i=0; i < nAttrCount; i++ ) { const OUString& rAttrName = xAttrList->getNameByIndex( i ); OUString aLocalName; sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName ); const OUString& rValue = xAttrList->getValueByIndex( i ); sal_Int32 nVal; switch( aTokenMap.Get( nPrefix, aLocalName ) ) { case XML_TOK_STYLE_ATTRIBUTES_ATTR_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( rValue, XML_SPACE ) ) eLabelFollowedBy = LabelFollow::SPACE; else if( IsXMLToken( rValue, XML_NOTHING ) ) eLabelFollowedBy = LabelFollow::NOTHING; else if( IsXMLToken( rValue, XML_NEWLINE ) ) eLabelFollowedBy = LabelFollow::NEWLINE; } break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_LISTTAB_STOP_POSITION: if (rUnitConv.convertMeasureToCore(nVal, rValue, 0, SHRT_MAX)) rLLevel.SetListtabStopPosition( nVal ); break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_FIRST_LINE_INDENT: if (rUnitConv.convertMeasureToCore(nVal, rValue, SHRT_MIN, SHRT_MAX)) rLLevel.SetFirstLineIndent( nVal ); break; case XML_TOK_STYLE_ATTRIBUTES_ATTR_INDENT_AT: if (rUnitConv.convertMeasureToCore(nVal, rValue, SHRT_MIN, SHRT_MAX)) rLLevel.SetIndentAt( nVal ); break; } } rLLevel.SetLabelFollowedBy( eLabelFollowedBy ); } void SvxXMLListStyleContext::SetAttribute( sal_uInt16 nPrefixKey, const OUString& rLocalName, const OUString& rValue ) { if( XML_NAMESPACE_TEXT == nPrefixKey && IsXMLToken( rLocalName, XML_CONSECUTIVE_NUMBERING ) ) { bConsecutive = IsXMLToken( rValue, XML_TRUE ); } else { SvXMLStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue ); } } static const OUStringLiteral sIsPhysical( "IsPhysical" ); static const OUStringLiteral sNumberingRules( "NumberingRules" ); static const OUStringLiteral sIsContinuousNumbering( "IsContinuousNumbering" ); SvxXMLListStyleContext::SvxXMLListStyleContext( SvXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, const Reference< xml::sax::XAttributeList > & xAttrList, bool bOutl ) : SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList, bOutl ? XmlStyleFamily::TEXT_OUTLINE : XmlStyleFamily::TEXT_LIST ) , bConsecutive( false ) , bOutline( bOutl ) { } SvxXMLListStyleContext::SvxXMLListStyleContext( SvXMLImport& rImport, sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList, bool bOutl ) : SvXMLStyleContext( rImport, nElement, xAttrList, bOutl ? XmlStyleFamily::TEXT_OUTLINE : XmlStyleFamily::TEXT_LIST ) , bConsecutive( false ) , bOutline( bOutl ) { } SvxXMLListStyleContext::~SvxXMLListStyleContext() {} SvXMLImportContextRef SvxXMLListStyleContext::CreateChildContext( sal_uInt16 nPrefix, const OUString& rLocalName, const Reference< xml::sax::XAttributeList > & xAttrList ) { SvXMLImportContextRef xContext; if( XML_NAMESPACE_TEXT == nPrefix && ( bOutline ? IsXMLToken( rLocalName, XML_OUTLINE_LEVEL_STYLE ) : ( IsXMLToken( rLocalName, XML_LIST_LEVEL_STYLE_NUMBER ) || IsXMLToken( rLocalName, XML_LIST_LEVEL_STYLE_BULLET ) || IsXMLToken( rLocalName, XML_LIST_LEVEL_STYLE_IMAGE ) ) ) ) { rtl::Reference xLevelStyle{ new SvxXMLListLevelStyleContext_Impl( GetImport(), nPrefix, rLocalName, xAttrList )}; if( !pLevelStyles ) pLevelStyles = std::make_unique(); pLevelStyles->push_back( xLevelStyle ); xContext = xLevelStyle.get(); } return xContext; } void SvxXMLListStyleContext::FillUnoNumRule( const Reference & rNumRule) const { try { if( pLevelStyles && rNumRule.is() ) { sal_Int32 l_nLevels = rNumRule->getCount(); for (const auto& pLevelStyle : *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(bConsecutive) ); } } catch (const Exception&) { OSL_FAIL( "SvxXMLListStyleContext::FillUnoNumRule - Exception caught" ); } } void SvxXMLListStyleContext::CreateAndInsertLate( bool bOverwrite ) { if( 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::makeAny( IsHidden( ) ) ); if( rName != GetName() ) GetImport().AddStyleDisplayName( XmlStyleFamily::TEXT_LIST, GetName(), rName ); Any aAny = xPropSet->getPropertyValue( sNumberingRules ); aAny >>= xNumRules; if( bOverwrite || bNew ) { FillUnoNumRule(xNumRules); xPropSet->setPropertyValue( sNumberingRules, Any(xNumRules) ); } else { SetValid( false ); } SetNew( bNew ); } } void SvxXMLListStyleContext::CreateAndInsertAuto() const { SAL_WARN_IF( bOutline, "xmloff", "Outlines cannot be inserted here" ); SAL_WARN_IF( xNumRules.is(), "xmloff", "Numbering Rule is existing already" ); const OUString& rName = GetName(); if( bOutline || xNumRules.is() || rName.isEmpty() ) { const_cast(this)->SetValid( false ); return; } const_cast(this)->xNumRules = CreateNumRule( GetImport().GetModel() ); FillUnoNumRule(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; OUString sTmp = OUStringChar(sal_Unicode(0xF000 + 149)); pProps->Name = "BulletChar"; (pProps++)->Value <<= sTmp; pProps->Name = "CharStyleName"; (pProps++)->Value <<= OUString( "Numbering Symbols" ); } rNumRule->replaceByIndex( nLevel, Any(aPropSeq) ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */