1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_xmloff.hxx" 26 27 #include "XMLTextPropertySetContext.hxx" 28 #include "xmloff/xmlnmspe.hxx" 29 #include "xmloff/XMLEventsImportContext.hxx" 30 #include "xmloff/attrlist.hxx" 31 #include "xmloff/families.hxx" 32 #include "xmloff/txtprmap.hxx" 33 #include "xmloff/txtstyli.hxx" 34 #include "xmloff/xmlimp.hxx" 35 #include "xmloff/xmltkmap.hxx" 36 #include "xmloff/xmltoken.hxx" 37 #include "xmloff/xmluconv.hxx" 38 39 #include <com/sun/star/beans/XMultiPropertySet.hpp> 40 #include <com/sun/star/container/XNameContainer.hpp> 41 #include <com/sun/star/document/XEventsSupplier.hpp> 42 #include <com/sun/star/frame/XModel.hpp> 43 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 44 #include <com/sun/star/style/ParagraphStyleCategory.hpp> 45 #include <com/sun/star/style/XStyle.hpp> 46 47 #include <tools/debug.hxx> 48 #include <tools/diagnose_ex.h> 49 50 // STL includes 51 #include <algorithm> 52 #include <functional> 53 #include <utility> 54 #include <vector> 55 56 using ::rtl::OUString; 57 using ::rtl::OUStringBuffer; 58 59 using namespace ::std; 60 using namespace ::com::sun::star; 61 using namespace ::com::sun::star::uno; 62 using namespace ::com::sun::star::xml::sax; 63 using namespace ::com::sun::star::style; 64 using namespace ::com::sun::star::frame; 65 using namespace ::com::sun::star::beans; 66 using namespace ::com::sun::star::lang; 67 using namespace ::com::sun::star::container; 68 //using namespace ::com::sun::star::text; 69 using namespace ::xmloff::token; 70 71 static __FAR_DATA SvXMLEnumMapEntry aCategoryMap[] = 72 { 73 { XML_TEXT, ParagraphStyleCategory::TEXT }, 74 { XML_CHAPTER, ParagraphStyleCategory::CHAPTER }, 75 { XML_LIST, ParagraphStyleCategory::LIST }, 76 { XML_INDEX, ParagraphStyleCategory::INDEX }, 77 { XML_EXTRA, ParagraphStyleCategory::EXTRA }, 78 { XML_HTML, ParagraphStyleCategory::HTML }, 79 { XML_TOKEN_INVALID, 0 } 80 }; 81 82 void XMLTextStyleContext::SetAttribute( sal_uInt16 nPrefixKey, 83 const OUString& rLocalName, 84 const OUString& rValue ) 85 { 86 if( XML_NAMESPACE_STYLE == nPrefixKey ) 87 { 88 // TODO: use a map here 89 if( IsXMLToken( rLocalName, XML_AUTO_UPDATE ) ) 90 { 91 if( IsXMLToken( rValue, XML_TRUE ) ) 92 bAutoUpdate = sal_True; 93 } 94 else if( IsXMLToken( rLocalName, XML_LIST_STYLE_NAME ) ) 95 { 96 sListStyleName = rValue; 97 // --> OD 2006-09-21 #i69523# 98 mbListStyleSet = sal_True; 99 // <-- 100 } 101 else if( IsXMLToken( rLocalName, XML_MASTER_PAGE_NAME ) ) 102 { 103 sMasterPageName = rValue; 104 bHasMasterPageName = sal_True; 105 } 106 else if( IsXMLToken( rLocalName, XML_DATA_STYLE_NAME ) ) 107 { 108 sDataStyleName = rValue; 109 } 110 else if( IsXMLToken( rLocalName, XML_CLASS ) ) 111 { 112 sCategoryVal = rValue; 113 } 114 else if( IsXMLToken( rLocalName, XML_DEFAULT_OUTLINE_LEVEL ) ) 115 { 116 sal_Int32 nTmp; 117 if( SvXMLUnitConverter::convertNumber( nTmp, rValue ) && 118 // nTmp > 0 && nTmp < 256 ) //#outline level, removed by zhaojianwei 119 0 <= nTmp && nTmp <= 10 ) //<-end,add by zhaojianwei 120 nOutlineLevel = static_cast< sal_Int8 >( nTmp ); 121 } 122 else 123 { 124 XMLPropStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue ); 125 } 126 } 127 else 128 { 129 XMLPropStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue ); 130 } 131 } 132 133 TYPEINIT1( XMLTextStyleContext, XMLPropStyleContext ); 134 135 XMLTextStyleContext::XMLTextStyleContext( SvXMLImport& rImport, 136 sal_uInt16 nPrfx, const OUString& rLName, 137 const Reference< XAttributeList > & xAttrList, 138 SvXMLStylesContext& rStyles, sal_uInt16 nFamily, 139 sal_Bool bDefaultStyle ) 140 : XMLPropStyleContext( rImport, nPrfx, rLName, xAttrList, rStyles, nFamily, bDefaultStyle ) 141 , sIsAutoUpdate( RTL_CONSTASCII_USTRINGPARAM( "IsAutoUpdate" ) ) 142 , sCategory( RTL_CONSTASCII_USTRINGPARAM( "Category" ) ) 143 , sNumberingStyleName( RTL_CONSTASCII_USTRINGPARAM( "NumberingStyleName" ) ) 144 , sOutlineLevel(RTL_CONSTASCII_USTRINGPARAM( "OutlineLevel" ) )//#outline level,add by zhaojianwei 145 , sDropCapCharStyleName( RTL_CONSTASCII_USTRINGPARAM( "DropCapCharStyleName" ) ) 146 , sPageDescName( RTL_CONSTASCII_USTRINGPARAM( "PageDescName" ) ) 147 //, nOutlineLevel( 0 ) // removed by zhaojianwei 148 , nOutlineLevel( -1 ) //<-end, add by zhaojianwei 149 , bAutoUpdate( sal_False ) 150 , bHasMasterPageName( sal_False ) 151 , bHasCombinedCharactersLetter( sal_False ) 152 // --> OD 2006-09-21 #i69523# 153 , mbListStyleSet( sal_False ) 154 // <-- 155 , pEventContext( NULL ) 156 { 157 } 158 159 XMLTextStyleContext::~XMLTextStyleContext() 160 { 161 } 162 163 SvXMLImportContext *XMLTextStyleContext::CreateChildContext( 164 sal_uInt16 nPrefix, 165 const OUString& rLocalName, 166 const Reference< XAttributeList > & xAttrList ) 167 { 168 SvXMLImportContext *pContext = 0; 169 170 if( XML_NAMESPACE_STYLE == nPrefix ) 171 { 172 sal_uInt32 nFamily = 0; 173 if( IsXMLToken( rLocalName, XML_TEXT_PROPERTIES ) ) 174 nFamily = XML_TYPE_PROP_TEXT; 175 else if( IsXMLToken( rLocalName, XML_PARAGRAPH_PROPERTIES ) ) 176 nFamily = XML_TYPE_PROP_PARAGRAPH; 177 else if( IsXMLToken( rLocalName, XML_SECTION_PROPERTIES ) ) 178 nFamily = XML_TYPE_PROP_SECTION; 179 else if( IsDefaultStyle() && IsXMLToken( rLocalName, XML_TABLE_PROPERTIES ) ) 180 nFamily = XML_TYPE_PROP_TABLE; 181 else if( IsDefaultStyle() && IsXMLToken( rLocalName, XML_TABLE_ROW_PROPERTIES ) ) 182 nFamily = XML_TYPE_PROP_TABLE_ROW; 183 if( nFamily ) 184 { 185 UniReference < SvXMLImportPropertyMapper > xImpPrMap = 186 GetStyles()->GetImportPropertyMapper( GetFamily() ); 187 if( xImpPrMap.is() ) 188 pContext = new XMLTextPropertySetContext( GetImport(), nPrefix, 189 rLocalName, xAttrList, 190 nFamily, 191 GetProperties(), 192 xImpPrMap, 193 sDropCapTextStyleName ); 194 } 195 } 196 else if ( (XML_NAMESPACE_OFFICE == nPrefix) && 197 IsXMLToken( rLocalName, XML_EVENT_LISTENERS ) ) 198 { 199 // create and remember events import context 200 // (for delayed processing of events) 201 pEventContext = new XMLEventsImportContext( GetImport(), nPrefix, 202 rLocalName); 203 pEventContext->AddRef(); 204 pContext = pEventContext; 205 } 206 207 if( !pContext ) 208 pContext = XMLPropStyleContext::CreateChildContext( nPrefix, rLocalName, 209 xAttrList ); 210 211 return pContext; 212 } 213 214 void XMLTextStyleContext::CreateAndInsert( sal_Bool bOverwrite ) 215 { 216 XMLPropStyleContext::CreateAndInsert( bOverwrite ); 217 Reference < XStyle > xStyle = GetStyle(); 218 if( !xStyle.is() || !(bOverwrite || IsNew()) ) 219 return; 220 221 Reference < XPropertySet > xPropSet( xStyle, UNO_QUERY ); 222 Reference< XPropertySetInfo > xPropSetInfo = 223 xPropSet->getPropertySetInfo(); 224 if( xPropSetInfo->hasPropertyByName( sIsAutoUpdate ) ) 225 { 226 Any aAny; 227 sal_Bool bTmp = bAutoUpdate; 228 aAny.setValue( &bTmp, ::getBooleanCppuType() ); 229 xPropSet->setPropertyValue( sIsAutoUpdate, aAny ); 230 } 231 232 sal_uInt16 nCategory = ParagraphStyleCategory::TEXT; 233 if( XML_STYLE_FAMILY_TEXT_PARAGRAPH == GetFamily() && 234 sCategoryVal.getLength() && xStyle->isUserDefined() && 235 xPropSetInfo->hasPropertyByName( sCategory ) && 236 SvXMLUnitConverter::convertEnum( nCategory, sCategoryVal, aCategoryMap ) ) 237 { 238 Any aAny; 239 aAny <<= (sal_Int16)nCategory; 240 xPropSet->setPropertyValue( sCategory, aAny ); 241 } 242 243 // tell the style about it's events (if applicable) 244 if (NULL != pEventContext) 245 { 246 // set event suppplier and release reference to context 247 Reference<document::XEventsSupplier> xEventsSupplier(xStyle,UNO_QUERY); 248 pEventContext->SetEvents(xEventsSupplier); 249 pEventContext->ReleaseRef(); 250 } 251 252 // --> OD 2006-10-12 #i69629# 253 if ( nOutlineLevel > 0 ) 254 { 255 GetImport().GetTextImport()->AddOutlineStyleCandidate( nOutlineLevel, 256 GetDisplayName() ); 257 } 258 // <-- 259 } 260 261 void XMLTextStyleContext::SetDefaults( ) 262 { 263 if( ( GetFamily() == XML_STYLE_FAMILY_TEXT_PARAGRAPH ) || 264 ( GetFamily() == XML_STYLE_FAMILY_TABLE_TABLE ) || 265 ( GetFamily() == XML_STYLE_FAMILY_TABLE_ROW ) ) 266 { 267 Reference < XMultiServiceFactory > xFactory ( GetImport().GetModel(), UNO_QUERY); 268 if (xFactory.is()) 269 { 270 Reference < XInterface > xInt = xFactory->createInstance ( 271 OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.text.Defaults" ) ) ); 272 Reference < XPropertySet > xProperties ( xInt, UNO_QUERY ); 273 if ( xProperties.is() ) 274 FillPropertySet ( xProperties ); 275 } 276 } 277 } 278 279 void XMLTextStyleContext::Finish( sal_Bool bOverwrite ) 280 { 281 XMLPropStyleContext::Finish( bOverwrite ); 282 283 Reference < XStyle > xStyle = GetStyle(); 284 // --> OD 2006-09-21 #i69523# 285 // consider set empty list style 286 // if ( !( sListStyleName.getLength() || 287 if ( !( mbListStyleSet || 288 nOutlineLevel >= 0 || //#outline level,add by zhaojianwei 289 sDropCapTextStyleName.getLength() || 290 bHasMasterPageName ) || 291 !xStyle.is() || 292 !( bOverwrite || IsNew() ) ) 293 return; 294 // <-- 295 296 Reference < XPropertySet > xPropSet( xStyle, UNO_QUERY ); 297 Reference< XPropertySetInfo > xPropSetInfo = 298 xPropSet->getPropertySetInfo(); 299 300 //#outline level,add by zhaojianwei 301 if( xPropSetInfo->hasPropertyByName( sOutlineLevel )) 302 { 303 Any aAny; 304 if( nOutlineLevel >= 0 ) 305 { 306 aAny <<= nOutlineLevel; 307 xPropSet->setPropertyValue( sOutlineLevel, aAny ); 308 } 309 } 310 //<-end,zhaojianwei 311 312 313 // --> OD 2006-09-21 #i69523# 314 // consider set empty list style 315 // if( sListStyleName.getLength() ) 316 if ( mbListStyleSet && 317 xPropSetInfo->hasPropertyByName( sNumberingStyleName ) ) 318 { 319 // --> OD 2006-10-12 #i70223# 320 // Only for text document from version prior OOo 2.1 resp. SO 8 PU5: 321 // - Do not apply list style, if paragraph style has a default outline 322 // level > 0 and thus, will be assigned to the corresponding list 323 // level of the outline style. 324 bool bApplyListStyle( true ); 325 if ( nOutlineLevel > 0 ) 326 { 327 // --> OD 2007-12-19 #152540# 328 if ( GetImport().IsTextDocInOOoFileFormat() ) 329 { 330 bApplyListStyle = false; 331 } 332 else 333 { 334 sal_Int32 nUPD( 0 ); 335 sal_Int32 nBuild( 0 ); 336 // --> OD 2008-03-19 #i86058# 337 // check explicitly on certain versions 338 if ( GetImport().getBuildIds( nUPD, nBuild ) && 339 ( ( nUPD == 641 ) || ( nUPD == 645 ) || // prior OOo 2.0 340 ( nUPD == 680 && nBuild <= 9073 ) ) ) // OOo 2.0 - OOo 2.0.4 341 { 342 bApplyListStyle = false; 343 } 344 // <-- 345 } 346 // <-- 347 } 348 349 if ( bApplyListStyle ) 350 { 351 if ( !sListStyleName.getLength() ) 352 { 353 Any aAny; 354 aAny <<= sListStyleName /* empty string */; 355 xPropSet->setPropertyValue( sNumberingStyleName, aAny ); 356 } 357 else 358 { 359 // change list style name to display name 360 OUString sDisplayListStyleName( 361 GetImport().GetStyleDisplayName( XML_STYLE_FAMILY_TEXT_LIST, 362 sListStyleName ) ); 363 // The families container must exist 364 const Reference < XNameContainer >& rNumStyles = 365 GetImport().GetTextImport()->GetNumberingStyles(); 366 // if( rNumStyles.is() && rNumStyles->hasByName( sDisplayListStyleName ) && 367 // xPropSetInfo->hasPropertyByName( sNumberingStyleName ) ) 368 if ( rNumStyles.is() && 369 rNumStyles->hasByName( sDisplayListStyleName ) ) 370 { 371 Any aAny; 372 aAny <<= sDisplayListStyleName; 373 xPropSet->setPropertyValue( sNumberingStyleName, aAny ); 374 } 375 } 376 } 377 // <-- 378 } 379 // <-- 380 381 if( sDropCapTextStyleName.getLength() ) 382 { 383 // change list style name to display name 384 OUString sDisplayDropCapTextStyleName( 385 GetImport().GetStyleDisplayName( XML_STYLE_FAMILY_TEXT_TEXT, 386 sDropCapTextStyleName ) ); 387 // The families cointaner must exist 388 const Reference < XNameContainer >& rTextStyles = 389 GetImport().GetTextImport()->GetTextStyles(); 390 if( rTextStyles.is() && 391 rTextStyles->hasByName( sDisplayDropCapTextStyleName ) && 392 xPropSetInfo->hasPropertyByName( sDropCapCharStyleName ) ) 393 { 394 Any aAny; 395 aAny <<= sDisplayDropCapTextStyleName; 396 xPropSet->setPropertyValue( sDropCapCharStyleName, aAny ); 397 } 398 } 399 400 if( bHasMasterPageName ) 401 { 402 OUString sDisplayName( 403 GetImport().GetStyleDisplayName( 404 XML_STYLE_FAMILY_MASTER_PAGE, sMasterPageName ) ); 405 // The families cointaner must exist 406 const Reference < XNameContainer >& rPageStyles = 407 GetImport().GetTextImport()->GetPageStyles(); 408 if( ( !sDisplayName.getLength() || 409 (rPageStyles.is() && 410 rPageStyles->hasByName( sDisplayName )) ) && 411 xPropSetInfo->hasPropertyByName( sPageDescName ) ) 412 { 413 Any aAny; 414 aAny <<= sDisplayName; 415 xPropSet->setPropertyValue( sPageDescName, aAny ); 416 } 417 } 418 } 419 420 void XMLTextStyleContext::FillPropertySet( 421 const Reference<XPropertySet > & rPropSet ) 422 { 423 // imitate the FillPropertySet of the super class, so we get a chance to 424 // catch the combined characters attribute 425 426 // imitate XMLPropStyleContext::FillPropertySet(...) 427 UniReference < SvXMLImportPropertyMapper > xImpPrMap = 428 ((SvXMLStylesContext *)GetStyles())->GetImportPropertyMapper(GetFamily()); 429 DBG_ASSERT( xImpPrMap.is(), "Where is the import prop mapper?" ); 430 if( xImpPrMap.is() ) 431 { 432 433 // imitate SvXMLImportPropertyMapper::FillPropertySet(...) 434 435 // The reason for this is that we have no other way to 436 // efficiently intercept the value of combined characters. To 437 // get that value, we could iterate through the map once more, 438 // but instead we chose to insert the code into this 439 // iteration. I haven't been able to come up with a much more 440 // intelligent solution. 441 442 443 struct _ContextID_Index_Pair aContextIDs[] = 444 { 445 { CTF_COMBINED_CHARACTERS_FIELD, -1 }, 446 { CTF_KEEP_TOGETHER, -1 }, 447 { CTF_BORDER_MODEL, -1 }, 448 { CTF_TEXT_DISPLAY, -1 }, 449 { CTF_FONTFAMILYNAME, -1 }, 450 { CTF_FONTFAMILYNAME_CJK, -1 }, 451 { CTF_FONTFAMILYNAME_CTL, -1 }, 452 { -1, -1 } 453 }; 454 455 // get property set info 456 Reference< XPropertySetInfo > xInfo( rPropSet->getPropertySetInfo(), UNO_SET_THROW ); 457 458 bool bAutomatic = false; 459 if( ((SvXMLStylesContext *)GetStyles())->IsAutomaticStyle() && 460 ( GetFamily() == XML_STYLE_FAMILY_TEXT_TEXT || GetFamily() == XML_STYLE_FAMILY_TEXT_PARAGRAPH ) ) 461 { 462 bAutomatic = true; 463 if( GetAutoName().getLength() ) 464 { 465 OUString sAutoProp = ( GetFamily() == XML_STYLE_FAMILY_TEXT_TEXT ) ? 466 OUString( RTL_CONSTASCII_USTRINGPARAM("CharAutoStyleName") ): 467 OUString( RTL_CONSTASCII_USTRINGPARAM("ParaAutoStyleName") ); 468 try 469 { 470 if ( xInfo->hasPropertyByName( sAutoProp ) ) 471 rPropSet->setPropertyValue( sAutoProp, makeAny(GetAutoName()) ); 472 else 473 bAutomatic = false; 474 } 475 catch( const RuntimeException& ) { throw; } 476 catch( const Exception& ) 477 { 478 DBG_UNHANDLED_EXCEPTION(); 479 bAutomatic = false; 480 } 481 } 482 } 483 if( bAutomatic ) 484 xImpPrMap->CheckSpecialContext( GetProperties(), rPropSet, aContextIDs ); 485 else 486 xImpPrMap->FillPropertySet( GetProperties(), rPropSet, aContextIDs ); 487 488 // have we found a combined characters 489 sal_Int32 nIndex = aContextIDs[0].nIndex; 490 if ( nIndex != -1 ) 491 { 492 Any& rAny = GetProperties()[nIndex].maValue; 493 sal_Bool bVal = *(sal_Bool*)rAny.getValue(); 494 bHasCombinedCharactersLetter = bVal; 495 } 496 497 // keep-together: the application default is different from 498 // the file format default. Hence, if we always set this 499 // value; if we didn't find one, we'll set to false, the file 500 // format default. 501 // border-model: same 502 if( IsDefaultStyle() && GetFamily() == XML_STYLE_FAMILY_TABLE_ROW ) 503 { 504 OUString sIsSplitAllowed = 505 OUString( RTL_CONSTASCII_USTRINGPARAM( "IsSplitAllowed" ) ); 506 DBG_ASSERT( rPropSet->getPropertySetInfo()->hasPropertyByName( sIsSplitAllowed ), 507 "property missing?" ); 508 rPropSet->setPropertyValue( sIsSplitAllowed, 509 (aContextIDs[1].nIndex == -1) 510 ? makeAny( false ) 511 : GetProperties()[aContextIDs[1].nIndex].maValue ); 512 } 513 514 if( IsDefaultStyle() && GetFamily() == XML_STYLE_FAMILY_TABLE_TABLE ) 515 { 516 OUString sCollapsingBorders( 517 OUString( RTL_CONSTASCII_USTRINGPARAM( "CollapsingBorders" ) ) ); 518 DBG_ASSERT( rPropSet->getPropertySetInfo()->hasPropertyByName( sCollapsingBorders ), 519 "property missing?" ); 520 rPropSet->setPropertyValue( sCollapsingBorders, 521 (aContextIDs[2].nIndex == -1) 522 ? makeAny( false ) 523 : GetProperties()[aContextIDs[2].nIndex].maValue ); 524 } 525 526 527 // check for StarBats and StarMath fonts 528 529 // iterate over aContextIDs entries 3..6 530 for ( sal_Int32 i = 3; i < 7; i++ ) 531 { 532 nIndex = aContextIDs[i].nIndex; 533 if ( nIndex != -1 ) 534 { 535 // Found! 536 struct XMLPropertyState& rState = GetProperties()[nIndex]; 537 Any rAny = rState.maValue; 538 sal_Int32 nMapperIndex = rState.mnIndex; 539 540 // Now check for font name in rState and set corrected value, 541 // if necessary. 542 OUString sFontName; 543 rAny >>= sFontName; 544 if ( sFontName.getLength() > 0 ) 545 { 546 OUString sStarBats( RTL_CONSTASCII_USTRINGPARAM("StarBats" ) ); 547 OUString sStarMath( RTL_CONSTASCII_USTRINGPARAM("StarMath" ) ); 548 if ( sFontName.equalsIgnoreAsciiCase( sStarBats ) || 549 sFontName.equalsIgnoreAsciiCase( sStarMath ) ) 550 { 551 // construct new value 552 sFontName = OUString( 553 RTL_CONSTASCII_USTRINGPARAM("StarSymbol") ); 554 Any aAny( rAny ); 555 aAny <<= sFontName; 556 557 // get property set mapper 558 UniReference<XMLPropertySetMapper> rPropMapper = 559 xImpPrMap->getPropertySetMapper(); 560 561 // set property 562 OUString rPropertyName( 563 rPropMapper->GetEntryAPIName(nMapperIndex) ); 564 if ( xInfo->hasPropertyByName( rPropertyName ) ) 565 { 566 rPropSet->setPropertyValue( rPropertyName, aAny ); 567 } 568 } 569 // else: "normal" style name -> no correction is necessary 570 } 571 // else: no style name found -> illegal value -> ignore 572 } 573 } 574 } 575 } 576