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>
32 #include <xmloff/maptype.hxx>
34 #include <com/sun/star/beans/XMultiPropertySet.hpp>
35 #include <com/sun/star/container/XNameContainer.hpp>
36 #include <com/sun/star/document/XEventsSupplier.hpp>
37 #include <com/sun/star/frame/XModel.hpp>
38 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
39 #include <com/sun/star/style/ParagraphStyleCategory.hpp>
40 #include <com/sun/star/style/XStyle.hpp>
42 #include <sax/tools/converter.hxx>
44 #include <tools/debug.hxx>
45 #include <tools/diagnose_ex.h>
53 #include <xmlsdtypes.hxx>
54 #include <xmloff/xmlerror.hxx>
57 using namespace ::std
;
58 using namespace ::com::sun::star
;
59 using namespace ::com::sun::star::uno
;
60 using namespace ::com::sun::star::xml::sax
;
61 using namespace ::com::sun::star::style
;
62 using namespace ::com::sun::star::frame
;
63 using namespace ::com::sun::star::beans
;
64 using namespace ::com::sun::star::lang
;
65 using namespace ::com::sun::star::container
;
66 using namespace ::xmloff::token
;
68 static const SvXMLEnumMapEntry aCategoryMap
[] =
70 { XML_TEXT
, ParagraphStyleCategory::TEXT
},
71 { XML_CHAPTER
, ParagraphStyleCategory::CHAPTER
},
72 { XML_LIST
, ParagraphStyleCategory::LIST
},
73 { XML_INDEX
, ParagraphStyleCategory::INDEX
},
74 { XML_EXTRA
, ParagraphStyleCategory::EXTRA
},
75 { XML_HTML
, ParagraphStyleCategory::HTML
},
76 { XML_TOKEN_INVALID
, 0 }
79 void XMLTextStyleContext::SetAttribute( sal_uInt16 nPrefixKey
,
80 const OUString
& rLocalName
,
81 const OUString
& rValue
)
83 if( XML_NAMESPACE_STYLE
== nPrefixKey
)
85 // TODO: use a map here
86 if( IsXMLToken( rLocalName
, XML_AUTO_UPDATE
) )
88 if( IsXMLToken( rValue
, XML_TRUE
) )
91 else if( IsXMLToken( rLocalName
, XML_LIST_STYLE_NAME
) )
93 sListStyleName
= rValue
;
94 // Inherited paragraph style lost information about unset numbering (#i69523#)
95 mbListStyleSet
= true;
97 else if( IsXMLToken( rLocalName
, XML_MASTER_PAGE_NAME
) )
99 sMasterPageName
= rValue
;
100 bHasMasterPageName
= true;
102 else if( IsXMLToken( rLocalName
, XML_DATA_STYLE_NAME
) )
104 sDataStyleName
= rValue
;
106 else if( IsXMLToken( rLocalName
, XML_CLASS
) )
108 sCategoryVal
= rValue
;
110 else if( IsXMLToken( rLocalName
, XML_DEFAULT_OUTLINE_LEVEL
) )
113 if (::sax::Converter::convertNumber( nTmp
, rValue
) &&
114 0 <= nTmp
&& nTmp
<= 10 )
115 nOutlineLevel
= static_cast< sal_Int8
>( nTmp
);
119 XMLPropStyleContext::SetAttribute( nPrefixKey
, rLocalName
, rValue
);
124 XMLPropStyleContext::SetAttribute( nPrefixKey
, rLocalName
, rValue
);
128 TYPEINIT1( XMLTextStyleContext
, XMLPropStyleContext
);
130 XMLTextStyleContext::XMLTextStyleContext( SvXMLImport
& rImport
,
131 sal_uInt16 nPrfx
, const OUString
& rLName
,
132 const Reference
< XAttributeList
> & xAttrList
,
133 SvXMLStylesContext
& rStyles
, sal_uInt16 nFamily
,
135 : XMLPropStyleContext( rImport
, nPrfx
, rLName
, xAttrList
, rStyles
, nFamily
, bDefaultStyle
)
136 , sIsAutoUpdate( "IsAutoUpdate" )
137 , sCategory( "Category" )
138 , sNumberingStyleName( "NumberingStyleName" )
139 , sOutlineLevel("OutlineLevel" )
140 , sDropCapCharStyleName( "DropCapCharStyleName" )
141 , sPageDescName( "PageDescName" )
142 , nOutlineLevel( -1 )
143 , bAutoUpdate( false )
144 , bHasMasterPageName( false )
145 , bHasCombinedCharactersLetter( false )
146 // Inherited paragraph style lost information about unset numbering (#i69523#)
147 , mbListStyleSet( false )
148 , pEventContext( NULL
)
152 XMLTextStyleContext::~XMLTextStyleContext()
156 SvXMLImportContext
*XMLTextStyleContext::CreateChildContext(
158 const OUString
& rLocalName
,
159 const Reference
< XAttributeList
> & xAttrList
)
161 SvXMLImportContext
*pContext
= 0;
163 if( XML_NAMESPACE_STYLE
== nPrefix
)
165 sal_uInt32 nFamily
= 0;
166 if( IsXMLToken( rLocalName
, XML_TEXT_PROPERTIES
) )
167 nFamily
= XML_TYPE_PROP_TEXT
;
168 else if( IsXMLToken( rLocalName
, XML_PARAGRAPH_PROPERTIES
) )
169 nFamily
= XML_TYPE_PROP_PARAGRAPH
;
170 else if( IsXMLToken( rLocalName
, XML_SECTION_PROPERTIES
) )
171 nFamily
= XML_TYPE_PROP_SECTION
;
172 else if( IsDefaultStyle() && IsXMLToken( rLocalName
, XML_TABLE_PROPERTIES
) )
173 nFamily
= XML_TYPE_PROP_TABLE
;
174 else if( IsDefaultStyle() && IsXMLToken( rLocalName
, XML_TABLE_ROW_PROPERTIES
) )
175 nFamily
= XML_TYPE_PROP_TABLE_ROW
;
178 rtl::Reference
< SvXMLImportPropertyMapper
> xImpPrMap
=
179 GetStyles()->GetImportPropertyMapper( GetFamily() );
181 pContext
= new XMLTextPropertySetContext( GetImport(), nPrefix
,
182 rLocalName
, xAttrList
,
186 sDropCapTextStyleName
);
189 else if ( (XML_NAMESPACE_OFFICE
== nPrefix
) &&
190 IsXMLToken( rLocalName
, XML_EVENT_LISTENERS
) )
192 // create and remember events import context
193 // (for delayed processing of events)
194 pEventContext
= new XMLEventsImportContext( GetImport(), nPrefix
,
196 pEventContext
->AddFirstRef();
197 pContext
= pEventContext
;
201 pContext
= XMLPropStyleContext::CreateChildContext( nPrefix
, rLocalName
,
207 void XMLTextStyleContext::CreateAndInsert( bool bOverwrite
)
209 XMLPropStyleContext::CreateAndInsert( bOverwrite
);
210 Reference
< XStyle
> xStyle
= GetStyle();
211 if( !xStyle
.is() || !(bOverwrite
|| IsNew()) )
214 Reference
< XPropertySet
> xPropSet( xStyle
, UNO_QUERY
);
215 Reference
< XPropertySetInfo
> xPropSetInfo
=
216 xPropSet
->getPropertySetInfo();
217 if( xPropSetInfo
->hasPropertyByName( sIsAutoUpdate
) )
220 sal_Bool bTmp
= bAutoUpdate
;
221 aAny
.setValue( &bTmp
, cppu::UnoType
<bool>::get() );
222 xPropSet
->setPropertyValue( sIsAutoUpdate
, aAny
);
225 sal_uInt16 nCategory
= ParagraphStyleCategory::TEXT
;
226 if( XML_STYLE_FAMILY_TEXT_PARAGRAPH
== GetFamily() &&
227 !sCategoryVal
.isEmpty() && xStyle
->isUserDefined() &&
228 xPropSetInfo
->hasPropertyByName( sCategory
) &&
229 SvXMLUnitConverter::convertEnum( nCategory
, sCategoryVal
, aCategoryMap
) )
232 aAny
<<= (sal_Int16
)nCategory
;
233 xPropSet
->setPropertyValue( sCategory
, aAny
);
236 // tell the style about it's events (if applicable)
237 if (NULL
!= pEventContext
)
239 // set event suppplier and release reference to context
240 Reference
<document::XEventsSupplier
> xEventsSupplier(xStyle
,UNO_QUERY
);
241 pEventContext
->SetEvents(xEventsSupplier
);
242 pEventContext
->ReleaseRef();
245 // XML import: reconstrution of assignment of paragraph style to outline levels (#i69629#)
246 if ( nOutlineLevel
> 0 )
248 GetImport().GetTextImport()->AddOutlineStyleCandidate( nOutlineLevel
,
253 void XMLTextStyleContext::SetDefaults( )
255 if( ( GetFamily() == XML_STYLE_FAMILY_TEXT_PARAGRAPH
) ||
256 ( GetFamily() == XML_STYLE_FAMILY_TABLE_TABLE
) ||
257 ( GetFamily() == XML_STYLE_FAMILY_TABLE_ROW
) )
259 Reference
< XMultiServiceFactory
> xFactory ( GetImport().GetModel(), UNO_QUERY
);
262 Reference
< XInterface
> xInt
= xFactory
->createInstance (
263 OUString ( "com.sun.star.text.Defaults" ) );
264 Reference
< XPropertySet
> xProperties ( xInt
, UNO_QUERY
);
265 if ( xProperties
.is() )
266 FillPropertySet ( xProperties
);
271 void XMLTextStyleContext::Finish( bool bOverwrite
)
273 XMLPropStyleContext::Finish( bOverwrite
);
275 Reference
< XStyle
> xStyle
= GetStyle();
276 // Consider set empty list style (#i69523#)
277 if ( !( mbListStyleSet
||
278 nOutlineLevel
>= 0 ||
279 !sDropCapTextStyleName
.isEmpty() ||
280 bHasMasterPageName
) ||
282 !( bOverwrite
|| IsNew() ) )
285 Reference
< XPropertySet
> xPropSet( xStyle
, UNO_QUERY
);
286 Reference
< XPropertySetInfo
> xPropSetInfo
=
287 xPropSet
->getPropertySetInfo();
289 if( xPropSetInfo
->hasPropertyByName( sOutlineLevel
))
292 if( nOutlineLevel
>= 0 )
294 aAny
<<= nOutlineLevel
;
295 xPropSet
->setPropertyValue( sOutlineLevel
, aAny
);
299 // Consider set empty list style (#i69523#)
300 if ( mbListStyleSet
&&
301 xPropSetInfo
->hasPropertyByName( sNumberingStyleName
) )
303 /* Only for text document from version prior OOo 2.1 resp. SO 8 PU5:
304 - Do not apply list style, if paragraph style has a default outline
305 level > 0 and thus, will be assigned to the corresponding list
306 level of the outline style. (#i70223#)
308 bool bApplyListStyle( true );
309 if ( nOutlineLevel
> 0 )
311 if ( GetImport().IsTextDocInOOoFileFormat() )
313 bApplyListStyle
= false;
318 sal_Int32
nBuild( 0 );
319 // Check explicitly on certain versions (#i86058#)
320 if ( GetImport().getBuildIds( nUPD
, nBuild
) &&
321 ( ( nUPD
== 641 ) || ( nUPD
== 645 ) || // prior OOo 2.0
322 ( nUPD
== 680 && nBuild
<= 9073 ) ) ) // OOo 2.0 - OOo 2.0.4
324 bApplyListStyle
= false;
329 if ( bApplyListStyle
)
331 if ( sListStyleName
.isEmpty() )
334 aAny
<<= sListStyleName
/* empty string */;
335 xPropSet
->setPropertyValue( sNumberingStyleName
, aAny
);
339 // change list style name to display name
340 OUString
sDisplayListStyleName(
341 GetImport().GetStyleDisplayName( XML_STYLE_FAMILY_TEXT_LIST
,
343 // The families container must exist
344 const Reference
< XNameContainer
>& rNumStyles
=
345 GetImport().GetTextImport()->GetNumberingStyles();
346 // if( rNumStyles.is() && rNumStyles->hasByName( sDisplayListStyleName ) &&
347 // xPropSetInfo->hasPropertyByName( sNumberingStyleName ) )
348 if ( rNumStyles
.is() &&
349 rNumStyles
->hasByName( sDisplayListStyleName
) )
352 aAny
<<= sDisplayListStyleName
;
353 xPropSet
->setPropertyValue( sNumberingStyleName
, aAny
);
359 if( !sDropCapTextStyleName
.isEmpty() )
361 // change list style name to display name
362 OUString
sDisplayDropCapTextStyleName(
363 GetImport().GetStyleDisplayName( XML_STYLE_FAMILY_TEXT_TEXT
,
364 sDropCapTextStyleName
) );
365 // The families cointaner must exist
366 const Reference
< XNameContainer
>& rTextStyles
=
367 GetImport().GetTextImport()->GetTextStyles();
368 if( rTextStyles
.is() &&
369 rTextStyles
->hasByName( sDisplayDropCapTextStyleName
) &&
370 xPropSetInfo
->hasPropertyByName( sDropCapCharStyleName
) )
373 aAny
<<= sDisplayDropCapTextStyleName
;
374 xPropSet
->setPropertyValue( sDropCapCharStyleName
, aAny
);
378 if( bHasMasterPageName
)
380 OUString
sDisplayName(
381 GetImport().GetStyleDisplayName(
382 XML_STYLE_FAMILY_MASTER_PAGE
, sMasterPageName
) );
383 // The families cointaner must exist
384 const Reference
< XNameContainer
>& rPageStyles
=
385 GetImport().GetTextImport()->GetPageStyles();
386 if( ( sDisplayName
.isEmpty() ||
388 rPageStyles
->hasByName( sDisplayName
)) ) &&
389 xPropSetInfo
->hasPropertyByName( sPageDescName
) )
392 aAny
<<= sDisplayName
;
393 xPropSet
->setPropertyValue( sPageDescName
, aAny
);
398 void XMLTextStyleContext::FillPropertySet(
399 const Reference
<XPropertySet
> & rPropSet
)
401 // imitate the FillPropertySet of the super class, so we get a chance to
402 // catch the combined characters attribute
404 // imitate XMLPropStyleContext::FillPropertySet(...)
405 SvXMLStylesContext
* pSvXMLStylesContext
= static_cast< SvXMLStylesContext
* >(GetStyles());
406 rtl::Reference
< SvXMLImportPropertyMapper
> xImpPrMap
= pSvXMLStylesContext
->GetImportPropertyMapper(GetFamily());
407 DBG_ASSERT(xImpPrMap
.is(),"Where is the import prop mapper?");
411 // imitate SvXMLImportPropertyMapper::FillPropertySet(...)
412 // The reason for this is that we have no other way to
413 // efficiently intercept the value of combined characters. To
414 // get that value, we could iterate through the map once more,
415 // but instead we chose to insert the code into this
416 // iteration. I haven't been able to come up with a much more
417 // intelligent solution.
418 struct _ContextID_Index_Pair aContextIDs
[] =
420 { CTF_COMBINED_CHARACTERS_FIELD
, -1 },
421 { CTF_KEEP_TOGETHER
, -1 },
422 { CTF_BORDER_MODEL
, -1 },
423 { CTF_TEXT_DISPLAY
, -1 },
424 { CTF_FONTFAMILYNAME
, -1 },
425 { CTF_FONTFAMILYNAME_CJK
, -1 },
426 { CTF_FONTFAMILYNAME_CTL
, -1 },
428 //UUU need special handling for DrawingLayer FillStyle names
429 { CTF_FILLGRADIENTNAME
, -1 },
430 { CTF_FILLTRANSNAME
, -1 },
431 { CTF_FILLHATCHNAME
, -1 },
432 { CTF_FILLBITMAPNAME
, -1 },
437 // the style families associated with the same index modulo 4
438 static sal_uInt16 aFamilies
[] =
440 XML_STYLE_FAMILY_SD_GRADIENT_ID
,
441 XML_STYLE_FAMILY_SD_GRADIENT_ID
,
442 XML_STYLE_FAMILY_SD_HATCH_ID
,
443 XML_STYLE_FAMILY_SD_FILL_IMAGE_ID
446 // get property set info
447 Reference
< XPropertySetInfo
> xInfo
;
448 rtl::Reference
< XMLPropertySetMapper
> rPropMapper
;
449 bool bAutomatic
= false;
451 if(pSvXMLStylesContext
->IsAutomaticStyle() &&
452 (XML_STYLE_FAMILY_TEXT_TEXT
== GetFamily() || XML_STYLE_FAMILY_TEXT_PARAGRAPH
== GetFamily()))
456 if( !GetAutoName().isEmpty() )
458 OUString sAutoProp
= ( GetFamily() == XML_STYLE_FAMILY_TEXT_TEXT
) ?
459 OUString( "CharAutoStyleName" ):
460 OUString( "ParaAutoStyleName" );
466 xInfo
= rPropSet
->getPropertySetInfo();
469 if ( xInfo
->hasPropertyByName( sAutoProp
) )
471 rPropSet
->setPropertyValue( sAutoProp
, makeAny(GetAutoName()) );
478 catch( const RuntimeException
& ) { throw; }
479 catch( const Exception
& )
481 DBG_UNHANDLED_EXCEPTION();
489 xImpPrMap
->CheckSpecialContext( GetProperties(), rPropSet
, aContextIDs
);
493 xImpPrMap
->FillPropertySet( GetProperties(), rPropSet
, aContextIDs
);
496 sal_Int32 nIndex
= aContextIDs
[0].nIndex
;
498 // have we found a combined characters
501 Any
& rAny
= GetProperties()[nIndex
].maValue
;
502 bool bVal
= *static_cast<sal_Bool
const *>(rAny
.getValue());
503 bHasCombinedCharactersLetter
= bVal
;
506 // keep-together: the application default is different from
507 // the file format default. Hence, if we always set this
508 // value; if we didn't find one, we'll set to false, the file
510 // border-model: same
511 if(IsDefaultStyle() && XML_STYLE_FAMILY_TABLE_ROW
== GetFamily())
513 OUString
sIsSplitAllowed("IsSplitAllowed");
514 DBG_ASSERT( rPropSet
->getPropertySetInfo()->hasPropertyByName( sIsSplitAllowed
), "property missing?" );
515 rPropSet
->setPropertyValue(
517 (aContextIDs
[1].nIndex
== -1) ? makeAny( false ) : GetProperties()[aContextIDs
[1].nIndex
].maValue
);
520 if(IsDefaultStyle() && XML_STYLE_FAMILY_TABLE_TABLE
== GetFamily())
522 OUString
sCollapsingBorders("CollapsingBorders");
523 DBG_ASSERT( rPropSet
->getPropertySetInfo()->hasPropertyByName( sCollapsingBorders
), "property missing?" );
524 rPropSet
->setPropertyValue(
526 (aContextIDs
[2].nIndex
== -1)
528 : GetProperties()[aContextIDs
[2].nIndex
].maValue
);
532 // iterate over aContextIDs entries, start with 3, prev ones are already used above
533 for(sal_uInt16
i(3); aContextIDs
[i
].nContextID
!= -1; i
++)
535 nIndex
= aContextIDs
[i
].nIndex
;
540 struct XMLPropertyState
& rState
= GetProperties()[nIndex
];
542 switch(aContextIDs
[i
].nContextID
)
544 case CTF_FILLGRADIENTNAME
:
545 case CTF_FILLTRANSNAME
:
546 case CTF_FILLHATCHNAME
:
547 case CTF_FILLBITMAPNAME
:
549 // DrawingLayer FillStyle name needs to be mapped to DisplayName
550 rtl::OUString sStyleName
;
551 rState
.maValue
>>= sStyleName
;
553 //UUUU translate the used name from ODF intern to the name used in the Model
554 sStyleName
= GetImport().GetStyleDisplayName(aFamilies
[i
- 7], sStyleName
);
558 // in this case the rPropSet got not really filled since above the call to
559 // CheckSpecialContext was used and not FillPropertySet, thus the below call to
560 // setPropertyValue can fail/will not be useful (e.g. when the rPropSet
561 // is a SwXTextCursor).
562 // This happens for AutoStyles which are already filled in XMLPropStyleContext::CreateAndInsert,
563 // thus the whole mechanism based on _ContextID_Index_Pair will not work
564 // in that case. Thus the slots which need to be converted already get
565 // converted there (its called first) and not here (see
566 // translateNameBasedDrawingLayerFillStyleDefinitionsToStyleDisplayNames)
567 // For convenience, still Write back the corrected value to the XMLPropertyState entry
568 rState
.maValue
<<= sStyleName
;
572 // Still needed if it's not an AutomaticStyle (!)
575 if(!rPropMapper
.is())
577 rPropMapper
= xImpPrMap
->getPropertySetMapper();
581 const rtl::OUString
& rPropertyName
= rPropMapper
->GetEntryAPIName(rState
.mnIndex
);
585 xInfo
= rPropSet
->getPropertySetInfo();
588 if(xInfo
->hasPropertyByName(rPropertyName
))
590 rPropSet
->setPropertyValue(rPropertyName
,Any(sStyleName
));
593 catch(::com::sun::star::lang::IllegalArgumentException
& e
)
595 Sequence
< rtl::OUString
> aSeq(1);
596 aSeq
[0] = sStyleName
;
597 GetImport().SetError(XMLERROR_STYLE_PROP_VALUE
| XMLERROR_FLAG_WARNING
, aSeq
, e
.Message
, NULL
);
603 // check for StarBats and StarMath fonts
604 Any rAny
= rState
.maValue
;
605 sal_Int32 nMapperIndex
= rState
.mnIndex
;
607 // Now check for font name in rState and set corrected value,
612 if ( !sFontName
.isEmpty() )
614 if ( sFontName
.equalsIgnoreAsciiCase( "StarBats" ) ||
615 sFontName
.equalsIgnoreAsciiCase( "StarMath" ) )
617 // construct new value
618 sFontName
= "StarSymbol";
622 if(!rPropMapper
.is())
624 rPropMapper
= xImpPrMap
->getPropertySetMapper();
628 OUString
rPropertyName(rPropMapper
->GetEntryAPIName(nMapperIndex
));
632 xInfo
= rPropSet
->getPropertySetInfo();
635 if(xInfo
->hasPropertyByName(rPropertyName
))
637 rPropSet
->setPropertyValue(rPropertyName
,aAny
);
640 // else: "normal" style name -> no correction is necessary
642 // else: no style name found -> illegal value -> ignore
650 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */