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