1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "XMLTextPropertySetContext.hxx"
22 #include "xmloff/xmlnmspe.hxx"
23 #include "xmloff/XMLEventsImportContext.hxx"
24 #include "xmloff/attrlist.hxx"
25 #include "xmloff/families.hxx"
26 #include "xmloff/txtprmap.hxx"
27 #include "xmloff/txtstyli.hxx"
28 #include "xmloff/xmlimp.hxx"
29 #include "xmloff/xmltkmap.hxx"
30 #include "xmloff/xmltoken.hxx"
31 #include "xmloff/xmluconv.hxx"
33 #include <com/sun/star/beans/XMultiPropertySet.hpp>
34 #include <com/sun/star/container/XNameContainer.hpp>
35 #include <com/sun/star/document/XEventsSupplier.hpp>
36 #include <com/sun/star/frame/XModel.hpp>
37 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
38 #include <com/sun/star/style/ParagraphStyleCategory.hpp>
39 #include <com/sun/star/style/XStyle.hpp>
41 #include <sax/tools/converter.hxx>
43 #include <tools/debug.hxx>
44 #include <tools/diagnose_ex.h>
53 using namespace ::std
;
54 using namespace ::com::sun::star
;
55 using namespace ::com::sun::star::uno
;
56 using namespace ::com::sun::star::xml::sax
;
57 using namespace ::com::sun::star::style
;
58 using namespace ::com::sun::star::frame
;
59 using namespace ::com::sun::star::beans
;
60 using namespace ::com::sun::star::lang
;
61 using namespace ::com::sun::star::container
;
62 using namespace ::xmloff::token
;
64 static SvXMLEnumMapEntry aCategoryMap
[] =
66 { XML_TEXT
, ParagraphStyleCategory::TEXT
},
67 { XML_CHAPTER
, ParagraphStyleCategory::CHAPTER
},
68 { XML_LIST
, ParagraphStyleCategory::LIST
},
69 { XML_INDEX
, ParagraphStyleCategory::INDEX
},
70 { XML_EXTRA
, ParagraphStyleCategory::EXTRA
},
71 { XML_HTML
, ParagraphStyleCategory::HTML
},
72 { XML_TOKEN_INVALID
, 0 }
75 void XMLTextStyleContext::SetAttribute( sal_uInt16 nPrefixKey
,
76 const OUString
& rLocalName
,
77 const OUString
& rValue
)
79 if( XML_NAMESPACE_STYLE
== nPrefixKey
)
81 // TODO: use a map here
82 if( IsXMLToken( rLocalName
, XML_AUTO_UPDATE
) )
84 if( IsXMLToken( rValue
, XML_TRUE
) )
85 bAutoUpdate
= sal_True
;
87 else if( IsXMLToken( rLocalName
, XML_LIST_STYLE_NAME
) )
89 sListStyleName
= rValue
;
90 // Inherited paragraph style lost information about unset numbering (#i69523#)
91 mbListStyleSet
= sal_True
;
93 else if( IsXMLToken( rLocalName
, XML_MASTER_PAGE_NAME
) )
95 sMasterPageName
= rValue
;
96 bHasMasterPageName
= sal_True
;
98 else if( IsXMLToken( rLocalName
, XML_DATA_STYLE_NAME
) )
100 sDataStyleName
= rValue
;
102 else if( IsXMLToken( rLocalName
, XML_CLASS
) )
104 sCategoryVal
= rValue
;
106 else if( IsXMLToken( rLocalName
, XML_DEFAULT_OUTLINE_LEVEL
) )
109 if (::sax::Converter::convertNumber( nTmp
, rValue
) &&
110 0 <= nTmp
&& nTmp
<= 10 )
111 nOutlineLevel
= static_cast< sal_Int8
>( nTmp
);
115 XMLPropStyleContext::SetAttribute( nPrefixKey
, rLocalName
, rValue
);
120 XMLPropStyleContext::SetAttribute( nPrefixKey
, rLocalName
, rValue
);
124 TYPEINIT1( XMLTextStyleContext
, XMLPropStyleContext
);
126 XMLTextStyleContext::XMLTextStyleContext( SvXMLImport
& rImport
,
127 sal_uInt16 nPrfx
, const OUString
& rLName
,
128 const Reference
< XAttributeList
> & xAttrList
,
129 SvXMLStylesContext
& rStyles
, sal_uInt16 nFamily
,
130 sal_Bool bDefaultStyle
)
131 : XMLPropStyleContext( rImport
, nPrfx
, rLName
, xAttrList
, rStyles
, nFamily
, bDefaultStyle
)
132 , sIsAutoUpdate( "IsAutoUpdate" )
133 , sCategory( "Category" )
134 , sNumberingStyleName( "NumberingStyleName" )
135 , sOutlineLevel("OutlineLevel" )
136 , sDropCapCharStyleName( "DropCapCharStyleName" )
137 , sPageDescName( "PageDescName" )
138 , nOutlineLevel( -1 )
139 , bAutoUpdate( sal_False
)
140 , bHasMasterPageName( sal_False
)
141 , bHasCombinedCharactersLetter( sal_False
)
142 // Inherited paragraph style lost information about unset numbering (#i69523#)
143 , mbListStyleSet( sal_False
)
144 , pEventContext( NULL
)
148 XMLTextStyleContext::~XMLTextStyleContext()
152 SvXMLImportContext
*XMLTextStyleContext::CreateChildContext(
154 const OUString
& rLocalName
,
155 const Reference
< XAttributeList
> & xAttrList
)
157 SvXMLImportContext
*pContext
= 0;
159 if( XML_NAMESPACE_STYLE
== nPrefix
)
161 sal_uInt32 nFamily
= 0;
162 if( IsXMLToken( rLocalName
, XML_TEXT_PROPERTIES
) )
163 nFamily
= XML_TYPE_PROP_TEXT
;
164 else if( IsXMLToken( rLocalName
, XML_PARAGRAPH_PROPERTIES
) )
165 nFamily
= XML_TYPE_PROP_PARAGRAPH
;
166 else if( IsXMLToken( rLocalName
, XML_SECTION_PROPERTIES
) )
167 nFamily
= XML_TYPE_PROP_SECTION
;
168 else if( IsDefaultStyle() && IsXMLToken( rLocalName
, XML_TABLE_PROPERTIES
) )
169 nFamily
= XML_TYPE_PROP_TABLE
;
170 else if( IsDefaultStyle() && IsXMLToken( rLocalName
, XML_TABLE_ROW_PROPERTIES
) )
171 nFamily
= XML_TYPE_PROP_TABLE_ROW
;
174 UniReference
< SvXMLImportPropertyMapper
> xImpPrMap
=
175 GetStyles()->GetImportPropertyMapper( GetFamily() );
177 pContext
= new XMLTextPropertySetContext( GetImport(), nPrefix
,
178 rLocalName
, xAttrList
,
182 sDropCapTextStyleName
);
185 else if ( (XML_NAMESPACE_OFFICE
== nPrefix
) &&
186 IsXMLToken( rLocalName
, XML_EVENT_LISTENERS
) )
188 // create and remember events import context
189 // (for delayed processing of events)
190 pEventContext
= new XMLEventsImportContext( GetImport(), nPrefix
,
192 pEventContext
->AddRef();
193 pContext
= pEventContext
;
197 pContext
= XMLPropStyleContext::CreateChildContext( nPrefix
, rLocalName
,
203 void XMLTextStyleContext::CreateAndInsert( sal_Bool bOverwrite
)
205 XMLPropStyleContext::CreateAndInsert( bOverwrite
);
206 Reference
< XStyle
> xStyle
= GetStyle();
207 if( !xStyle
.is() || !(bOverwrite
|| IsNew()) )
210 Reference
< XPropertySet
> xPropSet( xStyle
, UNO_QUERY
);
211 Reference
< XPropertySetInfo
> xPropSetInfo
=
212 xPropSet
->getPropertySetInfo();
213 if( xPropSetInfo
->hasPropertyByName( sIsAutoUpdate
) )
216 sal_Bool bTmp
= bAutoUpdate
;
217 aAny
.setValue( &bTmp
, ::getBooleanCppuType() );
218 xPropSet
->setPropertyValue( sIsAutoUpdate
, aAny
);
221 sal_uInt16 nCategory
= ParagraphStyleCategory::TEXT
;
222 if( XML_STYLE_FAMILY_TEXT_PARAGRAPH
== GetFamily() &&
223 !sCategoryVal
.isEmpty() && xStyle
->isUserDefined() &&
224 xPropSetInfo
->hasPropertyByName( sCategory
) &&
225 SvXMLUnitConverter::convertEnum( nCategory
, sCategoryVal
, aCategoryMap
) )
228 aAny
<<= (sal_Int16
)nCategory
;
229 xPropSet
->setPropertyValue( sCategory
, aAny
);
232 // tell the style about it's events (if applicable)
233 if (NULL
!= pEventContext
)
235 // set event suppplier and release reference to context
236 Reference
<document::XEventsSupplier
> xEventsSupplier(xStyle
,UNO_QUERY
);
237 pEventContext
->SetEvents(xEventsSupplier
);
238 pEventContext
->ReleaseRef();
241 // XML import: reconstrution of assignment of paragraph style to outline levels (#i69629#)
242 if ( nOutlineLevel
> 0 )
244 GetImport().GetTextImport()->AddOutlineStyleCandidate( nOutlineLevel
,
249 void XMLTextStyleContext::SetDefaults( )
251 if( ( GetFamily() == XML_STYLE_FAMILY_TEXT_PARAGRAPH
) ||
252 ( GetFamily() == XML_STYLE_FAMILY_TABLE_TABLE
) ||
253 ( GetFamily() == XML_STYLE_FAMILY_TABLE_ROW
) )
255 Reference
< XMultiServiceFactory
> xFactory ( GetImport().GetModel(), UNO_QUERY
);
258 Reference
< XInterface
> xInt
= xFactory
->createInstance (
259 OUString ( "com.sun.star.text.Defaults" ) );
260 Reference
< XPropertySet
> xProperties ( xInt
, UNO_QUERY
);
261 if ( xProperties
.is() )
262 FillPropertySet ( xProperties
);
267 void XMLTextStyleContext::Finish( sal_Bool bOverwrite
)
269 XMLPropStyleContext::Finish( bOverwrite
);
271 Reference
< XStyle
> xStyle
= GetStyle();
272 // Consider set empty list style (#i69523#)
273 if ( !( mbListStyleSet
||
274 nOutlineLevel
>= 0 ||
275 !sDropCapTextStyleName
.isEmpty() ||
276 bHasMasterPageName
) ||
278 !( bOverwrite
|| IsNew() ) )
281 Reference
< XPropertySet
> xPropSet( xStyle
, UNO_QUERY
);
282 Reference
< XPropertySetInfo
> xPropSetInfo
=
283 xPropSet
->getPropertySetInfo();
285 if( xPropSetInfo
->hasPropertyByName( sOutlineLevel
))
288 if( nOutlineLevel
>= 0 )
290 aAny
<<= nOutlineLevel
;
291 xPropSet
->setPropertyValue( sOutlineLevel
, aAny
);
295 // Consider set empty list style (#i69523#)
296 if ( mbListStyleSet
&&
297 xPropSetInfo
->hasPropertyByName( sNumberingStyleName
) )
299 /* Only for text document from version prior OOo 2.1 resp. SO 8 PU5:
300 - Do not apply list style, if paragraph style has a default outline
301 level > 0 and thus, will be assigned to the corresponding list
302 level of the outline style. (#i70223#)
304 bool bApplyListStyle( true );
305 if ( nOutlineLevel
> 0 )
307 if ( GetImport().IsTextDocInOOoFileFormat() )
309 bApplyListStyle
= false;
314 sal_Int32
nBuild( 0 );
315 // Check explicitly on certain versions (#i86058#)
316 if ( GetImport().getBuildIds( nUPD
, nBuild
) &&
317 ( ( nUPD
== 641 ) || ( nUPD
== 645 ) || // prior OOo 2.0
318 ( nUPD
== 680 && nBuild
<= 9073 ) ) ) // OOo 2.0 - OOo 2.0.4
320 bApplyListStyle
= false;
325 if ( bApplyListStyle
)
327 if ( sListStyleName
.isEmpty() )
330 aAny
<<= sListStyleName
/* empty string */;
331 xPropSet
->setPropertyValue( sNumberingStyleName
, aAny
);
335 // change list style name to display name
336 OUString
sDisplayListStyleName(
337 GetImport().GetStyleDisplayName( XML_STYLE_FAMILY_TEXT_LIST
,
339 // The families container must exist
340 const Reference
< XNameContainer
>& rNumStyles
=
341 GetImport().GetTextImport()->GetNumberingStyles();
342 // if( rNumStyles.is() && rNumStyles->hasByName( sDisplayListStyleName ) &&
343 // xPropSetInfo->hasPropertyByName( sNumberingStyleName ) )
344 if ( rNumStyles
.is() &&
345 rNumStyles
->hasByName( sDisplayListStyleName
) )
348 aAny
<<= sDisplayListStyleName
;
349 xPropSet
->setPropertyValue( sNumberingStyleName
, aAny
);
355 if( !sDropCapTextStyleName
.isEmpty() )
357 // change list style name to display name
358 OUString
sDisplayDropCapTextStyleName(
359 GetImport().GetStyleDisplayName( XML_STYLE_FAMILY_TEXT_TEXT
,
360 sDropCapTextStyleName
) );
361 // The families cointaner must exist
362 const Reference
< XNameContainer
>& rTextStyles
=
363 GetImport().GetTextImport()->GetTextStyles();
364 if( rTextStyles
.is() &&
365 rTextStyles
->hasByName( sDisplayDropCapTextStyleName
) &&
366 xPropSetInfo
->hasPropertyByName( sDropCapCharStyleName
) )
369 aAny
<<= sDisplayDropCapTextStyleName
;
370 xPropSet
->setPropertyValue( sDropCapCharStyleName
, aAny
);
374 if( bHasMasterPageName
)
376 OUString
sDisplayName(
377 GetImport().GetStyleDisplayName(
378 XML_STYLE_FAMILY_MASTER_PAGE
, sMasterPageName
) );
379 // The families cointaner must exist
380 const Reference
< XNameContainer
>& rPageStyles
=
381 GetImport().GetTextImport()->GetPageStyles();
382 if( ( sDisplayName
.isEmpty() ||
384 rPageStyles
->hasByName( sDisplayName
)) ) &&
385 xPropSetInfo
->hasPropertyByName( sPageDescName
) )
388 aAny
<<= sDisplayName
;
389 xPropSet
->setPropertyValue( sPageDescName
, aAny
);
394 void XMLTextStyleContext::FillPropertySet(
395 const Reference
<XPropertySet
> & rPropSet
)
397 // imitate the FillPropertySet of the super class, so we get a chance to
398 // catch the combined characters attribute
400 // imitate XMLPropStyleContext::FillPropertySet(...)
401 UniReference
< SvXMLImportPropertyMapper
> xImpPrMap
=
402 ((SvXMLStylesContext
*)GetStyles())->GetImportPropertyMapper(GetFamily());
403 DBG_ASSERT( xImpPrMap
.is(), "Where is the import prop mapper?" );
407 // imitate SvXMLImportPropertyMapper::FillPropertySet(...)
409 // The reason for this is that we have no other way to
410 // efficiently intercept the value of combined characters. To
411 // get that value, we could iterate through the map once more,
412 // but instead we chose to insert the code into this
413 // iteration. I haven't been able to come up with a much more
414 // intelligent solution.
417 struct _ContextID_Index_Pair aContextIDs
[] =
419 { CTF_COMBINED_CHARACTERS_FIELD
, -1 },
420 { CTF_KEEP_TOGETHER
, -1 },
421 { CTF_BORDER_MODEL
, -1 },
422 { CTF_TEXT_DISPLAY
, -1 },
423 { CTF_FONTFAMILYNAME
, -1 },
424 { CTF_FONTFAMILYNAME_CJK
, -1 },
425 { CTF_FONTFAMILYNAME_CTL
, -1 },
429 // get property set info
430 Reference
< XPropertySetInfo
> xInfo( rPropSet
->getPropertySetInfo(), UNO_SET_THROW
);
432 bool bAutomatic
= false;
433 if( ((SvXMLStylesContext
*)GetStyles())->IsAutomaticStyle() &&
434 ( GetFamily() == XML_STYLE_FAMILY_TEXT_TEXT
|| GetFamily() == XML_STYLE_FAMILY_TEXT_PARAGRAPH
) )
437 if( !GetAutoName().isEmpty() )
439 OUString sAutoProp
= ( GetFamily() == XML_STYLE_FAMILY_TEXT_TEXT
) ?
440 OUString( "CharAutoStyleName" ):
441 OUString( "ParaAutoStyleName" );
444 if ( xInfo
->hasPropertyByName( sAutoProp
) )
445 rPropSet
->setPropertyValue( sAutoProp
, makeAny(GetAutoName()) );
449 catch( const RuntimeException
& ) { throw; }
450 catch( const Exception
& )
452 DBG_UNHANDLED_EXCEPTION();
458 xImpPrMap
->CheckSpecialContext( GetProperties(), rPropSet
, aContextIDs
);
460 xImpPrMap
->FillPropertySet( GetProperties(), rPropSet
, aContextIDs
);
462 // have we found a combined characters
463 sal_Int32 nIndex
= aContextIDs
[0].nIndex
;
466 Any
& rAny
= GetProperties()[nIndex
].maValue
;
467 sal_Bool bVal
= *(sal_Bool
*)rAny
.getValue();
468 bHasCombinedCharactersLetter
= bVal
;
471 // keep-together: the application default is different from
472 // the file format default. Hence, if we always set this
473 // value; if we didn't find one, we'll set to false, the file
475 // border-model: same
476 if( IsDefaultStyle() && GetFamily() == XML_STYLE_FAMILY_TABLE_ROW
)
478 OUString
sIsSplitAllowed( "IsSplitAllowed" );
479 DBG_ASSERT( rPropSet
->getPropertySetInfo()->hasPropertyByName( sIsSplitAllowed
),
480 "property missing?" );
481 rPropSet
->setPropertyValue( sIsSplitAllowed
,
482 (aContextIDs
[1].nIndex
== -1)
484 : GetProperties()[aContextIDs
[1].nIndex
].maValue
);
487 if( IsDefaultStyle() && GetFamily() == XML_STYLE_FAMILY_TABLE_TABLE
)
489 OUString
sCollapsingBorders("CollapsingBorders");
490 DBG_ASSERT( rPropSet
->getPropertySetInfo()->hasPropertyByName( sCollapsingBorders
),
491 "property missing?" );
492 rPropSet
->setPropertyValue( sCollapsingBorders
,
493 (aContextIDs
[2].nIndex
== -1)
495 : GetProperties()[aContextIDs
[2].nIndex
].maValue
);
499 // check for StarBats and StarMath fonts
501 // iterate over aContextIDs entries 3..6
502 for ( sal_Int32 i
= 3; i
< 7; i
++ )
504 nIndex
= aContextIDs
[i
].nIndex
;
508 struct XMLPropertyState
& rState
= GetProperties()[nIndex
];
509 Any rAny
= rState
.maValue
;
510 sal_Int32 nMapperIndex
= rState
.mnIndex
;
512 // Now check for font name in rState and set corrected value,
516 if ( !sFontName
.isEmpty() )
518 OUString
sStarBats( "StarBats" );
519 OUString
sStarMath( "StarMath" );
520 if ( sFontName
.equalsIgnoreAsciiCase( sStarBats
) ||
521 sFontName
.equalsIgnoreAsciiCase( sStarMath
) )
523 // construct new value
524 sFontName
= OUString("StarSymbol");
528 // get property set mapper
529 UniReference
<XMLPropertySetMapper
> rPropMapper
=
530 xImpPrMap
->getPropertySetMapper();
533 OUString
rPropertyName(
534 rPropMapper
->GetEntryAPIName(nMapperIndex
) );
535 if ( xInfo
->hasPropertyByName( rPropertyName
) )
537 rPropSet
->setPropertyValue( rPropertyName
, aAny
);
540 // else: "normal" style name -> no correction is necessary
542 // else: no style name found -> illegal value -> ignore
548 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */