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
,
1492 GetInputLineString(fOutNumber
, nFIndex
, sOutString
, &pColor
);
1495 void SvNumberFormatter::GetInputLineString(const double& fOutNumber
,
1497 String
& sOutString
, Color
** ppColor
)
1499 SvNumberformat
* pFormat
;
1501 pFormat
= (SvNumberformat
*) aFTable
.Get(nFIndex
);
1503 pFormat
= aFTable
.Get(ZF_STANDARD
);
1504 LanguageType eLang
= pFormat
->GetLanguage();
1505 ChangeIntl( eLang
);
1506 short eType
= pFormat
->GetType() & ~NUMBERFORMAT_DEFINED
;
1508 eType
= NUMBERFORMAT_DEFINED
;
1510 if (eType
== NUMBERFORMAT_NUMBER
|| eType
== NUMBERFORMAT_PERCENT
1511 || eType
== NUMBERFORMAT_CURRENCY
1512 || eType
== NUMBERFORMAT_SCIENTIFIC
1513 || eType
== NUMBERFORMAT_FRACTION
)
1515 if (eType
!= NUMBERFORMAT_PERCENT
) // spaeter Sonderbehandlung %
1516 eType
= NUMBERFORMAT_NUMBER
;
1517 nOldPrec
= pFormatScanner
->GetStandardPrec();
1518 ChangeStandardPrec(300); // Merkwert
1520 sal_uInt32 nKey
= nFIndex
;
1522 { // #61619# immer vierstelliges Jahr editieren
1523 case NUMBERFORMAT_DATE
:
1524 nKey
= GetFormatIndex( NF_DATE_SYS_DDMMYYYY
, eLang
);
1526 case NUMBERFORMAT_DATETIME
:
1527 nKey
= GetFormatIndex( NF_DATETIME_SYS_DDMMYYYY_HHMMSS
, eLang
);
1530 nKey
= GetStandardFormat( fOutNumber
, nFIndex
, eType
, eLang
);
1532 if ( nKey
!= nFIndex
)
1533 pFormat
= (SvNumberformat
*) aFTable
.Get( nKey
);
1536 if ( eType
== NUMBERFORMAT_TIME
&& pFormat
->GetFormatPrecision() )
1538 nOldPrec
= pFormatScanner
->GetStandardPrec();
1539 ChangeStandardPrec(300); // Merkwert
1542 pFormat
->GetOutputString(fOutNumber
, sOutString
, ppColor
);
1545 Color
* pColor
; // throw away the color info.
1546 pFormat
->GetOutputString(fOutNumber
, sOutString
, &pColor
);
1550 ChangeStandardPrec(nOldPrec
);
1553 void SvNumberFormatter::GetOutputString(const double& fOutNumber
,
1558 if (bNoZero
&& fOutNumber
== 0.0)
1563 SvNumberformat
* pFormat
= (SvNumberformat
*) aFTable
.Get(nFIndex
);
1565 pFormat
= aFTable
.Get(ZF_STANDARD
);
1566 ChangeIntl(pFormat
->GetLanguage());
1567 pFormat
->GetOutputString(fOutNumber
, sOutString
, ppColor
);
1570 void SvNumberFormatter::GetOutputString(String
& sString
,
1575 SvNumberformat
* pFormat
= (SvNumberformat
*) aFTable
.Get(nFIndex
);
1577 pFormat
= aFTable
.Get(ZF_STANDARD_TEXT
);
1578 if (!pFormat
->IsTextFormat() && !pFormat
->HasTextFormat())
1581 sOutString
= sString
;
1585 ChangeIntl(pFormat
->GetLanguage());
1586 pFormat
->GetOutputString(sString
, sOutString
, ppColor
);
1590 void SvNumberFormatter::GetStringColor( sal_uInt32 nFIndex
, Color
** ppColor
)
1595 SvNumberformat
* pFormat
= (SvNumberformat
*) aFTable
.Get(nFIndex
);
1597 pFormat
= aFTable
.Get(ZF_STANDARD_TEXT
);
1599 if (pFormat
->IsTextFormat() || pFormat
->HasTextFormat())
1600 pFormat
->GetStringColor(ppColor
);
1605 BOOL
SvNumberFormatter::GetPreviewString(const String
& sFormatString
,
1606 double fPreviewNumber
,
1611 if (sFormatString
.Len() == 0) // keinen Leerstring
1614 xub_StrLen nCheckPos
= STRING_NOTFOUND
;
1616 if (eLnge
== LANGUAGE_DONTKNOW
)
1618 ChangeIntl(eLnge
); // ggfs. austauschen
1620 String sTmpString
= sFormatString
;
1621 SvNumberformat
* p_Entry
= new SvNumberformat(sTmpString
,
1626 if (nCheckPos
== 0) // String ok
1628 sal_uInt32 CLOffset
= ImpGenerateCL(eLnge
); // ggfs. neu Standard-
1630 nKey
= ImpIsEntry(p_Entry
->GetFormatstring(),CLOffset
, eLnge
);
1631 if (nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
) // schon vorhanden
1632 GetOutputString(fPreviewNumber
,nKey
,sOutString
,ppColor
);
1634 p_Entry
->GetOutputString(fPreviewNumber
,sOutString
, ppColor
);
1645 BOOL
SvNumberFormatter::GetPreviewStringGuess( const String
& sFormatString
,
1646 double fPreviewNumber
,
1649 LanguageType eLnge
)
1651 if (sFormatString
.Len() == 0) // keinen Leerstring
1654 if (eLnge
== LANGUAGE_DONTKNOW
)
1657 ChangeIntl( eLnge
);
1659 BOOL bEnglish
= (eLnge
== LANGUAGE_ENGLISH_US
);
1661 String
aFormatStringUpper( pCharClass
->upper( sFormatString
) );
1662 sal_uInt32 nCLOffset
= ImpGenerateCL( eLnge
);
1663 sal_uInt32 nKey
= ImpIsEntry( aFormatStringUpper
, nCLOffset
, eLnge
);
1664 if ( nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
1665 { // Zielformat vorhanden
1666 GetOutputString( fPreviewNumber
, nKey
, sOutString
, ppColor
);
1670 SvNumberformat
*pEntry
= NULL
;
1671 xub_StrLen nCheckPos
= STRING_NOTFOUND
;
1676 sTmpString
= sFormatString
;
1677 pEntry
= new SvNumberformat( sTmpString
, pFormatScanner
,
1678 pStringScanner
, nCheckPos
, eLnge
);
1682 nCLOffset
= ImpGenerateCL( LANGUAGE_ENGLISH_US
);
1683 nKey
= ImpIsEntry( aFormatStringUpper
, nCLOffset
, LANGUAGE_ENGLISH_US
);
1684 BOOL bEnglishFormat
= (nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
);
1686 // try english --> other bzw. english nach other konvertieren
1687 LanguageType eFormatLang
= LANGUAGE_ENGLISH_US
;
1688 pFormatScanner
->SetConvertMode( LANGUAGE_ENGLISH_US
, eLnge
);
1689 sTmpString
= sFormatString
;
1690 pEntry
= new SvNumberformat( sTmpString
, pFormatScanner
,
1691 pStringScanner
, nCheckPos
, eFormatLang
);
1692 pFormatScanner
->SetConvertMode( FALSE
);
1693 ChangeIntl( eLnge
);
1695 if ( !bEnglishFormat
)
1697 if ( nCheckPos
> 0 || xTransliteration
->isEqual( sFormatString
,
1698 pEntry
->GetFormatstring() ) )
1701 sTmpString
= sFormatString
;
1702 pEntry
= new SvNumberformat( sTmpString
, pFormatScanner
,
1703 pStringScanner
, nCheckPos
, eLnge
);
1707 xub_StrLen nCheckPos2
= STRING_NOTFOUND
;
1708 // try other --> english
1709 eFormatLang
= eLnge
;
1710 pFormatScanner
->SetConvertMode( eLnge
, LANGUAGE_ENGLISH_US
);
1711 sTmpString
= sFormatString
;
1712 SvNumberformat
* pEntry2
= new SvNumberformat( sTmpString
, pFormatScanner
,
1713 pStringScanner
, nCheckPos2
, eFormatLang
);
1714 pFormatScanner
->SetConvertMode( FALSE
);
1715 ChangeIntl( eLnge
);
1716 if ( nCheckPos2
== 0 && !xTransliteration
->isEqual( sFormatString
,
1717 pEntry2
->GetFormatstring() ) )
1720 sTmpString
= sFormatString
;
1721 pEntry
= new SvNumberformat( sTmpString
, pFormatScanner
,
1722 pStringScanner
, nCheckPos
, eLnge
);
1729 if (nCheckPos
== 0) // String ok
1731 ImpGenerateCL( eLnge
); // ggfs. neu Standardformate anlegen
1732 pEntry
->GetOutputString( fPreviewNumber
, sOutString
, ppColor
);
1740 sal_uInt32
SvNumberFormatter::TestNewString(const String
& sFormatString
,
1743 if (sFormatString
.Len() == 0) // keinen Leerstring
1744 return NUMBERFORMAT_ENTRY_NOT_FOUND
;
1746 xub_StrLen nCheckPos
= STRING_NOTFOUND
;
1747 if (eLnge
== LANGUAGE_DONTKNOW
)
1749 ChangeIntl(eLnge
); // ggfs. austauschen
1752 String sTmpString
= sFormatString
;
1753 SvNumberformat
* pEntry
= new SvNumberformat(sTmpString
,
1758 if (nCheckPos
== 0) // String ok
1760 sal_uInt32 CLOffset
= ImpGenerateCL(eLnge
); // ggfs. neu Standard-
1762 nRes
= ImpIsEntry(pEntry
->GetFormatstring(),CLOffset
, eLnge
);
1763 // schon vorhanden ?
1766 nRes
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
1771 SvNumberformat
* SvNumberFormatter::ImpInsertFormat(
1772 const ::com::sun::star::i18n::NumberFormatCode
& rCode
,
1773 sal_uInt32 nPos
, BOOL bAfterLoadingSO5
, sal_Int16 nOrgIndex
)
1775 String
aCodeStr( rCode
.Code
);
1776 if ( rCode
.Index
< NF_INDEX_TABLE_ENTRIES
&&
1777 rCode
.Usage
== ::com::sun::star::i18n::KNumberFormatUsage::CURRENCY
&&
1778 rCode
.Index
!= NF_CURRENCY_1000DEC2_CCC
)
1779 { // strip surrounding [$...] on automatic currency
1780 if ( aCodeStr
.SearchAscii( "[$" ) != STRING_NOTFOUND
)
1781 aCodeStr
= SvNumberformat::StripNewCurrencyDelimiters( aCodeStr
, FALSE
);
1784 if (LocaleDataWrapper::areChecksEnabled() &&
1785 rCode
.Index
!= NF_CURRENCY_1000DEC2_CCC
)
1787 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
1788 "SvNumberFormatter::ImpInsertFormat: no [$...] on currency format code, index "));
1789 aMsg
+= String::CreateFromInt32( rCode
.Index
);
1790 aMsg
.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ":\n"));
1791 aMsg
+= String( rCode
.Code
);
1792 LocaleDataWrapper::outputCheckMessage(
1793 xLocaleData
->appendLocaleInfo( aMsg
));
1797 xub_StrLen nCheckPos
= 0;
1798 SvNumberformat
* pFormat
= new SvNumberformat(aCodeStr
,
1803 if ( !pFormat
|| nCheckPos
> 0 )
1805 if (LocaleDataWrapper::areChecksEnabled())
1807 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
1808 "SvNumberFormatter::ImpInsertFormat: bad format code, index "));
1809 aMsg
+= String::CreateFromInt32( rCode
.Index
);
1811 aMsg
+= String( rCode
.Code
);
1812 LocaleDataWrapper::outputCheckMessage(
1813 xLocaleData
->appendLocaleInfo( aMsg
));
1818 if ( rCode
.Index
>= NF_INDEX_TABLE_ENTRIES
)
1820 sal_uInt32 nCLOffset
= nPos
- (nPos
% SV_COUNTRY_LANGUAGE_OFFSET
);
1821 sal_uInt32 nKey
= ImpIsEntry( aCodeStr
, nCLOffset
, ActLnge
);
1822 if ( nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
1824 if (LocaleDataWrapper::areChecksEnabled())
1826 switch ( nOrgIndex
)
1828 // These may be dupes of integer versions for locales where
1829 // currencies have no decimals like Italian Lira.
1830 case NF_CURRENCY_1000DEC2
: // NF_CURRENCY_1000INT
1831 case NF_CURRENCY_1000DEC2_RED
: // NF_CURRENCY_1000INT_RED
1832 case NF_CURRENCY_1000DEC2_DASHED
: // NF_CURRENCY_1000INT_RED
1835 if ( !bAfterLoadingSO5
)
1836 { // If bAfterLoadingSO5 there will definitely be some dupes,
1837 // don't cry. But we need this test for verification of locale
1838 // data if not loading old SO5 documents.
1839 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
1840 "SvNumberFormatter::ImpInsertFormat: dup format code, index "));
1841 aMsg
+= String::CreateFromInt32( rCode
.Index
);
1843 aMsg
+= String( rCode
.Code
);
1844 LocaleDataWrapper::outputCheckMessage(
1845 xLocaleData
->appendLocaleInfo( aMsg
));
1852 else if ( nPos
- nCLOffset
>= SV_COUNTRY_LANGUAGE_OFFSET
)
1854 if (LocaleDataWrapper::areChecksEnabled())
1856 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
1857 "SvNumberFormatter::ImpInsertFormat: too many format codes, index "));
1858 aMsg
+= String::CreateFromInt32( rCode
.Index
);
1860 aMsg
+= String( rCode
.Code
);
1861 LocaleDataWrapper::outputCheckMessage(
1862 xLocaleData
->appendLocaleInfo( aMsg
));
1868 if ( !aFTable
.Insert( nPos
, pFormat
) )
1870 if (LocaleDataWrapper::areChecksEnabled())
1872 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
1873 "ImpInsertFormat: can't insert number format key pos: "));
1874 aMsg
+= String::CreateFromInt32( nPos
);
1875 aMsg
.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ", code index "));
1876 aMsg
+= String::CreateFromInt32( rCode
.Index
);
1878 aMsg
+= String( rCode
.Code
);
1879 LocaleDataWrapper::outputCheckMessage(
1880 xLocaleData
->appendLocaleInfo( aMsg
));
1885 if ( rCode
.Default
)
1886 pFormat
->SetStandard();
1887 if ( rCode
.DefaultName
.getLength() )
1888 pFormat
->SetComment( rCode
.DefaultName
);
1892 SvNumberformat
* SvNumberFormatter::ImpInsertNewStandardFormat(
1893 const ::com::sun::star::i18n::NumberFormatCode
& rCode
,
1894 sal_uInt32 nPos
, USHORT nVersion
, BOOL bAfterLoadingSO5
,
1895 sal_Int16 nOrgIndex
)
1897 SvNumberformat
* pNewFormat
= ImpInsertFormat( rCode
, nPos
,
1898 bAfterLoadingSO5
, nOrgIndex
);
1900 pNewFormat
->SetNewStandardDefined( nVersion
);
1901 // so that it gets saved, displayed properly, and converted by old versions
1905 void SvNumberFormatter::GetFormatSpecialInfo(sal_uInt32 nFormat
,
1909 USHORT
& nAnzLeading
)
1912 const SvNumberformat
* pFormat
= aFTable
.Get(nFormat
);
1914 pFormat
->GetFormatSpecialInfo(bThousand
, IsRed
,
1915 nPrecision
, nAnzLeading
);
1920 nPrecision
= pFormatScanner
->GetStandardPrec();
1925 USHORT
SvNumberFormatter::GetFormatPrecision( sal_uInt32 nFormat
) const
1927 const SvNumberformat
* pFormat
= aFTable
.Get( nFormat
);
1929 return pFormat
->GetFormatPrecision();
1931 return pFormatScanner
->GetStandardPrec();
1935 String
SvNumberFormatter::GetFormatDecimalSep( sal_uInt32 nFormat
) const
1937 const SvNumberformat
* pFormat
= aFTable
.Get( nFormat
);
1938 if ( !pFormat
|| pFormat
->GetLanguage() == ActLnge
)
1939 return GetNumDecimalSep();
1942 LanguageType eSaveLang
= xLocaleData
.getCurrentLanguage();
1943 if ( pFormat
->GetLanguage() == eSaveLang
)
1944 aRet
= xLocaleData
->getNumDecimalSep();
1947 ::com::sun::star::lang::Locale
aSaveLocale( xLocaleData
->getLocale() );
1948 ::com::sun::star::lang::Locale
aTmpLocale(MsLangId::convertLanguageToLocale(pFormat
->GetLanguage()));
1949 ((SvNumberFormatter
*)this)->xLocaleData
.changeLocale(aTmpLocale
, pFormat
->GetLanguage() );
1950 aRet
= xLocaleData
->getNumDecimalSep();
1951 ((SvNumberFormatter
*)this)->xLocaleData
.changeLocale( aSaveLocale
, eSaveLang
);
1957 sal_uInt32
SvNumberFormatter::GetFormatSpecialInfo( const String
& rFormatString
,
1958 BOOL
& bThousand
, BOOL
& IsRed
, USHORT
& nPrecision
,
1959 USHORT
& nAnzLeading
, LanguageType eLnge
)
1962 xub_StrLen nCheckPos
= 0;
1963 if (eLnge
== LANGUAGE_DONTKNOW
)
1965 ChangeIntl(eLnge
); // ggfs. austauschen
1967 String
aTmpStr( rFormatString
);
1968 SvNumberformat
* pFormat
= new SvNumberformat( aTmpStr
,
1969 pFormatScanner
, pStringScanner
, nCheckPos
, eLnge
);
1970 if ( nCheckPos
== 0 )
1971 pFormat
->GetFormatSpecialInfo( bThousand
, IsRed
, nPrecision
, nAnzLeading
);
1976 nPrecision
= pFormatScanner
->GetStandardPrec();
1984 inline sal_uInt32
SetIndexTable( NfIndexTableOffset nTabOff
, sal_uInt32 nIndOff
)
1986 if ( !bIndexTableInitialized
)
1988 DBG_ASSERT( theIndexTable
[nTabOff
] == NUMBERFORMAT_ENTRY_NOT_FOUND
,
1989 "SetIndexTable: theIndexTable[nTabOff] already occupied" );
1990 theIndexTable
[nTabOff
] = nIndOff
;
1996 sal_Int32
SvNumberFormatter::ImpGetFormatCodeIndex(
1997 ::com::sun::star::uno::Sequence
< ::com::sun::star::i18n::NumberFormatCode
>& rSeq
,
1998 const NfIndexTableOffset nTabOff
)
2000 const sal_Int32 nLen
= rSeq
.getLength();
2001 for ( sal_Int32 j
=0; j
<nLen
; j
++ )
2003 if ( rSeq
[j
].Index
== nTabOff
)
2006 if (LocaleDataWrapper::areChecksEnabled() && (nTabOff
< NF_CURRENCY_START
2007 || NF_CURRENCY_END
< nTabOff
|| nTabOff
== NF_CURRENCY_1000INT
2008 || nTabOff
== NF_CURRENCY_1000INT_RED
2009 || nTabOff
== NF_CURRENCY_1000DEC2_CCC
))
2010 { // currency entries with decimals might not exist, e.g. Italian Lira
2011 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
2012 "SvNumberFormatter::ImpGetFormatCodeIndex: not found: "));
2013 aMsg
+= String::CreateFromInt32( nTabOff
);
2014 LocaleDataWrapper::outputCheckMessage( xLocaleData
->appendLocaleInfo(
2020 // look for a preset default
2021 for ( j
=0; j
<nLen
; j
++ )
2023 if ( rSeq
[j
].Default
)
2026 // currencies are special, not all format codes must exist, but all
2027 // builtin number format key index positions must have a format assigned
2028 if ( NF_CURRENCY_START
<= nTabOff
&& nTabOff
<= NF_CURRENCY_END
)
2030 // look for a format with decimals
2031 for ( j
=0; j
<nLen
; j
++ )
2033 if ( rSeq
[j
].Index
== NF_CURRENCY_1000DEC2
)
2036 // last resort: look for a format without decimals
2037 for ( j
=0; j
<nLen
; j
++ )
2039 if ( rSeq
[j
].Index
== NF_CURRENCY_1000INT
)
2045 { // we need at least _some_ format
2047 rSeq
[0] = ::com::sun::star::i18n::NumberFormatCode();
2049 aTmp
+= GetNumDecimalSep();
2050 aTmp
.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "############" ) );
2051 rSeq
[0].Code
= aTmp
;
2057 sal_Int32
SvNumberFormatter::ImpAdjustFormatCodeDefault(
2058 ::com::sun::star::i18n::NumberFormatCode
* pFormatArr
,
2059 sal_Int32 nCnt
, BOOL bCheckCorrectness
)
2061 using namespace ::com::sun::star
;
2065 if (bCheckCorrectness
&& LocaleDataWrapper::areChecksEnabled())
2066 { // check the locale data for correctness
2068 sal_Int32 nElem
, nShort
, nMedium
, nLong
, nShortDef
, nMediumDef
, nLongDef
;
2069 nShort
= nMedium
= nLong
= nShortDef
= nMediumDef
= nLongDef
= -1;
2070 for ( nElem
= 0; nElem
< nCnt
; nElem
++ )
2072 switch ( pFormatArr
[nElem
].Type
)
2074 case i18n::KNumberFormatType::SHORT
:
2077 case i18n::KNumberFormatType::MEDIUM
:
2080 case i18n::KNumberFormatType::LONG
:
2084 aMsg
= "unknown type";
2086 if ( pFormatArr
[nElem
].Default
)
2088 switch ( pFormatArr
[nElem
].Type
)
2090 case i18n::KNumberFormatType::SHORT
:
2091 if ( nShortDef
!= -1 )
2092 aMsg
= "dupe short type default";
2095 case i18n::KNumberFormatType::MEDIUM
:
2096 if ( nMediumDef
!= -1 )
2097 aMsg
= "dupe medium type default";
2100 case i18n::KNumberFormatType::LONG
:
2101 if ( nLongDef
!= -1 )
2102 aMsg
= "dupe long type default";
2109 aMsg
.Insert( "SvNumberFormatter::ImpAdjustFormatCodeDefault: ", 0 );
2110 aMsg
+= "\nXML locale data FormatElement formatindex: ";
2111 aMsg
+= ByteString::CreateFromInt32( pFormatArr
[nElem
].Index
);
2112 String
aUMsg( aMsg
, RTL_TEXTENCODING_ASCII_US
);
2113 LocaleDataWrapper::outputCheckMessage(
2114 xLocaleData
->appendLocaleInfo( aUMsg
));
2118 if ( nShort
!= -1 && nShortDef
== -1 )
2119 aMsg
+= "no short type default ";
2120 if ( nMedium
!= -1 && nMediumDef
== -1 )
2121 aMsg
+= "no medium type default ";
2122 if ( nLong
!= -1 && nLongDef
== -1 )
2123 aMsg
+= "no long type default ";
2126 aMsg
.Insert( "SvNumberFormatter::ImpAdjustFormatCodeDefault: ", 0 );
2127 aMsg
+= "\nXML locale data FormatElement group of: ";
2128 String
aUMsg( aMsg
, RTL_TEXTENCODING_ASCII_US
);
2129 aUMsg
+= String( pFormatArr
[0].NameID
);
2130 LocaleDataWrapper::outputCheckMessage(
2131 xLocaleData
->appendLocaleInfo( aUMsg
));
2135 // find the default (medium preferred, then long) and reset all other defaults
2136 sal_Int32 nElem
, nDef
, nMedium
;
2137 nDef
= nMedium
= -1;
2138 for ( nElem
= 0; nElem
< nCnt
; nElem
++ )
2140 if ( pFormatArr
[nElem
].Default
)
2142 switch ( pFormatArr
[nElem
].Type
)
2144 case i18n::KNumberFormatType::MEDIUM
:
2145 nDef
= nMedium
= nElem
;
2147 case i18n::KNumberFormatType::LONG
:
2148 if ( nMedium
== -1 )
2154 pFormatArr
[nElem
].Default
= sal_False
;
2160 pFormatArr
[nDef
].Default
= sal_True
;
2165 void SvNumberFormatter::ImpGenerateFormats( sal_uInt32 CLOffset
, BOOL bLoadingSO5
)
2167 using namespace ::com::sun::star
;
2169 if ( !bIndexTableInitialized
)
2171 for ( USHORT j
=0; j
<NF_INDEX_TABLE_ENTRIES
; j
++ )
2173 theIndexTable
[j
] = NUMBERFORMAT_ENTRY_NOT_FOUND
;
2176 BOOL bOldConvertMode
= pFormatScanner
->GetConvertMode();
2177 if (bOldConvertMode
)
2178 pFormatScanner
->SetConvertMode(FALSE
); // switch off for this function
2180 NumberFormatCodeWrapper
aNumberFormatCode( xServiceManager
, GetLocale() );
2182 xub_StrLen nCheckPos
= 0;
2183 SvNumberformat
* pNewFormat
= NULL
;
2188 // Counter for additional builtin formats not fitting into the first 10
2189 // of a category (TLOT:=The Legacy Of Templin), altogether about 20 formats.
2190 // Has to be incremented on each ImpInsertNewStandardformat, new formats
2191 // must be appended, not inserted!
2192 USHORT nNewExtended
= ZF_STANDARD_NEWEXTENDED
;
2195 uno::Sequence
< i18n::NumberFormatCode
> aFormatSeq
2196 = aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::FIXED_NUMBER
);
2197 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2200 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_STANDARD
);
2201 SvNumberformat
* pStdFormat
= ImpInsertFormat( aFormatSeq
[nIdx
],
2202 CLOffset
+ SetIndexTable( NF_NUMBER_STANDARD
, ZF_STANDARD
));
2205 // This is _the_ standard format.
2206 if (LocaleDataWrapper::areChecksEnabled() &&
2207 pStdFormat
->GetType() != NUMBERFORMAT_NUMBER
)
2209 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
2210 "SvNumberFormatter::ImpGenerateFormats: General format not NUMBER"));
2211 LocaleDataWrapper::outputCheckMessage(
2212 xLocaleData
->appendLocaleInfo( aMsg
));
2214 pStdFormat
->SetType( NUMBERFORMAT_NUMBER
);
2215 pStdFormat
->SetStandard();
2216 pStdFormat
->SetLastInsertKey( SV_MAX_ANZ_STANDARD_FORMATE
);
2220 if (LocaleDataWrapper::areChecksEnabled())
2222 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
2223 "SvNumberFormatter::ImpGenerateFormats: General format not insertable, nothing will work"));
2224 LocaleDataWrapper::outputCheckMessage(
2225 xLocaleData
->appendLocaleInfo( aMsg
));
2230 aFormatCode
= pFormatScanner
->GetBooleanString();
2231 pNewFormat
= new SvNumberformat( aFormatCode
,
2232 pFormatScanner
, pStringScanner
, nCheckPos
, ActLnge
);
2233 pNewFormat
->SetType(NUMBERFORMAT_LOGICAL
);
2234 pNewFormat
->SetStandard();
2235 if ( !aFTable
.Insert(
2236 CLOffset
+ SetIndexTable( NF_BOOLEAN
, ZF_STANDARD_LOGICAL
),
2242 pNewFormat
= new SvNumberformat( aFormatCode
,
2243 pFormatScanner
, pStringScanner
, nCheckPos
, ActLnge
);
2244 pNewFormat
->SetType(NUMBERFORMAT_TEXT
);
2245 pNewFormat
->SetStandard();
2246 if ( !aFTable
.Insert(
2247 CLOffset
+ SetIndexTable( NF_TEXT
, ZF_STANDARD_TEXT
),
2254 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_INT
);
2255 ImpInsertFormat( aFormatSeq
[nIdx
],
2256 CLOffset
+ SetIndexTable( NF_NUMBER_INT
, ZF_STANDARD
+1 ));
2259 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_DEC2
);
2260 ImpInsertFormat( aFormatSeq
[nIdx
],
2261 CLOffset
+ SetIndexTable( NF_NUMBER_DEC2
, ZF_STANDARD
+2 ));
2264 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_1000INT
);
2265 ImpInsertFormat( aFormatSeq
[nIdx
],
2266 CLOffset
+ SetIndexTable( NF_NUMBER_1000INT
, ZF_STANDARD
+3 ));
2269 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_1000DEC2
);
2270 ImpInsertFormat( aFormatSeq
[nIdx
],
2271 CLOffset
+ SetIndexTable( NF_NUMBER_1000DEC2
, ZF_STANDARD
+4 ));
2273 // #.##0,00 System country/language dependent since number formatter version 6
2274 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_SYSTEM
);
2275 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2276 CLOffset
+ SetIndexTable( NF_NUMBER_SYSTEM
, ZF_STANDARD
+5 ),
2277 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2281 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::PERCENT_NUMBER
);
2282 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2285 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_PERCENT_INT
);
2286 ImpInsertFormat( aFormatSeq
[nIdx
],
2287 CLOffset
+ SetIndexTable( NF_PERCENT_INT
, ZF_STANDARD_PERCENT
));
2290 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_PERCENT_DEC2
);
2291 ImpInsertFormat( aFormatSeq
[nIdx
],
2292 CLOffset
+ SetIndexTable( NF_PERCENT_DEC2
, ZF_STANDARD_PERCENT
+1 ));
2296 // Currency. NO default standard option! Default is determined of locale
2297 // data default currency and format is generated if needed.
2298 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::CURRENCY
);
2299 if (LocaleDataWrapper::areChecksEnabled())
2301 // though no default desired here, test for correctness of locale data
2302 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2306 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000INT
);
2307 bDefault
= aFormatSeq
[nIdx
].Default
;
2308 aFormatSeq
[nIdx
].Default
= sal_False
;
2309 ImpInsertFormat( aFormatSeq
[nIdx
],
2310 CLOffset
+ SetIndexTable( NF_CURRENCY_1000INT
, ZF_STANDARD_CURRENCY
));
2311 aFormatSeq
[nIdx
].Default
= bDefault
;
2314 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000DEC2
);
2315 bDefault
= aFormatSeq
[nIdx
].Default
;
2316 aFormatSeq
[nIdx
].Default
= sal_False
;
2317 ImpInsertFormat( aFormatSeq
[nIdx
],
2318 CLOffset
+ SetIndexTable( NF_CURRENCY_1000DEC2
, ZF_STANDARD_CURRENCY
+1 ));
2319 aFormatSeq
[nIdx
].Default
= bDefault
;
2321 // #,##0 negative red
2322 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000INT_RED
);
2323 bDefault
= aFormatSeq
[nIdx
].Default
;
2324 aFormatSeq
[nIdx
].Default
= sal_False
;
2325 ImpInsertFormat( aFormatSeq
[nIdx
],
2326 CLOffset
+ SetIndexTable( NF_CURRENCY_1000INT_RED
, ZF_STANDARD_CURRENCY
+2 ));
2327 aFormatSeq
[nIdx
].Default
= bDefault
;
2329 // #,##0.00 negative red
2330 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000DEC2_RED
);
2331 bDefault
= aFormatSeq
[nIdx
].Default
;
2332 aFormatSeq
[nIdx
].Default
= sal_False
;
2333 ImpInsertFormat( aFormatSeq
[nIdx
],
2334 CLOffset
+ SetIndexTable( NF_CURRENCY_1000DEC2_RED
, ZF_STANDARD_CURRENCY
+3 ));
2335 aFormatSeq
[nIdx
].Default
= bDefault
;
2337 // #,##0.00 USD since number formatter version 3
2338 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000DEC2_CCC
);
2339 bDefault
= aFormatSeq
[nIdx
].Default
;
2340 aFormatSeq
[nIdx
].Default
= sal_False
;
2341 pNewFormat
= ImpInsertFormat( aFormatSeq
[nIdx
],
2342 CLOffset
+ SetIndexTable( NF_CURRENCY_1000DEC2_CCC
, ZF_STANDARD_CURRENCY
+4 ));
2344 pNewFormat
->SetUsed(TRUE
); // must be saved for older versions
2345 aFormatSeq
[nIdx
].Default
= bDefault
;
2347 // #.##0,-- since number formatter version 6
2348 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000DEC2_DASHED
);
2349 bDefault
= aFormatSeq
[nIdx
].Default
;
2350 aFormatSeq
[nIdx
].Default
= sal_False
;
2351 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2352 CLOffset
+ SetIndexTable( NF_CURRENCY_1000DEC2_DASHED
, ZF_STANDARD_CURRENCY
+5 ),
2353 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2354 aFormatSeq
[nIdx
].Default
= bDefault
;
2359 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::DATE
);
2360 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2363 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYSTEM_SHORT
);
2364 ImpInsertFormat( aFormatSeq
[nIdx
],
2365 CLOffset
+ SetIndexTable( NF_DATE_SYSTEM_SHORT
, ZF_STANDARD_DATE
));
2368 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DEF_NNDDMMMYY
);
2369 ImpInsertFormat( aFormatSeq
[nIdx
],
2370 CLOffset
+ SetIndexTable( NF_DATE_DEF_NNDDMMMYY
, ZF_STANDARD_DATE
+1 ));
2372 // DD.MM.YY def/System
2373 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_MMYY
);
2374 ImpInsertFormat( aFormatSeq
[nIdx
],
2375 CLOffset
+ SetIndexTable( NF_DATE_SYS_MMYY
, ZF_STANDARD_DATE
+2 ));
2378 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DDMMM
);
2379 ImpInsertFormat( aFormatSeq
[nIdx
],
2380 CLOffset
+ SetIndexTable( NF_DATE_SYS_DDMMM
, ZF_STANDARD_DATE
+3 ));
2383 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_MMMM
);
2384 ImpInsertFormat( aFormatSeq
[nIdx
],
2385 CLOffset
+ SetIndexTable( NF_DATE_MMMM
, ZF_STANDARD_DATE
+4 ));
2388 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_QQJJ
);
2389 ImpInsertFormat( aFormatSeq
[nIdx
],
2390 CLOffset
+ SetIndexTable( NF_DATE_QQJJ
, ZF_STANDARD_DATE
+5 ));
2392 // DD.MM.YYYY since number formatter version 2, was DD.MM.[YY]YY
2393 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DDMMYYYY
);
2394 pNewFormat
= ImpInsertFormat( aFormatSeq
[nIdx
],
2395 CLOffset
+ SetIndexTable( NF_DATE_SYS_DDMMYYYY
, ZF_STANDARD_DATE
+6 ));
2397 pNewFormat
->SetUsed(TRUE
); // must be saved for older versions
2399 // DD.MM.YY def/System, since number formatter version 6
2400 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DDMMYY
);
2401 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2402 CLOffset
+ SetIndexTable( NF_DATE_SYS_DDMMYY
, ZF_STANDARD_DATE
+7 ),
2403 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2405 // NNN, D. MMMM YYYY System
2406 // Long day of week: "NNNN" instead of "NNN," because of compatibility
2407 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYSTEM_LONG
);
2408 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2409 CLOffset
+ SetIndexTable( NF_DATE_SYSTEM_LONG
, ZF_STANDARD_DATE
+8 ),
2410 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2412 // Hard coded but system (regional settings) delimiters dependent long date formats
2413 // since numberformatter version 6
2415 // D. MMM YY def/System
2416 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DMMMYY
);
2417 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2418 CLOffset
+ SetIndexTable( NF_DATE_SYS_DMMMYY
, ZF_STANDARD_DATE
+9 ),
2419 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2421 //! Unfortunally TLOT intended only 10 builtin formats per category, more
2422 //! would overwrite the next category (ZF_STANDARD_TIME) :-((
2423 //! Therefore they are inserted with nNewExtended++ (which is also limited)
2425 // D. MMM YYYY def/System
2426 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DMMMYYYY
);
2427 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2428 CLOffset
+ SetIndexTable( NF_DATE_SYS_DMMMYYYY
, nNewExtended
++ ),
2429 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2431 // D. MMMM YYYY def/System
2432 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DMMMMYYYY
);
2433 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2434 CLOffset
+ SetIndexTable( NF_DATE_SYS_DMMMMYYYY
, nNewExtended
++ ),
2435 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2437 // NN, D. MMM YY def/System
2438 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_NNDMMMYY
);
2439 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2440 CLOffset
+ SetIndexTable( NF_DATE_SYS_NNDMMMYY
, nNewExtended
++ ),
2441 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2443 // NN, D. MMMM YYYY def/System
2444 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_NNDMMMMYYYY
);
2445 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2446 CLOffset
+ SetIndexTable( NF_DATE_SYS_NNDMMMMYYYY
, nNewExtended
++ ),
2447 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2449 // NNN, D. MMMM YYYY def/System
2450 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_NNNNDMMMMYYYY
);
2451 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2452 CLOffset
+ SetIndexTable( NF_DATE_SYS_NNNNDMMMMYYYY
, nNewExtended
++ ),
2453 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2455 // Hard coded DIN (Deutsche Industrie Norm) and EN (European Norm) date formats
2457 // D. MMM. YYYY DIN/EN
2458 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DIN_DMMMYYYY
);
2459 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2460 CLOffset
+ SetIndexTable( NF_DATE_DIN_DMMMYYYY
, nNewExtended
++ ),
2461 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2463 // D. MMMM YYYY DIN/EN
2464 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DIN_DMMMMYYYY
);
2465 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2466 CLOffset
+ SetIndexTable( NF_DATE_DIN_DMMMMYYYY
, nNewExtended
++ ),
2467 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2470 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DIN_MMDD
);
2471 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2472 CLOffset
+ SetIndexTable( NF_DATE_DIN_MMDD
, nNewExtended
++ ),
2473 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2476 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DIN_YYMMDD
);
2477 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2478 CLOffset
+ SetIndexTable( NF_DATE_DIN_YYMMDD
, nNewExtended
++ ),
2479 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2481 // YYYY-MM-DD DIN/EN
2482 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DIN_YYYYMMDD
);
2483 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2484 CLOffset
+ SetIndexTable( NF_DATE_DIN_YYYYMMDD
, nNewExtended
++ ),
2485 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2490 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::TIME
);
2491 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2494 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HHMM
);
2495 ImpInsertFormat( aFormatSeq
[nIdx
],
2496 CLOffset
+ SetIndexTable( NF_TIME_HHMM
, ZF_STANDARD_TIME
));
2499 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HHMMSS
);
2500 ImpInsertFormat( aFormatSeq
[nIdx
],
2501 CLOffset
+ SetIndexTable( NF_TIME_HHMMSS
, ZF_STANDARD_TIME
+1 ));
2504 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HHMMAMPM
);
2505 ImpInsertFormat( aFormatSeq
[nIdx
],
2506 CLOffset
+ SetIndexTable( NF_TIME_HHMMAMPM
, ZF_STANDARD_TIME
+2 ));
2509 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HHMMSSAMPM
);
2510 ImpInsertFormat( aFormatSeq
[nIdx
],
2511 CLOffset
+ SetIndexTable( NF_TIME_HHMMSSAMPM
, ZF_STANDARD_TIME
+3 ));
2514 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HH_MMSS
);
2515 ImpInsertFormat( aFormatSeq
[nIdx
],
2516 CLOffset
+ SetIndexTable( NF_TIME_HH_MMSS
, ZF_STANDARD_TIME
+4 ));
2519 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_MMSS00
);
2520 ImpInsertFormat( aFormatSeq
[nIdx
],
2521 CLOffset
+ SetIndexTable( NF_TIME_MMSS00
, ZF_STANDARD_TIME
+5 ));
2524 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HH_MMSS00
);
2525 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2526 CLOffset
+ SetIndexTable( NF_TIME_HH_MMSS00
, ZF_STANDARD_TIME
+6 ),
2527 SV_NUMBERFORMATTER_VERSION_NF_TIME_HH_MMSS00
);
2532 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::DATE_TIME
);
2533 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2535 // DD.MM.YY HH:MM System
2536 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATETIME_SYSTEM_SHORT_HHMM
);
2537 ImpInsertFormat( aFormatSeq
[nIdx
],
2538 CLOffset
+ SetIndexTable( NF_DATETIME_SYSTEM_SHORT_HHMM
, ZF_STANDARD_DATETIME
));
2540 // DD.MM.YYYY HH:MM:SS System
2541 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATETIME_SYS_DDMMYYYY_HHMMSS
);
2542 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2543 CLOffset
+ SetIndexTable( NF_DATETIME_SYS_DDMMYYYY_HHMMSS
, ZF_STANDARD_DATETIME
+1 ),
2544 SV_NUMBERFORMATTER_VERSION_NF_DATETIME_SYS_DDMMYYYY_HHMMSS
);
2548 // Scientific number
2549 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::SCIENTIFIC_NUMBER
);
2550 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2553 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_SCIENTIFIC_000E000
);
2554 ImpInsertFormat( aFormatSeq
[nIdx
],
2555 CLOffset
+ SetIndexTable( NF_SCIENTIFIC_000E000
, ZF_STANDARD_SCIENTIFIC
));
2558 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_SCIENTIFIC_000E00
);
2559 ImpInsertFormat( aFormatSeq
[nIdx
],
2560 CLOffset
+ SetIndexTable( NF_SCIENTIFIC_000E00
, ZF_STANDARD_SCIENTIFIC
+1 ));
2564 // Fraction number (no default option)
2565 i18n::NumberFormatCode aSingleFormatCode
;
2568 aSingleFormatCode
.Code
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "# ?/?" ) );
2569 String
s25( RTL_CONSTASCII_USTRINGPARAM( "# ?/?" ) ); // # ?/?
2570 ImpInsertFormat( aSingleFormatCode
,
2571 CLOffset
+ SetIndexTable( NF_FRACTION_1
, ZF_STANDARD_FRACTION
));
2574 //! "??/" would be interpreted by the compiler as a trigraph for '\'
2575 aSingleFormatCode
.Code
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "# ?\?/?\?" ) );
2576 ImpInsertFormat( aSingleFormatCode
,
2577 CLOffset
+ SetIndexTable( NF_FRACTION_2
, ZF_STANDARD_FRACTION
+1 ));
2579 // Week of year must be appended here because of nNewExtended
2580 const String
* pKeyword
= pFormatScanner
->GetKeywords();
2581 aSingleFormatCode
.Code
= pKeyword
[NF_KEY_WW
];
2582 ImpInsertNewStandardFormat( aSingleFormatCode
,
2583 CLOffset
+ SetIndexTable( NF_DATE_WW
, nNewExtended
++ ),
2584 SV_NUMBERFORMATTER_VERSION_NF_DATE_WW
);
2588 bIndexTableInitialized
= TRUE
;
2589 DBG_ASSERT( nNewExtended
<= ZF_STANDARD_NEWEXTENDEDMAX
,
2590 "ImpGenerateFormats: overflow of nNewExtended standard formats" );
2592 // Now all additional format codes provided by I18N, but only if not
2593 // loading from old SO5 file format, then they are appended last.
2595 ImpGenerateAdditionalFormats( CLOffset
, aNumberFormatCode
, FALSE
);
2597 if (bOldConvertMode
)
2598 pFormatScanner
->SetConvertMode(TRUE
);
2602 void SvNumberFormatter::ImpGenerateAdditionalFormats( sal_uInt32 CLOffset
,
2603 NumberFormatCodeWrapper
& rNumberFormatCode
, BOOL bAfterLoadingSO5
)
2605 using namespace ::com::sun::star
;
2607 SvNumberformat
* pStdFormat
=
2608 (SvNumberformat
*) aFTable
.Get( CLOffset
+ ZF_STANDARD
);
2611 DBG_ERRORFILE( "ImpGenerateAdditionalFormats: no GENERAL format" );
2614 sal_uInt32 nPos
= CLOffset
+ pStdFormat
->GetLastInsertKey();
2615 rNumberFormatCode
.setLocale( GetLocale() );
2618 // All currencies, this time with [$...] which was stripped in
2619 // ImpGenerateFormats for old "automatic" currency formats.
2620 uno::Sequence
< i18n::NumberFormatCode
> aFormatSeq
=
2621 rNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::CURRENCY
);
2622 i18n::NumberFormatCode
* pFormatArr
= aFormatSeq
.getArray();
2623 sal_Int32 nCodes
= aFormatSeq
.getLength();
2624 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), nCodes
);
2625 for ( j
= 0; j
< nCodes
; j
++ )
2627 if ( nPos
- CLOffset
>= SV_COUNTRY_LANGUAGE_OFFSET
)
2629 DBG_ERRORFILE( "ImpGenerateAdditionalFormats: too many formats" );
2632 if ( pFormatArr
[j
].Index
< NF_INDEX_TABLE_ENTRIES
&&
2633 pFormatArr
[j
].Index
!= NF_CURRENCY_1000DEC2_CCC
)
2634 { // Insert only if not already inserted, but internal index must be
2635 // above so ImpInsertFormat can distinguish it.
2636 sal_Int16 nOrgIndex
= pFormatArr
[j
].Index
;
2637 pFormatArr
[j
].Index
= sal::static_int_cast
< sal_Int16
>(
2638 pFormatArr
[j
].Index
+ nCodes
+ NF_INDEX_TABLE_ENTRIES
);
2639 //! no default on currency
2640 sal_Bool bDefault
= aFormatSeq
[j
].Default
;
2641 aFormatSeq
[j
].Default
= sal_False
;
2642 if ( ImpInsertNewStandardFormat( pFormatArr
[j
], nPos
+1,
2643 SV_NUMBERFORMATTER_VERSION_ADDITIONAL_I18N_FORMATS
,
2644 bAfterLoadingSO5
, nOrgIndex
) )
2646 pFormatArr
[j
].Index
= nOrgIndex
;
2647 aFormatSeq
[j
].Default
= bDefault
;
2651 // all additional format codes provided by I18N that are not old standard index
2652 aFormatSeq
= rNumberFormatCode
.getAllFormatCodes();
2653 nCodes
= aFormatSeq
.getLength();
2656 pFormatArr
= aFormatSeq
.getArray();
2658 sal_Int32 nDef
= ImpAdjustFormatCodeDefault( pFormatArr
, nCodes
, FALSE
);
2659 // don't have any defaults here
2660 pFormatArr
[nDef
].Default
= sal_False
;
2661 for ( j
= 0; j
< nCodes
; j
++ )
2663 if ( nPos
- CLOffset
>= SV_COUNTRY_LANGUAGE_OFFSET
)
2665 DBG_ERRORFILE( "ImpGenerateAdditionalFormats: too many formats" );
2668 if ( pFormatArr
[j
].Index
>= NF_INDEX_TABLE_ENTRIES
)
2669 if ( ImpInsertNewStandardFormat( pFormatArr
[j
], nPos
+1,
2670 SV_NUMBERFORMATTER_VERSION_ADDITIONAL_I18N_FORMATS
,
2671 bAfterLoadingSO5
) )
2676 pStdFormat
->SetLastInsertKey( (USHORT
)(nPos
- CLOffset
) );
2680 void SvNumberFormatter::ImpGetPosCurrFormat( String
& sPosStr
, const String
& rCurrSymbol
)
2682 NfCurrencyEntry::CompletePositiveFormatString( sPosStr
,
2683 rCurrSymbol
, xLocaleData
->getCurrPositiveFormat() );
2686 void SvNumberFormatter::ImpGetNegCurrFormat( String
& sNegStr
, const String
& rCurrSymbol
)
2688 NfCurrencyEntry::CompleteNegativeFormatString( sNegStr
,
2689 rCurrSymbol
, xLocaleData
->getCurrNegativeFormat() );
2692 void SvNumberFormatter::GenerateFormat(String
& sString
,
2700 if (eLnge
== LANGUAGE_DONTKNOW
)
2702 short eType
= GetType(nIndex
);
2704 ImpGenerateCL(eLnge
); // ggfs. neu Standard-
2708 utl::DigitGroupingIterator
aGrouping( xLocaleData
->getDigitGrouping());
2709 const xub_StrLen nDigitsInFirstGroup
= static_cast<xub_StrLen
>(aGrouping
.get());
2710 const String
& rThSep
= GetNumThousandSep();
2711 if (nAnzLeading
== 0)
2719 sString
.Expand( sString
.Len() + nDigitsInFirstGroup
, '#' );
2724 for (i
= 0; i
< nAnzLeading
; i
++)
2726 if (bThousand
&& i
> 0 && i
== aGrouping
.getPos())
2728 sString
.Insert( rThSep
, 0 );
2729 aGrouping
.advance();
2731 sString
.Insert('0',0);
2733 if (bThousand
&& nAnzLeading
< nDigitsInFirstGroup
+ 1)
2735 for (i
= nAnzLeading
; i
< nDigitsInFirstGroup
+ 1; i
++)
2737 if (bThousand
&& i
% nDigitsInFirstGroup
== 0)
2738 sString
.Insert( rThSep
, 0 );
2739 sString
.Insert('#',0);
2745 sString
+= GetNumDecimalSep();
2746 sString
.Expand( sString
.Len() + nPrecision
, '0' );
2748 if (eType
== NUMBERFORMAT_PERCENT
)
2750 else if (eType
== NUMBERFORMAT_CURRENCY
)
2752 String sNegStr
= sString
;
2754 const NfCurrencyEntry
* pEntry
;
2756 if ( GetNewCurrencySymbolString( nIndex
, aCurr
, &pEntry
, &bBank
) )
2760 USHORT nPosiForm
= NfCurrencyEntry::GetEffectivePositiveFormat(
2761 xLocaleData
->getCurrPositiveFormat(),
2762 pEntry
->GetPositiveFormat(), bBank
);
2763 USHORT nNegaForm
= NfCurrencyEntry::GetEffectiveNegativeFormat(
2764 xLocaleData
->getCurrNegativeFormat(),
2765 pEntry
->GetNegativeFormat(), bBank
);
2766 pEntry
->CompletePositiveFormatString( sString
, bBank
,
2768 pEntry
->CompleteNegativeFormatString( sNegStr
, bBank
,
2772 { // assume currency abbreviation (AKA banking symbol), not symbol
2773 USHORT nPosiForm
= NfCurrencyEntry::GetEffectivePositiveFormat(
2774 xLocaleData
->getCurrPositiveFormat(),
2775 xLocaleData
->getCurrPositiveFormat(), TRUE
);
2776 USHORT nNegaForm
= NfCurrencyEntry::GetEffectiveNegativeFormat(
2777 xLocaleData
->getCurrNegativeFormat(),
2778 xLocaleData
->getCurrNegativeFormat(), TRUE
);
2779 NfCurrencyEntry::CompletePositiveFormatString( sString
, aCurr
,
2781 NfCurrencyEntry::CompleteNegativeFormatString( sNegStr
, aCurr
,
2786 { // "automatic" old style
2787 String aSymbol
, aAbbrev
;
2788 GetCompatibilityCurrency( aSymbol
, aAbbrev
);
2789 ImpGetPosCurrFormat( sString
, aSymbol
);
2790 ImpGetNegCurrFormat( sNegStr
, aSymbol
);
2796 sString
+= pFormatScanner
->GetRedString();
2803 if (IsRed
&& eType
!= NUMBERFORMAT_CURRENCY
)
2805 String sTmpStr
= sString
;
2808 sTmpStr
+= pFormatScanner
->GetRedString();
2816 BOOL
SvNumberFormatter::IsUserDefined(const String
& sStr
,
2819 if (eLnge
== LANGUAGE_DONTKNOW
)
2821 sal_uInt32 CLOffset
= ImpGenerateCL(eLnge
); // ggfs. neu Standard-
2824 sal_uInt32 nKey
= ImpIsEntry(sStr
, CLOffset
, eLnge
);
2825 if (nKey
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
2827 SvNumberformat
* pEntry
= aFTable
.Get(nKey
);
2828 if ( pEntry
&& ((pEntry
->GetType() & NUMBERFORMAT_DEFINED
) != 0) )
2833 sal_uInt32
SvNumberFormatter::GetEntryKey(const String
& sStr
,
2836 if (eLnge
== LANGUAGE_DONTKNOW
)
2838 sal_uInt32 CLOffset
= ImpGenerateCL(eLnge
); // ggfs. neu Standard-
2840 return ImpIsEntry(sStr
, CLOffset
, eLnge
);
2843 sal_uInt32
SvNumberFormatter::GetStandardIndex(LanguageType eLnge
)
2845 if (eLnge
== LANGUAGE_DONTKNOW
)
2847 return GetStandardFormat(NUMBERFORMAT_NUMBER
, eLnge
);
2850 short SvNumberFormatter::GetType(sal_uInt32 nFIndex
)
2853 SvNumberformat
* pFormat
= (SvNumberformat
*) aFTable
.Get(nFIndex
);
2855 eType
= NUMBERFORMAT_UNDEFINED
;
2858 eType
= pFormat
->GetType() &~NUMBERFORMAT_DEFINED
;
2860 eType
= NUMBERFORMAT_DEFINED
;
2865 void SvNumberFormatter::ClearMergeTable()
2869 sal_uInt32
* pIndex
= (sal_uInt32
*) pMergeTable
->First();
2873 pIndex
= pMergeTable
->Next();
2875 pMergeTable
->Clear();
2879 SvNumberFormatterIndexTable
* SvNumberFormatter::MergeFormatter(SvNumberFormatter
& rTable
)
2884 pMergeTable
= new SvNumberFormatterIndexTable
;
2885 sal_uInt32 nCLOffset
= 0;
2886 sal_uInt32 nOldKey
, nOffset
, nNewKey
;
2887 sal_uInt32
* pNewIndex
;
2888 SvNumberformat
* pNewEntry
;
2889 SvNumberformat
* pFormat
= rTable
.aFTable
.First();
2892 nOldKey
= rTable
.aFTable
.GetCurKey();
2893 nOffset
= nOldKey
% SV_COUNTRY_LANGUAGE_OFFSET
; // relativIndex
2894 if (nOffset
== 0) // 1. Format von CL
2895 nCLOffset
= ImpGenerateCL(pFormat
->GetLanguage());
2897 if (nOffset
<= SV_MAX_ANZ_STANDARD_FORMATE
) // Std.form.
2899 nNewKey
= nCLOffset
+ nOffset
;
2900 if (!aFTable
.Get(nNewKey
)) // noch nicht da
2902 // pNewEntry = new SvNumberformat(*pFormat); // Copy reicht nicht !!!
2903 pNewEntry
= new SvNumberformat( *pFormat
, *pFormatScanner
);
2904 if (!aFTable
.Insert(nNewKey
, pNewEntry
))
2907 if (nNewKey
!= nOldKey
) // neuer Index
2909 pNewIndex
= new sal_uInt32(nNewKey
);
2910 if (!pMergeTable
->Insert(nOldKey
,pNewIndex
))
2914 else // benutzerdef.
2916 // pNewEntry = new SvNumberformat(*pFormat); // Copy reicht nicht !!!
2917 pNewEntry
= new SvNumberformat( *pFormat
, *pFormatScanner
);
2918 nNewKey
= ImpIsEntry(pNewEntry
->GetFormatstring(),
2920 pFormat
->GetLanguage());
2921 if (nNewKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
) // schon vorhanden
2925 SvNumberformat
* pStdFormat
=
2926 (SvNumberformat
*) aFTable
.Get(nCLOffset
+ ZF_STANDARD
);
2927 sal_uInt32 nPos
= nCLOffset
+ pStdFormat
->GetLastInsertKey();
2929 if (nPos
- nCLOffset
>= SV_COUNTRY_LANGUAGE_OFFSET
)
2933 "SvNumberFormatter:: Zu viele Formate pro CL");
2936 else if (!aFTable
.Insert(nNewKey
, pNewEntry
))
2939 pStdFormat
->SetLastInsertKey((USHORT
) (nNewKey
- nCLOffset
));
2941 if (nNewKey
!= nOldKey
) // neuer Index
2943 pNewIndex
= new sal_uInt32(nNewKey
);
2944 if (!pMergeTable
->Insert(nOldKey
,pNewIndex
))
2948 pFormat
= rTable
.aFTable
.Next();
2954 SvNumberFormatterMergeMap
SvNumberFormatter::ConvertMergeTableToMap()
2956 if (!HasMergeFmtTbl())
2957 return SvNumberFormatterMergeMap();
2959 SvNumberFormatterMergeMap aMap
;
2960 for (sal_uInt32
* pIndex
= pMergeTable
->First(); pIndex
; pIndex
= pMergeTable
->Next())
2962 sal_uInt32 nOldKey
= pMergeTable
->GetCurKey();
2963 aMap
.insert( SvNumberFormatterMergeMap::value_type( nOldKey
, *pIndex
));
2970 sal_uInt32
SvNumberFormatter::GetFormatForLanguageIfBuiltIn( sal_uInt32 nFormat
,
2971 LanguageType eLnge
)
2973 if ( eLnge
== LANGUAGE_DONTKNOW
)
2975 if ( nFormat
< SV_COUNTRY_LANGUAGE_OFFSET
&& eLnge
== IniLnge
)
2976 return nFormat
; // es bleibt wie es ist
2977 sal_uInt32 nOffset
= nFormat
% SV_COUNTRY_LANGUAGE_OFFSET
; // relativIndex
2978 if ( nOffset
> SV_MAX_ANZ_STANDARD_FORMATE
)
2979 return nFormat
; // kein eingebautes Format
2980 sal_uInt32 nCLOffset
= ImpGenerateCL(eLnge
); // ggbf. generieren
2981 return nCLOffset
+ nOffset
;
2985 sal_uInt32
SvNumberFormatter::GetFormatIndex( NfIndexTableOffset nTabOff
,
2986 LanguageType eLnge
)
2988 if ( nTabOff
>= NF_INDEX_TABLE_ENTRIES
2989 || theIndexTable
[nTabOff
] == NUMBERFORMAT_ENTRY_NOT_FOUND
)
2990 return NUMBERFORMAT_ENTRY_NOT_FOUND
;
2991 if ( eLnge
== LANGUAGE_DONTKNOW
)
2993 sal_uInt32 nCLOffset
= ImpGenerateCL(eLnge
); // ggbf. generieren
2994 return nCLOffset
+ theIndexTable
[nTabOff
];
2998 NfIndexTableOffset
SvNumberFormatter::GetIndexTableOffset( sal_uInt32 nFormat
) const
3000 sal_uInt32 nOffset
= nFormat
% SV_COUNTRY_LANGUAGE_OFFSET
; // relativIndex
3001 if ( nOffset
> SV_MAX_ANZ_STANDARD_FORMATE
)
3002 return NF_INDEX_TABLE_ENTRIES
; // kein eingebautes Format
3003 for ( USHORT j
= 0; j
< NF_INDEX_TABLE_ENTRIES
; j
++ )
3005 if ( theIndexTable
[j
] == nOffset
)
3006 return (NfIndexTableOffset
) j
;
3008 return NF_INDEX_TABLE_ENTRIES
; // bad luck
3012 void SvNumberFormatter::SetYear2000( USHORT nVal
)
3014 pStringScanner
->SetYear2000( nVal
);
3018 USHORT
SvNumberFormatter::GetYear2000() const
3020 return pStringScanner
->GetYear2000();
3024 USHORT
SvNumberFormatter::ExpandTwoDigitYear( USHORT nYear
) const
3027 return SvNumberFormatter::ExpandTwoDigitYear( nYear
,
3028 pStringScanner
->GetYear2000() );
3034 USHORT
SvNumberFormatter::GetYear2000Default()
3036 return Application::GetSettings().GetMiscSettings().GetTwoDigitYearStart();
3041 const NfCurrencyTable
& SvNumberFormatter::GetTheCurrencyTable()
3043 ::osl::MutexGuard
aGuard( GetMutex() );
3044 while ( !bCurrencyTableInitialized
)
3045 ImpInitCurrencyTable();
3046 return theCurrencyTable::get();
3051 const NfCurrencyEntry
* SvNumberFormatter::MatchSystemCurrency()
3053 // MUST call GetTheCurrencyTable() before accessing nSystemCurrencyPosition
3054 const NfCurrencyTable
& rTable
= GetTheCurrencyTable();
3055 return nSystemCurrencyPosition
? rTable
[nSystemCurrencyPosition
] : NULL
;
3060 const NfCurrencyEntry
& SvNumberFormatter::GetCurrencyEntry( LanguageType eLang
)
3062 if ( eLang
== LANGUAGE_SYSTEM
)
3064 const NfCurrencyEntry
* pCurr
= MatchSystemCurrency();
3065 return pCurr
? *pCurr
: *(GetTheCurrencyTable()[0]);
3069 eLang
= MsLangId::getRealLanguage( eLang
);
3070 const NfCurrencyTable
& rTable
= GetTheCurrencyTable();
3071 USHORT nCount
= rTable
.Count();
3072 const NfCurrencyEntryPtr
* ppData
= rTable
.GetData();
3073 for ( USHORT j
= 0; j
< nCount
; j
++, ppData
++ )
3075 if ( (*ppData
)->GetLanguage() == eLang
)
3078 return *(rTable
[0]);
3084 const NfCurrencyEntry
* SvNumberFormatter::GetCurrencyEntry(
3085 const String
& rAbbrev
, LanguageType eLang
)
3087 eLang
= MsLangId::getRealLanguage( eLang
);
3088 const NfCurrencyTable
& rTable
= GetTheCurrencyTable();
3089 USHORT nCount
= rTable
.Count();
3090 const NfCurrencyEntryPtr
* ppData
= rTable
.GetData();
3091 for ( USHORT j
= 0; j
< nCount
; j
++, ppData
++ )
3093 if ( (*ppData
)->GetLanguage() == eLang
&&
3094 (*ppData
)->GetBankSymbol() == rAbbrev
)
3102 const NfCurrencyEntry
* SvNumberFormatter::GetLegacyOnlyCurrencyEntry(
3103 const String
& rSymbol
, const String
& rAbbrev
)
3105 if (!bCurrencyTableInitialized
)
3106 GetTheCurrencyTable(); // just for initialization
3107 const NfCurrencyTable
& rTable
= theLegacyOnlyCurrencyTable::get();
3108 USHORT nCount
= rTable
.Count();
3109 const NfCurrencyEntryPtr
* ppData
= rTable
.GetData();
3110 for ( USHORT j
= 0; j
< nCount
; j
++, ppData
++ )
3112 if ( (*ppData
)->GetSymbol() == rSymbol
&&
3113 (*ppData
)->GetBankSymbol() == rAbbrev
)
3121 IMPL_STATIC_LINK_NOINSTANCE( SvNumberFormatter
, CurrencyChangeLink
, void*, EMPTYARG
)
3123 ::osl::MutexGuard
aGuard( GetMutex() );
3125 LanguageType eLang
= LANGUAGE_SYSTEM
;
3126 SvtSysLocaleOptions().GetCurrencyAbbrevAndLanguage( aAbbrev
, eLang
);
3127 SetDefaultSystemCurrency( aAbbrev
, eLang
);
3133 void SvNumberFormatter::SetDefaultSystemCurrency( const String
& rAbbrev
, LanguageType eLang
)
3135 ::osl::MutexGuard
aGuard( GetMutex() );
3136 if ( eLang
== LANGUAGE_SYSTEM
)
3137 eLang
= Application::GetSettings().GetLanguage();
3138 const NfCurrencyTable
& rTable
= GetTheCurrencyTable();
3139 USHORT nCount
= rTable
.Count();
3140 const NfCurrencyEntryPtr
* ppData
= rTable
.GetData();
3141 if ( rAbbrev
.Len() )
3143 for ( USHORT j
= 0; j
< nCount
; j
++, ppData
++ )
3145 if ( (*ppData
)->GetLanguage() == eLang
&& (*ppData
)->GetBankSymbol() == rAbbrev
)
3147 nSystemCurrencyPosition
= j
;
3154 for ( USHORT j
= 0; j
< nCount
; j
++, ppData
++ )
3156 if ( (*ppData
)->GetLanguage() == eLang
)
3158 nSystemCurrencyPosition
= j
;
3163 nSystemCurrencyPosition
= 0; // not found => simple SYSTEM
3167 void SvNumberFormatter::ResetDefaultSystemCurrency()
3169 nDefaultSystemCurrencyFormat
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
3173 sal_uInt32
SvNumberFormatter::ImpGetDefaultSystemCurrencyFormat()
3175 if ( nDefaultSystemCurrencyFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
3179 NfWSStringsDtor aCurrList
;
3180 USHORT nDefault
= GetCurrencyFormatStrings( aCurrList
,
3181 GetCurrencyEntry( LANGUAGE_SYSTEM
), FALSE
);
3182 DBG_ASSERT( aCurrList
.Count(), "where is the NewCurrency System standard format?!?" );
3183 // if already loaded or user defined nDefaultSystemCurrencyFormat
3184 // will be set to the right value
3185 PutEntry( *aCurrList
.GetObject( nDefault
), nCheck
, nType
,
3186 nDefaultSystemCurrencyFormat
, LANGUAGE_SYSTEM
);
3187 DBG_ASSERT( nCheck
== 0, "NewCurrency CheckError" );
3188 DBG_ASSERT( nDefaultSystemCurrencyFormat
!= NUMBERFORMAT_ENTRY_NOT_FOUND
,
3189 "nDefaultSystemCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND" );
3191 return nDefaultSystemCurrencyFormat
;
3195 sal_uInt32
SvNumberFormatter::ImpGetDefaultCurrencyFormat()
3197 sal_uInt32 CLOffset
= ImpGetCLOffset( ActLnge
);
3198 sal_uInt32 nDefaultCurrencyFormat
=
3199 (sal_uInt32
)(sal_uIntPtr
) aDefaultFormatKeys
.Get( CLOffset
+ ZF_STANDARD_CURRENCY
);
3200 if ( !nDefaultCurrencyFormat
)
3201 nDefaultCurrencyFormat
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
3202 if ( nDefaultCurrencyFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
3204 // look for a defined standard
3205 sal_uInt32 nStopKey
= CLOffset
+ SV_COUNTRY_LANGUAGE_OFFSET
;
3207 aFTable
.Seek( CLOffset
);
3208 while ( (nKey
= aFTable
.GetCurKey()) >= CLOffset
&& nKey
< nStopKey
)
3210 const SvNumberformat
* pEntry
=
3211 (const SvNumberformat
*) aFTable
.GetCurObject();
3212 if ( pEntry
->IsStandard() && (pEntry
->GetType() & NUMBERFORMAT_CURRENCY
) )
3214 nDefaultCurrencyFormat
= nKey
;
3220 if ( nDefaultCurrencyFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
3221 { // none found, create one
3224 NfWSStringsDtor aCurrList
;
3225 USHORT nDefault
= GetCurrencyFormatStrings( aCurrList
,
3226 GetCurrencyEntry( ActLnge
), FALSE
);
3227 DBG_ASSERT( aCurrList
.Count(), "where is the NewCurrency standard format?" );
3228 if ( aCurrList
.Count() )
3230 // if already loaded or user defined nDefaultSystemCurrencyFormat
3231 // will be set to the right value
3232 PutEntry( *aCurrList
.GetObject( nDefault
), nCheck
, nType
,
3233 nDefaultCurrencyFormat
, ActLnge
);
3234 DBG_ASSERT( nCheck
== 0, "NewCurrency CheckError" );
3235 DBG_ASSERT( nDefaultCurrencyFormat
!= NUMBERFORMAT_ENTRY_NOT_FOUND
,
3236 "nDefaultCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND" );
3238 // old automatic currency format as a last resort
3239 if ( nDefaultCurrencyFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
3240 nDefaultCurrencyFormat
= CLOffset
+ ZF_STANDARD_CURRENCY
+3;
3242 { // mark as standard so that it is found next time
3243 SvNumberformat
* pEntry
= aFTable
.Get( nDefaultCurrencyFormat
);
3245 pEntry
->SetStandard();
3248 aDefaultFormatKeys
.Insert( CLOffset
+ ZF_STANDARD_CURRENCY
,
3249 (void*) nDefaultCurrencyFormat
);
3251 return nDefaultCurrencyFormat
;
3256 // try to make it inline if possible since this a loop body
3257 // TRUE: continue; FALSE: break loop, if pFoundEntry==NULL dupe found
3261 BOOL
SvNumberFormatter::ImpLookupCurrencyEntryLoopBody(
3262 const NfCurrencyEntry
*& pFoundEntry
, BOOL
& bFoundBank
,
3263 const NfCurrencyEntry
* pData
, USHORT nPos
, const String
& rSymbol
)
3266 if ( pData
->GetSymbol() == rSymbol
)
3271 else if ( pData
->GetBankSymbol() == rSymbol
)
3280 if ( pFoundEntry
&& pFoundEntry
!= pData
)
3283 return FALSE
; // break loop, not unique
3286 { // first entry is SYSTEM
3287 pFoundEntry
= MatchSystemCurrency();
3289 return FALSE
; // break loop
3290 // even if there are more matching entries
3291 // this one is propably the one we are looking for
3293 pFoundEntry
= pData
;
3296 pFoundEntry
= pData
;
3302 BOOL
SvNumberFormatter::GetNewCurrencySymbolString( sal_uInt32 nFormat
,
3303 String
& rStr
, const NfCurrencyEntry
** ppEntry
/* = NULL */,
3304 BOOL
* pBank
/* = NULL */ ) const
3311 SvNumberformat
* pFormat
= (SvNumberformat
*) aFTable
.Get( nFormat
);
3314 String aSymbol
, aExtension
;
3315 if ( pFormat
->GetNewCurrencySymbol( aSymbol
, aExtension
) )
3319 BOOL bFoundBank
= FALSE
;
3320 // we definiteley need an entry matching the format code string
3321 const NfCurrencyEntry
* pFoundEntry
= GetCurrencyEntry(
3322 bFoundBank
, aSymbol
, aExtension
, pFormat
->GetLanguage(),
3326 *ppEntry
= pFoundEntry
;
3328 *pBank
= bFoundBank
;
3329 pFoundEntry
->BuildSymbolString( rStr
, bFoundBank
);
3333 { // analog zu BuildSymbolString
3336 if ( aSymbol
.Search( '-' ) != STRING_NOTFOUND
||
3337 aSymbol
.Search( ']' ) != STRING_NOTFOUND
)
3345 if ( aExtension
.Len() )
3357 const NfCurrencyEntry
* SvNumberFormatter::GetCurrencyEntry( BOOL
& bFoundBank
,
3358 const String
& rSymbol
, const String
& rExtension
,
3359 LanguageType eFormatLanguage
, BOOL bOnlyStringLanguage
)
3361 xub_StrLen nExtLen
= rExtension
.Len();
3362 LanguageType eExtLang
;
3365 sal_Int32 nExtLang
= ::rtl::OUString( rExtension
).toInt32( 16 );
3367 eExtLang
= LANGUAGE_DONTKNOW
;
3369 eExtLang
= (LanguageType
) ((nExtLang
< 0) ?
3370 -nExtLang
: nExtLang
);
3373 eExtLang
= LANGUAGE_DONTKNOW
;
3374 const NfCurrencyEntry
* pFoundEntry
= NULL
;
3375 const NfCurrencyTable
& rTable
= GetTheCurrencyTable();
3376 USHORT nCount
= rTable
.Count();
3379 // first try with given extension language/country
3382 const NfCurrencyEntryPtr
* ppData
= rTable
.GetData();
3383 for ( USHORT j
= 0; j
< nCount
&& bCont
; j
++, ppData
++ )
3385 LanguageType eLang
= (*ppData
)->GetLanguage();
3386 if ( eLang
== eExtLang
||
3387 ((eExtLang
== LANGUAGE_DONTKNOW
) &&
3388 (eLang
== LANGUAGE_SYSTEM
))
3391 bCont
= ImpLookupCurrencyEntryLoopBody( pFoundEntry
, bFoundBank
,
3392 *ppData
, j
, rSymbol
);
3398 if ( pFoundEntry
|| !bCont
|| (bOnlyStringLanguage
&& nExtLen
) )
3401 if ( !bOnlyStringLanguage
)
3403 // now try the language/country of the number format
3404 const NfCurrencyEntryPtr
* ppData
= rTable
.GetData();
3405 for ( USHORT j
= 0; j
< nCount
&& bCont
; j
++, ppData
++ )
3407 LanguageType eLang
= (*ppData
)->GetLanguage();
3408 if ( eLang
== eFormatLanguage
||
3409 ((eFormatLanguage
== LANGUAGE_DONTKNOW
) &&
3410 (eLang
== LANGUAGE_SYSTEM
))
3413 bCont
= ImpLookupCurrencyEntryLoopBody( pFoundEntry
, bFoundBank
,
3414 *ppData
, j
, rSymbol
);
3419 if ( pFoundEntry
|| !bCont
)
3423 // then try without language/country if no extension specified
3426 const NfCurrencyEntryPtr
* ppData
= rTable
.GetData();
3427 for ( USHORT j
= 0; j
< nCount
&& bCont
; j
++, ppData
++ )
3429 bCont
= ImpLookupCurrencyEntryLoopBody( pFoundEntry
, bFoundBank
,
3430 *ppData
, j
, rSymbol
);
3438 void SvNumberFormatter::GetCompatibilityCurrency( String
& rSymbol
, String
& rAbbrev
) const
3440 ::com::sun::star::uno::Sequence
< ::com::sun::star::i18n::Currency2
>
3441 xCurrencies
= xLocaleData
->getAllCurrencies();
3442 sal_Int32 nCurrencies
= xCurrencies
.getLength();
3444 for ( j
=0; j
< nCurrencies
; ++j
)
3446 if ( xCurrencies
[j
].UsedInCompatibleFormatCodes
)
3448 rSymbol
= xCurrencies
[j
].Symbol
;
3449 rAbbrev
= xCurrencies
[j
].BankSymbol
;
3453 if ( j
>= nCurrencies
)
3455 if (LocaleDataWrapper::areChecksEnabled())
3457 String
aMsg( RTL_CONSTASCII_USTRINGPARAM(
3458 "GetCompatibilityCurrency: none?"));
3459 LocaleDataWrapper::outputCheckMessage(
3460 xLocaleData
->appendLocaleInfo( aMsg
));
3462 rSymbol
= xLocaleData
->getCurrSymbol();
3463 rAbbrev
= xLocaleData
->getCurrBankSymbol();
3468 void lcl_CheckCurrencySymbolPosition( const NfCurrencyEntry
& rCurr
)
3470 short nPos
= -1; // -1:=unknown, 0:=vorne, 1:=hinten
3472 switch ( rCurr
.GetPositiveFormat() )
3487 LocaleDataWrapper::outputCheckMessage(
3488 "lcl_CheckCurrencySymbolPosition: unknown PositiveFormat");
3491 switch ( rCurr
.GetNegativeFormat() )
3542 LocaleDataWrapper::outputCheckMessage(
3543 "lcl_CheckCurrencySymbolPosition: unknown NegativeFormat");
3546 if ( nPos
>= 0 && nNeg
>= 0 && nPos
!= nNeg
)
3548 ByteString
aStr( "positions of currency symbols differ\nLanguage: " );
3549 aStr
+= ByteString::CreateFromInt32( rCurr
.GetLanguage() );
3551 aStr
+= ByteString( rCurr
.GetSymbol(), RTL_TEXTENCODING_UTF8
);
3552 aStr
+= "> positive: ";
3553 aStr
+= ByteString::CreateFromInt32( rCurr
.GetPositiveFormat() );
3554 aStr
+= ( nPos
? " (postfix)" : " (prefix)" );
3555 aStr
+= ", negative: ";
3556 aStr
+= ByteString::CreateFromInt32( rCurr
.GetNegativeFormat() );
3557 aStr
+= ( nNeg
? " (postfix)" : " (prefix)" );
3559 // seems that there really are some currencies which differ, e.g. YugoDinar
3560 DBG_ERRORFILE( aStr
.GetBuffer() );
3567 void SvNumberFormatter::ImpInitCurrencyTable()
3569 // racing condition possible:
3570 // ::osl::MutexGuard aGuard( GetMutex() );
3571 // while ( !bCurrencyTableInitialized )
3572 // ImpInitCurrencyTable();
3573 static BOOL bInitializing
= FALSE
;
3574 if ( bCurrencyTableInitialized
|| bInitializing
)
3576 bInitializing
= TRUE
;
3578 RTL_LOGFILE_CONTEXT_AUTHOR( aTimeLog
, "svtools", "er93726", "SvNumberFormatter::ImpInitCurrencyTable" );
3580 LanguageType eSysLang
= Application::GetSettings().GetLanguage();
3581 LocaleDataWrapper
* pLocaleData
= new LocaleDataWrapper(
3582 ::comphelper::getProcessServiceFactory(),
3583 MsLangId::convertLanguageToLocale( eSysLang
) );
3584 // get user configured currency
3585 String aConfiguredCurrencyAbbrev
;
3586 LanguageType eConfiguredCurrencyLanguage
= LANGUAGE_SYSTEM
;
3587 SvtSysLocaleOptions().GetCurrencyAbbrevAndLanguage(
3588 aConfiguredCurrencyAbbrev
, eConfiguredCurrencyLanguage
);
3589 USHORT nSecondarySystemCurrencyPosition
= 0;
3590 USHORT nMatchingSystemCurrencyPosition
= 0;
3591 NfCurrencyEntryPtr pEntry
;
3593 // first entry is SYSTEM
3594 pEntry
= new NfCurrencyEntry( *pLocaleData
, LANGUAGE_SYSTEM
);
3595 theCurrencyTable::get().Insert( pEntry
, 0 );
3596 USHORT nCurrencyPos
= 1;
3598 ::com::sun::star::uno::Sequence
< ::com::sun::star::lang::Locale
> xLoc
=
3599 LocaleDataWrapper::getInstalledLocaleNames();
3600 sal_Int32 nLocaleCount
= xLoc
.getLength();
3601 RTL_LOGFILE_CONTEXT_TRACE1( aTimeLog
, "number of locales: %ld", nLocaleCount
);
3602 Locale
const * const pLocales
= xLoc
.getConstArray();
3603 NfCurrencyTable
&rCurrencyTable
= theCurrencyTable::get();
3604 NfCurrencyTable
&rLegacyOnlyCurrencyTable
= theLegacyOnlyCurrencyTable::get();
3605 USHORT nLegacyOnlyCurrencyPos
= 0;
3606 for ( sal_Int32 nLocale
= 0; nLocale
< nLocaleCount
; nLocale
++ )
3608 LanguageType eLang
= MsLangId::convertLocaleToLanguage(
3610 #if OSL_DEBUG_LEVEL > 1
3611 LanguageType eReal
= MsLangId::getRealLanguage( eLang
);
3612 if ( eReal
!= eLang
) {
3617 pLocaleData
->setLocale( pLocales
[nLocale
] );
3618 Sequence
< Currency2
> aCurrSeq
= pLocaleData
->getAllCurrencies();
3619 sal_Int32 nCurrencyCount
= aCurrSeq
.getLength();
3620 Currency2
const * const pCurrencies
= aCurrSeq
.getConstArray();
3622 // one default currency for each locale, insert first so it is found first
3624 for ( nDefault
= 0; nDefault
< nCurrencyCount
; nDefault
++ )
3626 if ( pCurrencies
[nDefault
].Default
)
3629 if ( nDefault
< nCurrencyCount
)
3630 pEntry
= new NfCurrencyEntry( pCurrencies
[nDefault
], *pLocaleData
, eLang
);
3632 pEntry
= new NfCurrencyEntry( *pLocaleData
, eLang
); // first or ShellsAndPebbles
3634 if (LocaleDataWrapper::areChecksEnabled())
3635 lcl_CheckCurrencySymbolPosition( *pEntry
);
3637 rCurrencyTable
.Insert( pEntry
, nCurrencyPos
++ );
3638 if ( !nSystemCurrencyPosition
&& (aConfiguredCurrencyAbbrev
.Len() ?
3639 pEntry
->GetBankSymbol() == aConfiguredCurrencyAbbrev
&&
3640 pEntry
->GetLanguage() == eConfiguredCurrencyLanguage
: FALSE
) )
3641 nSystemCurrencyPosition
= nCurrencyPos
-1;
3642 if ( !nMatchingSystemCurrencyPosition
&&
3643 pEntry
->GetLanguage() == eSysLang
)
3644 nMatchingSystemCurrencyPosition
= nCurrencyPos
-1;
3646 // all remaining currencies for each locale
3647 if ( nCurrencyCount
> 1 )
3649 sal_Int32 nCurrency
;
3650 for ( nCurrency
= 0; nCurrency
< nCurrencyCount
; nCurrency
++ )
3652 if (pCurrencies
[nCurrency
].LegacyOnly
)
3654 pEntry
= new NfCurrencyEntry( pCurrencies
[nCurrency
], *pLocaleData
, eLang
);
3655 rLegacyOnlyCurrencyTable
.Insert( pEntry
, nLegacyOnlyCurrencyPos
++ );
3657 else if ( nCurrency
!= nDefault
)
3659 pEntry
= new NfCurrencyEntry( pCurrencies
[nCurrency
], *pLocaleData
, eLang
);
3661 BOOL bInsert
= TRUE
;
3662 NfCurrencyEntry
const * const * pData
= rCurrencyTable
.GetData();
3663 USHORT n
= rCurrencyTable
.Count();
3664 pData
++; // skip first SYSTEM entry
3665 for ( USHORT j
=1; j
<n
; j
++ )
3667 if ( *(*pData
++) == *pEntry
)
3677 rCurrencyTable
.Insert( pEntry
, nCurrencyPos
++ );
3678 if ( !nSecondarySystemCurrencyPosition
&&
3679 (aConfiguredCurrencyAbbrev
.Len() ?
3680 pEntry
->GetBankSymbol() == aConfiguredCurrencyAbbrev
:
3681 pEntry
->GetLanguage() == eConfiguredCurrencyLanguage
) )
3682 nSecondarySystemCurrencyPosition
= nCurrencyPos
-1;
3683 if ( !nMatchingSystemCurrencyPosition
&&
3684 pEntry
->GetLanguage() == eSysLang
)
3685 nMatchingSystemCurrencyPosition
= nCurrencyPos
-1;
3691 if ( !nSystemCurrencyPosition
)
3692 nSystemCurrencyPosition
= nSecondarySystemCurrencyPosition
;
3693 if ((aConfiguredCurrencyAbbrev
.Len() && !nSystemCurrencyPosition
) &&
3694 LocaleDataWrapper::areChecksEnabled())
3695 LocaleDataWrapper::outputCheckMessage(
3696 "SvNumberFormatter::ImpInitCurrencyTable: configured currency not in I18N locale data.");
3697 // match SYSTEM if no configured currency found
3698 if ( !nSystemCurrencyPosition
)
3699 nSystemCurrencyPosition
= nMatchingSystemCurrencyPosition
;
3700 if ((!aConfiguredCurrencyAbbrev
.Len() && !nSystemCurrencyPosition
) &&
3701 LocaleDataWrapper::areChecksEnabled())
3702 LocaleDataWrapper::outputCheckMessage(
3703 "SvNumberFormatter::ImpInitCurrencyTable: system currency not in I18N locale data.");
3705 SvtSysLocaleOptions::SetCurrencyChangeLink(
3706 STATIC_LINK( NULL
, SvNumberFormatter
, CurrencyChangeLink
) );
3707 bInitializing
= FALSE
;
3708 bCurrencyTableInitialized
= TRUE
;
3712 USHORT
SvNumberFormatter::GetCurrencyFormatStrings( NfWSStringsDtor
& rStrArr
,
3713 const NfCurrencyEntry
& rCurr
, BOOL bBank
) const
3715 USHORT nDefault
= 0;
3717 { // nur Bankensymbole
3718 String aPositiveBank
, aNegativeBank
;
3719 rCurr
.BuildPositiveFormatString( aPositiveBank
, TRUE
, *xLocaleData
, 1 );
3720 rCurr
.BuildNegativeFormatString( aNegativeBank
, TRUE
, *xLocaleData
, 1 );
3722 WSStringPtr pFormat1
= new String( aPositiveBank
);
3724 WSStringPtr pFormat2
= new String( *pFormat1
);
3727 aRed
+= pFormatScanner
->GetRedString();
3732 *pFormat1
+= aNegativeBank
;
3733 *pFormat2
+= aNegativeBank
;
3735 rStrArr
.Insert( pFormat1
, rStrArr
.Count() );
3736 rStrArr
.Insert( pFormat2
, rStrArr
.Count() );
3737 nDefault
= rStrArr
.Count() - 1;
3740 { // gemischte Formate wie in SvNumberFormatter::ImpGenerateFormats
3741 // aber keine doppelten, wenn keine Nachkommastellen in Waehrung
3742 String aPositive
, aNegative
, aPositiveNoDec
, aNegativeNoDec
,
3743 aPositiveDashed
, aNegativeDashed
;
3744 WSStringPtr pFormat1
, pFormat2
, pFormat3
, pFormat4
, pFormat5
;
3747 aRed
+= pFormatScanner
->GetRedString();
3750 rCurr
.BuildPositiveFormatString( aPositive
, FALSE
, *xLocaleData
, 1 );
3751 rCurr
.BuildNegativeFormatString( aNegative
, FALSE
, *xLocaleData
, 1 );
3752 if ( rCurr
.GetDigits() )
3754 rCurr
.BuildPositiveFormatString( aPositiveNoDec
, FALSE
, *xLocaleData
, 0 );
3755 rCurr
.BuildNegativeFormatString( aNegativeNoDec
, FALSE
, *xLocaleData
, 0 );
3756 rCurr
.BuildPositiveFormatString( aPositiveDashed
, FALSE
, *xLocaleData
, 2 );
3757 rCurr
.BuildNegativeFormatString( aNegativeDashed
, FALSE
, *xLocaleData
, 2 );
3759 pFormat1
= new String( aPositiveNoDec
);
3761 pFormat3
= new String( *pFormat1
);
3762 pFormat5
= new String( aPositiveDashed
);
3765 *pFormat1
+= aNegativeNoDec
;
3770 *pFormat3
+= aNegativeNoDec
;
3771 *pFormat5
+= aNegativeDashed
;
3780 pFormat2
= new String( aPositive
);
3782 pFormat4
= new String( *pFormat2
);
3784 *pFormat2
+= aNegative
;
3787 *pFormat4
+= aNegative
;
3790 rStrArr
.Insert( pFormat1
, rStrArr
.Count() );
3791 rStrArr
.Insert( pFormat2
, rStrArr
.Count() );
3793 rStrArr
.Insert( pFormat3
, rStrArr
.Count() );
3794 rStrArr
.Insert( pFormat4
, rStrArr
.Count() );
3795 nDefault
= rStrArr
.Count() - 1;
3797 rStrArr
.Insert( pFormat5
, rStrArr
.Count() );
3803 //--- NfCurrencyEntry ----------------------------------------------------
3805 NfCurrencyEntry::NfCurrencyEntry()
3806 : eLanguage( LANGUAGE_DONTKNOW
),
3815 NfCurrencyEntry::NfCurrencyEntry( const LocaleDataWrapper
& rLocaleData
, LanguageType eLang
)
3817 aSymbol
= rLocaleData
.getCurrSymbol();
3818 aBankSymbol
= rLocaleData
.getCurrBankSymbol();
3820 nPositiveFormat
= rLocaleData
.getCurrPositiveFormat();
3821 nNegativeFormat
= rLocaleData
.getCurrNegativeFormat();
3822 nDigits
= rLocaleData
.getCurrDigits();
3823 cZeroChar
= rLocaleData
.getCurrZeroChar();
3827 NfCurrencyEntry::NfCurrencyEntry( const ::com::sun::star::i18n::Currency
& rCurr
,
3828 const LocaleDataWrapper
& rLocaleData
, LanguageType eLang
)
3830 aSymbol
= rCurr
.Symbol
;
3831 aBankSymbol
= rCurr
.BankSymbol
;
3833 nPositiveFormat
= rLocaleData
.getCurrPositiveFormat();
3834 nNegativeFormat
= rLocaleData
.getCurrNegativeFormat();
3835 nDigits
= rCurr
.DecimalPlaces
;
3836 cZeroChar
= rLocaleData
.getCurrZeroChar();
3840 BOOL
NfCurrencyEntry::operator==( const NfCurrencyEntry
& r
) const
3842 return aSymbol
== r
.aSymbol
3843 && aBankSymbol
== r
.aBankSymbol
3844 && eLanguage
== r
.eLanguage
3849 void NfCurrencyEntry::SetEuro()
3851 aSymbol
= NfCurrencyEntry::GetEuroSymbol();
3852 aBankSymbol
.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "EUR" ) );
3853 eLanguage
= LANGUAGE_DONTKNOW
;
3854 nPositiveFormat
= 3;
3855 nNegativeFormat
= 8;
3861 BOOL
NfCurrencyEntry::IsEuro() const
3863 if ( aBankSymbol
.EqualsAscii( "EUR" ) )
3865 String
aEuro( NfCurrencyEntry::GetEuroSymbol() );
3866 return aSymbol
== aEuro
;
3870 void NfCurrencyEntry::ApplyVariableInformation( const NfCurrencyEntry
& r
)
3872 nPositiveFormat
= r
.nPositiveFormat
;
3873 nNegativeFormat
= r
.nNegativeFormat
;
3874 cZeroChar
= r
.cZeroChar
;
3878 void NfCurrencyEntry::BuildSymbolString( String
& rStr
, BOOL bBank
,
3879 BOOL bWithoutExtension
) const
3884 rStr
+= aBankSymbol
;
3887 if ( aSymbol
.Search( '-' ) != STRING_NOTFOUND
|| aSymbol
.Search( ']' ) != STRING_NOTFOUND
)
3895 if ( !bWithoutExtension
&& eLanguage
!= LANGUAGE_DONTKNOW
&& eLanguage
!= LANGUAGE_SYSTEM
)
3898 rStr
+= String::CreateFromInt32( sal_Int32( eLanguage
), 16 ).ToUpperAscii();
3905 void NfCurrencyEntry::Impl_BuildFormatStringNumChars( String
& rStr
,
3906 const LocaleDataWrapper
& rLoc
, USHORT nDecimalFormat
) const
3908 rStr
.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "###0" ) );
3909 rStr
.Insert( rLoc
.getNumThousandSep(), 1 );
3910 if ( nDecimalFormat
&& nDigits
)
3912 rStr
+= rLoc
.getNumDecimalSep();
3913 rStr
.Expand( rStr
.Len() + nDigits
, (nDecimalFormat
== 2 ? '-' : cZeroChar
) );
3918 void NfCurrencyEntry::BuildPositiveFormatString( String
& rStr
, BOOL bBank
,
3919 const LocaleDataWrapper
& rLoc
, USHORT nDecimalFormat
) const
3921 Impl_BuildFormatStringNumChars( rStr
, rLoc
, nDecimalFormat
);
3922 USHORT nPosiForm
= NfCurrencyEntry::GetEffectivePositiveFormat(
3923 rLoc
.getCurrPositiveFormat(), nPositiveFormat
, bBank
);
3924 CompletePositiveFormatString( rStr
, bBank
, nPosiForm
);
3928 void NfCurrencyEntry::BuildNegativeFormatString( String
& rStr
, BOOL bBank
,
3929 const LocaleDataWrapper
& rLoc
, USHORT nDecimalFormat
) const
3931 Impl_BuildFormatStringNumChars( rStr
, rLoc
, nDecimalFormat
);
3932 USHORT nNegaForm
= NfCurrencyEntry::GetEffectiveNegativeFormat(
3933 rLoc
.getCurrNegativeFormat(), nNegativeFormat
, bBank
);
3934 CompleteNegativeFormatString( rStr
, bBank
, nNegaForm
);
3938 void NfCurrencyEntry::CompletePositiveFormatString( String
& rStr
, BOOL bBank
,
3939 USHORT nPosiForm
) const
3942 BuildSymbolString( aSymStr
, bBank
);
3943 NfCurrencyEntry::CompletePositiveFormatString( rStr
, aSymStr
, nPosiForm
);
3947 void NfCurrencyEntry::CompleteNegativeFormatString( String
& rStr
, BOOL bBank
,
3948 USHORT nNegaForm
) const
3951 BuildSymbolString( aSymStr
, bBank
);
3952 NfCurrencyEntry::CompleteNegativeFormatString( rStr
, aSymStr
, nNegaForm
);
3957 void NfCurrencyEntry::CompletePositiveFormatString( String
& rStr
,
3958 const String
& rSymStr
, USHORT nPositiveFormat
)
3960 switch( nPositiveFormat
)
3963 rStr
.Insert( rSymStr
, 0 );
3970 rStr
.Insert( ' ', 0 );
3971 rStr
.Insert( rSymStr
, 0 );
3981 DBG_ERROR("NfCurrencyEntry::CompletePositiveFormatString: unknown option");
3988 void NfCurrencyEntry::CompleteNegativeFormatString( String
& rStr
,
3989 const String
& rSymStr
, USHORT nNegativeFormat
)
3991 switch( nNegativeFormat
)
3995 rStr
.Insert( rSymStr
, 0);
4002 rStr
.Insert( rSymStr
, 0);
4009 rStr
.Insert( rSymStr
, 0);
4014 rStr
.Insert( rSymStr
, 0);
4053 rStr
.Insert( rSymStr
, 0);
4066 String
aTmp( rSymStr
);
4069 rStr
.Insert( aTmp
, 0 );
4074 rStr
.Insert(' ', 0);
4075 rStr
.Insert( rSymStr
, 0);
4089 rStr
.Insert( rSymStr
, 0);
4103 DBG_ERROR("NfCurrencyEntry::CompleteNegativeFormatString: unknown option");
4110 USHORT
NfCurrencyEntry::GetEffectivePositiveFormat( USHORT
4111 #if ! NF_BANKSYMBOL_FIX_POSITION
4114 , USHORT nCurrFormat
, BOOL bBank
)
4118 #if NF_BANKSYMBOL_FIX_POSITION
4121 switch ( nIntlFormat
)
4124 nIntlFormat
= 2; // $ 1
4127 nIntlFormat
= 3; // 1 $
4134 DBG_ERROR("NfCurrencyEntry::GetEffectivePositiveFormat: unknown option");
4145 // nur aufrufen, wenn nCurrFormat wirklich mit Klammern ist
4146 USHORT
lcl_MergeNegativeParenthesisFormat( USHORT nIntlFormat
, USHORT nCurrFormat
)
4148 short nSign
= 0; // -1:=Klammer 0:=links, 1:=mitte, 2:=rechts
4149 switch ( nIntlFormat
)
4175 DBG_ERROR("lcl_MergeNegativeParenthesisFormat: unknown option");
4179 switch ( nCurrFormat
)
4231 USHORT
NfCurrencyEntry::GetEffectiveNegativeFormat( USHORT nIntlFormat
,
4232 USHORT nCurrFormat
, BOOL bBank
)
4236 #if NF_BANKSYMBOL_FIX_POSITION
4239 switch ( nIntlFormat
)
4242 // nIntlFormat = 14; // ($ 1)
4243 nIntlFormat
= 9; // -$ 1
4246 nIntlFormat
= 9; // -$ 1
4249 nIntlFormat
= 11; // $ -1
4252 nIntlFormat
= 12; // $ 1-
4255 // nIntlFormat = 15; // (1 $)
4256 nIntlFormat
= 8; // -1 $
4259 nIntlFormat
= 8; // -1 $
4262 nIntlFormat
= 13; // 1- $
4265 nIntlFormat
= 10; // 1 $-
4280 // nIntlFormat = 14; // ($ 1)
4281 nIntlFormat
= 9; // -$ 1
4284 // nIntlFormat = 15; // (1 $)
4285 nIntlFormat
= 8; // -1 $
4288 DBG_ERROR("NfCurrencyEntry::GetEffectiveNegativeFormat: unknown option");
4293 else if ( nIntlFormat
!= nCurrFormat
)
4295 switch ( nCurrFormat
)
4298 nIntlFormat
= lcl_MergeNegativeParenthesisFormat(
4299 nIntlFormat
, nCurrFormat
);
4302 nIntlFormat
= nCurrFormat
;
4305 nIntlFormat
= nCurrFormat
;
4308 nIntlFormat
= nCurrFormat
;
4311 nIntlFormat
= lcl_MergeNegativeParenthesisFormat(
4312 nIntlFormat
, nCurrFormat
);
4315 nIntlFormat
= nCurrFormat
;
4318 nIntlFormat
= nCurrFormat
;
4321 nIntlFormat
= nCurrFormat
;
4324 nIntlFormat
= nCurrFormat
;
4327 nIntlFormat
= nCurrFormat
;
4330 nIntlFormat
= nCurrFormat
;
4333 nIntlFormat
= nCurrFormat
;
4336 nIntlFormat
= nCurrFormat
;
4339 nIntlFormat
= nCurrFormat
;
4342 nIntlFormat
= lcl_MergeNegativeParenthesisFormat(
4343 nIntlFormat
, nCurrFormat
);
4346 nIntlFormat
= lcl_MergeNegativeParenthesisFormat(
4347 nIntlFormat
, nCurrFormat
);
4350 DBG_ERROR("NfCurrencyEntry::GetEffectiveNegativeFormat: unknown option");
4358 // we only support default encodings here
4360 sal_Char
NfCurrencyEntry::GetEuroSymbol( rtl_TextEncoding eTextEncoding
)
4362 switch ( eTextEncoding
)
4364 case RTL_TEXTENCODING_MS_1252
: // WNT Ansi
4365 case RTL_TEXTENCODING_ISO_8859_1
: // UNX for use with TrueType fonts
4367 case RTL_TEXTENCODING_ISO_8859_15
: // UNX real
4369 case RTL_TEXTENCODING_IBM_850
: // OS2
4371 case RTL_TEXTENCODING_APPLE_ROMAN
: // MAC
4373 default: // default system
4379 // return '\xA4'; // #56121# 0xA4 waere korrekt fuer iso-8859-15
4380 return '\x80'; // aber Windoze-Code fuer die konvertierten TrueType-Fonts
4382 #error EuroSymbol is what?