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