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 192 : sal_Int32 lcl_findProperty( uno::Sequence< beans::PropertyValue > aProps, OUString sName )
70 : {
71 192 : sal_Int32 i = 0;
72 192 : sal_Int32 nLen = aProps.getLength( );
73 192 : sal_Int32 nPos = -1;
74 :
75 1920 : while ( nPos == -1 && i < nLen )
76 : {
77 1536 : if ( aProps[i].Name.equals( sName ) )
78 192 : nPos = i;
79 : else
80 1344 : i++;
81 : }
82 :
83 192 : 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 1092 : void ListLevel::SetValue( Id nId, sal_Int32 nValue )
109 : {
110 1092 : switch( nId )
111 : {
112 : case NS_rtf::LN_ISTARTAT:
113 426 : m_nIStartAt = nValue;
114 426 : break;
115 : case NS_rtf::LN_NFC:
116 430 : m_nNFC = nValue;
117 430 : 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 32 : m_nXChFollow = nValue;
136 32 : break;
137 : case NS_ooxml::LN_CT_TabStop_pos:
138 204 : m_nTabstop = nValue;
139 204 : break;
140 : default:
141 : OSL_FAIL( "this line should never be reached");
142 : }
143 1092 : }
144 :
145 46 : void ListLevel::SetParaStyle( boost::shared_ptr< StyleSheetEntry > pStyle )
146 : {
147 46 : if (!pStyle)
148 46 : return;
149 46 : 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 46 : const OUString styleId = pStyle->sStyleIdentifierD;
154 46 : m_outline = ( styleId.getLength() == RTL_CONSTASCII_LENGTH( "Heading1" )
155 6 : && styleId.match( "Heading", 0 )
156 6 : && styleId[ RTL_CONSTASCII_LENGTH( "Heading" ) ] >= '1'
157 58 : && styleId[ RTL_CONSTASCII_LENGTH( "Heading" ) ] <= '9' );
158 : }
159 :
160 454 : sal_Int16 ListLevel::GetParentNumbering( OUString sText, sal_Int16 nLevel,
161 : OUString& rPrefix, OUString& rSuffix )
162 : {
163 454 : 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 454 : OUString sLevelText( sText );
168 454 : sal_Int32 nCurrentIndex = 0;
169 454 : sal_Int32 nFound = sLevelText.indexOf( '%', nCurrentIndex );
170 454 : if( nFound > 0 )
171 : {
172 12 : rPrefix = sLevelText.copy( 0, nFound );
173 12 : sLevelText = sLevelText.copy( nFound );
174 : }
175 454 : sal_Int32 nMinLevel = nLevel;
176 : //now the text should either be empty or start with %
177 454 : nFound = sLevelText.getLength( ) > 1 ? 0 : -1;
178 2040 : while( nFound >= 0 )
179 : {
180 1132 : if( sLevelText.getLength() > 1 )
181 : {
182 1132 : sal_Unicode cLevel = sLevelText.getStr()[1];
183 1132 : if( cLevel >= '1' && cLevel <= '9' )
184 : {
185 688 : if( cLevel - '1' < nMinLevel )
186 102 : nMinLevel = cLevel - '1';
187 : //remove first char - next char is removed later
188 688 : sLevelText = sLevelText.copy( 1 );
189 : }
190 : }
191 : //remove old '%' or number
192 1132 : sLevelText = sLevelText.copy( 1 );
193 1132 : nCurrentIndex = 0;
194 1132 : nFound = sLevelText.indexOf( '%', nCurrentIndex );
195 : //remove the text before the next %
196 1132 : if(nFound > 0)
197 444 : sLevelText = sLevelText.copy( nFound -1 );
198 : }
199 454 : if( nMinLevel < nLevel )
200 : {
201 102 : nParentNumbering = sal_Int16( nLevel - nMinLevel + 1);
202 : }
203 :
204 454 : rSuffix = sLevelText;
205 :
206 454 : return nParentNumbering;
207 : }
208 :
209 454 : uno::Sequence< beans::PropertyValue > ListLevel::GetProperties( )
210 : {
211 454 : uno::Sequence< beans::PropertyValue > aLevelProps = GetLevelProperties( );
212 454 : if ( m_pParaStyle.get( ) )
213 96 : AddParaProperties( &aLevelProps );
214 454 : return aLevelProps;
215 : }
216 :
217 454 : uno::Sequence< beans::PropertyValue > ListLevel::GetCharStyleProperties( )
218 : {
219 454 : PropertyValueVector_t rProperties;
220 454 : PropertyNameSupplier& aPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
221 :
222 454 : _PropertyMap::const_iterator aMapIter = begin();
223 454 : _PropertyMap::const_iterator aEndIter = end();
224 2156 : for( ; aMapIter != aEndIter; ++aMapIter )
225 : {
226 1702 : 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 1504 : break;
236 : default:
237 : {
238 : rProperties.push_back(
239 : beans::PropertyValue(
240 198 : aPropNameSupplier.GetName( aMapIter->first.eId ), 0,
241 396 : aMapIter->second, beans::PropertyState_DIRECT_VALUE ));
242 : }
243 : }
244 : }
245 :
246 454 : uno::Sequence< beans::PropertyValue > aRet( rProperties.size() );
247 454 : beans::PropertyValue* pValues = aRet.getArray();
248 454 : PropertyValueVector_t::const_iterator aIt = rProperties.begin();
249 454 : PropertyValueVector_t::const_iterator aEndIt = rProperties.end();
250 652 : for(sal_uInt32 nIndex = 0; aIt != aEndIt; ++aIt,++nIndex)
251 : {
252 198 : pValues[nIndex] = *aIt;
253 : }
254 454 : return aRet;
255 : }
256 :
257 454 : 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 454 : };
265 :
266 454 : PropertyNameSupplier& aPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
267 454 : PropertyValueVector_t aNumberingProperties;
268 :
269 454 : if( m_nIStartAt >= 0)
270 452 : aNumberingProperties.push_back( MAKE_PROPVAL(PROP_START_WITH, (sal_Int16)m_nIStartAt) );
271 :
272 454 : sal_Int16 nNumberFormat = ConversionHelper::ConvertNumberingType(m_nNFC);
273 454 : if( m_nNFC >= 0)
274 454 : aNumberingProperties.push_back( MAKE_PROPVAL(PROP_NUMBERING_TYPE, nNumberFormat ));
275 :
276 454 : 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 454 : if( !isOutlineNumbering())
280 : {
281 : // todo: this is not the bullet char
282 448 : if( nNumberFormat == style::NumberingType::CHAR_SPECIAL && !m_sBulletChar.isEmpty() )
283 208 : aNumberingProperties.push_back( MAKE_PROPVAL(PROP_BULLET_CHAR, m_sBulletChar.copy(0,1)));
284 : }
285 :
286 454 : 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 454 : 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 454 : aNumberingProperties.push_back( MAKE_PROPVAL( PROP_LEVEL_FOLLOW, m_nXChFollow ));
308 :
309 :
310 454 : _PropertyMap::const_iterator aMapIter = begin();
311 454 : _PropertyMap::const_iterator aEndIter = end();
312 2156 : for( ; aMapIter != aEndIter; ++aMapIter )
313 : {
314 1702 : 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 1290 : beans::PropertyValue( aPropNameSupplier.GetName( aMapIter->first.eId ), 0, aMapIter->second, beans::PropertyState_DIRECT_VALUE ));
323 1290 : break;
324 : case PROP_CHAR_FONT_NAME:
325 214 : if( !isOutlineNumbering())
326 : {
327 : aNumberingProperties.push_back(
328 214 : beans::PropertyValue( aPropNameSupplier.GetName( PROP_BULLET_FONT_NAME ), 0, aMapIter->second, beans::PropertyState_DIRECT_VALUE ));
329 : }
330 214 : break;
331 : default:
332 : {
333 : // Handled in GetCharStyleProperties method
334 : }
335 :
336 : }
337 : }
338 :
339 454 : uno::Sequence< beans::PropertyValue > aRet(aNumberingProperties.size());
340 454 : beans::PropertyValue* pValues = aRet.getArray();
341 454 : PropertyValueVector_t::const_iterator aIt = aNumberingProperties.begin();
342 454 : PropertyValueVector_t::const_iterator aEndIt = aNumberingProperties.end();
343 3980 : for(sal_uInt32 nIndex = 0; aIt != aEndIt; ++aIt,++nIndex)
344 : {
345 3526 : pValues[nIndex] = *aIt;
346 : }
347 454 : return aRet;
348 : }
349 :
350 : // Add the properties only if they do not already exist in the sequence.
351 96 : void ListLevel::AddParaProperties( uno::Sequence< beans::PropertyValue >* props )
352 : {
353 96 : uno::Sequence< beans::PropertyValue >& aProps = *props;
354 96 : PropertyNameSupplier& aPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
355 :
356 : OUString sFirstLineIndent = aPropNameSupplier.GetName(
357 96 : PROP_FIRST_LINE_INDENT );
358 : OUString sIndentAt = aPropNameSupplier.GetName(
359 96 : PROP_INDENT_AT );
360 :
361 96 : bool hasFirstLineIndent = lcl_findProperty( aProps, sFirstLineIndent );
362 96 : bool hasIndentAt = lcl_findProperty( aProps, sIndentAt );
363 :
364 96 : if( hasFirstLineIndent && hasIndentAt )
365 96 : 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 224 : AbstractListDef::AbstractListDef( ) :
399 : m_nTPLC( -1 )
400 : ,m_nSimpleList( -1 )
401 : ,m_nRestart( -1 )
402 : ,m_nUnsigned( -1 )
403 224 : ,m_nId( -1 )
404 : {
405 224 : }
406 :
407 312 : AbstractListDef::~AbstractListDef( )
408 : {
409 312 : }
410 :
411 68 : void AbstractListDef::SetValue( sal_uInt32 nSprmId, sal_Int32 nValue )
412 : {
413 68 : switch( nSprmId )
414 : {
415 : case NS_rtf::LN_TPLC:
416 68 : m_nTPLC = nValue;
417 68 : 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 68 : }
431 :
432 908 : ListLevel::Pointer AbstractListDef::GetLevel( sal_uInt16 nLvl )
433 : {
434 908 : ListLevel::Pointer pLevel;
435 908 : if ( m_aLevels.size( ) > nLvl )
436 454 : pLevel = m_aLevels[ nLvl ];
437 908 : return pLevel;
438 : }
439 :
440 430 : void AbstractListDef::AddLevel( )
441 : {
442 430 : ListLevel::Pointer pLevel( new ListLevel );
443 430 : m_pCurrentLevel = pLevel;
444 430 : m_aLevels.push_back( pLevel );
445 430 : }
446 :
447 256 : uno::Sequence< uno::Sequence< beans::PropertyValue > > AbstractListDef::GetPropertyValues( )
448 : {
449 256 : uno::Sequence< uno::Sequence< beans::PropertyValue > > result( sal_Int32( m_aLevels.size( ) ) );
450 256 : uno::Sequence< beans::PropertyValue >* aResult = result.getArray( );
451 :
452 256 : int nLevels = m_aLevels.size( );
453 710 : for ( int i = 0; i < nLevels; i++ )
454 : {
455 454 : aResult[i] = m_aLevels[i]->GetProperties( );
456 : }
457 :
458 256 : return result;
459 : }
460 :
461 : //---------------------------------------------- ListDef implementation
462 :
463 136 : ListDef::ListDef( ) : AbstractListDef( )
464 : {
465 136 : }
466 :
467 272 : ListDef::~ListDef( )
468 : {
469 272 : }
470 :
471 154 : OUString ListDef::GetStyleName( sal_Int32 nId )
472 : {
473 154 : OUString sStyleName( "WWNum" );
474 154 : sStyleName += OUString::valueOf( nId );
475 :
476 154 : return sStyleName;
477 : }
478 :
479 128 : uno::Sequence< uno::Sequence< beans::PropertyValue > > ListDef::GetPropertyValues( )
480 : {
481 : // [1] Call the same method on the abstract list
482 128 : uno::Sequence< uno::Sequence< beans::PropertyValue > > aAbstract = m_pAbstractDef->GetPropertyValues( );
483 :
484 : // [2] Call the upper class method
485 128 : uno::Sequence< uno::Sequence< beans::PropertyValue > > aThis = AbstractListDef::GetPropertyValues( );
486 :
487 : // Merge the results of [2] in [1]
488 128 : sal_Int32 nThisCount = aThis.getLength( );
489 128 : 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 128 : return aAbstract;
500 : }
501 :
502 142 : uno::Reference< container::XNameContainer > lcl_getUnoNumberingStyles(
503 : uno::Reference< lang::XMultiServiceFactory > xFactory )
504 : {
505 142 : uno::Reference< container::XNameContainer > xStyles;
506 :
507 : try
508 : {
509 142 : uno::Reference< style::XStyleFamiliesSupplier > xFamilies( xFactory, uno::UNO_QUERY_THROW );
510 130 : uno::Any oFamily = xFamilies->getStyleFamilies( )->getByName("NumberingStyles");
511 :
512 130 : oFamily >>= xStyles;
513 : }
514 12 : catch ( const uno::Exception )
515 : {
516 12 : }
517 :
518 142 : return xStyles;
519 : }
520 :
521 142 : void ListDef::CreateNumberingRules( DomainMapper& rDMapper,
522 : uno::Reference< lang::XMultiServiceFactory> xFactory )
523 : {
524 : // Get the UNO Numbering styles
525 142 : uno::Reference< container::XNameContainer > xStyles = lcl_getUnoNumberingStyles( xFactory );
526 :
527 : // Do the whole thing
528 142 : if( !m_xNumRules.is() && xFactory.is() && xStyles.is( ) )
529 : {
530 : try
531 : {
532 : // Create the numbering style
533 : uno::Reference< beans::XPropertySet > xStyle (
534 128 : xFactory->createInstance("com.sun.star.style.NumberingStyle"),
535 128 : uno::UNO_QUERY_THROW );
536 :
537 128 : OUString sStyleName = GetStyleName( GetId( ) );
538 :
539 128 : xStyles->insertByName( sStyleName, makeAny( xStyle ) );
540 :
541 128 : uno::Any oStyle = xStyles->getByName( sStyleName );
542 128 : xStyle.set( oStyle, uno::UNO_QUERY_THROW );
543 :
544 128 : PropertyNameSupplier& aPropNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
545 :
546 : // Get the default OOo Numbering style rules
547 128 : uno::Any aRules = xStyle->getPropertyValue( aPropNameSupplier.GetName( PROP_NUMBERING_RULES ) );
548 128 : aRules >>= m_xNumRules;
549 :
550 128 : uno::Sequence< uno::Sequence< beans::PropertyValue > > aProps = GetPropertyValues( );
551 :
552 128 : sal_Int32 nAbstLevels = m_pAbstractDef->Size( );
553 128 : sal_Int16 nLevel = 0;
554 710 : while ( nLevel < nAbstLevels )
555 : {
556 454 : ListLevel::Pointer pAbsLevel = m_pAbstractDef->GetLevel( nLevel );
557 454 : ListLevel::Pointer pLevel = GetLevel( nLevel );
558 :
559 : // Get the merged level properties
560 454 : 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 454 : uno::Sequence< beans::PropertyValue > aAbsCharStyleProps = pAbsLevel->GetCharStyleProperties( );
568 454 : uno::Sequence< beans::PropertyValue >& rAbsCharStyleProps = aAbsCharStyleProps;
569 454 : 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 454 : if( aAbsCharStyleProps.getLength() )
578 : {
579 : // Change the sequence into a vector
580 146 : PropertyValueVector_t aStyleProps;
581 344 : for ( sal_Int32 i = 0, nLen = aAbsCharStyleProps.getLength() ; i < nLen; i++ )
582 : {
583 198 : 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 146 : OUString sStyle = rDMapper.getOrCreateCharStyle( aStyleProps );
589 146 : aLvlProps.realloc( aLvlProps.getLength() + 1);
590 146 : aLvlProps[sal::static_int_cast<sal_uInt32>(aLvlProps.getLength()) - 1].Name = aPropNameSupplier.GetName( PROP_CHAR_STYLE_NAME );
591 146 : 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 454 : OUString sText = pAbsLevel->GetBulletChar( );
597 454 : if ( pLevel.get( ) )
598 0 : sText = pLevel->GetBulletChar( );
599 :
600 454 : OUString sPrefix;
601 454 : OUString sSuffix;
602 454 : OUString& rPrefix = sPrefix;
603 454 : OUString& rSuffix = sSuffix;
604 : sal_Int16 nParentNum = ListLevel::GetParentNumbering(
605 454 : sText, nLevel, rPrefix, rSuffix );
606 :
607 454 : aLvlProps.realloc( aLvlProps.getLength( ) + 4 );
608 454 : aLvlProps[sal::static_int_cast<sal_uInt32>(aLvlProps.getLength()) - 4] = MAKE_PROPVAL( PROP_PREFIX, rPrefix );
609 454 : aLvlProps[sal::static_int_cast<sal_uInt32>(aLvlProps.getLength()) - 3] = MAKE_PROPVAL( PROP_SUFFIX, rSuffix );
610 454 : aLvlProps[sal::static_int_cast<sal_uInt32>(aLvlProps.getLength()) - 2] = MAKE_PROPVAL( PROP_PARENT_NUMBERING, nParentNum );
611 :
612 908 : aLvlProps[sal::static_int_cast<sal_uInt32>(aLvlProps.getLength()) - 1] = MAKE_PROPVAL( PROP_POSITION_AND_SPACE_MODE,
613 454 : sal_Int16( text::PositionAndSpaceMode::LABEL_ALIGNMENT ) );
614 :
615 454 : StyleSheetEntryPtr pParaStyle = pAbsLevel->GetParaStyle( );
616 454 : if( pParaStyle.get())
617 : {
618 96 : aLvlProps.realloc( aLvlProps.getLength() + 1 );
619 192 : aLvlProps[sal::static_int_cast<sal_uInt32>(aLvlProps.getLength()) - 1] = MAKE_PROPVAL( PROP_PARAGRAPH_STYLE_NAME,
620 96 : pParaStyle->sConvertedStyleName );
621 : }
622 :
623 : // Replace the numbering rules for the level
624 454 : m_xNumRules->replaceByIndex( nLevel, uno::makeAny( aLvlProps ) );
625 :
626 : // Handle the outline level here
627 454 : if ( pAbsLevel->isOutlineNumbering())
628 : {
629 : uno::Reference< text::XChapterNumberingSupplier > xOutlines (
630 6 : xFactory, uno::UNO_QUERY_THROW );
631 : uno::Reference< container::XIndexReplace > xOutlineRules =
632 6 : xOutlines->getChapterNumberingRules( );
633 :
634 6 : aLvlProps.realloc( aLvlProps.getLength() + 1 );
635 12 : aLvlProps[sal::static_int_cast<sal_uInt32>(aLvlProps.getLength()) - 1] = MAKE_PROPVAL( PROP_HEADING_STYLE_NAME,
636 6 : pParaStyle->sConvertedStyleName );
637 :
638 6 : xOutlineRules->replaceByIndex( nLevel, uno::makeAny( aLvlProps ) );
639 : }
640 :
641 454 : nLevel++;
642 454 : }
643 :
644 : // Create the numbering style for these rules
645 128 : OUString sNumRulesName = aPropNameSupplier.GetName( PROP_NUMBERING_RULES );
646 128 : 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 142 : }
661 :
662 142 : }
663 :
664 : //------------------------------------- NumberingManager implementation
665 :
666 :
667 30 : 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 30 : m_xFactory( xFactory )
673 : {
674 30 : }
675 :
676 60 : ListsManager::~ListsManager( )
677 : {
678 60 : }
679 :
680 2572 : void ListsManager::lcl_attribute( Id nName, Value& rVal )
681 : {
682 : OSL_ENSURE( m_pCurrentDefinition.get(), "current entry has to be set here");
683 2572 : if(!m_pCurrentDefinition.get())
684 2572 : return ;
685 2572 : int nIntValue = rVal.getInt();
686 :
687 2572 : ListLevel::Pointer pCurrentLvl = m_pCurrentDefinition->GetCurrentLevel( );
688 :
689 :
690 2572 : 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 434 : if(pCurrentLvl.get())
704 430 : pCurrentLvl->SetBulletChar( rVal.getString() );
705 : }
706 434 : 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 40 : if ( pCurrentLvl.get( ) )
716 32 : pCurrentLvl->SetValue( nName, sal_Int32( nIntValue ) );
717 40 : 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 118 : m_pCurrentDefinition->SetId( rVal.getString().toInt32( ) );
723 118 : break;
724 : case NS_rtf::LN_LSID:
725 18 : m_pCurrentDefinition->SetId( nIntValue );
726 18 : 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 88 : sal_Int32 nVal = rVal.getString().toInt32();
749 88 : m_pCurrentDefinition->SetId( nVal );
750 : }
751 88 : break;
752 : case NS_ooxml::LN_CT_Ind_left:
753 370 : pCurrentLvl->Insert(
754 740 : PROP_INDENT_AT, true, uno::makeAny( ConversionHelper::convertTwipToMM100( nIntValue ) ));
755 370 : break;
756 : case NS_ooxml::LN_CT_Ind_hanging:
757 352 : pCurrentLvl->Insert(
758 704 : PROP_FIRST_LINE_INDENT, true, uno::makeAny( - ConversionHelper::convertTwipToMM100( nIntValue ) ));
759 352 : break;
760 : case NS_ooxml::LN_CT_Ind_firstLine:
761 18 : pCurrentLvl->Insert(
762 36 : PROP_FIRST_LINE_INDENT, true, uno::makeAny( ConversionHelper::convertTwipToMM100( nIntValue ) ));
763 18 : 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 726 : break;
768 : case NS_ooxml::LN_CT_TabStop_pos:
769 : {
770 : //no paragraph attributes in ListTable char style sheets
771 204 : if ( pCurrentLvl.get( ) )
772 : pCurrentLvl->SetValue( nName,
773 204 : ConversionHelper::convertTwipToMM100( nIntValue ) );
774 : }
775 204 : break;
776 : case NS_ooxml::LN_CT_TabStop_val:
777 : {
778 : // TODO Do something of that
779 : }
780 204 : 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 2572 : }
796 : }
797 :
798 4382 : void ListsManager::lcl_sprm( Sprm& rSprm )
799 : {
800 : //fill the attributes of the style sheet
801 4382 : sal_uInt32 nSprmId = rSprm.getId();
802 4382 : if( m_pCurrentDefinition.get() ||
803 : nSprmId == NS_ooxml::LN_CT_Numbering_abstractNum ||
804 : nSprmId == NS_ooxml::LN_CT_Numbering_num )
805 : {
806 4382 : sal_Int32 nIntValue = rSprm.getValue()->getInt();
807 4382 : switch( nSprmId )
808 : {
809 : case NS_ooxml::LN_CT_Numbering_abstractNum:
810 : {
811 88 : writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
812 88 : 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 88 : m_pCurrentDefinition.reset( new AbstractListDef );
817 88 : pProperties->resolve( *this );
818 : //append it to the table
819 88 : m_aAbstractLists.push_back( m_pCurrentDefinition );
820 88 : m_pCurrentDefinition = AbstractListDef::Pointer();
821 88 : }
822 : }
823 88 : break;
824 : case NS_ooxml::LN_CT_Numbering_num:
825 : {
826 136 : writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
827 136 : if(pProperties.get())
828 : {
829 : // Create a new list entry
830 : OSL_ENSURE( !m_pCurrentDefinition.get(), "current entry has to be NULL here");
831 136 : ListDef::Pointer listDef( new ListDef );
832 136 : m_pCurrentDefinition = listDef;
833 136 : pProperties->resolve( *this );
834 : //append it to the table
835 136 : m_aLists.push_back( listDef );
836 :
837 136 : m_pCurrentDefinition = AbstractListDef::Pointer();
838 136 : }
839 : }
840 136 : break;
841 : case NS_ooxml::LN_CT_Num_abstractNumId:
842 : {
843 136 : sal_Int32 nAbstractNumId = rSprm.getValue()->getInt();
844 136 : ListDef* pListDef = dynamic_cast< ListDef* >( m_pCurrentDefinition.get( ) );
845 136 : if ( pListDef != NULL )
846 : {
847 : // The current def should be a ListDef
848 : pListDef->SetAbstractDefinition(
849 136 : GetAbstractList( nAbstractNumId ) );
850 : }
851 : }
852 136 : break;
853 : case NS_ooxml::LN_CT_AbstractNum_multiLevelType:
854 70 : break;
855 : case NS_rtf::LN_TPLC:
856 68 : m_pCurrentDefinition->SetValue( nSprmId, nIntValue );
857 68 : break;
858 : case NS_ooxml::LN_CT_AbstractNum_lvl:
859 : {
860 430 : m_pCurrentDefinition->AddLevel();
861 430 : writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
862 430 : if(pProperties.get())
863 430 : pProperties->resolve(*this);
864 : }
865 430 : 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 864 : if (m_pCurrentDefinition->GetCurrentLevel().get())
876 856 : m_pCurrentDefinition->GetCurrentLevel( )->SetValue( nSprmId, nIntValue );
877 864 : 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 638 : writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
899 638 : if(pProperties.get())
900 638 : pProperties->resolve(*this);
901 : }
902 638 : 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 836 : m_pCurrentDefinition->GetCurrentLevel( )->Insert(
920 1254 : PROP_ADJUST, true, uno::makeAny( aWWAlignments[ nIntValue ] ) );
921 418 : writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
922 : }
923 418 : 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 740 : writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
929 740 : if(pProperties.get())
930 740 : pProperties->resolve(*this);
931 : }
932 740 : break;
933 : case NS_ooxml::LN_CT_PPrBase_tabs:
934 : case NS_ooxml::LN_CT_Tabs_tab:
935 : {
936 408 : writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
937 408 : if(pProperties.get())
938 408 : pProperties->resolve(*this);
939 : }
940 408 : break;
941 : case NS_ooxml::LN_CT_Lvl_pStyle:
942 : {
943 46 : OUString sStyleName = rSprm.getValue( )->getString( );
944 46 : ListLevel::Pointer pLevel = m_pCurrentDefinition->GetCurrentLevel( );
945 46 : StyleSheetTablePtr pStylesTable = m_rDMapper.GetStyleSheetTable( );
946 46 : const StyleSheetEntryPtr pStyle = pStylesTable->FindStyleSheetByISTD( sStyleName );
947 46 : pLevel->SetParaStyle( pStyle );
948 : }
949 46 : 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 340 : if( m_pCurrentDefinition->GetCurrentLevel( ).get())
959 : {
960 252 : m_rDMapper.PushListProperties( m_pCurrentDefinition->GetCurrentLevel( ) );
961 252 : m_rDMapper.sprm( rSprm );
962 252 : m_rDMapper.PopListProperties();
963 : }
964 : }
965 : }
966 4382 : }
967 :
968 36 : void ListsManager::lcl_entry( int /* pos */,
969 : writerfilter::Reference<Properties>::Pointer_t ref )
970 : {
971 36 : if( m_rDMapper.IsOOXMLImport() || m_rDMapper.IsRTFImport() )
972 : {
973 36 : 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 36 : }
1000 :
1001 136 : AbstractListDef::Pointer ListsManager::GetAbstractList( sal_Int32 nId )
1002 : {
1003 136 : AbstractListDef::Pointer pAbstractList;
1004 :
1005 136 : int nLen = m_aAbstractLists.size( );
1006 136 : int i = 0;
1007 794 : while ( !pAbstractList.get( ) && i < nLen )
1008 : {
1009 522 : if ( m_aAbstractLists[i]->GetId( ) == nId )
1010 136 : pAbstractList = m_aAbstractLists[i];
1011 522 : i++;
1012 : }
1013 :
1014 136 : return pAbstractList;
1015 : }
1016 :
1017 98 : ListDef::Pointer ListsManager::GetList( sal_Int32 nId )
1018 : {
1019 98 : ListDef::Pointer pList;
1020 :
1021 98 : int nLen = m_aLists.size( );
1022 98 : int i = 0;
1023 326 : while ( !pList.get( ) && i < nLen )
1024 : {
1025 130 : if ( m_aLists[i]->GetId( ) == nId )
1026 52 : pList = m_aLists[i];
1027 130 : i++;
1028 : }
1029 :
1030 98 : return pList;
1031 : }
1032 :
1033 36 : void ListsManager::CreateNumberingRules( )
1034 : {
1035 : // Loop over the definitions
1036 36 : std::vector< ListDef::Pointer >::iterator listIt = m_aLists.begin( );
1037 178 : for ( ; listIt != m_aLists.end( ); ++listIt )
1038 : {
1039 142 : (*listIt)->CreateNumberingRules( m_rDMapper, m_xFactory );
1040 : }
1041 36 : }
1042 :
1043 30 : } }
1044 :
1045 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|