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