1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23 #include "ConversionHelper.hxx"
24 #include "NumberingManager.hxx"
25 #include "StyleSheetTable.hxx"
26 #include "PropertyIds.hxx"
27
28 #include <doctok/resourceids.hxx>
29 #include <doctok/sprmids.hxx>
30 #include <ooxml/resourceids.hxx>
31
32 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
33 #include <com/sun/star/container/XNameContainer.hpp>
34 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
35 #include <com/sun/star/style/NumberingType.hpp>
36 #include <com/sun/star/text/HoriOrientation.hpp>
37 #include <com/sun/star/text/PositionAndSpaceMode.hpp>
38 #include <com/sun/star/text/XChapterNumberingSupplier.hpp>
39
40 #if DEBUG
41 #include <stdio.h>
42 #endif
43
44 #include "dmapperLoggers.hxx"
45
46 using namespace rtl;
47 using namespace com::sun::star;
48
49 #define MAKE_PROPVAL(NameId, Value) \
50 beans::PropertyValue(aPropNameSupplier.GetName(NameId), 0, uno::makeAny(Value), beans::PropertyState_DIRECT_VALUE )
51
52 #define OUSTR_TO_C( x ) OUStringToOString( x, RTL_TEXTENCODING_UTF8 ).getStr( )
53
54 #define NUMBERING_MAX_LEVELS 10
55
56
57 namespace writerfilter {
58 namespace dmapper {
59
60 //--------------------------------------------------- Utility functions
61
lcl_findProperty(uno::Sequence<beans::PropertyValue> aProps,OUString sName)62 sal_Int32 lcl_findProperty( uno::Sequence< beans::PropertyValue > aProps, OUString sName )
63 {
64 sal_Int32 i = 0;
65 sal_Int32 nLen = aProps.getLength( );
66 sal_Int32 nPos = -1;
67
68 while ( nPos == -1 && i < nLen )
69 {
70 if ( aProps[i].Name.equals( sName ) )
71 nPos = i;
72 else
73 i++;
74 }
75
76 return nPos;
77 }
78
lcl_mergeProperties(uno::Sequence<beans::PropertyValue> & aSrc,uno::Sequence<beans::PropertyValue> & aDst)79 void lcl_mergeProperties( uno::Sequence< beans::PropertyValue >& aSrc,
80 uno::Sequence< beans::PropertyValue >& aDst )
81 {
82 for ( sal_Int32 i = 0, nSrcLen = aSrc.getLength( ); i < nSrcLen; i++ )
83 {
84 // Look for the same property in aDst
85 sal_Int32 nPos = lcl_findProperty( aDst, aSrc[i].Name );
86 if ( nPos >= 0 )
87 {
88 // Replace the property value by the one in aSrc
89 aDst[nPos] = aSrc[i];
90 }
91 else
92 {
93 // Simply add the new value
94 aDst.realloc( aDst.getLength( ) + 1 );
95 aDst[ aDst.getLength( ) - 1 ] = aSrc[i];
96 }
97 }
98 }
99
100 //-------------------------------------------- ListLevel implementation
SetValue(Id nId,sal_Int32 nValue)101 void ListLevel::SetValue( Id nId, sal_Int32 nValue )
102 {
103 switch( nId )
104 {
105 case NS_rtf::LN_ISTARTAT:
106 m_nIStartAt = nValue;
107 break;
108 case NS_rtf::LN_NFC:
109 m_nNFC = nValue;
110 break;
111 case NS_rtf::LN_JC:
112 m_nJC = nValue;
113 break;
114 case NS_rtf::LN_FLEGAL:
115 m_nFLegal = nValue;
116 break;
117 case NS_rtf::LN_FNORESTART:
118 m_nFNoRestart = nValue;
119 break;
120 case NS_rtf::LN_FIDENTSAV:
121 m_nFPrev = nValue;
122 break;
123 case NS_rtf::LN_FCONVERTED:
124 m_nFPrevSpace = nValue;
125 break;
126 #if 0
127 case NS_rtf::LN_FWORD6:
128 m_nFWord6 = nValue;
129 break;
130 #endif
131 case NS_rtf::LN_IXCHFOLLOW:
132 m_nXChFollow = nValue;
133 break;
134 case NS_ooxml::LN_CT_TabStop_pos:
135 m_nTabstop = nValue;
136 break;
137 default:
138 OSL_ENSURE( false, "this line should never be reached");
139 }
140 }
141
GetParentNumbering(OUString sText,sal_Int16 nLevel,OUString & rPrefix,OUString & rSuffix)142 sal_Int16 ListLevel::GetParentNumbering( OUString sText, sal_Int16 nLevel,
143 OUString& rPrefix, OUString& rSuffix )
144 {
145 sal_Int16 nParentNumbering = nLevel;
146
147 //now parse the text to find %n from %1 to %nLevel+1
148 //everything before the first % and the last %x is prefix and suffix
149 OUString sLevelText( sText );
150 sal_Int32 nCurrentIndex = 0;
151 sal_Int32 nFound = sLevelText.indexOf( '%', nCurrentIndex );
152 if( nFound > 0 )
153 {
154 rPrefix = sLevelText.copy( 0, nFound );
155 sLevelText = sLevelText.copy( nFound );
156 }
157 sal_Int32 nMinLevel = nLevel;
158 //now the text should either be empty or start with %
159 nFound = sLevelText.getLength( ) > 1 ? 0 : -1;
160 while( nFound >= 0 )
161 {
162 if( sLevelText.getLength() > 1 )
163 {
164 sal_Unicode cLevel = sLevelText.getStr()[1];
165 if( cLevel >= '1' && cLevel <= '9' )
166 {
167 if( cLevel - '1' < nMinLevel )
168 nMinLevel = cLevel - '1';
169 //remove first char - next char is removed later
170 sLevelText = sLevelText.copy( 1 );
171 }
172 }
173 //remove old '%' or number
174 sLevelText = sLevelText.copy( 1 );
175 nCurrentIndex = 0;
176 nFound = sLevelText.indexOf( '%', nCurrentIndex );
177 //remove the text before the next %
178 if(nFound > 0)
179 sLevelText = sLevelText.copy( nFound -1 );
180 }
181 if( nMinLevel < nLevel )
182 {
183 nParentNumbering = sal_Int16( nLevel - nMinLevel + 1);
184 }
185
186 rSuffix = sLevelText;
187
188 return nParentNumbering;
189 }
190
GetProperties()191 uno::Sequence< beans::PropertyValue > ListLevel::GetProperties( )
192 {
193 uno::Sequence< beans::PropertyValue > aLevelProps = GetLevelProperties( );
194 if ( m_pParaStyle.get( ) )
195 {
196 // Merge with the paragraph properties
197 uno::Sequence< beans::PropertyValue > aParaProps = GetParaProperties( );
198 lcl_mergeProperties( aParaProps, aLevelProps );
199 }
200 return aLevelProps;
201 }
202
GetCharStyleProperties()203 uno::Sequence< beans::PropertyValue > ListLevel::GetCharStyleProperties( )
204 {
205 PropertyValueVector_t rProperties;
206 PropertyNameSupplier& aPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
207
208 _PropertyMap::const_iterator aMapIter = begin();
209 _PropertyMap::const_iterator aEndIter = end();
210 for( ; aMapIter != aEndIter; ++aMapIter )
211 {
212 switch( aMapIter->first.eId )
213 {
214 case PROP_ADJUST:
215 case PROP_INDENT_AT:
216 case PROP_FIRST_LINE_INDENT:
217 case PROP_FIRST_LINE_OFFSET:
218 case PROP_LEFT_MARGIN:
219 case PROP_CHAR_FONT_NAME:
220 // Do nothing: handled in the GetPropertyValues method
221 break;
222 default:
223 {
224 rProperties.push_back(
225 beans::PropertyValue(
226 aPropNameSupplier.GetName( aMapIter->first.eId ), 0,
227 aMapIter->second, beans::PropertyState_DIRECT_VALUE ));
228 }
229 }
230 }
231
232 uno::Sequence< beans::PropertyValue > aRet( rProperties.size() );
233 beans::PropertyValue* pValues = aRet.getArray();
234 PropertyValueVector_t::const_iterator aIt = rProperties.begin();
235 PropertyValueVector_t::const_iterator aEndIt = rProperties.end();
236 for(sal_uInt32 nIndex = 0; aIt != aEndIt; ++aIt,++nIndex)
237 {
238 pValues[nIndex] = *aIt;
239 }
240 return aRet;
241 }
242
GetLevelProperties()243 uno::Sequence< beans::PropertyValue > ListLevel::GetLevelProperties( )
244 {
245 const sal_Int16 aWWToUnoAdjust[] =
246 {
247 text::HoriOrientation::LEFT,
248 text::HoriOrientation::CENTER,
249 text::HoriOrientation::RIGHT,
250 };
251
252 PropertyNameSupplier& aPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
253 PropertyValueVector_t aNumberingProperties;
254
255 if( m_nIStartAt >= 0)
256 aNumberingProperties.push_back( MAKE_PROPVAL(PROP_START_WITH, (sal_Int16)m_nIStartAt) );
257
258 sal_Int16 nNumberFormat = ConversionHelper::ConvertNumberingType(m_nNFC);
259 if( m_nNFC >= 0)
260 aNumberingProperties.push_back( MAKE_PROPVAL(PROP_NUMBERING_TYPE, nNumberFormat ));
261
262 if( m_nJC >= 0 && m_nJC <= sal::static_int_cast<sal_Int32>(sizeof(aWWToUnoAdjust) / sizeof(sal_Int16)) )
263 aNumberingProperties.push_back( MAKE_PROPVAL(PROP_ADJUST, aWWToUnoAdjust[m_nJC]));
264
265 // todo: this is not the bullet char
266 if( nNumberFormat == style::NumberingType::CHAR_SPECIAL && m_sBulletChar.getLength() )
267 aNumberingProperties.push_back( MAKE_PROPVAL(PROP_BULLET_CHAR, m_sBulletChar.copy(0,1)));
268
269 aNumberingProperties.push_back( MAKE_PROPVAL( PROP_LISTTAB_STOP_POSITION, m_nTabstop ) );
270
271 //TODO: handling of nFLegal?
272 //TODO: nFNoRestart lower levels do not restart when higher levels are incremented, like:
273 //1.
274 //1.1
275 //2.2
276 //2.3
277 //3.4
278 //
279
280 if( m_nFWord6 > 0) //Word 6 compatibility
281 {
282 if( m_nFPrev == 1)
283 aNumberingProperties.push_back( MAKE_PROPVAL( PROP_PARENT_NUMBERING, (sal_Int16) NUMBERING_MAX_LEVELS ));
284 //TODO: prefixing space nFPrevSpace; - has not been used in WW8 filter
285 }
286
287 // TODO: sRGBXchNums; array of inherited numbers
288
289 // TODO: nXChFollow; following character 0 - tab, 1 - space, 2 - nothing
290
291 _PropertyMap::const_iterator aMapIter = begin();
292 _PropertyMap::const_iterator aEndIter = end();
293 for( ; aMapIter != aEndIter; ++aMapIter )
294 {
295 switch( aMapIter->first.eId )
296 {
297 case PROP_ADJUST:
298 case PROP_INDENT_AT:
299 case PROP_FIRST_LINE_INDENT:
300 case PROP_FIRST_LINE_OFFSET:
301 case PROP_LEFT_MARGIN:
302 aNumberingProperties.push_back(
303 beans::PropertyValue( aPropNameSupplier.GetName( aMapIter->first.eId ), 0, aMapIter->second, beans::PropertyState_DIRECT_VALUE ));
304 break;
305 case PROP_CHAR_FONT_NAME:
306 aNumberingProperties.push_back(
307 beans::PropertyValue( aPropNameSupplier.GetName( PROP_BULLET_FONT_NAME ), 0, aMapIter->second, beans::PropertyState_DIRECT_VALUE ));
308 break;
309 default:
310 {
311 // Handled in GetCharStyleProperties method
312 }
313
314 }
315 }
316
317 uno::Sequence< beans::PropertyValue > aRet(aNumberingProperties.size());
318 beans::PropertyValue* pValues = aRet.getArray();
319 PropertyValueVector_t::const_iterator aIt = aNumberingProperties.begin();
320 PropertyValueVector_t::const_iterator aEndIt = aNumberingProperties.end();
321 for(sal_uInt32 nIndex = 0; aIt != aEndIt; ++aIt,++nIndex)
322 {
323 pValues[nIndex] = *aIt;
324 }
325 return aRet;
326 }
327
GetParaProperties()328 uno::Sequence< beans::PropertyValue > ListLevel::GetParaProperties( )
329 {
330 PropertyNameSupplier& aPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
331
332 uno::Sequence< beans::PropertyValue > aParaProps = m_pParaStyle->pProperties->GetPropertyValues( );
333 uno::Sequence< beans::PropertyValue > aProps;
334
335 // ParaFirstLineIndent -> FirstLineIndent
336 // ParaLeftMargin -> IndentAt
337
338 OUString sParaIndent = aPropNameSupplier.GetName(
339 PROP_PARA_FIRST_LINE_INDENT );
340 OUString sFirstLineIndent = aPropNameSupplier.GetName(
341 PROP_FIRST_LINE_INDENT );
342 OUString sParaLeftMargin = aPropNameSupplier.GetName(
343 PROP_PARA_LEFT_MARGIN );
344 OUString sIndentAt = aPropNameSupplier.GetName(
345 PROP_INDENT_AT );
346
347 sal_Int32 nLen = aParaProps.getLength( );
348 for ( sal_Int32 i = 0; i < nLen; i++ )
349 {
350 if ( aParaProps[i].Name.equals( sParaIndent ) )
351 {
352 aProps.realloc( aProps.getLength() + 1 );
353 aProps[aProps.getLength( ) - 1] = aParaProps[i];
354 aProps[aProps.getLength( ) - 1].Name = sFirstLineIndent;
355 }
356 else if ( aParaProps[i].Name.equals( sParaLeftMargin ) )
357 {
358 aProps.realloc( aProps.getLength() + 1 );
359 aProps[aProps.getLength( ) - 1] = aParaProps[i];
360 aProps[aProps.getLength( ) - 1].Name = sIndentAt;
361 }
362
363 }
364
365 return aProps;
366 }
367
368 //--------------------------------------- AbstractListDef implementation
369
AbstractListDef()370 AbstractListDef::AbstractListDef( ) :
371 m_nTPLC( -1 )
372 ,m_nSimpleList( -1 )
373 ,m_nRestart( -1 )
374 ,m_nUnsigned( -1 )
375 ,m_nId( -1 )
376 {
377 }
378
~AbstractListDef()379 AbstractListDef::~AbstractListDef( )
380 {
381 }
382
SetValue(sal_uInt32 nSprmId,sal_Int32 nValue)383 void AbstractListDef::SetValue( sal_uInt32 nSprmId, sal_Int32 nValue )
384 {
385 switch( nSprmId )
386 {
387 case NS_rtf::LN_TPLC:
388 m_nTPLC = nValue;
389 break;
390 case NS_rtf::LN_FSIMPLELIST:
391 m_nSimpleList = nValue;
392 break;
393 case NS_rtf::LN_fAutoNum:
394 m_nRestart = nValue;
395 break;
396 case NS_rtf::LN_fHybrid:
397 m_nUnsigned = nValue;
398 break;
399 default:
400 OSL_ENSURE( false, "this line should never be reached");
401 }
402 }
403
GetLevel(sal_uInt16 nLvl)404 ListLevel::Pointer AbstractListDef::GetLevel( sal_uInt16 nLvl )
405 {
406 ListLevel::Pointer pLevel;
407 if ( m_aLevels.size( ) > nLvl )
408 pLevel = m_aLevels[ nLvl ];
409 return pLevel;
410 }
411
AddLevel()412 void AbstractListDef::AddLevel( )
413 {
414 ListLevel::Pointer pLevel( new ListLevel );
415 m_pCurrentLevel = pLevel;
416 m_aLevels.push_back( pLevel );
417 }
418
GetPropertyValues()419 uno::Sequence< uno::Sequence< beans::PropertyValue > > AbstractListDef::GetPropertyValues( )
420 {
421 uno::Sequence< uno::Sequence< beans::PropertyValue > > result( sal_Int32( m_aLevels.size( ) ) );
422 uno::Sequence< beans::PropertyValue >* aResult = result.getArray( );
423
424 int nLevels = m_aLevels.size( );
425 for ( int i = 0; i < nLevels; i++ )
426 {
427 aResult[i] = m_aLevels[i]->GetProperties( );
428 }
429
430 return result;
431 }
432
433 //---------------------------------------------- ListDef implementation
434
ListDef()435 ListDef::ListDef( ) : AbstractListDef( )
436 {
437 }
438
~ListDef()439 ListDef::~ListDef( )
440 {
441 }
442
GetStyleName(sal_Int32 nId)443 OUString ListDef::GetStyleName( sal_Int32 nId )
444 {
445 OUString sStyleName( OUString::createFromAscii( "WWNum" ) );
446 sStyleName += OUString::valueOf( nId );
447
448 return sStyleName;
449 }
450
GetPropertyValues()451 uno::Sequence< uno::Sequence< beans::PropertyValue > > ListDef::GetPropertyValues( )
452 {
453 // [1] Call the same method on the abstract list
454 uno::Sequence< uno::Sequence< beans::PropertyValue > > aAbstract = m_pAbstractDef->GetPropertyValues( );
455
456 // [2] Call the upper class method
457 uno::Sequence< uno::Sequence< beans::PropertyValue > > aThis = AbstractListDef::GetPropertyValues( );
458
459 // Merge the results of [2] in [1]
460 sal_Int32 nThisCount = aThis.getLength( );
461 for ( sal_Int32 i = 0; i < nThisCount; i++ )
462 {
463 uno::Sequence< beans::PropertyValue > level = aThis[i];
464 if ( level.getLength( ) == 0 )
465 {
466 // If the element contains something, merge it
467 lcl_mergeProperties( level, aAbstract[i] );
468 }
469 }
470
471 return aAbstract;
472 }
473
lcl_getUnoNumberingStyles(uno::Reference<lang::XMultiServiceFactory> xFactory)474 uno::Reference< container::XNameContainer > lcl_getUnoNumberingStyles(
475 uno::Reference< lang::XMultiServiceFactory > xFactory )
476 {
477 uno::Reference< container::XNameContainer > xStyles;
478
479 try
480 {
481 uno::Reference< style::XStyleFamiliesSupplier > xFamilies( xFactory, uno::UNO_QUERY_THROW );
482 uno::Any oFamily = xFamilies->getStyleFamilies( )->getByName( OUString::createFromAscii( "NumberingStyles" ) );
483
484 oFamily >>= xStyles;
485 }
486 catch ( const uno::Exception e)
487 {
488 (void) e;
489 }
490
491 return xStyles;
492 }
493
CreateNumberingRules(DomainMapper & rDMapper,uno::Reference<lang::XMultiServiceFactory> xFactory)494 void ListDef::CreateNumberingRules( DomainMapper& rDMapper,
495 uno::Reference< lang::XMultiServiceFactory> xFactory )
496 {
497 // Get the UNO Numbering styles
498 uno::Reference< container::XNameContainer > xStyles = lcl_getUnoNumberingStyles( xFactory );
499
500 // Do the whole thing
501 if( !m_xNumRules.is() && xFactory.is() && xStyles.is( ) )
502 {
503 try
504 {
505 // Create the numbering style
506 uno::Reference< beans::XPropertySet > xStyle (
507 xFactory->createInstance(
508 OUString::createFromAscii("com.sun.star.style.NumberingStyle")),
509 uno::UNO_QUERY_THROW );
510
511 rtl::OUString sStyleName = GetStyleName( GetId( ) );
512
513 xStyles->insertByName( sStyleName, makeAny( xStyle ) );
514
515 uno::Any oStyle = xStyles->getByName( sStyleName );
516 xStyle.set( oStyle, uno::UNO_QUERY_THROW );
517
518 PropertyNameSupplier& aPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
519
520 // Get the default OOo Numbering style rules
521 uno::Any aRules = xStyle->getPropertyValue( aPropNameSupplier.GetName( PROP_NUMBERING_RULES ) );
522 aRules >>= m_xNumRules;
523
524 uno::Sequence< uno::Sequence< beans::PropertyValue > > aProps = GetPropertyValues( );
525
526 sal_Int32 nAbstLevels = m_pAbstractDef->Size( );
527 sal_Int16 nLevel = 0;
528 while ( nLevel < nAbstLevels )
529 {
530 ListLevel::Pointer pAbsLevel = m_pAbstractDef->GetLevel( nLevel );
531 ListLevel::Pointer pLevel = GetLevel( nLevel );
532
533 // Get the merged level properties
534 uno::Sequence< beans::PropertyValue > aLvlProps = aProps[sal_Int32( nLevel )];
535
536 // Get the char style
537 uno::Sequence< beans::PropertyValue > aAbsCharStyleProps = pAbsLevel->GetCharStyleProperties( );
538 uno::Sequence< beans::PropertyValue >& rAbsCharStyleProps = aAbsCharStyleProps;
539 if ( pLevel.get( ) )
540 {
541 uno::Sequence< beans::PropertyValue > aCharStyleProps =
542 pLevel->GetCharStyleProperties( );
543 uno::Sequence< beans::PropertyValue >& rCharStyleProps = aCharStyleProps;
544 lcl_mergeProperties( rAbsCharStyleProps, rCharStyleProps );
545 }
546
547 if( aAbsCharStyleProps.getLength() )
548 {
549 // Change the sequence into a vector
550 PropertyValueVector_t aStyleProps;
551 for ( sal_Int32 i = 0, nLen = aAbsCharStyleProps.getLength() ; i < nLen; i++ )
552 {
553 aStyleProps.push_back( aAbsCharStyleProps[i] );
554 }
555
556 //create (or find) a character style containing the character
557 // attributes of the symbol and apply it to the numbering level
558 OUString sStyle = rDMapper.getOrCreateCharStyle( aStyleProps );
559 aLvlProps.realloc( aLvlProps.getLength() + 1);
560 aLvlProps[aLvlProps.getLength() - 1].Name = aPropNameSupplier.GetName( PROP_CHAR_STYLE_NAME );
561 aLvlProps[aLvlProps.getLength() - 1].Value <<= sStyle;
562 }
563
564 // Get the prefix / suffix / Parent numbering
565 // and add them to the level properties
566 OUString sText = pAbsLevel->GetBulletChar( );
567 if ( pLevel.get( ) )
568 sText = pLevel->GetBulletChar( );
569
570 OUString sPrefix;
571 OUString sSuffix;
572 OUString& rPrefix = sPrefix;
573 OUString& rSuffix = sSuffix;
574 sal_Int16 nParentNum = ListLevel::GetParentNumbering(
575 sText, nLevel, rPrefix, rSuffix );
576
577 aLvlProps.realloc( aLvlProps.getLength( ) + 4 );
578 aLvlProps[ aLvlProps.getLength( ) - 4 ] = MAKE_PROPVAL( PROP_PREFIX, rPrefix );
579 aLvlProps[ aLvlProps.getLength( ) - 3 ] = MAKE_PROPVAL( PROP_SUFFIX, rSuffix );
580 aLvlProps[ aLvlProps.getLength( ) - 2 ] = MAKE_PROPVAL( PROP_PARENT_NUMBERING, nParentNum );
581
582 aLvlProps[ aLvlProps.getLength( ) - 1 ] = MAKE_PROPVAL( PROP_POSITION_AND_SPACE_MODE,
583 sal_Int16( text::PositionAndSpaceMode::LABEL_ALIGNMENT ) );
584 // Replace the numbering rules for the level
585 m_xNumRules->replaceByIndex( nLevel, uno::makeAny( aLvlProps ) );
586
587 // Handle the outline level here
588 StyleSheetEntryPtr pParaStyle = pAbsLevel->GetParaStyle( );
589 if ( pParaStyle.get( ) )
590 {
591 uno::Reference< text::XChapterNumberingSupplier > xOutlines (
592 xFactory, uno::UNO_QUERY_THROW );
593 uno::Reference< container::XIndexReplace > xOutlineRules =
594 xOutlines->getChapterNumberingRules( );
595
596 aLvlProps.realloc( aLvlProps.getLength() + 1 );
597 aLvlProps[aLvlProps.getLength( ) - 1] = MAKE_PROPVAL( PROP_HEADING_STYLE_NAME, pParaStyle->sConvertedStyleName );
598
599 xOutlineRules->replaceByIndex( nLevel, uno::makeAny( aLvlProps ) );
600 }
601
602 nLevel++;
603 }
604
605 // Create the numbering style for these rules
606 OUString sNumRulesName = aPropNameSupplier.GetName( PROP_NUMBERING_RULES );
607 xStyle->setPropertyValue( sNumRulesName, uno::makeAny( m_xNumRules ) );
608 }
609 catch( const uno::Exception& rEx)
610 {
611 OSL_ENSURE( false, "ListTable::CreateNumberingRules");
612 }
613 }
614
615 }
616
617 //------------------------------------- NumberingManager implementation
618
619
ListsManager(DomainMapper & rDMapper,const uno::Reference<lang::XMultiServiceFactory> xFactory)620 ListsManager::ListsManager(DomainMapper& rDMapper,
621 const uno::Reference< lang::XMultiServiceFactory > xFactory) :
622 LoggedProperties(dmapper_logger, "ListsManager"),
623 LoggedTable(dmapper_logger, "ListsManager"),
624 m_rDMapper( rDMapper ),
625 m_xFactory( xFactory )
626 {
627 }
628
~ListsManager()629 ListsManager::~ListsManager( )
630 {
631 }
632
lcl_attribute(Id nName,Value & rVal)633 void ListsManager::lcl_attribute( Id nName, Value& rVal )
634 {
635 OSL_ENSURE( m_pCurrentDefinition.get(), "current entry has to be set here");
636 if(!m_pCurrentDefinition.get())
637 return ;
638 int nIntValue = rVal.getInt();
639
640 ListLevel::Pointer pCurrentLvl = m_pCurrentDefinition->GetCurrentLevel( );
641
642
643 /* WRITERFILTERSTATUS: table: ListTable_attributedata */
644 switch(nName)
645 {
646 /* WRITERFILTERSTATUS: done: 50, planned: 0, spent: 0 */
647 case NS_rtf::LN_RGBXCHNUMS:
648 if(pCurrentLvl.get())
649 pCurrentLvl->AddRGBXchNums( rVal.getString( ) );
650 break;
651 /* WRITERFILTERSTATUS: done: 0, planned: 0, spent: 0 */
652 case NS_ooxml::LN_CT_LevelText_val:
653 {
654 //this strings contains the definition of the level
655 //the level number is marked as %n
656 //these numbers can be mixed randomly together with seperators pre- and suffixes
657 //the Writer supports only a number of upper levels to show, separators is always a dot
658 //and each level can have a prefix and a suffix
659 if(pCurrentLvl.get())
660 pCurrentLvl->SetBulletChar( rVal.getString() );
661 }
662 break;
663 // case NS_rtf::LN_ISTD: break;
664 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
665 case NS_rtf::LN_ISTARTAT:
666 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
667 case NS_rtf::LN_NFC:
668 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
669 case NS_rtf::LN_JC:
670 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
671 case NS_rtf::LN_FLEGAL:
672 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
673 case NS_rtf::LN_FNORESTART:
674 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
675 case NS_rtf::LN_FIDENTSAV:
676 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
677 case NS_rtf::LN_FCONVERTED:
678 #if 0
679 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
680 case NS_rtf::LN_FWORD6:
681 #endif
682 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
683 case NS_rtf::LN_IXCHFOLLOW:
684 if ( pCurrentLvl.get( ) )
685 pCurrentLvl->SetValue( nName, sal_Int32( nIntValue ) );
686 break;
687 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
688 case NS_rtf::LN_RGISTD:
689 m_pCurrentDefinition->AddRGISTD( rVal.getString() );
690 break;
691 case NS_ooxml::LN_CT_Num_numId:
692 m_pCurrentDefinition->SetId( rVal.getString().toInt32( ) );
693 break;
694 case NS_rtf::LN_LSID:
695 m_pCurrentDefinition->SetId( nIntValue );
696 break;
697 case NS_rtf::LN_TPLC:
698 case NS_rtf::LN_FSIMPLELIST:
699 case NS_rtf::LN_fAutoNum:
700 case NS_rtf::LN_fHybrid:
701 m_pCurrentDefinition->SetValue( nName, nIntValue );
702 break;
703 case NS_ooxml::LN_CT_NumLvl_ilvl:
704 case NS_rtf::LN_LISTLEVEL:
705 {
706 //add a new level to the level vector and make it the current one
707 m_pCurrentDefinition->AddLevel();
708
709 writerfilter::Reference<Properties>::Pointer_t pProperties;
710 if((pProperties = rVal.getProperties()).get())
711 pProperties->resolve(*this);
712 }
713 break;
714 /* WRITERFILTERSTATUS: done: 100, planned: 0, spent: 0 */
715 case NS_ooxml::LN_CT_AbstractNum_abstractNumId:
716 {
717 // This one corresponds to the AbstractNum Id definition
718 // The reference to the abstract num is in the sprm method
719 sal_Int32 nVal = rVal.getString().toInt32();
720 m_pCurrentDefinition->SetId( nVal );
721 }
722 break;
723 case NS_ooxml::LN_CT_Ind_left:
724 /* WRITERFILTERSTATUS: done: 100, planned: 0.5, spent: 0 */
725 pCurrentLvl->Insert(
726 PROP_INDENT_AT, true, uno::makeAny( ConversionHelper::convertTwipToMM100( nIntValue ) ));
727 break;
728 case NS_ooxml::LN_CT_Ind_hanging:
729 /* WRITERFILTERSTATUS: done: 100, planned: 0.5, spent: 0 */
730 pCurrentLvl->Insert(
731 PROP_FIRST_LINE_INDENT, true, uno::makeAny( - ConversionHelper::convertTwipToMM100( nIntValue ) ));
732 break;
733 case NS_ooxml::LN_CT_Ind_firstLine:
734 /* WRITERFILTERSTATUS: done: 100, planned: 0.5, spent: 0 */
735 pCurrentLvl->Insert(
736 PROP_FIRST_LINE_INDENT, true, uno::makeAny( ConversionHelper::convertTwipToMM100( nIntValue ) ));
737 break;
738 case NS_ooxml::LN_CT_Lvl_ilvl: //overrides previous level - unsupported
739 case NS_ooxml::LN_CT_Lvl_tplc: //template code - unsupported
740 case NS_ooxml::LN_CT_Lvl_tentative: //marks level as unused in the document - unsupported
741 break;
742 case NS_ooxml::LN_CT_TabStop_pos:
743 {
744 //no paragraph attributes in ListTable char style sheets
745 if ( pCurrentLvl.get( ) )
746 pCurrentLvl->SetValue( nName,
747 ConversionHelper::convertTwipToMM100( nIntValue ) );
748 }
749 break;
750 case NS_ooxml::LN_CT_TabStop_val:
751 {
752 // TODO Do something of that
753 }
754 break;
755 default:
756 {
757 #if OSL_DEBUG_LEVEL > 0
758 ::rtl::OString sMessage( "ListTable::attribute() - Id: ");
759 sMessage += ::rtl::OString::valueOf( sal_Int32( nName ), 10 );
760 sMessage += ::rtl::OString(" / 0x");
761 sMessage += ::rtl::OString::valueOf( sal_Int32( nName ), 16 );
762 sMessage += ::rtl::OString(" value: ");
763 sMessage += ::rtl::OString::valueOf( sal_Int32( nIntValue ), 10 );
764 sMessage += ::rtl::OString(" / 0x");
765 sMessage += ::rtl::OString::valueOf( sal_Int32( nIntValue ), 16 );
766 OSL_ENSURE( false, sMessage.getStr()); //
767 #endif
768 }
769 }
770 }
771
lcl_sprm(Sprm & rSprm)772 void ListsManager::lcl_sprm( Sprm& rSprm )
773 {
774 //fill the attributes of the style sheet
775 sal_uInt32 nSprmId = rSprm.getId();
776 if( m_pCurrentDefinition.get() ||
777 nSprmId == NS_ooxml::LN_CT_Numbering_abstractNum ||
778 nSprmId == NS_ooxml::LN_CT_Numbering_num )
779 {
780 sal_Int32 nIntValue = rSprm.getValue()->getInt();
781 /* WRITERFILTERSTATUS: table: ListTable_sprm */
782 switch( nSprmId )
783 {
784 /* WRITERFILTERSTATUS: done: 100, planned: 0, spent: 0 */
785 case NS_ooxml::LN_CT_Numbering_abstractNum:
786 {
787 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
788 if(pProperties.get())
789 {
790 //create a new Abstract list entry
791 OSL_ENSURE( !m_pCurrentDefinition.get(), "current entry has to be NULL here");
792 m_pCurrentDefinition.reset( new AbstractListDef );
793 pProperties->resolve( *this );
794 //append it to the table
795 m_aAbstractLists.push_back( m_pCurrentDefinition );
796 m_pCurrentDefinition = AbstractListDef::Pointer();
797 }
798 }
799 break;
800 /* WRITERFILTERSTATUS: done: 50, planned: 0, spent: 0 */
801 case NS_ooxml::LN_CT_Numbering_num:
802 {
803 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
804 if(pProperties.get())
805 {
806 // Create a new list entry
807 OSL_ENSURE( !m_pCurrentDefinition.get(), "current entry has to be NULL here");
808 ListDef::Pointer listDef( new ListDef );
809 m_pCurrentDefinition = listDef;
810 pProperties->resolve( *this );
811 //append it to the table
812 m_aLists.push_back( listDef );
813
814 m_pCurrentDefinition = AbstractListDef::Pointer();
815 }
816 }
817 break;
818 case NS_ooxml::LN_CT_Num_abstractNumId:
819 {
820 sal_Int32 nAbstractNumId = rSprm.getValue()->getInt();
821 ListDef* pListDef = dynamic_cast< ListDef* >( m_pCurrentDefinition.get( ) );
822 if ( pListDef != NULL )
823 {
824 // The current def should be a ListDef
825 pListDef->SetAbstractDefinition(
826 GetAbstractList( nAbstractNumId ) );
827 }
828 }
829 break;
830 /* WRITERFILTERSTATUS: done: 0, planned: 0, spent: 0 */
831 case NS_ooxml::LN_CT_AbstractNum_multiLevelType:
832 break;
833 /* WRITERFILTERSTATUS: done: 50, planned: 0, spent: 0 */
834 case NS_rtf::LN_TPLC:
835 m_pCurrentDefinition->SetValue( nSprmId, nIntValue );
836 break;
837 /* WRITERFILTERSTATUS: done: 100, planned: 0, spent: 0 */
838 case NS_ooxml::LN_CT_AbstractNum_lvl:
839 {
840 m_pCurrentDefinition->AddLevel();
841 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
842 if(pProperties.get())
843 pProperties->resolve(*this);
844 }
845 break;
846 /* WRITERFILTERSTATUS: done: 0, planned: 0, spent: 0 */
847 case NS_rtf::LN_RGBXCHNUMS: break;
848 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
849 case NS_rtf::LN_ISTARTAT:
850 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
851 case NS_rtf::LN_NFC:
852 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
853 case NS_rtf::LN_JC:
854 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
855 case NS_rtf::LN_FLEGAL:
856 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
857 case NS_rtf::LN_FNORESTART:
858 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
859 case NS_rtf::LN_FIDENTSAV:
860 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
861 case NS_rtf::LN_FCONVERTED:
862 #if 0
863 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
864 case NS_rtf::LN_FWORD6:
865 #endif
866 /* WRITERFILTERSTATUS: done: 75, planned: 0, spent: 0 */
867 case NS_rtf::LN_IXCHFOLLOW:
868 m_pCurrentDefinition->GetCurrentLevel( )->SetValue( nSprmId, nIntValue );
869 break;
870 case NS_ooxml::LN_CT_Lvl_lvlText:
871 case NS_ooxml::LN_CT_Lvl_rPr : //contains LN_EG_RPrBase_rFonts
872 {
873 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
874 if(pProperties.get())
875 pProperties->resolve(*this);
876 }
877 break;
878 case NS_ooxml::LN_CT_NumLvl_lvl:
879 {
880 // overwrite level
881 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
882 if(pProperties.get())
883 pProperties->resolve(*this);
884 }
885 break;
886 case NS_ooxml::LN_CT_Lvl_lvlJc:
887 {
888 static sal_Int16 aWWAlignments[ ] =
889 {
890 text::HoriOrientation::LEFT,
891 text::HoriOrientation::CENTER,
892 text::HoriOrientation::RIGHT
893 };
894 m_pCurrentDefinition->GetCurrentLevel( )->Insert(
895 PROP_ADJUST, true, uno::makeAny( aWWAlignments[ nIntValue ] ) );
896 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
897 }
898 break;
899 case NS_ooxml::LN_CT_Lvl_pPr:
900 case NS_ooxml::LN_CT_PPrBase_ind:
901 {
902 //todo: how to handle paragraph properties within numbering levels (except LeftIndent and FirstLineIndent)?
903 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
904 if(pProperties.get())
905 pProperties->resolve(*this);
906 }
907 break;
908 case NS_ooxml::LN_CT_PPrBase_tabs:
909 case NS_ooxml::LN_CT_Tabs_tab:
910 {
911 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
912 if(pProperties.get())
913 pProperties->resolve(*this);
914 }
915 break;
916 case NS_ooxml::LN_CT_Lvl_suff:
917 //todo: currently unsupported suffix
918 //can be: "none", "space", "tab"
919 break;
920 case NS_ooxml::LN_CT_Lvl_pStyle:
921 {
922 OUString sStyleName = rSprm.getValue( )->getString( );
923 ListLevel::Pointer pLevel = m_pCurrentDefinition->GetCurrentLevel( );
924 StyleSheetTablePtr pStylesTable = m_rDMapper.GetStyleSheetTable( );
925 const StyleSheetEntryPtr pStyle = pStylesTable->FindStyleSheetByISTD( sStyleName );
926 pLevel->SetParaStyle( pStyle );
927 }
928 break;
929 case NS_ooxml::LN_CT_AbstractNum_numStyleLink:
930 {
931 OUString sStyleName = rSprm.getValue( )->getString( );
932 AbstractListDef* pAbstractListDef = dynamic_cast< AbstractListDef* >( m_pCurrentDefinition.get( ) );
933 pAbstractListDef->SetNumStyleLink(sStyleName);
934 }
935 break;
936 case NS_ooxml::LN_EG_RPrBase_rFonts: //contains font properties
937 case NS_ooxml::LN_EG_RPrBase_color:
938 case NS_ooxml::LN_EG_RPrBase_u:
939 case NS_sprm::LN_CHps: // sprmCHps
940 case NS_ooxml::LN_EG_RPrBase_lang:
941 case NS_ooxml::LN_EG_RPrBase_eastAsianLayout:
942 //no break!
943 default:
944 if( m_pCurrentDefinition->GetCurrentLevel( ).get())
945 {
946 m_rDMapper.PushListProperties( m_pCurrentDefinition->GetCurrentLevel( ) );
947 m_rDMapper.sprm( rSprm );
948 m_rDMapper.PopListProperties();
949 }
950 }
951 }
952 }
953
lcl_entry(int,writerfilter::Reference<Properties>::Pointer_t ref)954 void ListsManager::lcl_entry( int /* pos */,
955 writerfilter::Reference<Properties>::Pointer_t ref )
956 {
957 if( m_rDMapper.IsOOXMLImport() )
958 {
959 ref->resolve(*this);
960 }
961 else
962 {
963 if ( m_bIsLFOImport )
964 {
965 // Create ListDef's
966 OSL_ENSURE( !m_pCurrentDefinition.get(), "current entry has to be NULL here");
967 ListDef::Pointer pList( new ListDef() );
968 m_pCurrentDefinition = pList;
969 ref->resolve(*this);
970 //append it to the table
971 m_aLists.push_back( pList );
972 m_pCurrentDefinition = AbstractListDef::Pointer();
973 }
974 else
975 {
976 // Create AbstractListDef's
977 OSL_ENSURE( !m_pCurrentDefinition.get(), "current entry has to be NULL here");
978 m_pCurrentDefinition.reset( new AbstractListDef( ) );
979 ref->resolve(*this);
980 //append it to the table
981 m_aAbstractLists.push_back( m_pCurrentDefinition );
982 m_pCurrentDefinition = AbstractListDef::Pointer();
983 }
984 }
985 }
986
GetAbstractList(sal_Int32 nId)987 AbstractListDef::Pointer ListsManager::GetAbstractList( sal_Int32 nId )
988 {
989 AbstractListDef::Pointer pAbstractList;
990
991 int nLen = m_aAbstractLists.size( );
992 int i = 0;
993 while ( !pAbstractList.get( ) && i < nLen )
994 {
995 if ( m_aAbstractLists[i]->GetId( ) == nId )
996 {
997 if ( m_aAbstractLists[i]->GetNumStyleLink().getLength() > 0 )
998 {
999 // If the abstract num has a style linked, check the linked style's number id.
1000 StyleSheetTablePtr pStylesTable = m_rDMapper.GetStyleSheetTable( );
1001
1002 const StyleSheetEntryPtr pStyleSheetEntry =
1003 pStylesTable->FindStyleSheetByISTD( m_aAbstractLists[i]->GetNumStyleLink() );
1004
1005 const StyleSheetPropertyMap* pStyleSheetProperties =
1006 dynamic_cast<const StyleSheetPropertyMap*>(pStyleSheetEntry ? pStyleSheetEntry->pProperties.get() : 0);
1007
1008 if( pStyleSheetProperties && pStyleSheetProperties->GetNumId() >= 0 )
1009 {
1010 ListDef::Pointer pList = GetList( pStyleSheetProperties->GetNumId() );
1011 if( bool(pList) )
1012 return pList->GetAbstractDefinition();
1013 else
1014 pAbstractList = m_aAbstractLists[i];
1015 }
1016
1017 }
1018 else
1019 {
1020 pAbstractList = m_aAbstractLists[i];
1021 }
1022 }
1023 i++;
1024 }
1025
1026 return pAbstractList;
1027 }
1028
GetList(sal_Int32 nId)1029 ListDef::Pointer ListsManager::GetList( sal_Int32 nId )
1030 {
1031 ListDef::Pointer pList;
1032
1033 int nLen = m_aLists.size( );
1034 int i = 0;
1035 while ( !pList.get( ) && i < nLen )
1036 {
1037 if ( m_aLists[i]->GetId( ) == nId )
1038 pList = m_aLists[i];
1039 i++;
1040 }
1041
1042 return pList;
1043 }
1044
CreateNumberingRules()1045 void ListsManager::CreateNumberingRules( )
1046 {
1047 // Loop over the definitions
1048 std::vector< ListDef::Pointer >::iterator listIt = m_aLists.begin( );
1049 for ( ; listIt != m_aLists.end( ); listIt++ )
1050 {
1051 (*listIt)->CreateNumberingRules( m_rDMapper, m_xFactory );
1052 }
1053 }
1054
1055 } }
1056