1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #include "ConversionHelper.hxx"
20 #include "NumberingManager.hxx"
21 #include "StyleSheetTable.hxx"
22 #include "PropertyIds.hxx"
24 #include <doctok/resourceids.hxx>
25 #include <doctok/sprmids.hxx>
26 #include <ooxml/resourceids.hxx>
28 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
29 #include <com/sun/star/container/XNameContainer.hpp>
30 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
31 #include <com/sun/star/style/NumberingType.hpp>
32 #include <com/sun/star/text/HoriOrientation.hpp>
33 #include <com/sun/star/text/PositionAndSpaceMode.hpp>
34 #include <com/sun/star/text/XChapterNumberingSupplier.hpp>
36 #include <rtl/ustring.hxx>
38 #include "dmapperLoggers.hxx"
40 using namespace com::sun::star
;
42 #define MAKE_PROPVAL(NameId, Value) \
43 beans::PropertyValue(aPropNameSupplier.GetName(NameId), 0, uno::makeAny(Value), beans::PropertyState_DIRECT_VALUE )
45 #define NUMBERING_MAX_LEVELS 10
48 namespace writerfilter
{
51 //--------------------------------------------------- Utility functions
53 void lcl_printProperties( uno::Sequence
< beans::PropertyValue
> aProps
)
55 sal_Int32 nLen
= aProps
.getLength( );
56 for ( sal_Int32 i
= 0; i
< nLen
; i
++ )
58 uno::Any aValue
= aProps
[i
].Value
;
62 if ( !( aValue
>>= sValue
) && ( aValue
>>= nValue
) )
63 sValue
= OUString::valueOf( nValue
);
65 SAL_INFO("writerfilter", "Property " << aProps
[i
].Name
<< ": " << sValue
);
69 sal_Int32
lcl_findProperty( uno::Sequence
< beans::PropertyValue
> aProps
, OUString sName
)
72 sal_Int32 nLen
= aProps
.getLength( );
75 while ( nPos
== -1 && i
< nLen
)
77 if ( aProps
[i
].Name
.equals( sName
) )
86 void lcl_mergeProperties( uno::Sequence
< beans::PropertyValue
>& aSrc
,
87 uno::Sequence
< beans::PropertyValue
>& aDst
)
89 for ( sal_Int32 i
= 0, nSrcLen
= aSrc
.getLength( ); i
< nSrcLen
; i
++ )
91 // Look for the same property in aDst
92 sal_Int32 nPos
= lcl_findProperty( aDst
, aSrc
[i
].Name
);
95 // Replace the property value by the one in aSrc
100 // Simply add the new value
101 aDst
.realloc( aDst
.getLength( ) + 1 );
102 aDst
[ aDst
.getLength( ) - 1 ] = aSrc
[i
];
107 //-------------------------------------------- ListLevel implementation
108 void ListLevel::SetValue( Id nId
, sal_Int32 nValue
)
112 case NS_rtf::LN_ISTARTAT
:
113 m_nIStartAt
= nValue
;
121 case NS_rtf::LN_FLEGAL
:
124 case NS_rtf::LN_FNORESTART
:
125 m_nFNoRestart
= nValue
;
127 case NS_rtf::LN_FIDENTSAV
:
130 case NS_rtf::LN_FCONVERTED
:
131 m_nFPrevSpace
= nValue
;
133 case NS_rtf::LN_IXCHFOLLOW
:
134 case NS_ooxml::LN_CT_Lvl_suff
:
135 m_nXChFollow
= nValue
;
137 case NS_ooxml::LN_CT_TabStop_pos
:
140 SAL_INFO("writerfilter",
141 "unsupported list tab stop position " << nValue
);
147 OSL_FAIL( "this line should never be reached");
151 void ListLevel::SetParaStyle( boost::shared_ptr
< StyleSheetEntry
> pStyle
)
155 m_pParaStyle
= pStyle
;
156 // AFAICT .docx spec does not identify which numberings or paragraph
157 // styles are actually the ones to be used for outlines (chapter numbering),
158 // it only kind of says somewhere that they should be named Heading1 to Heading9.
159 const OUString styleId
= pStyle
->sStyleIdentifierD
;
160 m_outline
= ( styleId
.getLength() == RTL_CONSTASCII_LENGTH( "Heading1" )
161 && styleId
.match( "Heading", 0 )
162 && styleId
[ RTL_CONSTASCII_LENGTH( "Heading" ) ] >= '1'
163 && styleId
[ RTL_CONSTASCII_LENGTH( "Heading" ) ] <= '9' );
166 sal_Int16
ListLevel::GetParentNumbering( OUString sText
, sal_Int16 nLevel
,
167 OUString
& rPrefix
, OUString
& rSuffix
)
169 sal_Int16 nParentNumbering
= 1;
171 //now parse the text to find %n from %1 to %nLevel+1
172 //everything before the first % and the last %x is prefix and suffix
173 OUString
sLevelText( sText
);
174 sal_Int32 nCurrentIndex
= 0;
175 sal_Int32 nFound
= sLevelText
.indexOf( '%', nCurrentIndex
);
178 rPrefix
= sLevelText
.copy( 0, nFound
);
179 sLevelText
= sLevelText
.copy( nFound
);
181 sal_Int32 nMinLevel
= nLevel
;
182 //now the text should either be empty or start with %
183 nFound
= sLevelText
.getLength( ) > 1 ? 0 : -1;
186 if( sLevelText
.getLength() > 1 )
188 sal_Unicode cLevel
= sLevelText
.getStr()[1];
189 if( cLevel
>= '1' && cLevel
<= '9' )
191 if( cLevel
- '1' < nMinLevel
)
192 nMinLevel
= cLevel
- '1';
193 //remove first char - next char is removed later
194 sLevelText
= sLevelText
.copy( 1 );
197 //remove old '%' or number
198 sLevelText
= sLevelText
.copy( 1 );
200 nFound
= sLevelText
.indexOf( '%', nCurrentIndex
);
201 //remove the text before the next %
203 sLevelText
= sLevelText
.copy( nFound
-1 );
205 if( nMinLevel
< nLevel
)
207 nParentNumbering
= sal_Int16( nLevel
- nMinLevel
+ 1);
210 rSuffix
= sLevelText
;
212 return nParentNumbering
;
215 uno::Sequence
< beans::PropertyValue
> ListLevel::GetProperties( )
217 uno::Sequence
< beans::PropertyValue
> aLevelProps
= GetLevelProperties( );
218 if ( m_pParaStyle
.get( ) )
219 AddParaProperties( &aLevelProps
);
223 uno::Sequence
< beans::PropertyValue
> ListLevel::GetCharStyleProperties( )
225 PropertyValueVector_t rProperties
;
226 PropertyNameSupplier
& aPropNameSupplier
= PropertyNameSupplier::GetPropertyNameSupplier();
228 _PropertyMap::const_iterator aMapIter
= begin();
229 _PropertyMap::const_iterator aEndIter
= end();
230 for( ; aMapIter
!= aEndIter
; ++aMapIter
)
232 switch( aMapIter
->first
.eId
)
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
244 rProperties
.push_back(
245 beans::PropertyValue(
246 aPropNameSupplier
.GetName( aMapIter
->first
.eId
), 0,
247 aMapIter
->second
, beans::PropertyState_DIRECT_VALUE
));
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
)
258 pValues
[nIndex
] = *aIt
;
263 uno::Sequence
< beans::PropertyValue
> ListLevel::GetLevelProperties( )
265 const sal_Int16 aWWToUnoAdjust
[] =
267 text::HoriOrientation::LEFT
,
268 text::HoriOrientation::CENTER
,
269 text::HoriOrientation::RIGHT
,
272 PropertyNameSupplier
& aPropNameSupplier
= PropertyNameSupplier::GetPropertyNameSupplier();
273 PropertyValueVector_t aNumberingProperties
;
275 if( m_nIStartAt
>= 0)
276 aNumberingProperties
.push_back( MAKE_PROPVAL(PROP_START_WITH
, (sal_Int16
)m_nIStartAt
) );
278 sal_Int16 nNumberFormat
= ConversionHelper::ConvertNumberingType(m_nNFC
);
281 if (!m_sGraphicURL
.isEmpty() || m_sGraphicBitmap
.is())
282 nNumberFormat
= style::NumberingType::BITMAP
;
283 aNumberingProperties
.push_back( MAKE_PROPVAL(PROP_NUMBERING_TYPE
, nNumberFormat
));
286 if( m_nJC
>= 0 && m_nJC
<= sal::static_int_cast
<sal_Int32
>(sizeof(aWWToUnoAdjust
) / sizeof(sal_Int16
)) )
287 aNumberingProperties
.push_back( MAKE_PROPVAL(PROP_ADJUST
, aWWToUnoAdjust
[m_nJC
]));
289 if( !isOutlineNumbering())
291 // todo: this is not the bullet char
292 if( nNumberFormat
== style::NumberingType::CHAR_SPECIAL
&& !m_sBulletChar
.isEmpty() )
293 aNumberingProperties
.push_back( MAKE_PROPVAL(PROP_BULLET_CHAR
, m_sBulletChar
.copy(0,1)));
294 if (!m_sGraphicURL
.isEmpty())
295 aNumberingProperties
.push_back(MAKE_PROPVAL(PROP_GRAPHIC_URL
, m_sGraphicURL
));
296 if (m_sGraphicBitmap
.is())
297 aNumberingProperties
.push_back(MAKE_PROPVAL(PROP_GRAPHIC_BITMAP
, m_sGraphicBitmap
));
300 aNumberingProperties
.push_back( MAKE_PROPVAL( PROP_LISTTAB_STOP_POSITION
, m_nTabstop
) );
302 //TODO: handling of nFLegal?
303 //TODO: nFNoRestart lower levels do not restart when higher levels are incremented, like:
311 if( m_nFWord6
> 0) //Word 6 compatibility
314 aNumberingProperties
.push_back( MAKE_PROPVAL( PROP_PARENT_NUMBERING
, (sal_Int16
) NUMBERING_MAX_LEVELS
));
315 //TODO: prefixing space nFPrevSpace; - has not been used in WW8 filter
318 // TODO: sRGBXchNums; array of inherited numbers
320 // nXChFollow; following character 0 - tab, 1 - space, 2 - nothing
321 aNumberingProperties
.push_back( MAKE_PROPVAL( PROP_LEVEL_FOLLOW
, m_nXChFollow
));
324 _PropertyMap::const_iterator aMapIter
= begin();
325 _PropertyMap::const_iterator aEndIter
= end();
326 for( ; aMapIter
!= aEndIter
; ++aMapIter
)
328 switch( aMapIter
->first
.eId
)
332 case PROP_FIRST_LINE_INDENT
:
333 case PROP_FIRST_LINE_OFFSET
:
334 case PROP_LEFT_MARGIN
:
335 aNumberingProperties
.push_back(
336 beans::PropertyValue( aPropNameSupplier
.GetName( aMapIter
->first
.eId
), 0, aMapIter
->second
, beans::PropertyState_DIRECT_VALUE
));
338 case PROP_CHAR_FONT_NAME
:
339 if( !isOutlineNumbering())
341 aNumberingProperties
.push_back(
342 beans::PropertyValue( aPropNameSupplier
.GetName( PROP_BULLET_FONT_NAME
), 0, aMapIter
->second
, beans::PropertyState_DIRECT_VALUE
));
347 // Handled in GetCharStyleProperties method
353 uno::Sequence
< beans::PropertyValue
> aRet(aNumberingProperties
.size());
354 beans::PropertyValue
* pValues
= aRet
.getArray();
355 PropertyValueVector_t::const_iterator aIt
= aNumberingProperties
.begin();
356 PropertyValueVector_t::const_iterator aEndIt
= aNumberingProperties
.end();
357 for(sal_uInt32 nIndex
= 0; aIt
!= aEndIt
; ++aIt
,++nIndex
)
359 pValues
[nIndex
] = *aIt
;
364 // Add the properties only if they do not already exist in the sequence.
365 void ListLevel::AddParaProperties( uno::Sequence
< beans::PropertyValue
>* props
)
367 uno::Sequence
< beans::PropertyValue
>& aProps
= *props
;
368 PropertyNameSupplier
& aPropNameSupplier
= PropertyNameSupplier::GetPropertyNameSupplier();
370 OUString sFirstLineIndent
= aPropNameSupplier
.GetName(
371 PROP_FIRST_LINE_INDENT
);
372 OUString sIndentAt
= aPropNameSupplier
.GetName(
375 bool hasFirstLineIndent
= lcl_findProperty( aProps
, sFirstLineIndent
);
376 bool hasIndentAt
= lcl_findProperty( aProps
, sIndentAt
);
378 if( hasFirstLineIndent
&& hasIndentAt
)
379 return; // has them all, nothing to add
381 uno::Sequence
< beans::PropertyValue
> aParaProps
= m_pParaStyle
->pProperties
->GetPropertyValues( );
383 // ParaFirstLineIndent -> FirstLineIndent
384 // ParaLeftMargin -> IndentAt
386 OUString sParaIndent
= aPropNameSupplier
.GetName(
387 PROP_PARA_FIRST_LINE_INDENT
);
388 OUString sParaLeftMargin
= aPropNameSupplier
.GetName(
389 PROP_PARA_LEFT_MARGIN
);
391 sal_Int32 nLen
= aParaProps
.getLength( );
392 for ( sal_Int32 i
= 0; i
< nLen
; i
++ )
394 if ( !hasFirstLineIndent
&& aParaProps
[i
].Name
.equals( sParaIndent
) )
396 aProps
.realloc( aProps
.getLength() + 1 );
397 aProps
[aProps
.getLength( ) - 1] = aParaProps
[i
];
398 aProps
[aProps
.getLength( ) - 1].Name
= sFirstLineIndent
;
400 else if ( !hasIndentAt
&& aParaProps
[i
].Name
.equals( sParaLeftMargin
) )
402 aProps
.realloc( aProps
.getLength() + 1 );
403 aProps
[aProps
.getLength( ) - 1] = aParaProps
[i
];
404 aProps
[aProps
.getLength( ) - 1].Name
= sIndentAt
;
410 NumPicBullet::NumPicBullet()
415 NumPicBullet::~NumPicBullet()
419 void NumPicBullet::SetId(sal_Int32 nId
)
424 void NumPicBullet::SetShape(uno::Reference
<drawing::XShape
> xShape
)
429 sal_Int32
NumPicBullet::GetId()
434 uno::Reference
<drawing::XShape
> NumPicBullet::GetShape()
439 //--------------------------------------- AbstractListDef implementation
441 AbstractListDef::AbstractListDef( ) :
450 AbstractListDef::~AbstractListDef( )
454 void AbstractListDef::SetValue( sal_uInt32 nSprmId
, sal_Int32 nValue
)
458 case NS_rtf::LN_TPLC
:
461 case NS_rtf::LN_FSIMPLELIST
:
462 m_nSimpleList
= nValue
;
464 case NS_rtf::LN_fAutoNum
:
467 case NS_rtf::LN_fHybrid
:
468 m_nUnsigned
= nValue
;
471 OSL_FAIL( "this line should never be reached");
475 ListLevel::Pointer
AbstractListDef::GetLevel( sal_uInt16 nLvl
)
477 ListLevel::Pointer pLevel
;
478 if ( m_aLevels
.size( ) > nLvl
)
479 pLevel
= m_aLevels
[ nLvl
];
483 void AbstractListDef::AddLevel( )
485 ListLevel::Pointer
pLevel( new ListLevel
);
486 m_pCurrentLevel
= pLevel
;
487 m_aLevels
.push_back( pLevel
);
490 uno::Sequence
< uno::Sequence
< beans::PropertyValue
> > AbstractListDef::GetPropertyValues( )
492 uno::Sequence
< uno::Sequence
< beans::PropertyValue
> > result( sal_Int32( m_aLevels
.size( ) ) );
493 uno::Sequence
< beans::PropertyValue
>* aResult
= result
.getArray( );
495 int nLevels
= m_aLevels
.size( );
496 for ( int i
= 0; i
< nLevels
; i
++ )
498 aResult
[i
] = m_aLevels
[i
]->GetProperties( );
504 //---------------------------------------------- ListDef implementation
506 ListDef::ListDef( ) : AbstractListDef( )
514 OUString
ListDef::GetStyleName( sal_Int32 nId
)
516 OUString
sStyleName( "WWNum" );
517 sStyleName
+= OUString::valueOf( nId
);
522 uno::Sequence
< uno::Sequence
< beans::PropertyValue
> > ListDef::GetPropertyValues( )
524 // [1] Call the same method on the abstract list
525 uno::Sequence
< uno::Sequence
< beans::PropertyValue
> > aAbstract
= m_pAbstractDef
->GetPropertyValues( );
527 // [2] Call the upper class method
528 uno::Sequence
< uno::Sequence
< beans::PropertyValue
> > aThis
= AbstractListDef::GetPropertyValues( );
530 // Merge the results of [2] in [1]
531 sal_Int32 nThisCount
= aThis
.getLength( );
532 sal_Int32 nAbstractCount
= aAbstract
.getLength( );
533 for ( sal_Int32 i
= 0; i
< nThisCount
&& i
< nAbstractCount
; i
++ )
535 uno::Sequence
< beans::PropertyValue
> level
= aThis
[i
];
536 if ( level
.hasElements() )
538 // If the element contains something, merge it
539 lcl_mergeProperties( level
, aAbstract
[i
] );
546 uno::Reference
< container::XNameContainer
> lcl_getUnoNumberingStyles(
547 uno::Reference
< lang::XMultiServiceFactory
> xFactory
)
549 uno::Reference
< container::XNameContainer
> xStyles
;
553 uno::Reference
< style::XStyleFamiliesSupplier
> xFamilies( xFactory
, uno::UNO_QUERY_THROW
);
554 uno::Any oFamily
= xFamilies
->getStyleFamilies( )->getByName("NumberingStyles");
558 catch ( const uno::Exception
& )
565 void ListDef::CreateNumberingRules( DomainMapper
& rDMapper
,
566 uno::Reference
< lang::XMultiServiceFactory
> xFactory
)
568 // Get the UNO Numbering styles
569 uno::Reference
< container::XNameContainer
> xStyles
= lcl_getUnoNumberingStyles( xFactory
);
571 // Do the whole thing
572 if( !m_xNumRules
.is() && xFactory
.is() && xStyles
.is( ) )
576 // Create the numbering style
577 uno::Reference
< beans::XPropertySet
> xStyle (
578 xFactory
->createInstance("com.sun.star.style.NumberingStyle"),
579 uno::UNO_QUERY_THROW
);
581 OUString sStyleName
= GetStyleName( GetId( ) );
583 xStyles
->insertByName( sStyleName
, makeAny( xStyle
) );
585 uno::Any oStyle
= xStyles
->getByName( sStyleName
);
586 xStyle
.set( oStyle
, uno::UNO_QUERY_THROW
);
588 PropertyNameSupplier
& aPropNameSupplier
= PropertyNameSupplier::GetPropertyNameSupplier();
590 // Get the default OOo Numbering style rules
591 uno::Any aRules
= xStyle
->getPropertyValue( aPropNameSupplier
.GetName( PROP_NUMBERING_RULES
) );
592 aRules
>>= m_xNumRules
;
594 uno::Sequence
< uno::Sequence
< beans::PropertyValue
> > aProps
= GetPropertyValues( );
596 sal_Int32 nAbstLevels
= m_pAbstractDef
->Size( );
597 sal_Int16 nLevel
= 0;
598 while ( nLevel
< nAbstLevels
)
600 ListLevel::Pointer pAbsLevel
= m_pAbstractDef
->GetLevel( nLevel
);
601 ListLevel::Pointer pLevel
= GetLevel( nLevel
);
603 // Get the merged level properties
604 uno::Sequence
< beans::PropertyValue
> aLvlProps
= aProps
[sal_Int32( nLevel
)];
606 #if OSL_DEBUG_LEVEL > 1
607 lcl_printProperties( aLvlProps
);
610 // Get the char style
611 uno::Sequence
< beans::PropertyValue
> aAbsCharStyleProps
= pAbsLevel
->GetCharStyleProperties( );
612 uno::Sequence
< beans::PropertyValue
>& rAbsCharStyleProps
= aAbsCharStyleProps
;
615 uno::Sequence
< beans::PropertyValue
> aCharStyleProps
=
616 pLevel
->GetCharStyleProperties( );
617 uno::Sequence
< beans::PropertyValue
>& rCharStyleProps
= aCharStyleProps
;
618 lcl_mergeProperties( rAbsCharStyleProps
, rCharStyleProps
);
621 if( aAbsCharStyleProps
.getLength() )
623 // Change the sequence into a vector
624 PropertyValueVector_t aStyleProps
;
625 for ( sal_Int32 i
= 0, nLen
= aAbsCharStyleProps
.getLength() ; i
< nLen
; i
++ )
627 aStyleProps
.push_back( aAbsCharStyleProps
[i
] );
630 //create (or find) a character style containing the character
631 // attributes of the symbol and apply it to the numbering level
632 OUString sStyle
= rDMapper
.getOrCreateCharStyle( aStyleProps
);
633 aLvlProps
.realloc( aLvlProps
.getLength() + 1);
634 aLvlProps
[sal::static_int_cast
<sal_uInt32
>(aLvlProps
.getLength()) - 1].Name
= aPropNameSupplier
.GetName( PROP_CHAR_STYLE_NAME
);
635 aLvlProps
[sal::static_int_cast
<sal_uInt32
>(aLvlProps
.getLength()) - 1].Value
<<= sStyle
;
638 // Get the prefix / suffix / Parent numbering
639 // and add them to the level properties
640 OUString sText
= pAbsLevel
->GetBulletChar( );
642 sText
= pLevel
->GetBulletChar( );
646 OUString
& rPrefix
= sPrefix
;
647 OUString
& rSuffix
= sSuffix
;
648 sal_Int16 nParentNum
= ListLevel::GetParentNumbering(
649 sText
, nLevel
, rPrefix
, rSuffix
);
651 aLvlProps
.realloc( aLvlProps
.getLength( ) + 4 );
652 aLvlProps
[sal::static_int_cast
<sal_uInt32
>(aLvlProps
.getLength()) - 4] = MAKE_PROPVAL( PROP_PREFIX
, rPrefix
);
653 aLvlProps
[sal::static_int_cast
<sal_uInt32
>(aLvlProps
.getLength()) - 3] = MAKE_PROPVAL( PROP_SUFFIX
, rSuffix
);
654 aLvlProps
[sal::static_int_cast
<sal_uInt32
>(aLvlProps
.getLength()) - 2] = MAKE_PROPVAL( PROP_PARENT_NUMBERING
, nParentNum
);
656 aLvlProps
[sal::static_int_cast
<sal_uInt32
>(aLvlProps
.getLength()) - 1] = MAKE_PROPVAL( PROP_POSITION_AND_SPACE_MODE
,
657 sal_Int16( text::PositionAndSpaceMode::LABEL_ALIGNMENT
) );
659 StyleSheetEntryPtr pParaStyle
= pAbsLevel
->GetParaStyle( );
660 if( pParaStyle
.get())
662 aLvlProps
.realloc( aLvlProps
.getLength() + 1 );
663 aLvlProps
[sal::static_int_cast
<sal_uInt32
>(aLvlProps
.getLength()) - 1] = MAKE_PROPVAL( PROP_PARAGRAPH_STYLE_NAME
,
664 pParaStyle
->sConvertedStyleName
);
667 // Replace the numbering rules for the level
668 m_xNumRules
->replaceByIndex( nLevel
, uno::makeAny( aLvlProps
) );
670 // Handle the outline level here
671 if ( pAbsLevel
->isOutlineNumbering())
673 uno::Reference
< text::XChapterNumberingSupplier
> xOutlines (
674 xFactory
, uno::UNO_QUERY_THROW
);
675 uno::Reference
< container::XIndexReplace
> xOutlineRules
=
676 xOutlines
->getChapterNumberingRules( );
678 aLvlProps
.realloc( aLvlProps
.getLength() + 1 );
679 aLvlProps
[sal::static_int_cast
<sal_uInt32
>(aLvlProps
.getLength()) - 1] = MAKE_PROPVAL( PROP_HEADING_STYLE_NAME
,
680 pParaStyle
->sConvertedStyleName
);
682 xOutlineRules
->replaceByIndex( nLevel
, uno::makeAny( aLvlProps
) );
688 // Create the numbering style for these rules
689 OUString sNumRulesName
= aPropNameSupplier
.GetName( PROP_NUMBERING_RULES
);
690 xStyle
->setPropertyValue( sNumRulesName
, uno::makeAny( m_xNumRules
) );
692 catch( const lang::IllegalArgumentException
& e
)
694 SAL_WARN( "writerfilter", "Exception: " << e
.Message
);
695 assert( !"Incorrect argument to UNO call" );
697 catch( const uno::RuntimeException
& e
)
699 SAL_WARN( "writerfilter", "Exception: " << e
.Message
);
700 assert( !"Incorrect argument to UNO call" );
702 catch( const uno::Exception
& e
)
704 SAL_WARN( "writerfilter", "Exception: " << e
.Message
);
710 //------------------------------------- NumberingManager implementation
713 ListsManager::ListsManager(DomainMapper
& rDMapper
,
714 const uno::Reference
< lang::XMultiServiceFactory
> xFactory
) :
715 LoggedProperties(dmapper_logger
, "ListsManager"),
716 LoggedTable(dmapper_logger
, "ListsManager"),
717 m_rDMapper( rDMapper
),
718 m_xFactory( xFactory
)
722 ListsManager::~ListsManager( )
726 void ListsManager::lcl_attribute( Id nName
, Value
& rVal
)
728 ListLevel::Pointer pCurrentLvl
;
730 if (nName
!= NS_ooxml::LN_CT_NumPicBullet_numPicBulletId
)
732 OSL_ENSURE( m_pCurrentDefinition
.get(), "current entry has to be set here");
733 if(!m_pCurrentDefinition
.get())
735 pCurrentLvl
= m_pCurrentDefinition
->GetCurrentLevel( );
739 SAL_WARN_IF(!m_pCurrentNumPicBullet
.get(), "writerfilter", "current entry has to be set here");
740 if (!m_pCurrentNumPicBullet
.get())
743 int nIntValue
= rVal
.getInt();
749 case NS_rtf::LN_RGBXCHNUMS
:
750 if(pCurrentLvl
.get())
751 pCurrentLvl
->AddRGBXchNums( rVal
.getString( ) );
753 case NS_ooxml::LN_CT_LevelText_val
:
755 //this strings contains the definition of the level
756 //the level number is marked as %n
757 //these numbers can be mixed randomly toghether with separators pre- and suffixes
758 //the Writer supports only a number of upper levels to show, separators is always a dot
759 //and each level can have a prefix and a suffix
760 if(pCurrentLvl
.get())
761 pCurrentLvl
->SetBulletChar( rVal
.getString() );
764 case NS_rtf::LN_ISTARTAT
:
767 case NS_rtf::LN_FLEGAL
:
768 case NS_rtf::LN_FNORESTART
:
769 case NS_rtf::LN_FIDENTSAV
:
770 case NS_rtf::LN_FCONVERTED
:
771 case NS_rtf::LN_IXCHFOLLOW
:
772 if ( pCurrentLvl
.get( ) )
773 pCurrentLvl
->SetValue( nName
, sal_Int32( nIntValue
) );
775 case NS_rtf::LN_RGISTD
:
776 m_pCurrentDefinition
->AddRGISTD( rVal
.getString() );
778 case NS_ooxml::LN_CT_Num_numId
:
779 m_pCurrentDefinition
->SetId( rVal
.getString().toInt32( ) );
781 case NS_rtf::LN_LSID
:
782 m_pCurrentDefinition
->SetId( nIntValue
);
784 case NS_rtf::LN_TPLC
:
785 case NS_rtf::LN_FSIMPLELIST
:
786 case NS_rtf::LN_fAutoNum
:
787 case NS_rtf::LN_fHybrid
:
788 m_pCurrentDefinition
->SetValue( nName
, nIntValue
);
790 case NS_ooxml::LN_CT_NumLvl_ilvl
:
791 case NS_rtf::LN_LISTLEVEL
:
793 //add a new level to the level vector and make it the current one
794 m_pCurrentDefinition
->AddLevel();
796 writerfilter::Reference
<Properties
>::Pointer_t pProperties
;
797 if((pProperties
= rVal
.getProperties()).get())
798 pProperties
->resolve(*this);
801 case NS_ooxml::LN_CT_AbstractNum_abstractNumId
:
803 // This one corresponds to the AbstractNum Id definition
804 // The reference to the abstract num is in the sprm method
805 sal_Int32 nVal
= rVal
.getString().toInt32();
806 m_pCurrentDefinition
->SetId( nVal
);
809 case NS_ooxml::LN_CT_Ind_left
:
811 PROP_INDENT_AT
, true, uno::makeAny( ConversionHelper::convertTwipToMM100( nIntValue
) ));
813 case NS_ooxml::LN_CT_Ind_hanging
:
815 PROP_FIRST_LINE_INDENT
, true, uno::makeAny( - ConversionHelper::convertTwipToMM100( nIntValue
) ));
817 case NS_ooxml::LN_CT_Ind_firstLine
:
819 PROP_FIRST_LINE_INDENT
, true, uno::makeAny( ConversionHelper::convertTwipToMM100( nIntValue
) ));
821 case NS_ooxml::LN_CT_Lvl_ilvl
: //overrides previous level - unsupported
822 case NS_ooxml::LN_CT_Lvl_tplc
: //template code - unsupported
823 case NS_ooxml::LN_CT_Lvl_tentative
: //marks level as unused in the document - unsupported
825 case NS_ooxml::LN_CT_TabStop_pos
:
827 //no paragraph attributes in ListTable char style sheets
828 if ( pCurrentLvl
.get( ) )
829 pCurrentLvl
->SetValue( nName
,
830 ConversionHelper::convertTwipToMM100( nIntValue
) );
833 case NS_ooxml::LN_CT_TabStop_val
:
835 // TODO Do something of that
838 case NS_ooxml::LN_CT_NumPicBullet_numPicBulletId
:
839 m_pCurrentNumPicBullet
->SetId(rVal
.getString().toInt32());
843 #if OSL_DEBUG_LEVEL > 0
844 OString
sMessage( "ListTable::attribute() - Id: ");
845 sMessage
+= OString::valueOf( sal_Int32( nName
), 10 );
847 sMessage
+= OString::valueOf( sal_Int32( nName
), 16 );
848 sMessage
+= " value: ";
849 sMessage
+= OString::valueOf( sal_Int32( nIntValue
), 10 );
851 sMessage
+= OString::valueOf( sal_Int32( nIntValue
), 16 );
852 SAL_WARN("writerfilter", sMessage
.getStr());
858 void ListsManager::lcl_sprm( Sprm
& rSprm
)
860 //fill the attributes of the style sheet
861 sal_uInt32 nSprmId
= rSprm
.getId();
862 if( m_pCurrentDefinition
.get() ||
863 nSprmId
== NS_ooxml::LN_CT_Numbering_abstractNum
||
864 nSprmId
== NS_ooxml::LN_CT_Numbering_num
||
865 (nSprmId
== NS_ooxml::LN_CT_NumPicBullet_pict
&& m_pCurrentNumPicBullet
.get()) ||
866 nSprmId
== NS_ooxml::LN_CT_Numbering_numPicBullet
)
868 sal_Int32 nIntValue
= rSprm
.getValue()->getInt();
871 case NS_ooxml::LN_CT_Numbering_abstractNum
:
873 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
874 if(pProperties
.get())
876 //create a new Abstract list entry
877 OSL_ENSURE( !m_pCurrentDefinition
.get(), "current entry has to be NULL here");
878 m_pCurrentDefinition
.reset( new AbstractListDef
);
879 pProperties
->resolve( *this );
880 //append it to the table
881 m_aAbstractLists
.push_back( m_pCurrentDefinition
);
882 m_pCurrentDefinition
= AbstractListDef::Pointer();
886 case NS_ooxml::LN_CT_Numbering_num
:
888 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
889 if(pProperties
.get())
891 // Create a new list entry
892 OSL_ENSURE( !m_pCurrentDefinition
.get(), "current entry has to be NULL here");
893 ListDef::Pointer
listDef( new ListDef
);
894 m_pCurrentDefinition
= listDef
;
895 pProperties
->resolve( *this );
896 //append it to the table
897 m_aLists
.push_back( listDef
);
899 m_pCurrentDefinition
= AbstractListDef::Pointer();
903 case NS_ooxml::LN_CT_Numbering_numPicBullet
:
905 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
906 if (pProperties
.get())
908 NumPicBullet::Pointer
numPicBullet(new NumPicBullet());
909 m_pCurrentNumPicBullet
= numPicBullet
;
910 pProperties
->resolve(*this);
911 m_aNumPicBullets
.push_back(numPicBullet
);
912 m_pCurrentNumPicBullet
= NumPicBullet::Pointer();
916 case NS_ooxml::LN_CT_NumPicBullet_pict
:
918 uno::Reference
<drawing::XShape
> xShape
= m_rDMapper
.PopPendingShape();
919 m_pCurrentNumPicBullet
->SetShape(xShape
);
922 case NS_ooxml::LN_CT_Lvl_lvlPicBulletId
:
924 uno::Reference
<drawing::XShape
> xShape
;
925 for (std::vector
<NumPicBullet::Pointer
>::iterator it
= m_aNumPicBullets
.begin(); it
!= m_aNumPicBullets
.end(); ++it
)
927 if ((*it
)->GetId() == nIntValue
)
929 xShape
= (*it
)->GetShape();
935 uno::Reference
<beans::XPropertySet
> xPropertySet(xShape
, uno::UNO_QUERY
);
936 uno::Reference
<beans::XPropertySetInfo
> info
= xPropertySet
->getPropertySetInfo();
937 uno::Sequence
<beans::Property
> properties
= info
->getProperties();
940 uno::Any aAny
= xPropertySet
->getPropertyValue("GraphicURL");
941 if (aAny
.has
<OUString
>())
942 m_pCurrentDefinition
->GetCurrentLevel()->SetGraphicURL(aAny
.get
<OUString
>());
943 } catch(const beans::UnknownPropertyException
&)
947 uno::Reference
< graphic::XGraphic
> gr
;
948 xPropertySet
->getPropertyValue("Bitmap") >>= gr
;
949 m_pCurrentDefinition
->GetCurrentLevel()->SetGraphicBitmap( gr
);
950 } catch(const beans::UnknownPropertyException
&)
953 // Now that we saved the URL of the graphic, remove it from the document.
954 uno::Reference
<lang::XComponent
> xShapeComponent(xShape
, uno::UNO_QUERY
);
955 xShapeComponent
->dispose();
959 case NS_ooxml::LN_CT_Num_abstractNumId
:
961 sal_Int32 nAbstractNumId
= rSprm
.getValue()->getInt();
962 ListDef
* pListDef
= dynamic_cast< ListDef
* >( m_pCurrentDefinition
.get( ) );
963 if ( pListDef
!= NULL
)
965 // The current def should be a ListDef
966 pListDef
->SetAbstractDefinition(
967 GetAbstractList( nAbstractNumId
) );
971 case NS_ooxml::LN_CT_AbstractNum_multiLevelType
:
973 case NS_rtf::LN_TPLC
:
974 m_pCurrentDefinition
->SetValue( nSprmId
, nIntValue
);
976 case NS_ooxml::LN_CT_AbstractNum_lvl
:
978 m_pCurrentDefinition
->AddLevel();
979 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
980 if(pProperties
.get())
981 pProperties
->resolve(*this);
984 case NS_rtf::LN_RGBXCHNUMS
: break;
985 case NS_rtf::LN_ISTARTAT
:
988 case NS_rtf::LN_FLEGAL
:
989 case NS_rtf::LN_FNORESTART
:
990 case NS_rtf::LN_FIDENTSAV
:
991 case NS_rtf::LN_FCONVERTED
:
992 case NS_rtf::LN_IXCHFOLLOW
:
993 if (m_pCurrentDefinition
->GetCurrentLevel().get())
994 m_pCurrentDefinition
->GetCurrentLevel( )->SetValue( nSprmId
, nIntValue
);
996 case NS_ooxml::LN_CT_Lvl_suff
:
998 if (m_pCurrentDefinition
->GetCurrentLevel().get())
1000 SvxNumberFormat::LabelFollowedBy value
= SvxNumberFormat::LISTTAB
;
1001 if( rSprm
.getValue()->getString() == "tab" )
1002 value
= SvxNumberFormat::LISTTAB
;
1003 else if( rSprm
.getValue()->getString() == "space" )
1004 value
= SvxNumberFormat::SPACE
;
1005 else if( rSprm
.getValue()->getString() == "nothing" )
1006 value
= SvxNumberFormat::NOTHING
;
1008 SAL_WARN( "writerfilter", "Unknown ST_LevelSuffix value "
1009 << rSprm
.getValue()->getString());
1010 m_pCurrentDefinition
->GetCurrentLevel()->SetValue( nSprmId
, value
);
1014 case NS_ooxml::LN_CT_Lvl_lvlText
:
1015 case NS_ooxml::LN_CT_Lvl_rPr
: //contains LN_EG_RPrBase_rFonts
1017 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
1018 if(pProperties
.get())
1019 pProperties
->resolve(*this);
1022 case NS_ooxml::LN_CT_NumLvl_lvl
:
1025 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
1026 if(pProperties
.get())
1027 pProperties
->resolve(*this);
1030 case NS_ooxml::LN_CT_Lvl_lvlJc
:
1032 static sal_Int16 aWWAlignments
[ ] =
1034 text::HoriOrientation::LEFT
,
1035 text::HoriOrientation::CENTER
,
1036 text::HoriOrientation::RIGHT
1038 m_pCurrentDefinition
->GetCurrentLevel( )->Insert(
1039 PROP_ADJUST
, true, uno::makeAny( aWWAlignments
[ nIntValue
] ) );
1040 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
1043 case NS_ooxml::LN_CT_Lvl_pPr
:
1044 case NS_ooxml::LN_CT_PPrBase_ind
:
1046 //todo: how to handle paragraph properties within numbering levels (except LeftIndent and FirstLineIndent)?
1047 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
1048 if(pProperties
.get())
1049 pProperties
->resolve(*this);
1052 case NS_ooxml::LN_CT_PPrBase_tabs
:
1053 case NS_ooxml::LN_CT_Tabs_tab
:
1055 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
1056 if(pProperties
.get())
1057 pProperties
->resolve(*this);
1060 case NS_ooxml::LN_CT_Lvl_pStyle
:
1062 OUString sStyleName
= rSprm
.getValue( )->getString( );
1063 ListLevel::Pointer pLevel
= m_pCurrentDefinition
->GetCurrentLevel( );
1064 StyleSheetTablePtr pStylesTable
= m_rDMapper
.GetStyleSheetTable( );
1065 const StyleSheetEntryPtr pStyle
= pStylesTable
->FindStyleSheetByISTD( sStyleName
);
1066 pLevel
->SetParaStyle( pStyle
);
1069 case NS_ooxml::LN_CT_Num_lvlOverride
:
1071 writerfilter::Reference
<Properties
>::Pointer_t pProperties
= rSprm
.getProps();
1072 if (pProperties
.get())
1073 pProperties
->resolve(*this);
1076 case NS_ooxml::LN_CT_AbstractNum_numStyleLink
:
1078 OUString sStyleName
= rSprm
.getValue( )->getString( );
1079 AbstractListDef
* pAbstractListDef
= dynamic_cast< AbstractListDef
* >( m_pCurrentDefinition
.get( ) );
1080 pAbstractListDef
->SetNumStyleLink(sStyleName
);
1083 case NS_ooxml::LN_EG_RPrBase_rFonts
: //contains font properties
1084 case NS_ooxml::LN_EG_RPrBase_color
:
1085 case NS_ooxml::LN_EG_RPrBase_u
:
1086 case NS_sprm::LN_CHps
: // sprmCHps
1087 case NS_ooxml::LN_EG_RPrBase_lang
:
1088 case NS_ooxml::LN_EG_RPrBase_eastAsianLayout
:
1091 if( m_pCurrentDefinition
->GetCurrentLevel( ).get())
1093 m_rDMapper
.PushListProperties( m_pCurrentDefinition
->GetCurrentLevel( ) );
1094 m_rDMapper
.sprm( rSprm
);
1095 m_rDMapper
.PopListProperties();
1101 void ListsManager::lcl_entry( int /* pos */,
1102 writerfilter::Reference
<Properties
>::Pointer_t ref
)
1104 if( m_rDMapper
.IsOOXMLImport() || m_rDMapper
.IsRTFImport() )
1106 ref
->resolve(*this);
1110 if ( m_bIsLFOImport
)
1113 OSL_ENSURE( !m_pCurrentDefinition
.get(), "current entry has to be NULL here");
1114 ListDef::Pointer
pList( new ListDef() );
1115 m_pCurrentDefinition
= pList
;
1116 ref
->resolve(*this);
1117 //append it to the table
1118 m_aLists
.push_back( pList
);
1119 m_pCurrentDefinition
= AbstractListDef::Pointer();
1123 // Create AbstractListDef's
1124 OSL_ENSURE( !m_pCurrentDefinition
.get(), "current entry has to be NULL here");
1125 m_pCurrentDefinition
.reset( new AbstractListDef( ) );
1126 ref
->resolve(*this);
1127 //append it to the table
1128 m_aAbstractLists
.push_back( m_pCurrentDefinition
);
1129 m_pCurrentDefinition
= AbstractListDef::Pointer();
1134 AbstractListDef::Pointer
ListsManager::GetAbstractList( sal_Int32 nId
)
1136 AbstractListDef::Pointer pAbstractList
;
1138 int nLen
= m_aAbstractLists
.size( );
1140 while ( !pAbstractList
.get( ) && i
< nLen
)
1142 if ( m_aAbstractLists
[i
]->GetId( ) == nId
)
1144 if ( m_aAbstractLists
[i
]->GetNumStyleLink().getLength() > 0 )
1146 // If the abstract num has a style linked, check the linked style's number id.
1147 StyleSheetTablePtr pStylesTable
= m_rDMapper
.GetStyleSheetTable( );
1149 const StyleSheetEntryPtr pStyleSheetEntry
=
1150 pStylesTable
->FindStyleSheetByISTD( m_aAbstractLists
[i
]->GetNumStyleLink() );
1152 const StyleSheetPropertyMap
* pStyleSheetProperties
=
1153 dynamic_cast<const StyleSheetPropertyMap
*>(pStyleSheetEntry
? pStyleSheetEntry
->pProperties
.get() : 0);
1155 if( pStyleSheetProperties
&& pStyleSheetProperties
->GetNumId() >= 0 )
1157 ListDef::Pointer pList
= GetList( pStyleSheetProperties
->GetNumId() );
1159 return pList
->GetAbstractDefinition();
1161 pAbstractList
= m_aAbstractLists
[i
];
1167 pAbstractList
= m_aAbstractLists
[i
];
1173 return pAbstractList
;
1176 ListDef::Pointer
ListsManager::GetList( sal_Int32 nId
)
1178 ListDef::Pointer pList
;
1180 int nLen
= m_aLists
.size( );
1182 while ( !pList
.get( ) && i
< nLen
)
1184 if ( m_aLists
[i
]->GetId( ) == nId
)
1185 pList
= m_aLists
[i
];
1192 void ListsManager::CreateNumberingRules( )
1194 // Loop over the definitions
1195 std::vector
< ListDef::Pointer
>::iterator listIt
= m_aLists
.begin( );
1196 for ( ; listIt
!= m_aLists
.end( ); ++listIt
)
1198 (*listIt
)->CreateNumberingRules( m_rDMapper
, m_xFactory
);
1204 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */