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