1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: zforlist.cxx,v $
10 * $Revision: 1.72.60.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
37 #include <tools/debug.hxx>
38 #ifndef _SOUND_HXX //autogen
39 #include <vcl/sound.hxx>
41 #include <vcl/svapp.hxx>
42 #include <vcl/settings.hxx>
43 #include <unotools/charclass.hxx>
44 #include <i18npool/mslangid.hxx>
45 #include <unotools/localedatawrapper.hxx>
46 #include <unotools/numberformatcodewrapper.hxx>
47 #include <unotools/calendarwrapper.hxx>
48 #include <com/sun/star/i18n/KNumberFormatUsage.hpp>
49 #include <com/sun/star/i18n/KNumberFormatType.hpp>
50 #include <comphelper/processfactory.hxx>
52 #define _SVSTDARR_USHORTS
53 #include <svtools/svstdarr.hxx>
56 #include <osl/mutex.hxx>
57 #include <svtools/zforlist.hxx>
60 #include "zforscan.hxx"
61 #include "zforfind.hxx"
62 #include <svtools/zformat.hxx>
63 #include "numhead.hxx"
65 #include <svtools/syslocaleoptions.hxx>
66 #include "listener.hxx"
67 #include <svtools/smplhint.hxx>
68 #include <unotools/digitgroupingiterator.hxx>
69 #include <rtl/logfile.hxx>
70 #include <rtl/instance.hxx>
74 using namespace ::com::sun::star
;
75 using namespace ::com::sun::star::uno
;
76 using namespace ::com::sun::star::i18n
;
77 using namespace ::com::sun::star::lang
;
80 // Constants for type offsets per Country/Language (CL)
82 #define ZF_STANDARD_PERCENT 10
83 #define ZF_STANDARD_CURRENCY 20
84 #define ZF_STANDARD_DATE 30
85 #define ZF_STANDARD_TIME 40
86 #define ZF_STANDARD_DATETIME 50
87 #define ZF_STANDARD_SCIENTIFIC 60
88 #define ZF_STANDARD_FRACTION 70
89 #define ZF_STANDARD_NEWEXTENDED 75
90 #define ZF_STANDARD_NEWEXTENDEDMAX SV_MAX_ANZ_STANDARD_FORMATE-2 // 98
91 #define ZF_STANDARD_LOGICAL SV_MAX_ANZ_STANDARD_FORMATE-1 // 99
92 #define ZF_STANDARD_TEXT SV_MAX_ANZ_STANDARD_FORMATE // 100
94 /* Locale that is set if an unknown locale (from another system) is loaded of
95 * legacy documents. Can not be SYSTEM because else, for example, a German "DM"
96 * (old currency) is recognized as a date (#53155#). */
97 #define UNKNOWN_SUBSTITUTE LANGUAGE_ENGLISH_US
99 static BOOL bIndexTableInitialized
= FALSE
;
100 static sal_uInt32 __FAR_DATA theIndexTable
[NF_INDEX_TABLE_ENTRIES
];
103 // ====================================================================
106 instead of every number formatter being a listener we have a registry which
107 also handles one instance of the SysLocale options
110 class SvNumberFormatterRegistry_Impl
: public SvtListener
113 SvtSysLocaleOptions aSysLocaleOptions
;
114 LanguageType eSysLanguage
;
117 SvNumberFormatterRegistry_Impl();
118 virtual ~SvNumberFormatterRegistry_Impl();
120 void Insert( SvNumberFormatter
* pThis
)
121 { aFormatters
.Insert( pThis
, LIST_APPEND
); }
122 SvNumberFormatter
* Remove( SvNumberFormatter
* pThis
)
123 { return (SvNumberFormatter
*)aFormatters
.Remove( pThis
); }
125 { return aFormatters
.Count(); }
127 virtual void Notify( SvtBroadcaster
& rBC
, const SfxHint
& rHint
);
132 SvNumberFormatterRegistry_Impl::SvNumberFormatterRegistry_Impl()
134 eSysLanguage
= MsLangId::getRealLanguage( LANGUAGE_SYSTEM
);
135 aSysLocaleOptions
.AddListener( *this );
139 SvNumberFormatterRegistry_Impl::~SvNumberFormatterRegistry_Impl()
141 aSysLocaleOptions
.RemoveListener( *this );
145 void SvNumberFormatterRegistry_Impl::Notify( SvtBroadcaster
&, const SfxHint
& rHint
)
147 const SfxSimpleHint
* pHint
= PTR_CAST( SfxSimpleHint
, &rHint
);
150 if ( pHint
->GetId() & SYSLOCALEOPTIONS_HINT_LOCALE
)
152 ::osl::MutexGuard
aGuard( SvNumberFormatter::GetMutex() );
153 for ( SvNumberFormatter
* p
= (SvNumberFormatter
*)aFormatters
.First();
154 p
; p
= (SvNumberFormatter
*)aFormatters
.Next() )
156 p
->ReplaceSystemCL( eSysLanguage
);
158 eSysLanguage
= MsLangId::getRealLanguage( LANGUAGE_SYSTEM
);
160 if ( pHint
->GetId() & SYSLOCALEOPTIONS_HINT_CURRENCY
)
162 ::osl::MutexGuard
aGuard( SvNumberFormatter::GetMutex() );
163 for ( SvNumberFormatter
* p
= (SvNumberFormatter
*)aFormatters
.First();
164 p
; p
= (SvNumberFormatter
*)aFormatters
.Next() )
166 p
->ResetDefaultSystemCurrency();
173 // ====================================================================
175 SvNumberFormatterRegistry_Impl
* SvNumberFormatter::pFormatterRegistry
= NULL
;
176 BOOL
SvNumberFormatter::bCurrencyTableInitialized
= FALSE
;
179 struct theCurrencyTable
:
180 public rtl::Static
< NfCurrencyTable
, theCurrencyTable
> {};
182 struct theLegacyOnlyCurrencyTable
:
183 public rtl::Static
< NfCurrencyTable
, theLegacyOnlyCurrencyTable
> {};
185 USHORT
SvNumberFormatter::nSystemCurrencyPosition
= 0;
186 SV_IMPL_PTRARR( NfCurrencyTable
, NfCurrencyEntry
* );
187 SV_IMPL_PTRARR( NfWSStringsDtor
, String
* );
189 // ob das BankSymbol immer am Ende ist (1 $;-1 $) oder sprachabhaengig
190 #define NF_BANKSYMBOL_FIX_POSITION 1
193 /***********************Funktionen SvNumberFormatter**************************/
195 SvNumberFormatter::SvNumberFormatter(
196 const Reference
< XMultiServiceFactory
>& xSMgr
,
199 xServiceManager( xSMgr
)
201 ImpConstruct( eLang
);
205 SvNumberFormatter::SvNumberFormatter( LanguageType eLang
)
207 ImpConstruct( eLang
);
211 SvNumberFormatter::~SvNumberFormatter()
214 ::osl::MutexGuard
aGuard( GetMutex() );
215 pFormatterRegistry
->Remove( this );
216 if ( !pFormatterRegistry
->Count() )
218 delete pFormatterRegistry
;
219 pFormatterRegistry
= NULL
;
223 SvNumberformat
* pEntry
= aFTable
.First();
227 pEntry
= aFTable
.Next();
231 delete pStringScanner
;
232 delete pFormatScanner
;
238 void SvNumberFormatter::ImpConstruct( LanguageType eLang
)
240 RTL_LOGFILE_CONTEXT_AUTHOR( aTimeLog
, "svtools", "er93726", "SvNumberFormatter::ImpConstruct" );
242 if ( eLang
== LANGUAGE_DONTKNOW
)
243 eLang
= UNKNOWN_SUBSTITUTE
;
246 eEvalDateFormat
= NF_EVALDATEFORMAT_INTL
;
247 nDefaultSystemCurrencyFormat
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
249 aLocale
= MsLangId::convertLanguageToLocale( eLang
);
250 pCharClass
= new CharClass( xServiceManager
, aLocale
);
251 xLocaleData
.init( xServiceManager
, aLocale
, eLang
);
252 xCalendar
.init( xServiceManager
, aLocale
);
253 xTransliteration
.init( xServiceManager
, eLang
,
254 ::com::sun::star::i18n::TransliterationModules_IGNORE_CASE
);
255 xNatNum
.init( xServiceManager
);
257 // cached locale data items
258 const LocaleDataWrapper
* pLoc
= GetLocaleData();
259 aDecimalSep
= pLoc
->getNumDecimalSep();
260 aThousandSep
= pLoc
->getNumThousandSep();
261 aDateSep
= pLoc
->getDateSep();
263 pStringScanner
= new ImpSvNumberInputScan( this );
264 pFormatScanner
= new ImpSvNumberformatScan( this );
267 ImpGenerateFormats( 0, FALSE
); // 0 .. 999 for initialized language formats
271 ::osl::MutexGuard
aGuard( GetMutex() );
272 GetFormatterRegistry().Insert( this );
276 void SvNumberFormatter::ChangeIntl(LanguageType eLnge
)
278 if (ActLnge
!= eLnge
)
282 aLocale
= MsLangId::convertLanguageToLocale( eLnge
);
283 pCharClass
->setLocale( aLocale
);
284 xLocaleData
.changeLocale( aLocale
, eLnge
);
285 xCalendar
.changeLocale( aLocale
);
286 xTransliteration
.changeLocale( eLnge
);
288 // cached locale data items, initialize BEFORE calling ChangeIntl below
289 const LocaleDataWrapper
* pLoc
= GetLocaleData();
290 aDecimalSep
= pLoc
->getNumDecimalSep();
291 aThousandSep
= pLoc
->getNumThousandSep();
292 aDateSep
= pLoc
->getDateSep();
294 pFormatScanner
->ChangeIntl();
295 pStringScanner
->ChangeIntl();
301 ::osl::Mutex
& SvNumberFormatter::GetMutex()
303 static ::osl::Mutex
* pMutex
= NULL
;
306 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
309 // #i77768# Due to a static reference in the toolkit lib
310 // we need a mutex that lives longer than the svtools library.
311 // Otherwise the dtor would use a destructed mutex!!
312 pMutex
= new ::osl::Mutex
;
320 SvNumberFormatterRegistry_Impl
& SvNumberFormatter::GetFormatterRegistry()
322 ::osl::MutexGuard
aGuard( GetMutex() );
323 if ( !pFormatterRegistry
)
324 pFormatterRegistry
= new SvNumberFormatterRegistry_Impl
;
325 return *pFormatterRegistry
;
329 Color
* SvNumberFormatter::GetUserDefColor(USHORT nIndex
)
331 if( aColorLink
.IsSet() )
332 return (Color
*) ( aColorLink
.Call( (void*) &nIndex
));
337 void SvNumberFormatter::ChangeNullDate(USHORT nDay
,
341 pFormatScanner
->ChangeNullDate(nDay
, nMonth
, nYear
);
342 pStringScanner
->ChangeNullDate(nDay
, nMonth
, nYear
);
345 Date
* SvNumberFormatter::GetNullDate()
347 return pFormatScanner
->GetNullDate();
350 void SvNumberFormatter::ChangeStandardPrec(short nPrec
)
352 pFormatScanner
->ChangeStandardPrec(nPrec
);
355 short SvNumberFormatter::GetStandardPrec()
357 return pFormatScanner
->GetStandardPrec();
360 void SvNumberFormatter::ImpChangeSysCL( LanguageType eLnge
, BOOL bLoadingSO5
)
362 if (eLnge
== LANGUAGE_DONTKNOW
)
363 eLnge
= UNKNOWN_SUBSTITUTE
;
364 if (eLnge
!= IniLnge
)
368 SvNumberformat
* pEntry
= aFTable
.First();
369 while (pEntry
) // delete old formats
371 pEntry
= (SvNumberformat
*) aFTable
.Remove(aFTable
.GetCurKey());
373 pEntry
= (SvNumberformat
*) aFTable
.First();
375 ImpGenerateFormats( 0, bLoadingSO5
); // new standard formats
377 else if ( bLoadingSO5
)
378 { // delete additional standard formats
380 aFTable
.Seek( SV_MAX_ANZ_STANDARD_FORMATE
+ 1 );
381 while ( (nKey
= aFTable
.GetCurKey()) > SV_MAX_ANZ_STANDARD_FORMATE
&&
382 nKey
< SV_COUNTRY_LANGUAGE_OFFSET
)
384 SvNumberformat
* pEntry
= (SvNumberformat
*) aFTable
.Remove( nKey
);
391 void SvNumberFormatter::ReplaceSystemCL( LanguageType eOldLanguage
)
393 sal_uInt32 nCLOffset
= ImpGetCLOffset( LANGUAGE_SYSTEM
);
394 if ( nCLOffset
> MaxCLOffset
)
395 return ; // no SYSTEM entries to replace
397 const sal_uInt32 nMaxBuiltin
= nCLOffset
+ SV_MAX_ANZ_STANDARD_FORMATE
;
398 const sal_uInt32 nNextCL
= nCLOffset
+ SV_COUNTRY_LANGUAGE_OFFSET
;
401 // remove old builtin formats
402 aFTable
.Seek( nCLOffset
);
403 while ( (nKey
= aFTable
.GetCurKey()) >= nCLOffset
&& nKey
<= nMaxBuiltin
&& aFTable
.Count() )
405 SvNumberformat
* pEntry
= (SvNumberformat
*) aFTable
.Remove( nKey
);
409 // move additional and user defined to temporary table
411 while ( (nKey
= aFTable
.GetCurKey()) >= nCLOffset
&& nKey
< nNextCL
&& aFTable
.Count() )
413 SvNumberformat
* pEntry
= (SvNumberformat
*) aFTable
.Remove( nKey
);
414 aOldTable
.Insert( nKey
, pEntry
);
417 // generate new old builtin formats
418 // reset ActLnge otherwise ChangeIntl() wouldn't switch if already LANGUAGE_SYSTEM
419 ActLnge
= LANGUAGE_DONTKNOW
;
420 ChangeIntl( LANGUAGE_SYSTEM
);
421 ImpGenerateFormats( nCLOffset
, TRUE
);
423 // convert additional and user defined from old system to new system
424 SvNumberformat
* pStdFormat
= (SvNumberformat
*) aFTable
.Get( nCLOffset
+ ZF_STANDARD
);
425 sal_uInt32 nLastKey
= nMaxBuiltin
;
426 pFormatScanner
->SetConvertMode( eOldLanguage
, LANGUAGE_SYSTEM
, TRUE
);
428 while ( aOldTable
.Count() )
430 nKey
= aOldTable
.GetCurKey();
431 if ( nLastKey
< nKey
)
433 SvNumberformat
* pOldEntry
= (SvNumberformat
*) aOldTable
.Remove( nKey
);
434 String
aString( pOldEntry
->GetFormatstring() );
435 xub_StrLen nCheckPos
= STRING_NOTFOUND
;
437 // Same as PutEntry() but assures key position even if format code is
438 // a duplicate. Also won't mix up any LastInsertKey.
439 ChangeIntl( eOldLanguage
);
440 LanguageType eLge
= eOldLanguage
; // ConvertMode changes this
442 SvNumberformat
* pNewEntry
= new SvNumberformat( aString
, pFormatScanner
,
443 pStringScanner
, nCheckPos
, eLge
);
444 if ( nCheckPos
!= 0 )
448 short eCheckType
= pNewEntry
->GetType();
449 if ( eCheckType
!= NUMBERFORMAT_UNDEFINED
)
450 pNewEntry
->SetType( eCheckType
| NUMBERFORMAT_DEFINED
);
452 pNewEntry
->SetType( NUMBERFORMAT_DEFINED
);
454 if ( !aFTable
.Insert( nKey
, pNewEntry
) )
459 DBG_ASSERT( bCheck
, "SvNumberFormatter::ReplaceSystemCL: couldn't convert" );
463 pFormatScanner
->SetConvertMode(FALSE
);
464 pStdFormat
->SetLastInsertKey( USHORT(nLastKey
- nCLOffset
) );
466 // append new system additional formats
467 NumberFormatCodeWrapper
aNumberFormatCode( xServiceManager
, GetLocale() );
468 ImpGenerateAdditionalFormats( nCLOffset
, aNumberFormatCode
, TRUE
);
472 BOOL
SvNumberFormatter::IsTextFormat(sal_uInt32 F_Index
) const
474 SvNumberformat
* pFormat
= (SvNumberformat
*) aFTable
.Get(F_Index
);
478 return pFormat
->IsTextFormat();
481 BOOL
SvNumberFormatter::HasTextFormat(sal_uInt32 F_Index
) const
483 SvNumberformat
* pFormat
= (SvNumberformat
*) aFTable
.Get(F_Index
);
487 return pFormat
->HasTextFormat();
490 BOOL
SvNumberFormatter::PutEntry(String
& rString
,
491 xub_StrLen
& nCheckPos
,
493 sal_uInt32
& nKey
, // Formatnummer
497 if (rString
.Len() == 0) // keinen Leerstring
499 nCheckPos
= 1; // -> Fehler
502 if (eLnge
== LANGUAGE_DONTKNOW
)
505 ChangeIntl(eLnge
); // ggfs. austauschen
506 LanguageType eLge
= eLnge
; // Umgehung const fuer ConvertMode
508 SvNumberformat
* p_Entry
= new SvNumberformat(rString
,
513 if (nCheckPos
== 0) // Format ok
515 short eCheckType
= p_Entry
->GetType();
516 if ( eCheckType
!= NUMBERFORMAT_UNDEFINED
)
518 p_Entry
->SetType(eCheckType
| NUMBERFORMAT_DEFINED
);
523 p_Entry
->SetType(NUMBERFORMAT_DEFINED
);
524 nType
= NUMBERFORMAT_DEFINED
;
526 sal_uInt32 CLOffset
= ImpGenerateCL(eLge
); // ggfs. neu Standard-
528 nKey
= ImpIsEntry(p_Entry
->GetFormatstring(),CLOffset
, eLge
);
529 if (nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
) // schon vorhanden
533 SvNumberformat
* pStdFormat
=
534 (SvNumberformat
*) aFTable
.Get(CLOffset
+ ZF_STANDARD
);
535 sal_uInt32 nPos
= CLOffset
+ pStdFormat
->GetLastInsertKey();
536 if (nPos
- CLOffset
>= SV_COUNTRY_LANGUAGE_OFFSET
)
539 DBG_ERROR("SvNumberFormatter:: Zu viele Formate pro CL");
542 else if (!aFTable
.Insert(nPos
+1,p_Entry
))
548 pStdFormat
->SetLastInsertKey((USHORT
) (nKey
-CLOffset
));
557 BOOL
SvNumberFormatter::PutandConvertEntry(String
& rString
,
558 xub_StrLen
& nCheckPos
,
562 LanguageType eNewLnge
)
565 if (eNewLnge
== LANGUAGE_DONTKNOW
)
568 pFormatScanner
->SetConvertMode(eLnge
, eNewLnge
);
569 bRes
= PutEntry(rString
, nCheckPos
, nType
, nKey
, eLnge
);
570 pFormatScanner
->SetConvertMode(FALSE
);
575 BOOL
SvNumberFormatter::PutandConvertEntrySystem(String
& rString
,
576 xub_StrLen
& nCheckPos
,
580 LanguageType eNewLnge
)
583 if (eNewLnge
== LANGUAGE_DONTKNOW
)
586 pFormatScanner
->SetConvertMode(eLnge
, eNewLnge
, TRUE
);
587 bRes
= PutEntry(rString
, nCheckPos
, nType
, nKey
, eLnge
);
588 pFormatScanner
->SetConvertMode(FALSE
);
593 sal_uInt32
SvNumberFormatter::GetIndexPuttingAndConverting( String
& rString
,
594 LanguageType eLnge
, LanguageType eSysLnge
, short & rType
,
595 BOOL
& rNewInserted
, xub_StrLen
& rCheckPos
)
597 sal_uInt32 nKey
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
598 rNewInserted
= FALSE
;
601 // #62389# empty format string (of Writer) => General standard format
604 else if (eLnge
== LANGUAGE_SYSTEM
&& eSysLnge
!=
605 Application::GetSettings().GetLanguage())
607 sal_uInt32 nOrig
= GetEntryKey( rString
, eSysLnge
);
608 if (nOrig
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
609 nKey
= nOrig
; // none avaliable, maybe user-defined
611 nKey
= GetFormatForLanguageIfBuiltIn( nOrig
,
612 Application::GetSettings().GetLanguage());
615 // Not a builtin format, convert.
616 // The format code string may get modified and adapted to the real
617 // language and wouldn't match eSysLnge anymore, do that on a copy.
618 String
aTmp( rString
);
619 rNewInserted
= PutandConvertEntrySystem( aTmp
, rCheckPos
, rType
,
620 nKey
, eLnge
, Application::GetSettings().GetLanguage());
623 DBG_ERRORFILE("SvNumberFormatter::GetIndexPuttingAndConverting: bad format code string for current locale");
624 nKey
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
630 nKey
= GetEntryKey( rString
, eLnge
);
631 if (nKey
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
633 rNewInserted
= PutEntry( rString
, rCheckPos
, rType
, nKey
, eLnge
);
636 DBG_ERRORFILE("SvNumberFormatter::GetIndexPuttingAndConverting: bad format code string for specified locale");
637 nKey
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
641 if (nKey
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
642 nKey
= GetStandardIndex( eLnge
);
643 rType
= GetType( nKey
);
644 // Convert any (!) old "automatic" currency format to new fixed currency
646 if ((rType
& NUMBERFORMAT_CURRENCY
) != 0)
648 const SvNumberformat
* pFormat
= GetEntry( nKey
);
649 if (!pFormat
->HasNewCurrency())
653 DeleteEntry( nKey
); // don't leave trails of rubbish
654 rNewInserted
= FALSE
;
656 nKey
= GetStandardFormat( NUMBERFORMAT_CURRENCY
, eLnge
);
663 void SvNumberFormatter::DeleteEntry(sal_uInt32 nKey
)
665 SvNumberformat
* pEntry
= aFTable
.Remove(nKey
);
669 void SvNumberFormatter::PrepareSave()
671 SvNumberformat
* pFormat
= aFTable
.First();
674 pFormat
->SetUsed(FALSE
);
675 pFormat
= aFTable
.Next();
679 void SvNumberFormatter::SetFormatUsed(sal_uInt32 nFIndex
)
681 SvNumberformat
* pFormat
= (SvNumberformat
*) aFTable
.Get(nFIndex
);
683 pFormat
->SetUsed(TRUE
);
686 BOOL
SvNumberFormatter::Load( SvStream
& rStream
)
688 LanguageType eSysLang
= Application::GetSettings().GetLanguage();
689 SvNumberFormatter
* pConverter
= NULL
;
691 ImpSvNumMultipleReadHeader
aHdr( rStream
);
694 SvNumberformat
* pEntry
;
696 LanguageType eSaveSysLang
, eLoadSysLang
;
697 USHORT nSysOnStore
, eLge
, eDummy
; // Dummy fuer kompatibles Format
698 rStream
>> nSysOnStore
>> eLge
; // Systemeinstellung aus
700 eSaveSysLang
= (nVersion
< SV_NUMBERFORMATTER_VERSION_SYSTORE
?
701 LANGUAGE_SYSTEM
: (LanguageType
) nSysOnStore
);
702 LanguageType eLnge
= (LanguageType
) eLge
;
703 ImpChangeSysCL( eLnge
, TRUE
);
706 while (nPos
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
708 rStream
>> eDummy
>> eLge
;
709 eLnge
= (LanguageType
) eLge
;
710 ImpGenerateCL( eLnge
, TRUE
); // ggfs. neue Standardformate anlegen
712 sal_uInt32 nOffset
= nPos
% SV_COUNTRY_LANGUAGE_OFFSET
; // relativIndex
713 BOOL bUserDefined
= (nOffset
> SV_MAX_ANZ_STANDARD_FORMATE
);
714 //! HACK! ER 29.07.97 15:15
715 // SaveLang wurde bei SYSTEM nicht gespeichert sondern war auch SYSTEM,
716 // erst ab 364i Unterscheidung moeglich
717 BOOL bConversionHack
;
718 if ( eLnge
== LANGUAGE_SYSTEM
)
720 if ( nVersion
< SV_NUMBERFORMATTER_VERSION_SYSTORE
)
722 bConversionHack
= bUserDefined
;
723 eLoadSysLang
= eSaveSysLang
;
727 bConversionHack
= FALSE
;
728 eLoadSysLang
= eSysLang
;
733 bConversionHack
= FALSE
;
734 eLoadSysLang
= eSaveSysLang
;
737 pEntry
= new SvNumberformat(*pFormatScanner
, eLnge
);
738 if ( bConversionHack
)
740 // nVersion < SV_NUMBERFORMATTER_VERSION_SYSTORE
741 // nVersion < SV_NUMBERFORMATTER_VERSION_KEYWORDS
743 pConverter
= new SvNumberFormatter( xServiceManager
, eSysLang
);
744 NfHackConversion eHackConversion
= pEntry
->Load(
745 rStream
, aHdr
, pConverter
, *pStringScanner
);
746 switch ( eHackConversion
)
748 case NF_CONVERT_GERMAN_ENGLISH
:
749 pEntry
->ConvertLanguage( *pConverter
,
750 LANGUAGE_ENGLISH_US
, eSysLang
, TRUE
);
752 case NF_CONVERT_ENGLISH_GERMAN
:
755 case LANGUAGE_GERMAN
:
756 case LANGUAGE_GERMAN_SWISS
:
757 case LANGUAGE_GERMAN_AUSTRIAN
:
758 case LANGUAGE_GERMAN_LUXEMBOURG
:
759 case LANGUAGE_GERMAN_LIECHTENSTEIN
:
763 pEntry
->ConvertLanguage( *pConverter
,
764 LANGUAGE_GERMAN
, eSysLang
, TRUE
);
767 case NF_CONVERT_NONE
:
768 break; // -Wall not handled.
774 pEntry
->Load( rStream
, aHdr
, NULL
, *pStringScanner
);
776 bUserDefined
= (pEntry
->GetNewStandardDefined() > SV_NUMBERFORMATTER_VERSION
);
779 if ( eSaveSysLang
!= eLoadSysLang
)
780 { // SYSTEM verschieden
782 pConverter
= new SvNumberFormatter( xServiceManager
, eSysLang
);
783 if ( nVersion
< SV_NUMBERFORMATTER_VERSION_KEYWORDS
)
785 switch ( eSaveSysLang
)
787 case LANGUAGE_GERMAN
:
788 case LANGUAGE_GERMAN_SWISS
:
789 case LANGUAGE_GERMAN_AUSTRIAN
:
790 case LANGUAGE_GERMAN_LUXEMBOURG
:
791 case LANGUAGE_GERMAN_LIECHTENSTEIN
:
793 pEntry
->ConvertLanguage( *pConverter
,
794 eSaveSysLang
, eLoadSysLang
, TRUE
);
797 // alte english nach neuem anderen
798 pEntry
->ConvertLanguage( *pConverter
,
799 LANGUAGE_ENGLISH_US
, eLoadSysLang
, TRUE
);
803 pEntry
->ConvertLanguage( *pConverter
,
804 eSaveSysLang
, eLoadSysLang
, TRUE
);
807 { // nicht SYSTEM oder gleiches SYSTEM
808 if ( nVersion
< SV_NUMBERFORMATTER_VERSION_KEYWORDS
)
810 LanguageType eLoadLang
;
812 if ( eLnge
== LANGUAGE_SYSTEM
)
814 eLoadLang
= eSysLang
;
824 case LANGUAGE_GERMAN
:
825 case LANGUAGE_GERMAN_SWISS
:
826 case LANGUAGE_GERMAN_AUSTRIAN
:
827 case LANGUAGE_GERMAN_LUXEMBOURG
:
828 case LANGUAGE_GERMAN_LIECHTENSTEIN
:
832 // alte english nach neuem anderen
834 pConverter
= new SvNumberFormatter( xServiceManager
, eSysLang
);
835 pEntry
->ConvertLanguage( *pConverter
,
836 LANGUAGE_ENGLISH_US
, eLoadLang
, bSystem
);
842 if ( nOffset
== 0 ) // StandardFormat
844 SvNumberformat
* pEnt
= aFTable
.Get(nPos
);
846 pEnt
->SetLastInsertKey(pEntry
->GetLastInsertKey());
848 if (!aFTable
.Insert(nPos
, pEntry
))
853 // ab SV_NUMBERFORMATTER_VERSION_YEAR2000
854 if ( nVersion
>= SV_NUMBERFORMATTER_VERSION_YEAR2000
)
857 if ( aHdr
.BytesLeft() >= sizeof(UINT16
) )
861 if ( nVersion
< SV_NUMBERFORMATTER_VERSION_TWODIGITYEAR
&& nY2k
< 100 )
862 nY2k
+= 1901; // war vor src513e: 29, jetzt: 1930
871 // generate additional i18n standard formats for all used locales
872 LanguageType eOldLanguage
= ActLnge
;
873 NumberFormatCodeWrapper
aNumberFormatCode( xServiceManager
, GetLocale() );
875 GetUsedLanguages( aList
);
876 USHORT nCount
= aList
.Count();
877 for ( USHORT j
=0; j
<nCount
; j
++ )
879 LanguageType eLang
= aList
[j
];
881 sal_uInt32 CLOffset
= ImpGetCLOffset( eLang
);
882 ImpGenerateAdditionalFormats( CLOffset
, aNumberFormatCode
, TRUE
);
884 ChangeIntl( eOldLanguage
);
886 if (rStream
.GetError())
892 BOOL
SvNumberFormatter::Save( SvStream
& rStream
) const
894 ImpSvNumMultipleWriteHeader
aHdr( rStream
);
895 // ab 364i wird gespeichert was SYSTEM wirklich war, vorher hart LANGUAGE_SYSTEM
896 rStream
<< (USHORT
) SV_NUMBERFORMATTER_VERSION
;
897 rStream
<< (USHORT
) Application::GetSettings().GetLanguage() << (USHORT
) IniLnge
;
898 SvNumberFormatTable
* pTable
= (SvNumberFormatTable
*) &aFTable
;
899 SvNumberformat
* pEntry
= (SvNumberformat
*) pTable
->First();
902 // Gespeichert werden alle markierten, benutzerdefinierten Formate und
903 // jeweils das Standardformat zu allen angewaehlten CL-Kombinationen
904 // sowie NewStandardDefined
905 if ( pEntry
->GetUsed() || (pEntry
->GetType() & NUMBERFORMAT_DEFINED
) ||
906 pEntry
->GetNewStandardDefined() ||
907 (pTable
->GetCurKey() % SV_COUNTRY_LANGUAGE_OFFSET
== 0) )
909 rStream
<< static_cast<sal_uInt32
>(pTable
->GetCurKey())
910 << (USHORT
) LANGUAGE_SYSTEM
911 << (USHORT
) pEntry
->GetLanguage();
912 pEntry
->Save(rStream
, aHdr
);
914 pEntry
= (SvNumberformat
*) pTable
->Next();
916 rStream
<< NUMBERFORMAT_ENTRY_NOT_FOUND
; // EndeKennung
918 // ab SV_NUMBERFORMATTER_VERSION_YEAR2000
920 rStream
<< (UINT16
) GetYear2000();
923 if (rStream
.GetError())
930 void SvNumberFormatter::SkipNumberFormatterInStream( SvStream
& rStream
)
932 ImpSvNumMultipleReadHeader::Skip( rStream
);
935 void SvNumberFormatter::GetUsedLanguages( SvUShorts
& rList
)
937 rList
.Remove( 0, rList
.Count() );
939 sal_uInt32 nOffset
= 0;
940 while (nOffset
<= MaxCLOffset
)
942 SvNumberformat
* pFormat
= (SvNumberformat
*) aFTable
.Get(nOffset
);
944 rList
.Insert( pFormat
->GetLanguage(), rList
.Count() );
945 nOffset
+= SV_COUNTRY_LANGUAGE_OFFSET
;
950 void SvNumberFormatter::FillKeywordTable( NfKeywordTable
& rKeywords
,
954 const String
* pTable
= pFormatScanner
->GetKeywords();
955 for ( USHORT i
= 0; i
< NF_KEYWORD_ENTRIES_COUNT
; ++i
)
957 rKeywords
[i
] = pTable
[i
];
962 String
SvNumberFormatter::GetKeyword( LanguageType eLnge
, USHORT nIndex
)
965 const String
* pTable
= pFormatScanner
->GetKeywords();
966 if ( pTable
&& nIndex
< NF_KEYWORD_ENTRIES_COUNT
)
967 return pTable
[nIndex
];
969 DBG_ERROR("GetKeyword: invalid index");
974 String
SvNumberFormatter::GetStandardName( LanguageType eLnge
)
977 return pFormatScanner
->GetStandardName();
981 sal_uInt32
SvNumberFormatter::ImpGetCLOffset(LanguageType eLnge
) const
983 SvNumberformat
* pFormat
;
984 sal_uInt32 nOffset
= 0;
985 while (nOffset
<= MaxCLOffset
)
987 pFormat
= (SvNumberformat
*) aFTable
.Get(nOffset
);
988 if (pFormat
&& pFormat
->GetLanguage() == eLnge
)
990 nOffset
+= SV_COUNTRY_LANGUAGE_OFFSET
;
995 sal_uInt32
SvNumberFormatter::ImpIsEntry(const String
& rString
,
996 sal_uInt32 nCLOffset
,
999 #ifndef NF_COMMENT_IN_FORMATSTRING
1000 #error NF_COMMENT_IN_FORMATSTRING not defined (zformat.hxx)
1002 #if NF_COMMENT_IN_FORMATSTRING
1003 String
aStr( rString
);
1004 SvNumberformat::EraseComment( aStr
);
1006 sal_uInt32 res
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
1007 SvNumberformat
* pEntry
;
1008 pEntry
= (SvNumberformat
*) aFTable
.Seek(nCLOffset
);
1009 while ( res
== NUMBERFORMAT_ENTRY_NOT_FOUND
&&
1010 pEntry
&& pEntry
->GetLanguage() == eLnge
)
1012 #if NF_COMMENT_IN_FORMATSTRING
1013 if ( pEntry
->GetComment().Len() )
1015 String
aFormat( pEntry
->GetFormatstring() );
1016 SvNumberformat::EraseComment( aFormat
);
1017 if ( aStr
== aFormat
)
1018 res
= aFTable
.GetCurKey();
1020 pEntry
= (SvNumberformat
*) aFTable
.Next();
1024 if ( aStr
== pEntry
->GetFormatstring() )
1025 res
= aFTable
.GetCurKey();
1027 pEntry
= (SvNumberformat
*) aFTable
.Next();
1030 if ( rString
== pEntry
->GetFormatstring() )
1031 res
= aFTable
.GetCurKey();
1033 pEntry
= (SvNumberformat
*) aFTable
.Next();
1040 SvNumberFormatTable
& SvNumberFormatter::GetFirstEntryTable(
1043 LanguageType
& rLnge
)
1045 short eTypetmp
= eType
;
1046 if (eType
== NUMBERFORMAT_ALL
) // Leere Zelle oder don't care
1050 SvNumberformat
* pFormat
= (SvNumberformat
*) aFTable
.Get(FIndex
);
1053 // DBG_ERROR("SvNumberFormatter:: Unbekanntes altes Zahlformat (1)");
1055 eType
= NUMBERFORMAT_ALL
;
1060 rLnge
= pFormat
->GetLanguage();
1061 eType
= pFormat
->GetType()&~NUMBERFORMAT_DEFINED
;
1064 eType
= NUMBERFORMAT_DEFINED
;
1067 else if (eType
== NUMBERFORMAT_DATETIME
)
1070 eType
= NUMBERFORMAT_DATE
;
1077 return GetEntryTable(eTypetmp
, FIndex
, rLnge
);
1080 sal_uInt32
SvNumberFormatter::ImpGenerateCL( LanguageType eLnge
, BOOL bLoadingSO5
)
1083 sal_uInt32 CLOffset
= ImpGetCLOffset(ActLnge
);
1084 if (CLOffset
> MaxCLOffset
)
1085 { // new CL combination
1086 if (LocaleDataWrapper::areChecksEnabled())
1088 Locale aLoadedLocale
= xLocaleData
->getLoadedLocale();
1089 if ( aLoadedLocale
.Language
!= aLocale
.Language
||
1090 aLoadedLocale
.Country
!= aLocale
.Country
)
1092 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
1093 "SvNumerFormatter::ImpGenerateCL: locales don't match:"));
1094 LocaleDataWrapper::outputCheckMessage(
1095 xLocaleData
->appendLocaleInfo( aMsg
));
1097 // test XML locale data FormatElement entries
1099 uno::Sequence
< i18n::FormatElement
> xSeq
=
1100 xLocaleData
->getAllFormats();
1101 // A test for completeness of formatindex="0" ...
1102 // formatindex="47" is not needed here since it is done in
1103 // ImpGenerateFormats().
1105 // Test for dupes of formatindex="..."
1106 for ( sal_Int32 j
= 0; j
< xSeq
.getLength(); j
++ )
1108 sal_Int16 nIdx
= xSeq
[j
].formatIndex
;
1110 for ( sal_Int32 i
= 0; i
< xSeq
.getLength(); i
++ )
1112 if ( i
!= j
&& xSeq
[i
].formatIndex
== nIdx
)
1114 aDupes
+= String::CreateFromInt32( i
);
1116 aDupes
+= String( xSeq
[i
].formatKey
);
1123 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
1124 "XML locale data FormatElement formatindex dupe: "));
1125 aMsg
+= String::CreateFromInt32( nIdx
);
1126 aMsg
.AppendAscii( RTL_CONSTASCII_STRINGPARAM(
1127 "\nFormatElements: "));
1128 aMsg
+= String::CreateFromInt32( j
);
1130 aMsg
+= String( xSeq
[j
].formatKey
);
1134 LocaleDataWrapper::outputCheckMessage(
1135 xLocaleData
->appendLocaleInfo( aMsg
));
1141 MaxCLOffset
+= SV_COUNTRY_LANGUAGE_OFFSET
;
1142 ImpGenerateFormats( MaxCLOffset
, bLoadingSO5
);
1143 CLOffset
= MaxCLOffset
;
1148 SvNumberFormatTable
& SvNumberFormatter::ChangeCL(short eType
,
1152 ImpGenerateCL(eLnge
);
1153 return GetEntryTable(eType
, FIndex
, ActLnge
);
1156 SvNumberFormatTable
& SvNumberFormatter::GetEntryTable(
1162 pFormatTable
->Clear();
1164 pFormatTable
= new SvNumberFormatTable
;
1166 sal_uInt32 CLOffset
= ImpGetCLOffset(ActLnge
);
1168 // Might generate and insert a default format for the given type
1169 // (e.g. currency) => has to be done before collecting formats.
1170 sal_uInt32 nDefaultIndex
= GetStandardFormat( eType
, ActLnge
);
1172 SvNumberformat
* pEntry
;
1173 pEntry
= (SvNumberformat
*) aFTable
.Seek(CLOffset
);
1175 if (eType
== NUMBERFORMAT_ALL
)
1177 while (pEntry
&& pEntry
->GetLanguage() == ActLnge
)
1178 { // copy all entries to output table
1179 pFormatTable
->Insert( aFTable
.GetCurKey(), pEntry
);
1180 pEntry
= (SvNumberformat
*) aFTable
.Next();
1185 while (pEntry
&& pEntry
->GetLanguage() == ActLnge
)
1186 { // copy entries of queried type to output table
1187 if ((pEntry
->GetType()) & eType
)
1188 pFormatTable
->Insert(aFTable
.GetCurKey(),pEntry
);
1189 pEntry
= (SvNumberformat
*) aFTable
.Next();
1192 if ( pFormatTable
->Count() > 0 )
1193 { // select default if queried format doesn't exist or queried type or
1194 // language differ from existing format
1195 pEntry
= aFTable
.Get(FIndex
);
1196 if ( !pEntry
|| !(pEntry
->GetType() & eType
) || pEntry
->GetLanguage() != ActLnge
)
1197 FIndex
= nDefaultIndex
;
1199 return *pFormatTable
;
1202 BOOL
SvNumberFormatter::IsNumberFormat(const String
& sString
,
1203 sal_uInt32
& F_Index
,
1207 const SvNumberformat
* pFormat
= (SvNumberformat
*) aFTable
.Get(F_Index
);
1210 // DBG_ERROR("SvNumberFormatter:: Unbekanntes altes Zahlformat (2)");
1211 ChangeIntl(IniLnge
);
1212 FType
= NUMBERFORMAT_NUMBER
;
1216 FType
= pFormat
->GetType() &~NUMBERFORMAT_DEFINED
;
1218 FType
= NUMBERFORMAT_DEFINED
;
1219 ChangeIntl(pFormat
->GetLanguage());
1222 short RType
= FType
;
1225 if (RType
== NUMBERFORMAT_TEXT
) // Zahlzelle ->Stringz.
1228 res
= pStringScanner
->IsNumberFormat(sString
, RType
, fOutNumber
, pFormat
);
1230 if (res
&& !IsCompatible(FType
, RType
)) // unpassender Typ
1234 case NUMBERFORMAT_TIME
:
1236 if ( pStringScanner
->GetDecPos() )
1237 { // 100stel Sekunden
1238 if ( pStringScanner
->GetAnzNums() > 3 || fOutNumber
< 0.0 )
1239 F_Index
= GetFormatIndex( NF_TIME_HH_MMSS00
, ActLnge
);
1241 F_Index
= GetFormatIndex( NF_TIME_MMSS00
, ActLnge
);
1243 else if ( fOutNumber
>= 1.0 || fOutNumber
< 0.0 )
1244 F_Index
= GetFormatIndex( NF_TIME_HH_MMSS
, ActLnge
);
1246 F_Index
= GetStandardFormat( RType
, ActLnge
);
1250 F_Index
= GetStandardFormat( RType
, ActLnge
);
1256 BOOL
SvNumberFormatter::IsCompatible(short eOldType
,
1259 if (eOldType
== eNewType
)
1261 else if (eOldType
== NUMBERFORMAT_DEFINED
)
1267 case NUMBERFORMAT_NUMBER
:
1271 case NUMBERFORMAT_PERCENT
:
1272 case NUMBERFORMAT_CURRENCY
:
1273 case NUMBERFORMAT_SCIENTIFIC
:
1274 case NUMBERFORMAT_FRACTION
:
1275 // case NUMBERFORMAT_LOGICAL:
1276 case NUMBERFORMAT_DEFINED
:
1283 case NUMBERFORMAT_DATE
:
1287 case NUMBERFORMAT_DATETIME
:
1294 case NUMBERFORMAT_TIME
:
1298 case NUMBERFORMAT_DATETIME
:
1305 case NUMBERFORMAT_DATETIME
:
1309 case NUMBERFORMAT_TIME
:
1310 case NUMBERFORMAT_DATE
:
1325 sal_uInt32
SvNumberFormatter::ImpGetDefaultFormat( short nType
)
1327 sal_uInt32 CLOffset
= ImpGetCLOffset( ActLnge
);
1331 case NUMBERFORMAT_DATE
:
1332 nSearch
= CLOffset
+ ZF_STANDARD_DATE
;
1334 case NUMBERFORMAT_TIME
:
1335 nSearch
= CLOffset
+ ZF_STANDARD_TIME
;
1337 case NUMBERFORMAT_DATETIME
:
1338 nSearch
= CLOffset
+ ZF_STANDARD_DATETIME
;
1340 case NUMBERFORMAT_PERCENT
:
1341 nSearch
= CLOffset
+ ZF_STANDARD_PERCENT
;
1343 case NUMBERFORMAT_SCIENTIFIC
:
1344 nSearch
= CLOffset
+ ZF_STANDARD_SCIENTIFIC
;
1347 nSearch
= CLOffset
+ ZF_STANDARD
;
1349 sal_uInt32 nDefaultFormat
= (sal_uInt32
)(sal_uIntPtr
) aDefaultFormatKeys
.Get( nSearch
);
1350 if ( !nDefaultFormat
)
1351 nDefaultFormat
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
1352 if ( nDefaultFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
1353 { // look for a defined standard
1354 sal_uInt32 nStopKey
= CLOffset
+ SV_COUNTRY_LANGUAGE_OFFSET
;
1356 aFTable
.Seek( CLOffset
);
1357 while ( (nKey
= aFTable
.GetCurKey()) >= CLOffset
&& nKey
< nStopKey
)
1359 const SvNumberformat
* pEntry
=
1360 (const SvNumberformat
*) aFTable
.GetCurObject();
1361 if ( pEntry
->IsStandard() && ((pEntry
->GetType() &
1362 ~NUMBERFORMAT_DEFINED
) == nType
) )
1364 nDefaultFormat
= nKey
;
1370 if ( nDefaultFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
1371 { // none found, use old fixed standards
1374 case NUMBERFORMAT_DATE
:
1375 nDefaultFormat
= CLOffset
+ ZF_STANDARD_DATE
;
1377 case NUMBERFORMAT_TIME
:
1378 nDefaultFormat
= CLOffset
+ ZF_STANDARD_TIME
+1;
1380 case NUMBERFORMAT_DATETIME
:
1381 nDefaultFormat
= CLOffset
+ ZF_STANDARD_DATETIME
;
1383 case NUMBERFORMAT_PERCENT
:
1384 nDefaultFormat
= CLOffset
+ ZF_STANDARD_PERCENT
+1;
1386 case NUMBERFORMAT_SCIENTIFIC
:
1387 nDefaultFormat
= CLOffset
+ ZF_STANDARD_SCIENTIFIC
;
1390 nDefaultFormat
= CLOffset
+ ZF_STANDARD
;
1393 aDefaultFormatKeys
.Insert( nSearch
, (void*) nDefaultFormat
);
1395 return nDefaultFormat
;
1399 sal_uInt32
SvNumberFormatter::GetStandardFormat( short eType
, LanguageType eLnge
)
1401 sal_uInt32 CLOffset
= ImpGenerateCL(eLnge
);
1404 case NUMBERFORMAT_CURRENCY
:
1406 if ( eLnge
== LANGUAGE_SYSTEM
)
1407 return ImpGetDefaultSystemCurrencyFormat();
1409 return ImpGetDefaultCurrencyFormat();
1411 case NUMBERFORMAT_DATE
:
1412 case NUMBERFORMAT_TIME
:
1413 case NUMBERFORMAT_DATETIME
:
1414 case NUMBERFORMAT_PERCENT
:
1415 case NUMBERFORMAT_SCIENTIFIC
:
1416 return ImpGetDefaultFormat( eType
);
1418 case NUMBERFORMAT_FRACTION
: return CLOffset
+ ZF_STANDARD_FRACTION
;
1419 case NUMBERFORMAT_LOGICAL
: return CLOffset
+ ZF_STANDARD_LOGICAL
;
1420 case NUMBERFORMAT_TEXT
: return CLOffset
+ ZF_STANDARD_TEXT
;
1421 case NUMBERFORMAT_ALL
:
1422 case NUMBERFORMAT_DEFINED
:
1423 case NUMBERFORMAT_NUMBER
:
1424 case NUMBERFORMAT_UNDEFINED
:
1425 default : return CLOffset
+ ZF_STANDARD
;
1429 BOOL
SvNumberFormatter::IsSpecialStandardFormat( sal_uInt32 nFIndex
,
1430 LanguageType eLnge
)
1433 nFIndex
== GetFormatIndex( NF_TIME_MMSS00
, eLnge
) ||
1434 nFIndex
== GetFormatIndex( NF_TIME_HH_MMSS00
, eLnge
) ||
1435 nFIndex
== GetFormatIndex( NF_TIME_HH_MMSS
, eLnge
)
1439 sal_uInt32
SvNumberFormatter::GetStandardFormat( sal_uInt32 nFIndex
, short eType
,
1440 LanguageType eLnge
)
1442 if ( IsSpecialStandardFormat( nFIndex
, eLnge
) )
1445 return GetStandardFormat( eType
, eLnge
);
1448 sal_uInt32
SvNumberFormatter::GetStandardFormat( double fNumber
, sal_uInt32 nFIndex
,
1449 short eType
, LanguageType eLnge
)
1451 if ( IsSpecialStandardFormat( nFIndex
, eLnge
) )
1456 case NUMBERFORMAT_TIME
:
1459 if ( fNumber
< 0.0 )
1466 double fSeconds
= fNumber
* 86400;
1467 if ( floor( fSeconds
+ 0.5 ) * 100 != floor( fSeconds
* 100 + 0.5 ) )
1468 { // mit 100stel Sekunden
1469 if ( bSign
|| fSeconds
>= 3600 )
1470 return GetFormatIndex( NF_TIME_HH_MMSS00
, eLnge
);
1472 return GetFormatIndex( NF_TIME_MMSS00
, eLnge
);
1476 if ( bSign
|| fNumber
>= 1.0 )
1477 return GetFormatIndex( NF_TIME_HH_MMSS
, eLnge
);
1479 return GetStandardFormat( eType
, eLnge
);
1483 return GetStandardFormat( eType
, eLnge
);
1487 void SvNumberFormatter::GetInputLineString(const double& fOutNumber
,
1491 SvNumberformat
* pFormat
;
1494 pFormat
= (SvNumberformat
*) aFTable
.Get(nFIndex
);
1496 pFormat
= aFTable
.Get(ZF_STANDARD
);
1497 LanguageType eLang
= pFormat
->GetLanguage();
1498 ChangeIntl( eLang
);
1499 short eType
= pFormat
->GetType() & ~NUMBERFORMAT_DEFINED
;
1501 eType
= NUMBERFORMAT_DEFINED
;
1503 if (eType
== NUMBERFORMAT_NUMBER
|| eType
== NUMBERFORMAT_PERCENT
1504 || eType
== NUMBERFORMAT_CURRENCY
1505 || eType
== NUMBERFORMAT_SCIENTIFIC
1506 || eType
== NUMBERFORMAT_FRACTION
)
1508 if (eType
!= NUMBERFORMAT_PERCENT
) // spaeter Sonderbehandlung %
1509 eType
= NUMBERFORMAT_NUMBER
;
1510 nOldPrec
= pFormatScanner
->GetStandardPrec();
1511 ChangeStandardPrec(300); // Merkwert
1513 sal_uInt32 nKey
= nFIndex
;
1515 { // #61619# immer vierstelliges Jahr editieren
1516 case NUMBERFORMAT_DATE
:
1517 nKey
= GetFormatIndex( NF_DATE_SYS_DDMMYYYY
, eLang
);
1519 case NUMBERFORMAT_DATETIME
:
1520 nKey
= GetFormatIndex( NF_DATETIME_SYS_DDMMYYYY_HHMMSS
, eLang
);
1523 nKey
= GetStandardFormat( fOutNumber
, nFIndex
, eType
, eLang
);
1525 if ( nKey
!= nFIndex
)
1526 pFormat
= (SvNumberformat
*) aFTable
.Get( nKey
);
1529 if ( eType
== NUMBERFORMAT_TIME
&& pFormat
->GetFormatPrecision() )
1531 nOldPrec
= pFormatScanner
->GetStandardPrec();
1532 ChangeStandardPrec(300); // Merkwert
1534 pFormat
->GetOutputString(fOutNumber
, sOutString
, &pColor
);
1537 ChangeStandardPrec(nOldPrec
);
1540 void SvNumberFormatter::GetOutputString(const double& fOutNumber
,
1545 if (bNoZero
&& fOutNumber
== 0.0)
1550 SvNumberformat
* pFormat
= (SvNumberformat
*) aFTable
.Get(nFIndex
);
1552 pFormat
= aFTable
.Get(ZF_STANDARD
);
1553 ChangeIntl(pFormat
->GetLanguage());
1554 pFormat
->GetOutputString(fOutNumber
, sOutString
, ppColor
);
1557 void SvNumberFormatter::GetOutputString(String
& sString
,
1562 SvNumberformat
* pFormat
= (SvNumberformat
*) aFTable
.Get(nFIndex
);
1564 pFormat
= aFTable
.Get(ZF_STANDARD_TEXT
);
1565 if (!pFormat
->IsTextFormat() && !pFormat
->HasTextFormat())
1568 sOutString
= sString
;
1572 ChangeIntl(pFormat
->GetLanguage());
1573 pFormat
->GetOutputString(sString
, sOutString
, ppColor
);
1577 BOOL
SvNumberFormatter::GetPreviewString(const String
& sFormatString
,
1578 double fPreviewNumber
,
1583 if (sFormatString
.Len() == 0) // keinen Leerstring
1586 xub_StrLen nCheckPos
= STRING_NOTFOUND
;
1588 if (eLnge
== LANGUAGE_DONTKNOW
)
1590 ChangeIntl(eLnge
); // ggfs. austauschen
1592 String sTmpString
= sFormatString
;
1593 SvNumberformat
* p_Entry
= new SvNumberformat(sTmpString
,
1598 if (nCheckPos
== 0) // String ok
1600 sal_uInt32 CLOffset
= ImpGenerateCL(eLnge
); // ggfs. neu Standard-
1602 nKey
= ImpIsEntry(p_Entry
->GetFormatstring(),CLOffset
, eLnge
);
1603 if (nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
) // schon vorhanden
1604 GetOutputString(fPreviewNumber
,nKey
,sOutString
,ppColor
);
1606 p_Entry
->GetOutputString(fPreviewNumber
,sOutString
, ppColor
);
1617 BOOL
SvNumberFormatter::GetPreviewStringGuess( const String
& sFormatString
,
1618 double fPreviewNumber
,
1621 LanguageType eLnge
)
1623 if (sFormatString
.Len() == 0) // keinen Leerstring
1626 if (eLnge
== LANGUAGE_DONTKNOW
)
1629 ChangeIntl( eLnge
);
1631 BOOL bEnglish
= (eLnge
== LANGUAGE_ENGLISH_US
);
1633 String
aFormatStringUpper( pCharClass
->upper( sFormatString
) );
1634 sal_uInt32 nCLOffset
= ImpGenerateCL( eLnge
);
1635 sal_uInt32 nKey
= ImpIsEntry( aFormatStringUpper
, nCLOffset
, eLnge
);
1636 if ( nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
1637 { // Zielformat vorhanden
1638 GetOutputString( fPreviewNumber
, nKey
, sOutString
, ppColor
);
1642 SvNumberformat
*pEntry
= NULL
;
1643 xub_StrLen nCheckPos
= STRING_NOTFOUND
;
1648 sTmpString
= sFormatString
;
1649 pEntry
= new SvNumberformat( sTmpString
, pFormatScanner
,
1650 pStringScanner
, nCheckPos
, eLnge
);
1654 nCLOffset
= ImpGenerateCL( LANGUAGE_ENGLISH_US
);
1655 nKey
= ImpIsEntry( aFormatStringUpper
, nCLOffset
, LANGUAGE_ENGLISH_US
);
1656 BOOL bEnglishFormat
= (nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
);
1658 // try english --> other bzw. english nach other konvertieren
1659 LanguageType eFormatLang
= LANGUAGE_ENGLISH_US
;
1660 pFormatScanner
->SetConvertMode( LANGUAGE_ENGLISH_US
, eLnge
);
1661 sTmpString
= sFormatString
;
1662 pEntry
= new SvNumberformat( sTmpString
, pFormatScanner
,
1663 pStringScanner
, nCheckPos
, eFormatLang
);
1664 pFormatScanner
->SetConvertMode( FALSE
);
1665 ChangeIntl( eLnge
);
1667 if ( !bEnglishFormat
)
1669 if ( nCheckPos
> 0 || xTransliteration
->isEqual( sFormatString
,
1670 pEntry
->GetFormatstring() ) )
1673 sTmpString
= sFormatString
;
1674 pEntry
= new SvNumberformat( sTmpString
, pFormatScanner
,
1675 pStringScanner
, nCheckPos
, eLnge
);
1679 xub_StrLen nCheckPos2
= STRING_NOTFOUND
;
1680 // try other --> english
1681 eFormatLang
= eLnge
;
1682 pFormatScanner
->SetConvertMode( eLnge
, LANGUAGE_ENGLISH_US
);
1683 sTmpString
= sFormatString
;
1684 SvNumberformat
* pEntry2
= new SvNumberformat( sTmpString
, pFormatScanner
,
1685 pStringScanner
, nCheckPos2
, eFormatLang
);
1686 pFormatScanner
->SetConvertMode( FALSE
);
1687 ChangeIntl( eLnge
);
1688 if ( nCheckPos2
== 0 && !xTransliteration
->isEqual( sFormatString
,
1689 pEntry2
->GetFormatstring() ) )
1692 sTmpString
= sFormatString
;
1693 pEntry
= new SvNumberformat( sTmpString
, pFormatScanner
,
1694 pStringScanner
, nCheckPos
, eLnge
);
1701 if (nCheckPos
== 0) // String ok
1703 ImpGenerateCL( eLnge
); // ggfs. neu Standardformate anlegen
1704 pEntry
->GetOutputString( fPreviewNumber
, sOutString
, ppColor
);
1712 sal_uInt32
SvNumberFormatter::TestNewString(const String
& sFormatString
,
1715 if (sFormatString
.Len() == 0) // keinen Leerstring
1716 return NUMBERFORMAT_ENTRY_NOT_FOUND
;
1718 xub_StrLen nCheckPos
= STRING_NOTFOUND
;
1719 if (eLnge
== LANGUAGE_DONTKNOW
)
1721 ChangeIntl(eLnge
); // ggfs. austauschen
1724 String sTmpString
= sFormatString
;
1725 SvNumberformat
* pEntry
= new SvNumberformat(sTmpString
,
1730 if (nCheckPos
== 0) // String ok
1732 sal_uInt32 CLOffset
= ImpGenerateCL(eLnge
); // ggfs. neu Standard-
1734 nRes
= ImpIsEntry(pEntry
->GetFormatstring(),CLOffset
, eLnge
);
1735 // schon vorhanden ?
1738 nRes
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
1743 SvNumberformat
* SvNumberFormatter::ImpInsertFormat(
1744 const ::com::sun::star::i18n::NumberFormatCode
& rCode
,
1745 sal_uInt32 nPos
, BOOL bAfterLoadingSO5
, sal_Int16 nOrgIndex
)
1747 String
aCodeStr( rCode
.Code
);
1748 if ( rCode
.Index
< NF_INDEX_TABLE_ENTRIES
&&
1749 rCode
.Usage
== ::com::sun::star::i18n::KNumberFormatUsage::CURRENCY
&&
1750 rCode
.Index
!= NF_CURRENCY_1000DEC2_CCC
)
1751 { // strip surrounding [$...] on automatic currency
1752 if ( aCodeStr
.SearchAscii( "[$" ) != STRING_NOTFOUND
)
1753 aCodeStr
= SvNumberformat::StripNewCurrencyDelimiters( aCodeStr
, FALSE
);
1756 if (LocaleDataWrapper::areChecksEnabled() &&
1757 rCode
.Index
!= NF_CURRENCY_1000DEC2_CCC
)
1759 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
1760 "SvNumberFormatter::ImpInsertFormat: no [$...] on currency format code, index "));
1761 aMsg
+= String::CreateFromInt32( rCode
.Index
);
1762 aMsg
.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ":\n"));
1763 aMsg
+= String( rCode
.Code
);
1764 LocaleDataWrapper::outputCheckMessage(
1765 xLocaleData
->appendLocaleInfo( aMsg
));
1769 xub_StrLen nCheckPos
= 0;
1770 SvNumberformat
* pFormat
= new SvNumberformat(aCodeStr
,
1775 if ( !pFormat
|| nCheckPos
> 0 )
1777 if (LocaleDataWrapper::areChecksEnabled())
1779 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
1780 "SvNumberFormatter::ImpInsertFormat: bad format code, index "));
1781 aMsg
+= String::CreateFromInt32( rCode
.Index
);
1783 aMsg
+= String( rCode
.Code
);
1784 LocaleDataWrapper::outputCheckMessage(
1785 xLocaleData
->appendLocaleInfo( aMsg
));
1790 if ( rCode
.Index
>= NF_INDEX_TABLE_ENTRIES
)
1792 sal_uInt32 nCLOffset
= nPos
- (nPos
% SV_COUNTRY_LANGUAGE_OFFSET
);
1793 sal_uInt32 nKey
= ImpIsEntry( aCodeStr
, nCLOffset
, ActLnge
);
1794 if ( nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
1796 if (LocaleDataWrapper::areChecksEnabled())
1798 switch ( nOrgIndex
)
1800 // These may be dupes of integer versions for locales where
1801 // currencies have no decimals like Italian Lira.
1802 case NF_CURRENCY_1000DEC2
: // NF_CURRENCY_1000INT
1803 case NF_CURRENCY_1000DEC2_RED
: // NF_CURRENCY_1000INT_RED
1804 case NF_CURRENCY_1000DEC2_DASHED
: // NF_CURRENCY_1000INT_RED
1807 if ( !bAfterLoadingSO5
)
1808 { // If bAfterLoadingSO5 there will definitely be some dupes,
1809 // don't cry. But we need this test for verification of locale
1810 // data if not loading old SO5 documents.
1811 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
1812 "SvNumberFormatter::ImpInsertFormat: dup format code, index "));
1813 aMsg
+= String::CreateFromInt32( rCode
.Index
);
1815 aMsg
+= String( rCode
.Code
);
1816 LocaleDataWrapper::outputCheckMessage(
1817 xLocaleData
->appendLocaleInfo( aMsg
));
1824 else if ( nPos
- nCLOffset
>= SV_COUNTRY_LANGUAGE_OFFSET
)
1826 if (LocaleDataWrapper::areChecksEnabled())
1828 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
1829 "SvNumberFormatter::ImpInsertFormat: too many format codes, index "));
1830 aMsg
+= String::CreateFromInt32( rCode
.Index
);
1832 aMsg
+= String( rCode
.Code
);
1833 LocaleDataWrapper::outputCheckMessage(
1834 xLocaleData
->appendLocaleInfo( aMsg
));
1840 if ( !aFTable
.Insert( nPos
, pFormat
) )
1842 if (LocaleDataWrapper::areChecksEnabled())
1844 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
1845 "ImpInsertFormat: can't insert number format key pos: "));
1846 aMsg
+= String::CreateFromInt32( nPos
);
1847 aMsg
.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ", code index "));
1848 aMsg
+= String::CreateFromInt32( rCode
.Index
);
1850 aMsg
+= String( rCode
.Code
);
1851 LocaleDataWrapper::outputCheckMessage(
1852 xLocaleData
->appendLocaleInfo( aMsg
));
1857 if ( rCode
.Default
)
1858 pFormat
->SetStandard();
1859 if ( rCode
.DefaultName
.getLength() )
1860 pFormat
->SetComment( rCode
.DefaultName
);
1864 SvNumberformat
* SvNumberFormatter::ImpInsertNewStandardFormat(
1865 const ::com::sun::star::i18n::NumberFormatCode
& rCode
,
1866 sal_uInt32 nPos
, USHORT nVersion
, BOOL bAfterLoadingSO5
,
1867 sal_Int16 nOrgIndex
)
1869 SvNumberformat
* pNewFormat
= ImpInsertFormat( rCode
, nPos
,
1870 bAfterLoadingSO5
, nOrgIndex
);
1872 pNewFormat
->SetNewStandardDefined( nVersion
);
1873 // so that it gets saved, displayed properly, and converted by old versions
1877 void SvNumberFormatter::GetFormatSpecialInfo(sal_uInt32 nFormat
,
1881 USHORT
& nAnzLeading
)
1884 const SvNumberformat
* pFormat
= aFTable
.Get(nFormat
);
1886 pFormat
->GetFormatSpecialInfo(bThousand
, IsRed
,
1887 nPrecision
, nAnzLeading
);
1892 nPrecision
= pFormatScanner
->GetStandardPrec();
1897 USHORT
SvNumberFormatter::GetFormatPrecision( sal_uInt32 nFormat
) const
1899 const SvNumberformat
* pFormat
= aFTable
.Get( nFormat
);
1901 return pFormat
->GetFormatPrecision();
1903 return pFormatScanner
->GetStandardPrec();
1907 String
SvNumberFormatter::GetFormatDecimalSep( sal_uInt32 nFormat
) const
1909 const SvNumberformat
* pFormat
= aFTable
.Get( nFormat
);
1910 if ( !pFormat
|| pFormat
->GetLanguage() == ActLnge
)
1911 return GetNumDecimalSep();
1914 LanguageType eSaveLang
= xLocaleData
.getCurrentLanguage();
1915 if ( pFormat
->GetLanguage() == eSaveLang
)
1916 aRet
= xLocaleData
->getNumDecimalSep();
1919 ::com::sun::star::lang::Locale
aSaveLocale( xLocaleData
->getLocale() );
1920 ::com::sun::star::lang::Locale
aTmpLocale(MsLangId::convertLanguageToLocale(pFormat
->GetLanguage()));
1921 ((SvNumberFormatter
*)this)->xLocaleData
.changeLocale(aTmpLocale
, pFormat
->GetLanguage() );
1922 aRet
= xLocaleData
->getNumDecimalSep();
1923 ((SvNumberFormatter
*)this)->xLocaleData
.changeLocale( aSaveLocale
, eSaveLang
);
1929 sal_uInt32
SvNumberFormatter::GetFormatSpecialInfo( const String
& rFormatString
,
1930 BOOL
& bThousand
, BOOL
& IsRed
, USHORT
& nPrecision
,
1931 USHORT
& nAnzLeading
, LanguageType eLnge
)
1934 xub_StrLen nCheckPos
= 0;
1935 if (eLnge
== LANGUAGE_DONTKNOW
)
1937 ChangeIntl(eLnge
); // ggfs. austauschen
1939 String
aTmpStr( rFormatString
);
1940 SvNumberformat
* pFormat
= new SvNumberformat( aTmpStr
,
1941 pFormatScanner
, pStringScanner
, nCheckPos
, eLnge
);
1942 if ( nCheckPos
== 0 )
1943 pFormat
->GetFormatSpecialInfo( bThousand
, IsRed
, nPrecision
, nAnzLeading
);
1948 nPrecision
= pFormatScanner
->GetStandardPrec();
1956 inline sal_uInt32
SetIndexTable( NfIndexTableOffset nTabOff
, sal_uInt32 nIndOff
)
1958 if ( !bIndexTableInitialized
)
1960 DBG_ASSERT( theIndexTable
[nTabOff
] == NUMBERFORMAT_ENTRY_NOT_FOUND
,
1961 "SetIndexTable: theIndexTable[nTabOff] already occupied" );
1962 theIndexTable
[nTabOff
] = nIndOff
;
1968 sal_Int32
SvNumberFormatter::ImpGetFormatCodeIndex(
1969 ::com::sun::star::uno::Sequence
< ::com::sun::star::i18n::NumberFormatCode
>& rSeq
,
1970 const NfIndexTableOffset nTabOff
)
1972 const sal_Int32 nLen
= rSeq
.getLength();
1973 for ( sal_Int32 j
=0; j
<nLen
; j
++ )
1975 if ( rSeq
[j
].Index
== nTabOff
)
1978 if (LocaleDataWrapper::areChecksEnabled() && (nTabOff
< NF_CURRENCY_START
1979 || NF_CURRENCY_END
< nTabOff
|| nTabOff
== NF_CURRENCY_1000INT
1980 || nTabOff
== NF_CURRENCY_1000INT_RED
1981 || nTabOff
== NF_CURRENCY_1000DEC2_CCC
))
1982 { // currency entries with decimals might not exist, e.g. Italian Lira
1983 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
1984 "SvNumberFormatter::ImpGetFormatCodeIndex: not found: "));
1985 aMsg
+= String::CreateFromInt32( nTabOff
);
1986 LocaleDataWrapper::outputCheckMessage( xLocaleData
->appendLocaleInfo(
1992 // look for a preset default
1993 for ( j
=0; j
<nLen
; j
++ )
1995 if ( rSeq
[j
].Default
)
1998 // currencies are special, not all format codes must exist, but all
1999 // builtin number format key index positions must have a format assigned
2000 if ( NF_CURRENCY_START
<= nTabOff
&& nTabOff
<= NF_CURRENCY_END
)
2002 // look for a format with decimals
2003 for ( j
=0; j
<nLen
; j
++ )
2005 if ( rSeq
[j
].Index
== NF_CURRENCY_1000DEC2
)
2008 // last resort: look for a format without decimals
2009 for ( j
=0; j
<nLen
; j
++ )
2011 if ( rSeq
[j
].Index
== NF_CURRENCY_1000INT
)
2017 { // we need at least _some_ format
2019 rSeq
[0] = ::com::sun::star::i18n::NumberFormatCode();
2021 aTmp
+= GetNumDecimalSep();
2022 aTmp
.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "############" ) );
2023 rSeq
[0].Code
= aTmp
;
2029 sal_Int32
SvNumberFormatter::ImpAdjustFormatCodeDefault(
2030 ::com::sun::star::i18n::NumberFormatCode
* pFormatArr
,
2031 sal_Int32 nCnt
, BOOL bCheckCorrectness
)
2033 using namespace ::com::sun::star
;
2037 if (bCheckCorrectness
&& LocaleDataWrapper::areChecksEnabled())
2038 { // check the locale data for correctness
2040 sal_Int32 nElem
, nShort
, nMedium
, nLong
, nShortDef
, nMediumDef
, nLongDef
;
2041 nShort
= nMedium
= nLong
= nShortDef
= nMediumDef
= nLongDef
= -1;
2042 for ( nElem
= 0; nElem
< nCnt
; nElem
++ )
2044 switch ( pFormatArr
[nElem
].Type
)
2046 case i18n::KNumberFormatType::SHORT
:
2049 case i18n::KNumberFormatType::MEDIUM
:
2052 case i18n::KNumberFormatType::LONG
:
2056 aMsg
= "unknown type";
2058 if ( pFormatArr
[nElem
].Default
)
2060 switch ( pFormatArr
[nElem
].Type
)
2062 case i18n::KNumberFormatType::SHORT
:
2063 if ( nShortDef
!= -1 )
2064 aMsg
= "dupe short type default";
2067 case i18n::KNumberFormatType::MEDIUM
:
2068 if ( nMediumDef
!= -1 )
2069 aMsg
= "dupe medium type default";
2072 case i18n::KNumberFormatType::LONG
:
2073 if ( nLongDef
!= -1 )
2074 aMsg
= "dupe long type default";
2081 aMsg
.Insert( "SvNumberFormatter::ImpAdjustFormatCodeDefault: ", 0 );
2082 aMsg
+= "\nXML locale data FormatElement formatindex: ";
2083 aMsg
+= ByteString::CreateFromInt32( pFormatArr
[nElem
].Index
);
2084 String
aUMsg( aMsg
, RTL_TEXTENCODING_ASCII_US
);
2085 LocaleDataWrapper::outputCheckMessage(
2086 xLocaleData
->appendLocaleInfo( aUMsg
));
2090 if ( nShort
!= -1 && nShortDef
== -1 )
2091 aMsg
+= "no short type default ";
2092 if ( nMedium
!= -1 && nMediumDef
== -1 )
2093 aMsg
+= "no medium type default ";
2094 if ( nLong
!= -1 && nLongDef
== -1 )
2095 aMsg
+= "no long type default ";
2098 aMsg
.Insert( "SvNumberFormatter::ImpAdjustFormatCodeDefault: ", 0 );
2099 aMsg
+= "\nXML locale data FormatElement group of: ";
2100 String
aUMsg( aMsg
, RTL_TEXTENCODING_ASCII_US
);
2101 aUMsg
+= String( pFormatArr
[0].NameID
);
2102 LocaleDataWrapper::outputCheckMessage(
2103 xLocaleData
->appendLocaleInfo( aUMsg
));
2107 // find the default (medium preferred, then long) and reset all other defaults
2108 sal_Int32 nElem
, nDef
, nMedium
;
2109 nDef
= nMedium
= -1;
2110 for ( nElem
= 0; nElem
< nCnt
; nElem
++ )
2112 if ( pFormatArr
[nElem
].Default
)
2114 switch ( pFormatArr
[nElem
].Type
)
2116 case i18n::KNumberFormatType::MEDIUM
:
2117 nDef
= nMedium
= nElem
;
2119 case i18n::KNumberFormatType::LONG
:
2120 if ( nMedium
== -1 )
2126 pFormatArr
[nElem
].Default
= sal_False
;
2132 pFormatArr
[nDef
].Default
= sal_True
;
2137 void SvNumberFormatter::ImpGenerateFormats( sal_uInt32 CLOffset
, BOOL bLoadingSO5
)
2139 using namespace ::com::sun::star
;
2141 if ( !bIndexTableInitialized
)
2143 for ( USHORT j
=0; j
<NF_INDEX_TABLE_ENTRIES
; j
++ )
2145 theIndexTable
[j
] = NUMBERFORMAT_ENTRY_NOT_FOUND
;
2148 BOOL bOldConvertMode
= pFormatScanner
->GetConvertMode();
2149 if (bOldConvertMode
)
2150 pFormatScanner
->SetConvertMode(FALSE
); // switch off for this function
2152 NumberFormatCodeWrapper
aNumberFormatCode( xServiceManager
, GetLocale() );
2154 xub_StrLen nCheckPos
= 0;
2155 SvNumberformat
* pNewFormat
= NULL
;
2160 // Counter for additional builtin formats not fitting into the first 10
2161 // of a category (TLOT:=The Legacy Of Templin), altogether about 20 formats.
2162 // Has to be incremented on each ImpInsertNewStandardformat, new formats
2163 // must be appended, not inserted!
2164 USHORT nNewExtended
= ZF_STANDARD_NEWEXTENDED
;
2167 uno::Sequence
< i18n::NumberFormatCode
> aFormatSeq
2168 = aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::FIXED_NUMBER
);
2169 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2172 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_STANDARD
);
2173 SvNumberformat
* pStdFormat
= ImpInsertFormat( aFormatSeq
[nIdx
],
2174 CLOffset
+ SetIndexTable( NF_NUMBER_STANDARD
, ZF_STANDARD
));
2177 // This is _the_ standard format.
2178 if (LocaleDataWrapper::areChecksEnabled() &&
2179 pStdFormat
->GetType() != NUMBERFORMAT_NUMBER
)
2181 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
2182 "SvNumberFormatter::ImpGenerateFormats: General format not NUMBER"));
2183 LocaleDataWrapper::outputCheckMessage(
2184 xLocaleData
->appendLocaleInfo( aMsg
));
2186 pStdFormat
->SetType( NUMBERFORMAT_NUMBER
);
2187 pStdFormat
->SetStandard();
2188 pStdFormat
->SetLastInsertKey( SV_MAX_ANZ_STANDARD_FORMATE
);
2192 if (LocaleDataWrapper::areChecksEnabled())
2194 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
2195 "SvNumberFormatter::ImpGenerateFormats: General format not insertable, nothing will work"));
2196 LocaleDataWrapper::outputCheckMessage(
2197 xLocaleData
->appendLocaleInfo( aMsg
));
2202 aFormatCode
= pFormatScanner
->GetBooleanString();
2203 pNewFormat
= new SvNumberformat( aFormatCode
,
2204 pFormatScanner
, pStringScanner
, nCheckPos
, ActLnge
);
2205 pNewFormat
->SetType(NUMBERFORMAT_LOGICAL
);
2206 pNewFormat
->SetStandard();
2207 if ( !aFTable
.Insert(
2208 CLOffset
+ SetIndexTable( NF_BOOLEAN
, ZF_STANDARD_LOGICAL
),
2214 pNewFormat
= new SvNumberformat( aFormatCode
,
2215 pFormatScanner
, pStringScanner
, nCheckPos
, ActLnge
);
2216 pNewFormat
->SetType(NUMBERFORMAT_TEXT
);
2217 pNewFormat
->SetStandard();
2218 if ( !aFTable
.Insert(
2219 CLOffset
+ SetIndexTable( NF_TEXT
, ZF_STANDARD_TEXT
),
2226 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_INT
);
2227 ImpInsertFormat( aFormatSeq
[nIdx
],
2228 CLOffset
+ SetIndexTable( NF_NUMBER_INT
, ZF_STANDARD
+1 ));
2231 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_DEC2
);
2232 ImpInsertFormat( aFormatSeq
[nIdx
],
2233 CLOffset
+ SetIndexTable( NF_NUMBER_DEC2
, ZF_STANDARD
+2 ));
2236 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_1000INT
);
2237 ImpInsertFormat( aFormatSeq
[nIdx
],
2238 CLOffset
+ SetIndexTable( NF_NUMBER_1000INT
, ZF_STANDARD
+3 ));
2241 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_1000DEC2
);
2242 ImpInsertFormat( aFormatSeq
[nIdx
],
2243 CLOffset
+ SetIndexTable( NF_NUMBER_1000DEC2
, ZF_STANDARD
+4 ));
2245 // #.##0,00 System country/language dependent since number formatter version 6
2246 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_SYSTEM
);
2247 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2248 CLOffset
+ SetIndexTable( NF_NUMBER_SYSTEM
, ZF_STANDARD
+5 ),
2249 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2253 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::PERCENT_NUMBER
);
2254 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2257 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_PERCENT_INT
);
2258 ImpInsertFormat( aFormatSeq
[nIdx
],
2259 CLOffset
+ SetIndexTable( NF_PERCENT_INT
, ZF_STANDARD_PERCENT
));
2262 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_PERCENT_DEC2
);
2263 ImpInsertFormat( aFormatSeq
[nIdx
],
2264 CLOffset
+ SetIndexTable( NF_PERCENT_DEC2
, ZF_STANDARD_PERCENT
+1 ));
2268 // Currency. NO default standard option! Default is determined of locale
2269 // data default currency and format is generated if needed.
2270 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::CURRENCY
);
2271 if (LocaleDataWrapper::areChecksEnabled())
2273 // though no default desired here, test for correctness of locale data
2274 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2278 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000INT
);
2279 bDefault
= aFormatSeq
[nIdx
].Default
;
2280 aFormatSeq
[nIdx
].Default
= sal_False
;
2281 ImpInsertFormat( aFormatSeq
[nIdx
],
2282 CLOffset
+ SetIndexTable( NF_CURRENCY_1000INT
, ZF_STANDARD_CURRENCY
));
2283 aFormatSeq
[nIdx
].Default
= bDefault
;
2286 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000DEC2
);
2287 bDefault
= aFormatSeq
[nIdx
].Default
;
2288 aFormatSeq
[nIdx
].Default
= sal_False
;
2289 ImpInsertFormat( aFormatSeq
[nIdx
],
2290 CLOffset
+ SetIndexTable( NF_CURRENCY_1000DEC2
, ZF_STANDARD_CURRENCY
+1 ));
2291 aFormatSeq
[nIdx
].Default
= bDefault
;
2293 // #,##0 negative red
2294 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000INT_RED
);
2295 bDefault
= aFormatSeq
[nIdx
].Default
;
2296 aFormatSeq
[nIdx
].Default
= sal_False
;
2297 ImpInsertFormat( aFormatSeq
[nIdx
],
2298 CLOffset
+ SetIndexTable( NF_CURRENCY_1000INT_RED
, ZF_STANDARD_CURRENCY
+2 ));
2299 aFormatSeq
[nIdx
].Default
= bDefault
;
2301 // #,##0.00 negative red
2302 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000DEC2_RED
);
2303 bDefault
= aFormatSeq
[nIdx
].Default
;
2304 aFormatSeq
[nIdx
].Default
= sal_False
;
2305 ImpInsertFormat( aFormatSeq
[nIdx
],
2306 CLOffset
+ SetIndexTable( NF_CURRENCY_1000DEC2_RED
, ZF_STANDARD_CURRENCY
+3 ));
2307 aFormatSeq
[nIdx
].Default
= bDefault
;
2309 // #,##0.00 USD since number formatter version 3
2310 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000DEC2_CCC
);
2311 bDefault
= aFormatSeq
[nIdx
].Default
;
2312 aFormatSeq
[nIdx
].Default
= sal_False
;
2313 pNewFormat
= ImpInsertFormat( aFormatSeq
[nIdx
],
2314 CLOffset
+ SetIndexTable( NF_CURRENCY_1000DEC2_CCC
, ZF_STANDARD_CURRENCY
+4 ));
2316 pNewFormat
->SetUsed(TRUE
); // must be saved for older versions
2317 aFormatSeq
[nIdx
].Default
= bDefault
;
2319 // #.##0,-- since number formatter version 6
2320 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000DEC2_DASHED
);
2321 bDefault
= aFormatSeq
[nIdx
].Default
;
2322 aFormatSeq
[nIdx
].Default
= sal_False
;
2323 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2324 CLOffset
+ SetIndexTable( NF_CURRENCY_1000DEC2_DASHED
, ZF_STANDARD_CURRENCY
+5 ),
2325 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2326 aFormatSeq
[nIdx
].Default
= bDefault
;
2331 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::DATE
);
2332 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2335 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYSTEM_SHORT
);
2336 ImpInsertFormat( aFormatSeq
[nIdx
],
2337 CLOffset
+ SetIndexTable( NF_DATE_SYSTEM_SHORT
, ZF_STANDARD_DATE
));
2340 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DEF_NNDDMMMYY
);
2341 ImpInsertFormat( aFormatSeq
[nIdx
],
2342 CLOffset
+ SetIndexTable( NF_DATE_DEF_NNDDMMMYY
, ZF_STANDARD_DATE
+1 ));
2344 // DD.MM.YY def/System
2345 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_MMYY
);
2346 ImpInsertFormat( aFormatSeq
[nIdx
],
2347 CLOffset
+ SetIndexTable( NF_DATE_SYS_MMYY
, ZF_STANDARD_DATE
+2 ));
2350 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DDMMM
);
2351 ImpInsertFormat( aFormatSeq
[nIdx
],
2352 CLOffset
+ SetIndexTable( NF_DATE_SYS_DDMMM
, ZF_STANDARD_DATE
+3 ));
2355 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_MMMM
);
2356 ImpInsertFormat( aFormatSeq
[nIdx
],
2357 CLOffset
+ SetIndexTable( NF_DATE_MMMM
, ZF_STANDARD_DATE
+4 ));
2360 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_QQJJ
);
2361 ImpInsertFormat( aFormatSeq
[nIdx
],
2362 CLOffset
+ SetIndexTable( NF_DATE_QQJJ
, ZF_STANDARD_DATE
+5 ));
2364 // DD.MM.YYYY since number formatter version 2, was DD.MM.[YY]YY
2365 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DDMMYYYY
);
2366 pNewFormat
= ImpInsertFormat( aFormatSeq
[nIdx
],
2367 CLOffset
+ SetIndexTable( NF_DATE_SYS_DDMMYYYY
, ZF_STANDARD_DATE
+6 ));
2369 pNewFormat
->SetUsed(TRUE
); // must be saved for older versions
2371 // DD.MM.YY def/System, since number formatter version 6
2372 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DDMMYY
);
2373 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2374 CLOffset
+ SetIndexTable( NF_DATE_SYS_DDMMYY
, ZF_STANDARD_DATE
+7 ),
2375 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2377 // NNN, D. MMMM YYYY System
2378 // Long day of week: "NNNN" instead of "NNN," because of compatibility
2379 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYSTEM_LONG
);
2380 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2381 CLOffset
+ SetIndexTable( NF_DATE_SYSTEM_LONG
, ZF_STANDARD_DATE
+8 ),
2382 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2384 // Hard coded but system (regional settings) delimiters dependent long date formats
2385 // since numberformatter version 6
2387 // D. MMM YY def/System
2388 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DMMMYY
);
2389 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2390 CLOffset
+ SetIndexTable( NF_DATE_SYS_DMMMYY
, ZF_STANDARD_DATE
+9 ),
2391 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2393 //! Unfortunally TLOT intended only 10 builtin formats per category, more
2394 //! would overwrite the next category (ZF_STANDARD_TIME) :-((
2395 //! Therefore they are inserted with nNewExtended++ (which is also limited)
2397 // D. MMM YYYY def/System
2398 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DMMMYYYY
);
2399 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2400 CLOffset
+ SetIndexTable( NF_DATE_SYS_DMMMYYYY
, nNewExtended
++ ),
2401 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2403 // D. MMMM YYYY def/System
2404 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DMMMMYYYY
);
2405 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2406 CLOffset
+ SetIndexTable( NF_DATE_SYS_DMMMMYYYY
, nNewExtended
++ ),
2407 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2409 // NN, D. MMM YY def/System
2410 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_NNDMMMYY
);
2411 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2412 CLOffset
+ SetIndexTable( NF_DATE_SYS_NNDMMMYY
, nNewExtended
++ ),
2413 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2415 // NN, D. MMMM YYYY def/System
2416 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_NNDMMMMYYYY
);
2417 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2418 CLOffset
+ SetIndexTable( NF_DATE_SYS_NNDMMMMYYYY
, nNewExtended
++ ),
2419 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2421 // NNN, D. MMMM YYYY def/System
2422 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_NNNNDMMMMYYYY
);
2423 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2424 CLOffset
+ SetIndexTable( NF_DATE_SYS_NNNNDMMMMYYYY
, nNewExtended
++ ),
2425 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2427 // Hard coded DIN (Deutsche Industrie Norm) and EN (European Norm) date formats
2429 // D. MMM. YYYY DIN/EN
2430 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DIN_DMMMYYYY
);
2431 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2432 CLOffset
+ SetIndexTable( NF_DATE_DIN_DMMMYYYY
, nNewExtended
++ ),
2433 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2435 // D. MMMM YYYY DIN/EN
2436 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DIN_DMMMMYYYY
);
2437 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2438 CLOffset
+ SetIndexTable( NF_DATE_DIN_DMMMMYYYY
, nNewExtended
++ ),
2439 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2442 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DIN_MMDD
);
2443 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2444 CLOffset
+ SetIndexTable( NF_DATE_DIN_MMDD
, nNewExtended
++ ),
2445 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2448 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DIN_YYMMDD
);
2449 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2450 CLOffset
+ SetIndexTable( NF_DATE_DIN_YYMMDD
, nNewExtended
++ ),
2451 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2453 // YYYY-MM-DD DIN/EN
2454 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DIN_YYYYMMDD
);
2455 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2456 CLOffset
+ SetIndexTable( NF_DATE_DIN_YYYYMMDD
, nNewExtended
++ ),
2457 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2462 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::TIME
);
2463 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2466 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HHMM
);
2467 ImpInsertFormat( aFormatSeq
[nIdx
],
2468 CLOffset
+ SetIndexTable( NF_TIME_HHMM
, ZF_STANDARD_TIME
));
2471 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HHMMSS
);
2472 ImpInsertFormat( aFormatSeq
[nIdx
],
2473 CLOffset
+ SetIndexTable( NF_TIME_HHMMSS
, ZF_STANDARD_TIME
+1 ));
2476 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HHMMAMPM
);
2477 ImpInsertFormat( aFormatSeq
[nIdx
],
2478 CLOffset
+ SetIndexTable( NF_TIME_HHMMAMPM
, ZF_STANDARD_TIME
+2 ));
2481 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HHMMSSAMPM
);
2482 ImpInsertFormat( aFormatSeq
[nIdx
],
2483 CLOffset
+ SetIndexTable( NF_TIME_HHMMSSAMPM
, ZF_STANDARD_TIME
+3 ));
2486 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HH_MMSS
);
2487 ImpInsertFormat( aFormatSeq
[nIdx
],
2488 CLOffset
+ SetIndexTable( NF_TIME_HH_MMSS
, ZF_STANDARD_TIME
+4 ));
2491 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_MMSS00
);
2492 ImpInsertFormat( aFormatSeq
[nIdx
],
2493 CLOffset
+ SetIndexTable( NF_TIME_MMSS00
, ZF_STANDARD_TIME
+5 ));
2496 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HH_MMSS00
);
2497 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2498 CLOffset
+ SetIndexTable( NF_TIME_HH_MMSS00
, ZF_STANDARD_TIME
+6 ),
2499 SV_NUMBERFORMATTER_VERSION_NF_TIME_HH_MMSS00
);
2504 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::DATE_TIME
);
2505 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2507 // DD.MM.YY HH:MM System
2508 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATETIME_SYSTEM_SHORT_HHMM
);
2509 ImpInsertFormat( aFormatSeq
[nIdx
],
2510 CLOffset
+ SetIndexTable( NF_DATETIME_SYSTEM_SHORT_HHMM
, ZF_STANDARD_DATETIME
));
2512 // DD.MM.YYYY HH:MM:SS System
2513 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATETIME_SYS_DDMMYYYY_HHMMSS
);
2514 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2515 CLOffset
+ SetIndexTable( NF_DATETIME_SYS_DDMMYYYY_HHMMSS
, ZF_STANDARD_DATETIME
+1 ),
2516 SV_NUMBERFORMATTER_VERSION_NF_DATETIME_SYS_DDMMYYYY_HHMMSS
);
2520 // Scientific number
2521 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::SCIENTIFIC_NUMBER
);
2522 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2525 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_SCIENTIFIC_000E000
);
2526 ImpInsertFormat( aFormatSeq
[nIdx
],
2527 CLOffset
+ SetIndexTable( NF_SCIENTIFIC_000E000
, ZF_STANDARD_SCIENTIFIC
));
2530 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_SCIENTIFIC_000E00
);
2531 ImpInsertFormat( aFormatSeq
[nIdx
],
2532 CLOffset
+ SetIndexTable( NF_SCIENTIFIC_000E00
, ZF_STANDARD_SCIENTIFIC
+1 ));
2536 // Fraction number (no default option)
2537 i18n::NumberFormatCode aSingleFormatCode
;
2540 aSingleFormatCode
.Code
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "# ?/?" ) );
2541 String
s25( RTL_CONSTASCII_USTRINGPARAM( "# ?/?" ) ); // # ?/?
2542 ImpInsertFormat( aSingleFormatCode
,
2543 CLOffset
+ SetIndexTable( NF_FRACTION_1
, ZF_STANDARD_FRACTION
));
2546 //! "??/" would be interpreted by the compiler as a trigraph for '\'
2547 aSingleFormatCode
.Code
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "# ?\?/?\?" ) );
2548 ImpInsertFormat( aSingleFormatCode
,
2549 CLOffset
+ SetIndexTable( NF_FRACTION_2
, ZF_STANDARD_FRACTION
+1 ));
2551 // Week of year must be appended here because of nNewExtended
2552 const String
* pKeyword
= pFormatScanner
->GetKeywords();
2553 aSingleFormatCode
.Code
= pKeyword
[NF_KEY_WW
];
2554 ImpInsertNewStandardFormat( aSingleFormatCode
,
2555 CLOffset
+ SetIndexTable( NF_DATE_WW
, nNewExtended
++ ),
2556 SV_NUMBERFORMATTER_VERSION_NF_DATE_WW
);
2560 bIndexTableInitialized
= TRUE
;
2561 DBG_ASSERT( nNewExtended
<= ZF_STANDARD_NEWEXTENDEDMAX
,
2562 "ImpGenerateFormats: overflow of nNewExtended standard formats" );
2564 // Now all additional format codes provided by I18N, but only if not
2565 // loading from old SO5 file format, then they are appended last.
2567 ImpGenerateAdditionalFormats( CLOffset
, aNumberFormatCode
, FALSE
);
2569 if (bOldConvertMode
)
2570 pFormatScanner
->SetConvertMode(TRUE
);
2574 void SvNumberFormatter::ImpGenerateAdditionalFormats( sal_uInt32 CLOffset
,
2575 NumberFormatCodeWrapper
& rNumberFormatCode
, BOOL bAfterLoadingSO5
)
2577 using namespace ::com::sun::star
;
2579 SvNumberformat
* pStdFormat
=
2580 (SvNumberformat
*) aFTable
.Get( CLOffset
+ ZF_STANDARD
);
2583 DBG_ERRORFILE( "ImpGenerateAdditionalFormats: no GENERAL format" );
2586 sal_uInt32 nPos
= CLOffset
+ pStdFormat
->GetLastInsertKey();
2587 rNumberFormatCode
.setLocale( GetLocale() );
2590 // All currencies, this time with [$...] which was stripped in
2591 // ImpGenerateFormats for old "automatic" currency formats.
2592 uno::Sequence
< i18n::NumberFormatCode
> aFormatSeq
=
2593 rNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::CURRENCY
);
2594 i18n::NumberFormatCode
* pFormatArr
= aFormatSeq
.getArray();
2595 sal_Int32 nCodes
= aFormatSeq
.getLength();
2596 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), nCodes
);
2597 for ( j
= 0; j
< nCodes
; j
++ )
2599 if ( nPos
- CLOffset
>= SV_COUNTRY_LANGUAGE_OFFSET
)
2601 DBG_ERRORFILE( "ImpGenerateAdditionalFormats: too many formats" );
2604 if ( pFormatArr
[j
].Index
< NF_INDEX_TABLE_ENTRIES
&&
2605 pFormatArr
[j
].Index
!= NF_CURRENCY_1000DEC2_CCC
)
2606 { // Insert only if not already inserted, but internal index must be
2607 // above so ImpInsertFormat can distinguish it.
2608 sal_Int16 nOrgIndex
= pFormatArr
[j
].Index
;
2609 pFormatArr
[j
].Index
= sal::static_int_cast
< sal_Int16
>(
2610 pFormatArr
[j
].Index
+ nCodes
+ NF_INDEX_TABLE_ENTRIES
);
2611 //! no default on currency
2612 sal_Bool bDefault
= aFormatSeq
[j
].Default
;
2613 aFormatSeq
[j
].Default
= sal_False
;
2614 if ( ImpInsertNewStandardFormat( pFormatArr
[j
], nPos
+1,
2615 SV_NUMBERFORMATTER_VERSION_ADDITIONAL_I18N_FORMATS
,
2616 bAfterLoadingSO5
, nOrgIndex
) )
2618 pFormatArr
[j
].Index
= nOrgIndex
;
2619 aFormatSeq
[j
].Default
= bDefault
;
2623 // all additional format codes provided by I18N that are not old standard index
2624 aFormatSeq
= rNumberFormatCode
.getAllFormatCodes();
2625 nCodes
= aFormatSeq
.getLength();
2628 pFormatArr
= aFormatSeq
.getArray();
2630 sal_Int32 nDef
= ImpAdjustFormatCodeDefault( pFormatArr
, nCodes
, FALSE
);
2631 // don't have any defaults here
2632 pFormatArr
[nDef
].Default
= sal_False
;
2633 for ( j
= 0; j
< nCodes
; j
++ )
2635 if ( nPos
- CLOffset
>= SV_COUNTRY_LANGUAGE_OFFSET
)
2637 DBG_ERRORFILE( "ImpGenerateAdditionalFormats: too many formats" );
2640 if ( pFormatArr
[j
].Index
>= NF_INDEX_TABLE_ENTRIES
)
2641 if ( ImpInsertNewStandardFormat( pFormatArr
[j
], nPos
+1,
2642 SV_NUMBERFORMATTER_VERSION_ADDITIONAL_I18N_FORMATS
,
2643 bAfterLoadingSO5
) )
2648 pStdFormat
->SetLastInsertKey( (USHORT
)(nPos
- CLOffset
) );
2652 void SvNumberFormatter::ImpGetPosCurrFormat( String
& sPosStr
, const String
& rCurrSymbol
)
2654 NfCurrencyEntry::CompletePositiveFormatString( sPosStr
,
2655 rCurrSymbol
, xLocaleData
->getCurrPositiveFormat() );
2658 void SvNumberFormatter::ImpGetNegCurrFormat( String
& sNegStr
, const String
& rCurrSymbol
)
2660 NfCurrencyEntry::CompleteNegativeFormatString( sNegStr
,
2661 rCurrSymbol
, xLocaleData
->getCurrNegativeFormat() );
2664 void SvNumberFormatter::GenerateFormat(String
& sString
,
2672 if (eLnge
== LANGUAGE_DONTKNOW
)
2674 short eType
= GetType(nIndex
);
2676 ImpGenerateCL(eLnge
); // ggfs. neu Standard-
2680 utl::DigitGroupingIterator
aGrouping( xLocaleData
->getDigitGrouping());
2681 const xub_StrLen nDigitsInFirstGroup
= static_cast<xub_StrLen
>(aGrouping
.get());
2682 const String
& rThSep
= GetNumThousandSep();
2683 if (nAnzLeading
== 0)
2691 sString
.Expand( sString
.Len() + nDigitsInFirstGroup
, '#' );
2696 for (i
= 0; i
< nAnzLeading
; i
++)
2698 if (bThousand
&& i
> 0 && i
== aGrouping
.getPos())
2700 sString
.Insert( rThSep
, 0 );
2701 aGrouping
.advance();
2703 sString
.Insert('0',0);
2705 if (bThousand
&& nAnzLeading
< nDigitsInFirstGroup
+ 1)
2707 for (i
= nAnzLeading
; i
< nDigitsInFirstGroup
+ 1; i
++)
2709 if (bThousand
&& i
% nDigitsInFirstGroup
== 0)
2710 sString
.Insert( rThSep
, 0 );
2711 sString
.Insert('#',0);
2717 sString
+= GetNumDecimalSep();
2718 sString
.Expand( sString
.Len() + nPrecision
, '0' );
2720 if (eType
== NUMBERFORMAT_PERCENT
)
2722 else if (eType
== NUMBERFORMAT_CURRENCY
)
2724 String sNegStr
= sString
;
2726 const NfCurrencyEntry
* pEntry
;
2728 if ( GetNewCurrencySymbolString( nIndex
, aCurr
, &pEntry
, &bBank
) )
2732 USHORT nPosiForm
= NfCurrencyEntry::GetEffectivePositiveFormat(
2733 xLocaleData
->getCurrPositiveFormat(),
2734 pEntry
->GetPositiveFormat(), bBank
);
2735 USHORT nNegaForm
= NfCurrencyEntry::GetEffectiveNegativeFormat(
2736 xLocaleData
->getCurrNegativeFormat(),
2737 pEntry
->GetNegativeFormat(), bBank
);
2738 pEntry
->CompletePositiveFormatString( sString
, bBank
,
2740 pEntry
->CompleteNegativeFormatString( sNegStr
, bBank
,
2744 { // assume currency abbreviation (AKA banking symbol), not symbol
2745 USHORT nPosiForm
= NfCurrencyEntry::GetEffectivePositiveFormat(
2746 xLocaleData
->getCurrPositiveFormat(),
2747 xLocaleData
->getCurrPositiveFormat(), TRUE
);
2748 USHORT nNegaForm
= NfCurrencyEntry::GetEffectiveNegativeFormat(
2749 xLocaleData
->getCurrNegativeFormat(),
2750 xLocaleData
->getCurrNegativeFormat(), TRUE
);
2751 NfCurrencyEntry::CompletePositiveFormatString( sString
, aCurr
,
2753 NfCurrencyEntry::CompleteNegativeFormatString( sNegStr
, aCurr
,
2758 { // "automatic" old style
2759 String aSymbol
, aAbbrev
;
2760 GetCompatibilityCurrency( aSymbol
, aAbbrev
);
2761 ImpGetPosCurrFormat( sString
, aSymbol
);
2762 ImpGetNegCurrFormat( sNegStr
, aSymbol
);
2768 sString
+= pFormatScanner
->GetRedString();
2775 if (IsRed
&& eType
!= NUMBERFORMAT_CURRENCY
)
2777 String sTmpStr
= sString
;
2780 sTmpStr
+= pFormatScanner
->GetRedString();
2788 BOOL
SvNumberFormatter::IsUserDefined(const String
& sStr
,
2791 if (eLnge
== LANGUAGE_DONTKNOW
)
2793 sal_uInt32 CLOffset
= ImpGenerateCL(eLnge
); // ggfs. neu Standard-
2796 sal_uInt32 nKey
= ImpIsEntry(sStr
, CLOffset
, eLnge
);
2797 if (nKey
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
2799 SvNumberformat
* pEntry
= aFTable
.Get(nKey
);
2800 if ( pEntry
&& ((pEntry
->GetType() & NUMBERFORMAT_DEFINED
) != 0) )
2805 sal_uInt32
SvNumberFormatter::GetEntryKey(const String
& sStr
,
2808 if (eLnge
== LANGUAGE_DONTKNOW
)
2810 sal_uInt32 CLOffset
= ImpGenerateCL(eLnge
); // ggfs. neu Standard-
2812 return ImpIsEntry(sStr
, CLOffset
, eLnge
);
2815 sal_uInt32
SvNumberFormatter::GetStandardIndex(LanguageType eLnge
)
2817 if (eLnge
== LANGUAGE_DONTKNOW
)
2819 return GetStandardFormat(NUMBERFORMAT_NUMBER
, eLnge
);
2822 short SvNumberFormatter::GetType(sal_uInt32 nFIndex
)
2825 SvNumberformat
* pFormat
= (SvNumberformat
*) aFTable
.Get(nFIndex
);
2827 eType
= NUMBERFORMAT_UNDEFINED
;
2830 eType
= pFormat
->GetType() &~NUMBERFORMAT_DEFINED
;
2832 eType
= NUMBERFORMAT_DEFINED
;
2837 void SvNumberFormatter::ClearMergeTable()
2841 sal_uInt32
* pIndex
= (sal_uInt32
*) pMergeTable
->First();
2845 pIndex
= pMergeTable
->Next();
2847 pMergeTable
->Clear();
2851 SvNumberFormatterIndexTable
* SvNumberFormatter::MergeFormatter(SvNumberFormatter
& rTable
)
2856 pMergeTable
= new SvNumberFormatterIndexTable
;
2857 sal_uInt32 nCLOffset
= 0;
2858 sal_uInt32 nOldKey
, nOffset
, nNewKey
;
2859 sal_uInt32
* pNewIndex
;
2860 SvNumberformat
* pNewEntry
;
2861 SvNumberformat
* pFormat
= rTable
.aFTable
.First();
2864 nOldKey
= rTable
.aFTable
.GetCurKey();
2865 nOffset
= nOldKey
% SV_COUNTRY_LANGUAGE_OFFSET
; // relativIndex
2866 if (nOffset
== 0) // 1. Format von CL
2867 nCLOffset
= ImpGenerateCL(pFormat
->GetLanguage());
2869 if (nOffset
<= SV_MAX_ANZ_STANDARD_FORMATE
) // Std.form.
2871 nNewKey
= nCLOffset
+ nOffset
;
2872 if (!aFTable
.Get(nNewKey
)) // noch nicht da
2874 // pNewEntry = new SvNumberformat(*pFormat); // Copy reicht nicht !!!
2875 pNewEntry
= new SvNumberformat( *pFormat
, *pFormatScanner
);
2876 if (!aFTable
.Insert(nNewKey
, pNewEntry
))
2879 if (nNewKey
!= nOldKey
) // neuer Index
2881 pNewIndex
= new sal_uInt32(nNewKey
);
2882 if (!pMergeTable
->Insert(nOldKey
,pNewIndex
))
2886 else // benutzerdef.
2888 // pNewEntry = new SvNumberformat(*pFormat); // Copy reicht nicht !!!
2889 pNewEntry
= new SvNumberformat( *pFormat
, *pFormatScanner
);
2890 nNewKey
= ImpIsEntry(pNewEntry
->GetFormatstring(),
2892 pFormat
->GetLanguage());
2893 if (nNewKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
) // schon vorhanden
2897 SvNumberformat
* pStdFormat
=
2898 (SvNumberformat
*) aFTable
.Get(nCLOffset
+ ZF_STANDARD
);
2899 sal_uInt32 nPos
= nCLOffset
+ pStdFormat
->GetLastInsertKey();
2901 if (nPos
- nCLOffset
>= SV_COUNTRY_LANGUAGE_OFFSET
)
2905 "SvNumberFormatter:: Zu viele Formate pro CL");
2908 else if (!aFTable
.Insert(nNewKey
, pNewEntry
))
2911 pStdFormat
->SetLastInsertKey((USHORT
) (nNewKey
- nCLOffset
));
2913 if (nNewKey
!= nOldKey
) // neuer Index
2915 pNewIndex
= new sal_uInt32(nNewKey
);
2916 if (!pMergeTable
->Insert(nOldKey
,pNewIndex
))
2920 pFormat
= rTable
.aFTable
.Next();
2926 SvNumberFormatterMergeMap
SvNumberFormatter::ConvertMergeTableToMap()
2928 if (!HasMergeFmtTbl())
2929 return SvNumberFormatterMergeMap();
2931 SvNumberFormatterMergeMap aMap
;
2932 for (sal_uInt32
* pIndex
= pMergeTable
->First(); pIndex
; pIndex
= pMergeTable
->Next())
2934 sal_uInt32 nOldKey
= pMergeTable
->GetCurKey();
2935 aMap
.insert( SvNumberFormatterMergeMap::value_type( nOldKey
, *pIndex
));
2942 sal_uInt32
SvNumberFormatter::GetFormatForLanguageIfBuiltIn( sal_uInt32 nFormat
,
2943 LanguageType eLnge
)
2945 if ( eLnge
== LANGUAGE_DONTKNOW
)
2947 if ( nFormat
< SV_COUNTRY_LANGUAGE_OFFSET
&& eLnge
== IniLnge
)
2948 return nFormat
; // es bleibt wie es ist
2949 sal_uInt32 nOffset
= nFormat
% SV_COUNTRY_LANGUAGE_OFFSET
; // relativIndex
2950 if ( nOffset
> SV_MAX_ANZ_STANDARD_FORMATE
)
2951 return nFormat
; // kein eingebautes Format
2952 sal_uInt32 nCLOffset
= ImpGenerateCL(eLnge
); // ggbf. generieren
2953 return nCLOffset
+ nOffset
;
2957 sal_uInt32
SvNumberFormatter::GetFormatIndex( NfIndexTableOffset nTabOff
,
2958 LanguageType eLnge
)
2960 if ( nTabOff
>= NF_INDEX_TABLE_ENTRIES
2961 || theIndexTable
[nTabOff
] == NUMBERFORMAT_ENTRY_NOT_FOUND
)
2962 return NUMBERFORMAT_ENTRY_NOT_FOUND
;
2963 if ( eLnge
== LANGUAGE_DONTKNOW
)
2965 sal_uInt32 nCLOffset
= ImpGenerateCL(eLnge
); // ggbf. generieren
2966 return nCLOffset
+ theIndexTable
[nTabOff
];
2970 NfIndexTableOffset
SvNumberFormatter::GetIndexTableOffset( sal_uInt32 nFormat
) const
2972 sal_uInt32 nOffset
= nFormat
% SV_COUNTRY_LANGUAGE_OFFSET
; // relativIndex
2973 if ( nOffset
> SV_MAX_ANZ_STANDARD_FORMATE
)
2974 return NF_INDEX_TABLE_ENTRIES
; // kein eingebautes Format
2975 for ( USHORT j
= 0; j
< NF_INDEX_TABLE_ENTRIES
; j
++ )
2977 if ( theIndexTable
[j
] == nOffset
)
2978 return (NfIndexTableOffset
) j
;
2980 return NF_INDEX_TABLE_ENTRIES
; // bad luck
2984 void SvNumberFormatter::SetYear2000( USHORT nVal
)
2986 pStringScanner
->SetYear2000( nVal
);
2990 USHORT
SvNumberFormatter::GetYear2000() const
2992 return pStringScanner
->GetYear2000();
2996 USHORT
SvNumberFormatter::ExpandTwoDigitYear( USHORT nYear
) const
2999 return SvNumberFormatter::ExpandTwoDigitYear( nYear
,
3000 pStringScanner
->GetYear2000() );
3006 USHORT
SvNumberFormatter::GetYear2000Default()
3008 return Application::GetSettings().GetMiscSettings().GetTwoDigitYearStart();
3013 const NfCurrencyTable
& SvNumberFormatter::GetTheCurrencyTable()
3015 ::osl::MutexGuard
aGuard( GetMutex() );
3016 while ( !bCurrencyTableInitialized
)
3017 ImpInitCurrencyTable();
3018 return theCurrencyTable::get();
3023 const NfCurrencyEntry
* SvNumberFormatter::MatchSystemCurrency()
3025 // MUST call GetTheCurrencyTable() before accessing nSystemCurrencyPosition
3026 const NfCurrencyTable
& rTable
= GetTheCurrencyTable();
3027 return nSystemCurrencyPosition
? rTable
[nSystemCurrencyPosition
] : NULL
;
3032 const NfCurrencyEntry
& SvNumberFormatter::GetCurrencyEntry( LanguageType eLang
)
3034 if ( eLang
== LANGUAGE_SYSTEM
)
3036 const NfCurrencyEntry
* pCurr
= MatchSystemCurrency();
3037 return pCurr
? *pCurr
: *(GetTheCurrencyTable()[0]);
3041 eLang
= MsLangId::getRealLanguage( eLang
);
3042 const NfCurrencyTable
& rTable
= GetTheCurrencyTable();
3043 USHORT nCount
= rTable
.Count();
3044 const NfCurrencyEntryPtr
* ppData
= rTable
.GetData();
3045 for ( USHORT j
= 0; j
< nCount
; j
++, ppData
++ )
3047 if ( (*ppData
)->GetLanguage() == eLang
)
3050 return *(rTable
[0]);
3056 const NfCurrencyEntry
* SvNumberFormatter::GetCurrencyEntry(
3057 const String
& rAbbrev
, LanguageType eLang
)
3059 eLang
= MsLangId::getRealLanguage( eLang
);
3060 const NfCurrencyTable
& rTable
= GetTheCurrencyTable();
3061 USHORT nCount
= rTable
.Count();
3062 const NfCurrencyEntryPtr
* ppData
= rTable
.GetData();
3063 for ( USHORT j
= 0; j
< nCount
; j
++, ppData
++ )
3065 if ( (*ppData
)->GetLanguage() == eLang
&&
3066 (*ppData
)->GetBankSymbol() == rAbbrev
)
3074 const NfCurrencyEntry
* SvNumberFormatter::GetLegacyOnlyCurrencyEntry(
3075 const String
& rSymbol
, const String
& rAbbrev
)
3077 if (!bCurrencyTableInitialized
)
3078 GetTheCurrencyTable(); // just for initialization
3079 const NfCurrencyTable
& rTable
= theLegacyOnlyCurrencyTable::get();
3080 USHORT nCount
= rTable
.Count();
3081 const NfCurrencyEntryPtr
* ppData
= rTable
.GetData();
3082 for ( USHORT j
= 0; j
< nCount
; j
++, ppData
++ )
3084 if ( (*ppData
)->GetSymbol() == rSymbol
&&
3085 (*ppData
)->GetBankSymbol() == rAbbrev
)
3093 IMPL_STATIC_LINK_NOINSTANCE( SvNumberFormatter
, CurrencyChangeLink
, void*, EMPTYARG
)
3095 ::osl::MutexGuard
aGuard( GetMutex() );
3097 LanguageType eLang
= LANGUAGE_SYSTEM
;
3098 SvtSysLocaleOptions().GetCurrencyAbbrevAndLanguage( aAbbrev
, eLang
);
3099 SetDefaultSystemCurrency( aAbbrev
, eLang
);
3105 void SvNumberFormatter::SetDefaultSystemCurrency( const String
& rAbbrev
, LanguageType eLang
)
3107 ::osl::MutexGuard
aGuard( GetMutex() );
3108 if ( eLang
== LANGUAGE_SYSTEM
)
3109 eLang
= Application::GetSettings().GetLanguage();
3110 const NfCurrencyTable
& rTable
= GetTheCurrencyTable();
3111 USHORT nCount
= rTable
.Count();
3112 const NfCurrencyEntryPtr
* ppData
= rTable
.GetData();
3113 if ( rAbbrev
.Len() )
3115 for ( USHORT j
= 0; j
< nCount
; j
++, ppData
++ )
3117 if ( (*ppData
)->GetLanguage() == eLang
&& (*ppData
)->GetBankSymbol() == rAbbrev
)
3119 nSystemCurrencyPosition
= j
;
3126 for ( USHORT j
= 0; j
< nCount
; j
++, ppData
++ )
3128 if ( (*ppData
)->GetLanguage() == eLang
)
3130 nSystemCurrencyPosition
= j
;
3135 nSystemCurrencyPosition
= 0; // not found => simple SYSTEM
3139 void SvNumberFormatter::ResetDefaultSystemCurrency()
3141 nDefaultSystemCurrencyFormat
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
3145 sal_uInt32
SvNumberFormatter::ImpGetDefaultSystemCurrencyFormat()
3147 if ( nDefaultSystemCurrencyFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
3151 NfWSStringsDtor aCurrList
;
3152 USHORT nDefault
= GetCurrencyFormatStrings( aCurrList
,
3153 GetCurrencyEntry( LANGUAGE_SYSTEM
), FALSE
);
3154 DBG_ASSERT( aCurrList
.Count(), "where is the NewCurrency System standard format?!?" );
3155 // if already loaded or user defined nDefaultSystemCurrencyFormat
3156 // will be set to the right value
3157 PutEntry( *aCurrList
.GetObject( nDefault
), nCheck
, nType
,
3158 nDefaultSystemCurrencyFormat
, LANGUAGE_SYSTEM
);
3159 DBG_ASSERT( nCheck
== 0, "NewCurrency CheckError" );
3160 DBG_ASSERT( nDefaultSystemCurrencyFormat
!= NUMBERFORMAT_ENTRY_NOT_FOUND
,
3161 "nDefaultSystemCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND" );
3163 return nDefaultSystemCurrencyFormat
;
3167 sal_uInt32
SvNumberFormatter::ImpGetDefaultCurrencyFormat()
3169 sal_uInt32 CLOffset
= ImpGetCLOffset( ActLnge
);
3170 sal_uInt32 nDefaultCurrencyFormat
=
3171 (sal_uInt32
)(sal_uIntPtr
) aDefaultFormatKeys
.Get( CLOffset
+ ZF_STANDARD_CURRENCY
);
3172 if ( !nDefaultCurrencyFormat
)
3173 nDefaultCurrencyFormat
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
3174 if ( nDefaultCurrencyFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
3176 // look for a defined standard
3177 sal_uInt32 nStopKey
= CLOffset
+ SV_COUNTRY_LANGUAGE_OFFSET
;
3179 aFTable
.Seek( CLOffset
);
3180 while ( (nKey
= aFTable
.GetCurKey()) >= CLOffset
&& nKey
< nStopKey
)
3182 const SvNumberformat
* pEntry
=
3183 (const SvNumberformat
*) aFTable
.GetCurObject();
3184 if ( pEntry
->IsStandard() && (pEntry
->GetType() & NUMBERFORMAT_CURRENCY
) )
3186 nDefaultCurrencyFormat
= nKey
;
3192 if ( nDefaultCurrencyFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
3193 { // none found, create one
3196 NfWSStringsDtor aCurrList
;
3197 USHORT nDefault
= GetCurrencyFormatStrings( aCurrList
,
3198 GetCurrencyEntry( ActLnge
), FALSE
);
3199 DBG_ASSERT( aCurrList
.Count(), "where is the NewCurrency standard format?" );
3200 if ( aCurrList
.Count() )
3202 // if already loaded or user defined nDefaultSystemCurrencyFormat
3203 // will be set to the right value
3204 PutEntry( *aCurrList
.GetObject( nDefault
), nCheck
, nType
,
3205 nDefaultCurrencyFormat
, ActLnge
);
3206 DBG_ASSERT( nCheck
== 0, "NewCurrency CheckError" );
3207 DBG_ASSERT( nDefaultCurrencyFormat
!= NUMBERFORMAT_ENTRY_NOT_FOUND
,
3208 "nDefaultCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND" );
3210 // old automatic currency format as a last resort
3211 if ( nDefaultCurrencyFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
3212 nDefaultCurrencyFormat
= CLOffset
+ ZF_STANDARD_CURRENCY
+3;
3214 { // mark as standard so that it is found next time
3215 SvNumberformat
* pEntry
= aFTable
.Get( nDefaultCurrencyFormat
);
3217 pEntry
->SetStandard();
3220 aDefaultFormatKeys
.Insert( CLOffset
+ ZF_STANDARD_CURRENCY
,
3221 (void*) nDefaultCurrencyFormat
);
3223 return nDefaultCurrencyFormat
;
3228 // try to make it inline if possible since this a loop body
3229 // TRUE: continue; FALSE: break loop, if pFoundEntry==NULL dupe found
3233 BOOL
SvNumberFormatter::ImpLookupCurrencyEntryLoopBody(
3234 const NfCurrencyEntry
*& pFoundEntry
, BOOL
& bFoundBank
,
3235 const NfCurrencyEntry
* pData
, USHORT nPos
, const String
& rSymbol
)
3238 if ( pData
->GetSymbol() == rSymbol
)
3243 else if ( pData
->GetBankSymbol() == rSymbol
)
3252 if ( pFoundEntry
&& pFoundEntry
!= pData
)
3255 return FALSE
; // break loop, not unique
3258 { // first entry is SYSTEM
3259 pFoundEntry
= MatchSystemCurrency();
3261 return FALSE
; // break loop
3262 // even if there are more matching entries
3263 // this one is propably the one we are looking for
3265 pFoundEntry
= pData
;
3268 pFoundEntry
= pData
;
3274 BOOL
SvNumberFormatter::GetNewCurrencySymbolString( sal_uInt32 nFormat
,
3275 String
& rStr
, const NfCurrencyEntry
** ppEntry
/* = NULL */,
3276 BOOL
* pBank
/* = NULL */ ) const
3283 SvNumberformat
* pFormat
= (SvNumberformat
*) aFTable
.Get( nFormat
);
3286 String aSymbol
, aExtension
;
3287 if ( pFormat
->GetNewCurrencySymbol( aSymbol
, aExtension
) )
3291 BOOL bFoundBank
= FALSE
;
3292 // we definiteley need an entry matching the format code string
3293 const NfCurrencyEntry
* pFoundEntry
= GetCurrencyEntry(
3294 bFoundBank
, aSymbol
, aExtension
, pFormat
->GetLanguage(),
3298 *ppEntry
= pFoundEntry
;
3300 *pBank
= bFoundBank
;
3301 pFoundEntry
->BuildSymbolString( rStr
, bFoundBank
);
3305 { // analog zu BuildSymbolString
3308 if ( aSymbol
.Search( '-' ) != STRING_NOTFOUND
||
3309 aSymbol
.Search( ']' ) != STRING_NOTFOUND
)
3317 if ( aExtension
.Len() )
3329 const NfCurrencyEntry
* SvNumberFormatter::GetCurrencyEntry( BOOL
& bFoundBank
,
3330 const String
& rSymbol
, const String
& rExtension
,
3331 LanguageType eFormatLanguage
, BOOL bOnlyStringLanguage
)
3333 xub_StrLen nExtLen
= rExtension
.Len();
3334 LanguageType eExtLang
;
3337 sal_Int32 nExtLang
= ::rtl::OUString( rExtension
).toInt32( 16 );
3339 eExtLang
= LANGUAGE_DONTKNOW
;
3341 eExtLang
= (LanguageType
) ((nExtLang
< 0) ?
3342 -nExtLang
: nExtLang
);
3345 eExtLang
= LANGUAGE_DONTKNOW
;
3346 const NfCurrencyEntry
* pFoundEntry
= NULL
;
3347 const NfCurrencyTable
& rTable
= GetTheCurrencyTable();
3348 USHORT nCount
= rTable
.Count();
3351 // first try with given extension language/country
3354 const NfCurrencyEntryPtr
* ppData
= rTable
.GetData();
3355 for ( USHORT j
= 0; j
< nCount
&& bCont
; j
++, ppData
++ )
3357 LanguageType eLang
= (*ppData
)->GetLanguage();
3358 if ( eLang
== eExtLang
||
3359 ((eExtLang
== LANGUAGE_DONTKNOW
) &&
3360 (eLang
== LANGUAGE_SYSTEM
))
3363 bCont
= ImpLookupCurrencyEntryLoopBody( pFoundEntry
, bFoundBank
,
3364 *ppData
, j
, rSymbol
);
3370 if ( pFoundEntry
|| !bCont
|| (bOnlyStringLanguage
&& nExtLen
) )
3373 if ( !bOnlyStringLanguage
)
3375 // now try the language/country of the number format
3376 const NfCurrencyEntryPtr
* ppData
= rTable
.GetData();
3377 for ( USHORT j
= 0; j
< nCount
&& bCont
; j
++, ppData
++ )
3379 LanguageType eLang
= (*ppData
)->GetLanguage();
3380 if ( eLang
== eFormatLanguage
||
3381 ((eFormatLanguage
== LANGUAGE_DONTKNOW
) &&
3382 (eLang
== LANGUAGE_SYSTEM
))
3385 bCont
= ImpLookupCurrencyEntryLoopBody( pFoundEntry
, bFoundBank
,
3386 *ppData
, j
, rSymbol
);
3391 if ( pFoundEntry
|| !bCont
)
3395 // then try without language/country if no extension specified
3398 const NfCurrencyEntryPtr
* ppData
= rTable
.GetData();
3399 for ( USHORT j
= 0; j
< nCount
&& bCont
; j
++, ppData
++ )
3401 bCont
= ImpLookupCurrencyEntryLoopBody( pFoundEntry
, bFoundBank
,
3402 *ppData
, j
, rSymbol
);
3410 void SvNumberFormatter::GetCompatibilityCurrency( String
& rSymbol
, String
& rAbbrev
) const
3412 ::com::sun::star::uno::Sequence
< ::com::sun::star::i18n::Currency2
>
3413 xCurrencies
= xLocaleData
->getAllCurrencies();
3414 sal_Int32 nCurrencies
= xCurrencies
.getLength();
3416 for ( j
=0; j
< nCurrencies
; ++j
)
3418 if ( xCurrencies
[j
].UsedInCompatibleFormatCodes
)
3420 rSymbol
= xCurrencies
[j
].Symbol
;
3421 rAbbrev
= xCurrencies
[j
].BankSymbol
;
3425 if ( j
>= nCurrencies
)
3427 if (LocaleDataWrapper::areChecksEnabled())
3429 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
3430 "GetCompatibilityCurrency: none?"));
3431 LocaleDataWrapper::outputCheckMessage(
3432 xLocaleData
->appendLocaleInfo( aMsg
));
3434 rSymbol
= xLocaleData
->getCurrSymbol();
3435 rAbbrev
= xLocaleData
->getCurrBankSymbol();
3440 void lcl_CheckCurrencySymbolPosition( const NfCurrencyEntry
& rCurr
)
3442 short nPos
= -1; // -1:=unknown, 0:=vorne, 1:=hinten
3444 switch ( rCurr
.GetPositiveFormat() )
3459 LocaleDataWrapper::outputCheckMessage(
3460 "lcl_CheckCurrencySymbolPosition: unknown PositiveFormat");
3463 switch ( rCurr
.GetNegativeFormat() )
3514 LocaleDataWrapper::outputCheckMessage(
3515 "lcl_CheckCurrencySymbolPosition: unknown NegativeFormat");
3518 if ( nPos
>= 0 && nNeg
>= 0 && nPos
!= nNeg
)
3520 ByteString
aStr( "positions of currency symbols differ\nLanguage: " );
3521 aStr
+= ByteString::CreateFromInt32( rCurr
.GetLanguage() );
3523 aStr
+= ByteString( rCurr
.GetSymbol(), RTL_TEXTENCODING_UTF8
);
3524 aStr
+= "> positive: ";
3525 aStr
+= ByteString::CreateFromInt32( rCurr
.GetPositiveFormat() );
3526 aStr
+= ( nPos
? " (postfix)" : " (prefix)" );
3527 aStr
+= ", negative: ";
3528 aStr
+= ByteString::CreateFromInt32( rCurr
.GetNegativeFormat() );
3529 aStr
+= ( nNeg
? " (postfix)" : " (prefix)" );
3531 // seems that there really are some currencies which differ, e.g. YugoDinar
3532 DBG_ERRORFILE( aStr
.GetBuffer() );
3539 void SvNumberFormatter::ImpInitCurrencyTable()
3541 // racing condition possible:
3542 // ::osl::MutexGuard aGuard( GetMutex() );
3543 // while ( !bCurrencyTableInitialized )
3544 // ImpInitCurrencyTable();
3545 static BOOL bInitializing
= FALSE
;
3546 if ( bCurrencyTableInitialized
|| bInitializing
)
3548 bInitializing
= TRUE
;
3550 RTL_LOGFILE_CONTEXT_AUTHOR( aTimeLog
, "svtools", "er93726", "SvNumberFormatter::ImpInitCurrencyTable" );
3552 LanguageType eSysLang
= Application::GetSettings().GetLanguage();
3553 LocaleDataWrapper
* pLocaleData
= new LocaleDataWrapper(
3554 ::comphelper::getProcessServiceFactory(),
3555 MsLangId::convertLanguageToLocale( eSysLang
) );
3556 // get user configured currency
3557 String aConfiguredCurrencyAbbrev
;
3558 LanguageType eConfiguredCurrencyLanguage
= LANGUAGE_SYSTEM
;
3559 SvtSysLocaleOptions().GetCurrencyAbbrevAndLanguage(
3560 aConfiguredCurrencyAbbrev
, eConfiguredCurrencyLanguage
);
3561 USHORT nSecondarySystemCurrencyPosition
= 0;
3562 USHORT nMatchingSystemCurrencyPosition
= 0;
3563 NfCurrencyEntryPtr pEntry
;
3565 // first entry is SYSTEM
3566 pEntry
= new NfCurrencyEntry( *pLocaleData
, LANGUAGE_SYSTEM
);
3567 theCurrencyTable::get().Insert( pEntry
, 0 );
3568 USHORT nCurrencyPos
= 1;
3570 ::com::sun::star::uno::Sequence
< ::com::sun::star::lang::Locale
> xLoc
=
3571 LocaleDataWrapper::getInstalledLocaleNames();
3572 sal_Int32 nLocaleCount
= xLoc
.getLength();
3573 RTL_LOGFILE_CONTEXT_TRACE1( aTimeLog
, "number of locales: %ld", nLocaleCount
);
3574 Locale
const * const pLocales
= xLoc
.getConstArray();
3575 NfCurrencyTable
&rCurrencyTable
= theCurrencyTable::get();
3576 NfCurrencyTable
&rLegacyOnlyCurrencyTable
= theLegacyOnlyCurrencyTable::get();
3577 USHORT nLegacyOnlyCurrencyPos
= 0;
3578 for ( sal_Int32 nLocale
= 0; nLocale
< nLocaleCount
; nLocale
++ )
3580 LanguageType eLang
= MsLangId::convertLocaleToLanguage(
3582 #if OSL_DEBUG_LEVEL > 1
3583 LanguageType eReal
= MsLangId::getRealLanguage( eLang
);
3584 if ( eReal
!= eLang
) {
3589 pLocaleData
->setLocale( pLocales
[nLocale
] );
3590 Sequence
< Currency2
> aCurrSeq
= pLocaleData
->getAllCurrencies();
3591 sal_Int32 nCurrencyCount
= aCurrSeq
.getLength();
3592 Currency2
const * const pCurrencies
= aCurrSeq
.getConstArray();
3594 // one default currency for each locale, insert first so it is found first
3596 for ( nDefault
= 0; nDefault
< nCurrencyCount
; nDefault
++ )
3598 if ( pCurrencies
[nDefault
].Default
)
3601 if ( nDefault
< nCurrencyCount
)
3602 pEntry
= new NfCurrencyEntry( pCurrencies
[nDefault
], *pLocaleData
, eLang
);
3604 pEntry
= new NfCurrencyEntry( *pLocaleData
, eLang
); // first or ShellsAndPebbles
3606 if (LocaleDataWrapper::areChecksEnabled())
3607 lcl_CheckCurrencySymbolPosition( *pEntry
);
3609 rCurrencyTable
.Insert( pEntry
, nCurrencyPos
++ );
3610 if ( !nSystemCurrencyPosition
&& (aConfiguredCurrencyAbbrev
.Len() ?
3611 pEntry
->GetBankSymbol() == aConfiguredCurrencyAbbrev
&&
3612 pEntry
->GetLanguage() == eConfiguredCurrencyLanguage
: FALSE
) )
3613 nSystemCurrencyPosition
= nCurrencyPos
-1;
3614 if ( !nMatchingSystemCurrencyPosition
&&
3615 pEntry
->GetLanguage() == eSysLang
)
3616 nMatchingSystemCurrencyPosition
= nCurrencyPos
-1;
3618 // all remaining currencies for each locale
3619 if ( nCurrencyCount
> 1 )
3621 sal_Int32 nCurrency
;
3622 for ( nCurrency
= 0; nCurrency
< nCurrencyCount
; nCurrency
++ )
3624 if (pCurrencies
[nCurrency
].LegacyOnly
)
3626 pEntry
= new NfCurrencyEntry( pCurrencies
[nCurrency
], *pLocaleData
, eLang
);
3627 rLegacyOnlyCurrencyTable
.Insert( pEntry
, nLegacyOnlyCurrencyPos
++ );
3629 else if ( nCurrency
!= nDefault
)
3631 pEntry
= new NfCurrencyEntry( pCurrencies
[nCurrency
], *pLocaleData
, eLang
);
3633 BOOL bInsert
= TRUE
;
3634 NfCurrencyEntry
const * const * pData
= rCurrencyTable
.GetData();
3635 USHORT n
= rCurrencyTable
.Count();
3636 pData
++; // skip first SYSTEM entry
3637 for ( USHORT j
=1; j
<n
; j
++ )
3639 if ( *(*pData
++) == *pEntry
)
3649 rCurrencyTable
.Insert( pEntry
, nCurrencyPos
++ );
3650 if ( !nSecondarySystemCurrencyPosition
&&
3651 (aConfiguredCurrencyAbbrev
.Len() ?
3652 pEntry
->GetBankSymbol() == aConfiguredCurrencyAbbrev
:
3653 pEntry
->GetLanguage() == eConfiguredCurrencyLanguage
) )
3654 nSecondarySystemCurrencyPosition
= nCurrencyPos
-1;
3655 if ( !nMatchingSystemCurrencyPosition
&&
3656 pEntry
->GetLanguage() == eSysLang
)
3657 nMatchingSystemCurrencyPosition
= nCurrencyPos
-1;
3663 if ( !nSystemCurrencyPosition
)
3664 nSystemCurrencyPosition
= nSecondarySystemCurrencyPosition
;
3665 if ((aConfiguredCurrencyAbbrev
.Len() && !nSystemCurrencyPosition
) &&
3666 LocaleDataWrapper::areChecksEnabled())
3667 LocaleDataWrapper::outputCheckMessage(
3668 "SvNumberFormatter::ImpInitCurrencyTable: configured currency not in I18N locale data.");
3669 // match SYSTEM if no configured currency found
3670 if ( !nSystemCurrencyPosition
)
3671 nSystemCurrencyPosition
= nMatchingSystemCurrencyPosition
;
3672 if ((!aConfiguredCurrencyAbbrev
.Len() && !nSystemCurrencyPosition
) &&
3673 LocaleDataWrapper::areChecksEnabled())
3674 LocaleDataWrapper::outputCheckMessage(
3675 "SvNumberFormatter::ImpInitCurrencyTable: system currency not in I18N locale data.");
3677 SvtSysLocaleOptions::SetCurrencyChangeLink(
3678 STATIC_LINK( NULL
, SvNumberFormatter
, CurrencyChangeLink
) );
3679 bInitializing
= FALSE
;
3680 bCurrencyTableInitialized
= TRUE
;
3684 USHORT
SvNumberFormatter::GetCurrencyFormatStrings( NfWSStringsDtor
& rStrArr
,
3685 const NfCurrencyEntry
& rCurr
, BOOL bBank
) const
3687 USHORT nDefault
= 0;
3689 { // nur Bankensymbole
3690 String aPositiveBank
, aNegativeBank
;
3691 rCurr
.BuildPositiveFormatString( aPositiveBank
, TRUE
, *xLocaleData
, 1 );
3692 rCurr
.BuildNegativeFormatString( aNegativeBank
, TRUE
, *xLocaleData
, 1 );
3694 WSStringPtr pFormat1
= new String( aPositiveBank
);
3696 WSStringPtr pFormat2
= new String( *pFormat1
);
3699 aRed
+= pFormatScanner
->GetRedString();
3704 *pFormat1
+= aNegativeBank
;
3705 *pFormat2
+= aNegativeBank
;
3707 rStrArr
.Insert( pFormat1
, rStrArr
.Count() );
3708 rStrArr
.Insert( pFormat2
, rStrArr
.Count() );
3709 nDefault
= rStrArr
.Count() - 1;
3712 { // gemischte Formate wie in SvNumberFormatter::ImpGenerateFormats
3713 // aber keine doppelten, wenn keine Nachkommastellen in Waehrung
3714 String aPositive
, aNegative
, aPositiveNoDec
, aNegativeNoDec
,
3715 aPositiveDashed
, aNegativeDashed
;
3716 WSStringPtr pFormat1
, pFormat2
, pFormat3
, pFormat4
, pFormat5
;
3719 aRed
+= pFormatScanner
->GetRedString();
3722 rCurr
.BuildPositiveFormatString( aPositive
, FALSE
, *xLocaleData
, 1 );
3723 rCurr
.BuildNegativeFormatString( aNegative
, FALSE
, *xLocaleData
, 1 );
3724 if ( rCurr
.GetDigits() )
3726 rCurr
.BuildPositiveFormatString( aPositiveNoDec
, FALSE
, *xLocaleData
, 0 );
3727 rCurr
.BuildNegativeFormatString( aNegativeNoDec
, FALSE
, *xLocaleData
, 0 );
3728 rCurr
.BuildPositiveFormatString( aPositiveDashed
, FALSE
, *xLocaleData
, 2 );
3729 rCurr
.BuildNegativeFormatString( aNegativeDashed
, FALSE
, *xLocaleData
, 2 );
3731 pFormat1
= new String( aPositiveNoDec
);
3733 pFormat3
= new String( *pFormat1
);
3734 pFormat5
= new String( aPositiveDashed
);
3737 *pFormat1
+= aNegativeNoDec
;
3742 *pFormat3
+= aNegativeNoDec
;
3743 *pFormat5
+= aNegativeDashed
;
3752 pFormat2
= new String( aPositive
);
3754 pFormat4
= new String( *pFormat2
);
3756 *pFormat2
+= aNegative
;
3759 *pFormat4
+= aNegative
;
3762 rStrArr
.Insert( pFormat1
, rStrArr
.Count() );
3763 rStrArr
.Insert( pFormat2
, rStrArr
.Count() );
3765 rStrArr
.Insert( pFormat3
, rStrArr
.Count() );
3766 rStrArr
.Insert( pFormat4
, rStrArr
.Count() );
3767 nDefault
= rStrArr
.Count() - 1;
3769 rStrArr
.Insert( pFormat5
, rStrArr
.Count() );
3775 //--- NfCurrencyEntry ----------------------------------------------------
3777 NfCurrencyEntry::NfCurrencyEntry()
3778 : eLanguage( LANGUAGE_DONTKNOW
),
3787 NfCurrencyEntry::NfCurrencyEntry( const LocaleDataWrapper
& rLocaleData
, LanguageType eLang
)
3789 aSymbol
= rLocaleData
.getCurrSymbol();
3790 aBankSymbol
= rLocaleData
.getCurrBankSymbol();
3792 nPositiveFormat
= rLocaleData
.getCurrPositiveFormat();
3793 nNegativeFormat
= rLocaleData
.getCurrNegativeFormat();
3794 nDigits
= rLocaleData
.getCurrDigits();
3795 cZeroChar
= rLocaleData
.getCurrZeroChar();
3799 NfCurrencyEntry::NfCurrencyEntry( const ::com::sun::star::i18n::Currency
& rCurr
,
3800 const LocaleDataWrapper
& rLocaleData
, LanguageType eLang
)
3802 aSymbol
= rCurr
.Symbol
;
3803 aBankSymbol
= rCurr
.BankSymbol
;
3805 nPositiveFormat
= rLocaleData
.getCurrPositiveFormat();
3806 nNegativeFormat
= rLocaleData
.getCurrNegativeFormat();
3807 nDigits
= rCurr
.DecimalPlaces
;
3808 cZeroChar
= rLocaleData
.getCurrZeroChar();
3812 BOOL
NfCurrencyEntry::operator==( const NfCurrencyEntry
& r
) const
3814 return aSymbol
== r
.aSymbol
3815 && aBankSymbol
== r
.aBankSymbol
3816 && eLanguage
== r
.eLanguage
3821 void NfCurrencyEntry::SetEuro()
3823 aSymbol
= NfCurrencyEntry::GetEuroSymbol();
3824 aBankSymbol
.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "EUR" ) );
3825 eLanguage
= LANGUAGE_DONTKNOW
;
3826 nPositiveFormat
= 3;
3827 nNegativeFormat
= 8;
3833 BOOL
NfCurrencyEntry::IsEuro() const
3835 if ( aBankSymbol
.EqualsAscii( "EUR" ) )
3837 String
aEuro( NfCurrencyEntry::GetEuroSymbol() );
3838 return aSymbol
== aEuro
;
3842 void NfCurrencyEntry::ApplyVariableInformation( const NfCurrencyEntry
& r
)
3844 nPositiveFormat
= r
.nPositiveFormat
;
3845 nNegativeFormat
= r
.nNegativeFormat
;
3846 cZeroChar
= r
.cZeroChar
;
3850 void NfCurrencyEntry::BuildSymbolString( String
& rStr
, BOOL bBank
,
3851 BOOL bWithoutExtension
) const
3856 rStr
+= aBankSymbol
;
3859 if ( aSymbol
.Search( '-' ) != STRING_NOTFOUND
|| aSymbol
.Search( ']' ) != STRING_NOTFOUND
)
3867 if ( !bWithoutExtension
&& eLanguage
!= LANGUAGE_DONTKNOW
&& eLanguage
!= LANGUAGE_SYSTEM
)
3870 rStr
+= String::CreateFromInt32( sal_Int32( eLanguage
), 16 ).ToUpperAscii();
3877 void NfCurrencyEntry::Impl_BuildFormatStringNumChars( String
& rStr
,
3878 const LocaleDataWrapper
& rLoc
, USHORT nDecimalFormat
) const
3880 rStr
.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "###0" ) );
3881 rStr
.Insert( rLoc
.getNumThousandSep(), 1 );
3882 if ( nDecimalFormat
&& nDigits
)
3884 rStr
+= rLoc
.getNumDecimalSep();
3885 rStr
.Expand( rStr
.Len() + nDigits
, (nDecimalFormat
== 2 ? '-' : cZeroChar
) );
3890 void NfCurrencyEntry::BuildPositiveFormatString( String
& rStr
, BOOL bBank
,
3891 const LocaleDataWrapper
& rLoc
, USHORT nDecimalFormat
) const
3893 Impl_BuildFormatStringNumChars( rStr
, rLoc
, nDecimalFormat
);
3894 USHORT nPosiForm
= NfCurrencyEntry::GetEffectivePositiveFormat(
3895 rLoc
.getCurrPositiveFormat(), nPositiveFormat
, bBank
);
3896 CompletePositiveFormatString( rStr
, bBank
, nPosiForm
);
3900 void NfCurrencyEntry::BuildNegativeFormatString( String
& rStr
, BOOL bBank
,
3901 const LocaleDataWrapper
& rLoc
, USHORT nDecimalFormat
) const
3903 Impl_BuildFormatStringNumChars( rStr
, rLoc
, nDecimalFormat
);
3904 USHORT nNegaForm
= NfCurrencyEntry::GetEffectiveNegativeFormat(
3905 rLoc
.getCurrNegativeFormat(), nNegativeFormat
, bBank
);
3906 CompleteNegativeFormatString( rStr
, bBank
, nNegaForm
);
3910 void NfCurrencyEntry::CompletePositiveFormatString( String
& rStr
, BOOL bBank
,
3911 USHORT nPosiForm
) const
3914 BuildSymbolString( aSymStr
, bBank
);
3915 NfCurrencyEntry::CompletePositiveFormatString( rStr
, aSymStr
, nPosiForm
);
3919 void NfCurrencyEntry::CompleteNegativeFormatString( String
& rStr
, BOOL bBank
,
3920 USHORT nNegaForm
) const
3923 BuildSymbolString( aSymStr
, bBank
);
3924 NfCurrencyEntry::CompleteNegativeFormatString( rStr
, aSymStr
, nNegaForm
);
3929 void NfCurrencyEntry::CompletePositiveFormatString( String
& rStr
,
3930 const String
& rSymStr
, USHORT nPositiveFormat
)
3932 switch( nPositiveFormat
)
3935 rStr
.Insert( rSymStr
, 0 );
3942 rStr
.Insert( ' ', 0 );
3943 rStr
.Insert( rSymStr
, 0 );
3953 DBG_ERROR("NfCurrencyEntry::CompletePositiveFormatString: unknown option");
3960 void NfCurrencyEntry::CompleteNegativeFormatString( String
& rStr
,
3961 const String
& rSymStr
, USHORT nNegativeFormat
)
3963 switch( nNegativeFormat
)
3967 rStr
.Insert( rSymStr
, 0);
3974 rStr
.Insert( rSymStr
, 0);
3981 rStr
.Insert( rSymStr
, 0);
3986 rStr
.Insert( rSymStr
, 0);
4025 rStr
.Insert( rSymStr
, 0);
4038 String
aTmp( rSymStr
);
4041 rStr
.Insert( aTmp
, 0 );
4046 rStr
.Insert(' ', 0);
4047 rStr
.Insert( rSymStr
, 0);
4061 rStr
.Insert( rSymStr
, 0);
4075 DBG_ERROR("NfCurrencyEntry::CompleteNegativeFormatString: unknown option");
4082 USHORT
NfCurrencyEntry::GetEffectivePositiveFormat( USHORT
4083 #if ! NF_BANKSYMBOL_FIX_POSITION
4086 , USHORT nCurrFormat
, BOOL bBank
)
4090 #if NF_BANKSYMBOL_FIX_POSITION
4093 switch ( nIntlFormat
)
4096 nIntlFormat
= 2; // $ 1
4099 nIntlFormat
= 3; // 1 $
4106 DBG_ERROR("NfCurrencyEntry::GetEffectivePositiveFormat: unknown option");
4117 // nur aufrufen, wenn nCurrFormat wirklich mit Klammern ist
4118 USHORT
lcl_MergeNegativeParenthesisFormat( USHORT nIntlFormat
, USHORT nCurrFormat
)
4120 short nSign
= 0; // -1:=Klammer 0:=links, 1:=mitte, 2:=rechts
4121 switch ( nIntlFormat
)
4147 DBG_ERROR("lcl_MergeNegativeParenthesisFormat: unknown option");
4151 switch ( nCurrFormat
)
4203 USHORT
NfCurrencyEntry::GetEffectiveNegativeFormat( USHORT nIntlFormat
,
4204 USHORT nCurrFormat
, BOOL bBank
)
4208 #if NF_BANKSYMBOL_FIX_POSITION
4211 switch ( nIntlFormat
)
4214 // nIntlFormat = 14; // ($ 1)
4215 nIntlFormat
= 9; // -$ 1
4218 nIntlFormat
= 9; // -$ 1
4221 nIntlFormat
= 11; // $ -1
4224 nIntlFormat
= 12; // $ 1-
4227 // nIntlFormat = 15; // (1 $)
4228 nIntlFormat
= 8; // -1 $
4231 nIntlFormat
= 8; // -1 $
4234 nIntlFormat
= 13; // 1- $
4237 nIntlFormat
= 10; // 1 $-
4252 // nIntlFormat = 14; // ($ 1)
4253 nIntlFormat
= 9; // -$ 1
4256 // nIntlFormat = 15; // (1 $)
4257 nIntlFormat
= 8; // -1 $
4260 DBG_ERROR("NfCurrencyEntry::GetEffectiveNegativeFormat: unknown option");
4265 else if ( nIntlFormat
!= nCurrFormat
)
4267 switch ( nCurrFormat
)
4270 nIntlFormat
= lcl_MergeNegativeParenthesisFormat(
4271 nIntlFormat
, nCurrFormat
);
4274 nIntlFormat
= nCurrFormat
;
4277 nIntlFormat
= nCurrFormat
;
4280 nIntlFormat
= nCurrFormat
;
4283 nIntlFormat
= lcl_MergeNegativeParenthesisFormat(
4284 nIntlFormat
, nCurrFormat
);
4287 nIntlFormat
= nCurrFormat
;
4290 nIntlFormat
= nCurrFormat
;
4293 nIntlFormat
= nCurrFormat
;
4296 nIntlFormat
= nCurrFormat
;
4299 nIntlFormat
= nCurrFormat
;
4302 nIntlFormat
= nCurrFormat
;
4305 nIntlFormat
= nCurrFormat
;
4308 nIntlFormat
= nCurrFormat
;
4311 nIntlFormat
= nCurrFormat
;
4314 nIntlFormat
= lcl_MergeNegativeParenthesisFormat(
4315 nIntlFormat
, nCurrFormat
);
4318 nIntlFormat
= lcl_MergeNegativeParenthesisFormat(
4319 nIntlFormat
, nCurrFormat
);
4322 DBG_ERROR("NfCurrencyEntry::GetEffectiveNegativeFormat: unknown option");
4330 // we only support default encodings here
4332 sal_Char
NfCurrencyEntry::GetEuroSymbol( rtl_TextEncoding eTextEncoding
)
4334 switch ( eTextEncoding
)
4336 case RTL_TEXTENCODING_MS_1252
: // WNT Ansi
4337 case RTL_TEXTENCODING_ISO_8859_1
: // UNX for use with TrueType fonts
4339 case RTL_TEXTENCODING_ISO_8859_15
: // UNX real
4341 case RTL_TEXTENCODING_IBM_850
: // OS2
4343 case RTL_TEXTENCODING_APPLE_ROMAN
: // MAC
4345 default: // default system
4351 // return '\xA4'; // #56121# 0xA4 waere korrekt fuer iso-8859-15
4352 return '\x80'; // aber Windoze-Code fuer die konvertierten TrueType-Fonts
4354 #error EuroSymbol is what?