Update ooo320-m1
[ooovba.git] / xmloff / source / text / txtstyli.cxx
blob1e4dab709f0dbe5e66660b65713d08367834d97d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: txtstyli.cxx,v $
10 * $Revision: 1.38 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_xmloff.hxx"
33 #include <com/sun/star/frame/XModel.hpp>
34 #include <com/sun/star/style/XStyle.hpp>
35 #include <com/sun/star/container/XNameContainer.hpp>
36 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
37 #include <com/sun/star/style/ParagraphStyleCategory.hpp>
38 #ifndef _COM_SUN_STAR_DOCUMENT_XEVENTSSUPPLIER_HPP
39 #include <com/sun/star/document/XEventsSupplier.hpp>
40 #endif
41 #include <com/sun/star/beans/XMultiPropertySet.hpp>
42 #include "xmlnmspe.hxx"
43 #include <xmloff/xmltoken.hxx>
44 #ifndef _XMLOFF_FAMILIES_HXX
45 #include <xmloff/families.hxx>
46 #endif
47 #include "XMLTextPropertySetContext.hxx"
48 #include <xmloff/xmltkmap.hxx>
49 #include <xmloff/xmlimp.hxx>
50 #include <xmloff/xmluconv.hxx>
52 #ifndef _XMLOFF_TXTPRMAP_HXX
53 #include <xmloff/txtprmap.hxx>
54 #endif
55 #ifndef _XMLOFF_TXTSTYLI_HXX
56 #include <xmloff/txtstyli.hxx>
57 #endif
58 #include <xmloff/attrlist.hxx>
59 #include <xmloff/XMLEventsImportContext.hxx>
60 #include <tools/debug.hxx>
62 // STL includes
63 #include <algorithm>
64 #include <functional>
65 #include <utility>
66 #include <vector>
68 using ::rtl::OUString;
69 using ::rtl::OUStringBuffer;
71 using namespace ::std;
72 using namespace ::com::sun::star;
73 using namespace ::com::sun::star::uno;
74 using namespace ::com::sun::star::xml::sax;
75 using namespace ::com::sun::star::style;
76 using namespace ::com::sun::star::frame;
77 using namespace ::com::sun::star::beans;
78 using namespace ::com::sun::star::lang;
79 using namespace ::com::sun::star::container;
80 //using namespace ::com::sun::star::text;
81 using namespace ::xmloff::token;
83 static __FAR_DATA SvXMLEnumMapEntry aCategoryMap[] =
85 { XML_TEXT, ParagraphStyleCategory::TEXT },
86 { XML_CHAPTER, ParagraphStyleCategory::CHAPTER },
87 { XML_LIST, ParagraphStyleCategory::LIST },
88 { XML_INDEX, ParagraphStyleCategory::INDEX },
89 { XML_EXTRA, ParagraphStyleCategory::EXTRA },
90 { XML_HTML, ParagraphStyleCategory::HTML },
91 { XML_TOKEN_INVALID, 0 }
94 void XMLTextStyleContext::SetAttribute( sal_uInt16 nPrefixKey,
95 const OUString& rLocalName,
96 const OUString& rValue )
98 if( XML_NAMESPACE_STYLE == nPrefixKey )
100 // TODO: use a map here
101 if( IsXMLToken( rLocalName, XML_AUTO_UPDATE ) )
103 if( IsXMLToken( rValue, XML_TRUE ) )
104 bAutoUpdate = sal_True;
106 else if( IsXMLToken( rLocalName, XML_LIST_STYLE_NAME ) )
108 sListStyleName = rValue;
109 // --> OD 2006-09-21 #i69523#
110 mbListStyleSet = sal_True;
111 // <--
113 else if( IsXMLToken( rLocalName, XML_MASTER_PAGE_NAME ) )
115 sMasterPageName = rValue;
116 bHasMasterPageName = sal_True;
118 else if( IsXMLToken( rLocalName, XML_DATA_STYLE_NAME ) )
120 sDataStyleName = rValue;
122 else if( IsXMLToken( rLocalName, XML_CLASS ) )
124 sCategoryVal = rValue;
126 else if( IsXMLToken( rLocalName, XML_DEFAULT_OUTLINE_LEVEL ) )
128 sal_Int32 nTmp;
129 if( SvXMLUnitConverter::convertNumber( nTmp, rValue ) &&
130 // nTmp > 0 && nTmp < 256 ) //#outline level, removed by zhaojianwei
131 0 <= nTmp && nTmp <= 10 ) //<-end,add by zhaojianwei
132 nOutlineLevel = static_cast< sal_Int8 >( nTmp );
134 else
136 XMLPropStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue );
139 else
141 XMLPropStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue );
145 TYPEINIT1( XMLTextStyleContext, XMLPropStyleContext );
147 XMLTextStyleContext::XMLTextStyleContext( SvXMLImport& rImport,
148 sal_uInt16 nPrfx, const OUString& rLName,
149 const Reference< XAttributeList > & xAttrList,
150 SvXMLStylesContext& rStyles, sal_uInt16 nFamily,
151 sal_Bool bDefaultStyle )
152 : XMLPropStyleContext( rImport, nPrfx, rLName, xAttrList, rStyles, nFamily, bDefaultStyle )
153 , sIsAutoUpdate( RTL_CONSTASCII_USTRINGPARAM( "IsAutoUpdate" ) )
154 , sCategory( RTL_CONSTASCII_USTRINGPARAM( "Category" ) )
155 , sNumberingStyleName( RTL_CONSTASCII_USTRINGPARAM( "NumberingStyleName" ) )
156 , sOutlineLevel(RTL_CONSTASCII_USTRINGPARAM( "OutlineLevel" ) )//#outline level,add by zhaojianwei
157 , sDropCapCharStyleName( RTL_CONSTASCII_USTRINGPARAM( "DropCapCharStyleName" ) )
158 , sPageDescName( RTL_CONSTASCII_USTRINGPARAM( "PageDescName" ) )
159 //, nOutlineLevel( 0 ) // removed by zhaojianwei
160 , nOutlineLevel( -1 ) //<-end, add by zhaojianwei
161 , bAutoUpdate( sal_False )
162 , bHasMasterPageName( sal_False )
163 , bHasCombinedCharactersLetter( sal_False )
164 // --> OD 2006-09-21 #i69523#
165 , mbListStyleSet( sal_False )
166 // <--
167 , pEventContext( NULL )
171 XMLTextStyleContext::~XMLTextStyleContext()
175 SvXMLImportContext *XMLTextStyleContext::CreateChildContext(
176 sal_uInt16 nPrefix,
177 const OUString& rLocalName,
178 const Reference< XAttributeList > & xAttrList )
180 SvXMLImportContext *pContext = 0;
182 if( XML_NAMESPACE_STYLE == nPrefix )
184 sal_uInt32 nFamily = 0;
185 if( IsXMLToken( rLocalName, XML_TEXT_PROPERTIES ) )
186 nFamily = XML_TYPE_PROP_TEXT;
187 else if( IsXMLToken( rLocalName, XML_PARAGRAPH_PROPERTIES ) )
188 nFamily = XML_TYPE_PROP_PARAGRAPH;
189 else if( IsXMLToken( rLocalName, XML_SECTION_PROPERTIES ) )
190 nFamily = XML_TYPE_PROP_SECTION;
191 else if( IsDefaultStyle() && IsXMLToken( rLocalName, XML_TABLE_PROPERTIES ) )
192 nFamily = XML_TYPE_PROP_TABLE;
193 else if( IsDefaultStyle() && IsXMLToken( rLocalName, XML_TABLE_ROW_PROPERTIES ) )
194 nFamily = XML_TYPE_PROP_TABLE_ROW;
195 if( nFamily )
197 UniReference < SvXMLImportPropertyMapper > xImpPrMap =
198 GetStyles()->GetImportPropertyMapper( GetFamily() );
199 if( xImpPrMap.is() )
200 pContext = new XMLTextPropertySetContext( GetImport(), nPrefix,
201 rLocalName, xAttrList,
202 nFamily,
203 GetProperties(),
204 xImpPrMap,
205 sDropCapTextStyleName );
208 else if ( (XML_NAMESPACE_OFFICE == nPrefix) &&
209 IsXMLToken( rLocalName, XML_EVENT_LISTENERS ) )
211 // create and remember events import context
212 // (for delayed processing of events)
213 pEventContext = new XMLEventsImportContext( GetImport(), nPrefix,
214 rLocalName);
215 pEventContext->AddRef();
216 pContext = pEventContext;
219 if( !pContext )
220 pContext = XMLPropStyleContext::CreateChildContext( nPrefix, rLocalName,
221 xAttrList );
223 return pContext;
226 void XMLTextStyleContext::CreateAndInsert( sal_Bool bOverwrite )
228 XMLPropStyleContext::CreateAndInsert( bOverwrite );
229 Reference < XStyle > xStyle = GetStyle();
230 if( !xStyle.is() || !(bOverwrite || IsNew()) )
231 return;
233 Reference < XPropertySet > xPropSet( xStyle, UNO_QUERY );
234 Reference< XPropertySetInfo > xPropSetInfo =
235 xPropSet->getPropertySetInfo();
236 if( xPropSetInfo->hasPropertyByName( sIsAutoUpdate ) )
238 Any aAny;
239 sal_Bool bTmp = bAutoUpdate;
240 aAny.setValue( &bTmp, ::getBooleanCppuType() );
241 xPropSet->setPropertyValue( sIsAutoUpdate, aAny );
244 sal_uInt16 nCategory = ParagraphStyleCategory::TEXT;
245 if( XML_STYLE_FAMILY_TEXT_PARAGRAPH == GetFamily() &&
246 sCategoryVal.getLength() && xStyle->isUserDefined() &&
247 xPropSetInfo->hasPropertyByName( sCategory ) &&
248 SvXMLUnitConverter::convertEnum( nCategory, sCategoryVal, aCategoryMap ) )
250 Any aAny;
251 aAny <<= (sal_Int16)nCategory;
252 xPropSet->setPropertyValue( sCategory, aAny );
255 // tell the style about it's events (if applicable)
256 if (NULL != pEventContext)
258 // set event suppplier and release reference to context
259 Reference<document::XEventsSupplier> xEventsSupplier(xStyle,UNO_QUERY);
260 pEventContext->SetEvents(xEventsSupplier);
261 pEventContext->ReleaseRef();
264 // --> OD 2006-10-12 #i69629#
265 if ( nOutlineLevel > 0 )
267 GetImport().GetTextImport()->AddOutlineStyleCandidate( nOutlineLevel,
268 GetDisplayName() );
270 // <--
273 void XMLTextStyleContext::SetDefaults( )
275 if( ( GetFamily() == XML_STYLE_FAMILY_TEXT_PARAGRAPH ) ||
276 ( GetFamily() == XML_STYLE_FAMILY_TABLE_TABLE ) ||
277 ( GetFamily() == XML_STYLE_FAMILY_TABLE_ROW ) )
279 Reference < XMultiServiceFactory > xFactory ( GetImport().GetModel(), UNO_QUERY);
280 if (xFactory.is())
282 Reference < XInterface > xInt = xFactory->createInstance (
283 OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.text.Defaults" ) ) );
284 Reference < XPropertySet > xProperties ( xInt, UNO_QUERY );
285 if ( xProperties.is() )
286 FillPropertySet ( xProperties );
291 void XMLTextStyleContext::Finish( sal_Bool bOverwrite )
293 XMLPropStyleContext::Finish( bOverwrite );
295 Reference < XStyle > xStyle = GetStyle();
296 // --> OD 2006-09-21 #i69523#
297 // consider set empty list style
298 // if ( !( sListStyleName.getLength() ||
299 if ( !( mbListStyleSet ||
300 nOutlineLevel >= 0 || //#outline level,add by zhaojianwei
301 sDropCapTextStyleName.getLength() ||
302 bHasMasterPageName ) ||
303 !xStyle.is() ||
304 !( bOverwrite || IsNew() ) )
305 return;
306 // <--
308 Reference < XPropertySet > xPropSet( xStyle, UNO_QUERY );
309 Reference< XPropertySetInfo > xPropSetInfo =
310 xPropSet->getPropertySetInfo();
312 //#outline level,add by zhaojianwei
313 if( xPropSetInfo->hasPropertyByName( sOutlineLevel ))
315 Any aAny;
316 if( nOutlineLevel >= 0 )
318 aAny <<= nOutlineLevel;
319 xPropSet->setPropertyValue( sOutlineLevel, aAny );
322 //<-end,zhaojianwei
325 // --> OD 2006-09-21 #i69523#
326 // consider set empty list style
327 // if( sListStyleName.getLength() )
328 if ( mbListStyleSet &&
329 xPropSetInfo->hasPropertyByName( sNumberingStyleName ) )
331 // --> OD 2006-10-12 #i70223#
332 // Only for text document from version prior OOo 2.1 resp. SO 8 PU5:
333 // - Do not apply list style, if paragraph style has a default outline
334 // level > 0 and thus, will be assigned to the corresponding list
335 // level of the outline style.
336 bool bApplyListStyle( true );
337 if ( nOutlineLevel > 0 )
339 // --> OD 2007-12-19 #152540#
340 if ( GetImport().IsTextDocInOOoFileFormat() )
342 bApplyListStyle = false;
344 else
346 sal_Int32 nUPD( 0 );
347 sal_Int32 nBuild( 0 );
348 // --> OD 2008-03-19 #i86058#
349 // check explicitly on certain versions
350 if ( GetImport().getBuildIds( nUPD, nBuild ) &&
351 ( ( nUPD == 641 ) || ( nUPD == 645 ) || // prior OOo 2.0
352 ( nUPD == 680 && nBuild <= 9073 ) ) ) // OOo 2.0 - OOo 2.0.4
354 bApplyListStyle = false;
356 // <--
358 // <--
361 if ( bApplyListStyle )
363 if ( !sListStyleName.getLength() )
365 Any aAny;
366 aAny <<= sListStyleName /* empty string */;
367 xPropSet->setPropertyValue( sNumberingStyleName, aAny );
369 else
371 // change list style name to display name
372 OUString sDisplayListStyleName(
373 GetImport().GetStyleDisplayName( XML_STYLE_FAMILY_TEXT_LIST,
374 sListStyleName ) );
375 // The families container must exist
376 const Reference < XNameContainer >& rNumStyles =
377 GetImport().GetTextImport()->GetNumberingStyles();
378 // if( rNumStyles.is() && rNumStyles->hasByName( sDisplayListStyleName ) &&
379 // xPropSetInfo->hasPropertyByName( sNumberingStyleName ) )
380 if ( rNumStyles.is() &&
381 rNumStyles->hasByName( sDisplayListStyleName ) )
383 Any aAny;
384 aAny <<= sDisplayListStyleName;
385 xPropSet->setPropertyValue( sNumberingStyleName, aAny );
389 // <--
391 // <--
393 if( sDropCapTextStyleName.getLength() )
395 // change list style name to display name
396 OUString sDisplayDropCapTextStyleName(
397 GetImport().GetStyleDisplayName( XML_STYLE_FAMILY_TEXT_TEXT,
398 sDropCapTextStyleName ) );
399 // The families cointaner must exist
400 const Reference < XNameContainer >& rTextStyles =
401 GetImport().GetTextImport()->GetTextStyles();
402 if( rTextStyles.is() &&
403 rTextStyles->hasByName( sDisplayDropCapTextStyleName ) &&
404 xPropSetInfo->hasPropertyByName( sDropCapCharStyleName ) )
406 Any aAny;
407 aAny <<= sDisplayDropCapTextStyleName;
408 xPropSet->setPropertyValue( sDropCapCharStyleName, aAny );
412 if( bHasMasterPageName )
414 OUString sDisplayName(
415 GetImport().GetStyleDisplayName(
416 XML_STYLE_FAMILY_MASTER_PAGE, sMasterPageName ) );
417 // The families cointaner must exist
418 const Reference < XNameContainer >& rPageStyles =
419 GetImport().GetTextImport()->GetPageStyles();
420 if( ( !sDisplayName.getLength() ||
421 (rPageStyles.is() &&
422 rPageStyles->hasByName( sDisplayName )) ) &&
423 xPropSetInfo->hasPropertyByName( sPageDescName ) )
425 Any aAny;
426 aAny <<= sDisplayName;
427 xPropSet->setPropertyValue( sPageDescName, aAny );
432 void XMLTextStyleContext::FillPropertySet(
433 const Reference<XPropertySet > & rPropSet )
435 // imitate the FillPropertySet of the super class, so we get a chance to
436 // catch the combined characters attribute
438 // imitate XMLPropStyleContext::FillPropertySet(...)
439 UniReference < SvXMLImportPropertyMapper > xImpPrMap =
440 ((SvXMLStylesContext *)GetStyles())->GetImportPropertyMapper(GetFamily());
441 DBG_ASSERT( xImpPrMap.is(), "Where is the import prop mapper?" );
442 if( xImpPrMap.is() )
445 // imitate SvXMLImportPropertyMapper::FillPropertySet(...)
447 // The reason for this is that we have no other way to
448 // efficiently intercept the value of combined characters. To
449 // get that value, we could iterate through the map once more,
450 // but instead we chose to insert the code into this
451 // iteration. I haven't been able to come up with a much more
452 // intelligent solution.
455 struct _ContextID_Index_Pair aContextIDs[] =
457 { CTF_COMBINED_CHARACTERS_FIELD, -1 },
458 { CTF_KEEP_TOGETHER, -1 },
459 { CTF_BORDER_MODEL, -1 },
460 { CTF_TEXT_DISPLAY, -1 },
461 { CTF_FONTFAMILYNAME, -1 },
462 { CTF_FONTFAMILYNAME_CJK, -1 },
463 { CTF_FONTFAMILYNAME_CTL, -1 },
464 { -1, -1 }
467 bool bAutomatic = false;
468 if( ((SvXMLStylesContext *)GetStyles())->IsAutomaticStyle() &&
469 ( GetFamily() == XML_STYLE_FAMILY_TEXT_TEXT || GetFamily() == XML_STYLE_FAMILY_TEXT_PARAGRAPH ) )
471 bAutomatic = true;
472 if( GetAutoName().getLength() )
474 OUString sAutoProp = ( GetFamily() == XML_STYLE_FAMILY_TEXT_TEXT ) ?
475 OUString( RTL_CONSTASCII_USTRINGPARAM("CharAutoStyleName") ):
476 OUString( RTL_CONSTASCII_USTRINGPARAM("ParaAutoStyleName") );
479 rPropSet->setPropertyValue( sAutoProp, makeAny(GetAutoName()) );
481 catch( const RuntimeException& ) { throw; }
482 catch( const Exception& )
484 bAutomatic = false;
488 if( bAutomatic )
489 xImpPrMap->CheckSpecialContext( GetProperties(), rPropSet, aContextIDs );
490 else
491 xImpPrMap->FillPropertySet( GetProperties(), rPropSet, aContextIDs );
493 // have we found a combined characters
494 sal_Int32 nIndex = aContextIDs[0].nIndex;
495 if ( nIndex != -1 )
497 Any& rAny = GetProperties()[nIndex].maValue;
498 sal_Bool bVal = *(sal_Bool*)rAny.getValue();
499 bHasCombinedCharactersLetter = bVal;
502 // get property set info
503 Reference< XPropertySetInfo > xInfo;
505 // keep-together: the application default is different from
506 // the file format default. Hence, if we always set this
507 // value; if we didn't find one, we'll set to false, the file
508 // format default.
509 // border-model: same
510 if( IsDefaultStyle() && GetFamily() == XML_STYLE_FAMILY_TABLE_ROW )
512 OUString sIsSplitAllowed =
513 OUString( RTL_CONSTASCII_USTRINGPARAM( "IsSplitAllowed" ) );
514 DBG_ASSERT( rPropSet->getPropertySetInfo()->hasPropertyByName( sIsSplitAllowed ),
515 "property missing?" );
516 rPropSet->setPropertyValue( sIsSplitAllowed,
517 (aContextIDs[1].nIndex == -1)
518 ? makeAny( false )
519 : GetProperties()[aContextIDs[1].nIndex].maValue );
522 if( IsDefaultStyle() && GetFamily() == XML_STYLE_FAMILY_TABLE_TABLE )
524 OUString sCollapsingBorders(
525 OUString( RTL_CONSTASCII_USTRINGPARAM( "CollapsingBorders" ) ) );
526 DBG_ASSERT( rPropSet->getPropertySetInfo()->hasPropertyByName( sCollapsingBorders ),
527 "property missing?" );
528 rPropSet->setPropertyValue( sCollapsingBorders,
529 (aContextIDs[2].nIndex == -1)
530 ? makeAny( false )
531 : GetProperties()[aContextIDs[2].nIndex].maValue );
535 // check for StarBats and StarMath fonts
537 if (!xInfo.is())
538 xInfo.set(rPropSet->getPropertySetInfo());
540 // iterate over aContextIDs entries 3..6
541 for ( sal_Int32 i = 3; i < 7; i++ )
543 nIndex = aContextIDs[i].nIndex;
544 if ( nIndex != -1 )
546 // Found!
547 struct XMLPropertyState& rState = GetProperties()[nIndex];
548 Any rAny = rState.maValue;
549 sal_Int32 nMapperIndex = rState.mnIndex;
551 // Now check for font name in rState and set corrected value,
552 // if necessary.
553 OUString sFontName;
554 rAny >>= sFontName;
555 if ( sFontName.getLength() > 0 )
557 OUString sStarBats( RTL_CONSTASCII_USTRINGPARAM("StarBats" ) );
558 OUString sStarMath( RTL_CONSTASCII_USTRINGPARAM("StarMath" ) );
559 if ( sFontName.equalsIgnoreAsciiCase( sStarBats ) ||
560 sFontName.equalsIgnoreAsciiCase( sStarMath ) )
562 // construct new value
563 sFontName = OUString(
564 RTL_CONSTASCII_USTRINGPARAM("StarSymbol") );
565 Any aAny( rAny );
566 aAny <<= sFontName;
568 // get property set mapper
569 UniReference<XMLPropertySetMapper> rPropMapper =
570 xImpPrMap->getPropertySetMapper();
572 // set property
573 OUString rPropertyName(
574 rPropMapper->GetEntryAPIName(nMapperIndex) );
575 if( !xInfo.is() )
576 xInfo = rPropSet->getPropertySetInfo();
577 if ( xInfo->hasPropertyByName( rPropertyName ) )
579 rPropSet->setPropertyValue( rPropertyName, aAny );
582 // else: "normal" style name -> no correction is necessary
584 // else: no style name found -> illegal value -> ignore