1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_xmloff.hxx" 30 31 #include <unotools/syslocale.hxx> 32 33 #define _ZFORLIST_DECLARE_TABLE 34 #include <svl/zforlist.hxx> 35 36 #include <svl/zformat.hxx> 37 #include <svl/numuno.hxx> 38 #include <rtl/math.hxx> 39 #include <i18npool/mslangid.hxx> 40 #include <tools/debug.hxx> 41 #include <rtl/ustrbuf.hxx> 42 43 // #110680# 44 //#include <comphelper/processfactory.hxx> 45 46 #include <xmloff/xmlnumfi.hxx> 47 #include <xmloff/xmltkmap.hxx> 48 #include "xmloff/xmlnmspe.hxx" 49 #include <xmloff/xmlictxt.hxx> 50 #include <xmloff/xmlimp.hxx> 51 #include <xmloff/xmluconv.hxx> 52 #include <xmloff/nmspmap.hxx> 53 #include <xmloff/families.hxx> 54 #include <xmloff/xmltoken.hxx> 55 56 using ::rtl::OUString; 57 using ::rtl::OUStringBuffer; 58 59 using namespace ::com::sun::star; 60 using namespace ::xmloff::token; 61 62 //------------------------------------------------------------------------- 63 64 struct SvXMLNumFmtEntry 65 { 66 rtl::OUString aName; 67 sal_uInt32 nKey; 68 sal_Bool bRemoveAfterUse; 69 70 SvXMLNumFmtEntry( const rtl::OUString& rN, sal_uInt32 nK, sal_Bool bR ) : 71 aName(rN), nKey(nK), bRemoveAfterUse(bR) {} 72 }; 73 74 typedef SvXMLNumFmtEntry* SvXMLNumFmtEntryPtr; 75 SV_DECL_PTRARR_DEL( SvXMLNumFmtEntryArr, SvXMLNumFmtEntryPtr, 4, 4 ) 76 77 struct SvXMLEmbeddedElement 78 { 79 sal_Int32 nFormatPos; 80 rtl::OUString aText; 81 82 SvXMLEmbeddedElement( sal_Int32 nFP, const rtl::OUString& rT ) : 83 nFormatPos(nFP), aText(rT) {} 84 85 // comparison operators for PTRARR sorting - sorted by position 86 sal_Bool operator ==( const SvXMLEmbeddedElement& r ) const { return nFormatPos == r.nFormatPos; } 87 sal_Bool operator < ( const SvXMLEmbeddedElement& r ) const { return nFormatPos < r.nFormatPos; } 88 }; 89 90 typedef SvXMLEmbeddedElement* SvXMLEmbeddedElementPtr; 91 SV_DECL_PTRARR_SORT_DEL( SvXMLEmbeddedElementArr, SvXMLEmbeddedElementPtr, 0, 4 ) 92 93 //------------------------------------------------------------------------- 94 95 class SvXMLNumImpData 96 { 97 SvNumberFormatter* pFormatter; 98 SvXMLTokenMap* pStylesElemTokenMap; 99 SvXMLTokenMap* pStyleElemTokenMap; 100 SvXMLTokenMap* pStyleAttrTokenMap; 101 SvXMLTokenMap* pStyleElemAttrTokenMap; 102 LocaleDataWrapper* pLocaleData; 103 SvXMLNumFmtEntryArr aNameEntries; 104 105 // #110680# 106 ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxServiceFactory; 107 108 public: 109 // #110680# 110 // SvXMLNumImpData( SvNumberFormatter* pFmt ); 111 SvXMLNumImpData( 112 SvNumberFormatter* pFmt, 113 const uno::Reference<lang::XMultiServiceFactory>& xServiceFactory ); 114 ~SvXMLNumImpData(); 115 116 SvNumberFormatter* GetNumberFormatter() const { return pFormatter; } 117 const SvXMLTokenMap& GetStylesElemTokenMap(); 118 const SvXMLTokenMap& GetStyleElemTokenMap(); 119 const SvXMLTokenMap& GetStyleAttrTokenMap(); 120 const SvXMLTokenMap& GetStyleElemAttrTokenMap(); 121 const LocaleDataWrapper& GetLocaleData( LanguageType nLang ); 122 sal_uInt32 GetKeyForName( const rtl::OUString& rName ); 123 void AddKey( sal_uInt32 nKey, const rtl::OUString& rName, sal_Bool bRemoveAfterUse ); 124 void SetUsed( sal_uInt32 nKey ); 125 void RemoveVolatileFormats(); 126 }; 127 128 129 struct SvXMLNumberInfo 130 { 131 sal_Int32 nDecimals; 132 sal_Int32 nInteger; 133 sal_Int32 nExpDigits; 134 sal_Int32 nNumerDigits; 135 sal_Int32 nDenomDigits; 136 sal_Bool bGrouping; 137 sal_Bool bDecReplace; 138 sal_Bool bVarDecimals; 139 double fDisplayFactor; 140 SvXMLEmbeddedElementArr aEmbeddedElements; 141 142 SvXMLNumberInfo() 143 { 144 nDecimals = nInteger = nExpDigits = nNumerDigits = nDenomDigits = -1; 145 bGrouping = bDecReplace = bVarDecimals = sal_False; 146 fDisplayFactor = 1.0; 147 } 148 }; 149 150 class SvXMLNumFmtElementContext : public SvXMLImportContext 151 { 152 SvXMLNumFormatContext& rParent; 153 sal_uInt16 nType; 154 rtl::OUStringBuffer aContent; 155 SvXMLNumberInfo aNumInfo; 156 LanguageType nElementLang; 157 sal_Bool bLong; 158 sal_Bool bTextual; 159 rtl::OUString sCalendar; 160 161 public: 162 SvXMLNumFmtElementContext( SvXMLImport& rImport, sal_uInt16 nPrfx, 163 const rtl::OUString& rLName, 164 SvXMLNumFormatContext& rParentContext, sal_uInt16 nNewType, 165 const ::com::sun::star::uno::Reference< 166 ::com::sun::star::xml::sax::XAttributeList>& xAttrList ); 167 virtual ~SvXMLNumFmtElementContext(); 168 169 virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix, 170 const rtl::OUString& rLocalName, 171 const ::com::sun::star::uno::Reference< 172 ::com::sun::star::xml::sax::XAttributeList>& xAttrList ); 173 virtual void Characters( const rtl::OUString& rChars ); 174 virtual void EndElement(); 175 176 void AddEmbeddedElement( sal_Int32 nFormatPos, const rtl::OUString& rContent ); 177 }; 178 179 180 class SvXMLNumFmtEmbeddedTextContext : public SvXMLImportContext 181 { 182 SvXMLNumFmtElementContext& rParent; 183 rtl::OUStringBuffer aContent; 184 sal_Int32 nTextPosition; 185 186 public: 187 SvXMLNumFmtEmbeddedTextContext( SvXMLImport& rImport, sal_uInt16 nPrfx, 188 const rtl::OUString& rLName, 189 SvXMLNumFmtElementContext& rParentContext, 190 const ::com::sun::star::uno::Reference< 191 ::com::sun::star::xml::sax::XAttributeList>& xAttrList ); 192 virtual ~SvXMLNumFmtEmbeddedTextContext(); 193 194 virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix, 195 const rtl::OUString& rLocalName, 196 const ::com::sun::star::uno::Reference< 197 ::com::sun::star::xml::sax::XAttributeList>& xAttrList ); 198 virtual void Characters( const rtl::OUString& rChars ); 199 virtual void EndElement(); 200 }; 201 202 203 class SvXMLNumFmtMapContext : public SvXMLImportContext 204 { 205 SvXMLNumFormatContext& rParent; 206 rtl::OUString sCondition; 207 rtl::OUString sName; 208 209 public: 210 SvXMLNumFmtMapContext( SvXMLImport& rImport, sal_uInt16 nPrfx, 211 const rtl::OUString& rLName, 212 SvXMLNumFormatContext& rParentContext, 213 const ::com::sun::star::uno::Reference< 214 ::com::sun::star::xml::sax::XAttributeList>& xAttrList ); 215 virtual ~SvXMLNumFmtMapContext(); 216 217 virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix, 218 const rtl::OUString& rLocalName, 219 const ::com::sun::star::uno::Reference< 220 ::com::sun::star::xml::sax::XAttributeList>& xAttrList ); 221 virtual void Characters( const rtl::OUString& rChars ); 222 virtual void EndElement(); 223 }; 224 225 226 class SvXMLNumFmtPropContext : public SvXMLImportContext 227 { 228 SvXMLNumFormatContext& rParent; 229 Color aColor; 230 sal_Bool bColSet; 231 232 public: 233 SvXMLNumFmtPropContext( SvXMLImport& rImport, sal_uInt16 nPrfx, 234 const rtl::OUString& rLName, 235 SvXMLNumFormatContext& rParentContext, 236 const ::com::sun::star::uno::Reference< 237 ::com::sun::star::xml::sax::XAttributeList>& xAttrList ); 238 virtual ~SvXMLNumFmtPropContext(); 239 240 virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix, 241 const rtl::OUString& rLocalName, 242 const ::com::sun::star::uno::Reference< 243 ::com::sun::star::xml::sax::XAttributeList>& xAttrList ); 244 virtual void Characters( const rtl::OUString& rChars ); 245 virtual void EndElement(); 246 }; 247 248 249 //------------------------------------------------------------------------- 250 251 enum SvXMLStyleTokens 252 { 253 XML_TOK_STYLE_TEXT, 254 XML_TOK_STYLE_NUMBER, 255 XML_TOK_STYLE_SCIENTIFIC_NUMBER, 256 XML_TOK_STYLE_FRACTION, 257 XML_TOK_STYLE_CURRENCY_SYMBOL, 258 XML_TOK_STYLE_DAY, 259 XML_TOK_STYLE_MONTH, 260 XML_TOK_STYLE_YEAR, 261 XML_TOK_STYLE_ERA, 262 XML_TOK_STYLE_DAY_OF_WEEK, 263 XML_TOK_STYLE_WEEK_OF_YEAR, 264 XML_TOK_STYLE_QUARTER, 265 XML_TOK_STYLE_HOURS, 266 XML_TOK_STYLE_AM_PM, 267 XML_TOK_STYLE_MINUTES, 268 XML_TOK_STYLE_SECONDS, 269 XML_TOK_STYLE_BOOLEAN, 270 XML_TOK_STYLE_TEXT_CONTENT, 271 XML_TOK_STYLE_PROPERTIES, 272 XML_TOK_STYLE_MAP 273 }; 274 275 enum SvXMLStyleAttrTokens 276 { 277 XML_TOK_STYLE_ATTR_NAME, 278 XML_TOK_STYLE_ATTR_LANGUAGE, 279 XML_TOK_STYLE_ATTR_COUNTRY, 280 XML_TOK_STYLE_ATTR_TITLE, 281 XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER, 282 XML_TOK_STYLE_ATTR_FORMAT_SOURCE, 283 XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW, 284 XML_TOK_STYLE_ATTR_VOLATILE, 285 XML_TOK_STYLE_ATTR_TRANSL_FORMAT, 286 XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE, 287 XML_TOK_STYLE_ATTR_TRANSL_COUNTRY, 288 XML_TOK_STYLE_ATTR_TRANSL_STYLE 289 }; 290 291 enum SvXMLStyleElemAttrTokens 292 { 293 XML_TOK_ELEM_ATTR_DECIMAL_PLACES, 294 XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS, 295 XML_TOK_ELEM_ATTR_GROUPING, 296 XML_TOK_ELEM_ATTR_DISPLAY_FACTOR, 297 XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT, 298 XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS, 299 XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS, 300 XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS, 301 XML_TOK_ELEM_ATTR_LANGUAGE, 302 XML_TOK_ELEM_ATTR_COUNTRY, 303 XML_TOK_ELEM_ATTR_STYLE, 304 XML_TOK_ELEM_ATTR_TEXTUAL, 305 XML_TOK_ELEM_ATTR_CALENDAR 306 }; 307 308 //------------------------------------------------------------------------- 309 310 // 311 // standard colors 312 // 313 314 #define XML_NUMF_COLORCOUNT 10 315 316 static ColorData aNumFmtStdColors[XML_NUMF_COLORCOUNT] = 317 { 318 COL_BLACK, 319 COL_LIGHTBLUE, 320 COL_LIGHTGREEN, 321 COL_LIGHTCYAN, 322 COL_LIGHTRED, 323 COL_LIGHTMAGENTA, 324 COL_BROWN, 325 COL_GRAY, 326 COL_YELLOW, 327 COL_WHITE 328 }; 329 330 // 331 // token maps 332 // 333 334 // maps for SvXMLUnitConverter::convertEnum 335 336 static __FAR_DATA SvXMLEnumMapEntry aStyleValueMap[] = 337 { 338 { XML_SHORT, sal_False }, 339 { XML_LONG, sal_True }, 340 { XML_TOKEN_INVALID, 0 } 341 }; 342 343 static __FAR_DATA SvXMLEnumMapEntry aFormatSourceMap[] = 344 { 345 { XML_FIXED, sal_False }, 346 { XML_LANGUAGE, sal_True }, 347 { XML_TOKEN_INVALID, 0 } 348 }; 349 350 //------------------------------------------------------------------------- 351 352 struct SvXMLDefaultDateFormat 353 { 354 NfIndexTableOffset eFormat; 355 SvXMLDateElementAttributes eDOW; 356 SvXMLDateElementAttributes eDay; 357 SvXMLDateElementAttributes eMonth; 358 SvXMLDateElementAttributes eYear; 359 SvXMLDateElementAttributes eHours; 360 SvXMLDateElementAttributes eMins; 361 SvXMLDateElementAttributes eSecs; 362 sal_Bool bSystem; 363 }; 364 365 static __FAR_DATA SvXMLDefaultDateFormat aDefaultDateFormats[] = 366 { 367 // format day-of-week day month year hours minutes seconds format-source 368 369 { NF_DATE_SYSTEM_SHORT, XML_DEA_NONE, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_True }, 370 { NF_DATE_SYSTEM_LONG, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_True }, 371 { NF_DATE_SYS_MMYY, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_LONG, XML_DEA_SHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False }, 372 { NF_DATE_SYS_DDMMM, XML_DEA_NONE, XML_DEA_LONG, XML_DEA_TEXTSHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False }, 373 { NF_DATE_SYS_DDMMYYYY, XML_DEA_NONE, XML_DEA_LONG, XML_DEA_LONG, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False }, 374 { NF_DATE_SYS_DDMMYY, XML_DEA_NONE, XML_DEA_LONG, XML_DEA_LONG, XML_DEA_SHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False }, 375 { NF_DATE_SYS_DMMMYY, XML_DEA_NONE, XML_DEA_SHORT, XML_DEA_TEXTSHORT, XML_DEA_SHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False }, 376 { NF_DATE_SYS_DMMMYYYY, XML_DEA_NONE, XML_DEA_SHORT, XML_DEA_TEXTSHORT, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False }, 377 { NF_DATE_SYS_DMMMMYYYY, XML_DEA_NONE, XML_DEA_SHORT, XML_DEA_TEXTLONG, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False }, 378 { NF_DATE_SYS_NNDMMMYY, XML_DEA_SHORT, XML_DEA_SHORT, XML_DEA_TEXTSHORT, XML_DEA_SHORT, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False }, 379 { NF_DATE_SYS_NNDMMMMYYYY, XML_DEA_SHORT, XML_DEA_SHORT, XML_DEA_TEXTLONG, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False }, 380 { NF_DATE_SYS_NNNNDMMMMYYYY, XML_DEA_LONG, XML_DEA_SHORT, XML_DEA_TEXTLONG, XML_DEA_LONG, XML_DEA_NONE, XML_DEA_NONE, XML_DEA_NONE, sal_False }, 381 { NF_DATETIME_SYSTEM_SHORT_HHMM, XML_DEA_NONE, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_NONE, sal_True }, 382 { NF_DATETIME_SYS_DDMMYYYY_HHMMSS, XML_DEA_NONE, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, XML_DEA_ANY, sal_False } 383 }; 384 385 //------------------------------------------------------------------------- 386 387 SV_IMPL_PTRARR( SvXMLNumFmtEntryArr, SvXMLNumFmtEntryPtr ); 388 SV_IMPL_OP_PTRARR_SORT( SvXMLEmbeddedElementArr, SvXMLEmbeddedElementPtr ); 389 390 //------------------------------------------------------------------------- 391 392 // 393 // SvXMLNumImpData 394 // 395 396 // #110680# 397 // SvXMLNumImpData::SvXMLNumImpData( SvNumberFormatter* pFmt ) : 398 SvXMLNumImpData::SvXMLNumImpData( 399 SvNumberFormatter* pFmt, 400 const uno::Reference<lang::XMultiServiceFactory>& xServiceFactory ) 401 : pFormatter(pFmt), 402 pStylesElemTokenMap(NULL), 403 pStyleElemTokenMap(NULL), 404 pStyleAttrTokenMap(NULL), 405 pStyleElemAttrTokenMap(NULL), 406 pLocaleData(NULL), 407 408 // #110680# 409 mxServiceFactory(xServiceFactory) 410 { 411 DBG_ASSERT( mxServiceFactory.is(), "got no service manager" ); 412 } 413 414 SvXMLNumImpData::~SvXMLNumImpData() 415 { 416 delete pStylesElemTokenMap; 417 delete pStyleElemTokenMap; 418 delete pStyleAttrTokenMap; 419 delete pStyleElemAttrTokenMap; 420 delete pLocaleData; 421 } 422 423 sal_uInt32 SvXMLNumImpData::GetKeyForName( const rtl::OUString& rName ) 424 { 425 sal_uInt16 nCount = aNameEntries.Count(); 426 for (sal_uInt16 i=0; i<nCount; i++) 427 { 428 const SvXMLNumFmtEntry* pObj = aNameEntries[i]; 429 if ( pObj->aName == rName ) 430 return pObj->nKey; // found 431 } 432 return NUMBERFORMAT_ENTRY_NOT_FOUND; 433 } 434 435 void SvXMLNumImpData::AddKey( sal_uInt32 nKey, const rtl::OUString& rName, sal_Bool bRemoveAfterUse ) 436 { 437 if ( bRemoveAfterUse ) 438 { 439 // if there is already an entry for this key without the bRemoveAfterUse flag, 440 // clear the flag for this entry, too 441 442 sal_uInt16 nCount = aNameEntries.Count(); 443 for (sal_uInt16 i=0; i<nCount; i++) 444 { 445 SvXMLNumFmtEntry* pObj = aNameEntries[i]; 446 if ( pObj->nKey == nKey && !pObj->bRemoveAfterUse ) 447 { 448 bRemoveAfterUse = sal_False; // clear flag for new entry 449 break; 450 } 451 } 452 } 453 else 454 { 455 // call SetUsed to clear the bRemoveAfterUse flag for other entries for this key 456 SetUsed( nKey ); 457 } 458 459 SvXMLNumFmtEntry* pObj = new SvXMLNumFmtEntry( rName, nKey, bRemoveAfterUse ); 460 aNameEntries.Insert( pObj, aNameEntries.Count() ); 461 } 462 463 void SvXMLNumImpData::SetUsed( sal_uInt32 nKey ) 464 { 465 sal_uInt16 nCount = aNameEntries.Count(); 466 for (sal_uInt16 i=0; i<nCount; i++) 467 { 468 SvXMLNumFmtEntry* pObj = aNameEntries[i]; 469 if ( pObj->nKey == nKey ) 470 { 471 pObj->bRemoveAfterUse = sal_False; // used -> don't remove 472 473 // continue searching - there may be several entries for the same key 474 // (with different names), the format must not be deleted if any one of 475 // them is used 476 } 477 } 478 } 479 480 void SvXMLNumImpData::RemoveVolatileFormats() 481 { 482 // remove temporary (volatile) formats from NumberFormatter 483 // called at the end of each import (styles and content), so volatile formats 484 // from styles can't be used in content 485 486 if ( !pFormatter ) 487 return; 488 489 sal_uInt16 nCount = aNameEntries.Count(); 490 for (sal_uInt16 i=0; i<nCount; i++) 491 { 492 const SvXMLNumFmtEntry* pObj = aNameEntries[i]; 493 if ( pObj->bRemoveAfterUse ) 494 { 495 const SvNumberformat* pFormat = pFormatter->GetEntry(pObj->nKey); 496 if (pFormat && (pFormat->GetType() & NUMBERFORMAT_DEFINED)) 497 pFormatter->DeleteEntry( pObj->nKey ); 498 } 499 } 500 } 501 502 const SvXMLTokenMap& SvXMLNumImpData::GetStylesElemTokenMap() 503 { 504 if( !pStylesElemTokenMap ) 505 { 506 static __FAR_DATA SvXMLTokenMapEntry aStylesElemMap[] = 507 { 508 // style elements 509 { XML_NAMESPACE_NUMBER, XML_NUMBER_STYLE, XML_TOK_STYLES_NUMBER_STYLE }, 510 { XML_NAMESPACE_NUMBER, XML_CURRENCY_STYLE, XML_TOK_STYLES_CURRENCY_STYLE }, 511 { XML_NAMESPACE_NUMBER, XML_PERCENTAGE_STYLE, XML_TOK_STYLES_PERCENTAGE_STYLE }, 512 { XML_NAMESPACE_NUMBER, XML_DATE_STYLE, XML_TOK_STYLES_DATE_STYLE }, 513 { XML_NAMESPACE_NUMBER, XML_TIME_STYLE, XML_TOK_STYLES_TIME_STYLE }, 514 { XML_NAMESPACE_NUMBER, XML_BOOLEAN_STYLE, XML_TOK_STYLES_BOOLEAN_STYLE }, 515 { XML_NAMESPACE_NUMBER, XML_TEXT_STYLE, XML_TOK_STYLES_TEXT_STYLE }, 516 XML_TOKEN_MAP_END 517 }; 518 519 pStylesElemTokenMap = new SvXMLTokenMap( aStylesElemMap ); 520 } 521 return *pStylesElemTokenMap; 522 } 523 524 const SvXMLTokenMap& SvXMLNumImpData::GetStyleElemTokenMap() 525 { 526 if( !pStyleElemTokenMap ) 527 { 528 static __FAR_DATA SvXMLTokenMapEntry aStyleElemMap[] = 529 { 530 // elements in a style 531 { XML_NAMESPACE_NUMBER, XML_TEXT, XML_TOK_STYLE_TEXT }, 532 { XML_NAMESPACE_NUMBER, XML_NUMBER, XML_TOK_STYLE_NUMBER }, 533 { XML_NAMESPACE_NUMBER, XML_SCIENTIFIC_NUMBER, XML_TOK_STYLE_SCIENTIFIC_NUMBER }, 534 { XML_NAMESPACE_NUMBER, XML_FRACTION, XML_TOK_STYLE_FRACTION }, 535 { XML_NAMESPACE_NUMBER, XML_CURRENCY_SYMBOL, XML_TOK_STYLE_CURRENCY_SYMBOL }, 536 { XML_NAMESPACE_NUMBER, XML_DAY, XML_TOK_STYLE_DAY }, 537 { XML_NAMESPACE_NUMBER, XML_MONTH, XML_TOK_STYLE_MONTH }, 538 { XML_NAMESPACE_NUMBER, XML_YEAR, XML_TOK_STYLE_YEAR }, 539 { XML_NAMESPACE_NUMBER, XML_ERA, XML_TOK_STYLE_ERA }, 540 { XML_NAMESPACE_NUMBER, XML_DAY_OF_WEEK, XML_TOK_STYLE_DAY_OF_WEEK }, 541 { XML_NAMESPACE_NUMBER, XML_WEEK_OF_YEAR, XML_TOK_STYLE_WEEK_OF_YEAR }, 542 { XML_NAMESPACE_NUMBER, XML_QUARTER, XML_TOK_STYLE_QUARTER }, 543 { XML_NAMESPACE_NUMBER, XML_HOURS, XML_TOK_STYLE_HOURS }, 544 { XML_NAMESPACE_NUMBER, XML_AM_PM, XML_TOK_STYLE_AM_PM }, 545 { XML_NAMESPACE_NUMBER, XML_MINUTES, XML_TOK_STYLE_MINUTES }, 546 { XML_NAMESPACE_NUMBER, XML_SECONDS, XML_TOK_STYLE_SECONDS }, 547 { XML_NAMESPACE_NUMBER, XML_BOOLEAN, XML_TOK_STYLE_BOOLEAN }, 548 { XML_NAMESPACE_NUMBER, XML_TEXT_CONTENT, XML_TOK_STYLE_TEXT_CONTENT }, 549 { XML_NAMESPACE_STYLE, XML_TEXT_PROPERTIES, XML_TOK_STYLE_PROPERTIES }, 550 { XML_NAMESPACE_STYLE, XML_MAP, XML_TOK_STYLE_MAP }, 551 XML_TOKEN_MAP_END 552 }; 553 554 pStyleElemTokenMap = new SvXMLTokenMap( aStyleElemMap ); 555 } 556 return *pStyleElemTokenMap; 557 } 558 559 const SvXMLTokenMap& SvXMLNumImpData::GetStyleAttrTokenMap() 560 { 561 if( !pStyleAttrTokenMap ) 562 { 563 static __FAR_DATA SvXMLTokenMapEntry aStyleAttrMap[] = 564 { 565 // attributes for a style 566 { XML_NAMESPACE_STYLE, XML_NAME, XML_TOK_STYLE_ATTR_NAME }, 567 { XML_NAMESPACE_NUMBER, XML_LANGUAGE, XML_TOK_STYLE_ATTR_LANGUAGE }, 568 { XML_NAMESPACE_NUMBER, XML_COUNTRY, XML_TOK_STYLE_ATTR_COUNTRY }, 569 { XML_NAMESPACE_NUMBER, XML_TITLE, XML_TOK_STYLE_ATTR_TITLE }, 570 { XML_NAMESPACE_NUMBER, XML_AUTOMATIC_ORDER, XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER }, 571 { XML_NAMESPACE_NUMBER, XML_FORMAT_SOURCE, XML_TOK_STYLE_ATTR_FORMAT_SOURCE }, 572 { XML_NAMESPACE_NUMBER, XML_TRUNCATE_ON_OVERFLOW, XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW }, 573 { XML_NAMESPACE_STYLE, XML_VOLATILE, XML_TOK_STYLE_ATTR_VOLATILE }, 574 { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_FORMAT, XML_TOK_STYLE_ATTR_TRANSL_FORMAT }, 575 { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_LANGUAGE, XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE }, 576 { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_COUNTRY, XML_TOK_STYLE_ATTR_TRANSL_COUNTRY }, 577 { XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_STYLE, XML_TOK_STYLE_ATTR_TRANSL_STYLE }, 578 XML_TOKEN_MAP_END 579 }; 580 581 pStyleAttrTokenMap = new SvXMLTokenMap( aStyleAttrMap ); 582 } 583 return *pStyleAttrTokenMap; 584 } 585 586 const SvXMLTokenMap& SvXMLNumImpData::GetStyleElemAttrTokenMap() 587 { 588 if( !pStyleElemAttrTokenMap ) 589 { 590 static __FAR_DATA SvXMLTokenMapEntry aStyleElemAttrMap[] = 591 { 592 // attributes for an element within a style 593 { XML_NAMESPACE_NUMBER, XML_DECIMAL_PLACES, XML_TOK_ELEM_ATTR_DECIMAL_PLACES }, 594 { XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS, XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS }, 595 { XML_NAMESPACE_NUMBER, XML_GROUPING, XML_TOK_ELEM_ATTR_GROUPING }, 596 { XML_NAMESPACE_NUMBER, XML_DISPLAY_FACTOR, XML_TOK_ELEM_ATTR_DISPLAY_FACTOR }, 597 { XML_NAMESPACE_NUMBER, XML_DECIMAL_REPLACEMENT, XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT }, 598 { XML_NAMESPACE_NUMBER, XML_MIN_EXPONENT_DIGITS, XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS }, 599 { XML_NAMESPACE_NUMBER, XML_MIN_NUMERATOR_DIGITS, XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS }, 600 { XML_NAMESPACE_NUMBER, XML_MIN_DENOMINATOR_DIGITS, XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS }, 601 { XML_NAMESPACE_NUMBER, XML_LANGUAGE, XML_TOK_ELEM_ATTR_LANGUAGE }, 602 { XML_NAMESPACE_NUMBER, XML_COUNTRY, XML_TOK_ELEM_ATTR_COUNTRY }, 603 { XML_NAMESPACE_NUMBER, XML_STYLE, XML_TOK_ELEM_ATTR_STYLE }, 604 { XML_NAMESPACE_NUMBER, XML_TEXTUAL, XML_TOK_ELEM_ATTR_TEXTUAL }, 605 { XML_NAMESPACE_NUMBER, XML_CALENDAR, XML_TOK_ELEM_ATTR_CALENDAR }, 606 XML_TOKEN_MAP_END 607 }; 608 609 pStyleElemAttrTokenMap = new SvXMLTokenMap( aStyleElemAttrMap ); 610 } 611 return *pStyleElemAttrTokenMap; 612 } 613 614 const LocaleDataWrapper& SvXMLNumImpData::GetLocaleData( LanguageType nLang ) 615 { 616 if ( !pLocaleData ) 617 // #110680# 618 //pLocaleData = new LocaleDataWrapper( 619 // (pFormatter ? pFormatter->GetServiceManager() : 620 // ::comphelper::getProcessServiceFactory()), 621 // MsLangId::convertLanguageToLocale( nLang ) ); 622 pLocaleData = new LocaleDataWrapper( 623 (pFormatter ? pFormatter->GetServiceManager() : 624 mxServiceFactory), 625 MsLangId::convertLanguageToLocale( nLang ) ); 626 else 627 pLocaleData->setLocale( MsLangId::convertLanguageToLocale( nLang ) ); 628 return *pLocaleData; 629 } 630 631 //------------------------------------------------------------------------- 632 633 // 634 // SvXMLNumFmtMapContext 635 // 636 637 SvXMLNumFmtMapContext::SvXMLNumFmtMapContext( SvXMLImport& rImport, 638 sal_uInt16 nPrfx, const rtl::OUString& rLName, 639 SvXMLNumFormatContext& rParentContext, 640 const uno::Reference<xml::sax::XAttributeList>& xAttrList ) : 641 SvXMLImportContext( rImport, nPrfx, rLName ), 642 rParent( rParentContext ) 643 { 644 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; 645 for( sal_Int16 i=0; i < nAttrCount; i++ ) 646 { 647 OUString sAttrName = xAttrList->getNameByIndex( i ); 648 OUString sValue = xAttrList->getValueByIndex( i ); 649 OUString aLocalName; 650 sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName ); 651 if ( nPrefix == XML_NAMESPACE_STYLE ) 652 { 653 if ( IsXMLToken( aLocalName, XML_CONDITION) ) 654 sCondition = sValue; 655 else if ( IsXMLToken( aLocalName, XML_APPLY_STYLE_NAME) ) 656 sName = sValue; 657 } 658 } 659 } 660 661 SvXMLNumFmtMapContext::~SvXMLNumFmtMapContext() 662 { 663 } 664 665 SvXMLImportContext* SvXMLNumFmtMapContext::CreateChildContext( 666 sal_uInt16 nPrfx, const rtl::OUString& rLName, 667 const uno::Reference<xml::sax::XAttributeList>& ) 668 { 669 // no elements supported - use default context 670 return new SvXMLImportContext( GetImport(), nPrfx, rLName ); 671 } 672 673 void SvXMLNumFmtMapContext::Characters( const rtl::OUString& ) 674 { 675 } 676 677 void SvXMLNumFmtMapContext::EndElement() 678 { 679 rParent.AddCondition( sCondition, sName ); 680 } 681 682 //------------------------------------------------------------------------- 683 684 // 685 // SvXMLNumFmtPropContext 686 // 687 688 SvXMLNumFmtPropContext::SvXMLNumFmtPropContext( SvXMLImport& rImport, 689 sal_uInt16 nPrfx, const rtl::OUString& rLName, 690 SvXMLNumFormatContext& rParentContext, 691 const uno::Reference<xml::sax::XAttributeList>& xAttrList ) : 692 SvXMLImportContext( rImport, nPrfx, rLName ), 693 rParent( rParentContext ), 694 bColSet( sal_False ) 695 { 696 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; 697 for( sal_Int16 i=0; i < nAttrCount; i++ ) 698 { 699 OUString sAttrName = xAttrList->getNameByIndex( i ); 700 OUString sValue = xAttrList->getValueByIndex( i ); 701 OUString aLocalName; 702 sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName ); 703 if ( nPrefix == XML_NAMESPACE_FO && IsXMLToken( aLocalName, XML_COLOR ) ) 704 bColSet = SvXMLUnitConverter::convertColor( aColor, sValue ); 705 } 706 } 707 708 SvXMLNumFmtPropContext::~SvXMLNumFmtPropContext() 709 { 710 } 711 712 SvXMLImportContext* SvXMLNumFmtPropContext::CreateChildContext( 713 sal_uInt16 nPrfx, const rtl::OUString& rLName, 714 const uno::Reference<xml::sax::XAttributeList>& ) 715 { 716 // no elements supported - use default context 717 return new SvXMLImportContext( GetImport(), nPrfx, rLName ); 718 } 719 720 void SvXMLNumFmtPropContext::Characters( const rtl::OUString& ) 721 { 722 } 723 724 void SvXMLNumFmtPropContext::EndElement() 725 { 726 if (bColSet) 727 rParent.AddColor( aColor ); 728 } 729 730 //------------------------------------------------------------------------- 731 732 // 733 // SvXMLNumFmtEmbeddedTextContext 734 // 735 736 SvXMLNumFmtEmbeddedTextContext::SvXMLNumFmtEmbeddedTextContext( SvXMLImport& rImport, 737 sal_uInt16 nPrfx, const rtl::OUString& rLName, 738 SvXMLNumFmtElementContext& rParentContext, 739 const uno::Reference<xml::sax::XAttributeList>& xAttrList ) : 740 SvXMLImportContext( rImport, nPrfx, rLName ), 741 rParent( rParentContext ), 742 nTextPosition( 0 ) 743 { 744 sal_Int32 nAttrVal; 745 746 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; 747 for( sal_Int16 i=0; i < nAttrCount; i++ ) 748 { 749 OUString sAttrName = xAttrList->getNameByIndex( i ); 750 OUString sValue = xAttrList->getValueByIndex( i ); 751 OUString aLocalName; 752 sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName ); 753 if ( nPrefix == XML_NAMESPACE_NUMBER && IsXMLToken( aLocalName, XML_POSITION ) ) 754 { 755 if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) ) 756 nTextPosition = nAttrVal; 757 } 758 } 759 } 760 761 SvXMLNumFmtEmbeddedTextContext::~SvXMLNumFmtEmbeddedTextContext() 762 { 763 } 764 765 SvXMLImportContext* SvXMLNumFmtEmbeddedTextContext::CreateChildContext( 766 sal_uInt16 nPrfx, const rtl::OUString& rLName, 767 const uno::Reference<xml::sax::XAttributeList>& ) 768 { 769 // no elements supported - use default context 770 return new SvXMLImportContext( GetImport(), nPrfx, rLName ); 771 } 772 773 void SvXMLNumFmtEmbeddedTextContext::Characters( const rtl::OUString& rChars ) 774 { 775 aContent.append( rChars ); 776 } 777 778 void SvXMLNumFmtEmbeddedTextContext::EndElement() 779 { 780 rParent.AddEmbeddedElement( nTextPosition, aContent.makeStringAndClear() ); 781 } 782 783 //------------------------------------------------------------------------- 784 785 sal_Bool lcl_ValidChar( sal_Unicode cChar, const SvXMLNumFormatContext& rParent ) 786 { 787 sal_uInt16 nFormatType = rParent.GetType(); 788 789 // Treat space equal to non-breaking space separator. 790 const sal_Unicode cNBSP = 0x00A0; 791 sal_Unicode cTS; 792 if ( ( nFormatType == XML_TOK_STYLES_NUMBER_STYLE || 793 nFormatType == XML_TOK_STYLES_CURRENCY_STYLE || 794 nFormatType == XML_TOK_STYLES_PERCENTAGE_STYLE ) && 795 (cChar == (cTS = rParent.GetLocaleData().getNumThousandSep().GetChar(0)) || 796 (cChar == ' ' && cTS == cNBSP)) ) 797 { 798 // #i22394# Extra occurrences of thousands separator must be quoted, so they 799 // aren't mis-interpreted as display-factor. 800 // This must be limited to the format types that can contain a number element, 801 // because the same character can be a date separator that should not be quoted 802 // in date formats. 803 804 return sal_False; // force quotes 805 } 806 807 // see ImpSvNumberformatScan::Next_Symbol 808 if ( cChar == ' ' || 809 cChar == '-' || 810 cChar == '/' || 811 cChar == '.' || 812 cChar == ',' || 813 cChar == ':' || 814 cChar == '\'' ) 815 return sal_True; // for all format types 816 817 // percent sign must be used without quotes for percentage styles only 818 if ( nFormatType == XML_TOK_STYLES_PERCENTAGE_STYLE && cChar == '%' ) 819 return sal_True; 820 821 // don't put quotes around single parentheses (often used for negative numbers) 822 if ( ( nFormatType == XML_TOK_STYLES_NUMBER_STYLE || 823 nFormatType == XML_TOK_STYLES_CURRENCY_STYLE || 824 nFormatType == XML_TOK_STYLES_PERCENTAGE_STYLE ) && 825 ( cChar == '(' || cChar == ')' ) ) 826 return sal_True; 827 828 return sal_False; 829 } 830 831 void lcl_EnquoteIfNecessary( rtl::OUStringBuffer& rContent, const SvXMLNumFormatContext& rParent ) 832 { 833 sal_Bool bQuote = sal_True; 834 sal_Int32 nLength = rContent.getLength(); 835 836 if ( ( nLength == 1 && 837 lcl_ValidChar( rContent.charAt(0), rParent ) ) || 838 ( nLength == 2 && 839 lcl_ValidChar( rContent.charAt(0), rParent ) && 840 rContent.charAt(1) == ' ' ) ) 841 { 842 // don't quote single separator characters like space or percent, 843 // or separator characters followed by space (used in date formats) 844 bQuote = sal_False; 845 } 846 else if ( rParent.GetType() == XML_TOK_STYLES_PERCENTAGE_STYLE && nLength > 1 ) 847 { 848 // the percent character in percentage styles must be left out of quoting 849 // (one occurence is enough even if there are several percent characters in the string) 850 851 rtl::OUString aString( rContent.getStr() ); 852 sal_Int32 nPos = aString.indexOf( (sal_Unicode) '%' ); 853 if ( nPos >= 0 ) 854 { 855 if ( nPos + 1 < nLength ) 856 { 857 if ( nPos + 2 == nLength && lcl_ValidChar( rContent.charAt(nPos + 1), rParent ) ) 858 { 859 // single character that doesn't need quoting 860 } 861 else 862 { 863 // quote text behind percent character 864 rContent.insert( nPos + 1, (sal_Unicode) '"' ); 865 rContent.append( (sal_Unicode) '"' ); 866 } 867 } 868 if ( nPos > 0 ) 869 { 870 if ( nPos == 1 && lcl_ValidChar( rContent.charAt(0), rParent ) ) 871 { 872 // single character that doesn't need quoting 873 } 874 else 875 { 876 // quote text before percent character 877 rContent.insert( nPos, (sal_Unicode) '"' ); 878 rContent.insert( 0, (sal_Unicode) '"' ); 879 } 880 } 881 bQuote = sal_False; 882 } 883 // else: normal quoting (below) 884 } 885 886 if ( bQuote ) 887 { 888 // #i55469# quotes in the string itself have to be escaped 889 rtl::OUString aString( rContent.getStr() ); 890 bool bEscape = ( aString.indexOf( (sal_Unicode) '"' ) >= 0 ); 891 if ( bEscape ) 892 { 893 // A quote is turned into "\"" - a quote to end quoted text, an escaped quote, 894 // and a quote to resume quoting. 895 rtl::OUString aInsert( rtl::OUString::createFromAscii( "\"\\\"" ) ); 896 897 sal_Int32 nPos = 0; 898 while ( nPos < rContent.getLength() ) 899 { 900 if ( rContent.charAt( nPos ) == (sal_Unicode) '"' ) 901 { 902 rContent.insert( nPos, aInsert ); 903 nPos += aInsert.getLength(); 904 } 905 ++nPos; 906 } 907 } 908 909 // quote string literals 910 rContent.insert( 0, (sal_Unicode) '"' ); 911 rContent.append( (sal_Unicode) '"' ); 912 913 // remove redundant double quotes at start or end 914 if ( bEscape ) 915 { 916 if ( rContent.getLength() > 2 && 917 rContent.charAt(0) == (sal_Unicode) '"' && 918 rContent.charAt(1) == (sal_Unicode) '"' ) 919 { 920 String aTrimmed( rContent.makeStringAndClear().copy(2) ); 921 rContent = rtl::OUStringBuffer( aTrimmed ); 922 } 923 924 sal_Int32 nLen = rContent.getLength(); 925 if ( nLen > 2 && 926 rContent.charAt(nLen-1) == (sal_Unicode) '"' && 927 rContent.charAt(nLen-2) == (sal_Unicode) '"' ) 928 { 929 String aTrimmed( rContent.makeStringAndClear().copy( 0, nLen - 2 ) ); 930 rContent = rtl::OUStringBuffer( aTrimmed ); 931 } 932 } 933 } 934 } 935 936 // 937 // SvXMLNumFmtElementContext 938 // 939 940 SvXMLNumFmtElementContext::SvXMLNumFmtElementContext( SvXMLImport& rImport, 941 sal_uInt16 nPrfx, const rtl::OUString& rLName, 942 SvXMLNumFormatContext& rParentContext, sal_uInt16 nNewType, 943 const uno::Reference<xml::sax::XAttributeList>& xAttrList ) : 944 SvXMLImportContext( rImport, nPrfx, rLName ), 945 rParent( rParentContext ), 946 nType( nNewType ), 947 nElementLang( LANGUAGE_SYSTEM ), 948 bLong( sal_False ), 949 bTextual( sal_False ) 950 { 951 OUString sLanguage, sCountry; 952 sal_Int32 nAttrVal; 953 sal_Bool bAttrBool; 954 sal_uInt16 nAttrEnum; 955 double fAttrDouble; 956 957 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; 958 for( sal_Int16 i=0; i < nAttrCount; i++ ) 959 { 960 OUString sAttrName = xAttrList->getNameByIndex( i ); 961 OUString sValue = xAttrList->getValueByIndex( i ); 962 OUString aLocalName; 963 sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName ); 964 965 const SvXMLTokenMap& rTokenMap = rParent.GetData()->GetStyleElemAttrTokenMap(); 966 sal_uInt16 nToken = rTokenMap.Get( nPrefix, aLocalName ); 967 968 switch (nToken) 969 { 970 case XML_TOK_ELEM_ATTR_DECIMAL_PLACES: 971 if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) ) 972 aNumInfo.nDecimals = nAttrVal; 973 break; 974 case XML_TOK_ELEM_ATTR_MIN_INTEGER_DIGITS: 975 if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) ) 976 aNumInfo.nInteger = nAttrVal; 977 break; 978 case XML_TOK_ELEM_ATTR_GROUPING: 979 if ( SvXMLUnitConverter::convertBool( bAttrBool, sValue ) ) 980 aNumInfo.bGrouping = bAttrBool; 981 break; 982 case XML_TOK_ELEM_ATTR_DISPLAY_FACTOR: 983 if ( SvXMLUnitConverter::convertDouble( fAttrDouble, sValue ) ) 984 aNumInfo.fDisplayFactor = fAttrDouble; 985 break; 986 case XML_TOK_ELEM_ATTR_DECIMAL_REPLACEMENT: 987 if ( sValue.getLength() > 0 ) 988 aNumInfo.bDecReplace = sal_True; // only a default string is supported 989 else 990 aNumInfo.bVarDecimals = sal_True; // empty replacement string: variable decimals 991 break; 992 case XML_TOK_ELEM_ATTR_MIN_EXPONENT_DIGITS: 993 if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) ) 994 aNumInfo.nExpDigits = nAttrVal; 995 break; 996 case XML_TOK_ELEM_ATTR_MIN_NUMERATOR_DIGITS: 997 if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) ) 998 aNumInfo.nNumerDigits = nAttrVal; 999 break; 1000 case XML_TOK_ELEM_ATTR_MIN_DENOMINATOR_DIGITS: 1001 if ( SvXMLUnitConverter::convertNumber( nAttrVal, sValue, 0 ) ) 1002 aNumInfo.nDenomDigits = nAttrVal; 1003 break; 1004 case XML_TOK_ELEM_ATTR_LANGUAGE: 1005 sLanguage = sValue; 1006 break; 1007 case XML_TOK_ELEM_ATTR_COUNTRY: 1008 sCountry = sValue; 1009 break; 1010 case XML_TOK_ELEM_ATTR_STYLE: 1011 if ( SvXMLUnitConverter::convertEnum( nAttrEnum, sValue, aStyleValueMap ) ) 1012 bLong = (sal_Bool) nAttrEnum; 1013 break; 1014 case XML_TOK_ELEM_ATTR_TEXTUAL: 1015 if ( SvXMLUnitConverter::convertBool( bAttrBool, sValue ) ) 1016 bTextual = bAttrBool; 1017 break; 1018 case XML_TOK_ELEM_ATTR_CALENDAR: 1019 sCalendar = sValue; 1020 break; 1021 } 1022 } 1023 1024 if ( sLanguage.getLength() || sCountry.getLength() ) 1025 { 1026 nElementLang = MsLangId::convertIsoNamesToLanguage( sLanguage, sCountry ); 1027 if ( nElementLang == LANGUAGE_DONTKNOW ) 1028 nElementLang = LANGUAGE_SYSTEM; //! error handling for invalid locales? 1029 } 1030 } 1031 1032 SvXMLNumFmtElementContext::~SvXMLNumFmtElementContext() 1033 { 1034 } 1035 1036 SvXMLImportContext* SvXMLNumFmtElementContext::CreateChildContext( 1037 sal_uInt16 nPrfx, const rtl::OUString& rLName, 1038 const uno::Reference<xml::sax::XAttributeList>& xAttrList ) 1039 { 1040 // only number:number supports number:embedded-text child element 1041 1042 if ( nType == XML_TOK_STYLE_NUMBER && 1043 nPrfx == XML_NAMESPACE_NUMBER && IsXMLToken( rLName, XML_EMBEDDED_TEXT ) ) 1044 { 1045 return new SvXMLNumFmtEmbeddedTextContext( GetImport(), nPrfx, rLName, *this, xAttrList ); 1046 } 1047 else 1048 return new SvXMLImportContext( GetImport(), nPrfx, rLName ); 1049 } 1050 1051 void SvXMLNumFmtElementContext::Characters( const rtl::OUString& rChars ) 1052 { 1053 aContent.append( rChars ); 1054 } 1055 1056 void SvXMLNumFmtElementContext::AddEmbeddedElement( sal_Int32 nFormatPos, const rtl::OUString& rContent ) 1057 { 1058 if ( rContent.getLength() ) 1059 { 1060 SvXMLEmbeddedElement* pObj = new SvXMLEmbeddedElement( nFormatPos, rContent ); 1061 if ( !aNumInfo.aEmbeddedElements.Insert( pObj ) ) 1062 { 1063 // there's already an element at this position - append text to existing element 1064 1065 delete pObj; 1066 sal_uInt16 nElementCount = aNumInfo.aEmbeddedElements.Count(); 1067 for (sal_uInt16 i=0; i<nElementCount; i++) 1068 { 1069 pObj = aNumInfo.aEmbeddedElements[i]; 1070 if ( pObj->nFormatPos == nFormatPos ) 1071 { 1072 pObj->aText += rContent; 1073 break; 1074 } 1075 } 1076 } 1077 } 1078 } 1079 1080 void SvXMLNumFmtElementContext::EndElement() 1081 { 1082 sal_Bool bEffLong = bLong; 1083 switch (nType) 1084 { 1085 case XML_TOK_STYLE_TEXT: 1086 if ( rParent.HasLongDoW() && 1087 rParent.GetLocaleData().getLongDateDayOfWeekSep() == 1088 String( aContent.getStr() ) ) 1089 { 1090 // skip separator constant after long day of week 1091 // (NF_KEY_NNNN contains the separator) 1092 1093 if ( rParent.ReplaceNfKeyword( NF_KEY_NNN, NF_KEY_NNNN ) ) 1094 { 1095 //!aContent.setLength(0); //! doesn't work, #76293# 1096 aContent = OUStringBuffer(); 1097 } 1098 1099 rParent.SetHasLongDoW( sal_False ); // only once 1100 } 1101 if ( aContent.getLength() ) 1102 { 1103 lcl_EnquoteIfNecessary( aContent, rParent ); 1104 rParent.AddToCode( aContent.makeStringAndClear() ); 1105 } 1106 break; 1107 1108 case XML_TOK_STYLE_NUMBER: 1109 rParent.AddNumber( aNumInfo ); 1110 break; 1111 1112 case XML_TOK_STYLE_CURRENCY_SYMBOL: 1113 rParent.AddCurrency( aContent.makeStringAndClear(), nElementLang ); 1114 break; 1115 1116 case XML_TOK_STYLE_TEXT_CONTENT: 1117 rParent.AddToCode( OUString::valueOf((sal_Unicode)'@') ); 1118 break; 1119 case XML_TOK_STYLE_BOOLEAN: 1120 // ignored - only default boolean format is supported 1121 break; 1122 1123 case XML_TOK_STYLE_DAY: 1124 rParent.UpdateCalendar( sCalendar ); 1125 #if 0 1126 //! I18N doesn't provide SYSTEM or extended date information yet 1127 if ( rParent.IsFromSystem() ) 1128 bEffLong = SvXMLNumFmtDefaults::IsSystemLongDay( rParent.GetInternational(), bLong ); 1129 #endif 1130 rParent.AddNfKeyword( 1131 sal::static_int_cast< sal_uInt16 >( 1132 bEffLong ? NF_KEY_DD : NF_KEY_D ) ); 1133 break; 1134 case XML_TOK_STYLE_MONTH: 1135 rParent.UpdateCalendar( sCalendar ); 1136 #if 0 1137 //! I18N doesn't provide SYSTEM or extended date information yet 1138 if ( rParent.IsFromSystem() ) 1139 { 1140 bEffLong = SvXMLNumFmtDefaults::IsSystemLongMonth( rParent.GetInternational(), bLong ); 1141 bTextual = SvXMLNumFmtDefaults::IsSystemTextualMonth( rParent.GetInternational(), bLong ); 1142 } 1143 #endif 1144 rParent.AddNfKeyword( 1145 sal::static_int_cast< sal_uInt16 >( 1146 bTextual 1147 ? ( bEffLong ? NF_KEY_MMMM : NF_KEY_MMM ) 1148 : ( bEffLong ? NF_KEY_MM : NF_KEY_M ) ) ); 1149 break; 1150 case XML_TOK_STYLE_YEAR: 1151 rParent.UpdateCalendar( sCalendar ); 1152 #if 0 1153 //! I18N doesn't provide SYSTEM or extended date information yet 1154 if ( rParent.IsFromSystem() ) 1155 bEffLong = SvXMLNumFmtDefaults::IsSystemLongYear( rParent.GetInternational(), bLong ); 1156 #endif 1157 // Y after G (era) is replaced by E 1158 if ( rParent.HasEra() ) 1159 rParent.AddNfKeyword( 1160 sal::static_int_cast< sal_uInt16 >( 1161 bEffLong ? NF_KEY_EEC : NF_KEY_EC ) ); 1162 else 1163 rParent.AddNfKeyword( 1164 sal::static_int_cast< sal_uInt16 >( 1165 bEffLong ? NF_KEY_YYYY : NF_KEY_YY ) ); 1166 break; 1167 case XML_TOK_STYLE_ERA: 1168 rParent.UpdateCalendar( sCalendar ); 1169 #if 0 1170 //! I18N doesn't provide SYSTEM or extended date information yet 1171 if ( rParent.IsFromSystem() ) 1172 bEffLong = SvXMLNumFmtDefaults::IsSystemLongEra( rParent.GetInternational(), bLong ); 1173 #endif 1174 rParent.AddNfKeyword( 1175 sal::static_int_cast< sal_uInt16 >( 1176 bEffLong ? NF_KEY_GGG : NF_KEY_G ) ); 1177 // HasEra flag is set 1178 break; 1179 case XML_TOK_STYLE_DAY_OF_WEEK: 1180 rParent.UpdateCalendar( sCalendar ); 1181 #if 0 1182 //! I18N doesn't provide SYSTEM or extended date information yet 1183 if ( rParent.IsFromSystem() ) 1184 bEffLong = SvXMLNumFmtDefaults::IsSystemLongDayOfWeek( rParent.GetInternational(), bLong ); 1185 #endif 1186 rParent.AddNfKeyword( 1187 sal::static_int_cast< sal_uInt16 >( 1188 bEffLong ? NF_KEY_NNNN : NF_KEY_NN ) ); 1189 break; 1190 case XML_TOK_STYLE_WEEK_OF_YEAR: 1191 rParent.UpdateCalendar( sCalendar ); 1192 rParent.AddNfKeyword( NF_KEY_WW ); 1193 break; 1194 case XML_TOK_STYLE_QUARTER: 1195 rParent.UpdateCalendar( sCalendar ); 1196 rParent.AddNfKeyword( 1197 sal::static_int_cast< sal_uInt16 >( 1198 bEffLong ? NF_KEY_QQ : NF_KEY_Q ) ); 1199 break; 1200 case XML_TOK_STYLE_HOURS: 1201 rParent.AddNfKeyword( 1202 sal::static_int_cast< sal_uInt16 >( 1203 bEffLong ? NF_KEY_HH : NF_KEY_H ) ); 1204 break; 1205 case XML_TOK_STYLE_AM_PM: 1206 //! short/long? 1207 rParent.AddNfKeyword( NF_KEY_AMPM ); 1208 break; 1209 case XML_TOK_STYLE_MINUTES: 1210 rParent.AddNfKeyword( 1211 sal::static_int_cast< sal_uInt16 >( 1212 bEffLong ? NF_KEY_MMI : NF_KEY_MI ) ); 1213 break; 1214 case XML_TOK_STYLE_SECONDS: 1215 rParent.AddNfKeyword( 1216 sal::static_int_cast< sal_uInt16 >( 1217 bEffLong ? NF_KEY_SS : NF_KEY_S ) ); 1218 if ( aNumInfo.nDecimals > 0 ) 1219 { 1220 // manually add the decimal places 1221 const String& rSep = rParent.GetLocaleData().getNumDecimalSep(); 1222 for ( xub_StrLen j=0; j<rSep.Len(); j++ ) 1223 { 1224 rParent.AddToCode( OUString::valueOf( rSep.GetChar(j) ) ); 1225 } 1226 for (sal_Int32 i=0; i<aNumInfo.nDecimals; i++) 1227 rParent.AddToCode( OUString::valueOf((sal_Unicode)'0') ); 1228 } 1229 break; 1230 1231 case XML_TOK_STYLE_FRACTION: 1232 { 1233 if ( aNumInfo.nInteger >= 0 ) 1234 { 1235 // add integer part only if min-integer-digits attribute is there 1236 aNumInfo.nDecimals = 0; 1237 rParent.AddNumber( aNumInfo ); // number without decimals 1238 rParent.AddToCode( OUString::valueOf((sal_Unicode)' ') ); 1239 } 1240 1241 //! build string and add at once 1242 1243 sal_Int32 i; 1244 for (i=0; i<aNumInfo.nNumerDigits; i++) 1245 rParent.AddToCode( OUString::valueOf((sal_Unicode)'?') ); 1246 rParent.AddToCode( OUString::valueOf((sal_Unicode)'/') ); 1247 for (i=0; i<aNumInfo.nDenomDigits; i++) 1248 rParent.AddToCode( OUString::valueOf((sal_Unicode)'?') ); 1249 } 1250 break; 1251 1252 case XML_TOK_STYLE_SCIENTIFIC_NUMBER: 1253 { 1254 rParent.AddNumber( aNumInfo ); // simple number 1255 1256 rParent.AddToCode( OUString::createFromAscii( "E+" ) ); 1257 for (sal_Int32 i=0; i<aNumInfo.nExpDigits; i++) 1258 rParent.AddToCode( OUString::valueOf((sal_Unicode)'0') ); 1259 } 1260 break; 1261 1262 default: 1263 DBG_ERROR("invalid element ID"); 1264 } 1265 } 1266 1267 //------------------------------------------------------------------------- 1268 1269 sal_Bool SvXMLNumFmtDefaults::IsSystemLongDay( const SvtSysLocale&, sal_Bool bLong ) 1270 { 1271 // TODO: merge system information and defaults into i18n locale data 1272 #if 0 1273 return bLong ? rIntn.IsLongDateDayLeadingZero() : rIntn.IsDateDayLeadingZero(); 1274 #else 1275 return !bLong; 1276 #endif 1277 } 1278 1279 sal_Bool SvXMLNumFmtDefaults::IsSystemLongMonth( const SvtSysLocale&, sal_Bool bLong ) 1280 { 1281 // TODO: merge system information and defaults into i18n locale data 1282 #if 0 1283 if (bLong) 1284 { 1285 MonthFormat eMonth = rIntn.GetLongDateMonthFormat(); 1286 return ( eMonth == MONTH_ZERO || eMonth == MONTH_LONG ); 1287 } 1288 else 1289 return rIntn.IsDateMonthLeadingZero(); 1290 #else 1291 return !bLong; 1292 #endif 1293 } 1294 1295 sal_Bool SvXMLNumFmtDefaults::IsSystemTextualMonth( const SvtSysLocale&, sal_Bool bLong ) 1296 { 1297 // TODO: merge system information and defaults into i18n locale data 1298 #if 0 1299 if (bLong) 1300 { 1301 MonthFormat eMonth = rIntn.GetLongDateMonthFormat(); 1302 return ( eMonth == MONTH_SHORT || eMonth == MONTH_LONG ); 1303 } 1304 else 1305 return sal_False; 1306 #else 1307 return bLong; 1308 #endif 1309 } 1310 1311 sal_Bool SvXMLNumFmtDefaults::IsSystemLongYear( const SvtSysLocale&, sal_Bool bLong ) 1312 { 1313 // TODO: merge system information and defaults into i18n locale data 1314 #if 0 1315 return bLong ? rIntn.IsLongDateCentury() : rIntn.IsDateCentury(); 1316 #else 1317 return bLong; 1318 #endif 1319 } 1320 1321 sal_Bool SvXMLNumFmtDefaults::IsSystemLongEra( const SvtSysLocale& rSysLoc, sal_Bool bLong ) 1322 { 1323 // TODO: merge system information and defaults into i18n locale data 1324 return IsSystemLongYear( rSysLoc, bLong ); // no separate setting 1325 } 1326 1327 sal_Bool SvXMLNumFmtDefaults::IsSystemLongDayOfWeek( const SvtSysLocale&, sal_Bool bLong ) 1328 { 1329 // TODO: merge system information and defaults into i18n locale data 1330 #if 0 1331 return ( bLong && rIntn.GetLongDateDayOfWeekFormat() == DAYOFWEEK_LONG ); 1332 #else 1333 return bLong && true; 1334 #endif 1335 } 1336 1337 sal_uInt16 SvXMLNumFmtDefaults::GetDefaultDateFormat( SvXMLDateElementAttributes eDOW, 1338 SvXMLDateElementAttributes eDay, SvXMLDateElementAttributes eMonth, 1339 SvXMLDateElementAttributes eYear, SvXMLDateElementAttributes eHours, 1340 SvXMLDateElementAttributes eMins, SvXMLDateElementAttributes eSecs, 1341 sal_Bool bSystem ) 1342 { 1343 const sal_uInt16 nCount = sizeof(aDefaultDateFormats) / sizeof(SvXMLDefaultDateFormat); 1344 for (sal_uInt16 nPos=0; nPos<nCount; nPos++) 1345 { 1346 const SvXMLDefaultDateFormat& rEntry = aDefaultDateFormats[nPos]; 1347 if ( bSystem == rEntry.bSystem && 1348 ( eDOW == rEntry.eDOW || ( rEntry.eDOW == XML_DEA_ANY && eDOW != XML_DEA_NONE ) ) && 1349 ( eDay == rEntry.eDay || ( rEntry.eDay == XML_DEA_ANY && eDay != XML_DEA_NONE ) ) && 1350 ( eMonth == rEntry.eMonth || ( rEntry.eMonth == XML_DEA_ANY && eMonth != XML_DEA_NONE ) ) && 1351 ( eYear == rEntry.eYear || ( rEntry.eYear == XML_DEA_ANY && eYear != XML_DEA_NONE ) ) && 1352 ( eHours == rEntry.eHours || ( rEntry.eHours == XML_DEA_ANY && eHours != XML_DEA_NONE ) ) && 1353 ( eMins == rEntry.eMins || ( rEntry.eMins == XML_DEA_ANY && eMins != XML_DEA_NONE ) ) && 1354 ( eSecs == rEntry.eSecs || ( rEntry.eSecs == XML_DEA_ANY && eSecs != XML_DEA_NONE ) ) ) 1355 { 1356 return sal::static_int_cast< sal_uInt16 >(rEntry.eFormat); 1357 } 1358 } 1359 1360 return NF_INDEX_TABLE_ENTRIES; // invalid 1361 } 1362 1363 //------------------------------------------------------------------------- 1364 1365 // 1366 // SvXMLNumFormatContext 1367 // 1368 1369 SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport& rImport, 1370 sal_uInt16 nPrfx, const rtl::OUString& rLName, 1371 SvXMLNumImpData* pNewData, sal_uInt16 nNewType, 1372 const uno::Reference<xml::sax::XAttributeList>& xAttrList, 1373 SvXMLStylesContext& rStyles ) : 1374 SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList ), 1375 pData( pNewData ), 1376 pStyles( &rStyles ), 1377 aMyConditions(), 1378 nType( nNewType ), 1379 nKey(-1), 1380 nFormatLang( LANGUAGE_SYSTEM ), 1381 bAutoOrder( sal_False ), 1382 bFromSystem( sal_False ), 1383 bTruncate( sal_True ), 1384 bAutoDec( sal_False ), 1385 bAutoInt( sal_False ), 1386 bHasExtraText( sal_False ), 1387 bHasLongDoW( sal_False ), 1388 bHasEra( sal_False ), 1389 bHasDateTime( sal_False ), 1390 bRemoveAfterUse( sal_False ), 1391 eDateDOW( XML_DEA_NONE ), 1392 eDateDay( XML_DEA_NONE ), 1393 eDateMonth( XML_DEA_NONE ), 1394 eDateYear( XML_DEA_NONE ), 1395 eDateHours( XML_DEA_NONE ), 1396 eDateMins( XML_DEA_NONE ), 1397 eDateSecs( XML_DEA_NONE ), 1398 bDateNoDefault( sal_False ) 1399 { 1400 OUString sLanguage, sCountry; 1401 ::com::sun::star::i18n::NativeNumberXmlAttributes aNatNumAttr; 1402 sal_Bool bAttrBool; 1403 sal_uInt16 nAttrEnum; 1404 1405 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; 1406 for( sal_Int16 i=0; i < nAttrCount; i++ ) 1407 { 1408 OUString sAttrName = xAttrList->getNameByIndex( i ); 1409 OUString sValue = xAttrList->getValueByIndex( i ); 1410 OUString aLocalName; 1411 sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName ); 1412 1413 const SvXMLTokenMap& rTokenMap = pData->GetStyleAttrTokenMap(); 1414 sal_uInt16 nToken = rTokenMap.Get( nPrefix, aLocalName ); 1415 switch (nToken) 1416 { 1417 case XML_TOK_STYLE_ATTR_NAME: 1418 // aName = sValue; 1419 break; 1420 case XML_TOK_STYLE_ATTR_LANGUAGE: 1421 sLanguage = sValue; 1422 break; 1423 case XML_TOK_STYLE_ATTR_COUNTRY: 1424 sCountry = sValue; 1425 break; 1426 case XML_TOK_STYLE_ATTR_TITLE: 1427 sFormatTitle = sValue; 1428 break; 1429 case XML_TOK_STYLE_ATTR_AUTOMATIC_ORDER: 1430 if ( SvXMLUnitConverter::convertBool( bAttrBool, sValue ) ) 1431 bAutoOrder = bAttrBool; 1432 break; 1433 case XML_TOK_STYLE_ATTR_FORMAT_SOURCE: 1434 if ( SvXMLUnitConverter::convertEnum( nAttrEnum, sValue, aFormatSourceMap ) ) 1435 bFromSystem = (sal_Bool) nAttrEnum; 1436 break; 1437 case XML_TOK_STYLE_ATTR_TRUNCATE_ON_OVERFLOW: 1438 if ( SvXMLUnitConverter::convertBool( bAttrBool, sValue ) ) 1439 bTruncate = bAttrBool; 1440 break; 1441 case XML_TOK_STYLE_ATTR_VOLATILE: 1442 // volatile formats can be removed after importing 1443 // if not used in other styles 1444 if ( SvXMLUnitConverter::convertBool( bAttrBool, sValue ) ) 1445 bRemoveAfterUse = bAttrBool; 1446 break; 1447 case XML_TOK_STYLE_ATTR_TRANSL_FORMAT: 1448 aNatNumAttr.Format = sValue; 1449 break; 1450 case XML_TOK_STYLE_ATTR_TRANSL_LANGUAGE: 1451 aNatNumAttr.Locale.Language = sValue; 1452 break; 1453 case XML_TOK_STYLE_ATTR_TRANSL_COUNTRY: 1454 aNatNumAttr.Locale.Country = sValue; 1455 break; 1456 case XML_TOK_STYLE_ATTR_TRANSL_STYLE: 1457 aNatNumAttr.Style = sValue; 1458 break; 1459 } 1460 } 1461 1462 if ( sLanguage.getLength() || sCountry.getLength() ) 1463 { 1464 nFormatLang = MsLangId::convertIsoNamesToLanguage( sLanguage, sCountry ); 1465 if ( nFormatLang == LANGUAGE_DONTKNOW ) 1466 nFormatLang = LANGUAGE_SYSTEM; //! error handling for invalid locales? 1467 } 1468 1469 if ( aNatNumAttr.Format.getLength() ) 1470 { 1471 SvNumberFormatter* pFormatter = pData->GetNumberFormatter(); 1472 if ( pFormatter ) 1473 { 1474 sal_Int32 nNatNum = pFormatter->GetNatNum()->convertFromXmlAttributes( aNatNumAttr ); 1475 aFormatCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "[NatNum" ) ); 1476 aFormatCode.append( nNatNum, 10 ); 1477 1478 LanguageType eLang = MsLangId::convertLocaleToLanguage( aNatNumAttr.Locale ); 1479 if ( eLang == LANGUAGE_DONTKNOW ) 1480 eLang = LANGUAGE_SYSTEM; //! error handling for invalid locales? 1481 if ( eLang != nFormatLang && eLang != LANGUAGE_SYSTEM ) 1482 { 1483 aFormatCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "][$-" ) ); 1484 // language code in upper hex: 1485 aFormatCode.append( String::CreateFromInt32( sal_Int32( eLang ), 16 ).ToUpperAscii() ); 1486 } 1487 aFormatCode.append( sal_Unicode(']') ); 1488 } 1489 } 1490 } 1491 1492 SvXMLNumFormatContext::SvXMLNumFormatContext( SvXMLImport& rImport, 1493 sal_uInt16 nPrfx, const rtl::OUString& rLName, 1494 const uno::Reference<xml::sax::XAttributeList>& xAttrList, 1495 const sal_Int32 nTempKey, 1496 SvXMLStylesContext& rStyles ) : 1497 SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList, XML_STYLE_FAMILY_DATA_STYLE ), 1498 pData( NULL ), 1499 pStyles( &rStyles ), 1500 aMyConditions(), 1501 nType( 0 ), 1502 nKey(nTempKey), 1503 nFormatLang( LANGUAGE_SYSTEM ), 1504 bAutoOrder( sal_False ), 1505 bFromSystem( sal_False ), 1506 bTruncate( sal_True ), 1507 bAutoDec( sal_False ), 1508 bAutoInt( sal_False ), 1509 bHasExtraText( sal_False ), 1510 bHasLongDoW( sal_False ), 1511 bHasEra( sal_False ), 1512 bHasDateTime( sal_False ), 1513 bRemoveAfterUse( sal_False ), 1514 eDateDOW( XML_DEA_NONE ), 1515 eDateDay( XML_DEA_NONE ), 1516 eDateMonth( XML_DEA_NONE ), 1517 eDateYear( XML_DEA_NONE ), 1518 eDateHours( XML_DEA_NONE ), 1519 eDateMins( XML_DEA_NONE ), 1520 eDateSecs( XML_DEA_NONE ), 1521 bDateNoDefault( sal_False ) 1522 { 1523 SetAttribute(XML_NAMESPACE_STYLE, GetXMLToken(XML_NAME), rLName); 1524 } 1525 1526 SvXMLNumFormatContext::~SvXMLNumFormatContext() 1527 { 1528 } 1529 1530 SvXMLImportContext* SvXMLNumFormatContext::CreateChildContext( 1531 sal_uInt16 nPrfx, const rtl::OUString& rLName, 1532 const uno::Reference<xml::sax::XAttributeList>& xAttrList ) 1533 { 1534 SvXMLImportContext* pContext = NULL; 1535 1536 const SvXMLTokenMap& rTokenMap = pData->GetStyleElemTokenMap(); 1537 sal_uInt16 nToken = rTokenMap.Get( nPrfx, rLName ); 1538 switch (nToken) 1539 { 1540 case XML_TOK_STYLE_TEXT: 1541 case XML_TOK_STYLE_NUMBER: 1542 case XML_TOK_STYLE_SCIENTIFIC_NUMBER: 1543 case XML_TOK_STYLE_FRACTION: 1544 case XML_TOK_STYLE_CURRENCY_SYMBOL: 1545 case XML_TOK_STYLE_DAY: 1546 case XML_TOK_STYLE_MONTH: 1547 case XML_TOK_STYLE_YEAR: 1548 case XML_TOK_STYLE_ERA: 1549 case XML_TOK_STYLE_DAY_OF_WEEK: 1550 case XML_TOK_STYLE_WEEK_OF_YEAR: 1551 case XML_TOK_STYLE_QUARTER: 1552 case XML_TOK_STYLE_HOURS: 1553 case XML_TOK_STYLE_AM_PM: 1554 case XML_TOK_STYLE_MINUTES: 1555 case XML_TOK_STYLE_SECONDS: 1556 case XML_TOK_STYLE_BOOLEAN: 1557 case XML_TOK_STYLE_TEXT_CONTENT: 1558 pContext = new SvXMLNumFmtElementContext( GetImport(), nPrfx, rLName, 1559 *this, nToken, xAttrList ); 1560 break; 1561 1562 case XML_TOK_STYLE_PROPERTIES: 1563 pContext = new SvXMLNumFmtPropContext( GetImport(), nPrfx, rLName, 1564 *this, xAttrList ); 1565 break; 1566 case XML_TOK_STYLE_MAP: 1567 { 1568 // SvXMLNumFmtMapContext::EndElement adds to aMyConditions, 1569 // so there's no need for an extra flag 1570 pContext = new SvXMLNumFmtMapContext( GetImport(), nPrfx, rLName, 1571 *this, xAttrList ); 1572 } 1573 break; 1574 } 1575 1576 if( !pContext ) 1577 pContext = new SvXMLImportContext( GetImport(), nPrfx, rLName ); 1578 return pContext; 1579 } 1580 1581 sal_Int32 SvXMLNumFormatContext::GetKey() 1582 { 1583 if (nKey > -1) 1584 { 1585 if (bRemoveAfterUse) 1586 { 1587 // format is used -> don't remove 1588 bRemoveAfterUse = sal_False; 1589 if (pData) 1590 pData->SetUsed(nKey); 1591 1592 // Add to import's list of keys now - CreateAndInsert didn't add 1593 // the style if bRemoveAfterUse was set. 1594 GetImport().AddNumberStyle( nKey, GetName() ); 1595 } 1596 return nKey; 1597 } 1598 else 1599 { 1600 // reset bRemoveAfterUse before CreateAndInsert, so AddKey is called without bRemoveAfterUse set 1601 bRemoveAfterUse = sal_False; 1602 CreateAndInsert(sal_True); 1603 return nKey; 1604 } 1605 } 1606 1607 sal_Int32 SvXMLNumFormatContext::PrivateGetKey() 1608 { 1609 // used for map elements in CreateAndInsert - don't reset bRemoveAfterUse flag 1610 1611 if (nKey > -1) 1612 return nKey; 1613 else 1614 { 1615 CreateAndInsert(sal_True); 1616 return nKey; 1617 } 1618 } 1619 1620 sal_Int32 SvXMLNumFormatContext::CreateAndInsert( com::sun::star::uno::Reference< com::sun::star::util::XNumberFormatsSupplier >& xFormatsSupplier ) 1621 { 1622 if (nKey <= -1) 1623 { 1624 SvNumberFormatter* pFormatter = NULL; 1625 SvNumberFormatsSupplierObj* pObj = 1626 SvNumberFormatsSupplierObj::getImplementation( xFormatsSupplier ); 1627 if (pObj) 1628 pFormatter = pObj->GetNumberFormatter(); 1629 1630 if ( pFormatter ) 1631 return CreateAndInsert( pFormatter ); 1632 else 1633 return -1; 1634 } 1635 else 1636 return nKey; 1637 } 1638 1639 void SvXMLNumFormatContext::CreateAndInsert(sal_Bool /*bOverwrite*/) 1640 { 1641 if (!(nKey > -1)) 1642 CreateAndInsert(pData->GetNumberFormatter()); 1643 } 1644 1645 sal_Int32 SvXMLNumFormatContext::CreateAndInsert(SvNumberFormatter* pFormatter) 1646 { 1647 if (!pFormatter) 1648 { 1649 DBG_ERROR("no number formatter"); 1650 return -1; 1651 } 1652 1653 sal_uInt32 nIndex = NUMBERFORMAT_ENTRY_NOT_FOUND; 1654 1655 for (sal_uInt32 i = 0; i < aMyConditions.size(); i++) 1656 { 1657 SvXMLNumFormatContext* pStyle = (SvXMLNumFormatContext *)pStyles->FindStyleChildContext( 1658 XML_STYLE_FAMILY_DATA_STYLE, aMyConditions[i].sMapName, sal_False); 1659 if (pStyle) 1660 { 1661 if ((pStyle->PrivateGetKey() > -1)) // don't reset pStyle's bRemoveAfterUse flag 1662 AddCondition(i); 1663 } 1664 } 1665 1666 if ( !aFormatCode.getLength() ) 1667 { 1668 // insert empty format as empty string (with quotes) 1669 // #93901# this check has to be done before inserting the conditions 1670 aFormatCode.appendAscii("\"\""); // "" 1671 } 1672 1673 aFormatCode.insert( 0, aConditions.makeStringAndClear() ); 1674 OUString sFormat = aFormatCode.makeStringAndClear(); 1675 1676 // test special cases 1677 1678 if ( bAutoDec ) // automatic decimal places 1679 { 1680 // #99391# adjust only if the format contains no text elements, no conditions 1681 // and no color definition (detected by the '[' at the start) 1682 1683 if ( nType == XML_TOK_STYLES_NUMBER_STYLE && !bHasExtraText && 1684 aMyConditions.size() == 0 && sFormat.toChar() != (sal_Unicode)'[' ) 1685 nIndex = pFormatter->GetStandardIndex( nFormatLang ); 1686 } 1687 if ( bAutoInt ) // automatic integer digits 1688 { 1689 //! only if two decimal places was set? 1690 1691 if ( nType == XML_TOK_STYLES_NUMBER_STYLE && !bHasExtraText && 1692 aMyConditions.size() == 0 && sFormat.toChar() != (sal_Unicode)'[' ) 1693 nIndex = pFormatter->GetFormatIndex( NF_NUMBER_SYSTEM, nFormatLang ); 1694 } 1695 1696 // boolean is always the builtin boolean format 1697 // (no other boolean formats are implemented) 1698 if ( nType == XML_TOK_STYLES_BOOLEAN_STYLE ) 1699 nIndex = pFormatter->GetFormatIndex( NF_BOOLEAN, nFormatLang ); 1700 1701 // check for default date formats 1702 if ( nType == XML_TOK_STYLES_DATE_STYLE && bAutoOrder && !bDateNoDefault ) 1703 { 1704 NfIndexTableOffset eFormat = (NfIndexTableOffset) SvXMLNumFmtDefaults::GetDefaultDateFormat( 1705 eDateDOW, eDateDay, eDateMonth, eDateYear, 1706 eDateHours, eDateMins, eDateSecs, bFromSystem ); 1707 if ( eFormat < NF_INDEX_TABLE_ENTRIES ) 1708 { 1709 // #109651# if a date format has the automatic-order attribute and 1710 // contains exactly the elements of one of the default date formats, 1711 // use that default format, with the element order and separators 1712 // from the current locale settings 1713 1714 nIndex = pFormatter->GetFormatIndex( eFormat, nFormatLang ); 1715 } 1716 } 1717 1718 if ( nIndex == NUMBERFORMAT_ENTRY_NOT_FOUND && sFormat.getLength() ) 1719 { 1720 // insert by format string 1721 1722 String aFormatStr( sFormat ); 1723 nIndex = pFormatter->GetEntryKey( aFormatStr, nFormatLang ); 1724 if ( nIndex == NUMBERFORMAT_ENTRY_NOT_FOUND ) 1725 { 1726 xub_StrLen nErrPos = 0; 1727 short l_nType = 0; 1728 sal_Bool bOk = pFormatter->PutEntry( aFormatStr, nErrPos, l_nType, nIndex, nFormatLang ); 1729 if ( !bOk && nErrPos == 0 && aFormatStr != String(sFormat) ) 1730 { 1731 // if the string was modified by PutEntry, look for an existing format 1732 // with the modified string 1733 nIndex = pFormatter->GetEntryKey( aFormatStr, nFormatLang ); 1734 if ( nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND ) 1735 bOk = sal_True; 1736 } 1737 if (!bOk) 1738 nIndex = NUMBERFORMAT_ENTRY_NOT_FOUND; 1739 } 1740 } 1741 1742 #if 0 1743 //! I18N doesn't provide SYSTEM or extended date information yet 1744 if ( nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND && !bFromSystem ) 1745 { 1746 // instead of automatic date format, use fixed formats if bFromSystem is not set 1747 //! prevent use of automatic formats in other cases, force user-defined format? 1748 1749 sal_uInt32 nNewIndex = nIndex; 1750 1751 NfIndexTableOffset eOffset = pFormatter->GetIndexTableOffset( nIndex ); 1752 if ( eOffset == NF_DATE_SYSTEM_SHORT ) 1753 { 1754 const International& rInt = pData->GetInternational( nFormatLang ); 1755 if ( rInt.IsDateDayLeadingZero() && rInt.IsDateMonthLeadingZero() ) 1756 { 1757 if ( rInt.IsDateCentury() ) 1758 nNewIndex = pFormatter->GetFormatIndex( NF_DATE_SYS_DDMMYYYY, nFormatLang ); 1759 else 1760 nNewIndex = pFormatter->GetFormatIndex( NF_DATE_SYS_DDMMYY, nFormatLang ); 1761 } 1762 } 1763 else if ( eOffset == NF_DATE_SYSTEM_LONG ) 1764 { 1765 const International& rInt = pData->GetInternational( nFormatLang ); 1766 if ( !rInt.IsLongDateDayLeadingZero() ) 1767 { 1768 sal_Bool bCentury = rInt.IsLongDateCentury(); 1769 MonthFormat eMonth = rInt.GetLongDateMonthFormat(); 1770 if ( eMonth == MONTH_LONG && bCentury ) 1771 { 1772 if ( rInt.GetLongDateDayOfWeekFormat() == DAYOFWEEK_LONG ) 1773 nNewIndex = pFormatter->GetFormatIndex( NF_DATE_SYS_NNNNDMMMMYYYY, nFormatLang ); 1774 else 1775 nNewIndex = pFormatter->GetFormatIndex( NF_DATE_SYS_NNDMMMMYYYY, nFormatLang ); 1776 } 1777 else if ( eMonth == MONTH_SHORT && !bCentury ) 1778 nNewIndex = pFormatter->GetFormatIndex( NF_DATE_SYS_NNDMMMYY, nFormatLang ); 1779 } 1780 } 1781 1782 if ( nNewIndex != nIndex ) 1783 { 1784 // verify the fixed format really matches the format string 1785 // (not the case with some formats from locale data) 1786 1787 const SvNumberformat* pFixedFormat = pFormatter->GetEntry( nNewIndex ); 1788 if ( pFixedFormat && pFixedFormat->GetFormatstring() == String(sFormat) ) 1789 nIndex = nNewIndex; 1790 } 1791 } 1792 #endif 1793 1794 if ( nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND && !bAutoOrder ) 1795 { 1796 // use fixed-order formats instead of SYS... if bAutoOrder is false 1797 // (only if the format strings are equal for the locale) 1798 1799 NfIndexTableOffset eOffset = pFormatter->GetIndexTableOffset( nIndex ); 1800 if ( eOffset == NF_DATE_SYS_DMMMYYYY ) 1801 { 1802 sal_uInt32 nNewIndex = pFormatter->GetFormatIndex( NF_DATE_DIN_DMMMYYYY, nFormatLang ); 1803 const SvNumberformat* pOldEntry = pFormatter->GetEntry( nIndex ); 1804 const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewIndex ); 1805 if ( pOldEntry && pNewEntry && pOldEntry->GetFormatstring() == pNewEntry->GetFormatstring() ) 1806 nIndex = nNewIndex; 1807 } 1808 else if ( eOffset == NF_DATE_SYS_DMMMMYYYY ) 1809 { 1810 sal_uInt32 nNewIndex = pFormatter->GetFormatIndex( NF_DATE_DIN_DMMMMYYYY, nFormatLang ); 1811 const SvNumberformat* pOldEntry = pFormatter->GetEntry( nIndex ); 1812 const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewIndex ); 1813 if ( pOldEntry && pNewEntry && pOldEntry->GetFormatstring() == pNewEntry->GetFormatstring() ) 1814 nIndex = nNewIndex; 1815 } 1816 } 1817 1818 if ((nIndex != NUMBERFORMAT_ENTRY_NOT_FOUND) && sFormatTitle.getLength()) 1819 { 1820 SvNumberformat* pFormat = const_cast<SvNumberformat*>(pFormatter->GetEntry( nIndex )); 1821 if (pFormat) 1822 { 1823 String sTitle (sFormatTitle); 1824 pFormat->SetComment(sTitle); 1825 } 1826 } 1827 1828 if ( nIndex == NUMBERFORMAT_ENTRY_NOT_FOUND ) 1829 { 1830 DBG_ERROR("invalid number format"); 1831 nIndex = pFormatter->GetStandardIndex( nFormatLang ); 1832 } 1833 1834 pData->AddKey( nIndex, GetName(), bRemoveAfterUse ); 1835 nKey = nIndex; 1836 1837 // Add to import's list of keys (shared between styles and content import) 1838 // only if not volatile - formats are removed from NumberFormatter at the 1839 // end of each import (in SvXMLNumFmtHelper dtor). 1840 // If bRemoveAfterUse is reset later in GetKey, AddNumberStyle is called there. 1841 1842 if (!bRemoveAfterUse) 1843 GetImport().AddNumberStyle( nKey, GetName() ); 1844 1845 #if 0 1846 ByteString aByte( String(sFormatName), gsl_getSystemTextEncoding() ); 1847 aByte.Append( " | " ); 1848 aByte.Append(ByteString( String(sFormat), gsl_getSystemTextEncoding() )); 1849 aByte.Append( " | " ); 1850 aByte.Append(ByteString::CreateFromInt32( nIndex )); 1851 1852 // DBG_ERROR(aByte.GetBuffer()); 1853 int xxx=42; 1854 #endif 1855 1856 return nKey; 1857 } 1858 1859 void SvXMLNumFormatContext::Finish( sal_Bool bOverwrite ) 1860 { 1861 SvXMLStyleContext::Finish( bOverwrite ); 1862 // AddCondition(); 1863 } 1864 1865 const LocaleDataWrapper& SvXMLNumFormatContext::GetLocaleData() const 1866 { 1867 return pData->GetLocaleData( nFormatLang ); 1868 } 1869 1870 void SvXMLNumFormatContext::AddToCode( const rtl::OUString& rString ) 1871 { 1872 aFormatCode.append( rString ); 1873 bHasExtraText = sal_True; 1874 } 1875 1876 void SvXMLNumFormatContext::AddNumber( const SvXMLNumberInfo& rInfo ) 1877 { 1878 SvNumberFormatter* pFormatter = pData->GetNumberFormatter(); 1879 if (!pFormatter) 1880 return; 1881 1882 // store special conditions 1883 bAutoDec = ( rInfo.nDecimals < 0 ); 1884 bAutoInt = ( rInfo.nInteger < 0 ); 1885 1886 sal_uInt16 nPrec = 0; 1887 sal_uInt16 nLeading = 0; 1888 if ( rInfo.nDecimals >= 0 ) // < 0 : Default 1889 nPrec = (sal_uInt16) rInfo.nDecimals; 1890 if ( rInfo.nInteger >= 0 ) // < 0 : Default 1891 nLeading = (sal_uInt16) rInfo.nInteger; 1892 1893 if ( bAutoDec ) 1894 { 1895 if ( nType == XML_TOK_STYLES_CURRENCY_STYLE ) 1896 { 1897 // for currency formats, "automatic decimals" is used for the automatic 1898 // currency format with (fixed) decimals from the locale settings 1899 1900 const LocaleDataWrapper& rLoc = pData->GetLocaleData( nFormatLang ); 1901 nPrec = rLoc.getCurrDigits(); 1902 } 1903 else 1904 { 1905 // for other types, "automatic decimals" means dynamic determination of 1906 // decimals, as achieved with the "general" keyword 1907 1908 aFormatCode.append( pFormatter->GetStandardName( nFormatLang ) ); 1909 return; 1910 } 1911 } 1912 if ( bAutoInt ) 1913 { 1914 //!... 1915 } 1916 1917 sal_uInt16 nGenPrec = nPrec; 1918 if ( rInfo.bDecReplace || rInfo.bVarDecimals ) 1919 nGenPrec = 0; // generate format without decimals... 1920 1921 sal_Bool bGrouping = rInfo.bGrouping; 1922 sal_uInt16 nEmbeddedCount = rInfo.aEmbeddedElements.Count(); 1923 if ( nEmbeddedCount ) 1924 bGrouping = sal_False; // grouping and embedded characters can't be used together 1925 1926 String aNumStr; 1927 sal_uInt32 nStdIndex = pFormatter->GetStandardIndex( nFormatLang ); 1928 pFormatter->GenerateFormat( aNumStr, nStdIndex, nFormatLang, 1929 bGrouping, sal_False, nGenPrec, nLeading ); 1930 1931 if ( rInfo.nExpDigits >= 0 && nLeading == 0 && !bGrouping && nEmbeddedCount == 0 ) 1932 { 1933 // #i43959# For scientific numbers, "#" in the integer part forces a digit, 1934 // so it has to be removed if nLeading is 0 (".00E+0", not "#.00E+0"). 1935 1936 aNumStr.EraseLeadingChars( (sal_Unicode)'#' ); 1937 } 1938 1939 if ( nEmbeddedCount ) 1940 { 1941 // insert embedded strings into number string 1942 // only the integer part is supported 1943 // nZeroPos is the string position where format position 0 is inserted 1944 1945 xub_StrLen nZeroPos = aNumStr.Search( pData->GetLocaleData( nFormatLang ).getNumDecimalSep() ); 1946 if ( nZeroPos == STRING_NOTFOUND ) 1947 nZeroPos = aNumStr.Len(); 1948 1949 // aEmbeddedElements is sorted - last entry has the largest position (leftmost) 1950 const SvXMLEmbeddedElement* pLastObj = rInfo.aEmbeddedElements[nEmbeddedCount - 1]; 1951 sal_Int32 nLastFormatPos = pLastObj->nFormatPos; 1952 if ( nLastFormatPos >= nZeroPos ) 1953 { 1954 // add '#' characters so all embedded texts are really embedded in digits 1955 // (there always has to be a digit before the leftmost embedded text) 1956 1957 xub_StrLen nAddCount = (xub_StrLen)nLastFormatPos + 1 - nZeroPos; 1958 String aDigitStr; 1959 aDigitStr.Fill( nAddCount, (sal_Unicode)'#' ); 1960 aNumStr.Insert( aDigitStr, 0 ); 1961 nZeroPos = nZeroPos + nAddCount; 1962 } 1963 1964 // aEmbeddedElements is sorted with ascending positions - loop is from right to left 1965 for (sal_uInt16 nElement = 0; nElement < nEmbeddedCount; nElement++) 1966 { 1967 const SvXMLEmbeddedElement* pObj = rInfo.aEmbeddedElements[nElement]; 1968 sal_Int32 nFormatPos = pObj->nFormatPos; 1969 sal_Int32 nInsertPos = nZeroPos - nFormatPos; 1970 if ( nFormatPos >= 0 && nInsertPos >= 0 ) 1971 { 1972 rtl::OUStringBuffer aContent( pObj->aText ); 1973 // #107805# always quote embedded strings - even space would otherwise 1974 // be recognized as thousands separator in French. 1975 aContent.insert( 0, (sal_Unicode) '"' ); 1976 aContent.append( (sal_Unicode) '"' ); 1977 1978 aNumStr.Insert( String( aContent.makeStringAndClear() ), (xub_StrLen)nInsertPos ); 1979 } 1980 } 1981 } 1982 1983 aFormatCode.append( aNumStr ); 1984 1985 if ( ( rInfo.bDecReplace || rInfo.bVarDecimals ) && nPrec ) // add decimal replacement (dashes) 1986 { 1987 // add dashes for explicit decimal replacement, # for variable decimals 1988 sal_Unicode cAdd = rInfo.bDecReplace ? '-' : '#'; 1989 1990 aFormatCode.append( pData->GetLocaleData( nFormatLang ).getNumDecimalSep() ); 1991 for ( sal_uInt16 i=0; i<nPrec; i++) 1992 aFormatCode.append( cAdd ); 1993 } 1994 1995 // add extra thousands separators for display factor 1996 1997 if ( rInfo.fDisplayFactor != 1.0 && rInfo.fDisplayFactor > 0.0 ) 1998 { 1999 // test for 1.0 is just for optimization - nSepCount would be 0 2000 2001 // one separator for each factor of 1000 2002 sal_Int32 nSepCount = (sal_Int32) ::rtl::math::round( log10(rInfo.fDisplayFactor) / 3.0 ); 2003 if ( nSepCount > 0 ) 2004 { 2005 OUString aSep = pData->GetLocaleData( nFormatLang ).getNumThousandSep(); 2006 for ( sal_Int32 i=0; i<nSepCount; i++ ) 2007 aFormatCode.append( aSep ); 2008 } 2009 } 2010 } 2011 2012 void SvXMLNumFormatContext::AddCurrency( const rtl::OUString& rContent, LanguageType nLang ) 2013 { 2014 sal_Bool bAutomatic = sal_False; 2015 OUString aSymbol = rContent; 2016 if ( aSymbol.getLength() == 0 ) 2017 { 2018 // get currency symbol for language 2019 2020 //aSymbol = pData->GetLocaleData( nFormatLang ).getCurrSymbol(); 2021 2022 SvNumberFormatter* pFormatter = pData->GetNumberFormatter(); 2023 if ( pFormatter ) 2024 { 2025 pFormatter->ChangeIntl( nFormatLang ); 2026 String sCurString, sDummy; 2027 pFormatter->GetCompatibilityCurrency( sCurString, sDummy ); 2028 aSymbol = sCurString; 2029 2030 bAutomatic = sal_True; 2031 } 2032 } 2033 else if ( nLang == LANGUAGE_SYSTEM && aSymbol.compareToAscii("CCC") == 0 ) 2034 { 2035 // "CCC" is used for automatic long symbol 2036 bAutomatic = sal_True; 2037 } 2038 2039 if ( bAutomatic ) 2040 { 2041 // remove unnecessary quotes before automatic symbol (formats like "-(0DM)") 2042 // otherwise the currency symbol isn't recognized (#94048#) 2043 2044 sal_Int32 nLength = aFormatCode.getLength(); 2045 if ( nLength > 1 && aFormatCode.charAt( nLength-1 ) == '"' ) 2046 { 2047 // find start of quoted string 2048 // When SvXMLNumFmtElementContext::EndElement creates escaped quotes, 2049 // they must be handled here, too. 2050 2051 sal_Int32 nFirst = nLength - 2; 2052 while ( nFirst >= 0 && aFormatCode.charAt( nFirst ) != '"' ) 2053 --nFirst; 2054 if ( nFirst >= 0 ) 2055 { 2056 // remove both quotes from aFormatCode 2057 rtl::OUString aOld = aFormatCode.makeStringAndClear(); 2058 if ( nFirst > 0 ) 2059 aFormatCode.append( aOld.copy( 0, nFirst ) ); 2060 if ( nLength > nFirst + 2 ) 2061 aFormatCode.append( aOld.copy( nFirst + 1, nLength - nFirst - 2 ) ); 2062 } 2063 } 2064 } 2065 2066 if (!bAutomatic) 2067 aFormatCode.appendAscii( "[$" ); // intro for "new" currency symbols 2068 2069 aFormatCode.append( aSymbol ); 2070 2071 if (!bAutomatic) 2072 { 2073 if ( nLang != LANGUAGE_SYSTEM ) 2074 { 2075 // '-' sign and language code in hex: 2076 aFormatCode.append( (sal_Unicode) '-' ); 2077 aFormatCode.append( String::CreateFromInt32( sal_Int32( nLang ), 16 ).ToUpperAscii() ); 2078 } 2079 2080 aFormatCode.append( (sal_Unicode) ']' ); // end of "new" currency symbol 2081 } 2082 } 2083 2084 void SvXMLNumFormatContext::AddNfKeyword( sal_uInt16 nIndex ) 2085 { 2086 SvNumberFormatter* pFormatter = pData->GetNumberFormatter(); 2087 if (!pFormatter) 2088 return; 2089 2090 if ( nIndex == NF_KEY_G || nIndex == NF_KEY_GG || nIndex == NF_KEY_GGG ) 2091 bHasEra = sal_True; 2092 2093 if ( nIndex == NF_KEY_NNNN ) 2094 { 2095 nIndex = NF_KEY_NNN; 2096 bHasLongDoW = sal_True; // to remove string constant with separator 2097 } 2098 2099 String sKeyword = pFormatter->GetKeyword( nFormatLang, nIndex ); 2100 2101 if ( nIndex == NF_KEY_H || nIndex == NF_KEY_HH || 2102 nIndex == NF_KEY_MI || nIndex == NF_KEY_MMI || 2103 nIndex == NF_KEY_S || nIndex == NF_KEY_SS ) 2104 { 2105 if ( !bTruncate && !bHasDateTime ) 2106 { 2107 // with truncate-on-overflow = false, add "[]" to first time part 2108 2109 sKeyword.Insert( (sal_Unicode) '[', 0 ); 2110 sKeyword.Append( (sal_Unicode) ']' ); 2111 } 2112 bHasDateTime = sal_True; 2113 } 2114 2115 aFormatCode.append( sKeyword ); 2116 2117 // collect the date elements that the format contains, to recognize default date formats 2118 switch ( nIndex ) 2119 { 2120 case NF_KEY_NN: eDateDOW = XML_DEA_SHORT; break; 2121 case NF_KEY_NNN: 2122 case NF_KEY_NNNN: eDateDOW = XML_DEA_LONG; break; 2123 case NF_KEY_D: eDateDay = XML_DEA_SHORT; break; 2124 case NF_KEY_DD: eDateDay = XML_DEA_LONG; break; 2125 case NF_KEY_M: eDateMonth = XML_DEA_SHORT; break; 2126 case NF_KEY_MM: eDateMonth = XML_DEA_LONG; break; 2127 case NF_KEY_MMM: eDateMonth = XML_DEA_TEXTSHORT; break; 2128 case NF_KEY_MMMM: eDateMonth = XML_DEA_TEXTLONG; break; 2129 case NF_KEY_YY: eDateYear = XML_DEA_SHORT; break; 2130 case NF_KEY_YYYY: eDateYear = XML_DEA_LONG; break; 2131 case NF_KEY_H: eDateHours = XML_DEA_SHORT; break; 2132 case NF_KEY_HH: eDateHours = XML_DEA_LONG; break; 2133 case NF_KEY_MI: eDateMins = XML_DEA_SHORT; break; 2134 case NF_KEY_MMI: eDateMins = XML_DEA_LONG; break; 2135 case NF_KEY_S: eDateSecs = XML_DEA_SHORT; break; 2136 case NF_KEY_SS: eDateSecs = XML_DEA_LONG; break; 2137 case NF_KEY_AP: 2138 case NF_KEY_AMPM: break; // AM/PM may or may not be in date/time formats -> ignore by itself 2139 default: 2140 bDateNoDefault = sal_True; // any other element -> no default format 2141 } 2142 } 2143 2144 sal_Bool lcl_IsAtEnd( rtl::OUStringBuffer& rBuffer, const String& rToken ) 2145 { 2146 sal_Int32 nBufLen = rBuffer.getLength(); 2147 xub_StrLen nTokLen = rToken.Len(); 2148 2149 if ( nTokLen > nBufLen ) 2150 return sal_False; 2151 2152 sal_Int32 nStartPos = nBufLen - nTokLen; 2153 for ( xub_StrLen nTokPos = 0; nTokPos < nTokLen; nTokPos++ ) 2154 if ( rToken.GetChar( nTokPos ) != rBuffer.charAt( nStartPos + nTokPos ) ) 2155 return sal_False; 2156 2157 return sal_True; 2158 } 2159 2160 sal_Bool SvXMLNumFormatContext::ReplaceNfKeyword( sal_uInt16 nOld, sal_uInt16 nNew ) 2161 { 2162 // replaces one keyword with another if it is found at the end of the code 2163 2164 SvNumberFormatter* pFormatter = pData->GetNumberFormatter(); 2165 if (!pFormatter) 2166 return sal_False; 2167 2168 String sOldStr = pFormatter->GetKeyword( nFormatLang, nOld ); 2169 if ( lcl_IsAtEnd( aFormatCode, sOldStr ) ) 2170 { 2171 // remove old keyword 2172 aFormatCode.setLength( aFormatCode.getLength() - sOldStr.Len() ); 2173 2174 // add new keyword 2175 String sNewStr = pFormatter->GetKeyword( nFormatLang, nNew ); 2176 aFormatCode.append( sNewStr ); 2177 2178 return sal_True; // changed 2179 } 2180 return sal_False; // not found 2181 } 2182 2183 void SvXMLNumFormatContext::AddCondition( const sal_Int32 nIndex ) 2184 { 2185 rtl::OUString rApplyName = aMyConditions[nIndex].sMapName; 2186 rtl::OUString rCondition = aMyConditions[nIndex].sCondition; 2187 SvNumberFormatter* pFormatter = pData->GetNumberFormatter(); 2188 sal_uInt32 l_nKey = pData->GetKeyForName( rApplyName ); 2189 OUString sValue = OUString::createFromAscii( "value()" ); //! define constant 2190 sal_Int32 nValLen = sValue.getLength(); 2191 2192 if ( pFormatter && l_nKey != NUMBERFORMAT_ENTRY_NOT_FOUND && 2193 rCondition.copy( 0, nValLen ) == sValue ) 2194 { 2195 //! test for valid conditions 2196 //! test for default conditions 2197 2198 OUString sRealCond = rCondition.copy( nValLen, rCondition.getLength() - nValLen ); 2199 sal_Bool bDefaultCond = sal_False; 2200 2201 //! collect all conditions first and adjust default to >=0, >0 or <0 depending on count 2202 //! allow blanks in conditions 2203 sal_Bool bFirstCond = ( aConditions.getLength() == 0 ); 2204 if ( bFirstCond && aMyConditions.size() == 1 && sRealCond.compareToAscii( ">=0" ) == 0 ) 2205 bDefaultCond = sal_True; 2206 2207 if ( nType == XML_TOK_STYLES_TEXT_STYLE && nIndex == 2 ) 2208 { 2209 // The third condition in a number format with a text part can only be 2210 // "all other numbers", the condition string must be empty. 2211 bDefaultCond = sal_True; 2212 } 2213 2214 if (!bDefaultCond) 2215 { 2216 sal_Int32 nPos = sRealCond.indexOf( '.' ); 2217 if ( nPos >= 0 ) 2218 { // #i8026# #103991# localize decimal separator 2219 const String& rDecSep = GetLocaleData().getNumDecimalSep(); 2220 if ( rDecSep.Len() > 1 || rDecSep.GetChar(0) != '.' ) 2221 sRealCond = sRealCond.replaceAt( nPos, 1, rDecSep ); 2222 } 2223 aConditions.append( (sal_Unicode) '[' ); 2224 aConditions.append( sRealCond ); 2225 aConditions.append( (sal_Unicode) ']' ); 2226 } 2227 2228 const SvNumberformat* pFormat = pFormatter->GetEntry(l_nKey); 2229 if ( pFormat ) 2230 aConditions.append( OUString( pFormat->GetFormatstring() ) ); 2231 2232 aConditions.append( (sal_Unicode) ';' ); 2233 } 2234 } 2235 2236 void SvXMLNumFormatContext::AddCondition( const sal_Int32 nIndex, const rtl::OUString& rFormat, const LocaleDataWrapper& rData ) 2237 { 2238 rtl::OUString rCondition = aMyConditions[nIndex].sCondition; 2239 OUString sValue = OUString::createFromAscii( "value()" ); //! define constant 2240 sal_Int32 nValLen = sValue.getLength(); 2241 2242 if ( rCondition.copy( 0, nValLen ) == sValue ) 2243 { 2244 //! test for valid conditions 2245 //! test for default conditions 2246 2247 OUString sRealCond = rCondition.copy( nValLen, rCondition.getLength() - nValLen ); 2248 sal_Bool bDefaultCond = sal_False; 2249 2250 //! collect all conditions first and adjust default to >=0, >0 or <0 depending on count 2251 //! allow blanks in conditions 2252 sal_Bool bFirstCond = ( aConditions.getLength() == 0 ); 2253 if ( bFirstCond && aMyConditions.size() == 1 && sRealCond.compareToAscii( ">=0" ) == 0 ) 2254 bDefaultCond = sal_True; 2255 2256 if ( nType == XML_TOK_STYLES_TEXT_STYLE && nIndex == 2 ) 2257 { 2258 // The third condition in a number format with a text part can only be 2259 // "all other numbers", the condition string must be empty. 2260 bDefaultCond = sal_True; 2261 } 2262 2263 if (!bDefaultCond) 2264 { 2265 sal_Int32 nPos = sRealCond.indexOf( '.' ); 2266 if ( nPos >= 0 ) 2267 { // #i8026# #103991# localize decimal separator 2268 const String& rDecSep = rData.getNumDecimalSep(); 2269 if ( rDecSep.Len() > 1 || rDecSep.GetChar(0) != '.' ) 2270 sRealCond = sRealCond.replaceAt( nPos, 1, rDecSep ); 2271 } 2272 aConditions.append( (sal_Unicode) '[' ); 2273 aConditions.append( sRealCond ); 2274 aConditions.append( (sal_Unicode) ']' ); 2275 } 2276 2277 aConditions.append( rFormat ); 2278 2279 aConditions.append( (sal_Unicode) ';' ); 2280 } 2281 } 2282 2283 void SvXMLNumFormatContext::AddCondition( const rtl::OUString& rCondition, const rtl::OUString& rApplyName ) 2284 { 2285 MyCondition aCondition; 2286 aCondition.sCondition = rCondition; 2287 aCondition.sMapName = rApplyName; 2288 aMyConditions.push_back(aCondition); 2289 } 2290 2291 void SvXMLNumFormatContext::AddColor( const Color& rColor ) 2292 { 2293 SvNumberFormatter* pFormatter = pData->GetNumberFormatter(); 2294 if (!pFormatter) 2295 return; 2296 2297 OUStringBuffer aColName; 2298 for ( sal_uInt16 i=0; i<XML_NUMF_COLORCOUNT; i++ ) 2299 if ( rColor == aNumFmtStdColors[i] ) 2300 { 2301 aColName = OUString( pFormatter->GetKeyword( nFormatLang, sal::static_int_cast< sal_uInt16 >(NF_KEY_FIRSTCOLOR + i) ) ); 2302 break; 2303 } 2304 2305 if ( aColName.getLength() ) 2306 { 2307 aColName.insert( 0, (sal_Unicode) '[' ); 2308 aColName.append( (sal_Unicode) ']' ); 2309 aFormatCode.insert( 0, aColName.makeStringAndClear() ); 2310 } 2311 } 2312 2313 void SvXMLNumFormatContext::UpdateCalendar( const rtl::OUString& rNewCalendar ) 2314 { 2315 if ( rNewCalendar != sCalendar ) 2316 { 2317 sCalendar = rNewCalendar; 2318 if ( sCalendar.getLength() ) 2319 { 2320 aFormatCode.appendAscii( "[~" ); // intro for calendar code 2321 aFormatCode.append( sCalendar ); 2322 aFormatCode.append( (sal_Unicode) ']' ); // end of "new" currency symbolcalendar code 2323 } 2324 } 2325 } 2326 2327 sal_Bool SvXMLNumFormatContext::IsSystemLanguage() 2328 { 2329 return nFormatLang == LANGUAGE_SYSTEM; 2330 } 2331 2332 //------------------------------------------------------------------------- 2333 2334 // 2335 // SvXMLNumFmtHelper 2336 // 2337 2338 // #110680# 2339 //SvXMLNumFmtHelper::SvXMLNumFmtHelper( 2340 // const uno::Reference<util::XNumberFormatsSupplier>& rSupp ) 2341 SvXMLNumFmtHelper::SvXMLNumFmtHelper( 2342 const uno::Reference<util::XNumberFormatsSupplier>& rSupp, 2343 const uno::Reference<lang::XMultiServiceFactory>& xServiceFactory ) 2344 : mxServiceFactory(xServiceFactory) 2345 { 2346 DBG_ASSERT( mxServiceFactory.is(), "got no service manager" ); 2347 2348 SvNumberFormatter* pFormatter = NULL; 2349 SvNumberFormatsSupplierObj* pObj = 2350 SvNumberFormatsSupplierObj::getImplementation( rSupp ); 2351 if (pObj) 2352 pFormatter = pObj->GetNumberFormatter(); 2353 2354 // #110680# 2355 // pData = new SvXMLNumImpData( pFormatter ); 2356 pData = new SvXMLNumImpData( pFormatter, mxServiceFactory ); 2357 } 2358 2359 // #110680# 2360 // SvXMLNumFmtHelper::SvXMLNumFmtHelper( SvNumberFormatter* pNumberFormatter ) 2361 SvXMLNumFmtHelper::SvXMLNumFmtHelper( 2362 SvNumberFormatter* pNumberFormatter, 2363 const uno::Reference<lang::XMultiServiceFactory>& xServiceFactory ) 2364 : mxServiceFactory(xServiceFactory) 2365 { 2366 DBG_ASSERT( mxServiceFactory.is(), "got no service manager" ); 2367 2368 // #110680# 2369 // pData = new SvXMLNumImpData( pNumberFormatter ); 2370 pData = new SvXMLNumImpData( pNumberFormatter, mxServiceFactory ); 2371 } 2372 2373 SvXMLNumFmtHelper::~SvXMLNumFmtHelper() 2374 { 2375 // remove temporary (volatile) formats from NumberFormatter 2376 pData->RemoveVolatileFormats(); 2377 2378 delete pData; 2379 } 2380 2381 SvXMLStyleContext* SvXMLNumFmtHelper::CreateChildContext( SvXMLImport& rImport, 2382 sal_uInt16 nPrefix, const OUString& rLocalName, 2383 const uno::Reference<xml::sax::XAttributeList>& xAttrList, 2384 SvXMLStylesContext& rStyles ) 2385 { 2386 SvXMLStyleContext* pContext = NULL; 2387 2388 const SvXMLTokenMap& rTokenMap = pData->GetStylesElemTokenMap(); 2389 sal_uInt16 nToken = rTokenMap.Get( nPrefix, rLocalName ); 2390 switch (nToken) 2391 { 2392 case XML_TOK_STYLES_NUMBER_STYLE: 2393 case XML_TOK_STYLES_CURRENCY_STYLE: 2394 case XML_TOK_STYLES_PERCENTAGE_STYLE: 2395 case XML_TOK_STYLES_DATE_STYLE: 2396 case XML_TOK_STYLES_TIME_STYLE: 2397 case XML_TOK_STYLES_BOOLEAN_STYLE: 2398 case XML_TOK_STYLES_TEXT_STYLE: 2399 pContext = new SvXMLNumFormatContext( rImport, nPrefix, rLocalName, 2400 pData, nToken, xAttrList, rStyles ); 2401 break; 2402 } 2403 2404 // return NULL if not a data style, caller must handle other elements 2405 return pContext; 2406 } 2407 2408 const SvXMLTokenMap& SvXMLNumFmtHelper::GetStylesElemTokenMap() 2409 { 2410 return pData->GetStylesElemTokenMap(); 2411 } 2412 2413 /*sal_uInt32 SvXMLNumFmtHelper::GetKeyForName( const rtl::OUString& rName ) 2414 { 2415 return pData->GetKeyForName( rName ); 2416 }*/ 2417 2418 2419