| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_svl.hxx" |
| #ifndef GCC |
| #endif |
| |
| // #include <math.h> |
| #include <tools/debug.hxx> |
| #include <unotools/charclass.hxx> |
| #include <i18npool/mslangid.hxx> |
| #include <unotools/localedatawrapper.hxx> |
| #include <unotools/numberformatcodewrapper.hxx> |
| #include <unotools/calendarwrapper.hxx> |
| #include <com/sun/star/i18n/KNumberFormatUsage.hpp> |
| #include <com/sun/star/i18n/KNumberFormatType.hpp> |
| #include <comphelper/processfactory.hxx> |
| #include <unotools/misccfg.hxx> |
| |
| #define _SVSTDARR_USHORTS |
| #include <svl/svstdarr.hxx> |
| |
| #define _ZFORLIST_CXX |
| #include <osl/mutex.hxx> |
| #include <svl/zforlist.hxx> |
| #undef _ZFORLIST_CXX |
| |
| #include "zforscan.hxx" |
| #include "zforfind.hxx" |
| #include <svl/zformat.hxx> |
| #include "numhead.hxx" |
| |
| #include <unotools/syslocaleoptions.hxx> |
| #include <unotools/digitgroupingiterator.hxx> |
| #include <rtl/logfile.hxx> |
| #include <rtl/instance.hxx> |
| |
| #include <math.h> |
| #include <limits> |
| |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::i18n; |
| using namespace ::com::sun::star::lang; |
| |
| |
| // Constants for type offsets per Country/Language (CL) |
| #define ZF_STANDARD 0 |
| #define ZF_STANDARD_PERCENT 10 |
| #define ZF_STANDARD_CURRENCY 20 |
| #define ZF_STANDARD_DATE 30 |
| #define ZF_STANDARD_TIME 40 |
| #define ZF_STANDARD_DATETIME 50 |
| #define ZF_STANDARD_SCIENTIFIC 60 |
| #define ZF_STANDARD_FRACTION 70 |
| #define ZF_STANDARD_NEWEXTENDED 75 |
| #define ZF_STANDARD_NEWEXTENDEDMAX SV_MAX_ANZ_STANDARD_FORMATE-2 // 98 |
| #define ZF_STANDARD_LOGICAL SV_MAX_ANZ_STANDARD_FORMATE-1 // 99 |
| #define ZF_STANDARD_TEXT SV_MAX_ANZ_STANDARD_FORMATE // 100 |
| |
| /* Locale that is set if an unknown locale (from another system) is loaded of |
| * legacy documents. Can not be SYSTEM because else, for example, a German "DM" |
| * (old currency) is recognized as a date (#53155#). */ |
| #define UNKNOWN_SUBSTITUTE LANGUAGE_ENGLISH_US |
| |
| static sal_Bool bIndexTableInitialized = sal_False; |
| static sal_uInt32 __FAR_DATA theIndexTable[NF_INDEX_TABLE_ENTRIES]; |
| |
| |
| // ==================================================================== |
| |
| /** |
| instead of every number formatter being a listener we have a registry which |
| also handles one instance of the SysLocale options |
| */ |
| |
| class SvNumberFormatterRegistry_Impl : public utl::ConfigurationListener |
| { |
| List aFormatters; |
| SvtSysLocaleOptions aSysLocaleOptions; |
| LanguageType eSysLanguage; |
| |
| public: |
| SvNumberFormatterRegistry_Impl(); |
| virtual ~SvNumberFormatterRegistry_Impl(); |
| |
| void Insert( SvNumberFormatter* pThis ) |
| { aFormatters.Insert( pThis, LIST_APPEND ); } |
| SvNumberFormatter* Remove( SvNumberFormatter* pThis ) |
| { return (SvNumberFormatter*)aFormatters.Remove( pThis ); } |
| sal_uInt32 Count() |
| { return aFormatters.Count(); } |
| |
| virtual void ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 ); |
| }; |
| |
| |
| SvNumberFormatterRegistry_Impl::SvNumberFormatterRegistry_Impl() |
| { |
| eSysLanguage = MsLangId::getRealLanguage( LANGUAGE_SYSTEM ); |
| aSysLocaleOptions.AddListener( this ); |
| } |
| |
| |
| SvNumberFormatterRegistry_Impl::~SvNumberFormatterRegistry_Impl() |
| { |
| aSysLocaleOptions.RemoveListener( this ); |
| } |
| |
| |
| void SvNumberFormatterRegistry_Impl::ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 nHint ) |
| { |
| if ( nHint & SYSLOCALEOPTIONS_HINT_LOCALE ) |
| { |
| ::osl::MutexGuard aGuard( SvNumberFormatter::GetMutex() ); |
| for ( SvNumberFormatter* p = (SvNumberFormatter*)aFormatters.First(); |
| p; p = (SvNumberFormatter*)aFormatters.Next() ) |
| { |
| p->ReplaceSystemCL( eSysLanguage ); |
| } |
| eSysLanguage = MsLangId::getRealLanguage( LANGUAGE_SYSTEM ); |
| } |
| if ( nHint & SYSLOCALEOPTIONS_HINT_CURRENCY ) |
| { |
| ::osl::MutexGuard aGuard( SvNumberFormatter::GetMutex() ); |
| for ( SvNumberFormatter* p = (SvNumberFormatter*)aFormatters.First(); |
| p; p = (SvNumberFormatter*)aFormatters.Next() ) |
| { |
| p->ResetDefaultSystemCurrency(); |
| } |
| } |
| } |
| |
| |
| // ==================================================================== |
| |
| SvNumberFormatterRegistry_Impl* SvNumberFormatter::pFormatterRegistry = NULL; |
| sal_Bool SvNumberFormatter::bCurrencyTableInitialized = sal_False; |
| namespace |
| { |
| struct theCurrencyTable : |
| public rtl::Static< NfCurrencyTable, theCurrencyTable > {}; |
| |
| struct theLegacyOnlyCurrencyTable : |
| public rtl::Static< NfCurrencyTable, theLegacyOnlyCurrencyTable > {}; |
| } |
| sal_uInt16 SvNumberFormatter::nSystemCurrencyPosition = 0; |
| SV_IMPL_PTRARR( NfCurrencyTable, NfCurrencyEntry* ); |
| SV_IMPL_PTRARR( NfWSStringsDtor, String* ); |
| |
| // ob das BankSymbol immer am Ende ist (1 $;-1 $) oder sprachabhaengig |
| #define NF_BANKSYMBOL_FIX_POSITION 1 |
| |
| |
| /***********************Funktionen SvNumberFormatter**************************/ |
| |
| const sal_uInt16 SvNumberFormatter::UNLIMITED_PRECISION = ::std::numeric_limits<sal_uInt16>::max(); |
| const sal_uInt16 SvNumberFormatter::INPUTSTRING_PRECISION = ::std::numeric_limits<sal_uInt16>::max()-1; |
| |
| SvNumberFormatter::SvNumberFormatter( |
| const Reference< XMultiServiceFactory >& xSMgr, |
| LanguageType eLang ) |
| : |
| xServiceManager( xSMgr ) |
| { |
| ImpConstruct( eLang ); |
| } |
| |
| |
| SvNumberFormatter::SvNumberFormatter( LanguageType eLang ) |
| { |
| ImpConstruct( eLang ); |
| } |
| |
| |
| SvNumberFormatter::~SvNumberFormatter() |
| { |
| { |
| ::osl::MutexGuard aGuard( GetMutex() ); |
| pFormatterRegistry->Remove( this ); |
| if ( !pFormatterRegistry->Count() ) |
| { |
| delete pFormatterRegistry; |
| pFormatterRegistry = NULL; |
| } |
| } |
| |
| SvNumberformat* pEntry = aFTable.First(); |
| while (pEntry) |
| { |
| delete pEntry; |
| pEntry = aFTable.Next(); |
| } |
| delete pFormatTable; |
| delete pCharClass; |
| delete pStringScanner; |
| delete pFormatScanner; |
| ClearMergeTable(); |
| delete pMergeTable; |
| } |
| |
| |
| void SvNumberFormatter::ImpConstruct( LanguageType eLang ) |
| { |
| RTL_LOGFILE_CONTEXT_AUTHOR( aTimeLog, "svl", "er93726", "SvNumberFormatter::ImpConstruct" ); |
| |
| if ( eLang == LANGUAGE_DONTKNOW ) |
| eLang = UNKNOWN_SUBSTITUTE; |
| IniLnge = eLang; |
| ActLnge = eLang; |
| eEvalDateFormat = NF_EVALDATEFORMAT_INTL; |
| nDefaultSystemCurrencyFormat = NUMBERFORMAT_ENTRY_NOT_FOUND; |
| |
| aLocale = MsLangId::convertLanguageToLocale( eLang ); |
| pCharClass = new CharClass( xServiceManager, aLocale ); |
| xLocaleData.init( xServiceManager, aLocale, eLang ); |
| xCalendar.init( xServiceManager, aLocale ); |
| xTransliteration.init( xServiceManager, eLang, |
| ::com::sun::star::i18n::TransliterationModules_IGNORE_CASE ); |
| xNatNum.init( xServiceManager ); |
| |
| // cached locale data items |
| const LocaleDataWrapper* pLoc = GetLocaleData(); |
| aDecimalSep = pLoc->getNumDecimalSep(); |
| aThousandSep = pLoc->getNumThousandSep(); |
| aDateSep = pLoc->getDateSep(); |
| |
| pStringScanner = new ImpSvNumberInputScan( this ); |
| pFormatScanner = new ImpSvNumberformatScan( this ); |
| pFormatTable = NULL; |
| MaxCLOffset = 0; |
| ImpGenerateFormats( 0, sal_False ); // 0 .. 999 for initialized language formats |
| pMergeTable = NULL; |
| bNoZero = sal_False; |
| |
| ::osl::MutexGuard aGuard( GetMutex() ); |
| GetFormatterRegistry().Insert( this ); |
| } |
| |
| |
| void SvNumberFormatter::ChangeIntl(LanguageType eLnge) |
| { |
| if (ActLnge != eLnge) |
| { |
| ActLnge = eLnge; |
| |
| aLocale = MsLangId::convertLanguageToLocale( eLnge ); |
| pCharClass->setLocale( aLocale ); |
| xLocaleData.changeLocale( aLocale, eLnge ); |
| xCalendar.changeLocale( aLocale ); |
| xTransliteration.changeLocale( eLnge ); |
| |
| // cached locale data items, initialize BEFORE calling ChangeIntl below |
| const LocaleDataWrapper* pLoc = GetLocaleData(); |
| aDecimalSep = pLoc->getNumDecimalSep(); |
| aThousandSep = pLoc->getNumThousandSep(); |
| aDateSep = pLoc->getDateSep(); |
| |
| pFormatScanner->ChangeIntl(); |
| pStringScanner->ChangeIntl(); |
| } |
| } |
| |
| |
| // static |
| ::osl::Mutex& SvNumberFormatter::GetMutex() |
| { |
| static ::osl::Mutex* pMutex = NULL; |
| if( !pMutex ) |
| { |
| ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); |
| if( !pMutex ) |
| { |
| // #i77768# Due to a static reference in the toolkit lib |
| // we need a mutex that lives longer than the svl library. |
| // Otherwise the dtor would use a destructed mutex!! |
| pMutex = new ::osl::Mutex; |
| } |
| } |
| return *pMutex; |
| } |
| |
| |
| // static |
| SvNumberFormatterRegistry_Impl& SvNumberFormatter::GetFormatterRegistry() |
| { |
| ::osl::MutexGuard aGuard( GetMutex() ); |
| if ( !pFormatterRegistry ) |
| pFormatterRegistry = new SvNumberFormatterRegistry_Impl; |
| return *pFormatterRegistry; |
| } |
| |
| |
| Color* SvNumberFormatter::GetUserDefColor(sal_uInt16 nIndex) |
| { |
| if( aColorLink.IsSet() ) |
| return (Color*) ( aColorLink.Call( (void*) &nIndex )); |
| else |
| return NULL; |
| } |
| |
| void SvNumberFormatter::ChangeNullDate(sal_uInt16 nDay, |
| sal_uInt16 nMonth, |
| sal_uInt16 nYear) |
| { |
| pFormatScanner->ChangeNullDate(nDay, nMonth, nYear); |
| pStringScanner->ChangeNullDate(nDay, nMonth, nYear); |
| } |
| |
| Date* SvNumberFormatter::GetNullDate() |
| { |
| return pFormatScanner->GetNullDate(); |
| } |
| |
| void SvNumberFormatter::ChangeStandardPrec(short nPrec) |
| { |
| pFormatScanner->ChangeStandardPrec(nPrec); |
| } |
| |
| sal_uInt16 SvNumberFormatter::GetStandardPrec() |
| { |
| return pFormatScanner->GetStandardPrec(); |
| } |
| |
| void SvNumberFormatter::ImpChangeSysCL( LanguageType eLnge, sal_Bool bLoadingSO5 ) |
| { |
| if (eLnge == LANGUAGE_DONTKNOW) |
| eLnge = UNKNOWN_SUBSTITUTE; |
| if (eLnge != IniLnge) |
| { |
| IniLnge = eLnge; |
| ChangeIntl(eLnge); |
| SvNumberformat* pEntry = aFTable.First(); |
| while (pEntry) // delete old formats |
| { |
| pEntry = (SvNumberformat*) aFTable.Remove(aFTable.GetCurKey()); |
| delete pEntry; |
| pEntry = (SvNumberformat*) aFTable.First(); |
| } |
| ImpGenerateFormats( 0, bLoadingSO5 ); // new standard formats |
| } |
| else if ( bLoadingSO5 ) |
| { // delete additional standard formats |
| sal_uInt32 nKey; |
| aFTable.Seek( SV_MAX_ANZ_STANDARD_FORMATE + 1 ); |
| while ( (nKey = aFTable.GetCurKey()) > SV_MAX_ANZ_STANDARD_FORMATE && |
| nKey < SV_COUNTRY_LANGUAGE_OFFSET ) |
| { |
| SvNumberformat* pEntry = (SvNumberformat*) aFTable.Remove( nKey ); |
| delete pEntry; |
| } |
| } |
| } |
| |
| |
| void SvNumberFormatter::ReplaceSystemCL( LanguageType eOldLanguage ) |
| { |
| sal_uInt32 nCLOffset = ImpGetCLOffset( LANGUAGE_SYSTEM ); |
| if ( nCLOffset > MaxCLOffset ) |
| return ; // no SYSTEM entries to replace |
| |
| const sal_uInt32 nMaxBuiltin = nCLOffset + SV_MAX_ANZ_STANDARD_FORMATE; |
| const sal_uInt32 nNextCL = nCLOffset + SV_COUNTRY_LANGUAGE_OFFSET; |
| sal_uInt32 nKey; |
| |
| // remove old builtin formats |
| aFTable.Seek( nCLOffset ); |
| while ( (nKey = aFTable.GetCurKey()) >= nCLOffset && nKey <= nMaxBuiltin && aFTable.Count() ) |
| { |
| SvNumberformat* pEntry = (SvNumberformat*) aFTable.Remove( nKey ); |
| delete pEntry; |
| } |
| |
| // move additional and user defined to temporary table |
| Table aOldTable; |
| while ( (nKey = aFTable.GetCurKey()) >= nCLOffset && nKey < nNextCL && aFTable.Count() ) |
| { |
| SvNumberformat* pEntry = (SvNumberformat*) aFTable.Remove( nKey ); |
| aOldTable.Insert( nKey, pEntry ); |
| } |
| |
| // generate new old builtin formats |
| // reset ActLnge otherwise ChangeIntl() wouldn't switch if already LANGUAGE_SYSTEM |
| ActLnge = LANGUAGE_DONTKNOW; |
| ChangeIntl( LANGUAGE_SYSTEM ); |
| ImpGenerateFormats( nCLOffset, sal_True ); |
| |
| // convert additional and user defined from old system to new system |
| SvNumberformat* pStdFormat = (SvNumberformat*) aFTable.Get( nCLOffset + ZF_STANDARD ); |
| sal_uInt32 nLastKey = nMaxBuiltin; |
| pFormatScanner->SetConvertMode( eOldLanguage, LANGUAGE_SYSTEM, sal_True ); |
| aOldTable.First(); |
| while ( aOldTable.Count() ) |
| { |
| nKey = aOldTable.GetCurKey(); |
| if ( nLastKey < nKey ) |
| nLastKey = nKey; |
| SvNumberformat* pOldEntry = (SvNumberformat*) aOldTable.Remove( nKey ); |
| String aString( pOldEntry->GetFormatstring() ); |
| xub_StrLen nCheckPos = STRING_NOTFOUND; |
| |
| // Same as PutEntry() but assures key position even if format code is |
| // a duplicate. Also won't mix up any LastInsertKey. |
| ChangeIntl( eOldLanguage ); |
| LanguageType eLge = eOldLanguage; // ConvertMode changes this |
| sal_Bool bCheck = sal_False; |
| SvNumberformat* pNewEntry = new SvNumberformat( aString, pFormatScanner, |
| pStringScanner, nCheckPos, eLge ); |
| if ( nCheckPos != 0 ) |
| delete pNewEntry; |
| else |
| { |
| short eCheckType = pNewEntry->GetType(); |
| if ( eCheckType != NUMBERFORMAT_UNDEFINED ) |
| pNewEntry->SetType( eCheckType | NUMBERFORMAT_DEFINED ); |
| else |
| pNewEntry->SetType( NUMBERFORMAT_DEFINED ); |
| |
| if ( !aFTable.Insert( nKey, pNewEntry ) ) |
| delete pNewEntry; |
| else |
| bCheck = sal_True; |
| } |
| DBG_ASSERT( bCheck, "SvNumberFormatter::ReplaceSystemCL: couldn't convert" ); |
| |
| delete pOldEntry; |
| } |
| pFormatScanner->SetConvertMode(sal_False); |
| pStdFormat->SetLastInsertKey( sal_uInt16(nLastKey - nCLOffset) ); |
| |
| // append new system additional formats |
| NumberFormatCodeWrapper aNumberFormatCode( xServiceManager, GetLocale() ); |
| ImpGenerateAdditionalFormats( nCLOffset, aNumberFormatCode, sal_True ); |
| } |
| |
| |
| sal_Bool SvNumberFormatter::IsTextFormat(sal_uInt32 F_Index) const |
| { |
| SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(F_Index); |
| if (!pFormat) |
| return sal_False; |
| else |
| return pFormat->IsTextFormat(); |
| } |
| |
| sal_Bool SvNumberFormatter::HasTextFormat(sal_uInt32 F_Index) const |
| { |
| SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(F_Index); |
| if (!pFormat) |
| return sal_False; |
| else |
| return pFormat->HasTextFormat(); |
| } |
| |
| sal_Bool SvNumberFormatter::PutEntry(String& rString, |
| xub_StrLen& nCheckPos, |
| short& nType, |
| sal_uInt32& nKey, // Formatnummer |
| LanguageType eLnge) |
| { |
| nKey = 0; |
| if (rString.Len() == 0) // keinen Leerstring |
| { |
| nCheckPos = 1; // -> Fehler |
| return sal_False; |
| } |
| if (eLnge == LANGUAGE_DONTKNOW) |
| eLnge = IniLnge; |
| |
| ChangeIntl(eLnge); // ggfs. austauschen |
| LanguageType eLge = eLnge; // Umgehung const fuer ConvertMode |
| sal_Bool bCheck = sal_False; |
| SvNumberformat* p_Entry = new SvNumberformat(rString, |
| pFormatScanner, |
| pStringScanner, |
| nCheckPos, |
| eLge); |
| if (nCheckPos == 0) // Format ok |
| { // Typvergleich: |
| short eCheckType = p_Entry->GetType(); |
| if ( eCheckType != NUMBERFORMAT_UNDEFINED) |
| { |
| p_Entry->SetType(eCheckType | NUMBERFORMAT_DEFINED); |
| nType = eCheckType; |
| } |
| else |
| { |
| p_Entry->SetType(NUMBERFORMAT_DEFINED); |
| nType = NUMBERFORMAT_DEFINED; |
| } |
| sal_uInt32 CLOffset = ImpGenerateCL(eLge); // ggfs. neu Standard- |
| // formate anlegen |
| nKey = ImpIsEntry(p_Entry->GetFormatstring(),CLOffset, eLge); |
| if (nKey != NUMBERFORMAT_ENTRY_NOT_FOUND) // schon vorhanden |
| delete p_Entry; |
| else |
| { |
| SvNumberformat* pStdFormat = |
| (SvNumberformat*) aFTable.Get(CLOffset + ZF_STANDARD); |
| sal_uInt32 nPos = CLOffset + pStdFormat->GetLastInsertKey(); |
| if (nPos - CLOffset >= SV_COUNTRY_LANGUAGE_OFFSET) |
| { |
| DBG_ERROR("SvNumberFormatter:: Zu viele Formate pro CL"); |
| delete p_Entry; |
| } |
| else if (!aFTable.Insert(nPos+1,p_Entry)) |
| delete p_Entry; |
| else |
| { |
| bCheck = sal_True; |
| nKey = nPos+1; |
| pStdFormat->SetLastInsertKey((sal_uInt16) (nKey-CLOffset)); |
| } |
| } |
| } |
| else |
| delete p_Entry; |
| return bCheck; |
| } |
| |
| sal_Bool SvNumberFormatter::PutandConvertEntry(String& rString, |
| xub_StrLen& nCheckPos, |
| short& nType, |
| sal_uInt32& nKey, |
| LanguageType eLnge, |
| LanguageType eNewLnge) |
| { |
| sal_Bool bRes; |
| if (eNewLnge == LANGUAGE_DONTKNOW) |
| eNewLnge = IniLnge; |
| |
| pFormatScanner->SetConvertMode(eLnge, eNewLnge); |
| bRes = PutEntry(rString, nCheckPos, nType, nKey, eLnge); |
| pFormatScanner->SetConvertMode(sal_False); |
| return bRes; |
| } |
| |
| |
| sal_Bool SvNumberFormatter::PutandConvertEntrySystem(String& rString, |
| xub_StrLen& nCheckPos, |
| short& nType, |
| sal_uInt32& nKey, |
| LanguageType eLnge, |
| LanguageType eNewLnge) |
| { |
| sal_Bool bRes; |
| if (eNewLnge == LANGUAGE_DONTKNOW) |
| eNewLnge = IniLnge; |
| |
| pFormatScanner->SetConvertMode(eLnge, eNewLnge, sal_True); |
| bRes = PutEntry(rString, nCheckPos, nType, nKey, eLnge); |
| pFormatScanner->SetConvertMode(sal_False); |
| return bRes; |
| } |
| |
| |
| sal_uInt32 SvNumberFormatter::GetIndexPuttingAndConverting( String & rString, |
| LanguageType eLnge, LanguageType eSysLnge, short & rType, |
| sal_Bool & rNewInserted, xub_StrLen & rCheckPos ) |
| { |
| sal_uInt32 nKey = NUMBERFORMAT_ENTRY_NOT_FOUND; |
| rNewInserted = sal_False; |
| rCheckPos = 0; |
| |
| // #62389# empty format string (of Writer) => General standard format |
| if (!rString.Len()) |
| ; // nothing |
| else if (eLnge == LANGUAGE_SYSTEM && eSysLnge != SvtSysLocale().GetLanguage()) |
| { |
| sal_uInt32 nOrig = GetEntryKey( rString, eSysLnge ); |
| if (nOrig == NUMBERFORMAT_ENTRY_NOT_FOUND) |
| nKey = nOrig; // none avaliable, maybe user-defined |
| else |
| nKey = GetFormatForLanguageIfBuiltIn( nOrig, SvtSysLocale().GetLanguage() ); |
| |
| if (nKey == nOrig) |
| { |
| // Not a builtin format, convert. |
| // The format code string may get modified and adapted to the real |
| // language and wouldn't match eSysLnge anymore, do that on a copy. |
| String aTmp( rString); |
| rNewInserted = PutandConvertEntrySystem( aTmp, rCheckPos, rType, |
| nKey, eLnge, SvtSysLocale().GetLanguage()); |
| if (rCheckPos > 0) |
| { |
| DBG_ERRORFILE("SvNumberFormatter::GetIndexPuttingAndConverting: bad format code string for current locale"); |
| nKey = NUMBERFORMAT_ENTRY_NOT_FOUND; |
| } |
| } |
| } |
| else |
| { |
| nKey = GetEntryKey( rString, eLnge); |
| if (nKey == NUMBERFORMAT_ENTRY_NOT_FOUND) |
| { |
| rNewInserted = PutEntry( rString, rCheckPos, rType, nKey, eLnge); |
| if (rCheckPos > 0) |
| { |
| DBG_ERRORFILE("SvNumberFormatter::GetIndexPuttingAndConverting: bad format code string for specified locale"); |
| nKey = NUMBERFORMAT_ENTRY_NOT_FOUND; |
| } |
| } |
| } |
| if (nKey == NUMBERFORMAT_ENTRY_NOT_FOUND) |
| nKey = GetStandardIndex( eLnge); |
| rType = GetType( nKey); |
| // Convert any (!) old "automatic" currency format to new fixed currency |
| // default format. |
| if ((rType & NUMBERFORMAT_CURRENCY) != 0) |
| { |
| const SvNumberformat* pFormat = GetEntry( nKey); |
| if (!pFormat->HasNewCurrency()) |
| { |
| if (rNewInserted) |
| { |
| DeleteEntry( nKey); // don't leave trails of rubbish |
| rNewInserted = sal_False; |
| } |
| nKey = GetStandardFormat( NUMBERFORMAT_CURRENCY, eLnge); |
| } |
| } |
| return nKey; |
| } |
| |
| |
| void SvNumberFormatter::DeleteEntry(sal_uInt32 nKey) |
| { |
| SvNumberformat* pEntry = aFTable.Remove(nKey); |
| delete pEntry; |
| } |
| |
| void SvNumberFormatter::PrepareSave() |
| { |
| SvNumberformat* pFormat = aFTable.First(); |
| while (pFormat) |
| { |
| pFormat->SetUsed(sal_False); |
| pFormat = aFTable.Next(); |
| } |
| } |
| |
| void SvNumberFormatter::SetFormatUsed(sal_uInt32 nFIndex) |
| { |
| SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(nFIndex); |
| if (pFormat) |
| pFormat->SetUsed(sal_True); |
| } |
| |
| sal_Bool SvNumberFormatter::Load( SvStream& rStream ) |
| { |
| LanguageType eSysLang = SvtSysLocale().GetLanguage(); |
| SvNumberFormatter* pConverter = NULL; |
| |
| ImpSvNumMultipleReadHeader aHdr( rStream ); |
| sal_uInt16 nVersion; |
| rStream >> nVersion; |
| SvNumberformat* pEntry; |
| sal_uInt32 nPos; |
| LanguageType eSaveSysLang, eLoadSysLang; |
| sal_uInt16 nSysOnStore, eLge, eDummy; // Dummy fuer kompatibles Format |
| rStream >> nSysOnStore >> eLge; // Systemeinstellung aus |
| // Dokument |
| eSaveSysLang = (nVersion < SV_NUMBERFORMATTER_VERSION_SYSTORE ? |
| LANGUAGE_SYSTEM : (LanguageType) nSysOnStore); |
| LanguageType eLnge = (LanguageType) eLge; |
| ImpChangeSysCL( eLnge, sal_True ); |
| |
| rStream >> nPos; |
| while (nPos != NUMBERFORMAT_ENTRY_NOT_FOUND) |
| { |
| rStream >> eDummy >> eLge; |
| eLnge = (LanguageType) eLge; |
| ImpGenerateCL( eLnge, sal_True ); // ggfs. neue Standardformate anlegen |
| |
| sal_uInt32 nOffset = nPos % SV_COUNTRY_LANGUAGE_OFFSET; // relativIndex |
| sal_Bool bUserDefined = (nOffset > SV_MAX_ANZ_STANDARD_FORMATE); |
| //! HACK! ER 29.07.97 15:15 |
| // SaveLang wurde bei SYSTEM nicht gespeichert sondern war auch SYSTEM, |
| // erst ab 364i Unterscheidung moeglich |
| sal_Bool bConversionHack; |
| if ( eLnge == LANGUAGE_SYSTEM ) |
| { |
| if ( nVersion < SV_NUMBERFORMATTER_VERSION_SYSTORE ) |
| { |
| bConversionHack = bUserDefined; |
| eLoadSysLang = eSaveSysLang; |
| } |
| else |
| { |
| bConversionHack = sal_False; |
| eLoadSysLang = eSysLang; |
| } |
| } |
| else |
| { |
| bConversionHack = sal_False; |
| eLoadSysLang = eSaveSysLang; |
| } |
| |
| pEntry = new SvNumberformat(*pFormatScanner, eLnge); |
| if ( bConversionHack ) |
| { // SYSTEM |
| // nVersion < SV_NUMBERFORMATTER_VERSION_SYSTORE |
| // nVersion < SV_NUMBERFORMATTER_VERSION_KEYWORDS |
| if ( !pConverter ) |
| pConverter = new SvNumberFormatter( xServiceManager, eSysLang ); |
| NfHackConversion eHackConversion = pEntry->Load( |
| rStream, aHdr, pConverter, *pStringScanner ); |
| switch ( eHackConversion ) |
| { |
| case NF_CONVERT_GERMAN_ENGLISH : |
| pEntry->ConvertLanguage( *pConverter, |
| LANGUAGE_ENGLISH_US, eSysLang, sal_True ); |
| break; |
| case NF_CONVERT_ENGLISH_GERMAN : |
| switch ( eSysLang ) |
| { |
| case LANGUAGE_GERMAN: |
| case LANGUAGE_GERMAN_SWISS: |
| case LANGUAGE_GERMAN_AUSTRIAN: |
| case LANGUAGE_GERMAN_LUXEMBOURG: |
| case LANGUAGE_GERMAN_LIECHTENSTEIN: |
| // alles beim alten |
| break; |
| default: |
| pEntry->ConvertLanguage( *pConverter, |
| LANGUAGE_GERMAN, eSysLang, sal_True ); |
| } |
| break; |
| case NF_CONVERT_NONE : |
| break; // -Wall not handled. |
| } |
| |
| } |
| else |
| { |
| pEntry->Load( rStream, aHdr, NULL, *pStringScanner ); |
| if ( !bUserDefined ) |
| bUserDefined = (pEntry->GetNewStandardDefined() > SV_NUMBERFORMATTER_VERSION); |
| if ( bUserDefined ) |
| { |
| if ( eSaveSysLang != eLoadSysLang ) |
| { // SYSTEM verschieden |
| if ( !pConverter ) |
| pConverter = new SvNumberFormatter( xServiceManager, eSysLang ); |
| if ( nVersion < SV_NUMBERFORMATTER_VERSION_KEYWORDS ) |
| { |
| switch ( eSaveSysLang ) |
| { |
| case LANGUAGE_GERMAN: |
| case LANGUAGE_GERMAN_SWISS: |
| case LANGUAGE_GERMAN_AUSTRIAN: |
| case LANGUAGE_GERMAN_LUXEMBOURG: |
| case LANGUAGE_GERMAN_LIECHTENSTEIN: |
| // alles beim alten |
| pEntry->ConvertLanguage( *pConverter, |
| eSaveSysLang, eLoadSysLang, sal_True ); |
| break; |
| default: |
| // alte english nach neuem anderen |
| pEntry->ConvertLanguage( *pConverter, |
| LANGUAGE_ENGLISH_US, eLoadSysLang, sal_True ); |
| } |
| } |
| else |
| pEntry->ConvertLanguage( *pConverter, |
| eSaveSysLang, eLoadSysLang, sal_True ); |
| } |
| else |
| { // nicht SYSTEM oder gleiches SYSTEM |
| if ( nVersion < SV_NUMBERFORMATTER_VERSION_KEYWORDS ) |
| { |
| LanguageType eLoadLang; |
| sal_Bool bSystem; |
| if ( eLnge == LANGUAGE_SYSTEM ) |
| { |
| eLoadLang = eSysLang; |
| bSystem = sal_True; |
| } |
| else |
| { |
| eLoadLang = eLnge; |
| bSystem = sal_False; |
| } |
| switch ( eLoadLang ) |
| { |
| case LANGUAGE_GERMAN: |
| case LANGUAGE_GERMAN_SWISS: |
| case LANGUAGE_GERMAN_AUSTRIAN: |
| case LANGUAGE_GERMAN_LUXEMBOURG: |
| case LANGUAGE_GERMAN_LIECHTENSTEIN: |
| // alles beim alten |
| break; |
| default: |
| // alte english nach neuem anderen |
| if ( !pConverter ) |
| pConverter = new SvNumberFormatter( xServiceManager, eSysLang ); |
| pEntry->ConvertLanguage( *pConverter, |
| LANGUAGE_ENGLISH_US, eLoadLang, bSystem ); |
| } |
| } |
| } |
| } |
| } |
| if ( nOffset == 0 ) // StandardFormat |
| { |
| SvNumberformat* pEnt = aFTable.Get(nPos); |
| if (pEnt) |
| pEnt->SetLastInsertKey(pEntry->GetLastInsertKey()); |
| } |
| if (!aFTable.Insert(nPos, pEntry)) |
| delete pEntry; |
| rStream >> nPos; |
| } |
| |
| // ab SV_NUMBERFORMATTER_VERSION_YEAR2000 |
| if ( nVersion >= SV_NUMBERFORMATTER_VERSION_YEAR2000 ) |
| { |
| aHdr.StartEntry(); |
| if ( aHdr.BytesLeft() >= sizeof(sal_uInt16) ) |
| { |
| sal_uInt16 nY2k; |
| rStream >> nY2k; |
| if ( nVersion < SV_NUMBERFORMATTER_VERSION_TWODIGITYEAR && nY2k < 100 ) |
| nY2k += 1901; // war vor src513e: 29, jetzt: 1930 |
| SetYear2000( nY2k ); |
| } |
| aHdr.EndEntry(); |
| } |
| |
| if ( pConverter ) |
| delete pConverter; |
| |
| // generate additional i18n standard formats for all used locales |
| LanguageType eOldLanguage = ActLnge; |
| NumberFormatCodeWrapper aNumberFormatCode( xServiceManager, GetLocale() ); |
| SvUShorts aList; |
| GetUsedLanguages( aList ); |
| sal_uInt16 nCount = aList.Count(); |
| for ( sal_uInt16 j=0; j<nCount; j++ ) |
| { |
| LanguageType eLang = aList[j]; |
| ChangeIntl( eLang ); |
| sal_uInt32 CLOffset = ImpGetCLOffset( eLang ); |
| ImpGenerateAdditionalFormats( CLOffset, aNumberFormatCode, sal_True ); |
| } |
| ChangeIntl( eOldLanguage ); |
| |
| if (rStream.GetError()) |
| return sal_False; |
| else |
| return sal_True; |
| } |
| |
| sal_Bool SvNumberFormatter::Save( SvStream& rStream ) const |
| { |
| ImpSvNumMultipleWriteHeader aHdr( rStream ); |
| // ab 364i wird gespeichert was SYSTEM wirklich war, vorher hart LANGUAGE_SYSTEM |
| rStream << (sal_uInt16) SV_NUMBERFORMATTER_VERSION; |
| rStream << (sal_uInt16) SvtSysLocale().GetLanguage() << (sal_uInt16) IniLnge; |
| SvNumberFormatTable* pTable = (SvNumberFormatTable*) &aFTable; |
| SvNumberformat* pEntry = (SvNumberformat*) pTable->First(); |
| while (pEntry) |
| { |
| // Gespeichert werden alle markierten, benutzerdefinierten Formate und |
| // jeweils das Standardformat zu allen angewaehlten CL-Kombinationen |
| // sowie NewStandardDefined |
| if ( pEntry->GetUsed() || (pEntry->GetType() & NUMBERFORMAT_DEFINED) || |
| pEntry->GetNewStandardDefined() || |
| (pTable->GetCurKey() % SV_COUNTRY_LANGUAGE_OFFSET == 0) ) |
| { |
| rStream << static_cast<sal_uInt32>(pTable->GetCurKey()) |
| << (sal_uInt16) LANGUAGE_SYSTEM |
| << (sal_uInt16) pEntry->GetLanguage(); |
| pEntry->Save(rStream, aHdr); |
| } |
| pEntry = (SvNumberformat*) pTable->Next(); |
| } |
| rStream << NUMBERFORMAT_ENTRY_NOT_FOUND; // EndeKennung |
| |
| // ab SV_NUMBERFORMATTER_VERSION_YEAR2000 |
| aHdr.StartEntry(); |
| rStream << (sal_uInt16) GetYear2000(); |
| aHdr.EndEntry(); |
| |
| if (rStream.GetError()) |
| return sal_False; |
| else |
| return sal_True; |
| } |
| |
| // static |
| void SvNumberFormatter::SkipNumberFormatterInStream( SvStream& rStream ) |
| { |
| ImpSvNumMultipleReadHeader::Skip( rStream ); |
| } |
| |
| void SvNumberFormatter::GetUsedLanguages( SvUShorts& rList ) |
| { |
| rList.Remove( 0, rList.Count() ); |
| |
| sal_uInt32 nOffset = 0; |
| while (nOffset <= MaxCLOffset) |
| { |
| SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(nOffset); |
| if (pFormat) |
| rList.Insert( pFormat->GetLanguage(), rList.Count() ); |
| nOffset += SV_COUNTRY_LANGUAGE_OFFSET; |
| } |
| } |
| |
| |
| void SvNumberFormatter::FillKeywordTable( NfKeywordTable& rKeywords, |
| LanguageType eLang ) |
| { |
| ChangeIntl( eLang ); |
| const NfKeywordTable & rTable = pFormatScanner->GetKeywords(); |
| for ( sal_uInt16 i = 0; i < NF_KEYWORD_ENTRIES_COUNT; ++i ) |
| { |
| rKeywords[i] = rTable[i]; |
| } |
| } |
| |
| |
| String SvNumberFormatter::GetKeyword( LanguageType eLnge, sal_uInt16 nIndex ) |
| { |
| ChangeIntl(eLnge); |
| const NfKeywordTable & rTable = pFormatScanner->GetKeywords(); |
| if ( nIndex < NF_KEYWORD_ENTRIES_COUNT ) |
| return rTable[nIndex]; |
| |
| DBG_ERROR("GetKeyword: invalid index"); |
| return String(); |
| } |
| |
| |
| String SvNumberFormatter::GetStandardName( LanguageType eLnge ) |
| { |
| ChangeIntl( eLnge ); |
| return pFormatScanner->GetStandardName(); |
| } |
| |
| |
| sal_uInt32 SvNumberFormatter::ImpGetCLOffset(LanguageType eLnge) const |
| { |
| SvNumberformat* pFormat; |
| sal_uInt32 nOffset = 0; |
| while (nOffset <= MaxCLOffset) |
| { |
| pFormat = (SvNumberformat*) aFTable.Get(nOffset); |
| if (pFormat && pFormat->GetLanguage() == eLnge) |
| return nOffset; |
| nOffset += SV_COUNTRY_LANGUAGE_OFFSET; |
| } |
| return nOffset; |
| } |
| |
| sal_uInt32 SvNumberFormatter::ImpIsEntry(const String& rString, |
| sal_uInt32 nCLOffset, |
| LanguageType eLnge) |
| { |
| #ifndef NF_COMMENT_IN_FORMATSTRING |
| #error NF_COMMENT_IN_FORMATSTRING not defined (zformat.hxx) |
| #endif |
| #if NF_COMMENT_IN_FORMATSTRING |
| String aStr( rString ); |
| SvNumberformat::EraseComment( aStr ); |
| #endif |
| sal_uInt32 res = NUMBERFORMAT_ENTRY_NOT_FOUND; |
| SvNumberformat* pEntry; |
| pEntry = (SvNumberformat*) aFTable.Seek(nCLOffset); |
| while ( res == NUMBERFORMAT_ENTRY_NOT_FOUND && |
| pEntry && pEntry->GetLanguage() == eLnge ) |
| { |
| #if NF_COMMENT_IN_FORMATSTRING |
| if ( pEntry->GetComment().Len() ) |
| { |
| String aFormat( pEntry->GetFormatstring() ); |
| SvNumberformat::EraseComment( aFormat ); |
| if ( aStr == aFormat ) |
| res = aFTable.GetCurKey(); |
| else |
| pEntry = (SvNumberformat*) aFTable.Next(); |
| } |
| else |
| { |
| if ( aStr == pEntry->GetFormatstring() ) |
| res = aFTable.GetCurKey(); |
| else |
| pEntry = (SvNumberformat*) aFTable.Next(); |
| } |
| #else |
| if ( rString == pEntry->GetFormatstring() ) |
| res = aFTable.GetCurKey(); |
| else |
| pEntry = (SvNumberformat*) aFTable.Next(); |
| #endif |
| } |
| return res; |
| } |
| |
| |
| SvNumberFormatTable& SvNumberFormatter::GetFirstEntryTable( |
| short& eType, |
| sal_uInt32& FIndex, |
| LanguageType& rLnge) |
| { |
| short eTypetmp = eType; |
| if (eType == NUMBERFORMAT_ALL) // Leere Zelle oder don't care |
| rLnge = IniLnge; |
| else |
| { |
| SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(FIndex); |
| if (!pFormat) |
| { |
| // DBG_ERROR("SvNumberFormatter:: Unbekanntes altes Zahlformat (1)"); |
| rLnge = IniLnge; |
| eType = NUMBERFORMAT_ALL; |
| eTypetmp = eType; |
| } |
| else |
| { |
| rLnge = pFormat->GetLanguage(); |
| eType = pFormat->GetType()&~NUMBERFORMAT_DEFINED; |
| if (eType == 0) |
| { |
| eType = NUMBERFORMAT_DEFINED; |
| eTypetmp = eType; |
| } |
| else if (eType == NUMBERFORMAT_DATETIME) |
| { |
| eTypetmp = eType; |
| eType = NUMBERFORMAT_DATE; |
| } |
| else |
| eTypetmp = eType; |
| } |
| } |
| ChangeIntl(rLnge); |
| return GetEntryTable(eTypetmp, FIndex, rLnge); |
| } |
| |
| sal_uInt32 SvNumberFormatter::ImpGenerateCL( LanguageType eLnge, sal_Bool bLoadingSO5 ) |
| { |
| ChangeIntl(eLnge); |
| sal_uInt32 CLOffset = ImpGetCLOffset(ActLnge); |
| if (CLOffset > MaxCLOffset) |
| { // new CL combination |
| if (LocaleDataWrapper::areChecksEnabled()) |
| { |
| Locale aLoadedLocale = xLocaleData->getLoadedLocale(); |
| if ( aLoadedLocale.Language != aLocale.Language || |
| aLoadedLocale.Country != aLocale.Country ) |
| { |
| String aMsg( RTL_CONSTASCII_USTRINGPARAM( |
| "SvNumerFormatter::ImpGenerateCL: locales don't match:")); |
| LocaleDataWrapper::outputCheckMessage( |
| xLocaleData->appendLocaleInfo( aMsg )); |
| } |
| // test XML locale data FormatElement entries |
| { |
| uno::Sequence< i18n::FormatElement > xSeq = |
| xLocaleData->getAllFormats(); |
| // A test for completeness of formatindex="0" ... |
| // formatindex="47" is not needed here since it is done in |
| // ImpGenerateFormats(). |
| |
| // Test for dupes of formatindex="..." |
| for ( sal_Int32 j = 0; j < xSeq.getLength(); j++ ) |
| { |
| sal_Int16 nIdx = xSeq[j].formatIndex; |
| String aDupes; |
| for ( sal_Int32 i = 0; i < xSeq.getLength(); i++ ) |
| { |
| if ( i != j && xSeq[i].formatIndex == nIdx ) |
| { |
| aDupes += String::CreateFromInt32( i ); |
| aDupes += '('; |
| aDupes += String( xSeq[i].formatKey ); |
| aDupes += ')'; |
| aDupes += ' '; |
| } |
| } |
| if ( aDupes.Len() ) |
| { |
| String aMsg( RTL_CONSTASCII_USTRINGPARAM( |
| "XML locale data FormatElement formatindex dupe: ")); |
| aMsg += String::CreateFromInt32( nIdx ); |
| aMsg.AppendAscii( RTL_CONSTASCII_STRINGPARAM( |
| "\nFormatElements: ")); |
| aMsg += String::CreateFromInt32( j ); |
| aMsg += '('; |
| aMsg += String( xSeq[j].formatKey ); |
| aMsg += ')'; |
| aMsg += ' '; |
| aMsg += aDupes; |
| LocaleDataWrapper::outputCheckMessage( |
| xLocaleData->appendLocaleInfo( aMsg )); |
| } |
| } |
| } |
| } |
| |
| MaxCLOffset += SV_COUNTRY_LANGUAGE_OFFSET; |
| ImpGenerateFormats( MaxCLOffset, bLoadingSO5 ); |
| CLOffset = MaxCLOffset; |
| } |
| return CLOffset; |
| } |
| |
| SvNumberFormatTable& SvNumberFormatter::ChangeCL(short eType, |
| sal_uInt32& FIndex, |
| LanguageType eLnge) |
| { |
| ImpGenerateCL(eLnge); |
| return GetEntryTable(eType, FIndex, ActLnge); |
| } |
| |
| SvNumberFormatTable& SvNumberFormatter::GetEntryTable( |
| short eType, |
| sal_uInt32& FIndex, |
| LanguageType eLnge) |
| { |
| if ( pFormatTable ) |
| pFormatTable->Clear(); |
| else |
| pFormatTable = new SvNumberFormatTable; |
| ChangeIntl(eLnge); |
| sal_uInt32 CLOffset = ImpGetCLOffset(ActLnge); |
| |
| // Might generate and insert a default format for the given type |
| // (e.g. currency) => has to be done before collecting formats. |
| sal_uInt32 nDefaultIndex = GetStandardFormat( eType, ActLnge ); |
| |
| SvNumberformat* pEntry; |
| pEntry = (SvNumberformat*) aFTable.Seek(CLOffset); |
| |
| if (eType == NUMBERFORMAT_ALL) |
| { |
| while (pEntry && pEntry->GetLanguage() == ActLnge) |
| { // copy all entries to output table |
| pFormatTable->Insert( aFTable.GetCurKey(), pEntry ); |
| pEntry = (SvNumberformat*) aFTable.Next(); |
| } |
| } |
| else |
| { |
| while (pEntry && pEntry->GetLanguage() == ActLnge) |
| { // copy entries of queried type to output table |
| if ((pEntry->GetType()) & eType) |
| pFormatTable->Insert(aFTable.GetCurKey(),pEntry); |
| pEntry = (SvNumberformat*) aFTable.Next(); |
| } |
| } |
| if ( pFormatTable->Count() > 0 ) |
| { // select default if queried format doesn't exist or queried type or |
| // language differ from existing format |
| pEntry = aFTable.Get(FIndex); |
| if ( !pEntry || !(pEntry->GetType() & eType) || pEntry->GetLanguage() != ActLnge ) |
| FIndex = nDefaultIndex; |
| } |
| return *pFormatTable; |
| } |
| |
| sal_Bool SvNumberFormatter::IsNumberFormat(const String& sString, |
| sal_uInt32& F_Index, |
| double& fOutNumber) |
| { |
| short FType; |
| const SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(F_Index); |
| if (!pFormat) |
| { |
| // DBG_ERROR("SvNumberFormatter:: Unbekanntes altes Zahlformat (2)"); |
| ChangeIntl(IniLnge); |
| FType = NUMBERFORMAT_NUMBER; |
| } |
| else |
| { |
| FType = pFormat->GetType() &~NUMBERFORMAT_DEFINED; |
| if (FType == 0) |
| FType = NUMBERFORMAT_DEFINED; |
| ChangeIntl(pFormat->GetLanguage()); |
| } |
| sal_Bool res; |
| short RType = FType; |
| // Ergebnistyp |
| // ohne def-Kennung |
| if (RType == NUMBERFORMAT_TEXT) // Zahlzelle ->Stringz. |
| res = sal_False; |
| else |
| res = pStringScanner->IsNumberFormat(sString, RType, fOutNumber, pFormat); |
| |
| if (res && !IsCompatible(FType, RType)) // unpassender Typ |
| { |
| switch ( RType ) |
| { |
| case NUMBERFORMAT_TIME : |
| { |
| if ( pStringScanner->GetDecPos() ) |
| { // 100stel Sekunden |
| if ( pStringScanner->GetAnzNums() > 3 || fOutNumber < 0.0 ) |
| F_Index = GetFormatIndex( NF_TIME_HH_MMSS00, ActLnge ); |
| else |
| F_Index = GetFormatIndex( NF_TIME_MMSS00, ActLnge ); |
| } |
| else if ( fOutNumber >= 1.0 || fOutNumber < 0.0 ) |
| F_Index = GetFormatIndex( NF_TIME_HH_MMSS, ActLnge ); |
| else |
| F_Index = GetStandardFormat( RType, ActLnge ); |
| } |
| break; |
| default: |
| F_Index = GetStandardFormat( RType, ActLnge ); |
| } |
| } |
| return res; |
| } |
| |
| sal_Bool SvNumberFormatter::IsCompatible(short eOldType, |
| short eNewType) |
| { |
| if (eOldType == eNewType) |
| return sal_True; |
| else if (eOldType == NUMBERFORMAT_DEFINED) |
| return sal_True; |
| else |
| { |
| switch (eNewType) |
| { |
| case NUMBERFORMAT_NUMBER: |
| { |
| switch (eOldType) |
| { |
| case NUMBERFORMAT_PERCENT: |
| case NUMBERFORMAT_CURRENCY: |
| case NUMBERFORMAT_SCIENTIFIC: |
| case NUMBERFORMAT_FRACTION: |
| // case NUMBERFORMAT_LOGICAL: |
| case NUMBERFORMAT_DEFINED: |
| return sal_True; |
| default: |
| return sal_False; |
| } |
| } |
| break; |
| case NUMBERFORMAT_DATE: |
| { |
| switch (eOldType) |
| { |
| case NUMBERFORMAT_DATETIME: |
| return sal_True; |
| default: |
| return sal_False; |
| } |
| } |
| break; |
| case NUMBERFORMAT_TIME: |
| { |
| switch (eOldType) |
| { |
| case NUMBERFORMAT_DATETIME: |
| return sal_True; |
| default: |
| return sal_False; |
| } |
| } |
| break; |
| case NUMBERFORMAT_DATETIME: |
| { |
| switch (eOldType) |
| { |
| case NUMBERFORMAT_TIME: |
| case NUMBERFORMAT_DATE: |
| return sal_True; |
| default: |
| return sal_False; |
| } |
| } |
| break; |
| default: |
| return sal_False; |
| } |
| return sal_False; |
| } |
| } |
| |
| |
| sal_uInt32 SvNumberFormatter::ImpGetDefaultFormat( short nType ) |
| { |
| sal_uInt32 CLOffset = ImpGetCLOffset( ActLnge ); |
| sal_uInt32 nSearch; |
| switch( nType ) |
| { |
| case NUMBERFORMAT_DATE : |
| nSearch = CLOffset + ZF_STANDARD_DATE; |
| break; |
| case NUMBERFORMAT_TIME : |
| nSearch = CLOffset + ZF_STANDARD_TIME; |
| break; |
| case NUMBERFORMAT_DATETIME : |
| nSearch = CLOffset + ZF_STANDARD_DATETIME; |
| break; |
| case NUMBERFORMAT_PERCENT : |
| nSearch = CLOffset + ZF_STANDARD_PERCENT; |
| break; |
| case NUMBERFORMAT_SCIENTIFIC: |
| nSearch = CLOffset + ZF_STANDARD_SCIENTIFIC; |
| break; |
| default: |
| nSearch = CLOffset + ZF_STANDARD; |
| } |
| sal_uInt32 nDefaultFormat = (sal_uInt32)(sal_uLong) aDefaultFormatKeys.Get( nSearch ); |
| if ( !nDefaultFormat ) |
| nDefaultFormat = NUMBERFORMAT_ENTRY_NOT_FOUND; |
| if ( nDefaultFormat == NUMBERFORMAT_ENTRY_NOT_FOUND ) |
| { // look for a defined standard |
| sal_uInt32 nStopKey = CLOffset + SV_COUNTRY_LANGUAGE_OFFSET; |
| sal_uInt32 nKey; |
| aFTable.Seek( CLOffset ); |
| while ( (nKey = aFTable.GetCurKey()) >= CLOffset && nKey < nStopKey ) |
| { |
| const SvNumberformat* pEntry = |
| (const SvNumberformat*) aFTable.GetCurObject(); |
| if ( pEntry->IsStandard() && ((pEntry->GetType() & |
| ~NUMBERFORMAT_DEFINED) == nType) ) |
| { |
| nDefaultFormat = nKey; |
| break; // while |
| } |
| aFTable.Next(); |
| } |
| |
| if ( nDefaultFormat == NUMBERFORMAT_ENTRY_NOT_FOUND ) |
| { // none found, use old fixed standards |
| switch( nType ) |
| { |
| case NUMBERFORMAT_DATE : |
| nDefaultFormat = CLOffset + ZF_STANDARD_DATE; |
| break; |
| case NUMBERFORMAT_TIME : |
| nDefaultFormat = CLOffset + ZF_STANDARD_TIME+1; |
| break; |
| case NUMBERFORMAT_DATETIME : |
| nDefaultFormat = CLOffset + ZF_STANDARD_DATETIME; |
| break; |
| case NUMBERFORMAT_PERCENT : |
| nDefaultFormat = CLOffset + ZF_STANDARD_PERCENT+1; |
| break; |
| case NUMBERFORMAT_SCIENTIFIC: |
| nDefaultFormat = CLOffset + ZF_STANDARD_SCIENTIFIC; |
| break; |
| default: |
| nDefaultFormat = CLOffset + ZF_STANDARD; |
| } |
| } |
| aDefaultFormatKeys.Insert( nSearch, (void*) nDefaultFormat ); |
| } |
| return nDefaultFormat; |
| } |
| |
| |
| sal_uInt32 SvNumberFormatter::GetStandardFormat( short eType, LanguageType eLnge ) |
| { |
| sal_uInt32 CLOffset = ImpGenerateCL(eLnge); |
| switch(eType) |
| { |
| case NUMBERFORMAT_CURRENCY : |
| { |
| if ( eLnge == LANGUAGE_SYSTEM ) |
| return ImpGetDefaultSystemCurrencyFormat(); |
| else |
| return ImpGetDefaultCurrencyFormat(); |
| } |
| case NUMBERFORMAT_DATE : |
| case NUMBERFORMAT_TIME : |
| case NUMBERFORMAT_DATETIME : |
| case NUMBERFORMAT_PERCENT : |
| case NUMBERFORMAT_SCIENTIFIC: |
| return ImpGetDefaultFormat( eType ); |
| |
| case NUMBERFORMAT_FRACTION : return CLOffset + ZF_STANDARD_FRACTION; |
| case NUMBERFORMAT_LOGICAL : return CLOffset + ZF_STANDARD_LOGICAL; |
| case NUMBERFORMAT_TEXT : return CLOffset + ZF_STANDARD_TEXT; |
| case NUMBERFORMAT_ALL : |
| case NUMBERFORMAT_DEFINED : |
| case NUMBERFORMAT_NUMBER : |
| case NUMBERFORMAT_UNDEFINED : |
| default : return CLOffset + ZF_STANDARD; |
| } |
| } |
| |
| sal_Bool SvNumberFormatter::IsSpecialStandardFormat( sal_uInt32 nFIndex, |
| LanguageType eLnge ) |
| { |
| return |
| nFIndex == GetFormatIndex( NF_TIME_MMSS00, eLnge ) || |
| nFIndex == GetFormatIndex( NF_TIME_HH_MMSS00, eLnge ) || |
| nFIndex == GetFormatIndex( NF_TIME_HH_MMSS, eLnge ) |
| ; |
| } |
| |
| sal_uInt32 SvNumberFormatter::GetStandardFormat( sal_uInt32 nFIndex, short eType, |
| LanguageType eLnge ) |
| { |
| if ( IsSpecialStandardFormat( nFIndex, eLnge ) ) |
| return nFIndex; |
| else |
| return GetStandardFormat( eType, eLnge ); |
| } |
| |
| sal_uInt32 SvNumberFormatter::GetStandardFormat( double fNumber, sal_uInt32 nFIndex, |
| short eType, LanguageType eLnge ) |
| { |
| if ( IsSpecialStandardFormat( nFIndex, eLnge ) ) |
| return nFIndex; |
| |
| switch( eType ) |
| { |
| case NUMBERFORMAT_TIME : |
| { |
| sal_Bool bSign; |
| if ( fNumber < 0.0 ) |
| { |
| bSign = sal_True; |
| fNumber = -fNumber; |
| } |
| else |
| bSign = sal_False; |
| double fSeconds = fNumber * 86400; |
| if ( floor( fSeconds + 0.5 ) * 100 != floor( fSeconds * 100 + 0.5 ) ) |
| { // mit 100stel Sekunden |
| if ( bSign || fSeconds >= 3600 ) |
| return GetFormatIndex( NF_TIME_HH_MMSS00, eLnge ); |
| else |
| return GetFormatIndex( NF_TIME_MMSS00, eLnge ); |
| } |
| else |
| { |
| if ( bSign || fNumber >= 1.0 ) |
| return GetFormatIndex( NF_TIME_HH_MMSS, eLnge ); |
| else |
| return GetStandardFormat( eType, eLnge ); |
| } |
| } |
| default: |
| return GetStandardFormat( eType, eLnge ); |
| } |
| } |
| |
| void SvNumberFormatter::GetInputLineString(const double& fOutNumber, |
| sal_uInt32 nFIndex, |
| String& sOutString) |
| { |
| SvNumberformat* pFormat; |
| Color* pColor; |
| pFormat = (SvNumberformat*) aFTable.Get(nFIndex); |
| if (!pFormat) |
| pFormat = aFTable.Get(ZF_STANDARD); |
| LanguageType eLang = pFormat->GetLanguage(); |
| ChangeIntl( eLang ); |
| short eType = pFormat->GetType() & ~NUMBERFORMAT_DEFINED; |
| if (eType == 0) |
| eType = NUMBERFORMAT_DEFINED; |
| sal_uInt16 nOldPrec = pFormatScanner->GetStandardPrec(); |
| bool bPrecChanged = false; |
| if (eType == NUMBERFORMAT_NUMBER || eType == NUMBERFORMAT_PERCENT |
| || eType == NUMBERFORMAT_CURRENCY |
| || eType == NUMBERFORMAT_SCIENTIFIC |
| || eType == NUMBERFORMAT_FRACTION) |
| { |
| if (eType != NUMBERFORMAT_PERCENT) // spaeter Sonderbehandlung % |
| eType = NUMBERFORMAT_NUMBER; |
| ChangeStandardPrec(INPUTSTRING_PRECISION); |
| bPrecChanged = true; |
| } |
| sal_uInt32 nKey = nFIndex; |
| switch ( eType ) |
| { // #61619# immer vierstelliges Jahr editieren |
| case NUMBERFORMAT_DATE : |
| nKey = GetFormatIndex( NF_DATE_SYS_DDMMYYYY, eLang ); |
| break; |
| case NUMBERFORMAT_DATETIME : |
| nKey = GetFormatIndex( NF_DATETIME_SYS_DDMMYYYY_HHMMSS, eLang ); |
| break; |
| default: |
| nKey = GetStandardFormat( fOutNumber, nFIndex, eType, eLang ); |
| } |
| if ( nKey != nFIndex ) |
| pFormat = (SvNumberformat*) aFTable.Get( nKey ); |
| if (pFormat) |
| { |
| if ( eType == NUMBERFORMAT_TIME && pFormat->GetFormatPrecision() ) |
| { |
| ChangeStandardPrec(INPUTSTRING_PRECISION); |
| bPrecChanged = true; |
| } |
| pFormat->GetOutputString(fOutNumber, sOutString, &pColor); |
| } |
| if (bPrecChanged) |
| ChangeStandardPrec(nOldPrec); |
| } |
| |
| void SvNumberFormatter::GetOutputString(const double& fOutNumber, |
| sal_uInt32 nFIndex, |
| String& sOutString, |
| Color** ppColor) |
| { |
| if (bNoZero && fOutNumber == 0.0) |
| { |
| sOutString.Erase(); |
| return; |
| } |
| SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(nFIndex); |
| if (!pFormat) |
| pFormat = aFTable.Get(ZF_STANDARD); |
| ChangeIntl(pFormat->GetLanguage()); |
| pFormat->GetOutputString(fOutNumber, sOutString, ppColor); |
| } |
| |
| void SvNumberFormatter::GetOutputString(String& sString, |
| sal_uInt32 nFIndex, |
| String& sOutString, |
| Color** ppColor) |
| { |
| SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(nFIndex); |
| if (!pFormat) |
| pFormat = aFTable.Get(ZF_STANDARD_TEXT); |
| if (!pFormat->IsTextFormat() && !pFormat->HasTextFormat()) |
| { |
| *ppColor = NULL; |
| sOutString = sString; |
| } |
| else |
| { |
| ChangeIntl(pFormat->GetLanguage()); |
| pFormat->GetOutputString(sString, sOutString, ppColor); |
| } |
| } |
| |
| sal_Bool SvNumberFormatter::GetPreviewString(const String& sFormatString, |
| double fPreviewNumber, |
| String& sOutString, |
| Color** ppColor, |
| LanguageType eLnge) |
| { |
| if (sFormatString.Len() == 0) // keinen Leerstring |
| return sal_False; |
| |
| xub_StrLen nCheckPos = STRING_NOTFOUND; |
| sal_uInt32 nKey; |
| if (eLnge == LANGUAGE_DONTKNOW) |
| eLnge = IniLnge; |
| ChangeIntl(eLnge); // ggfs. austauschen |
| eLnge = ActLnge; |
| String sTmpString = sFormatString; |
| SvNumberformat* p_Entry = new SvNumberformat(sTmpString, |
| pFormatScanner, |
| pStringScanner, |
| nCheckPos, |
| eLnge); |
| if (nCheckPos == 0) // String ok |
| { |
| sal_uInt32 CLOffset = ImpGenerateCL(eLnge); // ggfs. neu Standard- |
| // formate anlegen |
| nKey = ImpIsEntry(p_Entry->GetFormatstring(),CLOffset, eLnge); |
| if (nKey != NUMBERFORMAT_ENTRY_NOT_FOUND) // schon vorhanden |
| GetOutputString(fPreviewNumber,nKey,sOutString,ppColor); |
| else |
| p_Entry->GetOutputString(fPreviewNumber,sOutString, ppColor); |
| delete p_Entry; |
| return sal_True; |
| } |
| else |
| { |
| delete p_Entry; |
| return sal_False; |
| } |
| } |
| |
| sal_Bool SvNumberFormatter::GetPreviewStringGuess( const String& sFormatString, |
| double fPreviewNumber, |
| String& sOutString, |
| Color** ppColor, |
| LanguageType eLnge ) |
| { |
| if (sFormatString.Len() == 0) // keinen Leerstring |
| return sal_False; |
| |
| if (eLnge == LANGUAGE_DONTKNOW) |
| eLnge = IniLnge; |
| |
| ChangeIntl( eLnge ); |
| eLnge = ActLnge; |
| sal_Bool bEnglish = (eLnge == LANGUAGE_ENGLISH_US); |
| |
| String aFormatStringUpper( pCharClass->upper( sFormatString ) ); |
| sal_uInt32 nCLOffset = ImpGenerateCL( eLnge ); |
| sal_uInt32 nKey = ImpIsEntry( aFormatStringUpper, nCLOffset, eLnge ); |
| if ( nKey != NUMBERFORMAT_ENTRY_NOT_FOUND ) |
| { // Zielformat vorhanden |
| GetOutputString( fPreviewNumber, nKey, sOutString, ppColor ); |
| return sal_True; |
| } |
| |
| SvNumberformat *pEntry = NULL; |
| xub_StrLen nCheckPos = STRING_NOTFOUND; |
| String sTmpString; |
| |
| if ( bEnglish ) |
| { |
| sTmpString = sFormatString; |
| pEntry = new SvNumberformat( sTmpString, pFormatScanner, |
| pStringScanner, nCheckPos, eLnge ); |
| } |
| else |
| { |
| nCLOffset = ImpGenerateCL( LANGUAGE_ENGLISH_US ); |
| nKey = ImpIsEntry( aFormatStringUpper, nCLOffset, LANGUAGE_ENGLISH_US ); |
| sal_Bool bEnglishFormat = (nKey != NUMBERFORMAT_ENTRY_NOT_FOUND); |
| |
| // try english --> other bzw. english nach other konvertieren |
| LanguageType eFormatLang = LANGUAGE_ENGLISH_US; |
| pFormatScanner->SetConvertMode( LANGUAGE_ENGLISH_US, eLnge ); |
| sTmpString = sFormatString; |
| pEntry = new SvNumberformat( sTmpString, pFormatScanner, |
| pStringScanner, nCheckPos, eFormatLang ); |
| pFormatScanner->SetConvertMode( sal_False ); |
| ChangeIntl( eLnge ); |
| |
| if ( !bEnglishFormat ) |
| { |
| if ( nCheckPos > 0 || xTransliteration->isEqual( sFormatString, |
| pEntry->GetFormatstring() ) ) |
| { // other Format |
| delete pEntry; |
| sTmpString = sFormatString; |
| pEntry = new SvNumberformat( sTmpString, pFormatScanner, |
| pStringScanner, nCheckPos, eLnge ); |
| } |
| else |
| { // verify english |
| xub_StrLen nCheckPos2 = STRING_NOTFOUND; |
| // try other --> english |
| eFormatLang = eLnge; |
| pFormatScanner->SetConvertMode( eLnge, LANGUAGE_ENGLISH_US ); |
| sTmpString = sFormatString; |
| SvNumberformat* pEntry2 = new SvNumberformat( sTmpString, pFormatScanner, |
| pStringScanner, nCheckPos2, eFormatLang ); |
| pFormatScanner->SetConvertMode( sal_False ); |
| ChangeIntl( eLnge ); |
| if ( nCheckPos2 == 0 && !xTransliteration->isEqual( sFormatString, |
| pEntry2->GetFormatstring() ) ) |
| { // other Format |
| delete pEntry; |
| sTmpString = sFormatString; |
| pEntry = new SvNumberformat( sTmpString, pFormatScanner, |
| pStringScanner, nCheckPos, eLnge ); |
| } |
| delete pEntry2; |
| } |
| } |
| } |
| |
| if (nCheckPos == 0) // String ok |
| { |
| ImpGenerateCL( eLnge ); // ggfs. neu Standardformate anlegen |
| pEntry->GetOutputString( fPreviewNumber, sOutString, ppColor ); |
| delete pEntry; |
| return sal_True; |
| } |
| delete pEntry; |
| return sal_False; |
| } |
| |
| sal_Bool SvNumberFormatter::GetPreviewString( const String& sFormatString, |
| const String& sPreviewString, |
| String& sOutString, |
| Color** ppColor, |
| LanguageType eLnge ) |
| { |
| if (sFormatString.Len() == 0) // no empty string |
| return sal_False; |
| |
| xub_StrLen nCheckPos = STRING_NOTFOUND; |
| sal_uInt32 nKey; |
| if (eLnge == LANGUAGE_DONTKNOW) |
| eLnge = IniLnge; |
| ChangeIntl(eLnge); // switch if needed |
| eLnge = ActLnge; |
| String sTmpString = sFormatString; |
| SvNumberformat* p_Entry = new SvNumberformat( sTmpString, |
| pFormatScanner, |
| pStringScanner, |
| nCheckPos, |
| eLnge); |
| if (nCheckPos == 0) // String ok |
| { |
| String aNonConstPreview( sPreviewString); |
| // May have to create standard formats for this locale. |
| sal_uInt32 CLOffset = ImpGenerateCL(eLnge); |
| nKey = ImpIsEntry( p_Entry->GetFormatstring(), CLOffset, eLnge); |
| if (nKey != NUMBERFORMAT_ENTRY_NOT_FOUND) // already present |
| GetOutputString( aNonConstPreview, nKey, sOutString, ppColor); |
| else |
| { |
| // If the format is valid but not a text format and does not |
| // include a text subformat, an empty string would result. Same as |
| // in SvNumberFormatter::GetOutputString() |
| if (p_Entry->IsTextFormat() || p_Entry->HasTextFormat()) |
| p_Entry->GetOutputString( aNonConstPreview, sOutString, ppColor); |
| else |
| { |
| *ppColor = NULL; |
| sOutString = sPreviewString; |
| } |
| } |
| delete p_Entry; |
| return sal_True; |
| } |
| else |
| { |
| delete p_Entry; |
| return sal_False; |
| } |
| } |
| |
| sal_uInt32 SvNumberFormatter::TestNewString(const String& sFormatString, |
| LanguageType eLnge) |
| { |
| if (sFormatString.Len() == 0) // keinen Leerstring |
| return NUMBERFORMAT_ENTRY_NOT_FOUND; |
| |
| xub_StrLen nCheckPos = STRING_NOTFOUND; |
| if (eLnge == LANGUAGE_DONTKNOW) |
| eLnge = IniLnge; |
| ChangeIntl(eLnge); // ggfs. austauschen |
| eLnge = ActLnge; |
| sal_uInt32 nRes; |
| String sTmpString = sFormatString; |
| SvNumberformat* pEntry = new SvNumberformat(sTmpString, |
| pFormatScanner, |
| pStringScanner, |
| nCheckPos, |
| eLnge); |
| if (nCheckPos == 0) // String ok |
| { |
| sal_uInt32 CLOffset = ImpGenerateCL(eLnge); // ggfs. neu Standard- |
| // formate anlegen |
| nRes = ImpIsEntry(pEntry->GetFormatstring(),CLOffset, eLnge); |
| // schon vorhanden ? |
| } |
| else |
| nRes = NUMBERFORMAT_ENTRY_NOT_FOUND; |
| delete pEntry; |
| return nRes; |
| } |
| |
| SvNumberformat* SvNumberFormatter::ImpInsertFormat( |
| const ::com::sun::star::i18n::NumberFormatCode& rCode, |
| sal_uInt32 nPos, sal_Bool bAfterLoadingSO5, sal_Int16 nOrgIndex ) |
| { |
| String aCodeStr( rCode.Code ); |
| if ( rCode.Index < NF_INDEX_TABLE_ENTRIES && |
| rCode.Usage == ::com::sun::star::i18n::KNumberFormatUsage::CURRENCY && |
| rCode.Index != NF_CURRENCY_1000DEC2_CCC ) |
| { // strip surrounding [$...] on automatic currency |
| if ( aCodeStr.SearchAscii( "[$" ) != STRING_NOTFOUND ) |
| aCodeStr = SvNumberformat::StripNewCurrencyDelimiters( aCodeStr, sal_False ); |
| else |
| { |
| if (LocaleDataWrapper::areChecksEnabled() && |
| rCode.Index != NF_CURRENCY_1000DEC2_CCC ) |
| { |
| String aMsg( RTL_CONSTASCII_USTRINGPARAM( |
| "SvNumberFormatter::ImpInsertFormat: no [$...] on currency format code, index ")); |
| aMsg += String::CreateFromInt32( rCode.Index ); |
| aMsg.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ":\n")); |
| aMsg += String( rCode.Code ); |
| LocaleDataWrapper::outputCheckMessage( |
| xLocaleData->appendLocaleInfo( aMsg)); |
| } |
| } |
| } |
| xub_StrLen nCheckPos = 0; |
| SvNumberformat* pFormat = new SvNumberformat(aCodeStr, |
| pFormatScanner, |
| pStringScanner, |
| nCheckPos, |
| ActLnge); |
| if ( !pFormat || nCheckPos > 0 ) |
| { |
| if (LocaleDataWrapper::areChecksEnabled()) |
| { |
| String aMsg( RTL_CONSTASCII_USTRINGPARAM( |
| "SvNumberFormatter::ImpInsertFormat: bad format code, index ")); |
| aMsg += String::CreateFromInt32( rCode.Index ); |
| aMsg += '\n'; |
| aMsg += String( rCode.Code ); |
| LocaleDataWrapper::outputCheckMessage( |
| xLocaleData->appendLocaleInfo( aMsg)); |
| } |
| delete pFormat; |
| return NULL; |
| } |
| if ( rCode.Index >= NF_INDEX_TABLE_ENTRIES ) |
| { |
| sal_uInt32 nCLOffset = nPos - (nPos % SV_COUNTRY_LANGUAGE_OFFSET); |
| sal_uInt32 nKey = ImpIsEntry( aCodeStr, nCLOffset, ActLnge ); |
| if ( nKey != NUMBERFORMAT_ENTRY_NOT_FOUND ) |
| { |
| if (LocaleDataWrapper::areChecksEnabled()) |
| { |
| switch ( nOrgIndex ) |
| { |
| // These may be dupes of integer versions for locales where |
| // currencies have no decimals like Italian Lira. |
| case NF_CURRENCY_1000DEC2 : // NF_CURRENCY_1000INT |
| case NF_CURRENCY_1000DEC2_RED : // NF_CURRENCY_1000INT_RED |
| case NF_CURRENCY_1000DEC2_DASHED : // NF_CURRENCY_1000INT_RED |
| break; |
| default: |
| if ( !bAfterLoadingSO5 ) |
| { // If bAfterLoadingSO5 there will definitely be some dupes, |
| // don't cry. But we need this test for verification of locale |
| // data if not loading old SO5 documents. |
| String aMsg( RTL_CONSTASCII_USTRINGPARAM( |
| "SvNumberFormatter::ImpInsertFormat: dup format code, index ")); |
| aMsg += String::CreateFromInt32( rCode.Index ); |
| aMsg += '\n'; |
| aMsg += String( rCode.Code ); |
| LocaleDataWrapper::outputCheckMessage( |
| xLocaleData->appendLocaleInfo( aMsg)); |
| } |
| } |
| } |
| delete pFormat; |
| return NULL; |
| } |
| else if ( nPos - nCLOffset >= SV_COUNTRY_LANGUAGE_OFFSET ) |
| { |
| if (LocaleDataWrapper::areChecksEnabled()) |
| { |
| String aMsg( RTL_CONSTASCII_USTRINGPARAM( |
| "SvNumberFormatter::ImpInsertFormat: too many format codes, index ")); |
| aMsg += String::CreateFromInt32( rCode.Index ); |
| aMsg += '\n'; |
| aMsg += String( rCode.Code ); |
| LocaleDataWrapper::outputCheckMessage( |
| xLocaleData->appendLocaleInfo( aMsg)); |
| } |
| delete pFormat; |
| return NULL; |
| } |
| } |
| if ( !aFTable.Insert( nPos, pFormat ) ) |
| { |
| if (LocaleDataWrapper::areChecksEnabled()) |
| { |
| String aMsg( RTL_CONSTASCII_USTRINGPARAM( |
| "ImpInsertFormat: can't insert number format key pos: ")); |
| aMsg += String::CreateFromInt32( nPos ); |
| aMsg.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ", code index ")); |
| aMsg += String::CreateFromInt32( rCode.Index ); |
| aMsg += '\n'; |
| aMsg += String( rCode.Code ); |
| LocaleDataWrapper::outputCheckMessage( |
| xLocaleData->appendLocaleInfo( aMsg)); |
| } |
| delete pFormat; |
| return NULL; |
| } |
| if ( rCode.Default ) |
| pFormat->SetStandard(); |
| if ( rCode.DefaultName.getLength() ) |
| pFormat->SetComment( rCode.DefaultName ); |
| return pFormat; |
| } |
| |
| SvNumberformat* SvNumberFormatter::ImpInsertNewStandardFormat( |
| const ::com::sun::star::i18n::NumberFormatCode& rCode, |
| sal_uInt32 nPos, sal_uInt16 nVersion, sal_Bool bAfterLoadingSO5, |
| sal_Int16 nOrgIndex ) |
| { |
| SvNumberformat* pNewFormat = ImpInsertFormat( rCode, nPos, |
| bAfterLoadingSO5, nOrgIndex ); |
| if (pNewFormat) |
| pNewFormat->SetNewStandardDefined( nVersion ); |
| // so that it gets saved, displayed properly, and converted by old versions |
| return pNewFormat; |
| } |
| |
| void SvNumberFormatter::GetFormatSpecialInfo(sal_uInt32 nFormat, |
| sal_Bool& bThousand, |
| sal_Bool& IsRed, |
| sal_uInt16& nPrecision, |
| sal_uInt16& nAnzLeading) |
| |
| { |
| const SvNumberformat* pFormat = aFTable.Get(nFormat); |
| if (pFormat) |
| pFormat->GetFormatSpecialInfo(bThousand, IsRed, |
| nPrecision, nAnzLeading); |
| else |
| { |
| bThousand = sal_False; |
| IsRed = sal_False; |
| nPrecision = pFormatScanner->GetStandardPrec(); |
| nAnzLeading = 0; |
| } |
| } |
| |
| sal_uInt16 SvNumberFormatter::GetFormatPrecision( sal_uInt32 nFormat ) const |
| { |
| const SvNumberformat* pFormat = aFTable.Get( nFormat ); |
| if ( pFormat ) |
| return pFormat->GetFormatPrecision(); |
| else |
| return pFormatScanner->GetStandardPrec(); |
| } |
| |
| |
| String SvNumberFormatter::GetFormatDecimalSep( sal_uInt32 nFormat ) const |
| { |
| const SvNumberformat* pFormat = aFTable.Get( nFormat ); |
| if ( !pFormat || pFormat->GetLanguage() == ActLnge ) |
| return GetNumDecimalSep(); |
| |
| String aRet; |
| LanguageType eSaveLang = xLocaleData.getCurrentLanguage(); |
| if ( pFormat->GetLanguage() == eSaveLang ) |
| aRet = xLocaleData->getNumDecimalSep(); |
| else |
| { |
| ::com::sun::star::lang::Locale aSaveLocale( xLocaleData->getLocale() ); |
| ::com::sun::star::lang::Locale aTmpLocale(MsLangId::convertLanguageToLocale(pFormat->GetLanguage())); |
| ((SvNumberFormatter*)this)->xLocaleData.changeLocale(aTmpLocale, pFormat->GetLanguage() ); |
| aRet = xLocaleData->getNumDecimalSep(); |
| ((SvNumberFormatter*)this)->xLocaleData.changeLocale( aSaveLocale, eSaveLang ); |
| } |
| return aRet; |
| } |
| |
| |
| sal_uInt32 SvNumberFormatter::GetFormatSpecialInfo( const String& rFormatString, |
| sal_Bool& bThousand, sal_Bool& IsRed, sal_uInt16& nPrecision, |
| sal_uInt16& nAnzLeading, LanguageType eLnge ) |
| |
| { |
| xub_StrLen nCheckPos = 0; |
| if (eLnge == LANGUAGE_DONTKNOW) |
| eLnge = IniLnge; |
| ChangeIntl(eLnge); // ggfs. austauschen |
| eLnge = ActLnge; |
| String aTmpStr( rFormatString ); |
| SvNumberformat* pFormat = new SvNumberformat( aTmpStr, |
| pFormatScanner, pStringScanner, nCheckPos, eLnge ); |
| if ( nCheckPos == 0 ) |
| pFormat->GetFormatSpecialInfo( bThousand, IsRed, nPrecision, nAnzLeading ); |
| else |
| { |
| bThousand = sal_False; |
| IsRed = sal_False; |
| nPrecision = pFormatScanner->GetStandardPrec(); |
| nAnzLeading = 0; |
| } |
| delete pFormat; |
| return nCheckPos; |
| } |
| |
| |
| inline sal_uInt32 SetIndexTable( NfIndexTableOffset nTabOff, sal_uInt32 nIndOff ) |
| { |
| if ( !bIndexTableInitialized ) |
| { |
| DBG_ASSERT( theIndexTable[nTabOff] == NUMBERFORMAT_ENTRY_NOT_FOUND, |
| "SetIndexTable: theIndexTable[nTabOff] already occupied" ); |
| theIndexTable[nTabOff] = nIndOff; |
| } |
| return nIndOff; |
| } |
| |
| |
| sal_Int32 SvNumberFormatter::ImpGetFormatCodeIndex( |
| ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::NumberFormatCode >& rSeq, |
| const NfIndexTableOffset nTabOff ) |
| { |
| const sal_Int32 nLen = rSeq.getLength(); |
| for ( sal_Int32 j=0; j<nLen; j++ ) |
| { |
| if ( rSeq[j].Index == nTabOff ) |
| return j; |
| } |
| if (LocaleDataWrapper::areChecksEnabled() && (nTabOff < NF_CURRENCY_START |
| || NF_CURRENCY_END < nTabOff || nTabOff == NF_CURRENCY_1000INT |
| || nTabOff == NF_CURRENCY_1000INT_RED |
| || nTabOff == NF_CURRENCY_1000DEC2_CCC)) |
| { // currency entries with decimals might not exist, e.g. Italian Lira |
| String aMsg( RTL_CONSTASCII_USTRINGPARAM( |
| "SvNumberFormatter::ImpGetFormatCodeIndex: not found: ")); |
| aMsg += String::CreateFromInt32( nTabOff ); |
| LocaleDataWrapper::outputCheckMessage( xLocaleData->appendLocaleInfo( |
| aMsg)); |
| } |
| if ( nLen ) |
| { |
| sal_Int32 j; |
| // look for a preset default |
| for ( j=0; j<nLen; j++ ) |
| { |
| if ( rSeq[j].Default ) |
| return j; |
| } |
| // currencies are special, not all format codes must exist, but all |
| // builtin number format key index positions must have a format assigned |
| if ( NF_CURRENCY_START <= nTabOff && nTabOff <= NF_CURRENCY_END ) |
| { |
| // look for a format with decimals |
| for ( j=0; j<nLen; j++ ) |
| { |
| if ( rSeq[j].Index == NF_CURRENCY_1000DEC2 ) |
| return j; |
| } |
| // last resort: look for a format without decimals |
| for ( j=0; j<nLen; j++ ) |
| { |
| if ( rSeq[j].Index == NF_CURRENCY_1000INT ) |
| return j; |
| } |
| } |
| } |
| else |
| { // we need at least _some_ format |
| rSeq.realloc(1); |
| rSeq[0] = ::com::sun::star::i18n::NumberFormatCode(); |
| String aTmp( '0' ); |
| aTmp += GetNumDecimalSep(); |
| aTmp.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "############" ) ); |
| rSeq[0].Code = aTmp; |
| } |
| return 0; |
| } |
| |
| |
| sal_Int32 SvNumberFormatter::ImpAdjustFormatCodeDefault( |
| ::com::sun::star::i18n::NumberFormatCode * pFormatArr, |
| sal_Int32 nCnt, sal_Bool bCheckCorrectness ) |
| { |
| using namespace ::com::sun::star; |
| |
| if ( !nCnt ) |
| return -1; |
| if (bCheckCorrectness && LocaleDataWrapper::areChecksEnabled()) |
| { // check the locale data for correctness |
| ByteString aMsg; |
| sal_Int32 nElem, nShort, nMedium, nLong, nShortDef, nMediumDef, nLongDef; |
| nShort = nMedium = nLong = nShortDef = nMediumDef = nLongDef = -1; |
| for ( nElem = 0; nElem < nCnt; nElem++ ) |
| { |
| switch ( pFormatArr[nElem].Type ) |
| { |
| case i18n::KNumberFormatType::SHORT : |
| nShort = nElem; |
| break; |
| case i18n::KNumberFormatType::MEDIUM : |
| nMedium = nElem; |
| break; |
| case i18n::KNumberFormatType::LONG : |
| nLong = nElem; |
| break; |
| default: |
| aMsg = "unknown type"; |
| } |
| if ( pFormatArr[nElem].Default ) |
| { |
| switch ( pFormatArr[nElem].Type ) |
| { |
| case i18n::KNumberFormatType::SHORT : |
| if ( nShortDef != -1 ) |
| aMsg = "dupe short type default"; |
| nShortDef = nElem; |
| break; |
| case i18n::KNumberFormatType::MEDIUM : |
| if ( nMediumDef != -1 ) |
| aMsg = "dupe medium type default"; |
| nMediumDef = nElem; |
| break; |
| case i18n::KNumberFormatType::LONG : |
| if ( nLongDef != -1 ) |
| aMsg = "dupe long type default"; |
| nLongDef = nElem; |
| break; |
| } |
| } |
| if ( aMsg.Len() ) |
| { |
| aMsg.Insert( "SvNumberFormatter::ImpAdjustFormatCodeDefault: ", 0 ); |
| aMsg += "\nXML locale data FormatElement formatindex: "; |
| aMsg += ByteString::CreateFromInt32( pFormatArr[nElem].Index ); |
| String aUMsg( aMsg, RTL_TEXTENCODING_ASCII_US); |
| LocaleDataWrapper::outputCheckMessage( |
| xLocaleData->appendLocaleInfo( aUMsg)); |
| aMsg.Erase(); |
| } |
| } |
| if ( nShort != -1 && nShortDef == -1 ) |
| aMsg += "no short type default "; |
| if ( nMedium != -1 && nMediumDef == -1 ) |
| aMsg += "no medium type default "; |
| if ( nLong != -1 && nLongDef == -1 ) |
| aMsg += "no long type default "; |
| if ( aMsg.Len() ) |
| { |
| aMsg.Insert( "SvNumberFormatter::ImpAdjustFormatCodeDefault: ", 0 ); |
| aMsg += "\nXML locale data FormatElement group of: "; |
| String aUMsg( aMsg, RTL_TEXTENCODING_ASCII_US); |
| aUMsg += String( pFormatArr[0].NameID ); |
| LocaleDataWrapper::outputCheckMessage( |
| xLocaleData->appendLocaleInfo( aUMsg)); |
| aMsg.Erase(); |
| } |
| } |
| // find the default (medium preferred, then long) and reset all other defaults |
| sal_Int32 nElem, nDef, nMedium; |
| nDef = nMedium = -1; |
| for ( nElem = 0; nElem < nCnt; nElem++ ) |
| { |
| if ( pFormatArr[nElem].Default ) |
| { |
| switch ( pFormatArr[nElem].Type ) |
| { |
| case i18n::KNumberFormatType::MEDIUM : |
| nDef = nMedium = nElem; |
| break; |
| case i18n::KNumberFormatType::LONG : |
| if ( nMedium == -1 ) |
| nDef = nElem; |
| // fallthru |
| default: |
| if ( nDef == -1 ) |
| nDef = nElem; |
| pFormatArr[nElem].Default = sal_False; |
| } |
| } |
| } |
| if ( nDef == -1 ) |
| nDef = 0; |
| pFormatArr[nDef].Default = sal_True; |
| return nDef; |
| } |
| |
| |
| void SvNumberFormatter::ImpGenerateFormats( sal_uInt32 CLOffset, sal_Bool bLoadingSO5 ) |
| { |
| using namespace ::com::sun::star; |
| |
| if ( !bIndexTableInitialized ) |
| { |
| for ( sal_uInt16 j=0; j<NF_INDEX_TABLE_ENTRIES; j++ ) |
| { |
| theIndexTable[j] = NUMBERFORMAT_ENTRY_NOT_FOUND; |
| } |
| } |
| sal_Bool bOldConvertMode = pFormatScanner->GetConvertMode(); |
| if (bOldConvertMode) |
| pFormatScanner->SetConvertMode(sal_False); // switch off for this function |
| |
| NumberFormatCodeWrapper aNumberFormatCode( xServiceManager, GetLocale() ); |
| |
| xub_StrLen nCheckPos = 0; |
| SvNumberformat* pNewFormat = NULL; |
| String aFormatCode; |
| sal_Int32 nIdx; |
| sal_Bool bDefault; |
| |
| // Counter for additional builtin formats not fitting into the first 10 |
| // of a category (TLOT:=The Legacy Of Templin), altogether about 20 formats. |
| // Has to be incremented on each ImpInsertNewStandardformat, new formats |
| // must be appended, not inserted! |
| sal_uInt16 nNewExtended = ZF_STANDARD_NEWEXTENDED; |
| |
| // Number |
| uno::Sequence< i18n::NumberFormatCode > aFormatSeq |
| = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::FIXED_NUMBER ); |
| ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() ); |
| |
| // General |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_STANDARD ); |
| SvNumberformat* pStdFormat = ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_NUMBER_STANDARD, ZF_STANDARD )); |
| if (pStdFormat) |
| { |
| // This is _the_ standard format. |
| if (LocaleDataWrapper::areChecksEnabled() && |
| pStdFormat->GetType() != NUMBERFORMAT_NUMBER) |
| { |
| String aMsg( RTL_CONSTASCII_USTRINGPARAM( |
| "SvNumberFormatter::ImpGenerateFormats: General format not NUMBER")); |
| LocaleDataWrapper::outputCheckMessage( |
| xLocaleData->appendLocaleInfo( aMsg)); |
| } |
| pStdFormat->SetType( NUMBERFORMAT_NUMBER ); |
| pStdFormat->SetStandard(); |
| pStdFormat->SetLastInsertKey( SV_MAX_ANZ_STANDARD_FORMATE ); |
| } |
| else |
| { |
| if (LocaleDataWrapper::areChecksEnabled()) |
| { |
| String aMsg( RTL_CONSTASCII_USTRINGPARAM( |
| "SvNumberFormatter::ImpGenerateFormats: General format not insertable, nothing will work")); |
| LocaleDataWrapper::outputCheckMessage( |
| xLocaleData->appendLocaleInfo( aMsg)); |
| } |
| } |
| |
| // Boolean |
| aFormatCode = pFormatScanner->GetBooleanString(); |
| pNewFormat = new SvNumberformat( aFormatCode, |
| pFormatScanner, pStringScanner, nCheckPos, ActLnge ); |
| pNewFormat->SetType(NUMBERFORMAT_LOGICAL); |
| pNewFormat->SetStandard(); |
| if ( !aFTable.Insert( |
| CLOffset + SetIndexTable( NF_BOOLEAN, ZF_STANDARD_LOGICAL ), |
| pNewFormat)) |
| delete pNewFormat; |
| |
| // Text |
| aFormatCode = '@'; |
| pNewFormat = new SvNumberformat( aFormatCode, |
| pFormatScanner, pStringScanner, nCheckPos, ActLnge ); |
| pNewFormat->SetType(NUMBERFORMAT_TEXT); |
| pNewFormat->SetStandard(); |
| if ( !aFTable.Insert( |
| CLOffset + SetIndexTable( NF_TEXT, ZF_STANDARD_TEXT ), |
| pNewFormat)) |
| delete pNewFormat; |
| |
| |
| |
| // 0 |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_INT ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_NUMBER_INT, ZF_STANDARD+1 )); |
| |
| // 0.00 |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_DEC2 ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_NUMBER_DEC2, ZF_STANDARD+2 )); |
| |
| // #,##0 |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_1000INT ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_NUMBER_1000INT, ZF_STANDARD+3 )); |
| |
| // #,##0.00 |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_1000DEC2 ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_NUMBER_1000DEC2, ZF_STANDARD+4 )); |
| |
| // #.##0,00 System country/language dependent since number formatter version 6 |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_SYSTEM ); |
| ImpInsertNewStandardFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_NUMBER_SYSTEM, ZF_STANDARD+5 ), |
| SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); |
| |
| |
| // Percent number |
| aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::PERCENT_NUMBER ); |
| ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() ); |
| |
| // 0% |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_PERCENT_INT ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_PERCENT_INT, ZF_STANDARD_PERCENT )); |
| |
| // 0.00% |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_PERCENT_DEC2 ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_PERCENT_DEC2, ZF_STANDARD_PERCENT+1 )); |
| |
| |
| |
| // Currency. NO default standard option! Default is determined of locale |
| // data default currency and format is generated if needed. |
| aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::CURRENCY ); |
| if (LocaleDataWrapper::areChecksEnabled()) |
| { |
| // though no default desired here, test for correctness of locale data |
| ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() ); |
| } |
| |
| // #,##0 |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000INT ); |
| bDefault = aFormatSeq[nIdx].Default; |
| aFormatSeq[nIdx].Default = sal_False; |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_CURRENCY_1000INT, ZF_STANDARD_CURRENCY )); |
| aFormatSeq[nIdx].Default = bDefault; |
| |
| // #,##0.00 |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000DEC2 ); |
| bDefault = aFormatSeq[nIdx].Default; |
| aFormatSeq[nIdx].Default = sal_False; |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_CURRENCY_1000DEC2, ZF_STANDARD_CURRENCY+1 )); |
| aFormatSeq[nIdx].Default = bDefault; |
| |
| // #,##0 negative red |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000INT_RED ); |
| bDefault = aFormatSeq[nIdx].Default; |
| aFormatSeq[nIdx].Default = sal_False; |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_CURRENCY_1000INT_RED, ZF_STANDARD_CURRENCY+2 )); |
| aFormatSeq[nIdx].Default = bDefault; |
| |
| // #,##0.00 negative red |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000DEC2_RED ); |
| bDefault = aFormatSeq[nIdx].Default; |
| aFormatSeq[nIdx].Default = sal_False; |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_CURRENCY_1000DEC2_RED, ZF_STANDARD_CURRENCY+3 )); |
| aFormatSeq[nIdx].Default = bDefault; |
| |
| // #,##0.00 USD since number formatter version 3 |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000DEC2_CCC ); |
| bDefault = aFormatSeq[nIdx].Default; |
| aFormatSeq[nIdx].Default = sal_False; |
| pNewFormat = ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_CURRENCY_1000DEC2_CCC, ZF_STANDARD_CURRENCY+4 )); |
| if ( pNewFormat ) |
| pNewFormat->SetUsed(sal_True); // must be saved for older versions |
| aFormatSeq[nIdx].Default = bDefault; |
| |
| // #.##0,-- since number formatter version 6 |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000DEC2_DASHED ); |
| bDefault = aFormatSeq[nIdx].Default; |
| aFormatSeq[nIdx].Default = sal_False; |
| ImpInsertNewStandardFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_CURRENCY_1000DEC2_DASHED, ZF_STANDARD_CURRENCY+5 ), |
| SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); |
| aFormatSeq[nIdx].Default = bDefault; |
| |
| |
| |
| // Date |
| aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::DATE ); |
| ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() ); |
| |
| // DD.MM.YY System |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYSTEM_SHORT ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_SYSTEM_SHORT, ZF_STANDARD_DATE )); |
| |
| // NN DD.MMM YY |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DEF_NNDDMMMYY ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_DEF_NNDDMMMYY, ZF_STANDARD_DATE+1 )); |
| |
| // DD.MM.YY def/System |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_MMYY ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_SYS_MMYY, ZF_STANDARD_DATE+2 )); |
| |
| // DD MMM |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DDMMM ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_SYS_DDMMM, ZF_STANDARD_DATE+3 )); |
| |
| // MMMM |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_MMMM ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_MMMM, ZF_STANDARD_DATE+4 )); |
| |
| // QQ YY |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_QQJJ ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_QQJJ, ZF_STANDARD_DATE+5 )); |
| |
| // DD.MM.YYYY since number formatter version 2, was DD.MM.[YY]YY |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DDMMYYYY ); |
| pNewFormat = ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_SYS_DDMMYYYY, ZF_STANDARD_DATE+6 )); |
| if ( pNewFormat ) |
| pNewFormat->SetUsed(sal_True); // must be saved for older versions |
| |
| // DD.MM.YY def/System, since number formatter version 6 |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DDMMYY ); |
| ImpInsertNewStandardFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_SYS_DDMMYY, ZF_STANDARD_DATE+7 ), |
| SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); |
| |
| // NNN, D. MMMM YYYY System |
| // Long day of week: "NNNN" instead of "NNN," because of compatibility |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYSTEM_LONG ); |
| ImpInsertNewStandardFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_SYSTEM_LONG, ZF_STANDARD_DATE+8 ), |
| SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); |
| |
| // Hard coded but system (regional settings) delimiters dependent long date formats |
| // since numberformatter version 6 |
| |
| // D. MMM YY def/System |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DMMMYY ); |
| ImpInsertNewStandardFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_SYS_DMMMYY, ZF_STANDARD_DATE+9 ), |
| SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); |
| |
| //! Unfortunally TLOT intended only 10 builtin formats per category, more |
| //! would overwrite the next category (ZF_STANDARD_TIME) :-(( |
| //! Therefore they are inserted with nNewExtended++ (which is also limited) |
| |
| // D. MMM YYYY def/System |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DMMMYYYY ); |
| ImpInsertNewStandardFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_SYS_DMMMYYYY, nNewExtended++ ), |
| SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); |
| |
| // D. MMMM YYYY def/System |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DMMMMYYYY ); |
| ImpInsertNewStandardFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_SYS_DMMMMYYYY, nNewExtended++ ), |
| SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); |
| |
| // NN, D. MMM YY def/System |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_NNDMMMYY ); |
| ImpInsertNewStandardFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_SYS_NNDMMMYY, nNewExtended++ ), |
| SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); |
| |
| // NN, D. MMMM YYYY def/System |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_NNDMMMMYYYY ); |
| ImpInsertNewStandardFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_SYS_NNDMMMMYYYY, nNewExtended++ ), |
| SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); |
| |
| // NNN, D. MMMM YYYY def/System |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_NNNNDMMMMYYYY ); |
| ImpInsertNewStandardFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_SYS_NNNNDMMMMYYYY, nNewExtended++ ), |
| SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); |
| |
| // Hard coded DIN (Deutsche Industrie Norm) and EN (European Norm) date formats |
| |
| // D. MMM. YYYY DIN/EN |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_DMMMYYYY ); |
| ImpInsertNewStandardFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_DIN_DMMMYYYY, nNewExtended++ ), |
| SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); |
| |
| // D. MMMM YYYY DIN/EN |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_DMMMMYYYY ); |
| ImpInsertNewStandardFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_DIN_DMMMMYYYY, nNewExtended++ ), |
| SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); |
| |
| // MM-DD DIN/EN |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_MMDD ); |
| ImpInsertNewStandardFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_DIN_MMDD, nNewExtended++ ), |
| SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); |
| |
| // YY-MM-DD DIN/EN |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_YYMMDD ); |
| ImpInsertNewStandardFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_DIN_YYMMDD, nNewExtended++ ), |
| SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); |
| |
| // YYYY-MM-DD DIN/EN |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_YYYYMMDD ); |
| ImpInsertNewStandardFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATE_DIN_YYYYMMDD, nNewExtended++ ), |
| SV_NUMBERFORMATTER_VERSION_NEWSTANDARD ); |
| |
| |
| |
| // Time |
| aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::TIME ); |
| ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() ); |
| |
| // HH:MM |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HHMM ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_TIME_HHMM, ZF_STANDARD_TIME )); |
| |
| // HH:MM:SS |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HHMMSS ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_TIME_HHMMSS, ZF_STANDARD_TIME+1 )); |
| |
| // HH:MM AM/PM |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HHMMAMPM ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_TIME_HHMMAMPM, ZF_STANDARD_TIME+2 )); |
| |
| // HH:MM:SS AM/PM |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HHMMSSAMPM ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_TIME_HHMMSSAMPM, ZF_STANDARD_TIME+3 )); |
| |
| // [HH]:MM:SS |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HH_MMSS ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_TIME_HH_MMSS, ZF_STANDARD_TIME+4 )); |
| |
| // MM:SS,00 |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_MMSS00 ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_TIME_MMSS00, ZF_STANDARD_TIME+5 )); |
| |
| // [HH]:MM:SS,00 |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HH_MMSS00 ); |
| ImpInsertNewStandardFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_TIME_HH_MMSS00, ZF_STANDARD_TIME+6 ), |
| SV_NUMBERFORMATTER_VERSION_NF_TIME_HH_MMSS00 ); |
| |
| |
| |
| // DateTime |
| aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::DATE_TIME ); |
| ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() ); |
| |
| // DD.MM.YY HH:MM System |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATETIME_SYSTEM_SHORT_HHMM ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATETIME_SYSTEM_SHORT_HHMM, ZF_STANDARD_DATETIME )); |
| |
| // DD.MM.YYYY HH:MM:SS System |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATETIME_SYS_DDMMYYYY_HHMMSS ); |
| ImpInsertNewStandardFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_DATETIME_SYS_DDMMYYYY_HHMMSS, ZF_STANDARD_DATETIME+1 ), |
| SV_NUMBERFORMATTER_VERSION_NF_DATETIME_SYS_DDMMYYYY_HHMMSS ); |
| |
| |
| |
| // Scientific number |
| aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::SCIENTIFIC_NUMBER ); |
| ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() ); |
| |
| // 0.00E+000 |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_SCIENTIFIC_000E000 ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_SCIENTIFIC_000E000, ZF_STANDARD_SCIENTIFIC )); |
| |
| // 0.00E+00 |
| nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_SCIENTIFIC_000E00 ); |
| ImpInsertFormat( aFormatSeq[nIdx], |
| CLOffset + SetIndexTable( NF_SCIENTIFIC_000E00, ZF_STANDARD_SCIENTIFIC+1 )); |
| |
| |
| |
| // Fraction number (no default option) |
| i18n::NumberFormatCode aSingleFormatCode; |
| |
| // # ?/? |
| aSingleFormatCode.Code = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "# ?/?" ) ); |
| String s25( RTL_CONSTASCII_USTRINGPARAM( "# ?/?" ) ); // # ?/? |
| ImpInsertFormat( aSingleFormatCode, |
| CLOffset + SetIndexTable( NF_FRACTION_1, ZF_STANDARD_FRACTION )); |
| |
| // # ??/?? |
| //! "??/" would be interpreted by the compiler as a trigraph for '\' |
| aSingleFormatCode.Code = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "# ?\?/?\?" ) ); |
| ImpInsertFormat( aSingleFormatCode, |
| CLOffset + SetIndexTable( NF_FRACTION_2, ZF_STANDARD_FRACTION+1 )); |
| |
| // Week of year must be appended here because of nNewExtended |
| const NfKeywordTable & rKeyword = pFormatScanner->GetKeywords(); |
| aSingleFormatCode.Code = rKeyword[NF_KEY_WW]; |
| ImpInsertNewStandardFormat( aSingleFormatCode, |
| CLOffset + SetIndexTable( NF_DATE_WW, nNewExtended++ ), |
| SV_NUMBERFORMATTER_VERSION_NF_DATE_WW ); |
| |
| |
| |
| bIndexTableInitialized = sal_True; |
| DBG_ASSERT( nNewExtended <= ZF_STANDARD_NEWEXTENDEDMAX, |
| "ImpGenerateFormats: overflow of nNewExtended standard formats" ); |
| |
| // Now all additional format codes provided by I18N, but only if not |
| // loading from old SO5 file format, then they are appended last. |
| if ( !bLoadingSO5 ) |
| ImpGenerateAdditionalFormats( CLOffset, aNumberFormatCode, sal_False ); |
| |
| if (bOldConvertMode) |
| pFormatScanner->SetConvertMode(sal_True); |
| } |
| |
| |
| void SvNumberFormatter::ImpGenerateAdditionalFormats( sal_uInt32 CLOffset, |
| NumberFormatCodeWrapper& rNumberFormatCode, sal_Bool bAfterLoadingSO5 ) |
| { |
| using namespace ::com::sun::star; |
| |
| SvNumberformat* pStdFormat = |
| (SvNumberformat*) aFTable.Get( CLOffset + ZF_STANDARD ); |
| if ( !pStdFormat ) |
| { |
| DBG_ERRORFILE( "ImpGenerateAdditionalFormats: no GENERAL format" ); |
| return ; |
| } |
| sal_uInt32 nPos = CLOffset + pStdFormat->GetLastInsertKey(); |
| rNumberFormatCode.setLocale( GetLocale() ); |
| sal_Int32 j; |
| |
| // All currencies, this time with [$...] which was stripped in |
| // ImpGenerateFormats for old "automatic" currency formats. |
| uno::Sequence< i18n::NumberFormatCode > aFormatSeq = |
| rNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::CURRENCY ); |
| i18n::NumberFormatCode * pFormatArr = aFormatSeq.getArray(); |
| sal_Int32 nCodes = aFormatSeq.getLength(); |
| ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), nCodes ); |
| for ( j = 0; j < nCodes; j++ ) |
| { |
| if ( nPos - CLOffset >= SV_COUNTRY_LANGUAGE_OFFSET ) |
| { |
| DBG_ERRORFILE( "ImpGenerateAdditionalFormats: too many formats" ); |
| break; // for |
| } |
| if ( pFormatArr[j].Index < NF_INDEX_TABLE_ENTRIES && |
| pFormatArr[j].Index != NF_CURRENCY_1000DEC2_CCC ) |
| { // Insert only if not already inserted, but internal index must be |
| // above so ImpInsertFormat can distinguish it. |
| sal_Int16 nOrgIndex = pFormatArr[j].Index; |
| pFormatArr[j].Index = sal::static_int_cast< sal_Int16 >( |
| pFormatArr[j].Index + nCodes + NF_INDEX_TABLE_ENTRIES); |
| //! no default on currency |
| sal_Bool bDefault = aFormatSeq[j].Default; |
| aFormatSeq[j].Default = sal_False; |
| if ( ImpInsertNewStandardFormat( pFormatArr[j], nPos+1, |
| SV_NUMBERFORMATTER_VERSION_ADDITIONAL_I18N_FORMATS, |
| bAfterLoadingSO5, nOrgIndex ) ) |
| nPos++; |
| pFormatArr[j].Index = nOrgIndex; |
| aFormatSeq[j].Default = bDefault; |
| } |
| } |
| |
| // all additional format codes provided by I18N that are not old standard index |
| aFormatSeq = rNumberFormatCode.getAllFormatCodes(); |
| nCodes = aFormatSeq.getLength(); |
| if ( nCodes ) |
| { |
| pFormatArr = aFormatSeq.getArray(); |
| // don't check ALL |
| sal_Int32 nDef = ImpAdjustFormatCodeDefault( pFormatArr, nCodes, sal_False); |
| // don't have any defaults here |
| pFormatArr[nDef].Default = sal_False; |
| for ( j = 0; j < nCodes; j++ ) |
| { |
| if ( nPos - CLOffset >= SV_COUNTRY_LANGUAGE_OFFSET ) |
| { |
| DBG_ERRORFILE( "ImpGenerateAdditionalFormats: too many formats" ); |
| break; // for |
| } |
| if ( pFormatArr[j].Index >= NF_INDEX_TABLE_ENTRIES ) |
| if ( ImpInsertNewStandardFormat( pFormatArr[j], nPos+1, |
| SV_NUMBERFORMATTER_VERSION_ADDITIONAL_I18N_FORMATS, |
| bAfterLoadingSO5 ) ) |
| nPos++; |
| } |
| } |
| |
| pStdFormat->SetLastInsertKey( (sal_uInt16)(nPos - CLOffset) ); |
| } |
| |
| |
| void SvNumberFormatter::ImpGetPosCurrFormat( String& sPosStr, const String& rCurrSymbol ) |
| { |
| NfCurrencyEntry::CompletePositiveFormatString( sPosStr, |
| rCurrSymbol, xLocaleData->getCurrPositiveFormat() ); |
| } |
| |
| void SvNumberFormatter::ImpGetNegCurrFormat( String& sNegStr, const String& rCurrSymbol ) |
| { |
| NfCurrencyEntry::CompleteNegativeFormatString( sNegStr, |
| rCurrSymbol, xLocaleData->getCurrNegativeFormat() ); |
| } |
| |
| void SvNumberFormatter::GenerateFormat(String& sString, |
| sal_uInt32 nIndex, |
| LanguageType eLnge, |
| sal_Bool bThousand, |
| sal_Bool IsRed, |
| sal_uInt16 nPrecision, |
| sal_uInt16 nAnzLeading) |
| { |
| if (eLnge == LANGUAGE_DONTKNOW) |
| eLnge = IniLnge; |
| short eType = GetType(nIndex); |
| sal_uInt16 i; |
| ImpGenerateCL(eLnge); // ggfs. neu Standard- |
| // formate anlegen |
| sString.Erase(); |
| |
| utl::DigitGroupingIterator aGrouping( xLocaleData->getDigitGrouping()); |
| const xub_StrLen nDigitsInFirstGroup = static_cast<xub_StrLen>(aGrouping.get()); |
| const String& rThSep = GetNumThousandSep(); |
| if (nAnzLeading == 0) |
| { |
| if (!bThousand) |
| sString += '#'; |
| else |
| { |
| sString += '#'; |
| sString += rThSep; |
| sString.Expand( sString.Len() + nDigitsInFirstGroup, '#' ); |
| } |
| } |
| else |
| { |
| for (i = 0; i < nAnzLeading; i++) |
| { |
| if (bThousand && i > 0 && i == aGrouping.getPos()) |
| { |
| sString.Insert( rThSep, 0 ); |
| aGrouping.advance(); |
| } |
| sString.Insert('0',0); |
| } |
| if (bThousand && nAnzLeading < nDigitsInFirstGroup + 1) |
| { |
| for (i = nAnzLeading; i < nDigitsInFirstGroup + 1; i++) |
| { |
| if (bThousand && i % nDigitsInFirstGroup == 0) |
| sString.Insert( rThSep, 0 ); |
| sString.Insert('#',0); |
| } |
| } |
| } |
| if (nPrecision > 0) |
| { |
| sString += GetNumDecimalSep(); |
| sString.Expand( sString.Len() + nPrecision, '0' ); |
| } |
| if (eType == NUMBERFORMAT_PERCENT) |
| sString += '%'; |
| else if (eType == NUMBERFORMAT_CURRENCY) |
| { |
| String sNegStr = sString; |
| String aCurr; |
| const NfCurrencyEntry* pEntry; |
| sal_Bool bBank; |
| if ( GetNewCurrencySymbolString( nIndex, aCurr, &pEntry, &bBank ) ) |
| { |
| if ( pEntry ) |
| { |
| sal_uInt16 nPosiForm = NfCurrencyEntry::GetEffectivePositiveFormat( |
| xLocaleData->getCurrPositiveFormat(), |
| pEntry->GetPositiveFormat(), bBank ); |
| sal_uInt16 nNegaForm = NfCurrencyEntry::GetEffectiveNegativeFormat( |
| xLocaleData->getCurrNegativeFormat(), |
| pEntry->GetNegativeFormat(), bBank ); |
| pEntry->CompletePositiveFormatString( sString, bBank, |
| nPosiForm ); |
| pEntry->CompleteNegativeFormatString( sNegStr, bBank, |
| nNegaForm ); |
| } |
| else |
| { // assume currency abbreviation (AKA banking symbol), not symbol |
| sal_uInt16 nPosiForm = NfCurrencyEntry::GetEffectivePositiveFormat( |
| xLocaleData->getCurrPositiveFormat(), |
| xLocaleData->getCurrPositiveFormat(), sal_True ); |
| sal_uInt16 nNegaForm = NfCurrencyEntry::GetEffectiveNegativeFormat( |
| xLocaleData->getCurrNegativeFormat(), |
| xLocaleData->getCurrNegativeFormat(), sal_True ); |
| NfCurrencyEntry::CompletePositiveFormatString( sString, aCurr, |
| nPosiForm ); |
| NfCurrencyEntry::CompleteNegativeFormatString( sNegStr, aCurr, |
| nNegaForm ); |
| } |
| } |
| else |
| { // "automatic" old style |
| String aSymbol, aAbbrev; |
| GetCompatibilityCurrency( aSymbol, aAbbrev ); |
| ImpGetPosCurrFormat( sString, aSymbol ); |
| ImpGetNegCurrFormat( sNegStr, aSymbol ); |
| } |
| if (IsRed) |
| { |
| sString += ';'; |
| sString += '['; |
| sString += pFormatScanner->GetRedString(); |
| sString += ']'; |
| } |
| else |
| sString += ';'; |
| sString += sNegStr; |
| } |
| if (IsRed && eType != NUMBERFORMAT_CURRENCY) |
| { |
| String sTmpStr = sString; |
| sTmpStr += ';'; |
| sTmpStr += '['; |
| sTmpStr += pFormatScanner->GetRedString(); |
| sTmpStr += ']'; |
| sTmpStr += '-'; |
| sTmpStr +=sString; |
| sString = sTmpStr; |
| } |
| } |
| |
| sal_Bool SvNumberFormatter::IsUserDefined(const String& sStr, |
| LanguageType eLnge) |
| { |
| if (eLnge == LANGUAGE_DONTKNOW) |
| eLnge = IniLnge; |
| sal_uInt32 CLOffset = ImpGenerateCL(eLnge); // ggfs. neu Standard- |
| // formate anlegen |
| eLnge = ActLnge; |
| sal_uInt32 nKey = ImpIsEntry(sStr, CLOffset, eLnge); |
| if (nKey == NUMBERFORMAT_ENTRY_NOT_FOUND) |
| return sal_True; |
| SvNumberformat* pEntry = aFTable.Get(nKey); |
| if ( pEntry && ((pEntry->GetType() & NUMBERFORMAT_DEFINED) != 0) ) |
| return sal_True; |
| return sal_False; |
| } |
| |
| sal_uInt32 SvNumberFormatter::GetEntryKey(const String& sStr, |
| LanguageType eLnge) |
| { |
| if (eLnge == LANGUAGE_DONTKNOW) |
| eLnge = IniLnge; |
| sal_uInt32 CLOffset = ImpGenerateCL(eLnge); // ggfs. neu Standard- |
| // formate anlegen |
| return ImpIsEntry(sStr, CLOffset, eLnge); |
| } |
| |
| sal_uInt32 SvNumberFormatter::GetStandardIndex(LanguageType eLnge) |
| { |
| if (eLnge == LANGUAGE_DONTKNOW) |
| eLnge = IniLnge; |
| return GetStandardFormat(NUMBERFORMAT_NUMBER, eLnge); |
| } |
| |
| short SvNumberFormatter::GetType(sal_uInt32 nFIndex) |
| { |
| short eType; |
| SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get(nFIndex); |
| if (!pFormat) |
| eType = NUMBERFORMAT_UNDEFINED; |
| else |
| { |
| eType = pFormat->GetType() &~NUMBERFORMAT_DEFINED; |
| if (eType == 0) |
| eType = NUMBERFORMAT_DEFINED; |
| } |
| return eType; |
| } |
| |
| void SvNumberFormatter::ClearMergeTable() |
| { |
| if ( pMergeTable ) |
| { |
| sal_uInt32* pIndex = (sal_uInt32*) pMergeTable->First(); |
| while (pIndex) |
| { |
| delete pIndex; |
| pIndex = pMergeTable->Next(); |
| } |
| pMergeTable->Clear(); |
| } |
| } |
| |
| SvNumberFormatterIndexTable* SvNumberFormatter::MergeFormatter(SvNumberFormatter& rTable) |
| { |
| if ( pMergeTable ) |
| ClearMergeTable(); |
| else |
| pMergeTable = new SvNumberFormatterIndexTable; |
| sal_uInt32 nCLOffset = 0; |
| sal_uInt32 nOldKey, nOffset, nNewKey; |
| sal_uInt32* pNewIndex; |
| SvNumberformat* pNewEntry; |
| SvNumberformat* pFormat = rTable.aFTable.First(); |
| while (pFormat) |
| { |
| nOldKey = rTable.aFTable.GetCurKey(); |
| nOffset = nOldKey % SV_COUNTRY_LANGUAGE_OFFSET; // relativIndex |
| if (nOffset == 0) // 1. Format von CL |
| nCLOffset = ImpGenerateCL(pFormat->GetLanguage()); |
| |
| if (nOffset <= SV_MAX_ANZ_STANDARD_FORMATE) // Std.form. |
| { |
| nNewKey = nCLOffset + nOffset; |
| if (!aFTable.Get(nNewKey)) // noch nicht da |
| { |
| // pNewEntry = new SvNumberformat(*pFormat); // Copy reicht nicht !!! |
| pNewEntry = new SvNumberformat( *pFormat, *pFormatScanner ); |
| if (!aFTable.Insert(nNewKey, pNewEntry)) |
| delete pNewEntry; |
| } |
| if (nNewKey != nOldKey) // neuer Index |
| { |
| pNewIndex = new sal_uInt32(nNewKey); |
| if (!pMergeTable->Insert(nOldKey,pNewIndex)) |
| delete pNewIndex; |
| } |
| } |
| else // benutzerdef. |
| { |
| // pNewEntry = new SvNumberformat(*pFormat); // Copy reicht nicht !!! |
| pNewEntry = new SvNumberformat( *pFormat, *pFormatScanner ); |
| nNewKey = ImpIsEntry(pNewEntry->GetFormatstring(), |
| nCLOffset, |
| pFormat->GetLanguage()); |
| if (nNewKey != NUMBERFORMAT_ENTRY_NOT_FOUND) // schon vorhanden |
| delete pNewEntry; |
| else |
| { |
| SvNumberformat* pStdFormat = |
| (SvNumberformat*) aFTable.Get(nCLOffset + ZF_STANDARD); |
| sal_uInt32 nPos = nCLOffset + pStdFormat->GetLastInsertKey(); |
| nNewKey = nPos+1; |
| if (nPos - nCLOffset >= SV_COUNTRY_LANGUAGE_OFFSET) |
| { |
| DBG_ERROR( |
| "SvNumberFormatter:: Zu viele Formate pro CL"); |
| delete pNewEntry; |
| } |
| else if (!aFTable.Insert(nNewKey, pNewEntry)) |
| delete pNewEntry; |
| else |
| pStdFormat->SetLastInsertKey((sal_uInt16) (nNewKey - nCLOffset)); |
| } |
| if (nNewKey != nOldKey) // neuer Index |
| { |
| pNewIndex = new sal_uInt32(nNewKey); |
| if (!pMergeTable->Insert(nOldKey,pNewIndex)) |
| delete pNewIndex; |
| } |
| } |
| pFormat = rTable.aFTable.Next(); |
| } |
| return pMergeTable; |
| } |
| |
| |
| SvNumberFormatterMergeMap SvNumberFormatter::ConvertMergeTableToMap() |
| { |
| if (!HasMergeFmtTbl()) |
| return SvNumberFormatterMergeMap(); |
| |
| SvNumberFormatterMergeMap aMap; |
| for (sal_uInt32* pIndex = pMergeTable->First(); pIndex; pIndex = pMergeTable->Next()) |
| { |
| sal_uInt32 nOldKey = pMergeTable->GetCurKey(); |
| aMap.insert( SvNumberFormatterMergeMap::value_type( nOldKey, *pIndex)); |
| } |
| ClearMergeTable(); |
| return aMap; |
| } |
| |
| |
| sal_uInt32 SvNumberFormatter::GetFormatForLanguageIfBuiltIn( sal_uInt32 nFormat, |
| LanguageType eLnge ) |
| { |
| if ( eLnge == LANGUAGE_DONTKNOW ) |
| eLnge = IniLnge; |
| if ( nFormat < SV_COUNTRY_LANGUAGE_OFFSET && eLnge == IniLnge ) |
| return nFormat; // es bleibt wie es ist |
| sal_uInt32 nOffset = nFormat % SV_COUNTRY_LANGUAGE_OFFSET; // relativIndex |
| if ( nOffset > SV_MAX_ANZ_STANDARD_FORMATE ) |
| return nFormat; // kein eingebautes Format |
| sal_uInt32 nCLOffset = ImpGenerateCL(eLnge); // ggbf. generieren |
| return nCLOffset + nOffset; |
| } |
| |
| |
| sal_uInt32 SvNumberFormatter::GetFormatIndex( NfIndexTableOffset nTabOff, |
| LanguageType eLnge ) |
| { |
| if ( nTabOff >= NF_INDEX_TABLE_ENTRIES |
| || theIndexTable[nTabOff] == NUMBERFORMAT_ENTRY_NOT_FOUND ) |
| return NUMBERFORMAT_ENTRY_NOT_FOUND; |
| if ( eLnge == LANGUAGE_DONTKNOW ) |
| eLnge = IniLnge; |
| sal_uInt32 nCLOffset = ImpGenerateCL(eLnge); // ggbf. generieren |
| return nCLOffset + theIndexTable[nTabOff]; |
| } |
| |
| |
| NfIndexTableOffset SvNumberFormatter::GetIndexTableOffset( sal_uInt32 nFormat ) const |
| { |
| sal_uInt32 nOffset = nFormat % SV_COUNTRY_LANGUAGE_OFFSET; // relativIndex |
| if ( nOffset > SV_MAX_ANZ_STANDARD_FORMATE ) |
| return NF_INDEX_TABLE_ENTRIES; // kein eingebautes Format |
| for ( sal_uInt16 j = 0; j < NF_INDEX_TABLE_ENTRIES; j++ ) |
| { |
| if ( theIndexTable[j] == nOffset ) |
| return (NfIndexTableOffset) j; |
| } |
| return NF_INDEX_TABLE_ENTRIES; // bad luck |
| } |
| |
| |
| void SvNumberFormatter::SetYear2000( sal_uInt16 nVal ) |
| { |
| pStringScanner->SetYear2000( nVal ); |
| } |
| |
| |
| sal_uInt16 SvNumberFormatter::GetYear2000() const |
| { |
| return pStringScanner->GetYear2000(); |
| } |
| |
| |
| sal_uInt16 SvNumberFormatter::ExpandTwoDigitYear( sal_uInt16 nYear ) const |
| { |
| if ( nYear < 100 ) |
| return SvNumberFormatter::ExpandTwoDigitYear( nYear, |
| pStringScanner->GetYear2000() ); |
| return nYear; |
| } |
| |
| |
| // static |
| sal_uInt16 SvNumberFormatter::GetYear2000Default() |
| { |
| return (sal_uInt16) ::utl::MiscCfg().GetYear2000(); |
| } |
| |
| const String& SvNumberFormatter::GetTrueString(){return pFormatScanner->GetTrueString();} |
| const String& SvNumberFormatter::GetFalseString(){return pFormatScanner->GetFalseString();} |
| |
| // static |
| const NfCurrencyTable& SvNumberFormatter::GetTheCurrencyTable() |
| { |
| ::osl::MutexGuard aGuard( GetMutex() ); |
| while ( !bCurrencyTableInitialized ) |
| ImpInitCurrencyTable(); |
| return theCurrencyTable::get(); |
| } |
| |
| |
| // static |
| const NfCurrencyEntry* SvNumberFormatter::MatchSystemCurrency() |
| { |
| // MUST call GetTheCurrencyTable() before accessing nSystemCurrencyPosition |
| const NfCurrencyTable& rTable = GetTheCurrencyTable(); |
| return nSystemCurrencyPosition ? rTable[nSystemCurrencyPosition] : NULL; |
| } |
| |
| |
| // static |
| const NfCurrencyEntry& SvNumberFormatter::GetCurrencyEntry( LanguageType eLang ) |
| { |
| if ( eLang == LANGUAGE_SYSTEM ) |
| { |
| const NfCurrencyEntry* pCurr = MatchSystemCurrency(); |
| return pCurr ? *pCurr : *(GetTheCurrencyTable()[0]); |
| } |
| else |
| { |
| eLang = MsLangId::getRealLanguage( eLang ); |
| const NfCurrencyTable& rTable = GetTheCurrencyTable(); |
| sal_uInt16 nCount = rTable.Count(); |
| const NfCurrencyEntryPtr* ppData = rTable.GetData(); |
| for ( sal_uInt16 j = 0; j < nCount; j++, ppData++ ) |
| { |
| if ( (*ppData)->GetLanguage() == eLang ) |
| return **ppData; |
| } |
| return *(rTable[0]); |
| } |
| } |
| |
| |
| // static |
| const NfCurrencyEntry* SvNumberFormatter::GetCurrencyEntry( |
| const String& rAbbrev, LanguageType eLang ) |
| { |
| eLang = MsLangId::getRealLanguage( eLang ); |
| const NfCurrencyTable& rTable = GetTheCurrencyTable(); |
| sal_uInt16 nCount = rTable.Count(); |
| const NfCurrencyEntryPtr* ppData = rTable.GetData(); |
| for ( sal_uInt16 j = 0; j < nCount; j++, ppData++ ) |
| { |
| if ( (*ppData)->GetLanguage() == eLang && |
| (*ppData)->GetBankSymbol() == rAbbrev ) |
| return *ppData; |
| } |
| return NULL; |
| } |
| |
| |
| // static |
| const NfCurrencyEntry* SvNumberFormatter::GetLegacyOnlyCurrencyEntry( |
| const String& rSymbol, const String& rAbbrev ) |
| { |
| if (!bCurrencyTableInitialized) |
| GetTheCurrencyTable(); // just for initialization |
| const NfCurrencyTable& rTable = theLegacyOnlyCurrencyTable::get(); |
| sal_uInt16 nCount = rTable.Count(); |
| const NfCurrencyEntryPtr* ppData = rTable.GetData(); |
| for ( sal_uInt16 j = 0; j < nCount; j++, ppData++ ) |
| { |
| if ( (*ppData)->GetSymbol() == rSymbol && |
| (*ppData)->GetBankSymbol() == rAbbrev ) |
| return *ppData; |
| } |
| return NULL; |
| } |
| |
| |
| // static |
| IMPL_STATIC_LINK_NOINSTANCE( SvNumberFormatter, CurrencyChangeLink, void*, EMPTYARG ) |
| { |
| ::osl::MutexGuard aGuard( GetMutex() ); |
| String aAbbrev; |
| LanguageType eLang = LANGUAGE_SYSTEM; |
| SvtSysLocaleOptions().GetCurrencyAbbrevAndLanguage( aAbbrev, eLang ); |
| SetDefaultSystemCurrency( aAbbrev, eLang ); |
| return 0; |
| } |
| |
| |
| // static |
| void SvNumberFormatter::SetDefaultSystemCurrency( const String& rAbbrev, LanguageType eLang ) |
| { |
| ::osl::MutexGuard aGuard( GetMutex() ); |
| if ( eLang == LANGUAGE_SYSTEM ) |
| eLang = SvtSysLocale().GetLanguage(); |
| const NfCurrencyTable& rTable = GetTheCurrencyTable(); |
| sal_uInt16 nCount = rTable.Count(); |
| const NfCurrencyEntryPtr* ppData = rTable.GetData(); |
| if ( rAbbrev.Len() ) |
| { |
| for ( sal_uInt16 j = 0; j < nCount; j++, ppData++ ) |
| { |
| if ( (*ppData)->GetLanguage() == eLang && (*ppData)->GetBankSymbol() == rAbbrev ) |
| { |
| nSystemCurrencyPosition = j; |
| return ; |
| } |
| } |
| } |
| else |
| { |
| for ( sal_uInt16 j = 0; j < nCount; j++, ppData++ ) |
| { |
| if ( (*ppData)->GetLanguage() == eLang ) |
| { |
| nSystemCurrencyPosition = j; |
| return ; |
| } |
| } |
| } |
| nSystemCurrencyPosition = 0; // not found => simple SYSTEM |
| } |
| |
| |
| void SvNumberFormatter::ResetDefaultSystemCurrency() |
| { |
| nDefaultSystemCurrencyFormat = NUMBERFORMAT_ENTRY_NOT_FOUND; |
| } |
| |
| |
| sal_uInt32 SvNumberFormatter::ImpGetDefaultSystemCurrencyFormat() |
| { |
| if ( nDefaultSystemCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND ) |
| { |
| xub_StrLen nCheck; |
| short nType; |
| NfWSStringsDtor aCurrList; |
| sal_uInt16 nDefault = GetCurrencyFormatStrings( aCurrList, |
| GetCurrencyEntry( LANGUAGE_SYSTEM ), sal_False ); |
| DBG_ASSERT( aCurrList.Count(), "where is the NewCurrency System standard format?!?" ); |
| // if already loaded or user defined nDefaultSystemCurrencyFormat |
| // will be set to the right value |
| PutEntry( *aCurrList.GetObject( nDefault ), nCheck, nType, |
| nDefaultSystemCurrencyFormat, LANGUAGE_SYSTEM ); |
| DBG_ASSERT( nCheck == 0, "NewCurrency CheckError" ); |
| DBG_ASSERT( nDefaultSystemCurrencyFormat != NUMBERFORMAT_ENTRY_NOT_FOUND, |
| "nDefaultSystemCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND" ); |
| } |
| return nDefaultSystemCurrencyFormat; |
| } |
| |
| |
| sal_uInt32 SvNumberFormatter::ImpGetDefaultCurrencyFormat() |
| { |
| sal_uInt32 CLOffset = ImpGetCLOffset( ActLnge ); |
| sal_uInt32 nDefaultCurrencyFormat = |
| (sal_uInt32)(sal_uLong) aDefaultFormatKeys.Get( CLOffset + ZF_STANDARD_CURRENCY ); |
| if ( !nDefaultCurrencyFormat ) |
| nDefaultCurrencyFormat = NUMBERFORMAT_ENTRY_NOT_FOUND; |
| if ( nDefaultCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND ) |
| { |
| // look for a defined standard |
| sal_uInt32 nStopKey = CLOffset + SV_COUNTRY_LANGUAGE_OFFSET; |
| sal_uInt32 nKey; |
| aFTable.Seek( CLOffset ); |
| while ( (nKey = aFTable.GetCurKey()) >= CLOffset && nKey < nStopKey ) |
| { |
| const SvNumberformat* pEntry = |
| (const SvNumberformat*) aFTable.GetCurObject(); |
| if ( pEntry->IsStandard() && (pEntry->GetType() & NUMBERFORMAT_CURRENCY) ) |
| { |
| nDefaultCurrencyFormat = nKey; |
| break; // while |
| } |
| aFTable.Next(); |
| } |
| |
| if ( nDefaultCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND ) |
| { // none found, create one |
| xub_StrLen nCheck; |
| short nType; |
| NfWSStringsDtor aCurrList; |
| sal_uInt16 nDefault = GetCurrencyFormatStrings( aCurrList, |
| GetCurrencyEntry( ActLnge ), sal_False ); |
| DBG_ASSERT( aCurrList.Count(), "where is the NewCurrency standard format?" ); |
| if ( aCurrList.Count() ) |
| { |
| // if already loaded or user defined nDefaultSystemCurrencyFormat |
| // will be set to the right value |
| PutEntry( *aCurrList.GetObject( nDefault ), nCheck, nType, |
| nDefaultCurrencyFormat, ActLnge ); |
| DBG_ASSERT( nCheck == 0, "NewCurrency CheckError" ); |
| DBG_ASSERT( nDefaultCurrencyFormat != NUMBERFORMAT_ENTRY_NOT_FOUND, |
| "nDefaultCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND" ); |
| } |
| // old automatic currency format as a last resort |
| if ( nDefaultCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND ) |
| nDefaultCurrencyFormat = CLOffset + ZF_STANDARD_CURRENCY+3; |
| else |
| { // mark as standard so that it is found next time |
| SvNumberformat* pEntry = aFTable.Get( nDefaultCurrencyFormat ); |
| if ( pEntry ) |
| pEntry->SetStandard(); |
| } |
| } |
| aDefaultFormatKeys.Insert( CLOffset + ZF_STANDARD_CURRENCY, |
| (void*) nDefaultCurrencyFormat ); |
| } |
| return nDefaultCurrencyFormat; |
| } |
| |
| |
| // static |
| // try to make it inline if possible since this a loop body |
| // sal_True: continue; sal_False: break loop, if pFoundEntry==NULL dupe found |
| #ifndef DBG_UTIL |
| inline |
| #endif |
| sal_Bool SvNumberFormatter::ImpLookupCurrencyEntryLoopBody( |
| const NfCurrencyEntry*& pFoundEntry, sal_Bool& bFoundBank, |
| const NfCurrencyEntry* pData, sal_uInt16 nPos, const String& rSymbol ) |
| { |
| sal_Bool bFound; |
| if ( pData->GetSymbol() == rSymbol ) |
| { |
| bFound = sal_True; |
| bFoundBank = sal_False; |
| } |
| else if ( pData->GetBankSymbol() == rSymbol ) |
| { |
| bFound = sal_True; |
| bFoundBank = sal_True; |
| } |
| else |
| bFound = sal_False; |
| if ( bFound ) |
| { |
| if ( pFoundEntry && pFoundEntry != pData ) |
| { |
| pFoundEntry = NULL; |
| return sal_False; // break loop, not unique |
| } |
| if ( nPos == 0 ) |
| { // first entry is SYSTEM |
| pFoundEntry = MatchSystemCurrency(); |
| if ( pFoundEntry ) |
| return sal_False; // break loop |
| // even if there are more matching entries |
| // this one is propably the one we are looking for |
| else |
| pFoundEntry = pData; |
| } |
| else |
| pFoundEntry = pData; |
| } |
| return sal_True; |
| } |
| |
| |
| sal_Bool SvNumberFormatter::GetNewCurrencySymbolString( sal_uInt32 nFormat, |
| String& rStr, const NfCurrencyEntry** ppEntry /* = NULL */, |
| sal_Bool* pBank /* = NULL */ ) const |
| { |
| rStr.Erase(); |
| if ( ppEntry ) |
| *ppEntry = NULL; |
| if ( pBank ) |
| *pBank = sal_False; |
| SvNumberformat* pFormat = (SvNumberformat*) aFTable.Get( nFormat ); |
| if ( pFormat ) |
| { |
| String aSymbol, aExtension; |
| if ( pFormat->GetNewCurrencySymbol( aSymbol, aExtension ) ) |
| { |
| if ( ppEntry ) |
| { |
| sal_Bool bFoundBank = sal_False; |
| // we definiteley need an entry matching the format code string |
| const NfCurrencyEntry* pFoundEntry = GetCurrencyEntry( |
| bFoundBank, aSymbol, aExtension, pFormat->GetLanguage(), |
| sal_True ); |
| if ( pFoundEntry ) |
| { |
| *ppEntry = pFoundEntry; |
| if ( pBank ) |
| *pBank = bFoundBank; |
| pFoundEntry->BuildSymbolString( rStr, bFoundBank ); |
| } |
| } |
| if ( !rStr.Len() ) |
| { // analog zu BuildSymbolString |
| rStr = '['; |
| rStr += '$'; |
| if ( aSymbol.Search( '-' ) != STRING_NOTFOUND || |
| aSymbol.Search( ']' ) != STRING_NOTFOUND ) |
| { |
| rStr += '"'; |
| rStr += aSymbol; |
| rStr += '"'; |
| } |
| else |
| rStr += aSymbol; |
| if ( aExtension.Len() ) |
| rStr += aExtension; |
| rStr += ']'; |
| } |
| return sal_True; |
| } |
| } |
| return sal_False; |
| } |
| |
| |
| // static |
| const NfCurrencyEntry* SvNumberFormatter::GetCurrencyEntry( sal_Bool & bFoundBank, |
| const String& rSymbol, const String& rExtension, |
| LanguageType eFormatLanguage, sal_Bool bOnlyStringLanguage ) |
| { |
| xub_StrLen nExtLen = rExtension.Len(); |
| LanguageType eExtLang; |
| if ( nExtLen ) |
| { |
| sal_Int32 nExtLang = ::rtl::OUString( rExtension ).toInt32( 16 ); |
| if ( !nExtLang ) |
| eExtLang = LANGUAGE_DONTKNOW; |
| else |
| eExtLang = (LanguageType) ((nExtLang < 0) ? |
| -nExtLang : nExtLang); |
| } |
| else |
| eExtLang = LANGUAGE_DONTKNOW; |
| const NfCurrencyEntry* pFoundEntry = NULL; |
| const NfCurrencyTable& rTable = GetTheCurrencyTable(); |
| sal_uInt16 nCount = rTable.Count(); |
| sal_Bool bCont = sal_True; |
| |
| // first try with given extension language/country |
| if ( nExtLen ) |
| { |
| const NfCurrencyEntryPtr* ppData = rTable.GetData(); |
| for ( sal_uInt16 j = 0; j < nCount && bCont; j++, ppData++ ) |
| { |
| LanguageType eLang = (*ppData)->GetLanguage(); |
| if ( eLang == eExtLang || |
| ((eExtLang == LANGUAGE_DONTKNOW) && |
| (eLang == LANGUAGE_SYSTEM)) |
| ) |
| { |
| bCont = ImpLookupCurrencyEntryLoopBody( pFoundEntry, bFoundBank, |
| *ppData, j, rSymbol ); |
| } |
| } |
| } |
| |
| // ok? |
| if ( pFoundEntry || !bCont || (bOnlyStringLanguage && nExtLen) ) |
| return pFoundEntry; |
| |
| if ( !bOnlyStringLanguage ) |
| { |
| // now try the language/country of the number format |
| const NfCurrencyEntryPtr* ppData = rTable.GetData(); |
| for ( sal_uInt16 j = 0; j < nCount && bCont; j++, ppData++ ) |
| { |
| LanguageType eLang = (*ppData)->GetLanguage(); |
| if ( eLang == eFormatLanguage || |
| ((eFormatLanguage == LANGUAGE_DONTKNOW) && |
| (eLang == LANGUAGE_SYSTEM)) |
| ) |
| { |
| bCont = ImpLookupCurrencyEntryLoopBody( pFoundEntry, bFoundBank, |
| *ppData, j, rSymbol ); |
| } |
| } |
| |
| // ok? |
| if ( pFoundEntry || !bCont ) |
| return pFoundEntry; |
| } |
| |
| // then try without language/country if no extension specified |
| if ( !nExtLen ) |
| { |
| const NfCurrencyEntryPtr* ppData = rTable.GetData(); |
| for ( sal_uInt16 j = 0; j < nCount && bCont; j++, ppData++ ) |
| { |
| bCont = ImpLookupCurrencyEntryLoopBody( pFoundEntry, bFoundBank, |
| *ppData, j, rSymbol ); |
| } |
| } |
| |
| return pFoundEntry; |
| } |
| |
| |
| void SvNumberFormatter::GetCompatibilityCurrency( String& rSymbol, String& rAbbrev ) const |
| { |
| ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Currency2 > |
| xCurrencies = xLocaleData->getAllCurrencies(); |
| sal_Int32 nCurrencies = xCurrencies.getLength(); |
| sal_Int32 j; |
| for ( j=0; j < nCurrencies; ++j ) |
| { |
| if ( xCurrencies[j].UsedInCompatibleFormatCodes ) |
| { |
| rSymbol = xCurrencies[j].Symbol; |
| rAbbrev = xCurrencies[j].BankSymbol; |
| break; |
| } |
| } |
| if ( j >= nCurrencies ) |
| { |
| if (LocaleDataWrapper::areChecksEnabled()) |
| { |
| String aMsg( RTL_CONSTASCII_USTRINGPARAM( |
| "GetCompatibilityCurrency: none?")); |
| LocaleDataWrapper::outputCheckMessage( |
| xLocaleData->appendLocaleInfo( aMsg)); |
| } |
| rSymbol = xLocaleData->getCurrSymbol(); |
| rAbbrev = xLocaleData->getCurrBankSymbol(); |
| } |
| } |
| |
| |
| void lcl_CheckCurrencySymbolPosition( const NfCurrencyEntry& rCurr ) |
| { |
| short nPos = -1; // -1:=unknown, 0:=vorne, 1:=hinten |
| short nNeg = -1; |
| switch ( rCurr.GetPositiveFormat() ) |
| { |
| case 0: // $1 |
| nPos = 0; |
| break; |
| case 1: // 1$ |
| nPos = 1; |
| break; |
| case 2: // $ 1 |
| nPos = 0; |
| break; |
| case 3: // 1 $ |
| nPos = 1; |
| break; |
| default: |
| LocaleDataWrapper::outputCheckMessage( |
| "lcl_CheckCurrencySymbolPosition: unknown PositiveFormat"); |
| break; |
| } |
| switch ( rCurr.GetNegativeFormat() ) |
| { |
| case 0: // ($1) |
| nNeg = 0; |
| break; |
| case 1: // -$1 |
| nNeg = 0; |
| break; |
| case 2: // $-1 |
| nNeg = 0; |
| break; |
| case 3: // $1- |
| nNeg = 0; |
| break; |
| case 4: // (1$) |
| nNeg = 1; |
| break; |
| case 5: // -1$ |
| nNeg = 1; |
| break; |
| case 6: // 1-$ |
| nNeg = 1; |
| break; |
| case 7: // 1$- |
| nNeg = 1; |
| break; |
| case 8: // -1 $ |
| nNeg = 1; |
| break; |
| case 9: // -$ 1 |
| nNeg = 0; |
| break; |
| case 10: // 1 $- |
| nNeg = 1; |
| break; |
| case 11: // $ -1 |
| nNeg = 0; |
| break; |
| case 12 : // $ 1- |
| nNeg = 0; |
| break; |
| case 13 : // 1- $ |
| nNeg = 1; |
| break; |
| case 14 : // ($ 1) |
| nNeg = 0; |
| break; |
| case 15 : // (1 $) |
| nNeg = 1; |
| break; |
| default: |
| LocaleDataWrapper::outputCheckMessage( |
| "lcl_CheckCurrencySymbolPosition: unknown NegativeFormat"); |
| break; |
| } |
| if ( nPos >= 0 && nNeg >= 0 && nPos != nNeg ) |
| { |
| ByteString aStr( "positions of currency symbols differ\nLanguage: " ); |
| aStr += ByteString::CreateFromInt32( rCurr.GetLanguage() ); |
| aStr += " <"; |
| aStr += ByteString( rCurr.GetSymbol(), RTL_TEXTENCODING_UTF8 ); |
| aStr += "> positive: "; |
| aStr += ByteString::CreateFromInt32( rCurr.GetPositiveFormat() ); |
| aStr += ( nPos ? " (postfix)" : " (prefix)" ); |
| aStr += ", negative: "; |
| aStr += ByteString::CreateFromInt32( rCurr.GetNegativeFormat() ); |
| aStr += ( nNeg ? " (postfix)" : " (prefix)" ); |
| #if 0 |
| // seems that there really are some currencies which differ, e.g. YugoDinar |
| DBG_ERRORFILE( aStr.GetBuffer() ); |
| #endif |
| } |
| } |
| |
| |
| // static |
| void SvNumberFormatter::ImpInitCurrencyTable() |
| { |
| // racing condition possible: |
| // ::osl::MutexGuard aGuard( GetMutex() ); |
| // while ( !bCurrencyTableInitialized ) |
| // ImpInitCurrencyTable(); |
| static sal_Bool bInitializing = sal_False; |
| if ( bCurrencyTableInitialized || bInitializing ) |
| return ; |
| bInitializing = sal_True; |
| |
| RTL_LOGFILE_CONTEXT_AUTHOR( aTimeLog, "svl", "er93726", "SvNumberFormatter::ImpInitCurrencyTable" ); |
| |
| LanguageType eSysLang = SvtSysLocale().GetLanguage(); |
| LocaleDataWrapper* pLocaleData = new LocaleDataWrapper( |
| ::comphelper::getProcessServiceFactory(), |
| MsLangId::convertLanguageToLocale( eSysLang ) ); |
| // get user configured currency |
| String aConfiguredCurrencyAbbrev; |
| LanguageType eConfiguredCurrencyLanguage = LANGUAGE_SYSTEM; |
| SvtSysLocaleOptions().GetCurrencyAbbrevAndLanguage( |
| aConfiguredCurrencyAbbrev, eConfiguredCurrencyLanguage ); |
| sal_uInt16 nSecondarySystemCurrencyPosition = 0; |
| sal_uInt16 nMatchingSystemCurrencyPosition = 0; |
| NfCurrencyEntryPtr pEntry; |
| |
| // first entry is SYSTEM |
| pEntry = new NfCurrencyEntry( *pLocaleData, LANGUAGE_SYSTEM ); |
| theCurrencyTable::get().Insert( pEntry, 0 ); |
| sal_uInt16 nCurrencyPos = 1; |
| |
| ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > xLoc = |
| LocaleDataWrapper::getInstalledLocaleNames(); |
| sal_Int32 nLocaleCount = xLoc.getLength(); |
| RTL_LOGFILE_CONTEXT_TRACE1( aTimeLog, "number of locales: %ld", nLocaleCount ); |
| Locale const * const pLocales = xLoc.getConstArray(); |
| NfCurrencyTable &rCurrencyTable = theCurrencyTable::get(); |
| NfCurrencyTable &rLegacyOnlyCurrencyTable = theLegacyOnlyCurrencyTable::get(); |
| sal_uInt16 nLegacyOnlyCurrencyPos = 0; |
| for ( sal_Int32 nLocale = 0; nLocale < nLocaleCount; nLocale++ ) |
| { |
| LanguageType eLang = MsLangId::convertLocaleToLanguage( |
| pLocales[nLocale]); |
| #if OSL_DEBUG_LEVEL > 1 |
| LanguageType eReal = MsLangId::getRealLanguage( eLang ); |
| if ( eReal != eLang ) { |
| sal_Bool bBreak; |
| bBreak = sal_True; |
| } |
| #endif |
| pLocaleData->setLocale( pLocales[nLocale] ); |
| Sequence< Currency2 > aCurrSeq = pLocaleData->getAllCurrencies(); |
| sal_Int32 nCurrencyCount = aCurrSeq.getLength(); |
| Currency2 const * const pCurrencies = aCurrSeq.getConstArray(); |
| |
| // one default currency for each locale, insert first so it is found first |
| sal_Int32 nDefault; |
| for ( nDefault = 0; nDefault < nCurrencyCount; nDefault++ ) |
| { |
| if ( pCurrencies[nDefault].Default ) |
| break; |
| } |
| if ( nDefault < nCurrencyCount ) |
| pEntry = new NfCurrencyEntry( pCurrencies[nDefault], *pLocaleData, eLang ); |
| else |
| pEntry = new NfCurrencyEntry( *pLocaleData, eLang ); // first or ShellsAndPebbles |
| |
| if (LocaleDataWrapper::areChecksEnabled()) |
| lcl_CheckCurrencySymbolPosition( *pEntry ); |
| |
| rCurrencyTable.Insert( pEntry, nCurrencyPos++ ); |
| if ( !nSystemCurrencyPosition && (aConfiguredCurrencyAbbrev.Len() ? |
| pEntry->GetBankSymbol() == aConfiguredCurrencyAbbrev && |
| pEntry->GetLanguage() == eConfiguredCurrencyLanguage : sal_False) ) |
| nSystemCurrencyPosition = nCurrencyPos-1; |
| if ( !nMatchingSystemCurrencyPosition && |
| pEntry->GetLanguage() == eSysLang ) |
| nMatchingSystemCurrencyPosition = nCurrencyPos-1; |
| |
| // all remaining currencies for each locale |
| if ( nCurrencyCount > 1 ) |
| { |
| sal_Int32 nCurrency; |
| for ( nCurrency = 0; nCurrency < nCurrencyCount; nCurrency++ ) |
| { |
| if (pCurrencies[nCurrency].LegacyOnly) |
| { |
| pEntry = new NfCurrencyEntry( pCurrencies[nCurrency], *pLocaleData, eLang ); |
| rLegacyOnlyCurrencyTable.Insert( pEntry, nLegacyOnlyCurrencyPos++ ); |
| } |
| else if ( nCurrency != nDefault ) |
| { |
| pEntry = new NfCurrencyEntry( pCurrencies[nCurrency], *pLocaleData, eLang ); |
| // no dupes |
| sal_Bool bInsert = sal_True; |
| NfCurrencyEntry const * const * pData = rCurrencyTable.GetData(); |
| sal_uInt16 n = rCurrencyTable.Count(); |
| pData++; // skip first SYSTEM entry |
| for ( sal_uInt16 j=1; j<n; j++ ) |
| { |
| if ( *(*pData++) == *pEntry ) |
| { |
| bInsert = sal_False; |
| break; // for |
| } |
| } |
| if ( !bInsert ) |
| delete pEntry; |
| else |
| { |
| rCurrencyTable.Insert( pEntry, nCurrencyPos++ ); |
| if ( !nSecondarySystemCurrencyPosition && |
| (aConfiguredCurrencyAbbrev.Len() ? |
| pEntry->GetBankSymbol() == aConfiguredCurrencyAbbrev : |
| pEntry->GetLanguage() == eConfiguredCurrencyLanguage) ) |
| nSecondarySystemCurrencyPosition = nCurrencyPos-1; |
| if ( !nMatchingSystemCurrencyPosition && |
| pEntry->GetLanguage() == eSysLang ) |
| nMatchingSystemCurrencyPosition = nCurrencyPos-1; |
| } |
| } |
| } |
| } |
| } |
| if ( !nSystemCurrencyPosition ) |
| nSystemCurrencyPosition = nSecondarySystemCurrencyPosition; |
| if ((aConfiguredCurrencyAbbrev.Len() && !nSystemCurrencyPosition) && |
| LocaleDataWrapper::areChecksEnabled()) |
| LocaleDataWrapper::outputCheckMessage( |
| "SvNumberFormatter::ImpInitCurrencyTable: configured currency not in I18N locale data."); |
| // match SYSTEM if no configured currency found |
| if ( !nSystemCurrencyPosition ) |
| nSystemCurrencyPosition = nMatchingSystemCurrencyPosition; |
| if ((!aConfiguredCurrencyAbbrev.Len() && !nSystemCurrencyPosition) && |
| LocaleDataWrapper::areChecksEnabled()) |
| LocaleDataWrapper::outputCheckMessage( |
| "SvNumberFormatter::ImpInitCurrencyTable: system currency not in I18N locale data."); |
| delete pLocaleData; |
| SvtSysLocaleOptions::SetCurrencyChangeLink( |
| STATIC_LINK( NULL, SvNumberFormatter, CurrencyChangeLink ) ); |
| bInitializing = sal_False; |
| bCurrencyTableInitialized = sal_True; |
| } |
| |
| |
| sal_uInt16 SvNumberFormatter::GetCurrencyFormatStrings( NfWSStringsDtor& rStrArr, |
| const NfCurrencyEntry& rCurr, sal_Bool bBank ) const |
| { |
| sal_uInt16 nDefault = 0; |
| if ( bBank ) |
| { // nur Bankensymbole |
| String aPositiveBank, aNegativeBank; |
| rCurr.BuildPositiveFormatString( aPositiveBank, sal_True, *xLocaleData, 1 ); |
| rCurr.BuildNegativeFormatString( aNegativeBank, sal_True, *xLocaleData, 1 ); |
| |
| WSStringPtr pFormat1 = new String( aPositiveBank ); |
| *pFormat1 += ';'; |
| WSStringPtr pFormat2 = new String( *pFormat1 ); |
| |
| String aRed( '[' ); |
| aRed += pFormatScanner->GetRedString(); |
| aRed += ']'; |
| |
| *pFormat2 += aRed; |
| |
| *pFormat1 += aNegativeBank; |
| *pFormat2 += aNegativeBank; |
| |
| rStrArr.Insert( pFormat1, rStrArr.Count() ); |
| rStrArr.Insert( pFormat2, rStrArr.Count() ); |
| nDefault = rStrArr.Count() - 1; |
| } |
| else |
| { // gemischte Formate wie in SvNumberFormatter::ImpGenerateFormats |
| // aber keine doppelten, wenn keine Nachkommastellen in Waehrung |
| String aPositive, aNegative, aPositiveNoDec, aNegativeNoDec, |
| aPositiveDashed, aNegativeDashed; |
| WSStringPtr pFormat1, pFormat2, pFormat3, pFormat4, pFormat5; |
| |
| String aRed( '[' ); |
| aRed += pFormatScanner->GetRedString(); |
| aRed += ']'; |
| |
| rCurr.BuildPositiveFormatString( aPositive, sal_False, *xLocaleData, 1 ); |
| rCurr.BuildNegativeFormatString( aNegative, sal_False, *xLocaleData, 1 ); |
| if ( rCurr.GetDigits() ) |
| { |
| rCurr.BuildPositiveFormatString( aPositiveNoDec, sal_False, *xLocaleData, 0 ); |
| rCurr.BuildNegativeFormatString( aNegativeNoDec, sal_False, *xLocaleData, 0 ); |
| rCurr.BuildPositiveFormatString( aPositiveDashed, sal_False, *xLocaleData, 2 ); |
| rCurr.BuildNegativeFormatString( aNegativeDashed, sal_False, *xLocaleData, 2 ); |
| |
| pFormat1 = new String( aPositiveNoDec ); |
| *pFormat1 += ';'; |
| pFormat3 = new String( *pFormat1 ); |
| pFormat5 = new String( aPositiveDashed ); |
| *pFormat5 += ';'; |
| |
| *pFormat1 += aNegativeNoDec; |
| |
| *pFormat3 += aRed; |
| *pFormat5 += aRed; |
| |
| *pFormat3 += aNegativeNoDec; |
| *pFormat5 += aNegativeDashed; |
| } |
| else |
| { |
| pFormat1 = NULL; |
| pFormat3 = NULL; |
| pFormat5 = NULL; |
| } |
| |
| pFormat2 = new String( aPositive ); |
| *pFormat2 += ';'; |
| pFormat4 = new String( *pFormat2 ); |
| |
| *pFormat2 += aNegative; |
| |
| *pFormat4 += aRed; |
| *pFormat4 += aNegative; |
| |
| if ( pFormat1 ) |
| rStrArr.Insert( pFormat1, rStrArr.Count() ); |
| rStrArr.Insert( pFormat2, rStrArr.Count() ); |
| if ( pFormat3 ) |
| rStrArr.Insert( pFormat3, rStrArr.Count() ); |
| rStrArr.Insert( pFormat4, rStrArr.Count() ); |
| nDefault = rStrArr.Count() - 1; |
| if ( pFormat5 ) |
| rStrArr.Insert( pFormat5, rStrArr.Count() ); |
| } |
| return nDefault; |
| } |
| |
| |
| //--- NfCurrencyEntry ---------------------------------------------------- |
| |
| NfCurrencyEntry::NfCurrencyEntry() |
| : eLanguage( LANGUAGE_DONTKNOW ), |
| nPositiveFormat(3), |
| nNegativeFormat(8), |
| nDigits(2), |
| cZeroChar('0') |
| { |
| } |
| |
| |
| NfCurrencyEntry::NfCurrencyEntry( const LocaleDataWrapper& rLocaleData, LanguageType eLang ) |
| { |
| aSymbol = rLocaleData.getCurrSymbol(); |
| aBankSymbol = rLocaleData.getCurrBankSymbol(); |
| eLanguage = eLang; |
| nPositiveFormat = rLocaleData.getCurrPositiveFormat(); |
| nNegativeFormat = rLocaleData.getCurrNegativeFormat(); |
| nDigits = rLocaleData.getCurrDigits(); |
| cZeroChar = rLocaleData.getCurrZeroChar(); |
| } |
| |
| |
| NfCurrencyEntry::NfCurrencyEntry( const ::com::sun::star::i18n::Currency & rCurr, |
| const LocaleDataWrapper& rLocaleData, LanguageType eLang ) |
| { |
| aSymbol = rCurr.Symbol; |
| aBankSymbol = rCurr.BankSymbol; |
| eLanguage = eLang; |
| nPositiveFormat = rLocaleData.getCurrPositiveFormat(); |
| nNegativeFormat = rLocaleData.getCurrNegativeFormat(); |
| nDigits = rCurr.DecimalPlaces; |
| cZeroChar = rLocaleData.getCurrZeroChar(); |
| } |
| |
| |
| sal_Bool NfCurrencyEntry::operator==( const NfCurrencyEntry& r ) const |
| { |
| return aSymbol == r.aSymbol |
| && aBankSymbol == r.aBankSymbol |
| && eLanguage == r.eLanguage |
| ; |
| } |
| |
| |
| void NfCurrencyEntry::SetEuro() |
| { |
| aSymbol = NfCurrencyEntry::GetEuroSymbol(); |
| aBankSymbol.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "EUR" ) ); |
| eLanguage = LANGUAGE_DONTKNOW; |
| nPositiveFormat = 3; |
| nNegativeFormat = 8; |
| nDigits = 2; |
| cZeroChar = '0'; |
| } |
| |
| |
| sal_Bool NfCurrencyEntry::IsEuro() const |
| { |
| if ( aBankSymbol.EqualsAscii( "EUR" ) ) |
| return sal_True; |
| String aEuro( NfCurrencyEntry::GetEuroSymbol() ); |
| return aSymbol == aEuro; |
| } |
| |
| |
| void NfCurrencyEntry::ApplyVariableInformation( const NfCurrencyEntry& r ) |
| { |
| nPositiveFormat = r.nPositiveFormat; |
| nNegativeFormat = r.nNegativeFormat; |
| cZeroChar = r.cZeroChar; |
| } |
| |
| |
| void NfCurrencyEntry::BuildSymbolString( String& rStr, sal_Bool bBank, |
| sal_Bool bWithoutExtension ) const |
| { |
| rStr = '['; |
| rStr += '$'; |
| if ( bBank ) |
| rStr += aBankSymbol; |
| else |
| { |
| if ( aSymbol.Search( '-' ) != STRING_NOTFOUND || aSymbol.Search( ']' ) != STRING_NOTFOUND ) |
| { |
| rStr += '"'; |
| rStr += aSymbol; |
| rStr += '"'; |
| } |
| else |
| rStr += aSymbol; |
| if ( !bWithoutExtension && eLanguage != LANGUAGE_DONTKNOW && eLanguage != LANGUAGE_SYSTEM ) |
| { |
| rStr += '-'; |
| rStr += String::CreateFromInt32( sal_Int32( eLanguage ), 16 ).ToUpperAscii(); |
| } |
| } |
| rStr += ']'; |
| } |
| |
| |
| void NfCurrencyEntry::Impl_BuildFormatStringNumChars( String& rStr, |
| const LocaleDataWrapper& rLoc, sal_uInt16 nDecimalFormat ) const |
| { |
| rStr.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "###0" ) ); |
| rStr.Insert( rLoc.getNumThousandSep(), 1 ); |
| if ( nDecimalFormat && nDigits ) |
| { |
| rStr += rLoc.getNumDecimalSep(); |
| rStr.Expand( rStr.Len() + nDigits, (nDecimalFormat == 2 ? '-' : cZeroChar) ); |
| } |
| } |
| |
| |
| void NfCurrencyEntry::BuildPositiveFormatString( String& rStr, sal_Bool bBank, |
| const LocaleDataWrapper& rLoc, sal_uInt16 nDecimalFormat ) const |
| { |
| Impl_BuildFormatStringNumChars( rStr, rLoc, nDecimalFormat ); |
| sal_uInt16 nPosiForm = NfCurrencyEntry::GetEffectivePositiveFormat( |
| rLoc.getCurrPositiveFormat(), nPositiveFormat, bBank ); |
| CompletePositiveFormatString( rStr, bBank, nPosiForm ); |
| } |
| |
| |
| void NfCurrencyEntry::BuildNegativeFormatString( String& rStr, sal_Bool bBank, |
| const LocaleDataWrapper& rLoc, sal_uInt16 nDecimalFormat ) const |
| { |
| Impl_BuildFormatStringNumChars( rStr, rLoc, nDecimalFormat ); |
| sal_uInt16 nNegaForm = NfCurrencyEntry::GetEffectiveNegativeFormat( |
| rLoc.getCurrNegativeFormat(), nNegativeFormat, bBank ); |
| CompleteNegativeFormatString( rStr, bBank, nNegaForm ); |
| } |
| |
| |
| void NfCurrencyEntry::CompletePositiveFormatString( String& rStr, sal_Bool bBank, |
| sal_uInt16 nPosiForm ) const |
| { |
| String aSymStr; |
| BuildSymbolString( aSymStr, bBank ); |
| NfCurrencyEntry::CompletePositiveFormatString( rStr, aSymStr, nPosiForm ); |
| } |
| |
| |
| void NfCurrencyEntry::CompleteNegativeFormatString( String& rStr, sal_Bool bBank, |
| sal_uInt16 nNegaForm ) const |
| { |
| String aSymStr; |
| BuildSymbolString( aSymStr, bBank ); |
| NfCurrencyEntry::CompleteNegativeFormatString( rStr, aSymStr, nNegaForm ); |
| } |
| |
| |
| // static |
| void NfCurrencyEntry::CompletePositiveFormatString( String& rStr, |
| const String& rSymStr, sal_uInt16 nPositiveFormat ) |
| { |
| switch( nPositiveFormat ) |
| { |
| case 0: // $1 |
| rStr.Insert( rSymStr , 0 ); |
| break; |
| case 1: // 1$ |
| rStr += rSymStr; |
| break; |
| case 2: // $ 1 |
| { |
| rStr.Insert( ' ', 0 ); |
| rStr.Insert( rSymStr, 0 ); |
| } |
| break; |
| case 3: // 1 $ |
| { |
| rStr += ' '; |
| rStr += rSymStr; |
| } |
| break; |
| default: |
| DBG_ERROR("NfCurrencyEntry::CompletePositiveFormatString: unknown option"); |
| break; |
| } |
| } |
| |
| |
| // static |
| void NfCurrencyEntry::CompleteNegativeFormatString( String& rStr, |
| const String& rSymStr, sal_uInt16 nNegativeFormat ) |
| { |
| switch( nNegativeFormat ) |
| { |
| case 0: // ($1) |
| { |
| rStr.Insert( rSymStr, 0); |
| rStr.Insert('(',0); |
| rStr += ')'; |
| } |
| break; |
| case 1: // -$1 |
| { |
| rStr.Insert( rSymStr, 0); |
| rStr.Insert('-',0); |
| } |
| break; |
| case 2: // $-1 |
| { |
| rStr.Insert('-',0); |
| rStr.Insert( rSymStr, 0); |
| } |
| break; |
| case 3: // $1- |
| { |
| rStr.Insert( rSymStr, 0); |
| rStr += '-'; |
| } |
| break; |
| case 4: // (1$) |
| { |
| rStr.Insert('(',0); |
| rStr += rSymStr; |
| rStr += ')'; |
| } |
| break; |
| case 5: // -1$ |
| { |
| rStr += rSymStr; |
| rStr.Insert('-',0); |
| } |
| break; |
| case 6: // 1-$ |
| { |
| rStr += '-'; |
| rStr += rSymStr; |
| } |
| break; |
| case 7: // 1$- |
| { |
| rStr += rSymStr; |
| rStr += '-'; |
| } |
| break; |
| case 8: // -1 $ |
| { |
| rStr += ' '; |
| rStr += rSymStr; |
| rStr.Insert('-',0); |
| } |
| break; |
| case 9: // -$ 1 |
| { |
| rStr.Insert(' ',0); |
| rStr.Insert( rSymStr, 0); |
| rStr.Insert('-',0); |
| } |
| break; |
| case 10: // 1 $- |
| { |
| rStr += ' '; |
| rStr += rSymStr; |
| rStr += '-'; |
| } |
| break; |
| case 11: // $ -1 |
| { |
| String aTmp( rSymStr ); |
| aTmp += ' '; |
| aTmp += '-'; |
| rStr.Insert( aTmp, 0 ); |
| } |
| break; |
| case 12 : // $ 1- |
| { |
| rStr.Insert(' ', 0); |
| rStr.Insert( rSymStr, 0); |
| rStr += '-'; |
| } |
| break; |
| case 13 : // 1- $ |
| { |
| rStr += '-'; |
| rStr += ' '; |
| rStr += rSymStr; |
| } |
| break; |
| case 14 : // ($ 1) |
| { |
| rStr.Insert(' ',0); |
| rStr.Insert( rSymStr, 0); |
| rStr.Insert('(',0); |
| rStr += ')'; |
| } |
| break; |
| case 15 : // (1 $) |
| { |
| rStr.Insert('(',0); |
| rStr += ' '; |
| rStr += rSymStr; |
| rStr += ')'; |
| } |
| break; |
| default: |
| DBG_ERROR("NfCurrencyEntry::CompleteNegativeFormatString: unknown option"); |
| break; |
| } |
| } |
| |
| |
| // static |
| sal_uInt16 NfCurrencyEntry::GetEffectivePositiveFormat( sal_uInt16 |
| #if ! NF_BANKSYMBOL_FIX_POSITION |
| nIntlFormat |
| #endif |
| , sal_uInt16 nCurrFormat, sal_Bool bBank ) |
| { |
| if ( bBank ) |
| { |
| #if NF_BANKSYMBOL_FIX_POSITION |
| return 3; |
| #else |
| switch ( nIntlFormat ) |
| { |
| case 0: // $1 |
| nIntlFormat = 2; // $ 1 |
| break; |
| case 1: // 1$ |
| nIntlFormat = 3; // 1 $ |
| break; |
| case 2: // $ 1 |
| break; |
| case 3: // 1 $ |
| break; |
| default: |
| DBG_ERROR("NfCurrencyEntry::GetEffectivePositiveFormat: unknown option"); |
| break; |
| } |
| return nIntlFormat; |
| #endif |
| } |
| else |
| return nCurrFormat; |
| } |
| |
| |
| // nur aufrufen, wenn nCurrFormat wirklich mit Klammern ist |
| sal_uInt16 lcl_MergeNegativeParenthesisFormat( sal_uInt16 nIntlFormat, sal_uInt16 nCurrFormat ) |
| { |
| short nSign = 0; // -1:=Klammer 0:=links, 1:=mitte, 2:=rechts |
| switch ( nIntlFormat ) |
| { |
| case 0: // ($1) |
| case 4: // (1$) |
| case 14 : // ($ 1) |
| case 15 : // (1 $) |
| return nCurrFormat; |
| case 1: // -$1 |
| case 5: // -1$ |
| case 8: // -1 $ |
| case 9: // -$ 1 |
| nSign = 0; |
| break; |
| case 2: // $-1 |
| case 6: // 1-$ |
| case 11 : // $ -1 |
| case 13 : // 1- $ |
| nSign = 1; |
| break; |
| case 3: // $1- |
| case 7: // 1$- |
| case 10: // 1 $- |
| case 12 : // $ 1- |
| nSign = 2; |
| break; |
| default: |
| DBG_ERROR("lcl_MergeNegativeParenthesisFormat: unknown option"); |
| break; |
| } |
| |
| switch ( nCurrFormat ) |
| { |
| case 0: // ($1) |
| switch ( nSign ) |
| { |
| case 0: |
| return 1; // -$1 |
| case 1: |
| return 2; // $-1 |
| case 2: |
| return 3; // $1- |
| } |
| break; |
| case 4: // (1$) |
| switch ( nSign ) |
| { |
| case 0: |
| return 5; // -1$ |
| case 1: |
| return 6; // 1-$ |
| case 2: |
| return 7; // 1$- |
| } |
| break; |
| case 14 : // ($ 1) |
| switch ( nSign ) |
| { |
| case 0: |
| return 9; // -$ 1 |
| case 1: |
| return 11; // $ -1 |
| case 2: |
| return 12; // $ 1- |
| } |
| break; |
| case 15 : // (1 $) |
| switch ( nSign ) |
| { |
| case 0: |
| return 8; // -1 $ |
| case 1: |
| return 13; // 1- $ |
| case 2: |
| return 10; // 1 $- |
| } |
| break; |
| } |
| return nCurrFormat; |
| } |
| |
| |
| // static |
| sal_uInt16 NfCurrencyEntry::GetEffectiveNegativeFormat( sal_uInt16 nIntlFormat, |
| sal_uInt16 nCurrFormat, sal_Bool bBank ) |
| { |
| if ( bBank ) |
| { |
| #if NF_BANKSYMBOL_FIX_POSITION |
| return 8; |
| #else |
| switch ( nIntlFormat ) |
| { |
| case 0: // ($1) |
| // nIntlFormat = 14; // ($ 1) |
| nIntlFormat = 9; // -$ 1 |
| break; |
| case 1: // -$1 |
| nIntlFormat = 9; // -$ 1 |
| break; |
| case 2: // $-1 |
| nIntlFormat = 11; // $ -1 |
| break; |
| case 3: // $1- |
| nIntlFormat = 12; // $ 1- |
| break; |
| case 4: // (1$) |
| // nIntlFormat = 15; // (1 $) |
| nIntlFormat = 8; // -1 $ |
| break; |
| case 5: // -1$ |
| nIntlFormat = 8; // -1 $ |
| break; |
| case 6: // 1-$ |
| nIntlFormat = 13; // 1- $ |
| break; |
| case 7: // 1$- |
| nIntlFormat = 10; // 1 $- |
| break; |
| case 8: // -1 $ |
| break; |
| case 9: // -$ 1 |
| break; |
| case 10: // 1 $- |
| break; |
| case 11: // $ -1 |
| break; |
| case 12 : // $ 1- |
| break; |
| case 13 : // 1- $ |
| break; |
| case 14 : // ($ 1) |
| // nIntlFormat = 14; // ($ 1) |
| nIntlFormat = 9; // -$ 1 |
| break; |
| case 15 : // (1 $) |
| // nIntlFormat = 15; // (1 $) |
| nIntlFormat = 8; // -1 $ |
| break; |
| default: |
| DBG_ERROR("NfCurrencyEntry::GetEffectiveNegativeFormat: unknown option"); |
| break; |
| } |
| #endif |
| } |
| else if ( nIntlFormat != nCurrFormat ) |
| { |
| switch ( nCurrFormat ) |
| { |
| case 0: // ($1) |
| nIntlFormat = lcl_MergeNegativeParenthesisFormat( |
| nIntlFormat, nCurrFormat ); |
| break; |
| case 1: // -$1 |
| nIntlFormat = nCurrFormat; |
| break; |
| case 2: // $-1 |
| nIntlFormat = nCurrFormat; |
| break; |
| case 3: // $1- |
| nIntlFormat = nCurrFormat; |
| break; |
| case 4: // (1$) |
| nIntlFormat = lcl_MergeNegativeParenthesisFormat( |
| nIntlFormat, nCurrFormat ); |
| break; |
| case 5: // -1$ |
| nIntlFormat = nCurrFormat; |
| break; |
| case 6: // 1-$ |
| nIntlFormat = nCurrFormat; |
| break; |
| case 7: // 1$- |
| nIntlFormat = nCurrFormat; |
| break; |
| case 8: // -1 $ |
| nIntlFormat = nCurrFormat; |
| break; |
| case 9: // -$ 1 |
| nIntlFormat = nCurrFormat; |
| break; |
| case 10: // 1 $- |
| nIntlFormat = nCurrFormat; |
| break; |
| case 11: // $ -1 |
| nIntlFormat = nCurrFormat; |
| break; |
| case 12 : // $ 1- |
| nIntlFormat = nCurrFormat; |
| break; |
| case 13 : // 1- $ |
| nIntlFormat = nCurrFormat; |
| break; |
| case 14 : // ($ 1) |
| nIntlFormat = lcl_MergeNegativeParenthesisFormat( |
| nIntlFormat, nCurrFormat ); |
| break; |
| case 15 : // (1 $) |
| nIntlFormat = lcl_MergeNegativeParenthesisFormat( |
| nIntlFormat, nCurrFormat ); |
| break; |
| default: |
| DBG_ERROR("NfCurrencyEntry::GetEffectiveNegativeFormat: unknown option"); |
| break; |
| } |
| } |
| return nIntlFormat; |
| } |
| |
| |
| // we only support default encodings here |
| // static |
| sal_Char NfCurrencyEntry::GetEuroSymbol( rtl_TextEncoding eTextEncoding ) |
| { |
| switch ( eTextEncoding ) |
| { |
| case RTL_TEXTENCODING_MS_1252 : // WNT Ansi |
| case RTL_TEXTENCODING_ISO_8859_1 : // UNX for use with TrueType fonts |
| return '\x80'; |
| case RTL_TEXTENCODING_ISO_8859_15 : // UNX real |
| return '\xA4'; |
| case RTL_TEXTENCODING_IBM_850 : // OS2 |
| return '\xD5'; |
| case RTL_TEXTENCODING_APPLE_ROMAN : // MAC |
| return '\xDB'; |
| default: // default system |
| #if WNT |
| return '\x80'; |
| #elif OS2 |
| return '\xD5'; |
| #elif UNX |
| // return '\xA4'; // #56121# 0xA4 waere korrekt fuer iso-8859-15 |
| return '\x80'; // aber Windoze-Code fuer die konvertierten TrueType-Fonts |
| #else |
| #error EuroSymbol is what? |
| return '\x80'; |
| #endif |
| } |
| return '\x80'; |
| } |
| |
| |
| |