1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <sal/config.h>
21
22 #include "ConversionHelper.hxx"
23 #include "NumberingManager.hxx"
24 #include "StyleSheetTable.hxx"
25 #include "PropertyIds.hxx"
26
27 #include <ooxml/resourceids.hxx>
28
29 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
30 #include <com/sun/star/container/XNameContainer.hpp>
31 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
32 #include <com/sun/star/style/NumberingType.hpp>
33 #include <com/sun/star/text/HoriOrientation.hpp>
34 #include <com/sun/star/text/PositionAndSpaceMode.hpp>
35 #include <com/sun/star/text/XChapterNumberingSupplier.hpp>
36 #include <com/sun/star/graphic/XGraphic.hpp>
37 #include <com/sun/star/awt/XBitmap.hpp>
38
39 #include <osl/diagnose.h>
40 #include <rtl/ustring.hxx>
41 #include <sal/log.hxx>
42 #include <tools/diagnose_ex.h>
43 #include <tools/UnitConversion.hxx>
44 #include <comphelper/sequence.hxx>
45 #include <comphelper/propertyvalue.hxx>
46 #include <comphelper/string.hxx>
47 #include <regex>
48
49 using namespace com::sun::star;
50
51 namespace writerfilter::dmapper {
52
53 //--------------------------------------------------- Utility functions
54 template <typename T>
lcl_makePropVal(PropertyIds nNameID,T const & aValue)55 static beans::PropertyValue lcl_makePropVal(PropertyIds nNameID, T const & aValue)
56 {
57 return {getPropertyName(nNameID), 0, uno::makeAny(aValue), beans::PropertyState_DIRECT_VALUE};
58 }
59
lcl_findProperty(const uno::Sequence<beans::PropertyValue> & aProps,std::u16string_view sName)60 static sal_Int32 lcl_findProperty( const uno::Sequence< beans::PropertyValue >& aProps, std::u16string_view sName )
61 {
62 sal_Int32 i = 0;
63 sal_Int32 nLen = aProps.getLength( );
64 sal_Int32 nPos = -1;
65
66 while ( nPos == -1 && i < nLen )
67 {
68 if ( aProps[i].Name == sName )
69 nPos = i;
70 else
71 i++;
72 }
73
74 return nPos;
75 }
76
lcl_mergeProperties(const uno::Sequence<beans::PropertyValue> & aSrc,uno::Sequence<beans::PropertyValue> & aDst)77 static void lcl_mergeProperties( const uno::Sequence< beans::PropertyValue >& aSrc,
78 uno::Sequence< beans::PropertyValue >& aDst )
79 {
80 for ( const auto& rProp : aSrc )
81 {
82 // Look for the same property in aDst
83 sal_Int32 nPos = lcl_findProperty( aDst, rProp.Name );
84 if ( nPos >= 0 )
85 {
86 // Replace the property value by the one in aSrc
87 aDst[nPos] = rProp;
88 }
89 else
90 {
91 // Simply add the new value
92 aDst.realloc( aDst.getLength( ) + 1 );
93 aDst[ aDst.getLength( ) - 1 ] = rProp;
94 }
95 }
96 }
97
98 //-------------------------------------------- ListLevel implementation
SetValue(Id nId,sal_Int32 nValue)99 void ListLevel::SetValue( Id nId, sal_Int32 nValue )
100 {
101 switch( nId )
102 {
103 case NS_ooxml::LN_CT_Lvl_start:
104 m_nIStartAt = nValue;
105 break;
106 case NS_ooxml::LN_CT_NumLvl_startOverride:
107 m_nStartOverride = nValue;
108 break;
109 case NS_ooxml::LN_CT_NumFmt_val:
110 m_nNFC = nValue;
111 break;
112 case NS_ooxml::LN_CT_Lvl_isLgl:
113 break;
114 case NS_ooxml::LN_CT_Lvl_legacy:
115 break;
116 case NS_ooxml::LN_CT_Lvl_suff:
117 m_nXChFollow = nValue;
118 break;
119 case NS_ooxml::LN_CT_TabStop_pos:
120 if (nValue < 0)
121 {
122 SAL_INFO("writerfilter",
123 "unsupported list tab stop position " << nValue);
124 }
125 else
126 m_nTabstop = nValue;
127 break;
128 default:
129 OSL_FAIL( "this line should never be reached");
130 }
131 m_bHasValues = true;
132 }
133
SetCustomNumberFormat(const OUString & rValue)134 void ListLevel::SetCustomNumberFormat(const OUString& rValue) { m_aCustomNumberFormat = rValue; }
135
HasValues() const136 bool ListLevel::HasValues() const
137 {
138 return m_bHasValues;
139 }
140
SetParaStyle(const tools::SvRef<StyleSheetEntry> & pStyle)141 void ListLevel::SetParaStyle( const tools::SvRef< StyleSheetEntry >& pStyle )
142 {
143 if (!pStyle)
144 return;
145 m_pParaStyle = pStyle;
146 // AFAICT .docx spec does not identify which numberings or paragraph
147 // styles are actually the ones to be used for outlines (chapter numbering),
148 // it only kind of says somewhere that they should be named Heading1 to Heading9.
149 const OUString styleId= pStyle->sConvertedStyleName;
150 m_outline = ( styleId.getLength() == RTL_CONSTASCII_LENGTH( "Heading 1" )
151 && styleId.match( "Heading ", 0 )
152 && styleId[ RTL_CONSTASCII_LENGTH( "Heading " ) ] >= '1'
153 && styleId[ RTL_CONSTASCII_LENGTH( "Heading " ) ] <= '9' );
154 }
155
GetProperties(bool bDefaults)156 uno::Sequence<beans::PropertyValue> ListLevel::GetProperties(bool bDefaults)
157 {
158 uno::Sequence<beans::PropertyValue> aLevelProps = GetLevelProperties(bDefaults);
159 if (m_pParaStyle)
160 AddParaProperties( &aLevelProps );
161 return aLevelProps;
162 }
163
IgnoreForCharStyle(std::u16string_view aStr,const bool bIsSymbol)164 static bool IgnoreForCharStyle(std::u16string_view aStr, const bool bIsSymbol)
165 {
166 //Names found in PropertyIds.cxx, Lines 56-396
167 return (aStr==u"Adjust" || aStr==u"IndentAt" || aStr==u"FirstLineIndent"
168 || aStr==u"FirstLineOffset" || aStr==u"LeftMargin"
169 // We need font names when they are different for the bullet and for the text.
170 // But leave symbols alone, we only want to keep the font style for letters and numbers.
171 || (bIsSymbol && aStr==u"CharFontName")
172 );
173 }
GetCharStyleProperties()174 uno::Sequence< beans::PropertyValue > ListLevel::GetCharStyleProperties( )
175 {
176 PropertyValueVector_t rProperties;
177
178 uno::Sequence< beans::PropertyValue > vPropVals = PropertyMap::GetPropertyValues();
179 beans::PropertyValue* aValIter = vPropVals.begin();
180 beans::PropertyValue* aEndIter = vPropVals.end();
181 const bool bIsSymbol(GetBulletChar().getLength() <= 1);
182 for( ; aValIter != aEndIter; ++aValIter )
183 if (! IgnoreForCharStyle(aValIter->Name, bIsSymbol))
184 rProperties.emplace_back(aValIter->Name, 0, aValIter->Value, beans::PropertyState_DIRECT_VALUE);
185
186 return comphelper::containerToSequence(rProperties);
187 }
188
GetLevelProperties(bool bDefaults)189 uno::Sequence<beans::PropertyValue> ListLevel::GetLevelProperties(bool bDefaults)
190 {
191 std::vector<beans::PropertyValue> aNumberingProperties;
192
193 if (m_nIStartAt >= 0)
194 aNumberingProperties.push_back(lcl_makePropVal<sal_Int16>(PROP_START_WITH, m_nIStartAt) );
195 else if (bDefaults)
196 aNumberingProperties.push_back(lcl_makePropVal<sal_Int16>(PROP_START_WITH, 0));
197
198 sal_Int16 nNumberFormat = -1;
199 if (m_nNFC == NS_ooxml::LN_Value_ST_NumberFormat_custom)
200 {
201 nNumberFormat = ConversionHelper::ConvertCustomNumberFormat(m_aCustomNumberFormat);
202 }
203 else
204 {
205 nNumberFormat = ConversionHelper::ConvertNumberingType(m_nNFC);
206 }
207 if( m_nNFC >= 0)
208 {
209 if (m_xGraphicBitmap.is())
210 nNumberFormat = style::NumberingType::BITMAP;
211 aNumberingProperties.push_back(lcl_makePropVal(PROP_NUMBERING_TYPE, nNumberFormat));
212 }
213
214 // todo: this is not the bullet char
215 if( nNumberFormat == style::NumberingType::CHAR_SPECIAL )
216 {
217 if (!GetBulletChar().isEmpty())
218 {
219 aNumberingProperties.push_back(lcl_makePropVal(PROP_BULLET_CHAR, m_sBulletChar->copy(0, 1)));
220 }
221 else
222 {
223 // If w:lvlText's value is null - set bullet char to zero.
224 aNumberingProperties.push_back(lcl_makePropVal<sal_Unicode>(PROP_BULLET_CHAR, 0));
225 }
226 }
227 if (m_xGraphicBitmap.is())
228 {
229 aNumberingProperties.push_back(lcl_makePropVal(PROP_GRAPHIC_BITMAP, m_xGraphicBitmap));
230 aNumberingProperties.push_back(lcl_makePropVal(PROP_GRAPHIC_SIZE, m_aGraphicSize));
231 }
232
233 if (m_nTabstop.has_value())
234 aNumberingProperties.push_back(lcl_makePropVal(PROP_LISTTAB_STOP_POSITION, *m_nTabstop));
235 else if (bDefaults)
236 aNumberingProperties.push_back(lcl_makePropVal<sal_Int16>(PROP_LISTTAB_STOP_POSITION, 0));
237
238 //TODO: handling of nFLegal?
239 //TODO: nFNoRestart lower levels do not restart when higher levels are incremented, like:
240 //1.
241 //1.1
242 //2.2
243 //2.3
244 //3.4
245
246 // TODO: sRGBXchNums; array of inherited numbers
247
248 // nXChFollow; following character 0 - tab, 1 - space, 2 - nothing
249 if (bDefaults || m_nXChFollow != SvxNumberFormat::LISTTAB)
250 aNumberingProperties.push_back(lcl_makePropVal(PROP_LEVEL_FOLLOW, m_nXChFollow));
251
252 PropertyIds const aReadIds[] =
253 {
254 PROP_ADJUST, PROP_INDENT_AT, PROP_FIRST_LINE_INDENT,
255 PROP_FIRST_LINE_OFFSET, PROP_LEFT_MARGIN
256 };
257 for(PropertyIds const & rReadId : aReadIds) {
258 std::optional<PropertyMap::Property> aProp = getProperty(rReadId);
259 if (aProp)
260 aNumberingProperties.emplace_back( getPropertyName(aProp->first), 0, aProp->second, beans::PropertyState_DIRECT_VALUE );
261 else if (rReadId == PROP_FIRST_LINE_INDENT && bDefaults)
262 // Writer default is -360 twips, Word default seems to be 0.
263 aNumberingProperties.emplace_back("FirstLineIndent", 0, uno::makeAny(static_cast<sal_Int32>(0)), beans::PropertyState_DIRECT_VALUE);
264 else if (rReadId == PROP_INDENT_AT && bDefaults)
265 // Writer default is 720 twips, Word default seems to be 0.
266 aNumberingProperties.emplace_back("IndentAt", 0,
267 uno::makeAny(static_cast<sal_Int32>(0)),
268 beans::PropertyState_DIRECT_VALUE);
269 }
270
271 std::optional<PropertyMap::Property> aPropFont = getProperty(PROP_CHAR_FONT_NAME);
272 if (aPropFont)
273 aNumberingProperties.emplace_back( getPropertyName(PROP_BULLET_FONT_NAME), 0, aPropFont->second, beans::PropertyState_DIRECT_VALUE );
274
275 return comphelper::containerToSequence(aNumberingProperties);
276 }
277
278 // Add the properties only if they do not already exist in the sequence.
AddParaProperties(uno::Sequence<beans::PropertyValue> * props)279 void ListLevel::AddParaProperties( uno::Sequence< beans::PropertyValue >* props )
280 {
281 uno::Sequence< beans::PropertyValue >& aProps = *props;
282
283 OUString sFirstLineIndent = getPropertyName(
284 PROP_FIRST_LINE_INDENT );
285 OUString sIndentAt = getPropertyName(
286 PROP_INDENT_AT );
287
288 bool hasFirstLineIndent = lcl_findProperty( aProps, sFirstLineIndent );
289 bool hasIndentAt = lcl_findProperty( aProps, sIndentAt );
290
291 if( hasFirstLineIndent && hasIndentAt )
292 return; // has them all, nothing to add
293
294 const uno::Sequence< beans::PropertyValue > aParaProps = m_pParaStyle->pProperties->GetPropertyValues( );
295
296 // ParaFirstLineIndent -> FirstLineIndent
297 // ParaLeftMargin -> IndentAt
298
299 OUString sParaIndent = getPropertyName(
300 PROP_PARA_FIRST_LINE_INDENT );
301 OUString sParaLeftMargin = getPropertyName(
302 PROP_PARA_LEFT_MARGIN );
303
304 for ( const auto& rParaProp : aParaProps )
305 {
306 if ( !hasFirstLineIndent && rParaProp.Name == sParaIndent )
307 {
308 aProps.realloc( aProps.getLength() + 1 );
309 aProps[aProps.getLength( ) - 1] = rParaProp;
310 aProps[aProps.getLength( ) - 1].Name = sFirstLineIndent;
311 }
312 else if ( !hasIndentAt && rParaProp.Name == sParaLeftMargin )
313 {
314 aProps.realloc( aProps.getLength() + 1 );
315 aProps[aProps.getLength( ) - 1] = rParaProp;
316 aProps[aProps.getLength( ) - 1].Name = sIndentAt;
317 }
318
319 }
320 }
321
NumPicBullet()322 NumPicBullet::NumPicBullet()
323 : m_nId(0)
324 {
325 }
326
~NumPicBullet()327 NumPicBullet::~NumPicBullet()
328 {
329 }
330
SetId(sal_Int32 nId)331 void NumPicBullet::SetId(sal_Int32 nId)
332 {
333 m_nId = nId;
334 }
335
SetShape(uno::Reference<drawing::XShape> const & xShape)336 void NumPicBullet::SetShape(uno::Reference<drawing::XShape> const& xShape)
337 {
338 m_xShape = xShape;
339 }
340
341
342 //--------------------------------------- AbstractListDef implementation
343
AbstractListDef()344 AbstractListDef::AbstractListDef( ) :
345 m_nId( -1 )
346 {
347 }
348
~AbstractListDef()349 AbstractListDef::~AbstractListDef( )
350 {
351 }
352
SetValue(sal_uInt32 nSprmId)353 void AbstractListDef::SetValue( sal_uInt32 nSprmId )
354 {
355 switch( nSprmId )
356 {
357 case NS_ooxml::LN_CT_AbstractNum_tmpl:
358 break;
359 default:
360 OSL_FAIL( "this line should never be reached");
361 }
362 }
363
GetLevel(sal_uInt16 nLvl)364 ListLevel::Pointer AbstractListDef::GetLevel( sal_uInt16 nLvl )
365 {
366 ListLevel::Pointer pLevel;
367 if ( m_aLevels.size( ) > nLvl )
368 pLevel = m_aLevels[ nLvl ];
369 return pLevel;
370 }
371
AddLevel(sal_uInt16 nLvl)372 void AbstractListDef::AddLevel( sal_uInt16 nLvl )
373 {
374 if ( nLvl >= m_aLevels.size() )
375 m_aLevels.resize( nLvl+1 );
376
377 ListLevel::Pointer pLevel( new ListLevel );
378 m_pCurrentLevel = pLevel;
379 m_aLevels[nLvl] = pLevel;
380 }
381
GetPropertyValues(bool bDefaults)382 uno::Sequence<uno::Sequence<beans::PropertyValue>> AbstractListDef::GetPropertyValues(bool bDefaults)
383 {
384 uno::Sequence< uno::Sequence< beans::PropertyValue > > result( sal_Int32( m_aLevels.size( ) ) );
385 uno::Sequence< beans::PropertyValue >* aResult = result.getArray( );
386
387 int nLevels = m_aLevels.size( );
388 for ( int i = 0; i < nLevels; i++ )
389 {
390 if (m_aLevels[i])
391 aResult[i] = m_aLevels[i]->GetProperties(bDefaults);
392 }
393
394 return result;
395 }
396
MapListId(OUString const & rId)397 const OUString& AbstractListDef::MapListId(OUString const& rId)
398 {
399 if (!m_oListId)
400 {
401 m_oListId = rId;
402 }
403 return *m_oListId;
404 }
405
406 //---------------------------------------------- ListDef implementation
407
ListDef()408 ListDef::ListDef( ) : AbstractListDef( )
409 {
410 m_nDefaultParentLevels = WW_OUTLINE_MAX + 1;
411 }
412
~ListDef()413 ListDef::~ListDef( )
414 {
415 }
416
GetStyleName(sal_Int32 const nId,uno::Reference<container::XNameContainer> const & xStyles)417 const OUString & ListDef::GetStyleName(sal_Int32 const nId,
418 uno::Reference<container::XNameContainer> const& xStyles)
419 {
420 if (xStyles.is())
421 {
422 OUString sStyleName = "WWNum" + OUString::number( nId );
423
424 while (xStyles->hasByName(sStyleName)) // unique
425 {
426 sStyleName += "a";
427 }
428
429 m_StyleName = sStyleName;
430 }
431 else
432 {
433 // fails in rtftok test assert(!m_StyleName.isEmpty()); // must be inited first
434 }
435
436 return m_StyleName;
437 }
438
GetMergedPropertyValues()439 uno::Sequence<uno::Sequence<beans::PropertyValue>> ListDef::GetMergedPropertyValues()
440 {
441 if (!m_pAbstractDef)
442 return uno::Sequence< uno::Sequence< beans::PropertyValue > >();
443
444 // [1] Call the same method on the abstract list
445 uno::Sequence<uno::Sequence<beans::PropertyValue>> aAbstract
446 = m_pAbstractDef->GetPropertyValues(/*bDefaults=*/true);
447
448 // [2] Call the upper class method
449 uno::Sequence<uno::Sequence<beans::PropertyValue>> aThis
450 = AbstractListDef::GetPropertyValues(/*bDefaults=*/false);
451
452 // Merge the results of [2] in [1]
453 sal_Int32 nThisCount = aThis.getLength( );
454 sal_Int32 nAbstractCount = aAbstract.getLength( );
455 for ( sal_Int32 i = 0; i < nThisCount && i < nAbstractCount; i++ )
456 {
457 uno::Sequence< beans::PropertyValue > level = aThis[i];
458 if (level.hasElements() && GetLevel(i)->HasValues())
459 {
460 // If the element contains something, merge it, but ignore stub overrides.
461 lcl_mergeProperties( level, aAbstract[i] );
462 }
463 }
464
465 return aAbstract;
466 }
467
lcl_getUnoNumberingStyles(uno::Reference<lang::XMultiServiceFactory> const & xFactory)468 static uno::Reference< container::XNameContainer > lcl_getUnoNumberingStyles(
469 uno::Reference<lang::XMultiServiceFactory> const& xFactory)
470 {
471 uno::Reference< container::XNameContainer > xStyles;
472
473 try
474 {
475 uno::Reference< style::XStyleFamiliesSupplier > xFamilies( xFactory, uno::UNO_QUERY_THROW );
476 uno::Any oFamily = xFamilies->getStyleFamilies( )->getByName("NumberingStyles");
477
478 oFamily >>= xStyles;
479 }
480 catch ( const uno::Exception & )
481 {
482 }
483
484 return xStyles;
485 }
486
CreateNumberingRules(DomainMapper & rDMapper,uno::Reference<lang::XMultiServiceFactory> const & xFactory)487 void ListDef::CreateNumberingRules( DomainMapper& rDMapper,
488 uno::Reference<lang::XMultiServiceFactory> const& xFactory)
489 {
490 // Get the UNO Numbering styles
491 uno::Reference< container::XNameContainer > xStyles = lcl_getUnoNumberingStyles( xFactory );
492
493 // Do the whole thing
494 if( !(!m_xNumRules.is() && xFactory.is() && xStyles.is( )) )
495 return;
496
497 try
498 {
499 // Create the numbering style
500 uno::Reference< beans::XPropertySet > xStyle (
501 xFactory->createInstance("com.sun.star.style.NumberingStyle"),
502 uno::UNO_QUERY_THROW );
503
504 OUString sStyleName = GetStyleName(GetId(), xStyles);
505
506 xStyles->insertByName( sStyleName, makeAny( xStyle ) );
507
508 uno::Any oStyle = xStyles->getByName( sStyleName );
509 xStyle.set( oStyle, uno::UNO_QUERY_THROW );
510
511 // Get the default OOo Numbering style rules
512 uno::Any aRules = xStyle->getPropertyValue( getPropertyName( PROP_NUMBERING_RULES ) );
513 aRules >>= m_xNumRules;
514
515 uno::Sequence<uno::Sequence<beans::PropertyValue>> aProps = GetMergedPropertyValues();
516
517 sal_Int32 nAbstLevels = m_pAbstractDef ? m_pAbstractDef->Size() : 0;
518 sal_Int32 nLevel = 0;
519 while ( nLevel < nAbstLevels )
520 {
521 ListLevel::Pointer pAbsLevel = m_pAbstractDef->GetLevel( nLevel );
522 ListLevel::Pointer pLevel = GetLevel( nLevel );
523
524 // Get the merged level properties
525 auto aLvlProps = comphelper::sequenceToContainer< std::vector<beans::PropertyValue> >(aProps[nLevel]);
526
527 // Get the char style
528 auto aAbsCharStyleProps = pAbsLevel
529 ? pAbsLevel->GetCharStyleProperties()
530 : uno::Sequence<beans::PropertyValue>();
531 if ( pLevel )
532 {
533 uno::Sequence< beans::PropertyValue >& rAbsCharStyleProps = aAbsCharStyleProps;
534 uno::Sequence< beans::PropertyValue > aCharStyleProps =
535 pLevel->GetCharStyleProperties( );
536 uno::Sequence< beans::PropertyValue >& rCharStyleProps = aCharStyleProps;
537 lcl_mergeProperties( rAbsCharStyleProps, rCharStyleProps );
538 }
539
540 if( aAbsCharStyleProps.hasElements() )
541 {
542 // Change the sequence into a vector
543 auto aStyleProps = comphelper::sequenceToContainer<PropertyValueVector_t>(aAbsCharStyleProps);
544
545 //create (or find) a character style containing the character
546 // attributes of the symbol and apply it to the numbering level
547 OUString sStyle = rDMapper.getOrCreateCharStyle( aStyleProps, /*bAlwaysCreate=*/true );
548 aLvlProps.push_back(comphelper::makePropertyValue(getPropertyName(PROP_CHAR_STYLE_NAME), sStyle));
549 }
550
551 OUString sText = pAbsLevel
552 ? pAbsLevel->GetBulletChar()
553 : OUString();
554 // Inherit <w:lvlText> from the abstract level in case the override would be empty.
555 if (pLevel && pLevel->HasBulletChar())
556 sText = pLevel->GetBulletChar( );
557
558 aLvlProps.push_back(comphelper::makePropertyValue(getPropertyName(PROP_LIST_FORMAT), sText));
559
560 aLvlProps.push_back(comphelper::makePropertyValue(getPropertyName(PROP_POSITION_AND_SPACE_MODE), sal_Int16(text::PositionAndSpaceMode::LABEL_ALIGNMENT)));
561
562 // Replace the numbering rules for the level
563 m_xNumRules->replaceByIndex(nLevel, uno::makeAny(comphelper::containerToSequence(aLvlProps)));
564
565 // Handle the outline level here
566 if (pAbsLevel && pAbsLevel->isOutlineNumbering())
567 {
568 uno::Reference< text::XChapterNumberingSupplier > xOutlines (
569 xFactory, uno::UNO_QUERY_THROW );
570 uno::Reference< container::XIndexReplace > xOutlineRules =
571 xOutlines->getChapterNumberingRules( );
572
573 StyleSheetEntryPtr pParaStyle = pAbsLevel->GetParaStyle( );
574 aLvlProps.push_back(comphelper::makePropertyValue(getPropertyName(PROP_HEADING_STYLE_NAME), pParaStyle->sConvertedStyleName));
575
576 xOutlineRules->replaceByIndex(nLevel, uno::makeAny(comphelper::containerToSequence(aLvlProps)));
577 }
578
579 if (pAbsLevel)
580 {
581 // first level without default outline paragraph style
582 const tools::SvRef< StyleSheetEntry >& aParaStyle = pAbsLevel->GetParaStyle();
583 if ( WW_OUTLINE_MAX + 1 == m_nDefaultParentLevels && ( !aParaStyle ||
584 aParaStyle->sConvertedStyleName.getLength() != RTL_CONSTASCII_LENGTH( "Heading 1" ) ||
585 !aParaStyle->sConvertedStyleName.startsWith("Heading ") ||
586 aParaStyle->sConvertedStyleName[ RTL_CONSTASCII_LENGTH( "Heading " ) ] - u'1' != nLevel ) )
587 {
588 m_nDefaultParentLevels = nLevel;
589 }
590 }
591
592 nLevel++;
593 }
594
595 // Create the numbering style for these rules
596 OUString sNumRulesName = getPropertyName( PROP_NUMBERING_RULES );
597 xStyle->setPropertyValue( sNumRulesName, uno::makeAny( m_xNumRules ) );
598 }
599 catch( const lang::IllegalArgumentException& )
600 {
601 TOOLS_WARN_EXCEPTION( "writerfilter", "" );
602 assert( !"Incorrect argument to UNO call" );
603 }
604 catch( const uno::RuntimeException& )
605 {
606 TOOLS_WARN_EXCEPTION( "writerfilter", "" );
607 assert( !"Incorrect argument to UNO call" );
608 }
609 catch( const uno::Exception& )
610 {
611 TOOLS_WARN_EXCEPTION( "writerfilter", "" );
612 }
613
614 }
615
616 //------------------------------------- NumberingManager implementation
617
618
ListsManager(DomainMapper & rDMapper,const uno::Reference<lang::XMultiServiceFactory> & xFactory)619 ListsManager::ListsManager(DomainMapper& rDMapper,
620 const uno::Reference<lang::XMultiServiceFactory> & xFactory)
621 : LoggedProperties("ListsManager")
622 , LoggedTable("ListsManager")
623 , m_rDMapper(rDMapper)
624 , m_xFactory(xFactory)
625 {
626 }
627
~ListsManager()628 ListsManager::~ListsManager( )
629 {
630 DisposeNumPicBullets();
631 }
632
DisposeNumPicBullets()633 void ListsManager::DisposeNumPicBullets( )
634 {
635 uno::Reference<drawing::XShape> xShape;
636 for (const auto& rNumPicBullet : m_aNumPicBullets)
637 {
638 xShape = rNumPicBullet->GetShape();
639 if (xShape.is())
640 {
641 uno::Reference<lang::XComponent> xShapeComponent(xShape, uno::UNO_QUERY);
642 xShapeComponent->dispose();
643 }
644 }
645 }
646
lcl_attribute(Id nName,Value & rVal)647 void ListsManager::lcl_attribute( Id nName, Value& rVal )
648 {
649 ListLevel::Pointer pCurrentLvl;
650
651 if (nName != NS_ooxml::LN_CT_NumPicBullet_numPicBulletId)
652 {
653 OSL_ENSURE( m_pCurrentDefinition, "current entry has to be set here");
654 if(!m_pCurrentDefinition)
655 return ;
656 pCurrentLvl = m_pCurrentDefinition->GetCurrentLevel( );
657 }
658 else
659 {
660 SAL_WARN_IF(!m_pCurrentNumPicBullet, "writerfilter", "current entry has to be set here");
661 if (!m_pCurrentNumPicBullet)
662 return;
663 }
664 int nIntValue = rVal.getInt();
665
666
667 switch(nName)
668 {
669 case NS_ooxml::LN_CT_LevelText_val:
670 {
671 if(pCurrentLvl)
672 {
673 //if the BulletChar is a soft-hyphen (0xad)
674 //replace it with a hard-hyphen (0x2d)
675 //-> this fixes missing hyphen export in PDF etc.
676 // see tdf#101626
677 std::string sLevelText = rVal.getString().replace(0xad, 0x2d).toUtf8().getStr();
678
679 // DOCX level-text contains levels definition in format "%1.%2.%3"
680 // we need to convert it to LO internal representation: "%1%.%2%.%3%"
681 static const std::regex aTokenRegex("(%\\d)");
682 sLevelText = std::regex_replace(sLevelText, aTokenRegex, "$1%");
683 pCurrentLvl->SetBulletChar( OUString::fromUtf8(sLevelText) );
684 }
685 }
686 break;
687 case NS_ooxml::LN_CT_Lvl_start:
688 case NS_ooxml::LN_CT_Lvl_numFmt:
689 case NS_ooxml::LN_CT_NumFmt_format:
690 case NS_ooxml::LN_CT_NumFmt_val:
691 case NS_ooxml::LN_CT_Lvl_isLgl:
692 case NS_ooxml::LN_CT_Lvl_legacy:
693 if ( pCurrentLvl )
694 {
695 if (nName == NS_ooxml::LN_CT_NumFmt_format)
696 {
697 pCurrentLvl->SetCustomNumberFormat(rVal.getString());
698 }
699 else
700 {
701 pCurrentLvl->SetValue(nName, sal_Int32(nIntValue));
702 }
703 }
704 break;
705 case NS_ooxml::LN_CT_Num_numId:
706 m_pCurrentDefinition->SetId( rVal.getString().toInt32( ) );
707 break;
708 case NS_ooxml::LN_CT_AbstractNum_nsid:
709 m_pCurrentDefinition->SetId( nIntValue );
710 break;
711 case NS_ooxml::LN_CT_AbstractNum_tmpl:
712 AbstractListDef::SetValue( nName );
713 break;
714 case NS_ooxml::LN_CT_NumLvl_ilvl:
715 //add a new level to the level vector and make it the current one
716 m_pCurrentDefinition->AddLevel(rVal.getString().toUInt32());
717 break;
718 case NS_ooxml::LN_CT_Lvl_ilvl:
719 m_pCurrentDefinition->AddLevel(rVal.getString().toUInt32());
720 break;
721 case NS_ooxml::LN_CT_AbstractNum_abstractNumId:
722 {
723 // This one corresponds to the AbstractNum Id definition
724 // The reference to the abstract num is in the sprm method
725 sal_Int32 nVal = rVal.getString().toInt32();
726 m_pCurrentDefinition->SetId( nVal );
727 }
728 break;
729 case NS_ooxml::LN_CT_Ind_start:
730 case NS_ooxml::LN_CT_Ind_left:
731 if ( pCurrentLvl )
732 pCurrentLvl->Insert(
733 PROP_INDENT_AT, uno::makeAny( ConversionHelper::convertTwipToMM100( nIntValue ) ));
734 break;
735 case NS_ooxml::LN_CT_Ind_hanging:
736 if ( pCurrentLvl )
737 pCurrentLvl->Insert(
738 PROP_FIRST_LINE_INDENT, uno::makeAny( - ConversionHelper::convertTwipToMM100( nIntValue ) ));
739 break;
740 case NS_ooxml::LN_CT_Ind_firstLine:
741 if ( pCurrentLvl )
742 pCurrentLvl->Insert(
743 PROP_FIRST_LINE_INDENT, uno::makeAny( ConversionHelper::convertTwipToMM100( nIntValue ) ));
744 break;
745 case NS_ooxml::LN_CT_Lvl_tplc: //template code - unsupported
746 case NS_ooxml::LN_CT_Lvl_tentative: //marks level as unused in the document - unsupported
747 break;
748 case NS_ooxml::LN_CT_TabStop_pos:
749 {
750 //no paragraph attributes in ListTable char style sheets
751 if ( pCurrentLvl )
752 pCurrentLvl->SetValue( nName,
753 ConversionHelper::convertTwipToMM100( nIntValue ) );
754 }
755 break;
756 case NS_ooxml::LN_CT_TabStop_val:
757 {
758 // TODO Do something of that
759 }
760 break;
761 case NS_ooxml::LN_CT_NumPicBullet_numPicBulletId:
762 m_pCurrentNumPicBullet->SetId(rVal.getString().toInt32());
763 break;
764 default:
765 SAL_WARN("writerfilter", "ListsManager::lcl_attribute: unhandled token: " << nName);
766 }
767 }
768
lcl_sprm(Sprm & rSprm)769 void ListsManager::lcl_sprm( Sprm& rSprm )
770 {
771 //fill the attributes of the style sheet
772 sal_uInt32 nSprmId = rSprm.getId();
773 if( !(m_pCurrentDefinition ||
774 nSprmId == NS_ooxml::LN_CT_Numbering_abstractNum ||
775 nSprmId == NS_ooxml::LN_CT_Numbering_num ||
776 (nSprmId == NS_ooxml::LN_CT_NumPicBullet_pict && m_pCurrentNumPicBullet) ||
777 nSprmId == NS_ooxml::LN_CT_Numbering_numPicBullet))
778 return;
779
780 static bool bIsStartVisited = false;
781 sal_Int32 nIntValue = rSprm.getValue()->getInt();
782 switch( nSprmId )
783 {
784 case NS_ooxml::LN_CT_Numbering_abstractNum:
785 {
786 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
787 if(pProperties)
788 {
789 //create a new Abstract list entry
790 OSL_ENSURE( !m_pCurrentDefinition, "current entry has to be NULL here");
791 m_pCurrentDefinition = new AbstractListDef;
792 pProperties->resolve( *this );
793 //append it to the table
794 m_aAbstractLists.push_back( m_pCurrentDefinition );
795 m_pCurrentDefinition = AbstractListDef::Pointer();
796 }
797 }
798 break;
799 case NS_ooxml::LN_CT_Numbering_num:
800 {
801 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
802 if(pProperties)
803 {
804 // Create a new list entry
805 OSL_ENSURE( !m_pCurrentDefinition, "current entry has to be NULL here");
806 ListDef::Pointer listDef( new ListDef );
807 m_pCurrentDefinition = listDef.get();
808 pProperties->resolve( *this );
809 //append it to the table
810 m_aLists.push_back( listDef );
811
812 m_pCurrentDefinition = AbstractListDef::Pointer();
813 }
814 }
815 break;
816 case NS_ooxml::LN_CT_Numbering_numPicBullet:
817 {
818 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
819 if (pProperties)
820 {
821 NumPicBullet::Pointer numPicBullet(new NumPicBullet());
822 m_pCurrentNumPicBullet = numPicBullet;
823 pProperties->resolve(*this);
824 m_aNumPicBullets.push_back(numPicBullet);
825 m_pCurrentNumPicBullet = NumPicBullet::Pointer();
826 }
827 }
828 break;
829 case NS_ooxml::LN_CT_NumPicBullet_pict:
830 {
831 uno::Reference<drawing::XShape> xShape = m_rDMapper.PopPendingShape();
832
833 m_pCurrentNumPicBullet->SetShape(xShape);
834 }
835 break;
836 case NS_ooxml::LN_CT_Lvl_lvlPicBulletId:
837 if (ListLevel::Pointer pCurrentLevel = m_pCurrentDefinition->GetCurrentLevel())
838 {
839 uno::Reference<drawing::XShape> xShape;
840 for (const auto& rNumPicBullet : m_aNumPicBullets)
841 {
842 if (rNumPicBullet->GetId() == nIntValue)
843 {
844 xShape = rNumPicBullet->GetShape();
845 break;
846 }
847 }
848 if (xShape.is())
849 {
850 uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
851 try
852 {
853 uno::Any aAny = xPropertySet->getPropertyValue("Graphic");
854 if (aAny.has<uno::Reference<graphic::XGraphic>>() && pCurrentLevel)
855 {
856 auto xGraphic = aAny.get<uno::Reference<graphic::XGraphic>>();
857 if (xGraphic.is())
858 {
859 uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
860 pCurrentLevel->SetGraphicBitmap(xBitmap);
861 }
862 }
863 }
864 catch (const beans::UnknownPropertyException&)
865 {}
866
867 // Respect only the aspect ratio of the picture, not its size.
868 awt::Size aPrefSize = xShape->getSize();
869 if ( aPrefSize.Height * aPrefSize.Width != 0 )
870 {
871 // See SwDefBulletConfig::InitFont(), default height is 14.
872 const int nFontHeight = 14;
873 // Point -> mm100.
874 const int nHeight = nFontHeight * 35;
875 int nWidth = (nHeight * aPrefSize.Width) / aPrefSize.Height;
876
877 awt::Size aSize( convertMm100ToTwip(nWidth), convertMm100ToTwip(nHeight) );
878 pCurrentLevel->SetGraphicSize( aSize );
879 }
880 else
881 {
882 awt::Size aSize( convertMm100ToTwip(aPrefSize.Width), convertMm100ToTwip(aPrefSize.Height) );
883 pCurrentLevel->SetGraphicSize( aSize );
884 }
885 }
886 }
887 break;
888 case NS_ooxml::LN_CT_Num_abstractNumId:
889 {
890 sal_Int32 nAbstractNumId = rSprm.getValue()->getInt();
891 ListDef* pListDef = dynamic_cast< ListDef* >( m_pCurrentDefinition.get( ) );
892 if ( pListDef != nullptr )
893 {
894 // The current def should be a ListDef
895 pListDef->SetAbstractDefinition(
896 GetAbstractList( nAbstractNumId ) );
897 }
898 }
899 break;
900 case NS_ooxml::LN_CT_AbstractNum_multiLevelType:
901 break;
902 case NS_ooxml::LN_CT_AbstractNum_tmpl:
903 AbstractListDef::SetValue( nSprmId );
904 break;
905 case NS_ooxml::LN_CT_AbstractNum_lvl:
906 {
907 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
908 if(pProperties)
909 pProperties->resolve(*this);
910 }
911 break;
912 case NS_ooxml::LN_CT_Lvl_start:
913 if (ListLevel::Pointer pCurrentLevel = m_pCurrentDefinition->GetCurrentLevel())
914 pCurrentLevel->SetValue( nSprmId, nIntValue );
915 bIsStartVisited = true;
916 break;
917 case NS_ooxml::LN_CT_Lvl_numFmt:
918 {
919 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
920 if (pProperties)
921 {
922 pProperties->resolve(*this);
923 }
924 if (ListLevel::Pointer pCurrentLevel = m_pCurrentDefinition->GetCurrentLevel())
925 {
926 if( !bIsStartVisited )
927 {
928 pCurrentLevel->SetValue( NS_ooxml::LN_CT_Lvl_start, 0 );
929 bIsStartVisited = true;
930 }
931 }
932 }
933 break;
934 case NS_ooxml::LN_CT_Lvl_isLgl:
935 case NS_ooxml::LN_CT_Lvl_legacy:
936 if (ListLevel::Pointer pCurrentLevel = m_pCurrentDefinition->GetCurrentLevel())
937 {
938 pCurrentLevel->SetValue(nSprmId, nIntValue);
939 }
940 break;
941 case NS_ooxml::LN_CT_Lvl_suff:
942 {
943 if (ListLevel::Pointer pCurrentLevel = m_pCurrentDefinition->GetCurrentLevel())
944 {
945 SvxNumberFormat::LabelFollowedBy value = SvxNumberFormat::LISTTAB;
946 if( rSprm.getValue()->getString() == "tab" )
947 value = SvxNumberFormat::LISTTAB;
948 else if( rSprm.getValue()->getString() == "space" )
949 value = SvxNumberFormat::SPACE;
950 else if( rSprm.getValue()->getString() == "nothing" )
951 value = SvxNumberFormat::NOTHING;
952 else
953 SAL_WARN( "writerfilter", "Unknown ST_LevelSuffix value "
954 << rSprm.getValue()->getString());
955 pCurrentLevel->SetValue( nSprmId, value );
956 }
957 }
958 break;
959 case NS_ooxml::LN_CT_Lvl_lvlText:
960 case NS_ooxml::LN_CT_Lvl_rPr : //contains LN_EG_RPrBase_rFonts
961 {
962 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
963 if(pProperties)
964 pProperties->resolve(*this);
965 }
966 break;
967 case NS_ooxml::LN_CT_NumLvl_lvl:
968 {
969 // overwrite level
970 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
971 if(pProperties)
972 pProperties->resolve(*this);
973 }
974 break;
975 case NS_ooxml::LN_CT_Lvl_lvlJc:
976 {
977 sal_Int16 nValue = text::HoriOrientation::NONE;
978 switch (nIntValue)
979 {
980 case NS_ooxml::LN_Value_ST_Jc_left:
981 case NS_ooxml::LN_Value_ST_Jc_start:
982 nValue = text::HoriOrientation::LEFT;
983 break;
984 case NS_ooxml::LN_Value_ST_Jc_center:
985 nValue = text::HoriOrientation::CENTER;
986 break;
987 case NS_ooxml::LN_Value_ST_Jc_right:
988 case NS_ooxml::LN_Value_ST_Jc_end:
989 nValue = text::HoriOrientation::RIGHT;
990 break;
991 }
992
993 if (nValue != text::HoriOrientation::NONE)
994 {
995 if (ListLevel::Pointer pLevel = m_pCurrentDefinition->GetCurrentLevel())
996 {
997 pLevel->Insert(
998 PROP_ADJUST, uno::makeAny( nValue ) );
999 }
1000 }
1001 }
1002 break;
1003 case NS_ooxml::LN_CT_Lvl_pPr:
1004 case NS_ooxml::LN_CT_PPrBase_ind:
1005 {
1006 //todo: how to handle paragraph properties within numbering levels (except LeftIndent and FirstLineIndent)?
1007 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
1008 if(pProperties)
1009 pProperties->resolve(*this);
1010 }
1011 break;
1012 case NS_ooxml::LN_CT_PPrBase_tabs:
1013 case NS_ooxml::LN_CT_Tabs_tab:
1014 {
1015 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
1016 if(pProperties)
1017 pProperties->resolve(*this);
1018 }
1019 break;
1020 case NS_ooxml::LN_CT_Lvl_pStyle:
1021 {
1022 OUString sStyleName = rSprm.getValue( )->getString( );
1023 if (ListLevel::Pointer pLevel = m_pCurrentDefinition->GetCurrentLevel())
1024 {
1025 StyleSheetTablePtr pStylesTable = m_rDMapper.GetStyleSheetTable( );
1026 const StyleSheetEntryPtr pStyle = pStylesTable->FindStyleSheetByISTD( sStyleName );
1027 pLevel->SetParaStyle( pStyle );
1028 }
1029 }
1030 break;
1031 case NS_ooxml::LN_CT_Num_lvlOverride:
1032 {
1033 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
1034 if (pProperties)
1035 pProperties->resolve(*this);
1036 }
1037 break;
1038 case NS_ooxml::LN_CT_NumLvl_startOverride:
1039 {
1040 if(m_pCurrentDefinition)
1041 {
1042 if (ListLevel::Pointer pCurrentLevel = m_pCurrentDefinition->GetCurrentLevel())
1043 {
1044 pCurrentLevel->SetValue(NS_ooxml::LN_CT_NumLvl_startOverride, nIntValue);
1045 }
1046 }
1047 }
1048 break;
1049 case NS_ooxml::LN_CT_AbstractNum_numStyleLink:
1050 {
1051 OUString sStyleName = rSprm.getValue( )->getString( );
1052 m_pCurrentDefinition->SetNumStyleLink(sStyleName);
1053 }
1054 break;
1055 case NS_ooxml::LN_CT_AbstractNum_styleLink:
1056 {
1057 OUString sStyleName = rSprm.getValue()->getString();
1058 m_pCurrentDefinition->SetStyleLink(sStyleName);
1059 }
1060 break;
1061 case NS_ooxml::LN_EG_RPrBase_rFonts: //contains font properties
1062 case NS_ooxml::LN_EG_RPrBase_color:
1063 case NS_ooxml::LN_EG_RPrBase_u:
1064 case NS_ooxml::LN_EG_RPrBase_sz:
1065 case NS_ooxml::LN_EG_RPrBase_lang:
1066 case NS_ooxml::LN_EG_RPrBase_eastAsianLayout:
1067 //no break!
1068 default:
1069 if (ListLevel::Pointer pCurrentLevel = m_pCurrentDefinition->GetCurrentLevel())
1070 {
1071 m_rDMapper.PushListProperties(pCurrentLevel.get());
1072 m_rDMapper.sprm( rSprm );
1073 m_rDMapper.PopListProperties();
1074 }
1075 }
1076 }
1077
lcl_entry(writerfilter::Reference<Properties>::Pointer_t ref)1078 void ListsManager::lcl_entry(writerfilter::Reference<Properties>::Pointer_t ref )
1079 {
1080 if( m_rDMapper.IsOOXMLImport() || m_rDMapper.IsRTFImport() )
1081 {
1082 ref->resolve(*this);
1083 }
1084 else
1085 {
1086 // Create AbstractListDef's
1087 OSL_ENSURE( !m_pCurrentDefinition, "current entry has to be NULL here");
1088 m_pCurrentDefinition = new AbstractListDef( );
1089 ref->resolve(*this);
1090 //append it to the table
1091 m_aAbstractLists.push_back( m_pCurrentDefinition );
1092 m_pCurrentDefinition = AbstractListDef::Pointer();
1093 }
1094 }
1095
GetAbstractList(sal_Int32 nId)1096 AbstractListDef::Pointer ListsManager::GetAbstractList( sal_Int32 nId )
1097 {
1098 for (const auto& listDef : m_aAbstractLists)
1099 {
1100 if (listDef->GetId( ) == nId)
1101 {
1102 if (listDef->GetNumStyleLink().getLength() > 0)
1103 {
1104 // If the abstract num has a style linked, check the linked style's number id.
1105 StyleSheetTablePtr pStylesTable = m_rDMapper.GetStyleSheetTable( );
1106
1107 const StyleSheetEntryPtr pStyleSheetEntry =
1108 pStylesTable->FindStyleSheetByISTD(listDef->GetNumStyleLink() );
1109
1110 const StyleSheetPropertyMap* pStyleSheetProperties =
1111 dynamic_cast<const StyleSheetPropertyMap*>(pStyleSheetEntry ? pStyleSheetEntry->pProperties.get() : nullptr);
1112
1113 if( pStyleSheetProperties && pStyleSheetProperties->GetListId() >= 0 )
1114 {
1115 ListDef::Pointer pList = GetList( pStyleSheetProperties->GetListId() );
1116 if ( pList!=nullptr )
1117 return pList->GetAbstractDefinition();
1118 }
1119
1120 // In stylesheet we did not found anything useful. Try to find base abstractnum having this stylelink
1121 for (const auto & baseListDef : m_aAbstractLists)
1122 {
1123 if (baseListDef->GetStyleLink() == listDef->GetNumStyleLink())
1124 {
1125 return baseListDef;
1126 }
1127 }
1128 }
1129
1130 // Standalone abstract list
1131 return listDef;
1132 }
1133 }
1134
1135 return nullptr;
1136 }
1137
GetList(sal_Int32 nId)1138 ListDef::Pointer ListsManager::GetList( sal_Int32 nId )
1139 {
1140 ListDef::Pointer pList;
1141
1142 int nLen = m_aLists.size( );
1143 int i = 0;
1144 while ( !pList && i < nLen )
1145 {
1146 if ( m_aLists[i]->GetId( ) == nId )
1147 pList = m_aLists[i];
1148 i++;
1149 }
1150
1151 return pList;
1152 }
1153
CreateNumberingRules()1154 void ListsManager::CreateNumberingRules( )
1155 {
1156 // Loop over the definitions
1157 for ( const auto& rList : m_aLists )
1158 {
1159 rList->CreateNumberingRules( m_rDMapper, m_xFactory );
1160 }
1161 m_rDMapper.GetStyleSheetTable()->ApplyNumberingStyleNameToParaStyles();
1162 }
1163
1164 }
1165
1166 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1167