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