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_svl.hxx" 26 #ifndef GCC 27 #endif 28 29 // #include <math.h> 30 #include <tools/debug.hxx> 31 #include <unotools/charclass.hxx> 32 #include <i18npool/mslangid.hxx> 33 #include <unotools/localedatawrapper.hxx> 34 #include <unotools/numberformatcodewrapper.hxx> 35 #include <unotools/calendarwrapper.hxx> 36 #include <com/sun/star/i18n/KNumberFormatUsage.hpp> 37 #include <com/sun/star/i18n/KNumberFormatType.hpp> 38 #include <comphelper/processfactory.hxx> 39 #include <unotools/misccfg.hxx> 40 41 #define _SVSTDARR_USHORTS 42 #include <svl/svstdarr.hxx> 43 44 #define _ZFORLIST_CXX 45 #include <osl/mutex.hxx> 46 #include <svl/zforlist.hxx> 47 #undef _ZFORLIST_CXX 48 49 #include "zforscan.hxx" 50 #include "zforfind.hxx" 51 #include <svl/zformat.hxx> 52 #include "numhead.hxx" 53 54 #include <unotools/syslocaleoptions.hxx> 55 #include <unotools/digitgroupingiterator.hxx> 56 #include <rtl/logfile.hxx> 57 #include <rtl/instance.hxx> 58 59 #include <math.h> 60 #include <limits> 61 62 using namespace ::com::sun::star; 63 using namespace ::com::sun::star::uno; 64 using namespace ::com::sun::star::i18n; 65 using namespace ::com::sun::star::lang; 66 67 68 // Constants for type offsets per Country/Language (CL) 69 #define ZF_STANDARD 0 70 #define ZF_STANDARD_PERCENT 10 71 #define ZF_STANDARD_CURRENCY 20 72 #define ZF_STANDARD_DATE 30 73 #define ZF_STANDARD_TIME 40 74 #define ZF_STANDARD_DATETIME 50 75 #define ZF_STANDARD_SCIENTIFIC 60 76 #define ZF_STANDARD_FRACTION 70 77 #define ZF_STANDARD_NEWEXTENDED 75 78 #define ZF_STANDARD_NEWEXTENDEDMAX SV_MAX_ANZ_STANDARD_FORMATE-2 // 98 79 #define ZF_STANDARD_LOGICAL SV_MAX_ANZ_STANDARD_FORMATE-1 // 99 80 #define ZF_STANDARD_TEXT SV_MAX_ANZ_STANDARD_FORMATE // 100 81 82 /* Locale that is set if an unknown locale (from another system) is loaded of 83 * legacy documents. Can not be SYSTEM because else, for example, a German "DM" 84 * (old currency) is recognized as a date (#53155#). */ 85 #define UNKNOWN_SUBSTITUTE LANGUAGE_ENGLISH_US 86 87 static sal_Bool bIndexTableInitialized = sal_False; 88 static sal_uInt32 __FAR_DATA theIndexTable[NF_INDEX_TABLE_ENTRIES]; 89 90 91 // ==================================================================== 92 93 /** 94 instead of every number formatter being a listener we have a registry which 95 also handles one instance of the SysLocale options 96 */ 97 98 class SvNumberFormatterRegistry_Impl : public utl::ConfigurationListener 99 { 100 List aFormatters; 101 SvtSysLocaleOptions aSysLocaleOptions; 102 LanguageType eSysLanguage; 103 104 public: 105 SvNumberFormatterRegistry_Impl(); 106 virtual ~SvNumberFormatterRegistry_Impl(); 107 108 void Insert( SvNumberFormatter* pThis ) 109 { aFormatters.Insert( pThis, LIST_APPEND ); } 110 SvNumberFormatter* Remove( SvNumberFormatter* pThis ) 111 { return (SvNumberFormatter*)aFormatters.Remove( pThis ); } 112 sal_uInt32 Count() 113 { return aFormatters.Count(); } 114 115 virtual void ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 ); 116 }; 117 118 119 SvNumberFormatterRegistry_Impl::SvNumberFormatterRegistry_Impl() 120 { 121 eSysLanguage = MsLangId::getRealLanguage( LANGUAGE_SYSTEM ); 122 aSysLocaleOptions.AddListener( this ); 123 } 124 125 126 SvNumberFormatterRegistry_Impl::~SvNumberFormatterRegistry_Impl() 127 { 128 aSysLocaleOptions.RemoveListener( this ); 129 } 130 131 132 void SvNumberFormatterRegistry_Impl::ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 nHint ) 133 { 134 if ( nHint & SYSLOCALEOPTIONS_HINT_LOCALE ) 135 { 136 ::osl::MutexGuard aGuard( SvNumberFormatter::GetMutex() ); 137 for ( SvNumberFormatter* p = (SvNumberFormatter*)aFormatters.First(); 138 p; p = (SvNumberFormatter*)aFormatters.Next() ) 139 { 140 p->ReplaceSystemCL( eSysLanguage ); 141 } 142 eSysLanguage = MsLangId::getRealLanguage( LANGUAGE_SYSTEM ); 143 } 144 if ( nHint & SYSLOCALEOPTIONS_HINT_CURRENCY ) 145 { 146 ::osl::MutexGuard aGuard( SvNumberFormatter::GetMutex() ); 147 for ( SvNumberFormatter* p = (SvNumberFormatter*)aFormatters.First(); 148 p; p = (SvNumberFormatter*)aFormatters.Next() ) 149 { 150 p->ResetDefaultSystemCurrency(); 151 } 152 } 153 } 154 155 156 // ==================================================================== 157 158 SvNumberFormatterRegistry_Impl* SvNumberFormatter::pFormatterRegistry = NULL; 159 sal_Bool SvNumberFormatter::bCurrencyTableInitialized = sal_False; 160 namespace 161 { 162 struct theCurrencyTable : 163 public rtl::Static< NfCurrencyTable, theCurrencyTable > {}; 164 165 struct theLegacyOnlyCurrencyTable : 166 public rtl::Static< NfCurrencyTable, theLegacyOnlyCurrencyTable > {}; 167 } 168 sal_uInt16 SvNumberFormatter::nSystemCurrencyPosition = 0; 169 SV_IMPL_PTRARR( NfCurrencyTable, NfCurrencyEntry* ); 170 SV_IMPL_PTRARR( NfWSStringsDtor, String* ); 171 172 // ob das BankSymbol immer am Ende ist (1 $;-1 $) oder sprachabhaengig 173 #define NF_BANKSYMBOL_FIX_POSITION 1 174 175 176 /***********************Funktionen SvNumberFormatter**************************/ 177 178 const sal_uInt16 SvNumberFormatter::UNLIMITED_PRECISION = ::std::numeric_limits<sal_uInt16>::max(); 179 const sal_uInt16 SvNumberFormatter::INPUTSTRING_PRECISION = ::std::numeric_limits<sal_uInt16>::max()-1; 180 181 SvNumberFormatter::SvNumberFormatter( 182 const Reference< XMultiServiceFactory >& xSMgr, 183 LanguageType eLang ) 184 : 185 xServiceManager( xSMgr ) 186 { 187 ImpConstruct( eLang ); 188 } 189 190 191 SvNumberFormatter::SvNumberFormatter( LanguageType eLang ) 192 { 193 ImpConstruct( eLang ); 194 } 195 196 197 SvNumberFormatter::~SvNumberFormatter() 198 { 199 { 200 ::osl::MutexGuard aGuard( GetMutex() ); 201 pFormatterRegistry->Remove( this ); 202 if ( !pFormatterRegistry->Count() ) 203 { 204 delete pFormatterRegistry; 205 pFormatterRegistry = NULL; 206 } 207 } 208 209 SvNumberformat* pEntry = aFTable.First(); 210 while (pEntry) 211 { 212 delete pEntry; 213 pEntry = aFTable.Next(); 214 } 215 delete pFormatTable; 216 delete pCharClass; 217 delete pStringScanner; 218 delete pFormatScanner; 219 ClearMergeTable(); 220 delete pMergeTable; 221 } 222 223 224 void SvNumberFormatter::ImpConstruct( LanguageType eLang ) 225 { 226 RTL_LOGFILE_CONTEXT_AUTHOR( aTimeLog, "svl", "er93726", "SvNumberFormatter::ImpConstruct" ); 227 228 if ( eLang == LANGUAGE_DONTKNOW ) 229 eLang = UNKNOWN_SUBSTITUTE; 230 IniLnge = eLang; 231 ActLnge = eLang; 232 eEvalDateFormat = NF_EVALDATEFORMAT_INTL; 233 nDefaultSystemCurrencyFormat = NUMBERFORMAT_ENTRY_NOT_FOUND; 234 235 aLocale = MsLangId::convertLanguageToLocale( eLang ); 236 pCharClass = new CharClass( xServiceManager, aLocale ); 237 xLocaleData.init( xServiceManager, aLocale, eLang ); 238 xCalendar.init( xServiceManager, aLocale ); 239 xTransliteration.init( xServiceManager, eLang, 240 ::com::sun::star::i18n::TransliterationModules_IGNORE_CASE ); 241 xNatNum.init( xServiceManager ); 242 243 // cached locale data items 244 const LocaleDataWrapper* pLoc = GetLocaleData(); 245 aDecimalSep = pLoc->getNumDecimalSep(); 246 aThousandSep = pLoc->getNumThousandSep(); 247 aDateSep = pLoc->getDateSep(); 248 249 pStringScanner = new ImpSvNumberInputScan( this ); 250 pFormatScanner = new ImpSvNumberformatScan( this ); 251 pFormatTable = NULL; 252 MaxCLOffset = 0; 253 ImpGenerateFormats( 0, sal_False ); // 0 .. 999 for initialized language formats 254 pMergeTable = NULL; 255 bNoZero = sal_False; 256 257 ::osl::MutexGuard aGuard( GetMutex() ); 258 GetFormatterRegistry().Insert( this ); 259 } 260 261 262 void SvNumberFormatter::ChangeIntl(LanguageType eLnge) 263 { 264 if (ActLnge != eLnge) 265 { 266 ActLnge = eLnge; 267 268 aLocale = MsLangId::convertLanguageToLocale( eLnge ); 269 pCharClass->setLocale( aLocale ); 270 xLocaleData.changeLocale( aLocale, eLnge ); 271 xCalendar.changeLocale( aLocale ); 272 xTransliteration.changeLocale( eLnge ); 273 274 // cached locale data items, initialize BEFORE calling ChangeIntl below 275 const LocaleDataWrapper* pLoc = GetLocaleData(); 276 aDecimalSep = pLoc->getNumDecimalSep(); 277 aThousandSep = pLoc->getNumThousandSep(); 278 aDateSep = pLoc->getDateSep(); 279 280 pFormatScanner->ChangeIntl(); 281 pStringScanner->ChangeIntl(); 282 } 283 } 284 285 286 // static 287 ::osl::Mutex& SvNumberFormatter::GetMutex() 288 { 289 static ::osl::Mutex* pMutex = NULL; 290 if( !pMutex ) 291 { 292 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 293 if( !pMutex ) 294 { 295 // #i77768# Due to a static reference in the toolkit lib 296 // we need a mutex that lives longer than the svl library. 297 // Otherwise the dtor would use a destructed mutex!! 298 pMutex = new ::osl::Mutex; 299 } 300 } 301 return *pMutex; 302 } 303 304 305 // static 306 SvNumberFormatterRegistry_Impl& SvNumberFormatter::GetFormatterRegistry() 307 { 308 ::osl::MutexGuard aGuard( GetMutex() ); 309 if ( !pFormatterRegistry ) 310 pFormatterRegistry = new SvNumberFormatterRegistry_Impl; 311 return *pFormatterRegistry; 312 } 313 314 315 Color* SvNumberFormatter::GetUserDefColor(sal_uInt16 nIndex) 316 { 317 if( aColorLink.IsSet() ) 318 return (Color*) ( aColorLink.Call( (void*) &nIndex )); 319 else 320 return NULL; 321 } 322 323 void SvNumberFormatter::ChangeNullDate(sal_uInt16 nDay, 324 sal_uInt16 nMonth, 325 sal_uInt16 nYear) 326 { 327 pFormatScanner->ChangeNullDate(nDay, nMonth, nYear); 328 pStringScanner->ChangeNullDate(nDay, nMonth, nYear); 329 } 330 331 Date* SvNumberFormatter::GetNullDate() 332 { 333 return pFormatScanner->GetNullDate(); 334 } 335 336 void SvNumberFormatter::ChangeStandardPrec(short nPrec) 337 { 338 pFormatScanner->ChangeStandardPrec(nPrec); 339 } 340 341 sal_uInt16 SvNumberFormatter::GetStandardPrec() 342 { 343 return pFormatScanner->GetStandardPrec(); 344 } 345 346 void SvNumberFormatter::ImpChangeSysCL( LanguageType eLnge, sal_Bool bLoadingSO5 ) 347 { 348 if (eLnge == LANGUAGE_DONTKNOW) 349 eLnge = UNKNOWN_SUBSTITUTE; 350 if (eLnge != IniLnge) 351 { 352 IniLnge = eLnge; 353 ChangeIntl(eLnge); 354 SvNumberformat* pEntry = aFTable.First(); 355 while (pEntry) // delete old formats 356 { 357 pEntry = (SvNumberformat*) aFTable.Remove(aFTable.GetCurKey()); 358 delete pEntry; 359 pEntry = (SvNumberformat*) aFTable.First(); 360 } 361 ImpGenerateFormats( 0, bLoadingSO5 ); // new standard formats 362 } 363 else if ( bLoadingSO5 ) 364 { // delete additional standard formats 365 sal_uInt32 nKey; 366 aFTable.Seek( SV_MAX_ANZ_STANDARD_FORMATE + 1 ); 367 while ( (nKey = aFTable.GetCurKey()) > SV_MAX_ANZ_STANDARD_FORMATE && 368 nKey < SV_COUNTRY_LANGUAGE_OFFSET ) 369 { 370 SvNumberformat* pEntry = (SvNumberformat*) aFTable.Remove( nKey ); 371 delete pEntry; 372 } 373 } 374 } 375 376 377 void SvNumberFormatter::ReplaceSystemCL( LanguageType eOldLanguage ) 378 { 379 sal_uInt32 nCLOffset = ImpGetCLOffset( LANGUAGE_SYSTEM ); 380 if ( nCLOffset > MaxCLOffset ) 381 return ; // no SYSTEM entries to replace 382 383 const sal_uInt32 nMaxBuiltin = nCLOffset + SV_MAX_ANZ_STANDARD_FORMATE; 384 const sal_uInt32 nNextCL = nCLOffset + SV_COUNTRY_LANGUAGE_OFFSET; 385 sal_uInt32 nKey; 386 387 // remove old builtin formats 388 aFTable.Seek( nCLOffset ); 389 while ( (nKey = aFTable.GetCurKey()) >= nCLOffset && nKey <= nMaxBuiltin && aFTable.Count() ) 390 { 391 SvNumberformat* pEntry = (SvNumberformat*) aFTable.Remove( nKey ); 392 delete pEntry; 393 } 394 395 // move additional and user defined to temporary table 396 Table aOldTable; 397 while ( (nKey = aFTable.GetCurKey()) >= nCLOffset && nKey < nNextCL && aFTable.Count() ) 398 { 399 SvNumberformat* pEntry = (SvNumberformat*) aFTable.Remove( nKey ); 400 aOldTable.Insert( nKey, pEntry ); 401 } 402 403 // generate new old builtin formats 404 // reset ActLnge otherwise ChangeIntl() wouldn't switch if already LANGUAGE_SYSTEM 405 ActLnge = LANGUAGE_DONTKNOW; 406 ChangeIntl( LANGUAGE_SYSTEM ); 407 ImpGenerateFormats( nCLOffset, sal_True ); 408 409 // convert additional and user defined from old system to new system 410 SvNumberformat* pStdFormat = (SvNumberformat*) aFTable.Get( nCLOffset + ZF_STANDARD ); 411 sal_uInt32 nLastKey = nMaxBuiltin; 412 pFormatScanner->SetConvertMode( eOldLanguage, LANGUAGE_SYSTEM, sal_True ); 413 aOldTable.First(); 414 while ( aOldTable.Count() ) 415 { 416 nKey = aOldTable.GetCurKey(); 417 if ( nLastKey < nKey ) 418 nLastKey = nKey; 419 SvNumberformat* pOldEntry = (SvNumberformat*) aOldTable.Remove( nKey ); 420 String aString( pOldEntry->GetFormatstring() ); 421 xub_StrLen nCheckPos = STRING_NOTFOUND; 422 423 // Same as PutEntry() but assures key position even if format code is 424 // a duplicate. Also won't mix up any LastInsertKey. 425 ChangeIntl( eOldLanguage ); 426 LanguageType eLge = eOldLanguage; // ConvertMode changes this 427 sal_Bool bCheck = sal_False; 428 SvNumberformat* pNewEntry = new SvNumberformat( aString, pFormatScanner, 429 pStringScanner, nCheckPos, eLge ); 430 if ( nCheckPos != 0 ) 431 delete pNewEntry; 432 else 433 { 434 short eCheckType = pNewEntry->GetType(); 435 if ( eCheckType != NUMBERFORMAT_UNDEFINED ) 436 pNewEntry->SetType( eCheckType | NUMBERFORMAT_DEFINED ); 437 else 438 pNewEntry->SetType( NUMBERFORMAT_DEFINED ); 439 440 if ( !aFTable.Insert( nKey, pNewEntry ) ) 441 delete pNewEntry; 442 else 443 bCheck = sal_True; 444 } 445 DBG_ASSERT( bCheck, "SvNumberFormatter::ReplaceSystemCL: couldn't convert" ); 446 447 delete pOldEntry; 448 } 449 pFormatScanner->SetConvertMode(sal_False); 450 pStdFormat->SetLastInsertKey( sal_uInt16(nLastKey - nCLOffset) ); 451 452 // append new system additional formats 453 NumberFormatCodeWrapper aNumberFormatCode( xServiceManager, GetLocale() ); 454 ImpGenerateAdditionalFormats( nCLOffset, aNumberFormatCode, sal_True ); 455 } 456 457 458 sal_Bool SvNumberFormatter::IsTextFormat(sal_uInt32 F_Index) const 459 { 460 SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(F_Index); 461 if (!pFormat) 462 return sal_False; 463 else 464 return pFormat->IsTextFormat(); 465 } 466 467 sal_Bool SvNumberFormatter::HasTextFormat(sal_uInt32 F_Index) const 468 { 469 SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(F_Index); 470 if (!pFormat) 471 return sal_False; 472 else 473 return pFormat->HasTextFormat(); 474 } 475 476 sal_Bool SvNumberFormatter::PutEntry(String& rString, 477 xub_StrLen& nCheckPos, 478 short& nType, 479 sal_uInt32& nKey, // Formatnummer 480 LanguageType eLnge) 481 { 482 nKey = 0; 483 if (rString.Len() == 0) // keinen Leerstring 484 { 485 nCheckPos = 1; // -> Fehler 486 return sal_False; 487 } 488 if (eLnge == LANGUAGE_DONTKNOW) 489 eLnge = IniLnge; 490 491 ChangeIntl(eLnge); // ggfs. austauschen 492 LanguageType eLge = eLnge; // Umgehung const fuer ConvertMode 493 sal_Bool bCheck = sal_False; 494 SvNumberformat* p_Entry = new SvNumberformat(rString, 495 pFormatScanner, 496 pStringScanner, 497 nCheckPos, 498 eLge); 499 if (nCheckPos == 0) // Format ok 500 { // Typvergleich: 501 short eCheckType = p_Entry->GetType(); 502 if ( eCheckType != NUMBERFORMAT_UNDEFINED) 503 { 504 p_Entry->SetType(eCheckType | NUMBERFORMAT_DEFINED); 505 nType = eCheckType; 506 } 507 else 508 { 509 p_Entry->SetType(NUMBERFORMAT_DEFINED); 510 nType = NUMBERFORMAT_DEFINED; 511 } 512 sal_uInt32 CLOffset = ImpGenerateCL(eLge); // ggfs. neu Standard- 513 // formate anlegen 514 nKey = ImpIsEntry(p_Entry->GetFormatstring(),CLOffset, eLge); 515 if (nKey != NUMBERFORMAT_ENTRY_NOT_FOUND) // schon vorhanden 516 delete p_Entry; 517 else 518 { 519 SvNumberformat* pStdFormat = 520 (SvNumberformat*) aFTable.Get(CLOffset + ZF_STANDARD); 521 sal_uInt32 nPos = CLOffset + pStdFormat->GetLastInsertKey(); 522 if (nPos - CLOffset >= SV_COUNTRY_LANGUAGE_OFFSET) 523 { 524 DBG_ERROR("SvNumberFormatter:: Zu viele Formate pro CL"); 525 delete p_Entry; 526 } 527 else if (!aFTable.Insert(nPos+1,p_Entry)) 528 delete p_Entry; 529 else 530 { 531 bCheck = sal_True; 532 nKey = nPos+1; 533 pStdFormat->SetLastInsertKey((sal_uInt16) (nKey-CLOffset)); 534 } 535 } 536 } 537 else 538 delete p_Entry; 539 return bCheck; 540 } 541 542 sal_Bool SvNumberFormatter::PutandConvertEntry(String& rString, 543 xub_StrLen& nCheckPos, 544 short& nType, 545 sal_uInt32& nKey, 546 LanguageType eLnge, 547 LanguageType eNewLnge) 548 { 549 sal_Bool bRes; 550 if (eNewLnge == LANGUAGE_DONTKNOW) 551 eNewLnge = IniLnge; 552 553 pFormatScanner->SetConvertMode(eLnge, eNewLnge); 554 bRes = PutEntry(rString, nCheckPos, nType, nKey, eLnge); 555 pFormatScanner->SetConvertMode(sal_False); 556 return bRes; 557 } 558 559 560 sal_Bool SvNumberFormatter::PutandConvertEntrySystem(String& rString, 561 xub_StrLen& nCheckPos, 562 short& nType, 563 sal_uInt32& nKey, 564 LanguageType eLnge, 565 LanguageType eNewLnge) 566 { 567 sal_Bool bRes; 568 if (eNewLnge == LANGUAGE_DONTKNOW) 569 eNewLnge = IniLnge; 570 571 pFormatScanner->SetConvertMode(eLnge, eNewLnge, sal_True); 572 bRes = PutEntry(rString, nCheckPos, nType, nKey, eLnge); 573 pFormatScanner->SetConvertMode(sal_False); 574 return bRes; 575 } 576 577 578 sal_uInt32 SvNumberFormatter::GetIndexPuttingAndConverting( String & rString, 579 LanguageType eLnge, LanguageType eSysLnge, short & rType, 580 sal_Bool & rNewInserted, xub_StrLen & rCheckPos ) 581 { 582 sal_uInt32 nKey = NUMBERFORMAT_ENTRY_NOT_FOUND; 583 rNewInserted = sal_False; 584 rCheckPos = 0; 585 586 // #62389# empty format string (of Writer) => General standard format 587 if (!rString.Len()) 588 ; // nothing 589 else if (eLnge == LANGUAGE_SYSTEM && eSysLnge != SvtSysLocale().GetLanguage()) 590 { 591 sal_uInt32 nOrig = GetEntryKey( rString, eSysLnge ); 592 if (nOrig == NUMBERFORMAT_ENTRY_NOT_FOUND) 593 nKey = nOrig; // none available, maybe user-defined 594 else 595 nKey = GetFormatForLanguageIfBuiltIn( nOrig, SvtSysLocale().GetLanguage() ); 596 597 if (nKey == nOrig) 598 { 599 // Not a builtin format, convert. 600 // The format code string may get modified and adapted to the real 601 // language and wouldn't match eSysLnge anymore, do that on a copy. 602 String aTmp( rString); 603 rNewInserted = PutandConvertEntrySystem( aTmp, rCheckPos, rType, 604 nKey, eLnge, SvtSysLocale().GetLanguage()); 605 if (rCheckPos > 0) 606 { 607 DBG_ERRORFILE("SvNumberFormatter::GetIndexPuttingAndConverting: bad format code string for current locale"); 608 nKey = NUMBERFORMAT_ENTRY_NOT_FOUND; 609 } 610 } 611 } 612 else 613 { 614 nKey = GetEntryKey( rString, eLnge); 615 if (nKey == NUMBERFORMAT_ENTRY_NOT_FOUND) 616 { 617 rNewInserted = PutEntry( rString, rCheckPos, rType, nKey, eLnge); 618 if (rCheckPos > 0) 619 { 620 DBG_ERRORFILE("SvNumberFormatter::GetIndexPuttingAndConverting: bad format code string for specified locale"); 621 nKey = NUMBERFORMAT_ENTRY_NOT_FOUND; 622 } 623 } 624 } 625 if (nKey == NUMBERFORMAT_ENTRY_NOT_FOUND) 626 nKey = GetStandardIndex( eLnge); 627 rType = GetType( nKey); 628 // Convert any (!) old "automatic" currency format to new fixed currency 629 // default format. 630 if ((rType & NUMBERFORMAT_CURRENCY) != 0) 631 { 632 const SvNumberformat* pFormat = GetEntry( nKey); 633 if (!pFormat->HasNewCurrency()) 634 { 635 if (rNewInserted) 636 { 637 DeleteEntry( nKey); // don't leave trails of rubbish 638 rNewInserted = sal_False; 639 } 640 nKey = GetStandardFormat( NUMBERFORMAT_CURRENCY, eLnge); 641 } 642 } 643 return nKey; 644 } 645 646 647 void SvNumberFormatter::DeleteEntry(sal_uInt32 nKey) 648 { 649 SvNumberformat* pEntry = aFTable.Remove(nKey); 650 delete pEntry; 651 } 652 653 void SvNumberFormatter::PrepareSave() 654 { 655 SvNumberformat* pFormat = aFTable.First(); 656 while (pFormat) 657 { 658 pFormat->SetUsed(sal_False); 659 pFormat = aFTable.Next(); 660 } 661 } 662 663 void SvNumberFormatter::SetFormatUsed(sal_uInt32 nFIndex) 664 { 665 SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(nFIndex); 666 if (pFormat) 667 pFormat->SetUsed(sal_True); 668 } 669 670 sal_Bool SvNumberFormatter::Load( SvStream& rStream ) 671 { 672 LanguageType eSysLang = SvtSysLocale().GetLanguage(); 673 SvNumberFormatter* pConverter = NULL; 674 675 ImpSvNumMultipleReadHeader aHdr( rStream ); 676 sal_uInt16 nVersion; 677 rStream >> nVersion; 678 SvNumberformat* pEntry; 679 sal_uInt32 nPos; 680 LanguageType eSaveSysLang, eLoadSysLang; 681 sal_uInt16 nSysOnStore, eLge, eDummy; // Dummy fuer kompatibles Format 682 rStream >> nSysOnStore >> eLge; // Systemeinstellung aus 683 // Dokument 684 eSaveSysLang = (nVersion < SV_NUMBERFORMATTER_VERSION_SYSTORE ? 685 LANGUAGE_SYSTEM : (LanguageType) nSysOnStore); 686 LanguageType eLnge = (LanguageType) eLge; 687 ImpChangeSysCL( eLnge, sal_True ); 688 689 rStream >> nPos; 690 while (nPos != NUMBERFORMAT_ENTRY_NOT_FOUND) 691 { 692 rStream >> eDummy >> eLge; 693 eLnge = (LanguageType) eLge; 694 ImpGenerateCL( eLnge, sal_True ); // ggfs. neue Standardformate anlegen 695 696 sal_uInt32 nOffset = nPos % SV_COUNTRY_LANGUAGE_OFFSET; // relativIndex 697 sal_Bool bUserDefined = (nOffset > SV_MAX_ANZ_STANDARD_FORMATE); 698 //! HACK! ER 29.07.97 15:15 699 // SaveLang wurde bei SYSTEM nicht gespeichert sondern war auch SYSTEM, 700 // erst ab 364i Unterscheidung moeglich 701 sal_Bool bConversionHack; 702 if ( eLnge == LANGUAGE_SYSTEM ) 703 { 704 if ( nVersion < SV_NUMBERFORMATTER_VERSION_SYSTORE ) 705 { 706 bConversionHack = bUserDefined; 707 eLoadSysLang = eSaveSysLang; 708 } 709 else 710 { 711 bConversionHack = sal_False; 712 eLoadSysLang = eSysLang; 713 } 714 } 715 else 716 { 717 bConversionHack = sal_False; 718 eLoadSysLang = eSaveSysLang; 719 } 720 721 pEntry = new SvNumberformat(*pFormatScanner, eLnge); 722 if ( bConversionHack ) 723 { // SYSTEM 724 // nVersion < SV_NUMBERFORMATTER_VERSION_SYSTORE 725 // nVersion < SV_NUMBERFORMATTER_VERSION_KEYWORDS 726 if ( !pConverter ) 727 pConverter = new SvNumberFormatter( xServiceManager, eSysLang ); 728 NfHackConversion eHackConversion = pEntry->Load( 729 rStream, aHdr, pConverter, *pStringScanner ); 730 switch ( eHackConversion ) 731 { 732 case NF_CONVERT_GERMAN_ENGLISH : 733 pEntry->ConvertLanguage( *pConverter, 734 LANGUAGE_ENGLISH_US, eSysLang, sal_True ); 735 break; 736 case NF_CONVERT_ENGLISH_GERMAN : 737 switch ( eSysLang ) 738 { 739 case LANGUAGE_GERMAN: 740 case LANGUAGE_GERMAN_SWISS: 741 case LANGUAGE_GERMAN_AUSTRIAN: 742 case LANGUAGE_GERMAN_LUXEMBOURG: 743 case LANGUAGE_GERMAN_LIECHTENSTEIN: 744 // alles beim alten 745 break; 746 default: 747 pEntry->ConvertLanguage( *pConverter, 748 LANGUAGE_GERMAN, eSysLang, sal_True ); 749 } 750 break; 751 case NF_CONVERT_NONE : 752 break; // -Wall not handled. 753 } 754 755 } 756 else 757 { 758 pEntry->Load( rStream, aHdr, NULL, *pStringScanner ); 759 if ( !bUserDefined ) 760 bUserDefined = (pEntry->GetNewStandardDefined() > SV_NUMBERFORMATTER_VERSION); 761 if ( bUserDefined ) 762 { 763 if ( eSaveSysLang != eLoadSysLang ) 764 { // SYSTEM verschieden 765 if ( !pConverter ) 766 pConverter = new SvNumberFormatter( xServiceManager, eSysLang ); 767 if ( nVersion < SV_NUMBERFORMATTER_VERSION_KEYWORDS ) 768 { 769 switch ( eSaveSysLang ) 770 { 771 case LANGUAGE_GERMAN: 772 case LANGUAGE_GERMAN_SWISS: 773 case LANGUAGE_GERMAN_AUSTRIAN: 774 case LANGUAGE_GERMAN_LUXEMBOURG: 775 case LANGUAGE_GERMAN_LIECHTENSTEIN: 776 // alles beim alten 777 pEntry->ConvertLanguage( *pConverter, 778 eSaveSysLang, eLoadSysLang, sal_True ); 779 break; 780 default: 781 // alte english nach neuem anderen 782 pEntry->ConvertLanguage( *pConverter, 783 LANGUAGE_ENGLISH_US, eLoadSysLang, sal_True ); 784 } 785 } 786 else 787 pEntry->ConvertLanguage( *pConverter, 788 eSaveSysLang, eLoadSysLang, sal_True ); 789 } 790 else 791 { // nicht SYSTEM oder gleiches SYSTEM 792 if ( nVersion < SV_NUMBERFORMATTER_VERSION_KEYWORDS ) 793 { 794 LanguageType eLoadLang; 795 sal_Bool bSystem; 796 if ( eLnge == LANGUAGE_SYSTEM ) 797 { 798 eLoadLang = eSysLang; 799 bSystem = sal_True; 800 } 801 else 802 { 803 eLoadLang = eLnge; 804 bSystem = sal_False; 805 } 806 switch ( eLoadLang ) 807 { 808 case LANGUAGE_GERMAN: 809 case LANGUAGE_GERMAN_SWISS: 810 case LANGUAGE_GERMAN_AUSTRIAN: 811 case LANGUAGE_GERMAN_LUXEMBOURG: 812 case LANGUAGE_GERMAN_LIECHTENSTEIN: 813 // alles beim alten 814 break; 815 default: 816 // alte english nach neuem anderen 817 if ( !pConverter ) 818 pConverter = new SvNumberFormatter( xServiceManager, eSysLang ); 819 pEntry->ConvertLanguage( *pConverter, 820 LANGUAGE_ENGLISH_US, eLoadLang, bSystem ); 821 } 822 } 823 } 824 } 825 } 826 if ( nOffset == 0 ) // StandardFormat 827 { 828 SvNumberformat* pEnt = aFTable.Get(nPos); 829 if (pEnt) 830 pEnt->SetLastInsertKey(pEntry->GetLastInsertKey()); 831 } 832 if (!aFTable.Insert(nPos, pEntry)) 833 delete pEntry; 834 rStream >> nPos; 835 } 836 837 // ab SV_NUMBERFORMATTER_VERSION_YEAR2000 838 if ( nVersion >= SV_NUMBERFORMATTER_VERSION_YEAR2000 ) 839 { 840 aHdr.StartEntry(); 841 if ( aHdr.BytesLeft() >= sizeof(sal_uInt16) ) 842 { 843 sal_uInt16 nY2k; 844 rStream >> nY2k; 845 if ( nVersion < SV_NUMBERFORMATTER_VERSION_TWODIGITYEAR && nY2k < 100 ) 846 nY2k += 1901; // war vor src513e: 29, jetzt: 1930 847 SetYear2000( nY2k ); 848 } 849 aHdr.EndEntry(); 850 } 851 852 if ( pConverter ) 853 delete pConverter; 854 855 // generate additional i18n standard formats for all used locales 856 LanguageType eOldLanguage = ActLnge; 857 NumberFormatCodeWrapper aNumberFormatCode( xServiceManager, GetLocale() ); 858 SvUShorts aList; 859 GetUsedLanguages( aList ); 860 sal_uInt16 nCount = aList.Count(); 861 for ( sal_uInt16 j=0; j<nCount; j++ ) 862 { 863 LanguageType eLang = aList[j]; 864 ChangeIntl( eLang ); 865 sal_uInt32 CLOffset = ImpGetCLOffset( eLang ); 866 ImpGenerateAdditionalFormats( CLOffset, aNumberFormatCode, sal_True ); 867 } 868 ChangeIntl( eOldLanguage ); 869 870 if (rStream.GetError()) 871 return sal_False; 872 else 873 return sal_True; 874 } 875 876 sal_Bool SvNumberFormatter::Save( SvStream& rStream ) const 877 { 878 ImpSvNumMultipleWriteHeader aHdr( rStream ); 879 // ab 364i wird gespeichert was SYSTEM wirklich war, vorher hart LANGUAGE_SYSTEM 880 rStream << (sal_uInt16) SV_NUMBERFORMATTER_VERSION; 881 rStream << (sal_uInt16) SvtSysLocale().GetLanguage() << (sal_uInt16) IniLnge; 882 SvNumberFormatTable* pTable = (SvNumberFormatTable*) &aFTable; 883 SvNumberformat* pEntry = (SvNumberformat*) pTable->First(); 884 while (pEntry) 885 { 886 // Gespeichert werden alle markierten, benutzerdefinierten Formate und 887 // jeweils das Standardformat zu allen angewaehlten CL-Kombinationen 888 // sowie NewStandardDefined 889 if ( pEntry->GetUsed() || (pEntry->GetType() & NUMBERFORMAT_DEFINED) || 890 pEntry->GetNewStandardDefined() || 891 (pTable->GetCurKey() % SV_COUNTRY_LANGUAGE_OFFSET == 0) ) 892 { 893 rStream << static_cast<sal_uInt32>(pTable->GetCurKey()) 894 << (sal_uInt16) LANGUAGE_SYSTEM 895 << (sal_uInt16) pEntry->GetLanguage(); 896 pEntry->Save(rStream, aHdr); 897 } 898 pEntry = (SvNumberformat*) pTable->Next(); 899 } 900 rStream << NUMBERFORMAT_ENTRY_NOT_FOUND; // EndeKennung 901 902 // ab SV_NUMBERFORMATTER_VERSION_YEAR2000 903 aHdr.StartEntry(); 904 rStream << (sal_uInt16) GetYear2000(); 905 aHdr.EndEntry(); 906 907 if (rStream.GetError()) 908 return sal_False; 909 else 910 return sal_True; 911 } 912 913 // static 914 void SvNumberFormatter::SkipNumberFormatterInStream( SvStream& rStream ) 915 { 916 ImpSvNumMultipleReadHeader::Skip( rStream ); 917 } 918 919 void SvNumberFormatter::GetUsedLanguages( SvUShorts& rList ) 920 { 921 rList.Remove( 0, rList.Count() ); 922 923 sal_uInt32 nOffset = 0; 924 while (nOffset <= MaxCLOffset) 925 { 926 SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(nOffset); 927 if (pFormat) 928 rList.Insert( pFormat->GetLanguage(), rList.Count() ); 929 nOffset += SV_COUNTRY_LANGUAGE_OFFSET; 930 } 931 } 932 933 934 void SvNumberFormatter::FillKeywordTable( NfKeywordTable& rKeywords, 935 LanguageType eLang ) 936 { 937 ChangeIntl( eLang ); 938 const NfKeywordTable & rTable = pFormatScanner->GetKeywords(); 939 for ( sal_uInt16 i = 0; i < NF_KEYWORD_ENTRIES_COUNT; ++i ) 940 { 941 rKeywords[i] = rTable[i]; 942 } 943 } 944 945 946 String SvNumberFormatter::GetKeyword( LanguageType eLnge, sal_uInt16 nIndex ) 947 { 948 ChangeIntl(eLnge); 949 const NfKeywordTable & rTable = pFormatScanner->GetKeywords(); 950 if ( nIndex < NF_KEYWORD_ENTRIES_COUNT ) 951 return rTable[nIndex]; 952 953 DBG_ERROR("GetKeyword: invalid index"); 954 return String(); 955 } 956 957 958 String SvNumberFormatter::GetStandardName( LanguageType eLnge ) 959 { 960 ChangeIntl( eLnge ); 961 return pFormatScanner->GetStandardName(); 962 } 963 964 965 sal_uInt32 SvNumberFormatter::ImpGetCLOffset(LanguageType eLnge) const 966 { 967 SvNumberformat* pFormat; 968 sal_uInt32 nOffset = 0; 969 while (nOffset <= MaxCLOffset) 970 { 971 pFormat = (SvNumberformat*) aFTable.Get(nOffset); 972 if (pFormat && pFormat->GetLanguage() == eLnge) 973 return nOffset; 974 nOffset += SV_COUNTRY_LANGUAGE_OFFSET; 975 } 976 return nOffset; 977 } 978 979 sal_uInt32 SvNumberFormatter::ImpIsEntry(const String& rString, 980 sal_uInt32 nCLOffset, 981 LanguageType eLnge) 982 { 983 #ifndef NF_COMMENT_IN_FORMATSTRING 984 #error NF_COMMENT_IN_FORMATSTRING not defined (zformat.hxx) 985 #endif 986 #if NF_COMMENT_IN_FORMATSTRING 987 String aStr( rString ); 988 SvNumberformat::EraseComment( aStr ); 989 #endif 990 sal_uInt32 res = NUMBERFORMAT_ENTRY_NOT_FOUND; 991 SvNumberformat* pEntry; 992 pEntry = (SvNumberformat*) aFTable.Seek(nCLOffset); 993 while ( res == NUMBERFORMAT_ENTRY_NOT_FOUND && 994 pEntry && pEntry->GetLanguage() == eLnge ) 995 { 996 #if NF_COMMENT_IN_FORMATSTRING 997 if ( pEntry->GetComment().Len() ) 998 { 999 String aFormat( pEntry->GetFormatstring() ); 1000 SvNumberformat::EraseComment( aFormat ); 1001 if ( aStr == aFormat ) 1002 res = aFTable.GetCurKey(); 1003 else 1004 pEntry = (SvNumberformat*) aFTable.Next(); 1005 } 1006 else 1007 { 1008 if ( aStr == pEntry->GetFormatstring() ) 1009 res = aFTable.GetCurKey(); 1010 else 1011 pEntry = (SvNumberformat*) aFTable.Next(); 1012 } 1013 #else 1014 if ( rString == pEntry->GetFormatstring() ) 1015 res = aFTable.GetCurKey(); 1016 else 1017 pEntry = (SvNumberformat*) aFTable.Next(); 1018 #endif 1019 } 1020 return res; 1021 } 1022 1023 1024 SvNumberFormatTable& SvNumberFormatter::GetFirstEntryTable( 1025 short& eType, 1026 sal_uInt32& FIndex, 1027 LanguageType& rLnge) 1028 { 1029 short eTypetmp = eType; 1030 if (eType == NUMBERFORMAT_ALL) // Leere Zelle oder don't care 1031 rLnge = IniLnge; 1032 else 1033 { 1034 SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(FIndex); 1035 if (!pFormat) 1036 { 1037 // DBG_ERROR("SvNumberFormatter:: Unbekanntes altes Zahlformat (1)"); 1038 rLnge = IniLnge; 1039 eType = NUMBERFORMAT_ALL; 1040 eTypetmp = eType; 1041 } 1042 else 1043 { 1044 rLnge = pFormat->GetLanguage(); 1045 eType = pFormat->GetType()&~NUMBERFORMAT_DEFINED; 1046 if (eType == 0) 1047 { 1048 eType = NUMBERFORMAT_DEFINED; 1049 eTypetmp = eType; 1050 } 1051 else if (eType == NUMBERFORMAT_DATETIME) 1052 { 1053 eTypetmp = eType; 1054 eType = NUMBERFORMAT_DATE; 1055 } 1056 else 1057 eTypetmp = eType; 1058 } 1059 } 1060 ChangeIntl(rLnge); 1061 return GetEntryTable(eTypetmp, FIndex, rLnge); 1062 } 1063 1064 sal_uInt32 SvNumberFormatter::ImpGenerateCL( LanguageType eLnge, sal_Bool bLoadingSO5 ) 1065 { 1066 ChangeIntl(eLnge); 1067 sal_uInt32 CLOffset = ImpGetCLOffset(ActLnge); 1068 if (CLOffset > MaxCLOffset) 1069 { // new CL combination 1070 if (LocaleDataWrapper::areChecksEnabled()) 1071 { 1072 Locale aLoadedLocale = xLocaleData->getLoadedLocale(); 1073 if ( aLoadedLocale.Language != aLocale.Language || 1074 aLoadedLocale.Country != aLocale.Country ) 1075 { 1076 String aMsg( RTL_CONSTASCII_USTRINGPARAM( 1077 "SvNumerFormatter::ImpGenerateCL: locales don't match:")); 1078 LocaleDataWrapper::outputCheckMessage( 1079 xLocaleData->appendLocaleInfo( aMsg )); 1080 } 1081 // test XML locale data FormatElement entries 1082 { 1083 uno::Sequence< i18n::FormatElement > xSeq = 1084 xLocaleData->getAllFormats(); 1085 // A test for completeness of formatindex="0" ... 1086 // formatindex="47" is not needed here since it is done in 1087 // ImpGenerateFormats(). 1088 1089 // Test for dupes of formatindex="..." 1090 for ( sal_Int32 j = 0; j < xSeq.getLength(); j++ ) 1091 { 1092 sal_Int16 nIdx = xSeq[j].formatIndex; 1093 String aDupes; 1094 for ( sal_Int32 i = 0; i < xSeq.getLength(); i++ ) 1095 { 1096 if ( i != j && xSeq[i].formatIndex == nIdx ) 1097 { 1098 aDupes += String::CreateFromInt32( i ); 1099 aDupes += '('; 1100 aDupes += String( xSeq[i].formatKey ); 1101 aDupes += ')'; 1102 aDupes += ' '; 1103 } 1104 } 1105 if ( aDupes.Len() ) 1106 { 1107 String aMsg( RTL_CONSTASCII_USTRINGPARAM( 1108 "XML locale data FormatElement formatindex dupe: ")); 1109 aMsg += String::CreateFromInt32( nIdx ); 1110 aMsg.AppendAscii( RTL_CONSTASCII_STRINGPARAM( 1111 "\nFormatElements: ")); 1112 aMsg += String::CreateFromInt32( j ); 1113 aMsg += '('; 1114 aMsg += String( xSeq[j].formatKey ); 1115 aMsg += ')'; 1116 aMsg += ' '; 1117 aMsg += aDupes; 1118 LocaleDataWrapper::outputCheckMessage( 1119 xLocaleData->appendLocaleInfo( aMsg )); 1120 } 1121 } 1122 } 1123 } 1124 1125 MaxCLOffset += SV_COUNTRY_LANGUAGE_OFFSET; 1126 ImpGenerateFormats( MaxCLOffset, bLoadingSO5 ); 1127 CLOffset = MaxCLOffset; 1128 } 1129 return CLOffset; 1130 } 1131 1132 SvNumberFormatTable& SvNumberFormatter::ChangeCL(short eType, 1133 sal_uInt32& FIndex, 1134 LanguageType eLnge) 1135 { 1136 ImpGenerateCL(eLnge); 1137 return GetEntryTable(eType, FIndex, ActLnge); 1138 } 1139 1140 SvNumberFormatTable& SvNumberFormatter::GetEntryTable( 1141 short eType, 1142 sal_uInt32& FIndex, 1143 LanguageType eLnge) 1144 { 1145 if ( pFormatTable ) 1146 pFormatTable->Clear(); 1147 else 1148 pFormatTable = new SvNumberFormatTable; 1149 ChangeIntl(eLnge); 1150 sal_uInt32 CLOffset = ImpGetCLOffset(ActLnge); 1151 1152 // Might generate and insert a default format for the given type 1153 // (e.g. currency) => has to be done before collecting formats. 1154 sal_uInt32 nDefaultIndex = GetStandardFormat( eType, ActLnge ); 1155 1156 SvNumberformat* pEntry; 1157 pEntry = (SvNumberformat*) aFTable.Seek(CLOffset); 1158 1159 if (eType == NUMBERFORMAT_ALL) 1160 { 1161 while (pEntry && pEntry->GetLanguage() == ActLnge) 1162 { // copy all entries to output table 1163 pFormatTable->Insert( aFTable.GetCurKey(), pEntry ); 1164 pEntry = (SvNumberformat*) aFTable.Next(); 1165 } 1166 } 1167 else 1168 { 1169 while (pEntry && pEntry->GetLanguage() == ActLnge) 1170 { // copy entries of queried type to output table 1171 if ((pEntry->GetType()) & eType) 1172 pFormatTable->Insert(aFTable.GetCurKey(),pEntry); 1173 pEntry = (SvNumberformat*) aFTable.Next(); 1174 } 1175 } 1176 if ( pFormatTable->Count() > 0 ) 1177 { // select default if queried format doesn't exist or queried type or 1178 // language differ from existing format 1179 pEntry = aFTable.Get(FIndex); 1180 if ( !pEntry || !(pEntry->GetType() & eType) || pEntry->GetLanguage() != ActLnge ) 1181 FIndex = nDefaultIndex; 1182 } 1183 return *pFormatTable; 1184 } 1185 1186 sal_Bool SvNumberFormatter::IsNumberFormat(const String& sString, 1187 sal_uInt32& F_Index, 1188 double& fOutNumber) 1189 { 1190 short FType; 1191 const SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(F_Index); 1192 if (!pFormat) 1193 { 1194 // DBG_ERROR("SvNumberFormatter:: Unbekanntes altes Zahlformat (2)"); 1195 ChangeIntl(IniLnge); 1196 FType = NUMBERFORMAT_NUMBER; 1197 } 1198 else 1199 { 1200 FType = pFormat->GetType() &~NUMBERFORMAT_DEFINED; 1201 if (FType == 0) 1202 FType = NUMBERFORMAT_DEFINED; 1203 ChangeIntl(pFormat->GetLanguage()); 1204 } 1205 sal_Bool res; 1206 short RType = FType; 1207 // Ergebnistyp 1208 // ohne def-Kennung 1209 if (RType == NUMBERFORMAT_TEXT) // Zahlzelle ->Stringz. 1210 res = sal_False; 1211 else 1212 res = pStringScanner->IsNumberFormat(sString, RType, fOutNumber, pFormat); 1213 1214 if (res && !IsCompatible(FType, RType)) // unpassender Typ 1215 { 1216 switch ( RType ) 1217 { 1218 case NUMBERFORMAT_TIME : 1219 { 1220 if ( pStringScanner->GetDecPos() ) 1221 { // 100stel Sekunden 1222 if ( pStringScanner->GetAnzNums() > 3 || fOutNumber < 0.0 ) 1223 F_Index = GetFormatIndex( NF_TIME_HH_MMSS00, ActLnge ); 1224 else 1225 F_Index = GetFormatIndex( NF_TIME_MMSS00, ActLnge ); 1226 } 1227 else if ( fOutNumber >= 1.0 || fOutNumber < 0.0 ) 1228 F_Index = GetFormatIndex( NF_TIME_HH_MMSS, ActLnge ); 1229 else 1230 F_Index = GetStandardFormat( RType, ActLnge ); 1231 } 1232 break; 1233 default: 1234 F_Index = GetStandardFormat( RType, ActLnge ); 1235 } 1236 } 1237 return res; 1238 } 1239 1240 sal_Bool SvNumberFormatter::IsCompatible(short eOldType, 1241 short eNewType) 1242 { 1243 if (eOldType == eNewType) 1244 return sal_True; 1245 else if (eOldType == NUMBERFORMAT_DEFINED) 1246 return sal_True; 1247 else 1248 { 1249 switch (eNewType) 1250 { 1251 case NUMBERFORMAT_NUMBER: 1252 { 1253 switch (eOldType) 1254 { 1255 case NUMBERFORMAT_PERCENT: 1256 case NUMBERFORMAT_CURRENCY: 1257 case NUMBERFORMAT_SCIENTIFIC: 1258 case NUMBERFORMAT_FRACTION: 1259 // case NUMBERFORMAT_LOGICAL: 1260 case NUMBERFORMAT_DEFINED: 1261 return sal_True; 1262 default: 1263 return sal_False; 1264 } 1265 } 1266 break; 1267 case NUMBERFORMAT_DATE: 1268 { 1269 switch (eOldType) 1270 { 1271 case NUMBERFORMAT_DATETIME: 1272 return sal_True; 1273 default: 1274 return sal_False; 1275 } 1276 } 1277 break; 1278 case NUMBERFORMAT_TIME: 1279 { 1280 switch (eOldType) 1281 { 1282 case NUMBERFORMAT_DATETIME: 1283 return sal_True; 1284 default: 1285 return sal_False; 1286 } 1287 } 1288 break; 1289 case NUMBERFORMAT_DATETIME: 1290 { 1291 switch (eOldType) 1292 { 1293 case NUMBERFORMAT_TIME: 1294 case NUMBERFORMAT_DATE: 1295 return sal_True; 1296 default: 1297 return sal_False; 1298 } 1299 } 1300 break; 1301 default: 1302 return sal_False; 1303 } 1304 return sal_False; 1305 } 1306 } 1307 1308 1309 sal_uInt32 SvNumberFormatter::ImpGetDefaultFormat( short nType ) 1310 { 1311 sal_uInt32 CLOffset = ImpGetCLOffset( ActLnge ); 1312 sal_uInt32 nSearch; 1313 switch( nType ) 1314 { 1315 case NUMBERFORMAT_DATE : 1316 nSearch = CLOffset + ZF_STANDARD_DATE; 1317 break; 1318 case NUMBERFORMAT_TIME : 1319 nSearch = CLOffset + ZF_STANDARD_TIME; 1320 break; 1321 case NUMBERFORMAT_DATETIME : 1322 nSearch = CLOffset + ZF_STANDARD_DATETIME; 1323 break; 1324 case NUMBERFORMAT_PERCENT : 1325 nSearch = CLOffset + ZF_STANDARD_PERCENT; 1326 break; 1327 case NUMBERFORMAT_SCIENTIFIC: 1328 nSearch = CLOffset + ZF_STANDARD_SCIENTIFIC; 1329 break; 1330 default: 1331 nSearch = CLOffset + ZF_STANDARD; 1332 } 1333 sal_uInt32 nDefaultFormat = (sal_uInt32)(sal_uLong) aDefaultFormatKeys.Get( nSearch ); 1334 if ( !nDefaultFormat ) 1335 nDefaultFormat = NUMBERFORMAT_ENTRY_NOT_FOUND; 1336 if ( nDefaultFormat == NUMBERFORMAT_ENTRY_NOT_FOUND ) 1337 { // look for a defined standard 1338 sal_uInt32 nStopKey = CLOffset + SV_COUNTRY_LANGUAGE_OFFSET; 1339 sal_uInt32 nKey; 1340 aFTable.Seek( CLOffset ); 1341 while ( (nKey = aFTable.GetCurKey()) >= CLOffset && nKey < nStopKey ) 1342 { 1343 const SvNumberformat* pEntry = 1344 (const SvNumberformat*) aFTable.GetCurObject(); 1345 if ( pEntry->IsStandard() && ((pEntry->GetType() & 1346 ~NUMBERFORMAT_DEFINED) == nType) ) 1347 { 1348 nDefaultFormat = nKey; 1349 break; // while 1350 } 1351 aFTable.Next(); 1352 } 1353 1354 if ( nDefaultFormat == NUMBERFORMAT_ENTRY_NOT_FOUND ) 1355 { // none found, use old fixed standards 1356 switch( nType ) 1357 { 1358 case NUMBERFORMAT_DATE : 1359 nDefaultFormat = CLOffset + ZF_STANDARD_DATE; 1360 break; 1361 case NUMBERFORMAT_TIME : 1362 nDefaultFormat = CLOffset + ZF_STANDARD_TIME+1; 1363 break; 1364 case NUMBERFORMAT_DATETIME : 1365 nDefaultFormat = CLOffset + ZF_STANDARD_DATETIME; 1366 break; 1367 case NUMBERFORMAT_PERCENT : 1368 nDefaultFormat = CLOffset + ZF_STANDARD_PERCENT+1; 1369 break; 1370 case NUMBERFORMAT_SCIENTIFIC: 1371 nDefaultFormat = CLOffset + ZF_STANDARD_SCIENTIFIC; 1372 break; 1373 default: 1374 nDefaultFormat = CLOffset + ZF_STANDARD; 1375 } 1376 } 1377 aDefaultFormatKeys.Insert( nSearch, (void*) nDefaultFormat ); 1378 } 1379 return nDefaultFormat; 1380 } 1381 1382 1383 sal_uInt32 SvNumberFormatter::GetStandardFormat( short eType, LanguageType eLnge ) 1384 { 1385 sal_uInt32 CLOffset = ImpGenerateCL(eLnge); 1386 switch(eType) 1387 { 1388 case NUMBERFORMAT_CURRENCY : 1389 { 1390 if ( eLnge == LANGUAGE_SYSTEM ) 1391 return ImpGetDefaultSystemCurrencyFormat(); 1392 else 1393 return ImpGetDefaultCurrencyFormat(); 1394 } 1395 case NUMBERFORMAT_DATE : 1396 case NUMBERFORMAT_TIME : 1397 case NUMBERFORMAT_DATETIME : 1398 case NUMBERFORMAT_PERCENT : 1399 case NUMBERFORMAT_SCIENTIFIC: 1400 return ImpGetDefaultFormat( eType ); 1401 1402 case NUMBERFORMAT_FRACTION : return CLOffset + ZF_STANDARD_FRACTION; 1403 case NUMBERFORMAT_LOGICAL : return CLOffset + ZF_STANDARD_LOGICAL; 1404 case NUMBERFORMAT_TEXT : return CLOffset + ZF_STANDARD_TEXT; 1405 case NUMBERFORMAT_ALL : 1406 case NUMBERFORMAT_DEFINED : 1407 case NUMBERFORMAT_NUMBER : 1408 case NUMBERFORMAT_UNDEFINED : 1409 default : return CLOffset + ZF_STANDARD; 1410 } 1411 } 1412 1413 sal_Bool SvNumberFormatter::IsSpecialStandardFormat( sal_uInt32 nFIndex, 1414 LanguageType eLnge ) 1415 { 1416 return 1417 nFIndex == GetFormatIndex( NF_TIME_MMSS00, eLnge ) || 1418 nFIndex == GetFormatIndex( NF_TIME_HH_MMSS00, eLnge ) || 1419 nFIndex == GetFormatIndex( NF_TIME_HH_MMSS, eLnge ) 1420 ; 1421 } 1422 1423 sal_uInt32 SvNumberFormatter::GetStandardFormat( sal_uInt32 nFIndex, short eType, 1424 LanguageType eLnge ) 1425 { 1426 if ( IsSpecialStandardFormat( nFIndex, eLnge ) ) 1427 return nFIndex; 1428 else 1429 return GetStandardFormat( eType, eLnge ); 1430 } 1431 1432 sal_uInt32 SvNumberFormatter::GetStandardFormat( double fNumber, sal_uInt32 nFIndex, 1433 short eType, LanguageType eLnge ) 1434 { 1435 if ( IsSpecialStandardFormat( nFIndex, eLnge ) ) 1436 return nFIndex; 1437 1438 switch( eType ) 1439 { 1440 case NUMBERFORMAT_TIME : 1441 { 1442 sal_Bool bSign; 1443 if ( fNumber < 0.0 ) 1444 { 1445 bSign = sal_True; 1446 fNumber = -fNumber; 1447 } 1448 else 1449 bSign = sal_False; 1450 double fSeconds = fNumber * 86400; 1451 if ( floor( fSeconds + 0.5 ) * 100 != floor( fSeconds * 100 + 0.5 ) ) 1452 { // mit 100stel Sekunden 1453 if ( bSign || fSeconds >= 3600 ) 1454 return GetFormatIndex( NF_TIME_HH_MMSS00, eLnge ); 1455 else 1456 return GetFormatIndex( NF_TIME_MMSS00, eLnge ); 1457 } 1458 else 1459 { 1460 if ( bSign || fNumber >= 1.0 ) 1461 return GetFormatIndex( NF_TIME_HH_MMSS, eLnge ); 1462 else 1463 return GetStandardFormat( eType, eLnge ); 1464 } 1465 } 1466 default: 1467 return GetStandardFormat( eType, eLnge ); 1468 } 1469 } 1470 1471 void SvNumberFormatter::GetInputLineString(const double& fOutNumber, 1472 sal_uInt32 nFIndex, 1473 String& sOutString) 1474 { 1475 SvNumberformat* pFormat; 1476 Color* pColor; 1477 pFormat = (SvNumberformat*) aFTable.Get(nFIndex); 1478 if (!pFormat) 1479 pFormat = aFTable.Get(ZF_STANDARD); 1480 LanguageType eLang = pFormat->GetLanguage(); 1481 ChangeIntl( eLang ); 1482 short eType = pFormat->GetType() & ~NUMBERFORMAT_DEFINED; 1483 if (eType == 0) 1484 eType = NUMBERFORMAT_DEFINED; 1485 sal_uInt16 nOldPrec = pFormatScanner->GetStandardPrec(); 1486 bool bPrecChanged = false; 1487 if (eType == NUMBERFORMAT_NUMBER || eType == NUMBERFORMAT_PERCENT 1488 || eType == NUMBERFORMAT_CURRENCY 1489 || eType == NUMBERFORMAT_SCIENTIFIC 1490 || eType == NUMBERFORMAT_FRACTION) 1491 { 1492 if (eType != NUMBERFORMAT_PERCENT) // spaeter Sonderbehandlung % 1493 eType = NUMBERFORMAT_NUMBER; 1494 ChangeStandardPrec(INPUTSTRING_PRECISION); 1495 bPrecChanged = true; 1496 } 1497 sal_uInt32 nKey = nFIndex; 1498 switch ( eType ) 1499 { // #61619# immer vierstelliges Jahr editieren 1500 case NUMBERFORMAT_DATE : 1501 nKey = GetFormatIndex( NF_DATE_SYS_DDMMYYYY, eLang ); 1502 break; 1503 case NUMBERFORMAT_DATETIME : 1504 nKey = GetFormatIndex( NF_DATETIME_SYS_DDMMYYYY_HHMMSS, eLang ); 1505 break; 1506 default: 1507 nKey = GetStandardFormat( fOutNumber, nFIndex, eType, eLang ); 1508 } 1509 if ( nKey != nFIndex ) 1510 pFormat = (SvNumberformat*) aFTable.Get( nKey ); 1511 if (pFormat) 1512 { 1513 if ( eType == NUMBERFORMAT_TIME && pFormat->GetFormatPrecision() ) 1514 { 1515 ChangeStandardPrec(INPUTSTRING_PRECISION); 1516 bPrecChanged = true; 1517 } 1518 pFormat->GetOutputString(fOutNumber, sOutString, &pColor); 1519 } 1520 if (bPrecChanged) 1521 ChangeStandardPrec(nOldPrec); 1522 } 1523 1524 void SvNumberFormatter::GetOutputString(const double& fOutNumber, 1525 sal_uInt32 nFIndex, 1526 String& sOutString, 1527 Color** ppColor) 1528 { 1529 if (bNoZero && fOutNumber == 0.0) 1530 { 1531 sOutString.Erase(); 1532 return; 1533 } 1534 SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(nFIndex); 1535 if (!pFormat) 1536 pFormat = aFTable.Get(ZF_STANDARD); 1537 ChangeIntl(pFormat->GetLanguage()); 1538 pFormat->GetOutputString(fOutNumber, sOutString, ppColor); 1539 } 1540 1541 void SvNumberFormatter::GetOutputString(String& sString, 1542 sal_uInt32 nFIndex, 1543 String& sOutString, 1544 Color** ppColor) 1545 { 1546 SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(nFIndex); 1547 if (!pFormat) 1548 pFormat = aFTable.Get(ZF_STANDARD_TEXT); 1549 if (!pFormat->IsTextFormat() && !pFormat->HasTextFormat()) 1550 { 1551 *ppColor = NULL; 1552 sOutString = sString; 1553 } 1554 else 1555 { 1556 ChangeIntl(pFormat->GetLanguage()); 1557 pFormat->GetOutputString(sString, sOutString, ppColor); 1558 } 1559 } 1560 1561 sal_Bool SvNumberFormatter::GetPreviewString(const String& sFormatString, 1562 double fPreviewNumber, 1563 String& sOutString, 1564 Color** ppColor, 1565 LanguageType eLnge) 1566 { 1567 if (sFormatString.Len() == 0) // keinen Leerstring 1568 return sal_False; 1569 1570 xub_StrLen nCheckPos = STRING_NOTFOUND; 1571 sal_uInt32 nKey; 1572 if (eLnge == LANGUAGE_DONTKNOW) 1573 eLnge = IniLnge; 1574 ChangeIntl(eLnge); // ggfs. austauschen 1575 eLnge = ActLnge; 1576 String sTmpString = sFormatString; 1577 SvNumberformat* p_Entry = new SvNumberformat(sTmpString, 1578 pFormatScanner, 1579 pStringScanner, 1580 nCheckPos, 1581 eLnge); 1582 if (nCheckPos == 0) // String ok 1583 { 1584 sal_uInt32 CLOffset = ImpGenerateCL(eLnge); // ggfs. neu Standard- 1585 // formate anlegen 1586 nKey = ImpIsEntry(p_Entry->GetFormatstring(),CLOffset, eLnge); 1587 if (nKey != NUMBERFORMAT_ENTRY_NOT_FOUND) // schon vorhanden 1588 GetOutputString(fPreviewNumber,nKey,sOutString,ppColor); 1589 else 1590 p_Entry->GetOutputString(fPreviewNumber,sOutString, ppColor); 1591 delete p_Entry; 1592 return sal_True; 1593 } 1594 else 1595 { 1596 delete p_Entry; 1597 return sal_False; 1598 } 1599 } 1600 1601 sal_Bool SvNumberFormatter::GetPreviewStringGuess( const String& sFormatString, 1602 double fPreviewNumber, 1603 String& sOutString, 1604 Color** ppColor, 1605 LanguageType eLnge ) 1606 { 1607 if (sFormatString.Len() == 0) // keinen Leerstring 1608 return sal_False; 1609 1610 if (eLnge == LANGUAGE_DONTKNOW) 1611 eLnge = IniLnge; 1612 1613 ChangeIntl( eLnge ); 1614 eLnge = ActLnge; 1615 sal_Bool bEnglish = (eLnge == LANGUAGE_ENGLISH_US); 1616 1617 String aFormatStringUpper( pCharClass->upper( sFormatString ) ); 1618 sal_uInt32 nCLOffset = ImpGenerateCL( eLnge ); 1619 sal_uInt32 nKey = ImpIsEntry( aFormatStringUpper, nCLOffset, eLnge ); 1620 if ( nKey != NUMBERFORMAT_ENTRY_NOT_FOUND ) 1621 { // Zielformat vorhanden 1622 GetOutputString( fPreviewNumber, nKey, sOutString, ppColor ); 1623 return sal_True; 1624 } 1625 1626 SvNumberformat *pEntry = NULL; 1627 xub_StrLen nCheckPos = STRING_NOTFOUND; 1628 String sTmpString; 1629 1630 if ( bEnglish ) 1631 { 1632 sTmpString = sFormatString; 1633 pEntry = new SvNumberformat( sTmpString, pFormatScanner, 1634 pStringScanner, nCheckPos, eLnge ); 1635 } 1636 else 1637 { 1638 nCLOffset = ImpGenerateCL( LANGUAGE_ENGLISH_US ); 1639 nKey = ImpIsEntry( aFormatStringUpper, nCLOffset, LANGUAGE_ENGLISH_US ); 1640 sal_Bool bEnglishFormat = (nKey != NUMBERFORMAT_ENTRY_NOT_FOUND); 1641 1642 // try english --> other bzw. english nach other konvertieren 1643 LanguageType eFormatLang = LANGUAGE_ENGLISH_US; 1644 pFormatScanner->SetConvertMode( LANGUAGE_ENGLISH_US, eLnge ); 1645 sTmpString = sFormatString; 1646 pEntry = new SvNumberformat( sTmpString, pFormatScanner, 1647 pStringScanner, nCheckPos, eFormatLang ); 1648 pFormatScanner->SetConvertMode( sal_False ); 1649 ChangeIntl( eLnge ); 1650 1651 if ( !bEnglishFormat ) 1652 { 1653 if ( nCheckPos > 0 || xTransliteration->isEqual( sFormatString, 1654 pEntry->GetFormatstring() ) ) 1655 { // other Format 1656 delete pEntry; 1657 sTmpString = sFormatString; 1658 pEntry = new SvNumberformat( sTmpString, pFormatScanner, 1659 pStringScanner, nCheckPos, eLnge ); 1660 } 1661 else 1662 { // verify english 1663 xub_StrLen nCheckPos2 = STRING_NOTFOUND; 1664 // try other --> english 1665 eFormatLang = eLnge; 1666 pFormatScanner->SetConvertMode( eLnge, LANGUAGE_ENGLISH_US ); 1667 sTmpString = sFormatString; 1668 SvNumberformat* pEntry2 = new SvNumberformat( sTmpString, pFormatScanner, 1669 pStringScanner, nCheckPos2, eFormatLang ); 1670 pFormatScanner->SetConvertMode( sal_False ); 1671 ChangeIntl( eLnge ); 1672 if ( nCheckPos2 == 0 && !xTransliteration->isEqual( sFormatString, 1673 pEntry2->GetFormatstring() ) ) 1674 { // other Format 1675 delete pEntry; 1676 sTmpString = sFormatString; 1677 pEntry = new SvNumberformat( sTmpString, pFormatScanner, 1678 pStringScanner, nCheckPos, eLnge ); 1679 } 1680 delete pEntry2; 1681 } 1682 } 1683 } 1684 1685 if (nCheckPos == 0) // String ok 1686 { 1687 ImpGenerateCL( eLnge ); // ggfs. neu Standardformate anlegen 1688 pEntry->GetOutputString( fPreviewNumber, sOutString, ppColor ); 1689 delete pEntry; 1690 return sal_True; 1691 } 1692 delete pEntry; 1693 return sal_False; 1694 } 1695 1696 sal_Bool SvNumberFormatter::GetPreviewString( const String& sFormatString, 1697 const String& sPreviewString, 1698 String& sOutString, 1699 Color** ppColor, 1700 LanguageType eLnge ) 1701 { 1702 if (sFormatString.Len() == 0) // no empty string 1703 return sal_False; 1704 1705 xub_StrLen nCheckPos = STRING_NOTFOUND; 1706 sal_uInt32 nKey; 1707 if (eLnge == LANGUAGE_DONTKNOW) 1708 eLnge = IniLnge; 1709 ChangeIntl(eLnge); // switch if needed 1710 eLnge = ActLnge; 1711 String sTmpString = sFormatString; 1712 SvNumberformat* p_Entry = new SvNumberformat( sTmpString, 1713 pFormatScanner, 1714 pStringScanner, 1715 nCheckPos, 1716 eLnge); 1717 if (nCheckPos == 0) // String ok 1718 { 1719 String aNonConstPreview( sPreviewString); 1720 // May have to create standard formats for this locale. 1721 sal_uInt32 CLOffset = ImpGenerateCL(eLnge); 1722 nKey = ImpIsEntry( p_Entry->GetFormatstring(), CLOffset, eLnge); 1723 if (nKey != NUMBERFORMAT_ENTRY_NOT_FOUND) // already present 1724 GetOutputString( aNonConstPreview, nKey, sOutString, ppColor); 1725 else 1726 { 1727 // If the format is valid but not a text format and does not 1728 // include a text subformat, an empty string would result. Same as 1729 // in SvNumberFormatter::GetOutputString() 1730 if (p_Entry->IsTextFormat() || p_Entry->HasTextFormat()) 1731 p_Entry->GetOutputString( aNonConstPreview, sOutString, ppColor); 1732 else 1733 { 1734 *ppColor = NULL; 1735 sOutString = sPreviewString; 1736 } 1737 } 1738 delete p_Entry; 1739 return sal_True; 1740 } 1741 else 1742 { 1743 delete p_Entry; 1744 return sal_False; 1745 } 1746 } 1747 1748 sal_uInt32 SvNumberFormatter::TestNewString(const String& sFormatString, 1749 LanguageType eLnge) 1750 { 1751 if (sFormatString.Len() == 0) // keinen Leerstring 1752 return NUMBERFORMAT_ENTRY_NOT_FOUND; 1753 1754 xub_StrLen nCheckPos = STRING_NOTFOUND; 1755 if (eLnge == LANGUAGE_DONTKNOW) 1756 eLnge = IniLnge; 1757 ChangeIntl(eLnge); // ggfs. austauschen 1758 eLnge = ActLnge; 1759 sal_uInt32 nRes; 1760 String sTmpString = sFormatString; 1761 SvNumberformat* pEntry = new SvNumberformat(sTmpString, 1762 pFormatScanner, 1763 pStringScanner, 1764 nCheckPos, 1765 eLnge); 1766 if (nCheckPos == 0) // String ok 1767 { 1768 sal_uInt32 CLOffset = ImpGenerateCL(eLnge); // ggfs. neu Standard- 1769 // formate anlegen 1770 nRes = ImpIsEntry(pEntry->GetFormatstring(),CLOffset, eLnge); 1771 // schon vorhanden ? 1772 } 1773 else 1774 nRes = NUMBERFORMAT_ENTRY_NOT_FOUND; 1775 delete pEntry; 1776 return nRes; 1777 } 1778 1779 SvNumberformat* SvNumberFormatter::ImpInsertFormat( 1780 const ::com::sun::star::i18n::NumberFormatCode& rCode, 1781 sal_uInt32 nPos, sal_Bool bAfterLoadingSO5, sal_Int16 nOrgIndex ) 1782 { 1783 String aCodeStr( rCode.Code ); 1784 if ( rCode.Index < NF_INDEX_TABLE_ENTRIES && 1785 rCode.Usage == ::com::sun::star::i18n::KNumberFormatUsage::CURRENCY && 1786 rCode.Index != NF_CURRENCY_1000DEC2_CCC ) 1787 { // strip surrounding [$...] on automatic currency 1788 if ( aCodeStr.SearchAscii( "[$" ) != STRING_NOTFOUND ) 1789 aCodeStr = SvNumberformat::StripNewCurrencyDelimiters( aCodeStr, sal_False ); 1790 else 1791 { 1792 if (LocaleDataWrapper::areChecksEnabled() && 1793 rCode.Index != NF_CURRENCY_1000DEC2_CCC ) 1794 { 1795 String aMsg( RTL_CONSTASCII_USTRINGPARAM( 1796 "SvNumberFormatter::ImpInsertFormat: no [$...] on currency format code, index ")); 1797 aMsg += String::CreateFromInt32( rCode.Index ); 1798 aMsg.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ":\n")); 1799 aMsg += String( rCode.Code ); 1800 LocaleDataWrapper::outputCheckMessage( 1801 xLocaleData->appendLocaleInfo( aMsg)); 1802 } 1803 } 1804 } 1805 xub_StrLen nCheckPos = 0; 1806 SvNumberformat* pFormat = new SvNumberformat(aCodeStr, 1807 pFormatScanner, 1808 pStringScanner, 1809 nCheckPos, 1810 ActLnge); 1811 if ( !pFormat || nCheckPos > 0 ) 1812 { 1813 if (LocaleDataWrapper::areChecksEnabled()) 1814 { 1815 String aMsg( RTL_CONSTASCII_USTRINGPARAM( 1816 "SvNumberFormatter::ImpInsertFormat: bad format code, index ")); 1817 aMsg += String::CreateFromInt32( rCode.Index ); 1818 aMsg += '\n'; 1819 aMsg += String( rCode.Code ); 1820 LocaleDataWrapper::outputCheckMessage( 1821 xLocaleData->appendLocaleInfo( aMsg)); 1822 } 1823 delete pFormat; 1824 return NULL; 1825 } 1826 if ( rCode.Index >= NF_INDEX_TABLE_ENTRIES ) 1827 { 1828 sal_uInt32 nCLOffset = nPos - (nPos % SV_COUNTRY_LANGUAGE_OFFSET); 1829 sal_uInt32 nKey = ImpIsEntry( aCodeStr, nCLOffset, ActLnge ); 1830 if ( nKey != NUMBERFORMAT_ENTRY_NOT_FOUND ) 1831 { 1832 if (LocaleDataWrapper::areChecksEnabled()) 1833 { 1834 switch ( nOrgIndex ) 1835 { 1836 // These may be dupes of integer versions for locales where 1837 // currencies have no decimals like Italian Lira. 1838 case NF_CURRENCY_1000DEC2 : // NF_CURRENCY_1000INT 1839 case NF_CURRENCY_1000DEC2_RED : // NF_CURRENCY_1000INT_RED 1840 case NF_CURRENCY_1000DEC2_DASHED : // NF_CURRENCY_1000INT_RED 1841 break; 1842 default: 1843 if ( !bAfterLoadingSO5 ) 1844 { // If bAfterLoadingSO5 there will definitely be some dupes, 1845 // don't cry. But we need this test for verification of locale 1846 // data if not loading old SO5 documents. 1847 String aMsg( RTL_CONSTASCII_USTRINGPARAM( 1848 "SvNumberFormatter::ImpInsertFormat: dup format code, index ")); 1849 aMsg += String::CreateFromInt32( rCode.Index ); 1850 aMsg += '\n'; 1851 aMsg += String( rCode.Code ); 1852 LocaleDataWrapper::outputCheckMessage( 1853 xLocaleData->appendLocaleInfo( aMsg)); 1854 } 1855 } 1856 } 1857 delete pFormat; 1858 return NULL; 1859 } 1860 else if ( nPos - nCLOffset >= SV_COUNTRY_LANGUAGE_OFFSET ) 1861 { 1862 if (LocaleDataWrapper::areChecksEnabled()) 1863 { 1864 String aMsg( RTL_CONSTASCII_USTRINGPARAM( 1865 "SvNumberFormatter::ImpInsertFormat: too many format codes, index ")); 1866 aMsg += String::CreateFromInt32( rCode.Index ); 1867 aMsg += '\n'; 1868 aMsg += String( rCode.Code ); 1869 LocaleDataWrapper::outputCheckMessage( 1870 xLocaleData->appendLocaleInfo( aMsg)); 1871 } 1872 delete pFormat; 1873 return NULL; 1874 } 1875 } 1876 if ( !aFTable.Insert( nPos, pFormat ) ) 1877 { 1878 if (LocaleDataWrapper::areChecksEnabled()) 1879 { 1880 String aMsg( RTL_CONSTASCII_USTRINGPARAM( 1881 "ImpInsertFormat: can't insert number format key pos: ")); 1882 aMsg += String::CreateFromInt32( nPos ); 1883 aMsg.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ", code index ")); 1884 aMsg += String::CreateFromInt32( rCode.Index ); 1885 aMsg += '\n'; 1886 aMsg += String( rCode.Code ); 1887 LocaleDataWrapper::outputCheckMessage( 1888 xLocaleData->appendLocaleInfo( aMsg)); 1889 } 1890 delete pFormat; 1891 return NULL; 1892 } 1893 if ( rCode.Default ) 1894 pFormat->SetStandard(); 1895 if ( rCode.DefaultName.getLength() ) 1896 pFormat->SetComment( rCode.DefaultName ); 1897 return pFormat; 1898 } 1899 1900 SvNumberformat* SvNumberFormatter::ImpInsertNewStandardFormat( 1901 const ::com::sun::star::i18n::NumberFormatCode& rCode, 1902 sal_uInt32 nPos, sal_uInt16 nVersion, sal_Bool bAfterLoadingSO5, 1903 sal_Int16 nOrgIndex ) 1904 { 1905 SvNumberformat* pNewFormat = ImpInsertFormat( rCode, nPos, 1906 bAfterLoadingSO5, nOrgIndex ); 1907 if (pNewFormat) 1908 pNewFormat->SetNewStandardDefined( nVersion ); 1909 // so that it gets saved, displayed properly, and converted by old versions 1910 return pNewFormat; 1911 } 1912 1913 void SvNumberFormatter::GetFormatSpecialInfo(sal_uInt32 nFormat, 1914 sal_Bool& bThousand, 1915 sal_Bool& IsRed, 1916 sal_uInt16& nPrecision, 1917 sal_uInt16& nAnzLeading) 1918 1919 { 1920 const SvNumberformat* pFormat = aFTable.Get(nFormat); 1921 if (pFormat) 1922 pFormat->GetFormatSpecialInfo(bThousand, IsRed, 1923 nPrecision, nAnzLeading); 1924 else 1925 { 1926 bThousand = sal_False; 1927 IsRed = sal_False; 1928 nPrecision = pFormatScanner->GetStandardPrec(); 1929 nAnzLeading = 0; 1930 } 1931 } 1932 1933 sal_uInt16 SvNumberFormatter::GetFormatPrecision( sal_uInt32 nFormat ) const 1934 { 1935 const SvNumberformat* pFormat = aFTable.Get( nFormat ); 1936 if ( pFormat ) 1937 return pFormat->GetFormatPrecision(); 1938 else 1939 return pFormatScanner->GetStandardPrec(); 1940 } 1941 1942 1943 String SvNumberFormatter::GetFormatDecimalSep( sal_uInt32 nFormat ) const 1944 { 1945 const SvNumberformat* pFormat = aFTable.Get( nFormat ); 1946 if ( !pFormat || pFormat->GetLanguage() == ActLnge ) 1947 return GetNumDecimalSep(); 1948 1949 String aRet; 1950 LanguageType eSaveLang = xLocaleData.getCurrentLanguage(); 1951 if ( pFormat->GetLanguage() == eSaveLang ) 1952 aRet = xLocaleData->getNumDecimalSep(); 1953 else 1954 { 1955 ::com::sun::star::lang::Locale aSaveLocale( xLocaleData->getLocale() ); 1956 ::com::sun::star::lang::Locale aTmpLocale(MsLangId::convertLanguageToLocale(pFormat->GetLanguage())); 1957 ((SvNumberFormatter*)this)->xLocaleData.changeLocale(aTmpLocale, pFormat->GetLanguage() ); 1958 aRet = xLocaleData->getNumDecimalSep(); 1959 ((SvNumberFormatter*)this)->xLocaleData.changeLocale( aSaveLocale, eSaveLang ); 1960 } 1961 return aRet; 1962 } 1963 1964 1965 sal_uInt32 SvNumberFormatter::GetFormatSpecialInfo( const String& rFormatString, 1966 sal_Bool& bThousand, sal_Bool& IsRed, sal_uInt16& nPrecision, 1967 sal_uInt16& nAnzLeading, LanguageType eLnge ) 1968 1969 { 1970 xub_StrLen nCheckPos = 0; 1971 if (eLnge == LANGUAGE_DONTKNOW) 1972 eLnge = IniLnge; 1973 ChangeIntl(eLnge); // ggfs. austauschen 1974 eLnge = ActLnge; 1975 String aTmpStr( rFormatString ); 1976 SvNumberformat* pFormat = new SvNumberformat( aTmpStr, 1977 pFormatScanner, pStringScanner, nCheckPos, eLnge ); 1978 if ( nCheckPos == 0 ) 1979 pFormat->GetFormatSpecialInfo( bThousand, IsRed, nPrecision, nAnzLeading ); 1980 else 1981 { 1982 bThousand = sal_False; 1983 IsRed = sal_False; 1984 nPrecision = pFormatScanner->GetStandardPrec(); 1985 nAnzLeading = 0; 1986 } 1987 delete pFormat; 1988 return nCheckPos; 1989 } 1990 1991 1992 inline sal_uInt32 SetIndexTable( NfIndexTableOffset nTabOff, sal_uInt32 nIndOff ) 1993 { 1994 if ( !bIndexTableInitialized ) 1995 { 1996 DBG_ASSERT( theIndexTable[nTabOff] == NUMBERFORMAT_ENTRY_NOT_FOUND, 1997 "SetIndexTable: theIndexTable[nTabOff] already occupied" ); 1998 theIndexTable[nTabOff] = nIndOff; 1999 } 2000 return nIndOff; 2001 } 2002 2003 2004 sal_Int32 SvNumberFormatter::ImpGetFormatCodeIndex( 2005 ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::NumberFormatCode >& rSeq, 2006 const NfIndexTableOffset nTabOff ) 2007 { 2008 const sal_Int32 nLen = rSeq.getLength(); 2009 for ( sal_Int32 j=0; j<nLen; j++ ) 2010 { 2011 if ( rSeq[j].Index == nTabOff ) 2012 return j; 2013 } 2014 if (LocaleDataWrapper::areChecksEnabled() && (nTabOff < NF_CURRENCY_START 2015 || NF_CURRENCY_END < nTabOff || nTabOff == NF_CURRENCY_1000INT 2016 || nTabOff == NF_CURRENCY_1000INT_RED 2017 || nTabOff == NF_CURRENCY_1000DEC2_CCC)) 2018 { // currency entries with decimals might not exist, e.g. Italian Lira 2019 String aMsg( RTL_CONSTASCII_USTRINGPARAM( 2020 "SvNumberFormatter::ImpGetFormatCodeIndex: not found: ")); 2021 aMsg += String::CreateFromInt32( nTabOff ); 2022 LocaleDataWrapper::outputCheckMessage( xLocaleData->appendLocaleInfo( 2023 aMsg)); 2024 } 2025 if ( nLen ) 2026 { 2027 sal_Int32 j; 2028 // look for a preset default 2029 for ( j=0; j<nLen; j++ ) 2030 { 2031 if ( rSeq[j].Default ) 2032 return j; 2033 } 2034 // currencies are special, not all format codes must exist, but all 2035 // builtin number format key index positions must have a format assigned 2036 if ( NF_CURRENCY_START <= nTabOff && nTabOff <= NF_CURRENCY_END ) 2037 { 2038 // look for a format with decimals 2039 for ( j=0; j<nLen; j++ ) 2040 { 2041 if ( rSeq[j].Index == NF_CURRENCY_1000DEC2 ) 2042 return j; 2043 } 2044 // last resort: look for a format without decimals 2045 for ( j=0; j<nLen; j++ ) 2046 { 2047 if ( rSeq[j].Index == NF_CURRENCY_1000INT ) 2048 return j; 2049 } 2050 } 2051 } 2052 else 2053 { // we need at least _some_ format 2054 rSeq.realloc(1); 2055 rSeq[0] = ::com::sun::star::i18n::NumberFormatCode(); 2056 String aTmp( '0' ); 2057 aTmp += GetNumDecimalSep(); 2058 aTmp.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "############" ) ); 2059 rSeq[0].Code = aTmp; 2060 } 2061 return 0; 2062 } 2063 2064 2065 sal_Int32 SvNumberFormatter::ImpAdjustFormatCodeDefault( 2066 ::com::sun::star::i18n::NumberFormatCode * pFormatArr, 2067 sal_Int32 nCnt, sal_Bool bCheckCorrectness ) 2068 { 2069 using namespace ::com::sun::star; 2070 2071 if ( !nCnt ) 2072 return -1; 2073 if (bCheckCorrectness && LocaleDataWrapper::areChecksEnabled()) 2074 { // check the locale data for correctness 2075 ByteString aMsg; 2076 sal_Int32 nElem, nShort, nMedium, nLong, nShortDef, nMediumDef, nLongDef; 2077 nShort = nMedium = nLong = nShortDef = nMediumDef = nLongDef = -1; 2078 for ( nElem = 0; nElem < nCnt; nElem++ ) 2079 { 2080 switch ( pFormatArr[nElem].Type ) 2081 { 2082 case i18n::KNumberFormatType::SHORT : 2083 nShort = nElem; 2084 break; 2085 case i18n::KNumberFormatType::MEDIUM : 2086 nMedium = nElem; 2087 break; 2088 case i18n::KNumberFormatType::LONG : 2089 nLong = nElem; 2090 break; 2091 default: 2092 aMsg = "unknown type"; 2093 } 2094 if ( pFormatArr[nElem].Default ) 2095 { 2096 switch ( pFormatArr[nElem].Type ) 2097 { 2098 case i18n::KNumberFormatType::SHORT : 2099 if ( nShortDef != -1 ) 2100 aMsg = "dupe short type default"; 2101 nShortDef = nElem; 2102 break; 2103 case i18n::KNumberFormatType::MEDIUM : 2104 if ( nMediumDef != -1 ) 2105 aMsg = "dupe medium type default"; 2106 nMediumDef = nElem; 2107 break; 2108 case i18n::KNumberFormatType::LONG : 2109 if ( nLongDef != -1 ) 2110 aMsg = "dupe long type default"; 2111 nLongDef = nElem; 2112 break; 2113 } 2114 } 2115 if ( aMsg.Len() ) 2116 { 2117 aMsg.Insert( "SvNumberFormatter::ImpAdjustFormatCodeDefault: ", 0 ); 2118 aMsg += "\nXML locale data FormatElement formatindex: "; 2119 aMsg += ByteString::CreateFromInt32( pFormatArr[nElem].Index ); 2120 String aUMsg( aMsg, RTL_TEXTENCODING_ASCII_US); 2121 LocaleDataWrapper::outputCheckMessage( 2122 xLocaleData->appendLocaleInfo( aUMsg)); 2123 aMsg.Erase(); 2124 } 2125 } 2126 if ( nShort != -1 && nShortDef == -1 ) 2127 aMsg += "no short type default "; 2128 if ( nMedium != -1 && nMediumDef == -1 ) 2129 aMsg += "no medium type default "; 2130 if ( nLong != -1 && nLongDef == -1 ) 2131 aMsg += "no long type default "; 2132 if ( aMsg.Len() ) 2133 { 2134 aMsg.Insert( "SvNumberFormatter::ImpAdjustFormatCodeDefault: ", 0 ); 2135 aMsg += "\nXML locale data FormatElement group of: "; 2136 String aUMsg( aMsg, RTL_TEXTENCODING_ASCII_US); 2137 aUMsg += String( pFormatArr[0].NameID ); 2138 LocaleDataWrapper::outputCheckMessage( 2139 xLocaleData->appendLocaleInfo( aUMsg)); 2140 aMsg.Erase(); 2141 } 2142 } 2143 // find the default (medium preferred, then long) and reset all other defaults 2144 sal_Int32 nElem, nDef, nMedium; 2145 nDef = nMedium = -1; 2146 for ( nElem = 0; nElem < nCnt; nElem++ ) 2147 { 2148 if ( pFormatArr[nElem].Default ) 2149 { 2150 switch ( pFormatArr[nElem].Type ) 2151 { 2152 case i18n::KNumberFormatType::MEDIUM : 2153 nDef = nMedium = nElem; 2154 break; 2155 case i18n::KNumberFormatType::LONG : 2156 if ( nMedium == -1 ) 2157 nDef = nElem; 2158 // fallthru 2159 default: 2160 if ( nDef == -1 ) 2161 nDef = nElem; 2162 pFormatArr[nElem].Default = sal_False; 2163 } 2164 } 2165 } 2166 if ( nDef == -1 ) 2167 nDef = 0; 2168 pFormatArr[nDef].Default = sal_True; 2169 return nDef; 2170 } 2171 2172 2173 void SvNumberFormatter::ImpGenerateFormats( sal_uInt32 CLOffset, sal_Bool bLoadingSO5 ) 2174 { 2175 using namespace ::com::sun::star; 2176 2177 if ( !bIndexTableInitialized ) 2178 { 2179 for ( sal_uInt16 j=0; j<NF_INDEX_TABLE_ENTRIES; j++ ) 2180 { 2181 theIndexTable[j] = NUMBERFORMAT_ENTRY_NOT_FOUND; 2182 } 2183 } 2184 sal_Bool bOldConvertMode = pFormatScanner->GetConvertMode(); 2185 if (bOldConvertMode) 2186 pFormatScanner->SetConvertMode(sal_False); // switch off for this function 2187 2188 NumberFormatCodeWrapper aNumberFormatCode( xServiceManager, GetLocale() ); 2189 2190 xub_StrLen nCheckPos = 0; 2191 SvNumberformat* pNewFormat = NULL; 2192 String aFormatCode; 2193 sal_Int32 nIdx; 2194 sal_Bool bDefault; 2195 2196 // Counter for additional builtin formats not fitting into the first 10 2197 // of a category (TLOT:=The Legacy Of Templin), altogether about 20 formats. 2198 // Has to be incremented on each ImpInsertNewStandardformat, new formats 2199 // must be appended, not inserted! 2200 sal_uInt16 nNewExtended = ZF_STANDARD_NEWEXTENDED; 2201 2202 // Number 2203 uno::Sequence< i18n::NumberFormatCode > aFormatSeq 2204 = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::FIXED_NUMBER ); 2205 ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() ); 2206 2207 // General 2208 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_STANDARD ); 2209 SvNumberformat* pStdFormat = ImpInsertFormat( aFormatSeq[nIdx], 2210 CLOffset + SetIndexTable( NF_NUMBER_STANDARD, ZF_STANDARD )); 2211 if (pStdFormat) 2212 { 2213 // This is _the_ standard format. 2214 if (LocaleDataWrapper::areChecksEnabled() && 2215 pStdFormat->GetType() != NUMBERFORMAT_NUMBER) 2216 { 2217 String aMsg( RTL_CONSTASCII_USTRINGPARAM( 2218 "SvNumberFormatter::ImpGenerateFormats: General format not NUMBER")); 2219 LocaleDataWrapper::outputCheckMessage( 2220 xLocaleData->appendLocaleInfo( aMsg)); 2221 } 2222 pStdFormat->SetType( NUMBERFORMAT_NUMBER ); 2223 pStdFormat->SetStandard(); 2224 pStdFormat->SetLastInsertKey( SV_MAX_ANZ_STANDARD_FORMATE ); 2225 } 2226 else 2227 { 2228 if (LocaleDataWrapper::areChecksEnabled()) 2229 { 2230 String aMsg( RTL_CONSTASCII_USTRINGPARAM( 2231 "SvNumberFormatter::ImpGenerateFormats: General format not insertable, nothing will work")); 2232 LocaleDataWrapper::outputCheckMessage( 2233 xLocaleData->appendLocaleInfo( aMsg)); 2234 } 2235 } 2236 2237 // Boolean 2238 aFormatCode = pFormatScanner->GetBooleanString(); 2239 pNewFormat = new SvNumberformat( aFormatCode, 2240 pFormatScanner, pStringScanner, nCheckPos, ActLnge ); 2241 pNewFormat->SetType(NUMBERFORMAT_LOGICAL); 2242 pNewFormat->SetStandard(); 2243 if ( !aFTable.Insert( 2244 CLOffset + SetIndexTable( NF_BOOLEAN, ZF_STANDARD_LOGICAL ), 2245 pNewFormat)) 2246 delete pNewFormat; 2247 2248 // Text 2249 aFormatCode = '@'; 2250 pNewFormat = new SvNumberformat( aFormatCode, 2251 pFormatScanner, pStringScanner, nCheckPos, ActLnge ); 2252 pNewFormat->SetType(NUMBERFORMAT_TEXT); 2253 pNewFormat->SetStandard(); 2254 if ( !aFTable.Insert( 2255 CLOffset + SetIndexTable( NF_TEXT, ZF_STANDARD_TEXT ), 2256 pNewFormat)) 2257 delete pNewFormat; 2258 2259 2260 2261 // 0 2262 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_INT ); 2263 ImpInsertFormat( aFormatSeq[nIdx], 2264 CLOffset + SetIndexTable( NF_NUMBER_INT, ZF_STANDARD+1 )); 2265 2266 // 0.00 2267 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_DEC2 ); 2268 ImpInsertFormat( aFormatSeq[nIdx], 2269 CLOffset + SetIndexTable( NF_NUMBER_DEC2, ZF_STANDARD+2 )); 2270 2271 // #,##0 2272 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_1000INT ); 2273 ImpInsertFormat( aFormatSeq[nIdx], 2274 CLOffset + SetIndexTable( NF_NUMBER_1000INT, ZF_STANDARD+3 )); 2275 2276 // #,##0.00 2277 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_1000DEC2 ); 2278 ImpInsertFormat( aFormatSeq[nIdx], 2279 CLOffset + SetIndexTable( NF_NUMBER_1000DEC2, ZF_STANDARD+4 )); 2280 2281 // #.##0,00 System country/language dependent since number formatter version 6 2282 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_SYSTEM ); 2283 ImpInsertNewStandardFormat( aFormatSeq[nIdx], 2284 CLOffset + SetIndexTable( NF_NUMBER_SYSTEM, ZF_STANDARD+5 ), 2285 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); 2286 2287 2288 // Percent number 2289 aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::PERCENT_NUMBER ); 2290 ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() ); 2291 2292 // 0% 2293 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_PERCENT_INT ); 2294 ImpInsertFormat( aFormatSeq[nIdx], 2295 CLOffset + SetIndexTable( NF_PERCENT_INT, ZF_STANDARD_PERCENT )); 2296 2297 // 0.00% 2298 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_PERCENT_DEC2 ); 2299 ImpInsertFormat( aFormatSeq[nIdx], 2300 CLOffset + SetIndexTable( NF_PERCENT_DEC2, ZF_STANDARD_PERCENT+1 )); 2301 2302 2303 2304 // Currency. NO default standard option! Default is determined of locale 2305 // data default currency and format is generated if needed. 2306 aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::CURRENCY ); 2307 if (LocaleDataWrapper::areChecksEnabled()) 2308 { 2309 // though no default desired here, test for correctness of locale data 2310 ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() ); 2311 } 2312 2313 // #,##0 2314 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000INT ); 2315 bDefault = aFormatSeq[nIdx].Default; 2316 aFormatSeq[nIdx].Default = sal_False; 2317 ImpInsertFormat( aFormatSeq[nIdx], 2318 CLOffset + SetIndexTable( NF_CURRENCY_1000INT, ZF_STANDARD_CURRENCY )); 2319 aFormatSeq[nIdx].Default = bDefault; 2320 2321 // #,##0.00 2322 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000DEC2 ); 2323 bDefault = aFormatSeq[nIdx].Default; 2324 aFormatSeq[nIdx].Default = sal_False; 2325 ImpInsertFormat( aFormatSeq[nIdx], 2326 CLOffset + SetIndexTable( NF_CURRENCY_1000DEC2, ZF_STANDARD_CURRENCY+1 )); 2327 aFormatSeq[nIdx].Default = bDefault; 2328 2329 // #,##0 negative red 2330 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000INT_RED ); 2331 bDefault = aFormatSeq[nIdx].Default; 2332 aFormatSeq[nIdx].Default = sal_False; 2333 ImpInsertFormat( aFormatSeq[nIdx], 2334 CLOffset + SetIndexTable( NF_CURRENCY_1000INT_RED, ZF_STANDARD_CURRENCY+2 )); 2335 aFormatSeq[nIdx].Default = bDefault; 2336 2337 // #,##0.00 negative red 2338 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000DEC2_RED ); 2339 bDefault = aFormatSeq[nIdx].Default; 2340 aFormatSeq[nIdx].Default = sal_False; 2341 ImpInsertFormat( aFormatSeq[nIdx], 2342 CLOffset + SetIndexTable( NF_CURRENCY_1000DEC2_RED, ZF_STANDARD_CURRENCY+3 )); 2343 aFormatSeq[nIdx].Default = bDefault; 2344 2345 // #,##0.00 USD since number formatter version 3 2346 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000DEC2_CCC ); 2347 bDefault = aFormatSeq[nIdx].Default; 2348 aFormatSeq[nIdx].Default = sal_False; 2349 pNewFormat = ImpInsertFormat( aFormatSeq[nIdx], 2350 CLOffset + SetIndexTable( NF_CURRENCY_1000DEC2_CCC, ZF_STANDARD_CURRENCY+4 )); 2351 if ( pNewFormat ) 2352 pNewFormat->SetUsed(sal_True); // must be saved for older versions 2353 aFormatSeq[nIdx].Default = bDefault; 2354 2355 // #.##0,-- since number formatter version 6 2356 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000DEC2_DASHED ); 2357 bDefault = aFormatSeq[nIdx].Default; 2358 aFormatSeq[nIdx].Default = sal_False; 2359 ImpInsertNewStandardFormat( aFormatSeq[nIdx], 2360 CLOffset + SetIndexTable( NF_CURRENCY_1000DEC2_DASHED, ZF_STANDARD_CURRENCY+5 ), 2361 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); 2362 aFormatSeq[nIdx].Default = bDefault; 2363 2364 2365 2366 // Date 2367 aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::DATE ); 2368 ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() ); 2369 2370 // DD.MM.YY System 2371 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYSTEM_SHORT ); 2372 ImpInsertFormat( aFormatSeq[nIdx], 2373 CLOffset + SetIndexTable( NF_DATE_SYSTEM_SHORT, ZF_STANDARD_DATE )); 2374 2375 // NN DD.MMM YY 2376 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DEF_NNDDMMMYY ); 2377 ImpInsertFormat( aFormatSeq[nIdx], 2378 CLOffset + SetIndexTable( NF_DATE_DEF_NNDDMMMYY, ZF_STANDARD_DATE+1 )); 2379 2380 // DD.MM.YY def/System 2381 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_MMYY ); 2382 ImpInsertFormat( aFormatSeq[nIdx], 2383 CLOffset + SetIndexTable( NF_DATE_SYS_MMYY, ZF_STANDARD_DATE+2 )); 2384 2385 // DD MMM 2386 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DDMMM ); 2387 ImpInsertFormat( aFormatSeq[nIdx], 2388 CLOffset + SetIndexTable( NF_DATE_SYS_DDMMM, ZF_STANDARD_DATE+3 )); 2389 2390 // MMMM 2391 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_MMMM ); 2392 ImpInsertFormat( aFormatSeq[nIdx], 2393 CLOffset + SetIndexTable( NF_DATE_MMMM, ZF_STANDARD_DATE+4 )); 2394 2395 // QQ YY 2396 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_QQJJ ); 2397 ImpInsertFormat( aFormatSeq[nIdx], 2398 CLOffset + SetIndexTable( NF_DATE_QQJJ, ZF_STANDARD_DATE+5 )); 2399 2400 // DD.MM.YYYY since number formatter version 2, was DD.MM.[YY]YY 2401 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DDMMYYYY ); 2402 pNewFormat = ImpInsertFormat( aFormatSeq[nIdx], 2403 CLOffset + SetIndexTable( NF_DATE_SYS_DDMMYYYY, ZF_STANDARD_DATE+6 )); 2404 if ( pNewFormat ) 2405 pNewFormat->SetUsed(sal_True); // must be saved for older versions 2406 2407 // DD.MM.YY def/System, since number formatter version 6 2408 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DDMMYY ); 2409 ImpInsertNewStandardFormat( aFormatSeq[nIdx], 2410 CLOffset + SetIndexTable( NF_DATE_SYS_DDMMYY, ZF_STANDARD_DATE+7 ), 2411 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); 2412 2413 // NNN, D. MMMM YYYY System 2414 // Long day of week: "NNNN" instead of "NNN," because of compatibility 2415 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYSTEM_LONG ); 2416 ImpInsertNewStandardFormat( aFormatSeq[nIdx], 2417 CLOffset + SetIndexTable( NF_DATE_SYSTEM_LONG, ZF_STANDARD_DATE+8 ), 2418 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); 2419 2420 // Hard coded but system (regional settings) delimiters dependent long date formats 2421 // since numberformatter version 6 2422 2423 // D. MMM YY def/System 2424 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DMMMYY ); 2425 ImpInsertNewStandardFormat( aFormatSeq[nIdx], 2426 CLOffset + SetIndexTable( NF_DATE_SYS_DMMMYY, ZF_STANDARD_DATE+9 ), 2427 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); 2428 2429 //! Unfortunally TLOT intended only 10 builtin formats per category, more 2430 //! would overwrite the next category (ZF_STANDARD_TIME) :-(( 2431 //! Therefore they are inserted with nNewExtended++ (which is also limited) 2432 2433 // D. MMM YYYY def/System 2434 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DMMMYYYY ); 2435 ImpInsertNewStandardFormat( aFormatSeq[nIdx], 2436 CLOffset + SetIndexTable( NF_DATE_SYS_DMMMYYYY, nNewExtended++ ), 2437 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); 2438 2439 // D. MMMM YYYY def/System 2440 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DMMMMYYYY ); 2441 ImpInsertNewStandardFormat( aFormatSeq[nIdx], 2442 CLOffset + SetIndexTable( NF_DATE_SYS_DMMMMYYYY, nNewExtended++ ), 2443 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); 2444 2445 // NN, D. MMM YY def/System 2446 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_NNDMMMYY ); 2447 ImpInsertNewStandardFormat( aFormatSeq[nIdx], 2448 CLOffset + SetIndexTable( NF_DATE_SYS_NNDMMMYY, nNewExtended++ ), 2449 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); 2450 2451 // NN, D. MMMM YYYY def/System 2452 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_NNDMMMMYYYY ); 2453 ImpInsertNewStandardFormat( aFormatSeq[nIdx], 2454 CLOffset + SetIndexTable( NF_DATE_SYS_NNDMMMMYYYY, nNewExtended++ ), 2455 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); 2456 2457 // NNN, D. MMMM YYYY def/System 2458 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_NNNNDMMMMYYYY ); 2459 ImpInsertNewStandardFormat( aFormatSeq[nIdx], 2460 CLOffset + SetIndexTable( NF_DATE_SYS_NNNNDMMMMYYYY, nNewExtended++ ), 2461 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); 2462 2463 // Hard coded DIN (Deutsche Industrie Norm) and EN (European Norm) date formats 2464 2465 // D. MMM. YYYY DIN/EN 2466 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_DMMMYYYY ); 2467 ImpInsertNewStandardFormat( aFormatSeq[nIdx], 2468 CLOffset + SetIndexTable( NF_DATE_DIN_DMMMYYYY, nNewExtended++ ), 2469 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); 2470 2471 // D. MMMM YYYY DIN/EN 2472 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_DMMMMYYYY ); 2473 ImpInsertNewStandardFormat( aFormatSeq[nIdx], 2474 CLOffset + SetIndexTable( NF_DATE_DIN_DMMMMYYYY, nNewExtended++ ), 2475 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); 2476 2477 // MM-DD DIN/EN 2478 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_MMDD ); 2479 ImpInsertNewStandardFormat( aFormatSeq[nIdx], 2480 CLOffset + SetIndexTable( NF_DATE_DIN_MMDD, nNewExtended++ ), 2481 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); 2482 2483 // YY-MM-DD DIN/EN 2484 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_YYMMDD ); 2485 ImpInsertNewStandardFormat( aFormatSeq[nIdx], 2486 CLOffset + SetIndexTable( NF_DATE_DIN_YYMMDD, nNewExtended++ ), 2487 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); 2488 2489 // YYYY-MM-DD DIN/EN 2490 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_YYYYMMDD ); 2491 ImpInsertNewStandardFormat( aFormatSeq[nIdx], 2492 CLOffset + SetIndexTable( NF_DATE_DIN_YYYYMMDD, nNewExtended++ ), 2493 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); 2494 2495 2496 2497 // Time 2498 aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::TIME ); 2499 ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() ); 2500 2501 // HH:MM 2502 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HHMM ); 2503 ImpInsertFormat( aFormatSeq[nIdx], 2504 CLOffset + SetIndexTable( NF_TIME_HHMM, ZF_STANDARD_TIME )); 2505 2506 // HH:MM:SS 2507 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HHMMSS ); 2508 ImpInsertFormat( aFormatSeq[nIdx], 2509 CLOffset + SetIndexTable( NF_TIME_HHMMSS, ZF_STANDARD_TIME+1 )); 2510 2511 // HH:MM AM/PM 2512 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HHMMAMPM ); 2513 ImpInsertFormat( aFormatSeq[nIdx], 2514 CLOffset + SetIndexTable( NF_TIME_HHMMAMPM, ZF_STANDARD_TIME+2 )); 2515 2516 // HH:MM:SS AM/PM 2517 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HHMMSSAMPM ); 2518 ImpInsertFormat( aFormatSeq[nIdx], 2519 CLOffset + SetIndexTable( NF_TIME_HHMMSSAMPM, ZF_STANDARD_TIME+3 )); 2520 2521 // [HH]:MM:SS 2522 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HH_MMSS ); 2523 ImpInsertFormat( aFormatSeq[nIdx], 2524 CLOffset + SetIndexTable( NF_TIME_HH_MMSS, ZF_STANDARD_TIME+4 )); 2525 2526 // MM:SS,00 2527 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_MMSS00 ); 2528 ImpInsertFormat( aFormatSeq[nIdx], 2529 CLOffset + SetIndexTable( NF_TIME_MMSS00, ZF_STANDARD_TIME+5 )); 2530 2531 // [HH]:MM:SS,00 2532 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HH_MMSS00 ); 2533 ImpInsertNewStandardFormat( aFormatSeq[nIdx], 2534 CLOffset + SetIndexTable( NF_TIME_HH_MMSS00, ZF_STANDARD_TIME+6 ), 2535 SV_NUMBERFORMATTER_VERSION_NF_TIME_HH_MMSS00 ); 2536 2537 2538 2539 // DateTime 2540 aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::DATE_TIME ); 2541 ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() ); 2542 2543 // DD.MM.YY HH:MM System 2544 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATETIME_SYSTEM_SHORT_HHMM ); 2545 ImpInsertFormat( aFormatSeq[nIdx], 2546 CLOffset + SetIndexTable( NF_DATETIME_SYSTEM_SHORT_HHMM, ZF_STANDARD_DATETIME )); 2547 2548 // DD.MM.YYYY HH:MM:SS System 2549 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATETIME_SYS_DDMMYYYY_HHMMSS ); 2550 ImpInsertNewStandardFormat( aFormatSeq[nIdx], 2551 CLOffset + SetIndexTable( NF_DATETIME_SYS_DDMMYYYY_HHMMSS, ZF_STANDARD_DATETIME+1 ), 2552 SV_NUMBERFORMATTER_VERSION_NF_DATETIME_SYS_DDMMYYYY_HHMMSS ); 2553 2554 2555 2556 // Scientific number 2557 aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::SCIENTIFIC_NUMBER ); 2558 ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() ); 2559 2560 // 0.00E+000 2561 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_SCIENTIFIC_000E000 ); 2562 ImpInsertFormat( aFormatSeq[nIdx], 2563 CLOffset + SetIndexTable( NF_SCIENTIFIC_000E000, ZF_STANDARD_SCIENTIFIC )); 2564 2565 // 0.00E+00 2566 nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_SCIENTIFIC_000E00 ); 2567 ImpInsertFormat( aFormatSeq[nIdx], 2568 CLOffset + SetIndexTable( NF_SCIENTIFIC_000E00, ZF_STANDARD_SCIENTIFIC+1 )); 2569 2570 2571 2572 // Fraction number (no default option) 2573 i18n::NumberFormatCode aSingleFormatCode; 2574 2575 // # ?/? 2576 aSingleFormatCode.Code = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "# ?/?" ) ); 2577 String s25( RTL_CONSTASCII_USTRINGPARAM( "# ?/?" ) ); // # ?/? 2578 ImpInsertFormat( aSingleFormatCode, 2579 CLOffset + SetIndexTable( NF_FRACTION_1, ZF_STANDARD_FRACTION )); 2580 2581 // # ??/?? 2582 //! "??/" would be interpreted by the compiler as a trigraph for '\' 2583 aSingleFormatCode.Code = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "# ?\?/?\?" ) ); 2584 ImpInsertFormat( aSingleFormatCode, 2585 CLOffset + SetIndexTable( NF_FRACTION_2, ZF_STANDARD_FRACTION+1 )); 2586 2587 // Week of year must be appended here because of nNewExtended 2588 const NfKeywordTable & rKeyword = pFormatScanner->GetKeywords(); 2589 aSingleFormatCode.Code = rKeyword[NF_KEY_WW]; 2590 ImpInsertNewStandardFormat( aSingleFormatCode, 2591 CLOffset + SetIndexTable( NF_DATE_WW, nNewExtended++ ), 2592 SV_NUMBERFORMATTER_VERSION_NF_DATE_WW ); 2593 2594 2595 2596 bIndexTableInitialized = sal_True; 2597 DBG_ASSERT( nNewExtended <= ZF_STANDARD_NEWEXTENDEDMAX, 2598 "ImpGenerateFormats: overflow of nNewExtended standard formats" ); 2599 2600 // Now all additional format codes provided by I18N, but only if not 2601 // loading from old SO5 file format, then they are appended last. 2602 if ( !bLoadingSO5 ) 2603 ImpGenerateAdditionalFormats( CLOffset, aNumberFormatCode, sal_False ); 2604 2605 if (bOldConvertMode) 2606 pFormatScanner->SetConvertMode(sal_True); 2607 } 2608 2609 2610 void SvNumberFormatter::ImpGenerateAdditionalFormats( sal_uInt32 CLOffset, 2611 NumberFormatCodeWrapper& rNumberFormatCode, sal_Bool bAfterLoadingSO5 ) 2612 { 2613 using namespace ::com::sun::star; 2614 2615 SvNumberformat* pStdFormat = 2616 (SvNumberformat*) aFTable.Get( CLOffset + ZF_STANDARD ); 2617 if ( !pStdFormat ) 2618 { 2619 DBG_ERRORFILE( "ImpGenerateAdditionalFormats: no GENERAL format" ); 2620 return ; 2621 } 2622 sal_uInt32 nPos = CLOffset + pStdFormat->GetLastInsertKey(); 2623 rNumberFormatCode.setLocale( GetLocale() ); 2624 sal_Int32 j; 2625 2626 // All currencies, this time with [$...] which was stripped in 2627 // ImpGenerateFormats for old "automatic" currency formats. 2628 uno::Sequence< i18n::NumberFormatCode > aFormatSeq = 2629 rNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::CURRENCY ); 2630 i18n::NumberFormatCode * pFormatArr = aFormatSeq.getArray(); 2631 sal_Int32 nCodes = aFormatSeq.getLength(); 2632 ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), nCodes ); 2633 for ( j = 0; j < nCodes; j++ ) 2634 { 2635 if ( nPos - CLOffset >= SV_COUNTRY_LANGUAGE_OFFSET ) 2636 { 2637 DBG_ERRORFILE( "ImpGenerateAdditionalFormats: too many formats" ); 2638 break; // for 2639 } 2640 if ( pFormatArr[j].Index < NF_INDEX_TABLE_ENTRIES && 2641 pFormatArr[j].Index != NF_CURRENCY_1000DEC2_CCC ) 2642 { // Insert only if not already inserted, but internal index must be 2643 // above so ImpInsertFormat can distinguish it. 2644 sal_Int16 nOrgIndex = pFormatArr[j].Index; 2645 pFormatArr[j].Index = sal::static_int_cast< sal_Int16 >( 2646 pFormatArr[j].Index + nCodes + NF_INDEX_TABLE_ENTRIES); 2647 //! no default on currency 2648 sal_Bool bDefault = aFormatSeq[j].Default; 2649 aFormatSeq[j].Default = sal_False; 2650 if ( ImpInsertNewStandardFormat( pFormatArr[j], nPos+1, 2651 SV_NUMBERFORMATTER_VERSION_ADDITIONAL_I18N_FORMATS, 2652 bAfterLoadingSO5, nOrgIndex ) ) 2653 nPos++; 2654 pFormatArr[j].Index = nOrgIndex; 2655 aFormatSeq[j].Default = bDefault; 2656 } 2657 } 2658 2659 // all additional format codes provided by I18N that are not old standard index 2660 aFormatSeq = rNumberFormatCode.getAllFormatCodes(); 2661 nCodes = aFormatSeq.getLength(); 2662 if ( nCodes ) 2663 { 2664 pFormatArr = aFormatSeq.getArray(); 2665 // don't check ALL 2666 sal_Int32 nDef = ImpAdjustFormatCodeDefault( pFormatArr, nCodes, sal_False); 2667 // don't have any defaults here 2668 pFormatArr[nDef].Default = sal_False; 2669 for ( j = 0; j < nCodes; j++ ) 2670 { 2671 if ( nPos - CLOffset >= SV_COUNTRY_LANGUAGE_OFFSET ) 2672 { 2673 DBG_ERRORFILE( "ImpGenerateAdditionalFormats: too many formats" ); 2674 break; // for 2675 } 2676 if ( pFormatArr[j].Index >= NF_INDEX_TABLE_ENTRIES ) 2677 if ( ImpInsertNewStandardFormat( pFormatArr[j], nPos+1, 2678 SV_NUMBERFORMATTER_VERSION_ADDITIONAL_I18N_FORMATS, 2679 bAfterLoadingSO5 ) ) 2680 nPos++; 2681 } 2682 } 2683 2684 pStdFormat->SetLastInsertKey( (sal_uInt16)(nPos - CLOffset) ); 2685 } 2686 2687 2688 void SvNumberFormatter::ImpGetPosCurrFormat( String& sPosStr, const String& rCurrSymbol ) 2689 { 2690 NfCurrencyEntry::CompletePositiveFormatString( sPosStr, 2691 rCurrSymbol, xLocaleData->getCurrPositiveFormat() ); 2692 } 2693 2694 void SvNumberFormatter::ImpGetNegCurrFormat( String& sNegStr, const String& rCurrSymbol ) 2695 { 2696 NfCurrencyEntry::CompleteNegativeFormatString( sNegStr, 2697 rCurrSymbol, xLocaleData->getCurrNegativeFormat() ); 2698 } 2699 2700 void SvNumberFormatter::GenerateFormat(String& sString, 2701 sal_uInt32 nIndex, 2702 LanguageType eLnge, 2703 sal_Bool bThousand, 2704 sal_Bool IsRed, 2705 sal_uInt16 nPrecision, 2706 sal_uInt16 nAnzLeading) 2707 { 2708 if (eLnge == LANGUAGE_DONTKNOW) 2709 eLnge = IniLnge; 2710 short eType = GetType(nIndex); 2711 sal_uInt16 i; 2712 ImpGenerateCL(eLnge); // ggfs. neu Standard- 2713 // formate anlegen 2714 sString.Erase(); 2715 2716 utl::DigitGroupingIterator aGrouping( xLocaleData->getDigitGrouping()); 2717 const xub_StrLen nDigitsInFirstGroup = static_cast<xub_StrLen>(aGrouping.get()); 2718 const String& rThSep = GetNumThousandSep(); 2719 if (nAnzLeading == 0) 2720 { 2721 if (!bThousand) 2722 sString += '#'; 2723 else 2724 { 2725 sString += '#'; 2726 sString += rThSep; 2727 sString.Expand( sString.Len() + nDigitsInFirstGroup, '#' ); 2728 } 2729 } 2730 else 2731 { 2732 for (i = 0; i < nAnzLeading; i++) 2733 { 2734 if (bThousand && i > 0 && i == aGrouping.getPos()) 2735 { 2736 sString.Insert( rThSep, 0 ); 2737 aGrouping.advance(); 2738 } 2739 sString.Insert('0',0); 2740 } 2741 if (bThousand && nAnzLeading < nDigitsInFirstGroup + 1) 2742 { 2743 for (i = nAnzLeading; i < nDigitsInFirstGroup + 1; i++) 2744 { 2745 if (bThousand && i % nDigitsInFirstGroup == 0) 2746 sString.Insert( rThSep, 0 ); 2747 sString.Insert('#',0); 2748 } 2749 } 2750 } 2751 if (nPrecision > 0) 2752 { 2753 sString += GetNumDecimalSep(); 2754 sString.Expand( sString.Len() + nPrecision, '0' ); 2755 } 2756 if (eType == NUMBERFORMAT_PERCENT) 2757 sString += '%'; 2758 else if (eType == NUMBERFORMAT_CURRENCY) 2759 { 2760 String sNegStr = sString; 2761 String aCurr; 2762 const NfCurrencyEntry* pEntry; 2763 sal_Bool bBank; 2764 if ( GetNewCurrencySymbolString( nIndex, aCurr, &pEntry, &bBank ) ) 2765 { 2766 if ( pEntry ) 2767 { 2768 sal_uInt16 nPosiForm = NfCurrencyEntry::GetEffectivePositiveFormat( 2769 xLocaleData->getCurrPositiveFormat(), 2770 pEntry->GetPositiveFormat(), bBank ); 2771 sal_uInt16 nNegaForm = NfCurrencyEntry::GetEffectiveNegativeFormat( 2772 xLocaleData->getCurrNegativeFormat(), 2773 pEntry->GetNegativeFormat(), bBank ); 2774 pEntry->CompletePositiveFormatString( sString, bBank, 2775 nPosiForm ); 2776 pEntry->CompleteNegativeFormatString( sNegStr, bBank, 2777 nNegaForm ); 2778 } 2779 else 2780 { // assume currency abbreviation (AKA banking symbol), not symbol 2781 sal_uInt16 nPosiForm = NfCurrencyEntry::GetEffectivePositiveFormat( 2782 xLocaleData->getCurrPositiveFormat(), 2783 xLocaleData->getCurrPositiveFormat(), sal_True ); 2784 sal_uInt16 nNegaForm = NfCurrencyEntry::GetEffectiveNegativeFormat( 2785 xLocaleData->getCurrNegativeFormat(), 2786 xLocaleData->getCurrNegativeFormat(), sal_True ); 2787 NfCurrencyEntry::CompletePositiveFormatString( sString, aCurr, 2788 nPosiForm ); 2789 NfCurrencyEntry::CompleteNegativeFormatString( sNegStr, aCurr, 2790 nNegaForm ); 2791 } 2792 } 2793 else 2794 { // "automatic" old style 2795 String aSymbol, aAbbrev; 2796 GetCompatibilityCurrency( aSymbol, aAbbrev ); 2797 ImpGetPosCurrFormat( sString, aSymbol ); 2798 ImpGetNegCurrFormat( sNegStr, aSymbol ); 2799 } 2800 if (IsRed) 2801 { 2802 sString += ';'; 2803 sString += '['; 2804 sString += pFormatScanner->GetRedString(); 2805 sString += ']'; 2806 } 2807 else 2808 sString += ';'; 2809 sString += sNegStr; 2810 } 2811 if (IsRed && eType != NUMBERFORMAT_CURRENCY) 2812 { 2813 String sTmpStr = sString; 2814 sTmpStr += ';'; 2815 sTmpStr += '['; 2816 sTmpStr += pFormatScanner->GetRedString(); 2817 sTmpStr += ']'; 2818 sTmpStr += '-'; 2819 sTmpStr +=sString; 2820 sString = sTmpStr; 2821 } 2822 } 2823 2824 sal_Bool SvNumberFormatter::IsUserDefined(const String& sStr, 2825 LanguageType eLnge) 2826 { 2827 if (eLnge == LANGUAGE_DONTKNOW) 2828 eLnge = IniLnge; 2829 sal_uInt32 CLOffset = ImpGenerateCL(eLnge); // ggfs. neu Standard- 2830 // formate anlegen 2831 eLnge = ActLnge; 2832 sal_uInt32 nKey = ImpIsEntry(sStr, CLOffset, eLnge); 2833 if (nKey == NUMBERFORMAT_ENTRY_NOT_FOUND) 2834 return sal_True; 2835 SvNumberformat* pEntry = aFTable.Get(nKey); 2836 if ( pEntry && ((pEntry->GetType() & NUMBERFORMAT_DEFINED) != 0) ) 2837 return sal_True; 2838 return sal_False; 2839 } 2840 2841 sal_uInt32 SvNumberFormatter::GetEntryKey(const String& sStr, 2842 LanguageType eLnge) 2843 { 2844 if (eLnge == LANGUAGE_DONTKNOW) 2845 eLnge = IniLnge; 2846 sal_uInt32 CLOffset = ImpGenerateCL(eLnge); // ggfs. neu Standard- 2847 // formate anlegen 2848 return ImpIsEntry(sStr, CLOffset, eLnge); 2849 } 2850 2851 sal_uInt32 SvNumberFormatter::GetStandardIndex(LanguageType eLnge) 2852 { 2853 if (eLnge == LANGUAGE_DONTKNOW) 2854 eLnge = IniLnge; 2855 return GetStandardFormat(NUMBERFORMAT_NUMBER, eLnge); 2856 } 2857 2858 short SvNumberFormatter::GetType(sal_uInt32 nFIndex) 2859 { 2860 short eType; 2861 SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(nFIndex); 2862 if (!pFormat) 2863 eType = NUMBERFORMAT_UNDEFINED; 2864 else 2865 { 2866 eType = pFormat->GetType() &~NUMBERFORMAT_DEFINED; 2867 if (eType == 0) 2868 eType = NUMBERFORMAT_DEFINED; 2869 } 2870 return eType; 2871 } 2872 2873 void SvNumberFormatter::ClearMergeTable() 2874 { 2875 if ( pMergeTable ) 2876 { 2877 sal_uInt32* pIndex = (sal_uInt32*) pMergeTable->First(); 2878 while (pIndex) 2879 { 2880 delete pIndex; 2881 pIndex = pMergeTable->Next(); 2882 } 2883 pMergeTable->Clear(); 2884 } 2885 } 2886 2887 SvNumberFormatterIndexTable* SvNumberFormatter::MergeFormatter(SvNumberFormatter& rTable) 2888 { 2889 if ( pMergeTable ) 2890 ClearMergeTable(); 2891 else 2892 pMergeTable = new SvNumberFormatterIndexTable; 2893 sal_uInt32 nCLOffset = 0; 2894 sal_uInt32 nOldKey, nOffset, nNewKey; 2895 sal_uInt32* pNewIndex; 2896 SvNumberformat* pNewEntry; 2897 SvNumberformat* pFormat = rTable.aFTable.First(); 2898 while (pFormat) 2899 { 2900 nOldKey = rTable.aFTable.GetCurKey(); 2901 nOffset = nOldKey % SV_COUNTRY_LANGUAGE_OFFSET; // relativIndex 2902 if (nOffset == 0) // 1. Format von CL 2903 nCLOffset = ImpGenerateCL(pFormat->GetLanguage()); 2904 2905 if (nOffset <= SV_MAX_ANZ_STANDARD_FORMATE) // Std.form. 2906 { 2907 nNewKey = nCLOffset + nOffset; 2908 if (!aFTable.Get(nNewKey)) // noch nicht da 2909 { 2910 // pNewEntry = new SvNumberformat(*pFormat); // Copy reicht nicht !!! 2911 pNewEntry = new SvNumberformat( *pFormat, *pFormatScanner ); 2912 if (!aFTable.Insert(nNewKey, pNewEntry)) 2913 delete pNewEntry; 2914 } 2915 if (nNewKey != nOldKey) // neuer Index 2916 { 2917 pNewIndex = new sal_uInt32(nNewKey); 2918 if (!pMergeTable->Insert(nOldKey,pNewIndex)) 2919 delete pNewIndex; 2920 } 2921 } 2922 else // benutzerdef. 2923 { 2924 // pNewEntry = new SvNumberformat(*pFormat); // Copy reicht nicht !!! 2925 pNewEntry = new SvNumberformat( *pFormat, *pFormatScanner ); 2926 nNewKey = ImpIsEntry(pNewEntry->GetFormatstring(), 2927 nCLOffset, 2928 pFormat->GetLanguage()); 2929 if (nNewKey != NUMBERFORMAT_ENTRY_NOT_FOUND) // schon vorhanden 2930 delete pNewEntry; 2931 else 2932 { 2933 SvNumberformat* pStdFormat = 2934 (SvNumberformat*) aFTable.Get(nCLOffset + ZF_STANDARD); 2935 sal_uInt32 nPos = nCLOffset + pStdFormat->GetLastInsertKey(); 2936 nNewKey = nPos+1; 2937 if (nPos - nCLOffset >= SV_COUNTRY_LANGUAGE_OFFSET) 2938 { 2939 DBG_ERROR( 2940 "SvNumberFormatter:: Zu viele Formate pro CL"); 2941 delete pNewEntry; 2942 } 2943 else if (!aFTable.Insert(nNewKey, pNewEntry)) 2944 delete pNewEntry; 2945 else 2946 pStdFormat->SetLastInsertKey((sal_uInt16) (nNewKey - nCLOffset)); 2947 } 2948 if (nNewKey != nOldKey) // neuer Index 2949 { 2950 pNewIndex = new sal_uInt32(nNewKey); 2951 if (!pMergeTable->Insert(nOldKey,pNewIndex)) 2952 delete pNewIndex; 2953 } 2954 } 2955 pFormat = rTable.aFTable.Next(); 2956 } 2957 return pMergeTable; 2958 } 2959 2960 2961 SvNumberFormatterMergeMap SvNumberFormatter::ConvertMergeTableToMap() 2962 { 2963 if (!HasMergeFmtTbl()) 2964 return SvNumberFormatterMergeMap(); 2965 2966 SvNumberFormatterMergeMap aMap; 2967 for (sal_uInt32* pIndex = pMergeTable->First(); pIndex; pIndex = pMergeTable->Next()) 2968 { 2969 sal_uInt32 nOldKey = pMergeTable->GetCurKey(); 2970 aMap.insert( SvNumberFormatterMergeMap::value_type( nOldKey, *pIndex)); 2971 } 2972 ClearMergeTable(); 2973 return aMap; 2974 } 2975 2976 2977 sal_uInt32 SvNumberFormatter::GetFormatForLanguageIfBuiltIn( sal_uInt32 nFormat, 2978 LanguageType eLnge ) 2979 { 2980 if ( eLnge == LANGUAGE_DONTKNOW ) 2981 eLnge = IniLnge; 2982 if ( nFormat < SV_COUNTRY_LANGUAGE_OFFSET && eLnge == IniLnge ) 2983 return nFormat; // es bleibt wie es ist 2984 sal_uInt32 nOffset = nFormat % SV_COUNTRY_LANGUAGE_OFFSET; // relativIndex 2985 if ( nOffset > SV_MAX_ANZ_STANDARD_FORMATE ) 2986 return nFormat; // kein eingebautes Format 2987 sal_uInt32 nCLOffset = ImpGenerateCL(eLnge); // ggbf. generieren 2988 return nCLOffset + nOffset; 2989 } 2990 2991 2992 sal_uInt32 SvNumberFormatter::GetFormatIndex( NfIndexTableOffset nTabOff, 2993 LanguageType eLnge ) 2994 { 2995 if ( nTabOff >= NF_INDEX_TABLE_ENTRIES 2996 || theIndexTable[nTabOff] == NUMBERFORMAT_ENTRY_NOT_FOUND ) 2997 return NUMBERFORMAT_ENTRY_NOT_FOUND; 2998 if ( eLnge == LANGUAGE_DONTKNOW ) 2999 eLnge = IniLnge; 3000 sal_uInt32 nCLOffset = ImpGenerateCL(eLnge); // ggbf. generieren 3001 return nCLOffset + theIndexTable[nTabOff]; 3002 } 3003 3004 3005 NfIndexTableOffset SvNumberFormatter::GetIndexTableOffset( sal_uInt32 nFormat ) const 3006 { 3007 sal_uInt32 nOffset = nFormat % SV_COUNTRY_LANGUAGE_OFFSET; // relativIndex 3008 if ( nOffset > SV_MAX_ANZ_STANDARD_FORMATE ) 3009 return NF_INDEX_TABLE_ENTRIES; // kein eingebautes Format 3010 for ( sal_uInt16 j = 0; j < NF_INDEX_TABLE_ENTRIES; j++ ) 3011 { 3012 if ( theIndexTable[j] == nOffset ) 3013 return (NfIndexTableOffset) j; 3014 } 3015 return NF_INDEX_TABLE_ENTRIES; // bad luck 3016 } 3017 3018 3019 void SvNumberFormatter::SetYear2000( sal_uInt16 nVal ) 3020 { 3021 pStringScanner->SetYear2000( nVal ); 3022 } 3023 3024 3025 sal_uInt16 SvNumberFormatter::GetYear2000() const 3026 { 3027 return pStringScanner->GetYear2000(); 3028 } 3029 3030 3031 sal_uInt16 SvNumberFormatter::ExpandTwoDigitYear( sal_uInt16 nYear ) const 3032 { 3033 if ( nYear < 100 ) 3034 return SvNumberFormatter::ExpandTwoDigitYear( nYear, 3035 pStringScanner->GetYear2000() ); 3036 return nYear; 3037 } 3038 3039 3040 // static 3041 sal_uInt16 SvNumberFormatter::GetYear2000Default() 3042 { 3043 return (sal_uInt16) ::utl::MiscCfg().GetYear2000(); 3044 } 3045 3046 const String& SvNumberFormatter::GetTrueString(){return pFormatScanner->GetTrueString();} 3047 const String& SvNumberFormatter::GetFalseString(){return pFormatScanner->GetFalseString();} 3048 3049 // static 3050 const NfCurrencyTable& SvNumberFormatter::GetTheCurrencyTable() 3051 { 3052 ::osl::MutexGuard aGuard( GetMutex() ); 3053 while ( !bCurrencyTableInitialized ) 3054 ImpInitCurrencyTable(); 3055 return theCurrencyTable::get(); 3056 } 3057 3058 3059 // static 3060 const NfCurrencyEntry* SvNumberFormatter::MatchSystemCurrency() 3061 { 3062 // MUST call GetTheCurrencyTable() before accessing nSystemCurrencyPosition 3063 const NfCurrencyTable& rTable = GetTheCurrencyTable(); 3064 return nSystemCurrencyPosition ? rTable[nSystemCurrencyPosition] : NULL; 3065 } 3066 3067 3068 // static 3069 const NfCurrencyEntry& SvNumberFormatter::GetCurrencyEntry( LanguageType eLang ) 3070 { 3071 if ( eLang == LANGUAGE_SYSTEM ) 3072 { 3073 const NfCurrencyEntry* pCurr = MatchSystemCurrency(); 3074 return pCurr ? *pCurr : *(GetTheCurrencyTable()[0]); 3075 } 3076 else 3077 { 3078 eLang = MsLangId::getRealLanguage( eLang ); 3079 const NfCurrencyTable& rTable = GetTheCurrencyTable(); 3080 sal_uInt16 nCount = rTable.Count(); 3081 const NfCurrencyEntryPtr* ppData = rTable.GetData(); 3082 for ( sal_uInt16 j = 0; j < nCount; j++, ppData++ ) 3083 { 3084 if ( (*ppData)->GetLanguage() == eLang ) 3085 return **ppData; 3086 } 3087 return *(rTable[0]); 3088 } 3089 } 3090 3091 3092 // static 3093 const NfCurrencyEntry* SvNumberFormatter::GetCurrencyEntry( 3094 const String& rAbbrev, LanguageType eLang ) 3095 { 3096 eLang = MsLangId::getRealLanguage( eLang ); 3097 const NfCurrencyTable& rTable = GetTheCurrencyTable(); 3098 sal_uInt16 nCount = rTable.Count(); 3099 const NfCurrencyEntryPtr* ppData = rTable.GetData(); 3100 for ( sal_uInt16 j = 0; j < nCount; j++, ppData++ ) 3101 { 3102 if ( (*ppData)->GetLanguage() == eLang && 3103 (*ppData)->GetBankSymbol() == rAbbrev ) 3104 return *ppData; 3105 } 3106 return NULL; 3107 } 3108 3109 3110 // static 3111 const NfCurrencyEntry* SvNumberFormatter::GetLegacyOnlyCurrencyEntry( 3112 const String& rSymbol, const String& rAbbrev ) 3113 { 3114 if (!bCurrencyTableInitialized) 3115 GetTheCurrencyTable(); // just for initialization 3116 const NfCurrencyTable& rTable = theLegacyOnlyCurrencyTable::get(); 3117 sal_uInt16 nCount = rTable.Count(); 3118 const NfCurrencyEntryPtr* ppData = rTable.GetData(); 3119 for ( sal_uInt16 j = 0; j < nCount; j++, ppData++ ) 3120 { 3121 if ( (*ppData)->GetSymbol() == rSymbol && 3122 (*ppData)->GetBankSymbol() == rAbbrev ) 3123 return *ppData; 3124 } 3125 return NULL; 3126 } 3127 3128 3129 // static 3130 IMPL_STATIC_LINK_NOINSTANCE( SvNumberFormatter, CurrencyChangeLink, void*, EMPTYARG ) 3131 { 3132 ::osl::MutexGuard aGuard( GetMutex() ); 3133 String aAbbrev; 3134 LanguageType eLang = LANGUAGE_SYSTEM; 3135 SvtSysLocaleOptions().GetCurrencyAbbrevAndLanguage( aAbbrev, eLang ); 3136 SetDefaultSystemCurrency( aAbbrev, eLang ); 3137 return 0; 3138 } 3139 3140 3141 // static 3142 void SvNumberFormatter::SetDefaultSystemCurrency( const String& rAbbrev, LanguageType eLang ) 3143 { 3144 ::osl::MutexGuard aGuard( GetMutex() ); 3145 if ( eLang == LANGUAGE_SYSTEM ) 3146 eLang = SvtSysLocale().GetLanguage(); 3147 const NfCurrencyTable& rTable = GetTheCurrencyTable(); 3148 sal_uInt16 nCount = rTable.Count(); 3149 const NfCurrencyEntryPtr* ppData = rTable.GetData(); 3150 if ( rAbbrev.Len() ) 3151 { 3152 for ( sal_uInt16 j = 0; j < nCount; j++, ppData++ ) 3153 { 3154 if ( (*ppData)->GetLanguage() == eLang && (*ppData)->GetBankSymbol() == rAbbrev ) 3155 { 3156 nSystemCurrencyPosition = j; 3157 return ; 3158 } 3159 } 3160 } 3161 else 3162 { 3163 for ( sal_uInt16 j = 0; j < nCount; j++, ppData++ ) 3164 { 3165 if ( (*ppData)->GetLanguage() == eLang ) 3166 { 3167 nSystemCurrencyPosition = j; 3168 return ; 3169 } 3170 } 3171 } 3172 nSystemCurrencyPosition = 0; // not found => simple SYSTEM 3173 } 3174 3175 3176 void SvNumberFormatter::ResetDefaultSystemCurrency() 3177 { 3178 nDefaultSystemCurrencyFormat = NUMBERFORMAT_ENTRY_NOT_FOUND; 3179 } 3180 3181 3182 sal_uInt32 SvNumberFormatter::ImpGetDefaultSystemCurrencyFormat() 3183 { 3184 if ( nDefaultSystemCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND ) 3185 { 3186 xub_StrLen nCheck; 3187 short nType; 3188 NfWSStringsDtor aCurrList; 3189 sal_uInt16 nDefault = GetCurrencyFormatStrings( aCurrList, 3190 GetCurrencyEntry( LANGUAGE_SYSTEM ), sal_False ); 3191 DBG_ASSERT( aCurrList.Count(), "where is the NewCurrency System standard format?!?" ); 3192 // if already loaded or user defined nDefaultSystemCurrencyFormat 3193 // will be set to the right value 3194 PutEntry( *aCurrList.GetObject( nDefault ), nCheck, nType, 3195 nDefaultSystemCurrencyFormat, LANGUAGE_SYSTEM ); 3196 DBG_ASSERT( nCheck == 0, "NewCurrency CheckError" ); 3197 DBG_ASSERT( nDefaultSystemCurrencyFormat != NUMBERFORMAT_ENTRY_NOT_FOUND, 3198 "nDefaultSystemCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND" ); 3199 } 3200 return nDefaultSystemCurrencyFormat; 3201 } 3202 3203 3204 sal_uInt32 SvNumberFormatter::ImpGetDefaultCurrencyFormat() 3205 { 3206 sal_uInt32 CLOffset = ImpGetCLOffset( ActLnge ); 3207 sal_uInt32 nDefaultCurrencyFormat = 3208 (sal_uInt32)(sal_uLong) aDefaultFormatKeys.Get( CLOffset + ZF_STANDARD_CURRENCY ); 3209 if ( !nDefaultCurrencyFormat ) 3210 nDefaultCurrencyFormat = NUMBERFORMAT_ENTRY_NOT_FOUND; 3211 if ( nDefaultCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND ) 3212 { 3213 // look for a defined standard 3214 sal_uInt32 nStopKey = CLOffset + SV_COUNTRY_LANGUAGE_OFFSET; 3215 sal_uInt32 nKey; 3216 aFTable.Seek( CLOffset ); 3217 while ( (nKey = aFTable.GetCurKey()) >= CLOffset && nKey < nStopKey ) 3218 { 3219 const SvNumberformat* pEntry = 3220 (const SvNumberformat*) aFTable.GetCurObject(); 3221 if ( pEntry->IsStandard() && (pEntry->GetType() & NUMBERFORMAT_CURRENCY) ) 3222 { 3223 nDefaultCurrencyFormat = nKey; 3224 break; // while 3225 } 3226 aFTable.Next(); 3227 } 3228 3229 if ( nDefaultCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND ) 3230 { // none found, create one 3231 xub_StrLen nCheck; 3232 short nType; 3233 NfWSStringsDtor aCurrList; 3234 sal_uInt16 nDefault = GetCurrencyFormatStrings( aCurrList, 3235 GetCurrencyEntry( ActLnge ), sal_False ); 3236 DBG_ASSERT( aCurrList.Count(), "where is the NewCurrency standard format?" ); 3237 if ( aCurrList.Count() ) 3238 { 3239 // if already loaded or user defined nDefaultSystemCurrencyFormat 3240 // will be set to the right value 3241 PutEntry( *aCurrList.GetObject( nDefault ), nCheck, nType, 3242 nDefaultCurrencyFormat, ActLnge ); 3243 DBG_ASSERT( nCheck == 0, "NewCurrency CheckError" ); 3244 DBG_ASSERT( nDefaultCurrencyFormat != NUMBERFORMAT_ENTRY_NOT_FOUND, 3245 "nDefaultCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND" ); 3246 } 3247 // old automatic currency format as a last resort 3248 if ( nDefaultCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND ) 3249 nDefaultCurrencyFormat = CLOffset + ZF_STANDARD_CURRENCY+3; 3250 else 3251 { // mark as standard so that it is found next time 3252 SvNumberformat* pEntry = aFTable.Get( nDefaultCurrencyFormat ); 3253 if ( pEntry ) 3254 pEntry->SetStandard(); 3255 } 3256 } 3257 aDefaultFormatKeys.Insert( CLOffset + ZF_STANDARD_CURRENCY, 3258 (void*) nDefaultCurrencyFormat ); 3259 } 3260 return nDefaultCurrencyFormat; 3261 } 3262 3263 3264 // static 3265 // try to make it inline if possible since this a loop body 3266 // sal_True: continue; sal_False: break loop, if pFoundEntry==NULL dupe found 3267 #ifndef DBG_UTIL 3268 inline 3269 #endif 3270 sal_Bool SvNumberFormatter::ImpLookupCurrencyEntryLoopBody( 3271 const NfCurrencyEntry*& pFoundEntry, sal_Bool& bFoundBank, 3272 const NfCurrencyEntry* pData, sal_uInt16 nPos, const String& rSymbol ) 3273 { 3274 sal_Bool bFound; 3275 if ( pData->GetSymbol() == rSymbol ) 3276 { 3277 bFound = sal_True; 3278 bFoundBank = sal_False; 3279 } 3280 else if ( pData->GetBankSymbol() == rSymbol ) 3281 { 3282 bFound = sal_True; 3283 bFoundBank = sal_True; 3284 } 3285 else 3286 bFound = sal_False; 3287 if ( bFound ) 3288 { 3289 if ( pFoundEntry && pFoundEntry != pData ) 3290 { 3291 pFoundEntry = NULL; 3292 return sal_False; // break loop, not unique 3293 } 3294 if ( nPos == 0 ) 3295 { // first entry is SYSTEM 3296 pFoundEntry = MatchSystemCurrency(); 3297 if ( pFoundEntry ) 3298 return sal_False; // break loop 3299 // even if there are more matching entries 3300 // this one is propably the one we are looking for 3301 else 3302 pFoundEntry = pData; 3303 } 3304 else 3305 pFoundEntry = pData; 3306 } 3307 return sal_True; 3308 } 3309 3310 3311 sal_Bool SvNumberFormatter::GetNewCurrencySymbolString( sal_uInt32 nFormat, 3312 String& rStr, const NfCurrencyEntry** ppEntry /* = NULL */, 3313 sal_Bool* pBank /* = NULL */ ) const 3314 { 3315 rStr.Erase(); 3316 if ( ppEntry ) 3317 *ppEntry = NULL; 3318 if ( pBank ) 3319 *pBank = sal_False; 3320 SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get( nFormat ); 3321 if ( pFormat ) 3322 { 3323 String aSymbol, aExtension; 3324 if ( pFormat->GetNewCurrencySymbol( aSymbol, aExtension ) ) 3325 { 3326 if ( ppEntry ) 3327 { 3328 sal_Bool bFoundBank = sal_False; 3329 // we definiteley need an entry matching the format code string 3330 const NfCurrencyEntry* pFoundEntry = GetCurrencyEntry( 3331 bFoundBank, aSymbol, aExtension, pFormat->GetLanguage(), 3332 sal_True ); 3333 if ( pFoundEntry ) 3334 { 3335 *ppEntry = pFoundEntry; 3336 if ( pBank ) 3337 *pBank = bFoundBank; 3338 pFoundEntry->BuildSymbolString( rStr, bFoundBank ); 3339 } 3340 } 3341 if ( !rStr.Len() ) 3342 { // analog zu BuildSymbolString 3343 rStr = '['; 3344 rStr += '$'; 3345 if ( aSymbol.Search( '-' ) != STRING_NOTFOUND || 3346 aSymbol.Search( ']' ) != STRING_NOTFOUND ) 3347 { 3348 rStr += '"'; 3349 rStr += aSymbol; 3350 rStr += '"'; 3351 } 3352 else 3353 rStr += aSymbol; 3354 if ( aExtension.Len() ) 3355 rStr += aExtension; 3356 rStr += ']'; 3357 } 3358 return sal_True; 3359 } 3360 } 3361 return sal_False; 3362 } 3363 3364 3365 // static 3366 const NfCurrencyEntry* SvNumberFormatter::GetCurrencyEntry( sal_Bool & bFoundBank, 3367 const String& rSymbol, const String& rExtension, 3368 LanguageType eFormatLanguage, sal_Bool bOnlyStringLanguage ) 3369 { 3370 xub_StrLen nExtLen = rExtension.Len(); 3371 LanguageType eExtLang; 3372 if ( nExtLen ) 3373 { 3374 sal_Int32 nExtLang = ::rtl::OUString( rExtension ).toInt32( 16 ); 3375 if ( !nExtLang ) 3376 eExtLang = LANGUAGE_DONTKNOW; 3377 else 3378 eExtLang = (LanguageType) ((nExtLang < 0) ? 3379 -nExtLang : nExtLang); 3380 } 3381 else 3382 eExtLang = LANGUAGE_DONTKNOW; 3383 const NfCurrencyEntry* pFoundEntry = NULL; 3384 const NfCurrencyTable& rTable = GetTheCurrencyTable(); 3385 sal_uInt16 nCount = rTable.Count(); 3386 sal_Bool bCont = sal_True; 3387 3388 // first try with given extension language/country 3389 if ( nExtLen ) 3390 { 3391 const NfCurrencyEntryPtr* ppData = rTable.GetData(); 3392 for ( sal_uInt16 j = 0; j < nCount && bCont; j++, ppData++ ) 3393 { 3394 LanguageType eLang = (*ppData)->GetLanguage(); 3395 if ( eLang == eExtLang || 3396 ((eExtLang == LANGUAGE_DONTKNOW) && 3397 (eLang == LANGUAGE_SYSTEM)) 3398 ) 3399 { 3400 bCont = ImpLookupCurrencyEntryLoopBody( pFoundEntry, bFoundBank, 3401 *ppData, j, rSymbol ); 3402 } 3403 } 3404 } 3405 3406 // ok? 3407 if ( pFoundEntry || !bCont || (bOnlyStringLanguage && nExtLen) ) 3408 return pFoundEntry; 3409 3410 if ( !bOnlyStringLanguage ) 3411 { 3412 // now try the language/country of the number format 3413 const NfCurrencyEntryPtr* ppData = rTable.GetData(); 3414 for ( sal_uInt16 j = 0; j < nCount && bCont; j++, ppData++ ) 3415 { 3416 LanguageType eLang = (*ppData)->GetLanguage(); 3417 if ( eLang == eFormatLanguage || 3418 ((eFormatLanguage == LANGUAGE_DONTKNOW) && 3419 (eLang == LANGUAGE_SYSTEM)) 3420 ) 3421 { 3422 bCont = ImpLookupCurrencyEntryLoopBody( pFoundEntry, bFoundBank, 3423 *ppData, j, rSymbol ); 3424 } 3425 } 3426 3427 // ok? 3428 if ( pFoundEntry || !bCont ) 3429 return pFoundEntry; 3430 } 3431 3432 // then try without language/country if no extension specified 3433 if ( !nExtLen ) 3434 { 3435 const NfCurrencyEntryPtr* ppData = rTable.GetData(); 3436 for ( sal_uInt16 j = 0; j < nCount && bCont; j++, ppData++ ) 3437 { 3438 bCont = ImpLookupCurrencyEntryLoopBody( pFoundEntry, bFoundBank, 3439 *ppData, j, rSymbol ); 3440 } 3441 } 3442 3443 return pFoundEntry; 3444 } 3445 3446 3447 void SvNumberFormatter::GetCompatibilityCurrency( String& rSymbol, String& rAbbrev ) const 3448 { 3449 ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Currency2 > 3450 xCurrencies = xLocaleData->getAllCurrencies(); 3451 sal_Int32 nCurrencies = xCurrencies.getLength(); 3452 sal_Int32 j; 3453 for ( j=0; j < nCurrencies; ++j ) 3454 { 3455 if ( xCurrencies[j].UsedInCompatibleFormatCodes ) 3456 { 3457 rSymbol = xCurrencies[j].Symbol; 3458 rAbbrev = xCurrencies[j].BankSymbol; 3459 break; 3460 } 3461 } 3462 if ( j >= nCurrencies ) 3463 { 3464 if (LocaleDataWrapper::areChecksEnabled()) 3465 { 3466 String aMsg( RTL_CONSTASCII_USTRINGPARAM( 3467 "GetCompatibilityCurrency: none?")); 3468 LocaleDataWrapper::outputCheckMessage( 3469 xLocaleData->appendLocaleInfo( aMsg)); 3470 } 3471 rSymbol = xLocaleData->getCurrSymbol(); 3472 rAbbrev = xLocaleData->getCurrBankSymbol(); 3473 } 3474 } 3475 3476 3477 void lcl_CheckCurrencySymbolPosition( const NfCurrencyEntry& rCurr ) 3478 { 3479 short nPos = -1; // -1:=unknown, 0:=vorne, 1:=hinten 3480 short nNeg = -1; 3481 switch ( rCurr.GetPositiveFormat() ) 3482 { 3483 case 0: // $1 3484 nPos = 0; 3485 break; 3486 case 1: // 1$ 3487 nPos = 1; 3488 break; 3489 case 2: // $ 1 3490 nPos = 0; 3491 break; 3492 case 3: // 1 $ 3493 nPos = 1; 3494 break; 3495 default: 3496 LocaleDataWrapper::outputCheckMessage( 3497 "lcl_CheckCurrencySymbolPosition: unknown PositiveFormat"); 3498 break; 3499 } 3500 switch ( rCurr.GetNegativeFormat() ) 3501 { 3502 case 0: // ($1) 3503 nNeg = 0; 3504 break; 3505 case 1: // -$1 3506 nNeg = 0; 3507 break; 3508 case 2: // $-1 3509 nNeg = 0; 3510 break; 3511 case 3: // $1- 3512 nNeg = 0; 3513 break; 3514 case 4: // (1$) 3515 nNeg = 1; 3516 break; 3517 case 5: // -1$ 3518 nNeg = 1; 3519 break; 3520 case 6: // 1-$ 3521 nNeg = 1; 3522 break; 3523 case 7: // 1$- 3524 nNeg = 1; 3525 break; 3526 case 8: // -1 $ 3527 nNeg = 1; 3528 break; 3529 case 9: // -$ 1 3530 nNeg = 0; 3531 break; 3532 case 10: // 1 $- 3533 nNeg = 1; 3534 break; 3535 case 11: // $ -1 3536 nNeg = 0; 3537 break; 3538 case 12 : // $ 1- 3539 nNeg = 0; 3540 break; 3541 case 13 : // 1- $ 3542 nNeg = 1; 3543 break; 3544 case 14 : // ($ 1) 3545 nNeg = 0; 3546 break; 3547 case 15 : // (1 $) 3548 nNeg = 1; 3549 break; 3550 default: 3551 LocaleDataWrapper::outputCheckMessage( 3552 "lcl_CheckCurrencySymbolPosition: unknown NegativeFormat"); 3553 break; 3554 } 3555 if ( nPos >= 0 && nNeg >= 0 && nPos != nNeg ) 3556 { 3557 ByteString aStr( "positions of currency symbols differ\nLanguage: " ); 3558 aStr += ByteString::CreateFromInt32( rCurr.GetLanguage() ); 3559 aStr += " <"; 3560 aStr += ByteString( rCurr.GetSymbol(), RTL_TEXTENCODING_UTF8 ); 3561 aStr += "> positive: "; 3562 aStr += ByteString::CreateFromInt32( rCurr.GetPositiveFormat() ); 3563 aStr += ( nPos ? " (postfix)" : " (prefix)" ); 3564 aStr += ", negative: "; 3565 aStr += ByteString::CreateFromInt32( rCurr.GetNegativeFormat() ); 3566 aStr += ( nNeg ? " (postfix)" : " (prefix)" ); 3567 #if 0 3568 // seems that there really are some currencies which differ, e.g. YugoDinar 3569 DBG_ERRORFILE( aStr.GetBuffer() ); 3570 #endif 3571 } 3572 } 3573 3574 3575 // static 3576 void SvNumberFormatter::ImpInitCurrencyTable() 3577 { 3578 // racing condition possible: 3579 // ::osl::MutexGuard aGuard( GetMutex() ); 3580 // while ( !bCurrencyTableInitialized ) 3581 // ImpInitCurrencyTable(); 3582 static sal_Bool bInitializing = sal_False; 3583 if ( bCurrencyTableInitialized || bInitializing ) 3584 return ; 3585 bInitializing = sal_True; 3586 3587 RTL_LOGFILE_CONTEXT_AUTHOR( aTimeLog, "svl", "er93726", "SvNumberFormatter::ImpInitCurrencyTable" ); 3588 3589 LanguageType eSysLang = SvtSysLocale().GetLanguage(); 3590 LocaleDataWrapper* pLocaleData = new LocaleDataWrapper( 3591 ::comphelper::getProcessServiceFactory(), 3592 MsLangId::convertLanguageToLocale( eSysLang ) ); 3593 // get user configured currency 3594 String aConfiguredCurrencyAbbrev; 3595 LanguageType eConfiguredCurrencyLanguage = LANGUAGE_SYSTEM; 3596 SvtSysLocaleOptions().GetCurrencyAbbrevAndLanguage( 3597 aConfiguredCurrencyAbbrev, eConfiguredCurrencyLanguage ); 3598 sal_uInt16 nSecondarySystemCurrencyPosition = 0; 3599 sal_uInt16 nMatchingSystemCurrencyPosition = 0; 3600 NfCurrencyEntryPtr pEntry; 3601 3602 // first entry is SYSTEM 3603 pEntry = new NfCurrencyEntry( *pLocaleData, LANGUAGE_SYSTEM ); 3604 theCurrencyTable::get().Insert( pEntry, 0 ); 3605 sal_uInt16 nCurrencyPos = 1; 3606 3607 ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > xLoc = 3608 LocaleDataWrapper::getInstalledLocaleNames(); 3609 sal_Int32 nLocaleCount = xLoc.getLength(); 3610 RTL_LOGFILE_CONTEXT_TRACE1( aTimeLog, "number of locales: %ld", nLocaleCount ); 3611 Locale const * const pLocales = xLoc.getConstArray(); 3612 NfCurrencyTable &rCurrencyTable = theCurrencyTable::get(); 3613 NfCurrencyTable &rLegacyOnlyCurrencyTable = theLegacyOnlyCurrencyTable::get(); 3614 sal_uInt16 nLegacyOnlyCurrencyPos = 0; 3615 for ( sal_Int32 nLocale = 0; nLocale < nLocaleCount; nLocale++ ) 3616 { 3617 LanguageType eLang = MsLangId::convertLocaleToLanguage( 3618 pLocales[nLocale]); 3619 #if OSL_DEBUG_LEVEL > 1 3620 LanguageType eReal = MsLangId::getRealLanguage( eLang ); 3621 if ( eReal != eLang ) { 3622 sal_Bool bBreak; 3623 bBreak = sal_True; 3624 } 3625 #endif 3626 pLocaleData->setLocale( pLocales[nLocale] ); 3627 Sequence< Currency2 > aCurrSeq = pLocaleData->getAllCurrencies(); 3628 sal_Int32 nCurrencyCount = aCurrSeq.getLength(); 3629 Currency2 const * const pCurrencies = aCurrSeq.getConstArray(); 3630 3631 // one default currency for each locale, insert first so it is found first 3632 sal_Int32 nDefault; 3633 for ( nDefault = 0; nDefault < nCurrencyCount; nDefault++ ) 3634 { 3635 if ( pCurrencies[nDefault].Default ) 3636 break; 3637 } 3638 if ( nDefault < nCurrencyCount ) 3639 pEntry = new NfCurrencyEntry( pCurrencies[nDefault], *pLocaleData, eLang ); 3640 else 3641 pEntry = new NfCurrencyEntry( *pLocaleData, eLang ); // first or ShellsAndPebbles 3642 3643 if (LocaleDataWrapper::areChecksEnabled()) 3644 lcl_CheckCurrencySymbolPosition( *pEntry ); 3645 3646 rCurrencyTable.Insert( pEntry, nCurrencyPos++ ); 3647 if ( !nSystemCurrencyPosition && (aConfiguredCurrencyAbbrev.Len() ? 3648 pEntry->GetBankSymbol() == aConfiguredCurrencyAbbrev && 3649 pEntry->GetLanguage() == eConfiguredCurrencyLanguage : sal_False) ) 3650 nSystemCurrencyPosition = nCurrencyPos-1; 3651 if ( !nMatchingSystemCurrencyPosition && 3652 pEntry->GetLanguage() == eSysLang ) 3653 nMatchingSystemCurrencyPosition = nCurrencyPos-1; 3654 3655 // all remaining currencies for each locale 3656 if ( nCurrencyCount > 1 ) 3657 { 3658 sal_Int32 nCurrency; 3659 for ( nCurrency = 0; nCurrency < nCurrencyCount; nCurrency++ ) 3660 { 3661 if (pCurrencies[nCurrency].LegacyOnly) 3662 { 3663 pEntry = new NfCurrencyEntry( pCurrencies[nCurrency], *pLocaleData, eLang ); 3664 rLegacyOnlyCurrencyTable.Insert( pEntry, nLegacyOnlyCurrencyPos++ ); 3665 } 3666 else if ( nCurrency != nDefault ) 3667 { 3668 pEntry = new NfCurrencyEntry( pCurrencies[nCurrency], *pLocaleData, eLang ); 3669 // no dupes 3670 sal_Bool bInsert = sal_True; 3671 NfCurrencyEntry const * const * pData = rCurrencyTable.GetData(); 3672 sal_uInt16 n = rCurrencyTable.Count(); 3673 pData++; // skip first SYSTEM entry 3674 for ( sal_uInt16 j=1; j<n; j++ ) 3675 { 3676 if ( *(*pData++) == *pEntry ) 3677 { 3678 bInsert = sal_False; 3679 break; // for 3680 } 3681 } 3682 if ( !bInsert ) 3683 delete pEntry; 3684 else 3685 { 3686 rCurrencyTable.Insert( pEntry, nCurrencyPos++ ); 3687 if ( !nSecondarySystemCurrencyPosition && 3688 (aConfiguredCurrencyAbbrev.Len() ? 3689 pEntry->GetBankSymbol() == aConfiguredCurrencyAbbrev : 3690 pEntry->GetLanguage() == eConfiguredCurrencyLanguage) ) 3691 nSecondarySystemCurrencyPosition = nCurrencyPos-1; 3692 if ( !nMatchingSystemCurrencyPosition && 3693 pEntry->GetLanguage() == eSysLang ) 3694 nMatchingSystemCurrencyPosition = nCurrencyPos-1; 3695 } 3696 } 3697 } 3698 } 3699 } 3700 if ( !nSystemCurrencyPosition ) 3701 nSystemCurrencyPosition = nSecondarySystemCurrencyPosition; 3702 if ((aConfiguredCurrencyAbbrev.Len() && !nSystemCurrencyPosition) && 3703 LocaleDataWrapper::areChecksEnabled()) 3704 LocaleDataWrapper::outputCheckMessage( 3705 "SvNumberFormatter::ImpInitCurrencyTable: configured currency not in I18N locale data."); 3706 // match SYSTEM if no configured currency found 3707 if ( !nSystemCurrencyPosition ) 3708 nSystemCurrencyPosition = nMatchingSystemCurrencyPosition; 3709 if ((!aConfiguredCurrencyAbbrev.Len() && !nSystemCurrencyPosition) && 3710 LocaleDataWrapper::areChecksEnabled()) 3711 LocaleDataWrapper::outputCheckMessage( 3712 "SvNumberFormatter::ImpInitCurrencyTable: system currency not in I18N locale data."); 3713 delete pLocaleData; 3714 SvtSysLocaleOptions::SetCurrencyChangeLink( 3715 STATIC_LINK( NULL, SvNumberFormatter, CurrencyChangeLink ) ); 3716 bInitializing = sal_False; 3717 bCurrencyTableInitialized = sal_True; 3718 } 3719 3720 3721 sal_uInt16 SvNumberFormatter::GetCurrencyFormatStrings( NfWSStringsDtor& rStrArr, 3722 const NfCurrencyEntry& rCurr, sal_Bool bBank ) const 3723 { 3724 sal_uInt16 nDefault = 0; 3725 if ( bBank ) 3726 { // nur Bankensymbole 3727 String aPositiveBank, aNegativeBank; 3728 rCurr.BuildPositiveFormatString( aPositiveBank, sal_True, *xLocaleData, 1 ); 3729 rCurr.BuildNegativeFormatString( aNegativeBank, sal_True, *xLocaleData, 1 ); 3730 3731 WSStringPtr pFormat1 = new String( aPositiveBank ); 3732 *pFormat1 += ';'; 3733 WSStringPtr pFormat2 = new String( *pFormat1 ); 3734 3735 String aRed( '[' ); 3736 aRed += pFormatScanner->GetRedString(); 3737 aRed += ']'; 3738 3739 *pFormat2 += aRed; 3740 3741 *pFormat1 += aNegativeBank; 3742 *pFormat2 += aNegativeBank; 3743 3744 rStrArr.Insert( pFormat1, rStrArr.Count() ); 3745 rStrArr.Insert( pFormat2, rStrArr.Count() ); 3746 nDefault = rStrArr.Count() - 1; 3747 } 3748 else 3749 { // gemischte Formate wie in SvNumberFormatter::ImpGenerateFormats 3750 // aber keine doppelten, wenn keine Nachkommastellen in Waehrung 3751 String aPositive, aNegative, aPositiveNoDec, aNegativeNoDec, 3752 aPositiveDashed, aNegativeDashed; 3753 WSStringPtr pFormat1, pFormat2, pFormat3, pFormat4, pFormat5; 3754 3755 String aRed( '[' ); 3756 aRed += pFormatScanner->GetRedString(); 3757 aRed += ']'; 3758 3759 rCurr.BuildPositiveFormatString( aPositive, sal_False, *xLocaleData, 1 ); 3760 rCurr.BuildNegativeFormatString( aNegative, sal_False, *xLocaleData, 1 ); 3761 if ( rCurr.GetDigits() ) 3762 { 3763 rCurr.BuildPositiveFormatString( aPositiveNoDec, sal_False, *xLocaleData, 0 ); 3764 rCurr.BuildNegativeFormatString( aNegativeNoDec, sal_False, *xLocaleData, 0 ); 3765 rCurr.BuildPositiveFormatString( aPositiveDashed, sal_False, *xLocaleData, 2 ); 3766 rCurr.BuildNegativeFormatString( aNegativeDashed, sal_False, *xLocaleData, 2 ); 3767 3768 pFormat1 = new String( aPositiveNoDec ); 3769 *pFormat1 += ';'; 3770 pFormat3 = new String( *pFormat1 ); 3771 pFormat5 = new String( aPositiveDashed ); 3772 *pFormat5 += ';'; 3773 3774 *pFormat1 += aNegativeNoDec; 3775 3776 *pFormat3 += aRed; 3777 *pFormat5 += aRed; 3778 3779 *pFormat3 += aNegativeNoDec; 3780 *pFormat5 += aNegativeDashed; 3781 } 3782 else 3783 { 3784 pFormat1 = NULL; 3785 pFormat3 = NULL; 3786 pFormat5 = NULL; 3787 } 3788 3789 pFormat2 = new String( aPositive ); 3790 *pFormat2 += ';'; 3791 pFormat4 = new String( *pFormat2 ); 3792 3793 *pFormat2 += aNegative; 3794 3795 *pFormat4 += aRed; 3796 *pFormat4 += aNegative; 3797 3798 if ( pFormat1 ) 3799 rStrArr.Insert( pFormat1, rStrArr.Count() ); 3800 rStrArr.Insert( pFormat2, rStrArr.Count() ); 3801 if ( pFormat3 ) 3802 rStrArr.Insert( pFormat3, rStrArr.Count() ); 3803 rStrArr.Insert( pFormat4, rStrArr.Count() ); 3804 nDefault = rStrArr.Count() - 1; 3805 if ( pFormat5 ) 3806 rStrArr.Insert( pFormat5, rStrArr.Count() ); 3807 } 3808 return nDefault; 3809 } 3810 3811 3812 //--- NfCurrencyEntry ---------------------------------------------------- 3813 3814 NfCurrencyEntry::NfCurrencyEntry() 3815 : eLanguage( LANGUAGE_DONTKNOW ), 3816 nPositiveFormat(3), 3817 nNegativeFormat(8), 3818 nDigits(2), 3819 cZeroChar('0') 3820 { 3821 } 3822 3823 3824 NfCurrencyEntry::NfCurrencyEntry( const LocaleDataWrapper& rLocaleData, LanguageType eLang ) 3825 { 3826 aSymbol = rLocaleData.getCurrSymbol(); 3827 aBankSymbol = rLocaleData.getCurrBankSymbol(); 3828 eLanguage = eLang; 3829 nPositiveFormat = rLocaleData.getCurrPositiveFormat(); 3830 nNegativeFormat = rLocaleData.getCurrNegativeFormat(); 3831 nDigits = rLocaleData.getCurrDigits(); 3832 cZeroChar = rLocaleData.getCurrZeroChar(); 3833 } 3834 3835 3836 NfCurrencyEntry::NfCurrencyEntry( const ::com::sun::star::i18n::Currency & rCurr, 3837 const LocaleDataWrapper& rLocaleData, LanguageType eLang ) 3838 { 3839 aSymbol = rCurr.Symbol; 3840 aBankSymbol = rCurr.BankSymbol; 3841 eLanguage = eLang; 3842 nPositiveFormat = rLocaleData.getCurrPositiveFormat(); 3843 nNegativeFormat = rLocaleData.getCurrNegativeFormat(); 3844 nDigits = rCurr.DecimalPlaces; 3845 cZeroChar = rLocaleData.getCurrZeroChar(); 3846 } 3847 3848 3849 sal_Bool NfCurrencyEntry::operator==( const NfCurrencyEntry& r ) const 3850 { 3851 return aSymbol == r.aSymbol 3852 && aBankSymbol == r.aBankSymbol 3853 && eLanguage == r.eLanguage 3854 ; 3855 } 3856 3857 3858 void NfCurrencyEntry::SetEuro() 3859 { 3860 aSymbol = NfCurrencyEntry::GetEuroSymbol(); 3861 aBankSymbol.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "EUR" ) ); 3862 eLanguage = LANGUAGE_DONTKNOW; 3863 nPositiveFormat = 3; 3864 nNegativeFormat = 8; 3865 nDigits = 2; 3866 cZeroChar = '0'; 3867 } 3868 3869 3870 sal_Bool NfCurrencyEntry::IsEuro() const 3871 { 3872 if ( aBankSymbol.EqualsAscii( "EUR" ) ) 3873 return sal_True; 3874 String aEuro( NfCurrencyEntry::GetEuroSymbol() ); 3875 return aSymbol == aEuro; 3876 } 3877 3878 3879 void NfCurrencyEntry::ApplyVariableInformation( const NfCurrencyEntry& r ) 3880 { 3881 nPositiveFormat = r.nPositiveFormat; 3882 nNegativeFormat = r.nNegativeFormat; 3883 cZeroChar = r.cZeroChar; 3884 } 3885 3886 3887 void NfCurrencyEntry::BuildSymbolString( String& rStr, sal_Bool bBank, 3888 sal_Bool bWithoutExtension ) const 3889 { 3890 rStr = '['; 3891 rStr += '$'; 3892 if ( bBank ) 3893 rStr += aBankSymbol; 3894 else 3895 { 3896 if ( aSymbol.Search( '-' ) != STRING_NOTFOUND || aSymbol.Search( ']' ) != STRING_NOTFOUND ) 3897 { 3898 rStr += '"'; 3899 rStr += aSymbol; 3900 rStr += '"'; 3901 } 3902 else 3903 rStr += aSymbol; 3904 if ( !bWithoutExtension && eLanguage != LANGUAGE_DONTKNOW && eLanguage != LANGUAGE_SYSTEM ) 3905 { 3906 rStr += '-'; 3907 rStr += String::CreateFromInt32( sal_Int32( eLanguage ), 16 ).ToUpperAscii(); 3908 } 3909 } 3910 rStr += ']'; 3911 } 3912 3913 3914 void NfCurrencyEntry::Impl_BuildFormatStringNumChars( String& rStr, 3915 const LocaleDataWrapper& rLoc, sal_uInt16 nDecimalFormat ) const 3916 { 3917 rStr.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "###0" ) ); 3918 rStr.Insert( rLoc.getNumThousandSep(), 1 ); 3919 if ( nDecimalFormat && nDigits ) 3920 { 3921 rStr += rLoc.getNumDecimalSep(); 3922 rStr.Expand( rStr.Len() + nDigits, (nDecimalFormat == 2 ? '-' : cZeroChar) ); 3923 } 3924 } 3925 3926 3927 void NfCurrencyEntry::BuildPositiveFormatString( String& rStr, sal_Bool bBank, 3928 const LocaleDataWrapper& rLoc, sal_uInt16 nDecimalFormat ) const 3929 { 3930 Impl_BuildFormatStringNumChars( rStr, rLoc, nDecimalFormat ); 3931 sal_uInt16 nPosiForm = NfCurrencyEntry::GetEffectivePositiveFormat( 3932 rLoc.getCurrPositiveFormat(), nPositiveFormat, bBank ); 3933 CompletePositiveFormatString( rStr, bBank, nPosiForm ); 3934 } 3935 3936 3937 void NfCurrencyEntry::BuildNegativeFormatString( String& rStr, sal_Bool bBank, 3938 const LocaleDataWrapper& rLoc, sal_uInt16 nDecimalFormat ) const 3939 { 3940 Impl_BuildFormatStringNumChars( rStr, rLoc, nDecimalFormat ); 3941 sal_uInt16 nNegaForm = NfCurrencyEntry::GetEffectiveNegativeFormat( 3942 rLoc.getCurrNegativeFormat(), nNegativeFormat, bBank ); 3943 CompleteNegativeFormatString( rStr, bBank, nNegaForm ); 3944 } 3945 3946 3947 void NfCurrencyEntry::CompletePositiveFormatString( String& rStr, sal_Bool bBank, 3948 sal_uInt16 nPosiForm ) const 3949 { 3950 String aSymStr; 3951 BuildSymbolString( aSymStr, bBank ); 3952 NfCurrencyEntry::CompletePositiveFormatString( rStr, aSymStr, nPosiForm ); 3953 } 3954 3955 3956 void NfCurrencyEntry::CompleteNegativeFormatString( String& rStr, sal_Bool bBank, 3957 sal_uInt16 nNegaForm ) const 3958 { 3959 String aSymStr; 3960 BuildSymbolString( aSymStr, bBank ); 3961 NfCurrencyEntry::CompleteNegativeFormatString( rStr, aSymStr, nNegaForm ); 3962 } 3963 3964 3965 // static 3966 void NfCurrencyEntry::CompletePositiveFormatString( String& rStr, 3967 const String& rSymStr, sal_uInt16 nPositiveFormat ) 3968 { 3969 switch( nPositiveFormat ) 3970 { 3971 case 0: // $1 3972 rStr.Insert( rSymStr , 0 ); 3973 break; 3974 case 1: // 1$ 3975 rStr += rSymStr; 3976 break; 3977 case 2: // $ 1 3978 { 3979 rStr.Insert( ' ', 0 ); 3980 rStr.Insert( rSymStr, 0 ); 3981 } 3982 break; 3983 case 3: // 1 $ 3984 { 3985 rStr += ' '; 3986 rStr += rSymStr; 3987 } 3988 break; 3989 default: 3990 DBG_ERROR("NfCurrencyEntry::CompletePositiveFormatString: unknown option"); 3991 break; 3992 } 3993 } 3994 3995 3996 // static 3997 void NfCurrencyEntry::CompleteNegativeFormatString( String& rStr, 3998 const String& rSymStr, sal_uInt16 nNegativeFormat ) 3999 { 4000 switch( nNegativeFormat ) 4001 { 4002 case 0: // ($1) 4003 { 4004 rStr.Insert( rSymStr, 0); 4005 rStr.Insert('(',0); 4006 rStr += ')'; 4007 } 4008 break; 4009 case 1: // -$1 4010 { 4011 rStr.Insert( rSymStr, 0); 4012 rStr.Insert('-',0); 4013 } 4014 break; 4015 case 2: // $-1 4016 { 4017 rStr.Insert('-',0); 4018 rStr.Insert( rSymStr, 0); 4019 } 4020 break; 4021 case 3: // $1- 4022 { 4023 rStr.Insert( rSymStr, 0); 4024 rStr += '-'; 4025 } 4026 break; 4027 case 4: // (1$) 4028 { 4029 rStr.Insert('(',0); 4030 rStr += rSymStr; 4031 rStr += ')'; 4032 } 4033 break; 4034 case 5: // -1$ 4035 { 4036 rStr += rSymStr; 4037 rStr.Insert('-',0); 4038 } 4039 break; 4040 case 6: // 1-$ 4041 { 4042 rStr += '-'; 4043 rStr += rSymStr; 4044 } 4045 break; 4046 case 7: // 1$- 4047 { 4048 rStr += rSymStr; 4049 rStr += '-'; 4050 } 4051 break; 4052 case 8: // -1 $ 4053 { 4054 rStr += ' '; 4055 rStr += rSymStr; 4056 rStr.Insert('-',0); 4057 } 4058 break; 4059 case 9: // -$ 1 4060 { 4061 rStr.Insert(' ',0); 4062 rStr.Insert( rSymStr, 0); 4063 rStr.Insert('-',0); 4064 } 4065 break; 4066 case 10: // 1 $- 4067 { 4068 rStr += ' '; 4069 rStr += rSymStr; 4070 rStr += '-'; 4071 } 4072 break; 4073 case 11: // $ -1 4074 { 4075 String aTmp( rSymStr ); 4076 aTmp += ' '; 4077 aTmp += '-'; 4078 rStr.Insert( aTmp, 0 ); 4079 } 4080 break; 4081 case 12 : // $ 1- 4082 { 4083 rStr.Insert(' ', 0); 4084 rStr.Insert( rSymStr, 0); 4085 rStr += '-'; 4086 } 4087 break; 4088 case 13 : // 1- $ 4089 { 4090 rStr += '-'; 4091 rStr += ' '; 4092 rStr += rSymStr; 4093 } 4094 break; 4095 case 14 : // ($ 1) 4096 { 4097 rStr.Insert(' ',0); 4098 rStr.Insert( rSymStr, 0); 4099 rStr.Insert('(',0); 4100 rStr += ')'; 4101 } 4102 break; 4103 case 15 : // (1 $) 4104 { 4105 rStr.Insert('(',0); 4106 rStr += ' '; 4107 rStr += rSymStr; 4108 rStr += ')'; 4109 } 4110 break; 4111 default: 4112 DBG_ERROR("NfCurrencyEntry::CompleteNegativeFormatString: unknown option"); 4113 break; 4114 } 4115 } 4116 4117 4118 // static 4119 sal_uInt16 NfCurrencyEntry::GetEffectivePositiveFormat( sal_uInt16 4120 #if ! NF_BANKSYMBOL_FIX_POSITION 4121 nIntlFormat 4122 #endif 4123 , sal_uInt16 nCurrFormat, sal_Bool bBank ) 4124 { 4125 if ( bBank ) 4126 { 4127 #if NF_BANKSYMBOL_FIX_POSITION 4128 return 3; 4129 #else 4130 switch ( nIntlFormat ) 4131 { 4132 case 0: // $1 4133 nIntlFormat = 2; // $ 1 4134 break; 4135 case 1: // 1$ 4136 nIntlFormat = 3; // 1 $ 4137 break; 4138 case 2: // $ 1 4139 break; 4140 case 3: // 1 $ 4141 break; 4142 default: 4143 DBG_ERROR("NfCurrencyEntry::GetEffectivePositiveFormat: unknown option"); 4144 break; 4145 } 4146 return nIntlFormat; 4147 #endif 4148 } 4149 else 4150 return nCurrFormat; 4151 } 4152 4153 4154 // nur aufrufen, wenn nCurrFormat wirklich mit Klammern ist 4155 sal_uInt16 lcl_MergeNegativeParenthesisFormat( sal_uInt16 nIntlFormat, sal_uInt16 nCurrFormat ) 4156 { 4157 short nSign = 0; // -1:=Klammer 0:=links, 1:=mitte, 2:=rechts 4158 switch ( nIntlFormat ) 4159 { 4160 case 0: // ($1) 4161 case 4: // (1$) 4162 case 14 : // ($ 1) 4163 case 15 : // (1 $) 4164 return nCurrFormat; 4165 case 1: // -$1 4166 case 5: // -1$ 4167 case 8: // -1 $ 4168 case 9: // -$ 1 4169 nSign = 0; 4170 break; 4171 case 2: // $-1 4172 case 6: // 1-$ 4173 case 11 : // $ -1 4174 case 13 : // 1- $ 4175 nSign = 1; 4176 break; 4177 case 3: // $1- 4178 case 7: // 1$- 4179 case 10: // 1 $- 4180 case 12 : // $ 1- 4181 nSign = 2; 4182 break; 4183 default: 4184 DBG_ERROR("lcl_MergeNegativeParenthesisFormat: unknown option"); 4185 break; 4186 } 4187 4188 switch ( nCurrFormat ) 4189 { 4190 case 0: // ($1) 4191 switch ( nSign ) 4192 { 4193 case 0: 4194 return 1; // -$1 4195 case 1: 4196 return 2; // $-1 4197 case 2: 4198 return 3; // $1- 4199 } 4200 break; 4201 case 4: // (1$) 4202 switch ( nSign ) 4203 { 4204 case 0: 4205 return 5; // -1$ 4206 case 1: 4207 return 6; // 1-$ 4208 case 2: 4209 return 7; // 1$- 4210 } 4211 break; 4212 case 14 : // ($ 1) 4213 switch ( nSign ) 4214 { 4215 case 0: 4216 return 9; // -$ 1 4217 case 1: 4218 return 11; // $ -1 4219 case 2: 4220 return 12; // $ 1- 4221 } 4222 break; 4223 case 15 : // (1 $) 4224 switch ( nSign ) 4225 { 4226 case 0: 4227 return 8; // -1 $ 4228 case 1: 4229 return 13; // 1- $ 4230 case 2: 4231 return 10; // 1 $- 4232 } 4233 break; 4234 } 4235 return nCurrFormat; 4236 } 4237 4238 4239 // static 4240 sal_uInt16 NfCurrencyEntry::GetEffectiveNegativeFormat( sal_uInt16 nIntlFormat, 4241 sal_uInt16 nCurrFormat, sal_Bool bBank ) 4242 { 4243 if ( bBank ) 4244 { 4245 #if NF_BANKSYMBOL_FIX_POSITION 4246 return 8; 4247 #else 4248 switch ( nIntlFormat ) 4249 { 4250 case 0: // ($1) 4251 // nIntlFormat = 14; // ($ 1) 4252 nIntlFormat = 9; // -$ 1 4253 break; 4254 case 1: // -$1 4255 nIntlFormat = 9; // -$ 1 4256 break; 4257 case 2: // $-1 4258 nIntlFormat = 11; // $ -1 4259 break; 4260 case 3: // $1- 4261 nIntlFormat = 12; // $ 1- 4262 break; 4263 case 4: // (1$) 4264 // nIntlFormat = 15; // (1 $) 4265 nIntlFormat = 8; // -1 $ 4266 break; 4267 case 5: // -1$ 4268 nIntlFormat = 8; // -1 $ 4269 break; 4270 case 6: // 1-$ 4271 nIntlFormat = 13; // 1- $ 4272 break; 4273 case 7: // 1$- 4274 nIntlFormat = 10; // 1 $- 4275 break; 4276 case 8: // -1 $ 4277 break; 4278 case 9: // -$ 1 4279 break; 4280 case 10: // 1 $- 4281 break; 4282 case 11: // $ -1 4283 break; 4284 case 12 : // $ 1- 4285 break; 4286 case 13 : // 1- $ 4287 break; 4288 case 14 : // ($ 1) 4289 // nIntlFormat = 14; // ($ 1) 4290 nIntlFormat = 9; // -$ 1 4291 break; 4292 case 15 : // (1 $) 4293 // nIntlFormat = 15; // (1 $) 4294 nIntlFormat = 8; // -1 $ 4295 break; 4296 default: 4297 DBG_ERROR("NfCurrencyEntry::GetEffectiveNegativeFormat: unknown option"); 4298 break; 4299 } 4300 #endif 4301 } 4302 else if ( nIntlFormat != nCurrFormat ) 4303 { 4304 switch ( nCurrFormat ) 4305 { 4306 case 0: // ($1) 4307 nIntlFormat = lcl_MergeNegativeParenthesisFormat( 4308 nIntlFormat, nCurrFormat ); 4309 break; 4310 case 1: // -$1 4311 nIntlFormat = nCurrFormat; 4312 break; 4313 case 2: // $-1 4314 nIntlFormat = nCurrFormat; 4315 break; 4316 case 3: // $1- 4317 nIntlFormat = nCurrFormat; 4318 break; 4319 case 4: // (1$) 4320 nIntlFormat = lcl_MergeNegativeParenthesisFormat( 4321 nIntlFormat, nCurrFormat ); 4322 break; 4323 case 5: // -1$ 4324 nIntlFormat = nCurrFormat; 4325 break; 4326 case 6: // 1-$ 4327 nIntlFormat = nCurrFormat; 4328 break; 4329 case 7: // 1$- 4330 nIntlFormat = nCurrFormat; 4331 break; 4332 case 8: // -1 $ 4333 nIntlFormat = nCurrFormat; 4334 break; 4335 case 9: // -$ 1 4336 nIntlFormat = nCurrFormat; 4337 break; 4338 case 10: // 1 $- 4339 nIntlFormat = nCurrFormat; 4340 break; 4341 case 11: // $ -1 4342 nIntlFormat = nCurrFormat; 4343 break; 4344 case 12 : // $ 1- 4345 nIntlFormat = nCurrFormat; 4346 break; 4347 case 13 : // 1- $ 4348 nIntlFormat = nCurrFormat; 4349 break; 4350 case 14 : // ($ 1) 4351 nIntlFormat = lcl_MergeNegativeParenthesisFormat( 4352 nIntlFormat, nCurrFormat ); 4353 break; 4354 case 15 : // (1 $) 4355 nIntlFormat = lcl_MergeNegativeParenthesisFormat( 4356 nIntlFormat, nCurrFormat ); 4357 break; 4358 default: 4359 DBG_ERROR("NfCurrencyEntry::GetEffectiveNegativeFormat: unknown option"); 4360 break; 4361 } 4362 } 4363 return nIntlFormat; 4364 } 4365 4366 4367 // we only support default encodings here 4368 // static 4369 sal_Char NfCurrencyEntry::GetEuroSymbol( rtl_TextEncoding eTextEncoding ) 4370 { 4371 switch ( eTextEncoding ) 4372 { 4373 case RTL_TEXTENCODING_MS_1252 : // WNT Ansi 4374 case RTL_TEXTENCODING_ISO_8859_1 : // UNX for use with TrueType fonts 4375 return '\x80'; 4376 case RTL_TEXTENCODING_ISO_8859_15 : // UNX real 4377 return '\xA4'; 4378 case RTL_TEXTENCODING_IBM_850 : // OS2 4379 return '\xD5'; 4380 case RTL_TEXTENCODING_APPLE_ROMAN : // MAC 4381 return '\xDB'; 4382 default: // default system 4383 #if WNT 4384 return '\x80'; 4385 #elif OS2 4386 return '\xD5'; 4387 #elif UNX 4388 // return '\xA4'; // #56121# 0xA4 waere korrekt fuer iso-8859-15 4389 return '\x80'; // aber Windoze-Code fuer die konvertierten TrueType-Fonts 4390 #else 4391 #error EuroSymbol is what? 4392 return '\x80'; 4393 #endif 4394 } 4395 return '\x80'; 4396 } 4397 4398 4399 4400