summaryrefslogtreecommitdiffstats
path: root/writerfilter/source/dmapper/NumberingManager.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'writerfilter/source/dmapper/NumberingManager.cxx')
-rw-r--r--writerfilter/source/dmapper/NumberingManager.cxx1210
1 files changed, 1210 insertions, 0 deletions
diff --git a/writerfilter/source/dmapper/NumberingManager.cxx b/writerfilter/source/dmapper/NumberingManager.cxx
new file mode 100644
index 000000000..cb97f59ff
--- /dev/null
+++ b/writerfilter/source/dmapper/NumberingManager.cxx
@@ -0,0 +1,1210 @@
+/* -*- 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 <sal/config.h>
+
+#include "ConversionHelper.hxx"
+#include "NumberingManager.hxx"
+#include "StyleSheetTable.hxx"
+#include "PropertyIds.hxx"
+
+#include <ooxml/resourceids.hxx>
+
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/style/NumberingType.hpp>
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/text/PositionAndSpaceMode.hpp>
+#include <com/sun/star/text/XChapterNumberingSupplier.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/awt/XBitmap.hpp>
+
+#include <osl/diagnose.h>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/UnitConversion.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/string.hxx>
+#include <regex>
+
+using namespace com::sun::star;
+
+namespace writerfilter::dmapper {
+
+//--------------------------------------------------- Utility functions
+template <typename T>
+static beans::PropertyValue lcl_makePropVal(PropertyIds nNameID, T const & aValue)
+{
+ return {getPropertyName(nNameID), 0, uno::Any(aValue), beans::PropertyState_DIRECT_VALUE};
+}
+
+static sal_Int32 lcl_findProperty( const uno::Sequence< beans::PropertyValue >& aProps, std::u16string_view sName )
+{
+ sal_Int32 i = 0;
+ sal_Int32 nLen = aProps.getLength( );
+ sal_Int32 nPos = -1;
+
+ while ( nPos == -1 && i < nLen )
+ {
+ if ( aProps[i].Name == sName )
+ nPos = i;
+ else
+ i++;
+ }
+
+ return nPos;
+}
+
+static void lcl_mergeProperties( const uno::Sequence< beans::PropertyValue >& aSrc,
+ uno::Sequence< beans::PropertyValue >& aDst )
+{
+ for ( const auto& rProp : aSrc )
+ {
+ // Look for the same property in aDst
+ sal_Int32 nPos = lcl_findProperty( aDst, rProp.Name );
+ if ( nPos >= 0 )
+ {
+ // Replace the property value by the one in aSrc
+ aDst.getArray()[nPos] = rProp;
+ }
+ else
+ {
+ // Simply add the new value
+ aDst.realloc( aDst.getLength( ) + 1 );
+ aDst.getArray()[ aDst.getLength( ) - 1 ] = rProp;
+ }
+ }
+}
+
+//-------------------------------------------- ListLevel implementation
+void ListLevel::SetValue( Id nId, sal_Int32 nValue )
+{
+ switch( nId )
+ {
+ case NS_ooxml::LN_CT_Lvl_start:
+ m_nIStartAt = nValue;
+ break;
+ case NS_ooxml::LN_CT_NumLvl_startOverride:
+ m_nStartOverride = nValue;
+ break;
+ case NS_ooxml::LN_CT_NumFmt_val:
+ m_nNFC = nValue;
+ break;
+ case NS_ooxml::LN_CT_Lvl_isLgl:
+ break;
+ case NS_ooxml::LN_CT_Lvl_legacy:
+ break;
+ case NS_ooxml::LN_CT_Lvl_suff:
+ m_nXChFollow = nValue;
+ break;
+ case NS_ooxml::LN_CT_TabStop_pos:
+ if (nValue < 0)
+ {
+ SAL_INFO("writerfilter",
+ "unsupported list tab stop position " << nValue);
+ }
+ else
+ m_nTabstop = nValue;
+ break;
+ default:
+ OSL_FAIL( "this line should never be reached");
+ }
+ m_bHasValues = true;
+}
+
+void ListLevel::SetCustomNumberFormat(const OUString& rValue) { m_aCustomNumberFormat = rValue; }
+
+sal_Int16 ListLevel::GetNumberingType(sal_Int16 nDefault) const
+{
+ return ConversionHelper::ConvertNumberingType(m_nNFC, nDefault);
+}
+
+bool ListLevel::HasValues() const
+{
+ return m_bHasValues;
+}
+
+void ListLevel::SetParaStyle( const tools::SvRef< StyleSheetEntry >& pStyle )
+{
+ if (!pStyle)
+ return;
+ m_pParaStyle = pStyle;
+}
+
+uno::Sequence<beans::PropertyValue> ListLevel::GetProperties(bool bDefaults)
+{
+ uno::Sequence<beans::PropertyValue> aLevelProps = GetLevelProperties(bDefaults);
+ if (m_pParaStyle)
+ AddParaProperties( &aLevelProps );
+ return aLevelProps;
+}
+
+static bool IgnoreForCharStyle(std::u16string_view aStr, const bool bIsSymbol)
+{
+ //Names found in PropertyIds.cxx, Lines 56-396
+ return (aStr==u"Adjust" || aStr==u"IndentAt" || aStr==u"FirstLineIndent"
+ || aStr==u"FirstLineOffset" || aStr==u"LeftMargin"
+ // We need font names when they are different for the bullet and for the text.
+ // But leave symbols alone, we only want to keep the font style for letters and numbers.
+ || (bIsSymbol && aStr==u"CharFontName")
+ );
+}
+uno::Sequence< beans::PropertyValue > ListLevel::GetCharStyleProperties( )
+{
+ PropertyValueVector_t rProperties;
+
+ const uno::Sequence< beans::PropertyValue > vPropVals = PropertyMap::GetPropertyValues();
+ const bool bIsSymbol(GetBulletChar().getLength() <= 1);
+ for( const auto& rPropNal : vPropVals )
+ if (! IgnoreForCharStyle(rPropNal.Name, bIsSymbol))
+ rProperties.emplace_back(rPropNal.Name, 0, rPropNal.Value, beans::PropertyState_DIRECT_VALUE);
+
+ return comphelper::containerToSequence(rProperties);
+}
+
+uno::Sequence<beans::PropertyValue> ListLevel::GetLevelProperties(bool bDefaults)
+{
+ std::vector<beans::PropertyValue> aNumberingProperties;
+
+ if (m_nIStartAt >= 0)
+ aNumberingProperties.push_back(lcl_makePropVal<sal_Int16>(PROP_START_WITH, m_nIStartAt) );
+ else if (bDefaults)
+ aNumberingProperties.push_back(lcl_makePropVal<sal_Int16>(PROP_START_WITH, 0));
+
+ sal_Int16 nNumberFormat = -1;
+ if (m_nNFC == NS_ooxml::LN_Value_ST_NumberFormat_custom)
+ {
+ nNumberFormat = ConversionHelper::ConvertCustomNumberFormat(m_aCustomNumberFormat);
+ }
+ else
+ {
+ nNumberFormat = ConversionHelper::ConvertNumberingType(m_nNFC);
+ }
+ if( m_nNFC >= 0)
+ {
+ if (m_xGraphicBitmap.is())
+ nNumberFormat = style::NumberingType::BITMAP;
+ aNumberingProperties.push_back(lcl_makePropVal(PROP_NUMBERING_TYPE, nNumberFormat));
+ }
+
+ // todo: this is not the bullet char
+ if( nNumberFormat == style::NumberingType::CHAR_SPECIAL )
+ {
+ if (!GetBulletChar().isEmpty())
+ {
+ aNumberingProperties.push_back(lcl_makePropVal(PROP_BULLET_CHAR, m_sBulletChar->copy(0, 1)));
+ }
+ else
+ {
+ // If w:lvlText's value is null - set bullet char to zero.
+ aNumberingProperties.push_back(lcl_makePropVal<sal_Unicode>(PROP_BULLET_CHAR, 0));
+ }
+ }
+ if (m_xGraphicBitmap.is())
+ {
+ aNumberingProperties.push_back(lcl_makePropVal(PROP_GRAPHIC_BITMAP, m_xGraphicBitmap));
+ aNumberingProperties.push_back(lcl_makePropVal(PROP_GRAPHIC_SIZE, m_aGraphicSize));
+ }
+
+ if (m_nTabstop.has_value())
+ aNumberingProperties.push_back(lcl_makePropVal(PROP_LISTTAB_STOP_POSITION, *m_nTabstop));
+ else if (bDefaults)
+ aNumberingProperties.push_back(lcl_makePropVal<sal_Int16>(PROP_LISTTAB_STOP_POSITION, 0));
+
+ //TODO: handling of nFLegal?
+ //TODO: nFNoRestart lower levels do not restart when higher levels are incremented, like:
+ //1.
+ //1.1
+ //2.2
+ //2.3
+ //3.4
+
+// TODO: sRGBXchNums; array of inherited numbers
+
+// nXChFollow; following character 0 - tab, 1 - space, 2 - nothing
+ if (bDefaults || m_nXChFollow != SvxNumberFormat::LISTTAB)
+ aNumberingProperties.push_back(lcl_makePropVal(PROP_LEVEL_FOLLOW, m_nXChFollow));
+
+ PropertyIds const aReadIds[] =
+ {
+ PROP_ADJUST, PROP_INDENT_AT, PROP_FIRST_LINE_INDENT,
+ PROP_FIRST_LINE_OFFSET, PROP_LEFT_MARGIN
+ };
+ for(PropertyIds const & rReadId : aReadIds) {
+ std::optional<PropertyMap::Property> aProp = getProperty(rReadId);
+ if (aProp)
+ aNumberingProperties.emplace_back( getPropertyName(aProp->first), 0, aProp->second, beans::PropertyState_DIRECT_VALUE );
+ else if (rReadId == PROP_FIRST_LINE_INDENT && bDefaults)
+ // Writer default is -360 twips, Word default seems to be 0.
+ aNumberingProperties.emplace_back("FirstLineIndent", 0, uno::Any(static_cast<sal_Int32>(0)), beans::PropertyState_DIRECT_VALUE);
+ else if (rReadId == PROP_INDENT_AT && bDefaults)
+ // Writer default is 720 twips, Word default seems to be 0.
+ aNumberingProperties.emplace_back("IndentAt", 0,
+ uno::Any(static_cast<sal_Int32>(0)),
+ beans::PropertyState_DIRECT_VALUE);
+ }
+
+ std::optional<PropertyMap::Property> aPropFont = getProperty(PROP_CHAR_FONT_NAME);
+ if (aPropFont)
+ aNumberingProperties.emplace_back( getPropertyName(PROP_BULLET_FONT_NAME), 0, aPropFont->second, beans::PropertyState_DIRECT_VALUE );
+
+ return comphelper::containerToSequence(aNumberingProperties);
+}
+
+// Add the properties only if they do not already exist in the sequence.
+void ListLevel::AddParaProperties( uno::Sequence< beans::PropertyValue >* props )
+{
+ uno::Sequence< beans::PropertyValue >& aProps = *props;
+
+ OUString sFirstLineIndent = getPropertyName(
+ PROP_FIRST_LINE_INDENT );
+ OUString sIndentAt = getPropertyName(
+ PROP_INDENT_AT );
+
+ bool hasFirstLineIndent = lcl_findProperty( aProps, sFirstLineIndent );
+ bool hasIndentAt = lcl_findProperty( aProps, sIndentAt );
+
+ if( hasFirstLineIndent && hasIndentAt )
+ return; // has them all, nothing to add
+
+ const uno::Sequence< beans::PropertyValue > aParaProps = m_pParaStyle->pProperties->GetPropertyValues( );
+
+ // ParaFirstLineIndent -> FirstLineIndent
+ // ParaLeftMargin -> IndentAt
+
+ OUString sParaIndent = getPropertyName(
+ PROP_PARA_FIRST_LINE_INDENT );
+ OUString sParaLeftMargin = getPropertyName(
+ PROP_PARA_LEFT_MARGIN );
+
+ for ( const auto& rParaProp : aParaProps )
+ {
+ if ( !hasFirstLineIndent && rParaProp.Name == sParaIndent )
+ {
+ aProps.realloc( aProps.getLength() + 1 );
+ auto pProps = aProps.getArray();
+ pProps[aProps.getLength( ) - 1] = rParaProp;
+ pProps[aProps.getLength( ) - 1].Name = sFirstLineIndent;
+ }
+ else if ( !hasIndentAt && rParaProp.Name == sParaLeftMargin )
+ {
+ aProps.realloc( aProps.getLength() + 1 );
+ auto pProps = aProps.getArray();
+ pProps[aProps.getLength( ) - 1] = rParaProp;
+ pProps[aProps.getLength( ) - 1].Name = sIndentAt;
+ }
+
+ }
+}
+
+NumPicBullet::NumPicBullet()
+ : m_nId(0)
+{
+}
+
+NumPicBullet::~NumPicBullet()
+{
+}
+
+void NumPicBullet::SetId(sal_Int32 nId)
+{
+ m_nId = nId;
+}
+
+void NumPicBullet::SetShape(uno::Reference<drawing::XShape> const& xShape)
+{
+ m_xShape = xShape;
+}
+
+
+//--------------------------------------- AbstractListDef implementation
+
+AbstractListDef::AbstractListDef( ) :
+ m_nId( -1 )
+{
+}
+
+AbstractListDef::~AbstractListDef( )
+{
+}
+
+void AbstractListDef::SetValue( sal_uInt32 nSprmId )
+{
+ switch( nSprmId )
+ {
+ case NS_ooxml::LN_CT_AbstractNum_tmpl:
+ break;
+ default:
+ OSL_FAIL( "this line should never be reached");
+ }
+}
+
+ListLevel::Pointer AbstractListDef::GetLevel( sal_uInt16 nLvl )
+{
+ ListLevel::Pointer pLevel;
+ if ( m_aLevels.size( ) > nLvl )
+ pLevel = m_aLevels[ nLvl ];
+ return pLevel;
+}
+
+void AbstractListDef::AddLevel( sal_uInt16 nLvl )
+{
+ if ( nLvl >= m_aLevels.size() )
+ m_aLevels.resize( nLvl+1 );
+
+ if (!m_aLevels[nLvl])
+ {
+ m_aLevels[nLvl] = new ListLevel;
+ }
+
+ m_pCurrentLevel = m_aLevels[nLvl];
+}
+
+uno::Sequence<uno::Sequence<beans::PropertyValue>> AbstractListDef::GetPropertyValues(bool bDefaults)
+{
+ uno::Sequence< uno::Sequence< beans::PropertyValue > > result( sal_Int32( m_aLevels.size( ) ) );
+ uno::Sequence< beans::PropertyValue >* aResult = result.getArray( );
+
+ int nLevels = m_aLevels.size( );
+ for ( int i = 0; i < nLevels; i++ )
+ {
+ if (m_aLevels[i])
+ aResult[i] = m_aLevels[i]->GetProperties(bDefaults);
+ }
+
+ return result;
+}
+
+const OUString& AbstractListDef::MapListId(OUString const& rId)
+{
+ if (!m_oListId)
+ {
+ m_oListId = rId;
+ }
+ return *m_oListId;
+}
+
+//---------------------------------------------- ListDef implementation
+
+ListDef::ListDef( )
+{
+}
+
+ListDef::~ListDef( )
+{
+}
+
+const OUString & ListDef::GetStyleName(sal_Int32 const nId,
+ uno::Reference<container::XNameContainer> const& xStyles)
+{
+ if (xStyles.is())
+ {
+ OUString sStyleName = "WWNum" + OUString::number( nId );
+
+ while (xStyles->hasByName(sStyleName)) // unique
+ {
+ sStyleName += "a";
+ }
+
+ m_StyleName = sStyleName;
+ }
+ else
+ {
+// fails in rtftok test assert(!m_StyleName.isEmpty()); // must be inited first
+ }
+
+ return m_StyleName;
+}
+
+uno::Sequence<uno::Sequence<beans::PropertyValue>> ListDef::GetMergedPropertyValues()
+{
+ if (!m_pAbstractDef)
+ return uno::Sequence< uno::Sequence< beans::PropertyValue > >();
+
+ // [1] Call the same method on the abstract list
+ uno::Sequence<uno::Sequence<beans::PropertyValue>> aAbstract
+ = m_pAbstractDef->GetPropertyValues(/*bDefaults=*/true);
+ auto aAbstractRange = asNonConstRange(aAbstract);
+
+ // [2] Call the upper class method
+ uno::Sequence<uno::Sequence<beans::PropertyValue>> aThis
+ = AbstractListDef::GetPropertyValues(/*bDefaults=*/false);
+
+ // Merge the results of [2] in [1]
+ sal_Int32 nThisCount = aThis.getLength( );
+ sal_Int32 nAbstractCount = aAbstract.getLength( );
+ for ( sal_Int32 i = 0; i < nThisCount && i < nAbstractCount; i++ )
+ {
+ uno::Sequence< beans::PropertyValue > level = aThis[i];
+ if (level.hasElements() && GetLevel(i)->HasValues())
+ {
+ // If the element contains something, merge it, but ignore stub overrides.
+ lcl_mergeProperties( level, aAbstractRange[i] );
+ }
+ }
+
+ return aAbstract;
+}
+
+static uno::Reference< container::XNameContainer > lcl_getUnoNumberingStyles(
+ uno::Reference<lang::XMultiServiceFactory> const& xFactory)
+{
+ uno::Reference< container::XNameContainer > xStyles;
+
+ try
+ {
+ uno::Reference< style::XStyleFamiliesSupplier > xFamilies( xFactory, uno::UNO_QUERY_THROW );
+ uno::Any oFamily = xFamilies->getStyleFamilies( )->getByName("NumberingStyles");
+
+ oFamily >>= xStyles;
+ }
+ catch ( const uno::Exception & )
+ {
+ }
+
+ return xStyles;
+}
+
+/// Rank the list in terms of suitability for becoming the Outline numbering rule in LO.
+sal_uInt16 ListDef::GetChapterNumberingWeight() const
+{
+ sal_Int16 nWeight = 0;
+ const sal_Int8 nAbstLevels = m_pAbstractDef ? m_pAbstractDef->Size() : 0;
+ for (sal_Int8 nLevel = 0; nLevel < nAbstLevels; ++nLevel)
+ {
+ const ListLevel::Pointer pAbsLevel = m_pAbstractDef->GetLevel(nLevel);
+ if (!pAbsLevel)
+ continue;
+ const StyleSheetEntryPtr pParaStyle = pAbsLevel->GetParaStyle();
+ if (!pParaStyle)
+ continue;
+ const StyleSheetPropertyMap& rProps = *pParaStyle->pProperties;
+ // In LO, the level's paraStyle outlineLevel always matches this listLevel.
+ // An undefined listLevel is treated as the first level.
+ sal_Int8 nListLevel = std::clamp<sal_Int8>(rProps.GetListLevel(), 0, 9);
+ if (nListLevel != nLevel || rProps.GetOutlineLevel() != nLevel)
+ return 0;
+ else if (pAbsLevel->GetNumberingType(style::NumberingType::NUMBER_NONE)
+ != style::NumberingType::NUMBER_NONE)
+ {
+ // Arbitrarily chosen weighting factors - trying to round-trip LO choices if possible.
+ // LibreOffice always saves Outline rule (usually containing heading styles) as numId 1.
+ sal_uInt16 nWeightingFactor = GetId() == 1 ? 8 : 1;
+ if (pParaStyle->sStyleIdentifierD.startsWith("Heading") )
+ ++nWeightingFactor;
+ nWeight += nWeightingFactor;
+ }
+ }
+ return nWeight;
+}
+
+void ListDef::CreateNumberingRules( DomainMapper& rDMapper,
+ uno::Reference<lang::XMultiServiceFactory> const& xFactory, sal_Int16 nOutline)
+{
+ // Get the UNO Numbering styles
+ uno::Reference< container::XNameContainer > xStyles = lcl_getUnoNumberingStyles( xFactory );
+
+ // Do the whole thing
+ if( !(!m_xNumRules.is() && xFactory.is() && xStyles.is( )) )
+ return;
+
+ try
+ {
+ // Create the numbering style
+ uno::Reference< beans::XPropertySet > xStyle (
+ xFactory->createInstance("com.sun.star.style.NumberingStyle"),
+ uno::UNO_QUERY_THROW );
+
+ if (GetId() == nOutline)
+ m_StyleName = "Outline"; //SwNumRule.GetOutlineRuleName()
+ else
+ xStyles->insertByName(GetStyleName(GetId(), xStyles), css::uno::Any(xStyle));
+
+ uno::Any oStyle = xStyles->getByName(GetStyleName());
+ xStyle.set( oStyle, uno::UNO_QUERY_THROW );
+
+ // Get the default OOo Numbering style rules
+ uno::Any aRules = xStyle->getPropertyValue( getPropertyName( PROP_NUMBERING_RULES ) );
+ aRules >>= m_xNumRules;
+
+ uno::Sequence<uno::Sequence<beans::PropertyValue>> aProps = GetMergedPropertyValues();
+
+ sal_Int32 nAbstLevels = m_pAbstractDef ? m_pAbstractDef->Size() : 0;
+ sal_Int32 nLevel = 0;
+ while ( nLevel < nAbstLevels )
+ {
+ ListLevel::Pointer pAbsLevel = m_pAbstractDef->GetLevel( nLevel );
+ ListLevel::Pointer pLevel = GetLevel( nLevel );
+
+ // Get the merged level properties
+ auto aLvlProps = comphelper::sequenceToContainer< std::vector<beans::PropertyValue> >(aProps[nLevel]);
+
+ // Get the char style
+ auto aAbsCharStyleProps = pAbsLevel
+ ? pAbsLevel->GetCharStyleProperties()
+ : uno::Sequence<beans::PropertyValue>();
+ if ( pLevel )
+ {
+ uno::Sequence< beans::PropertyValue >& rAbsCharStyleProps = aAbsCharStyleProps;
+ uno::Sequence< beans::PropertyValue > aCharStyleProps =
+ pLevel->GetCharStyleProperties( );
+ uno::Sequence< beans::PropertyValue >& rCharStyleProps = aCharStyleProps;
+ lcl_mergeProperties( rAbsCharStyleProps, rCharStyleProps );
+ }
+
+ // Change the sequence into a vector
+ auto aStyleProps
+ = comphelper::sequenceToContainer<PropertyValueVector_t>(aAbsCharStyleProps);
+
+ //create (or find) a character style containing the character
+ // attributes of the symbol and apply it to the numbering level
+ OUString sStyle = rDMapper.getOrCreateCharStyle(aStyleProps, /*bAlwaysCreate=*/true);
+ aLvlProps.push_back(
+ comphelper::makePropertyValue(getPropertyName(PROP_CHAR_STYLE_NAME), sStyle));
+
+ OUString sText = pAbsLevel
+ ? pAbsLevel->GetBulletChar()
+ : OUString();
+ // Inherit <w:lvlText> from the abstract level in case the override would be empty.
+ if (pLevel && pLevel->HasBulletChar())
+ sText = pLevel->GetBulletChar( );
+
+ aLvlProps.push_back(comphelper::makePropertyValue(getPropertyName(PROP_LIST_FORMAT), sText));
+
+ aLvlProps.push_back(comphelper::makePropertyValue(getPropertyName(PROP_POSITION_AND_SPACE_MODE), sal_Int16(text::PositionAndSpaceMode::LABEL_ALIGNMENT)));
+
+ // Replace the numbering rules for the level
+ m_xNumRules->replaceByIndex(nLevel, uno::Any(comphelper::containerToSequence(aLvlProps)));
+
+ // Handle the outline level here
+ if (GetId() == nOutline && pAbsLevel && pAbsLevel->GetParaStyle())
+ {
+ uno::Reference< text::XChapterNumberingSupplier > xOutlines (
+ xFactory, uno::UNO_QUERY_THROW );
+ uno::Reference< container::XIndexReplace > xOutlineRules =
+ xOutlines->getChapterNumberingRules( );
+
+ StyleSheetEntryPtr pParaStyle = pAbsLevel->GetParaStyle( );
+ pParaStyle->bAssignedAsChapterNumbering = true;
+ aLvlProps.push_back(comphelper::makePropertyValue(getPropertyName(PROP_HEADING_STYLE_NAME), pParaStyle->sConvertedStyleName));
+
+ xOutlineRules->replaceByIndex(nLevel, uno::Any(comphelper::containerToSequence(aLvlProps)));
+ }
+
+ nLevel++;
+ }
+
+ // Create the numbering style for these rules
+ OUString sNumRulesName = getPropertyName( PROP_NUMBERING_RULES );
+ xStyle->setPropertyValue( sNumRulesName, uno::Any( m_xNumRules ) );
+ }
+ catch( const lang::IllegalArgumentException& )
+ {
+ TOOLS_WARN_EXCEPTION( "writerfilter", "" );
+ assert( !"Incorrect argument to UNO call" );
+ }
+ catch( const uno::RuntimeException& )
+ {
+ TOOLS_WARN_EXCEPTION( "writerfilter", "" );
+ assert( !"Incorrect argument to UNO call" );
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "writerfilter", "" );
+ }
+
+}
+
+//------------------------------------- NumberingManager implementation
+
+
+ListsManager::ListsManager(DomainMapper& rDMapper,
+ const uno::Reference<lang::XMultiServiceFactory> & xFactory)
+ : LoggedProperties("ListsManager")
+ , LoggedTable("ListsManager")
+ , m_rDMapper(rDMapper)
+ , m_xFactory(xFactory)
+{
+}
+
+ListsManager::~ListsManager( )
+{
+ DisposeNumPicBullets();
+}
+
+void ListsManager::DisposeNumPicBullets( )
+{
+ uno::Reference<drawing::XShape> xShape;
+ for (const auto& rNumPicBullet : m_aNumPicBullets)
+ {
+ xShape = rNumPicBullet->GetShape();
+ if (xShape.is())
+ {
+ uno::Reference<lang::XComponent> xShapeComponent(xShape, uno::UNO_QUERY);
+ xShapeComponent->dispose();
+ }
+ }
+}
+
+void ListsManager::lcl_attribute( Id nName, Value& rVal )
+{
+ ListLevel::Pointer pCurrentLvl;
+
+ if (nName != NS_ooxml::LN_CT_NumPicBullet_numPicBulletId)
+ {
+ OSL_ENSURE( m_pCurrentDefinition, "current entry has to be set here");
+ if(!m_pCurrentDefinition)
+ return ;
+ pCurrentLvl = m_pCurrentDefinition->GetCurrentLevel( );
+ }
+ else
+ {
+ SAL_WARN_IF(!m_pCurrentNumPicBullet, "writerfilter", "current entry has to be set here");
+ if (!m_pCurrentNumPicBullet)
+ return;
+ }
+ int nIntValue = rVal.getInt();
+
+
+ switch(nName)
+ {
+ case NS_ooxml::LN_CT_LevelText_val:
+ {
+ if(pCurrentLvl)
+ {
+ //if the BulletChar is a soft-hyphen (0xad)
+ //replace it with a hard-hyphen (0x2d)
+ //-> this fixes missing hyphen export in PDF etc.
+ // see tdf#101626
+ std::string sLevelText = rVal.getString().replace(0xad, 0x2d).toUtf8().getStr();
+
+ // DOCX level-text contains levels definition in format "%1.%2.%3"
+ // we need to convert it to LO internal representation: "%1%.%2%.%3%"
+ static const std::regex aTokenRegex("(%\\d)");
+ sLevelText = std::regex_replace(sLevelText, aTokenRegex, "$1%");
+ pCurrentLvl->SetBulletChar( OUString::fromUtf8(sLevelText) );
+ }
+ }
+ break;
+ case NS_ooxml::LN_CT_Lvl_start:
+ case NS_ooxml::LN_CT_Lvl_numFmt:
+ case NS_ooxml::LN_CT_NumFmt_format:
+ case NS_ooxml::LN_CT_NumFmt_val:
+ case NS_ooxml::LN_CT_Lvl_isLgl:
+ case NS_ooxml::LN_CT_Lvl_legacy:
+ if ( pCurrentLvl )
+ {
+ if (nName == NS_ooxml::LN_CT_NumFmt_format)
+ {
+ pCurrentLvl->SetCustomNumberFormat(rVal.getString());
+ }
+ else
+ {
+ pCurrentLvl->SetValue(nName, sal_Int32(nIntValue));
+ }
+ }
+ break;
+ case NS_ooxml::LN_CT_Num_numId:
+ m_pCurrentDefinition->SetId( rVal.getString().toInt32( ) );
+ break;
+ case NS_ooxml::LN_CT_AbstractNum_nsid:
+ m_pCurrentDefinition->SetId( nIntValue );
+ break;
+ case NS_ooxml::LN_CT_AbstractNum_tmpl:
+ AbstractListDef::SetValue( nName );
+ break;
+ case NS_ooxml::LN_CT_NumLvl_ilvl:
+ //add a new level to the level vector and make it the current one
+ m_pCurrentDefinition->AddLevel(rVal.getString().toUInt32());
+ break;
+ case NS_ooxml::LN_CT_Lvl_ilvl:
+ m_pCurrentDefinition->AddLevel(rVal.getString().toUInt32());
+ break;
+ case NS_ooxml::LN_CT_AbstractNum_abstractNumId:
+ {
+ // This one corresponds to the AbstractNum Id definition
+ // The reference to the abstract num is in the sprm method
+ sal_Int32 nVal = rVal.getString().toInt32();
+ m_pCurrentDefinition->SetId( nVal );
+ }
+ break;
+ case NS_ooxml::LN_CT_Ind_start:
+ case NS_ooxml::LN_CT_Ind_left:
+ if ( pCurrentLvl )
+ pCurrentLvl->Insert(
+ PROP_INDENT_AT, uno::Any( ConversionHelper::convertTwipToMM100( nIntValue ) ));
+ break;
+ case NS_ooxml::LN_CT_Ind_hanging:
+ if ( pCurrentLvl )
+ pCurrentLvl->Insert(
+ PROP_FIRST_LINE_INDENT, uno::Any( - ConversionHelper::convertTwipToMM100( nIntValue ) ));
+ break;
+ case NS_ooxml::LN_CT_Ind_firstLine:
+ if ( pCurrentLvl )
+ pCurrentLvl->Insert(
+ PROP_FIRST_LINE_INDENT, uno::Any( ConversionHelper::convertTwipToMM100( nIntValue ) ));
+ break;
+ case NS_ooxml::LN_CT_Lvl_tplc: //template code - unsupported
+ case NS_ooxml::LN_CT_Lvl_tentative: //marks level as unused in the document - unsupported
+ break;
+ case NS_ooxml::LN_CT_TabStop_pos:
+ {
+ //no paragraph attributes in ListTable char style sheets
+ if ( pCurrentLvl )
+ pCurrentLvl->SetValue( nName,
+ ConversionHelper::convertTwipToMM100( nIntValue ) );
+ }
+ break;
+ case NS_ooxml::LN_CT_TabStop_val:
+ {
+ // TODO Do something of that
+ }
+ break;
+ case NS_ooxml::LN_CT_NumPicBullet_numPicBulletId:
+ m_pCurrentNumPicBullet->SetId(rVal.getString().toInt32());
+ break;
+ default:
+ SAL_WARN("writerfilter", "ListsManager::lcl_attribute: unhandled token: " << nName);
+ }
+}
+
+void ListsManager::lcl_sprm( Sprm& rSprm )
+{
+ //fill the attributes of the style sheet
+ sal_uInt32 nSprmId = rSprm.getId();
+ if( !(m_pCurrentDefinition ||
+ nSprmId == NS_ooxml::LN_CT_Numbering_abstractNum ||
+ nSprmId == NS_ooxml::LN_CT_Numbering_num ||
+ (nSprmId == NS_ooxml::LN_CT_NumPicBullet_pict && m_pCurrentNumPicBullet) ||
+ nSprmId == NS_ooxml::LN_CT_Numbering_numPicBullet))
+ return;
+
+ static bool bIsStartVisited = false;
+ sal_Int32 nIntValue = rSprm.getValue()->getInt();
+ switch( nSprmId )
+ {
+ case NS_ooxml::LN_CT_Numbering_abstractNum:
+ {
+ writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
+ if(pProperties)
+ {
+ //create a new Abstract list entry
+ OSL_ENSURE( !m_pCurrentDefinition, "current entry has to be NULL here");
+ m_pCurrentDefinition = new AbstractListDef;
+ pProperties->resolve( *this );
+ //append it to the table
+ m_aAbstractLists.push_back( m_pCurrentDefinition );
+ m_pCurrentDefinition = AbstractListDef::Pointer();
+ }
+ }
+ break;
+ case NS_ooxml::LN_CT_Numbering_num:
+ {
+ writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
+ if(pProperties)
+ {
+ // Create a new list entry
+ OSL_ENSURE( !m_pCurrentDefinition, "current entry has to be NULL here");
+ ListDef::Pointer listDef( new ListDef );
+ m_pCurrentDefinition = listDef.get();
+ pProperties->resolve( *this );
+ //append it to the table
+ m_aLists.push_back( listDef );
+
+ m_pCurrentDefinition = AbstractListDef::Pointer();
+ }
+ }
+ break;
+ case NS_ooxml::LN_CT_Numbering_numPicBullet:
+ {
+ writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
+ if (pProperties)
+ {
+ NumPicBullet::Pointer numPicBullet(new NumPicBullet());
+ m_pCurrentNumPicBullet = numPicBullet;
+ pProperties->resolve(*this);
+ m_aNumPicBullets.push_back(numPicBullet);
+ m_pCurrentNumPicBullet = NumPicBullet::Pointer();
+ }
+ }
+ break;
+ case NS_ooxml::LN_CT_NumPicBullet_pict:
+ {
+ uno::Reference<drawing::XShape> xShape = m_rDMapper.PopPendingShape();
+
+ m_pCurrentNumPicBullet->SetShape(xShape);
+ }
+ break;
+ case NS_ooxml::LN_CT_Lvl_lvlPicBulletId:
+ if (ListLevel::Pointer pCurrentLevel = m_pCurrentDefinition->GetCurrentLevel())
+ {
+ uno::Reference<drawing::XShape> xShape;
+ for (const auto& rNumPicBullet : m_aNumPicBullets)
+ {
+ if (rNumPicBullet->GetId() == nIntValue)
+ {
+ xShape = rNumPicBullet->GetShape();
+ break;
+ }
+ }
+ if (xShape.is())
+ {
+ uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
+ try
+ {
+ uno::Any aAny = xPropertySet->getPropertyValue("Graphic");
+ if (aAny.has<uno::Reference<graphic::XGraphic>>() && pCurrentLevel)
+ {
+ auto xGraphic = aAny.get<uno::Reference<graphic::XGraphic>>();
+ if (xGraphic.is())
+ {
+ uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
+ pCurrentLevel->SetGraphicBitmap(xBitmap);
+ }
+ }
+ }
+ catch (const beans::UnknownPropertyException&)
+ {}
+
+ // Respect only the aspect ratio of the picture, not its size.
+ awt::Size aPrefSize = xShape->getSize();
+ if ( aPrefSize.Height * aPrefSize.Width != 0 )
+ {
+ // See SwDefBulletConfig::InitFont(), default height is 14.
+ const int nFontHeight = 14;
+ // Point -> mm100.
+ const int nHeight = nFontHeight * 35;
+ int nWidth = (nHeight * aPrefSize.Width) / aPrefSize.Height;
+
+ awt::Size aSize( o3tl::toTwips(nWidth, o3tl::Length::mm100), o3tl::toTwips(nHeight, o3tl::Length::mm100) );
+ pCurrentLevel->SetGraphicSize( aSize );
+ }
+ else
+ {
+ awt::Size aSize( o3tl::toTwips(aPrefSize.Width, o3tl::Length::mm100), o3tl::toTwips(aPrefSize.Height, o3tl::Length::mm100) );
+ pCurrentLevel->SetGraphicSize( aSize );
+ }
+ }
+ }
+ break;
+ case NS_ooxml::LN_CT_Num_abstractNumId:
+ {
+ sal_Int32 nAbstractNumId = rSprm.getValue()->getInt();
+ ListDef* pListDef = dynamic_cast< ListDef* >( m_pCurrentDefinition.get( ) );
+ if ( pListDef != nullptr )
+ {
+ // The current def should be a ListDef
+ pListDef->SetAbstractDefinition(
+ GetAbstractList( nAbstractNumId ) );
+ }
+ }
+ break;
+ case NS_ooxml::LN_CT_AbstractNum_multiLevelType:
+ break;
+ case NS_ooxml::LN_CT_AbstractNum_tmpl:
+ AbstractListDef::SetValue( nSprmId );
+ break;
+ case NS_ooxml::LN_CT_AbstractNum_lvl:
+ {
+ writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
+ if(pProperties)
+ pProperties->resolve(*this);
+ }
+ break;
+ case NS_ooxml::LN_CT_Lvl_start:
+ if (ListLevel::Pointer pCurrentLevel = m_pCurrentDefinition->GetCurrentLevel())
+ pCurrentLevel->SetValue( nSprmId, nIntValue );
+ bIsStartVisited = true;
+ break;
+ case NS_ooxml::LN_CT_Lvl_numFmt:
+ {
+ writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
+ if (pProperties)
+ {
+ pProperties->resolve(*this);
+ }
+ if (ListLevel::Pointer pCurrentLevel = m_pCurrentDefinition->GetCurrentLevel())
+ {
+ if( !bIsStartVisited )
+ {
+ pCurrentLevel->SetValue( NS_ooxml::LN_CT_Lvl_start, 0 );
+ bIsStartVisited = true;
+ }
+ }
+ }
+ break;
+ case NS_ooxml::LN_CT_Lvl_isLgl:
+ case NS_ooxml::LN_CT_Lvl_legacy:
+ if (ListLevel::Pointer pCurrentLevel = m_pCurrentDefinition->GetCurrentLevel())
+ {
+ pCurrentLevel->SetValue(nSprmId, nIntValue);
+ }
+ break;
+ case NS_ooxml::LN_CT_Lvl_suff:
+ {
+ if (ListLevel::Pointer pCurrentLevel = m_pCurrentDefinition->GetCurrentLevel())
+ {
+ SvxNumberFormat::LabelFollowedBy value = SvxNumberFormat::LISTTAB;
+ if( rSprm.getValue()->getString() == "tab" )
+ value = SvxNumberFormat::LISTTAB;
+ else if( rSprm.getValue()->getString() == "space" )
+ value = SvxNumberFormat::SPACE;
+ else if( rSprm.getValue()->getString() == "nothing" )
+ value = SvxNumberFormat::NOTHING;
+ else
+ SAL_WARN( "writerfilter", "Unknown ST_LevelSuffix value "
+ << rSprm.getValue()->getString());
+ pCurrentLevel->SetValue( nSprmId, value );
+ }
+ }
+ break;
+ case NS_ooxml::LN_CT_Lvl_lvlText:
+ case NS_ooxml::LN_CT_Lvl_rPr : //contains LN_EG_RPrBase_rFonts
+ {
+ writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
+ if(pProperties)
+ pProperties->resolve(*this);
+ }
+ break;
+ case NS_ooxml::LN_CT_NumLvl_lvl:
+ {
+ // overwrite level
+ writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
+ if(pProperties)
+ pProperties->resolve(*this);
+ }
+ break;
+ case NS_ooxml::LN_CT_Lvl_lvlJc:
+ {
+ sal_Int16 nValue = text::HoriOrientation::NONE;
+ switch (nIntValue)
+ {
+ case NS_ooxml::LN_Value_ST_Jc_left:
+ case NS_ooxml::LN_Value_ST_Jc_start:
+ nValue = text::HoriOrientation::LEFT;
+ break;
+ case NS_ooxml::LN_Value_ST_Jc_center:
+ nValue = text::HoriOrientation::CENTER;
+ break;
+ case NS_ooxml::LN_Value_ST_Jc_right:
+ case NS_ooxml::LN_Value_ST_Jc_end:
+ nValue = text::HoriOrientation::RIGHT;
+ break;
+ }
+
+ if (nValue != text::HoriOrientation::NONE)
+ {
+ if (ListLevel::Pointer pLevel = m_pCurrentDefinition->GetCurrentLevel())
+ {
+ pLevel->Insert(
+ PROP_ADJUST, uno::Any( nValue ) );
+ }
+ }
+ }
+ break;
+ case NS_ooxml::LN_CT_Lvl_pPr:
+ case NS_ooxml::LN_CT_PPrBase_ind:
+ {
+ //todo: how to handle paragraph properties within numbering levels (except LeftIndent and FirstLineIndent)?
+ writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
+ if(pProperties)
+ pProperties->resolve(*this);
+ }
+ break;
+ case NS_ooxml::LN_CT_PPrBase_tabs:
+ case NS_ooxml::LN_CT_Tabs_tab:
+ {
+ writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
+ if(pProperties)
+ pProperties->resolve(*this);
+ }
+ break;
+ case NS_ooxml::LN_CT_Lvl_pStyle:
+ {
+ OUString sStyleName = rSprm.getValue( )->getString( );
+ if (ListLevel::Pointer pLevel = m_pCurrentDefinition->GetCurrentLevel())
+ {
+ StyleSheetTablePtr pStylesTable = m_rDMapper.GetStyleSheetTable( );
+ const StyleSheetEntryPtr pStyle = pStylesTable->FindStyleSheetByISTD( sStyleName );
+ pLevel->SetParaStyle( pStyle );
+ }
+ }
+ break;
+ case NS_ooxml::LN_CT_Num_lvlOverride:
+ {
+ writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
+ if (pProperties)
+ pProperties->resolve(*this);
+ }
+ break;
+ case NS_ooxml::LN_CT_NumLvl_startOverride:
+ {
+ if(m_pCurrentDefinition)
+ {
+ if (ListLevel::Pointer pCurrentLevel = m_pCurrentDefinition->GetCurrentLevel())
+ {
+ pCurrentLevel->SetValue(NS_ooxml::LN_CT_NumLvl_startOverride, nIntValue);
+ }
+ }
+ }
+ break;
+ case NS_ooxml::LN_CT_AbstractNum_numStyleLink:
+ {
+ OUString sStyleName = rSprm.getValue( )->getString( );
+ m_pCurrentDefinition->SetNumStyleLink(sStyleName);
+ }
+ break;
+ case NS_ooxml::LN_CT_AbstractNum_styleLink:
+ {
+ OUString sStyleName = rSprm.getValue()->getString();
+ m_pCurrentDefinition->SetStyleLink(sStyleName);
+ }
+ break;
+ case NS_ooxml::LN_EG_RPrBase_rFonts: //contains font properties
+ case NS_ooxml::LN_EG_RPrBase_color:
+ case NS_ooxml::LN_EG_RPrBase_u:
+ case NS_ooxml::LN_EG_RPrBase_sz:
+ case NS_ooxml::LN_EG_RPrBase_lang:
+ case NS_ooxml::LN_EG_RPrBase_eastAsianLayout:
+ //no break!
+ default:
+ if (ListLevel::Pointer pCurrentLevel = m_pCurrentDefinition->GetCurrentLevel())
+ {
+ m_rDMapper.PushListProperties(pCurrentLevel.get());
+ m_rDMapper.sprm( rSprm );
+ m_rDMapper.PopListProperties();
+ }
+ }
+}
+
+void ListsManager::lcl_entry(writerfilter::Reference<Properties>::Pointer_t ref )
+{
+ if( m_rDMapper.IsOOXMLImport() || m_rDMapper.IsRTFImport() )
+ {
+ ref->resolve(*this);
+ }
+ else
+ {
+ // Create AbstractListDef's
+ OSL_ENSURE( !m_pCurrentDefinition, "current entry has to be NULL here");
+ m_pCurrentDefinition = new AbstractListDef( );
+ ref->resolve(*this);
+ //append it to the table
+ m_aAbstractLists.push_back( m_pCurrentDefinition );
+ m_pCurrentDefinition = AbstractListDef::Pointer();
+ }
+}
+
+AbstractListDef::Pointer ListsManager::GetAbstractList( sal_Int32 nId )
+{
+ for (const auto& listDef : m_aAbstractLists)
+ {
+ if (listDef->GetId( ) == nId)
+ {
+ if (listDef->GetNumStyleLink().getLength() > 0)
+ {
+ // If the abstract num has a style linked, check the linked style's number id.
+ StyleSheetTablePtr pStylesTable = m_rDMapper.GetStyleSheetTable( );
+
+ const StyleSheetEntryPtr pStyleSheetEntry =
+ pStylesTable->FindStyleSheetByISTD(listDef->GetNumStyleLink() );
+
+ const StyleSheetPropertyMap* pStyleSheetProperties =
+ pStyleSheetEntry ? pStyleSheetEntry->pProperties.get() : nullptr;
+
+ if( pStyleSheetProperties && pStyleSheetProperties->GetListId() >= 0 )
+ {
+ ListDef::Pointer pList = GetList( pStyleSheetProperties->GetListId() );
+ if ( pList!=nullptr )
+ return pList->GetAbstractDefinition();
+ }
+
+ // In stylesheet we did not found anything useful. Try to find base abstractnum having this stylelink
+ for (const auto & baseListDef : m_aAbstractLists)
+ {
+ if (baseListDef->GetStyleLink() == listDef->GetNumStyleLink())
+ {
+ return baseListDef;
+ }
+ }
+ }
+
+ // Standalone abstract list
+ return listDef;
+ }
+ }
+
+ return nullptr;
+}
+
+ListDef::Pointer ListsManager::GetList( sal_Int32 nId )
+{
+ ListDef::Pointer pList;
+ if (nId == -1)
+ return pList;
+
+ int nLen = m_aLists.size( );
+ int i = 0;
+ while ( !pList && i < nLen )
+ {
+ if ( m_aLists[i]->GetId( ) == nId )
+ pList = m_aLists[i];
+ i++;
+ }
+
+ // nId 0 is only valid for abstractNum, not numId (which has an abstract definition)
+ assert(!pList || nId || !pList->GetAbstractDefinition() || m_rDMapper.IsRTFImport());
+
+ return pList;
+}
+
+void ListsManager::CreateNumberingRules( )
+{
+ // Try to determine which numId would best work as LO's Chapter Numbering Outline rule.
+ // (The best fix for many import bugs is just to prevent ANY assignment as chapter numbering.)
+ sal_Int16 nChosenAsChapterNumberingId = -1;
+ sal_uInt16 nHighestWeight = 5; // arbitrarily chosen minimum threshold
+ for (const auto& rList : m_aLists)
+ {
+ sal_uInt16 nWeight = rList->GetChapterNumberingWeight();
+ if (nWeight > nHighestWeight)
+ {
+ nHighestWeight = nWeight;
+ nChosenAsChapterNumberingId = rList->GetId();
+ //Optimization: if the weight cannot be beaten anymore, then quit early
+ if (nHighestWeight > 17)
+ break;
+ }
+ }
+
+ // Loop over the definitions
+ for ( const auto& rList : m_aLists )
+ {
+ rList->CreateNumberingRules(m_rDMapper, m_xFactory, nChosenAsChapterNumberingId);
+ }
+ m_rDMapper.GetStyleSheetTable()->ReApplyInheritedOutlineLevelFromChapterNumbering();
+ m_rDMapper.GetStyleSheetTable()->ApplyNumberingStyleNameToParaStyles();
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */