blob: 6103dc7496273a04389bb23185462951ce5ce445 [file] [log] [blame]
/**************************************************************
*
* 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';
}