1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <comphelper/string.hxx>
21 #include <tools/debug.hxx>
22 #include <unotools/charclass.hxx>
23 #include <i18nlangtag/mslangid.hxx>
24 #include <unotools/localedatawrapper.hxx>
25 #include <unotools/numberformatcodewrapper.hxx>
26 #include <unotools/calendarwrapper.hxx>
27 #include <com/sun/star/i18n/KNumberFormatUsage.hpp>
28 #include <com/sun/star/i18n/KNumberFormatType.hpp>
29 #include <comphelper/processfactory.hxx>
30 #include <unotools/misccfg.hxx>
33 #include <osl/mutex.hxx>
34 #include <svl/zforlist.hxx>
36 #include "zforscan.hxx"
37 #include "zforfind.hxx"
38 #include <svl/zformat.hxx>
39 #include "numhead.hxx"
41 #include <unotools/syslocaleoptions.hxx>
42 #include <unotools/digitgroupingiterator.hxx>
43 #include <rtl/instance.hxx>
44 #include <rtl/strbuf.hxx>
49 using namespace ::com::sun::star
;
50 using namespace ::com::sun::star::uno
;
51 using namespace ::com::sun::star::i18n
;
52 using namespace ::com::sun::star::lang
;
53 using namespace ::std
;
55 // Constants for type offsets per Country/Language (CL)
57 #define ZF_STANDARD_PERCENT 10
58 #define ZF_STANDARD_CURRENCY 20
59 #define ZF_STANDARD_DATE 30
60 #define ZF_STANDARD_TIME 40
61 #define ZF_STANDARD_DATETIME 50
62 #define ZF_STANDARD_SCIENTIFIC 60
63 #define ZF_STANDARD_FRACTION 70
64 #define ZF_STANDARD_NEWEXTENDED 75
65 #define ZF_STANDARD_NEWEXTENDEDMAX SV_MAX_ANZ_STANDARD_FORMATE-2 // 98
66 #define ZF_STANDARD_LOGICAL SV_MAX_ANZ_STANDARD_FORMATE-1 // 99
67 #define ZF_STANDARD_TEXT SV_MAX_ANZ_STANDARD_FORMATE // 100
69 /* Locale that is set if an unknown locale (from another system) is loaded of
70 * legacy documents. Can not be SYSTEM because else, for example, a German "DM"
71 * (old currency) is recognized as a date (#53155#). */
72 #define UNKNOWN_SUBSTITUTE LANGUAGE_ENGLISH_US
77 sal_uInt32 maData
[NF_INDEX_TABLE_ENTRIES
];
80 IndexTable() : mbInitialized(false) {}
83 static IndexTable theIndexTable
;
85 // ====================================================================
88 instead of every number formatter being a listener we have a registry which
89 also handles one instance of the SysLocale options
92 typedef ::std::vector
< SvNumberFormatter
* > SvNumberFormatterList_impl
;
94 class SvNumberFormatterRegistry_Impl
: public utl::ConfigurationListener
96 SvNumberFormatterList_impl aFormatters
;
97 SvtSysLocaleOptions aSysLocaleOptions
;
98 LanguageType eSysLanguage
;
101 SvNumberFormatterRegistry_Impl();
102 virtual ~SvNumberFormatterRegistry_Impl();
104 void Insert( SvNumberFormatter
* pThis
)
105 { aFormatters
.push_back( pThis
); }
107 SvNumberFormatter
* Remove( SvNumberFormatter
* pThis
);
110 { return aFormatters
.size(); }
112 virtual void ConfigurationChanged( utl::ConfigurationBroadcaster
*, sal_uInt32
);
115 SvNumberFormatterRegistry_Impl::SvNumberFormatterRegistry_Impl()
117 eSysLanguage
= MsLangId::getRealLanguage( LANGUAGE_SYSTEM
);
118 aSysLocaleOptions
.AddListener( this );
122 SvNumberFormatterRegistry_Impl::~SvNumberFormatterRegistry_Impl()
124 aSysLocaleOptions
.RemoveListener( this );
128 SvNumberFormatter
* SvNumberFormatterRegistry_Impl::Remove( SvNumberFormatter
* pThis
)
130 for (SvNumberFormatterList_impl::iterator it
= aFormatters
.begin();
131 it
!= aFormatters
.end(); ++it
)
135 aFormatters
.erase( it
);
142 void SvNumberFormatterRegistry_Impl::ConfigurationChanged( utl::ConfigurationBroadcaster
*,
145 ::osl::MutexGuard
aGuard( SvNumberFormatter::GetMutex() );
147 if ( nHint
& SYSLOCALEOPTIONS_HINT_LOCALE
)
149 for( size_t i
= 0, n
= aFormatters
.size(); i
< n
; ++i
)
150 aFormatters
[ i
]->ReplaceSystemCL( eSysLanguage
);
151 eSysLanguage
= MsLangId::getRealLanguage( LANGUAGE_SYSTEM
);
153 if ( nHint
& SYSLOCALEOPTIONS_HINT_CURRENCY
)
155 for( size_t i
= 0, n
= aFormatters
.size(); i
< n
; ++i
)
156 aFormatters
[ i
]->ResetDefaultSystemCurrency();
158 if ( nHint
& SYSLOCALEOPTIONS_HINT_DATEPATTERNS
)
160 for( size_t i
= 0, n
= aFormatters
.size(); i
< n
; ++i
)
161 aFormatters
[ i
]->InvalidateDateAcceptancePatterns();
166 // ====================================================================
168 SvNumberFormatterRegistry_Impl
* SvNumberFormatter::pFormatterRegistry
= NULL
;
169 bool SvNumberFormatter::bCurrencyTableInitialized
= false;
172 struct theCurrencyTable
:
173 public rtl::Static
< NfCurrencyTable
, theCurrencyTable
> {};
175 struct theLegacyOnlyCurrencyTable
:
176 public rtl::Static
< NfCurrencyTable
, theLegacyOnlyCurrencyTable
> {};
178 /** THE set of installed locales. */
179 struct theInstalledLocales
:
180 public rtl::Static
< NfInstalledLocales
, theInstalledLocales
> {};
183 sal_uInt16
SvNumberFormatter::nSystemCurrencyPosition
= 0;
185 // Whether BankSymbol (not CurrencySymbol!) is always at the end (1 $;-1 $) or
186 // language dependent.
187 #define NF_BANKSYMBOL_FIX_POSITION 1
190 /***********************Funktionen SvNumberFormatter**************************/
192 const sal_uInt16
SvNumberFormatter::UNLIMITED_PRECISION
= ::std::numeric_limits
<sal_uInt16
>::max();
193 const sal_uInt16
SvNumberFormatter::INPUTSTRING_PRECISION
= ::std::numeric_limits
<sal_uInt16
>::max()-1;
195 SvNumberFormatter::SvNumberFormatter( const Reference
< XComponentContext
>& rxContext
,
197 : m_xContext( rxContext
)
198 , maLanguageTag( eLang
)
200 ImpConstruct( eLang
);
204 SvNumberFormatter::~SvNumberFormatter()
207 ::osl::MutexGuard
aGuard( GetMutex() );
208 pFormatterRegistry
->Remove( this );
209 if ( !pFormatterRegistry
->Count() )
211 delete pFormatterRegistry
;
212 pFormatterRegistry
= NULL
;
216 for (SvNumberFormatTable::iterator it
= aFTable
.begin(); it
!= aFTable
.end(); ++it
)
220 delete pStringScanner
;
221 delete pFormatScanner
;
227 void SvNumberFormatter::ImpConstruct( LanguageType eLang
)
229 if ( eLang
== LANGUAGE_DONTKNOW
)
231 eLang
= UNKNOWN_SUBSTITUTE
;
235 eEvalDateFormat
= NF_EVALDATEFORMAT_INTL
;
236 nDefaultSystemCurrencyFormat
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
238 maLanguageTag
.reset( eLang
);
239 pCharClass
= new CharClass( m_xContext
, maLanguageTag
);
240 xLocaleData
.init( m_xContext
, maLanguageTag
);
241 xCalendar
.init( m_xContext
, maLanguageTag
.getLocale() );
242 xTransliteration
.init( m_xContext
, eLang
,
243 ::com::sun::star::i18n::TransliterationModules_IGNORE_CASE
);
244 xNatNum
.init( m_xContext
);
246 // cached locale data items
247 const LocaleDataWrapper
* pLoc
= GetLocaleData();
248 aDecimalSep
= pLoc
->getNumDecimalSep();
249 aThousandSep
= pLoc
->getNumThousandSep();
250 aDateSep
= pLoc
->getDateSep();
252 pStringScanner
= new ImpSvNumberInputScan( this );
253 pFormatScanner
= new ImpSvNumberformatScan( this );
256 ImpGenerateFormats( 0, false ); // 0 .. 999 for initialized language formats
260 ::osl::MutexGuard
aGuard( GetMutex() );
261 GetFormatterRegistry().Insert( this );
265 void SvNumberFormatter::ChangeIntl(LanguageType eLnge
)
267 if (ActLnge
!= eLnge
)
271 maLanguageTag
.reset( eLnge
);
272 pCharClass
->setLanguageTag( maLanguageTag
);
273 xLocaleData
.changeLocale( maLanguageTag
);
274 xCalendar
.changeLocale( maLanguageTag
.getLocale() );
275 xTransliteration
.changeLocale( eLnge
);
277 // cached locale data items, initialize BEFORE calling ChangeIntl below
278 const LocaleDataWrapper
* pLoc
= GetLocaleData();
279 aDecimalSep
= pLoc
->getNumDecimalSep();
280 aThousandSep
= pLoc
->getNumThousandSep();
281 aDateSep
= pLoc
->getDateSep();
283 pFormatScanner
->ChangeIntl();
284 pStringScanner
->ChangeIntl();
290 ::osl::Mutex
& SvNumberFormatter::GetMutex()
292 static ::osl::Mutex
* pMutex
= NULL
;
295 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
298 // #i77768# Due to a static reference in the toolkit lib
299 // we need a mutex that lives longer than the svl library.
300 // Otherwise the dtor would use a destructed mutex!!
301 pMutex
= new ::osl::Mutex
;
309 SvNumberFormatterRegistry_Impl
& SvNumberFormatter::GetFormatterRegistry()
311 ::osl::MutexGuard
aGuard( GetMutex() );
312 if ( !pFormatterRegistry
)
314 pFormatterRegistry
= new SvNumberFormatterRegistry_Impl
;
316 return *pFormatterRegistry
;
320 Color
* SvNumberFormatter::GetUserDefColor(sal_uInt16 nIndex
)
322 if( aColorLink
.IsSet() )
324 return (Color
*) ( aColorLink
.Call( (void*) &nIndex
));
332 void SvNumberFormatter::ChangeNullDate(sal_uInt16 nDay
,
336 pFormatScanner
->ChangeNullDate(nDay
, nMonth
, nYear
);
337 pStringScanner
->ChangeNullDate(nDay
, nMonth
, nYear
);
340 Date
* SvNumberFormatter::GetNullDate()
342 return pFormatScanner
->GetNullDate();
345 void SvNumberFormatter::ChangeStandardPrec(short nPrec
)
347 pFormatScanner
->ChangeStandardPrec(nPrec
);
350 sal_uInt16
SvNumberFormatter::GetStandardPrec()
352 return pFormatScanner
->GetStandardPrec();
355 void SvNumberFormatter::ImpChangeSysCL( LanguageType eLnge
, bool bNoAdditionalFormats
)
357 if (eLnge
== LANGUAGE_DONTKNOW
)
359 eLnge
= UNKNOWN_SUBSTITUTE
;
361 if (eLnge
!= IniLnge
)
365 // delete old formats
366 for (SvNumberFormatTable::iterator it
= aFTable
.begin(); it
!= aFTable
.end(); ++it
)
371 ImpGenerateFormats( 0, bNoAdditionalFormats
); // new standard formats
373 else if ( bNoAdditionalFormats
)
375 // delete additional standard formats
377 SvNumberFormatTable::iterator it
= aFTable
.find( SV_MAX_ANZ_STANDARD_FORMATE
+ 1 );
378 while ( it
!= aFTable
.end() &&
379 (nKey
= it
->first
) > SV_MAX_ANZ_STANDARD_FORMATE
&&
380 nKey
< SV_COUNTRY_LANGUAGE_OFFSET
)
383 aFTable
.erase( it
++ );
389 void SvNumberFormatter::ReplaceSystemCL( LanguageType eOldLanguage
)
391 sal_uInt32 nCLOffset
= ImpGetCLOffset( LANGUAGE_SYSTEM
);
392 if ( nCLOffset
> MaxCLOffset
)
394 return ; // no SYSTEM entries to replace
396 const sal_uInt32 nMaxBuiltin
= nCLOffset
+ SV_MAX_ANZ_STANDARD_FORMATE
;
397 const sal_uInt32 nNextCL
= nCLOffset
+ SV_COUNTRY_LANGUAGE_OFFSET
;
400 // remove old builtin formats
401 SvNumberFormatTable::iterator it
= aFTable
.find( nCLOffset
);
402 while ( it
!= aFTable
.end() && (nKey
= it
->first
) >= nCLOffset
&& nKey
<= nMaxBuiltin
)
405 aFTable
.erase( it
++ );
408 // move additional and user defined to temporary table
409 SvNumberFormatTable aOldTable
;
410 while ( it
!= aFTable
.end() && (nKey
= it
->first
) >= nCLOffset
&& nKey
< nNextCL
)
412 aOldTable
[ nKey
] = it
->second
;
413 aFTable
.erase( it
++ );
416 // generate new old builtin formats
417 // reset ActLnge otherwise ChangeIntl() wouldn't switch if already LANGUAGE_SYSTEM
418 ActLnge
= LANGUAGE_DONTKNOW
;
419 ChangeIntl( LANGUAGE_SYSTEM
);
420 ImpGenerateFormats( nCLOffset
, true );
422 // convert additional and user defined from old system to new system
423 SvNumberformat
* pStdFormat
= GetFormatEntry( nCLOffset
+ ZF_STANDARD
);
424 sal_uInt32 nLastKey
= nMaxBuiltin
;
425 pFormatScanner
->SetConvertMode( eOldLanguage
, LANGUAGE_SYSTEM
, true );
426 while ( !aOldTable
.empty() )
428 nKey
= aOldTable
.begin()->first
;
429 if ( nLastKey
< nKey
)
433 SvNumberformat
* pOldEntry
= aOldTable
.begin()->second
;
434 aOldTable
.erase( nKey
);
435 OUString
aString( pOldEntry
->GetFormatstring() );
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 sal_Int32 nCheckPos
= -1;
443 SvNumberformat
* pNewEntry
= new SvNumberformat( aString
, pFormatScanner
,
444 pStringScanner
, nCheckPos
, eLge
);
445 if ( nCheckPos
!= 0 )
451 short eCheckType
= pNewEntry
->GetType();
452 if ( eCheckType
!= NUMBERFORMAT_UNDEFINED
)
454 pNewEntry
->SetType( eCheckType
| NUMBERFORMAT_DEFINED
);
458 pNewEntry
->SetType( NUMBERFORMAT_DEFINED
);
461 if ( !aFTable
.insert( make_pair( nKey
, pNewEntry
) ).second
)
470 DBG_ASSERT( bCheck
, "SvNumberFormatter::ReplaceSystemCL: couldn't convert" );
475 pFormatScanner
->SetConvertMode(false);
476 pStdFormat
->SetLastInsertKey( sal_uInt16(nLastKey
- nCLOffset
) );
478 // append new system additional formats
479 NumberFormatCodeWrapper
aNumberFormatCode( m_xContext
,
480 GetLanguageTag().getLocale() );
481 ImpGenerateAdditionalFormats( nCLOffset
, aNumberFormatCode
, true );
485 bool SvNumberFormatter::IsTextFormat(sal_uInt32 F_Index
) const
487 const SvNumberformat
* pFormat
= GetFormatEntry(F_Index
);
489 return pFormat
? pFormat
->IsTextFormat() : false;
492 bool SvNumberFormatter::PutEntry(OUString
& rString
,
493 sal_Int32
& nCheckPos
,
495 sal_uInt32
& nKey
, // format key
499 if (rString
.isEmpty()) // empty string
501 nCheckPos
= 1; // -> Error
504 if (eLnge
== LANGUAGE_DONTKNOW
)
508 ChangeIntl(eLnge
); // change locale if necessary
509 LanguageType eLge
= eLnge
; // non-const for ConvertMode
511 SvNumberformat
* p_Entry
= new SvNumberformat(rString
,
517 if (nCheckPos
== 0) // Format ok
518 { // Type comparison:
519 short eCheckType
= p_Entry
->GetType();
520 if ( eCheckType
!= NUMBERFORMAT_UNDEFINED
)
522 p_Entry
->SetType(eCheckType
| NUMBERFORMAT_DEFINED
);
527 p_Entry
->SetType(NUMBERFORMAT_DEFINED
);
528 nType
= NUMBERFORMAT_DEFINED
;
531 sal_uInt32 CLOffset
= ImpGenerateCL(eLge
); // create new standard formats if necessary
533 nKey
= ImpIsEntry(p_Entry
->GetFormatstring(),CLOffset
, eLge
);
534 if (nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
) // already present
540 SvNumberformat
* pStdFormat
= GetFormatEntry(CLOffset
+ ZF_STANDARD
);
541 sal_uInt32 nPos
= CLOffset
+ pStdFormat
->GetLastInsertKey();
542 if (nPos
+1 - CLOffset
>= SV_COUNTRY_LANGUAGE_OFFSET
)
544 SAL_WARN( "svl.numbers", "SvNumberFormatter::PutEntry: too many formats for CL");
547 else if (!aFTable
.insert(make_pair( nPos
+1,p_Entry
)).second
)
549 SAL_WARN( "svl.numbers", "SvNumberFormatter::PutEntry: dup position");
556 pStdFormat
->SetLastInsertKey((sal_uInt16
) (nKey
-CLOffset
));
567 bool SvNumberFormatter::PutandConvertEntry(OUString
& rString
,
568 sal_Int32
& nCheckPos
,
572 LanguageType eNewLnge
)
575 if (eNewLnge
== LANGUAGE_DONTKNOW
)
579 pFormatScanner
->SetConvertMode(eLnge
, eNewLnge
);
580 bRes
= PutEntry(rString
, nCheckPos
, nType
, nKey
, eLnge
);
581 pFormatScanner
->SetConvertMode(false);
585 bool SvNumberFormatter::PutandConvertEntrySystem(OUString
& rString
,
586 sal_Int32
& nCheckPos
,
590 LanguageType eNewLnge
)
593 if (eNewLnge
== LANGUAGE_DONTKNOW
)
597 pFormatScanner
->SetConvertMode(eLnge
, eNewLnge
, true);
598 bRes
= PutEntry(rString
, nCheckPos
, nType
, nKey
, eLnge
);
599 pFormatScanner
->SetConvertMode(false);
603 sal_uInt32
SvNumberFormatter::GetIndexPuttingAndConverting( OUString
& rString
, LanguageType eLnge
,
604 LanguageType eSysLnge
, short & rType
,
605 bool & rNewInserted
, sal_Int32
& rCheckPos
)
607 sal_uInt32 nKey
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
608 rNewInserted
= false;
611 // #62389# empty format string (of Writer) => General standard format
612 if (rString
.isEmpty())
616 else if (eLnge
== LANGUAGE_SYSTEM
&& eSysLnge
!= SvtSysLocale().GetLanguageTag().getLanguageType())
618 sal_uInt32 nOrig
= GetEntryKey( rString
, eSysLnge
);
619 if (nOrig
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
621 nKey
= nOrig
; // none available, maybe user-defined
625 nKey
= GetFormatForLanguageIfBuiltIn( nOrig
, SvtSysLocale().GetLanguageTag().getLanguageType() );
629 // Not a builtin format, convert.
630 // The format code string may get modified and adapted to the real
631 // language and wouldn't match eSysLnge anymore, do that on a copy.
632 OUString
aTmp( rString
);
633 rNewInserted
= PutandConvertEntrySystem( aTmp
, rCheckPos
, rType
,
634 nKey
, eLnge
, SvtSysLocale().GetLanguageTag().getLanguageType());
637 SAL_WARN( "svl.numbers", "SvNumberFormatter::GetIndexPuttingAndConverting: bad format code string for current locale");
638 nKey
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
644 nKey
= GetEntryKey( rString
, eLnge
);
645 if (nKey
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
647 rNewInserted
= PutEntry( rString
, rCheckPos
, rType
, nKey
, eLnge
);
650 SAL_WARN( "svl.numbers", "SvNumberFormatter::GetIndexPuttingAndConverting: bad format code string for specified locale");
651 nKey
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
655 if (nKey
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
657 nKey
= GetStandardIndex( eLnge
);
659 rType
= GetType( nKey
);
660 // Convert any (!) old "automatic" currency format to new fixed currency
662 if ((rType
& NUMBERFORMAT_CURRENCY
) != 0)
664 const SvNumberformat
* pFormat
= GetEntry( nKey
);
665 if (!pFormat
->HasNewCurrency())
669 DeleteEntry( nKey
); // don't leave trails of rubbish
670 rNewInserted
= false;
672 nKey
= GetStandardFormat( NUMBERFORMAT_CURRENCY
, eLnge
);
679 void SvNumberFormatter::DeleteEntry(sal_uInt32 nKey
)
681 delete aFTable
[nKey
];
685 bool SvNumberFormatter::Load( SvStream
& rStream
)
687 LanguageType eSysLang
= SvtSysLocale().GetLanguageTag().getLanguageType();
688 SvNumberFormatter
* pConverter
= NULL
;
690 ImpSvNumMultipleReadHeader
aHdr( rStream
);
693 SvNumberformat
* pEntry
;
695 sal_uInt16 nSysOnStore
, eLge
, eDummy
; // Dummy for compatible format
696 rStream
>> nSysOnStore
>> eLge
; // system language from document
698 SAL_WARN_IF( nVersion
< SV_NUMBERFORMATTER_VERSION_CALENDAR
, "svl.numbers", "SvNumberFormatter::Load: where does this unsupported old data come from?!?");
700 LanguageType eSaveSysLang
= (LanguageType
) nSysOnStore
;
701 LanguageType eLnge
= (LanguageType
) eLge
;
702 ImpChangeSysCL( eLnge
, true );
705 while (nPos
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
707 rStream
>> eDummy
>> eLge
;
708 eLnge
= (LanguageType
) eLge
;
709 ImpGenerateCL( eLnge
, true ); // create new standard formats if necessary
711 sal_uInt32 nOffset
= nPos
% SV_COUNTRY_LANGUAGE_OFFSET
; // relativIndex
712 bool bUserDefined
= (nOffset
> SV_MAX_ANZ_STANDARD_FORMATE
);
714 pEntry
= new SvNumberformat(*pFormatScanner
, eLnge
);
715 pEntry
->Load( rStream
, aHdr
, NULL
, *pStringScanner
);
718 bUserDefined
= (pEntry
->GetNewStandardDefined() > SV_NUMBERFORMATTER_VERSION
);
722 LanguageType eLoadSysLang
= (eLnge
== LANGUAGE_SYSTEM
? eSysLang
: eSaveSysLang
);
723 if ( eSaveSysLang
!= eLoadSysLang
)
725 // different SYSTEM locale
728 pConverter
= new SvNumberFormatter( m_xContext
, eSysLang
);
730 pEntry
->ConvertLanguage( *pConverter
, eSaveSysLang
, eLoadSysLang
, true );
733 if ( nOffset
== 0 ) // Standard/General format
735 SvNumberformat
* pEnt
= GetFormatEntry(nPos
);
738 pEnt
->SetLastInsertKey(pEntry
->GetLastInsertKey());
741 if (!aFTable
.insert(make_pair( nPos
, pEntry
)).second
)
743 SAL_WARN( "svl.numbers", "SvNumberFormatter::Load: dup position");
749 // as of SV_NUMBERFORMATTER_VERSION_YEAR2000
750 if ( nVersion
>= SV_NUMBERFORMATTER_VERSION_YEAR2000
)
753 if ( aHdr
.BytesLeft() >= sizeof(sal_uInt16
) )
757 if ( nVersion
< SV_NUMBERFORMATTER_VERSION_TWODIGITYEAR
&& nY2k
< 100 )
759 nY2k
+= 1901; // was before src513e: 29, now: 1930
771 // generate additional i18n standard formats for all used locales
772 LanguageType eOldLanguage
= ActLnge
;
773 NumberFormatCodeWrapper
aNumberFormatCode( m_xContext
,
774 GetLanguageTag().getLocale() );
775 std::vector
<sal_uInt16
> aList
;
776 GetUsedLanguages( aList
);
777 for ( std::vector
<sal_uInt16
>::const_iterator
it(aList
.begin()); it
!= aList
.end(); ++it
)
779 LanguageType eLang
= *it
;
781 sal_uInt32 CLOffset
= ImpGetCLOffset( eLang
);
782 ImpGenerateAdditionalFormats( CLOffset
, aNumberFormatCode
, true );
784 ChangeIntl( eOldLanguage
);
786 return rStream
.GetError() ? false : true;
789 bool SvNumberFormatter::Save( SvStream
& rStream
) const
791 ImpSvNumMultipleWriteHeader
aHdr( rStream
);
792 // As of 364i we store what SYSTEM locale really was, before it was hard
793 // coded LANGUAGE_SYSTEM.
794 rStream
<< (sal_uInt16
) SV_NUMBERFORMATTER_VERSION
;
795 rStream
<< (sal_uInt16
) SvtSysLocale().GetLanguageTag().getLanguageType() << (sal_uInt16
) IniLnge
;
797 const SvNumberFormatTable
* pTable
= &aFTable
;
798 SvNumberFormatTable::const_iterator it
= pTable
->begin();
799 while (it
!= pTable
->end())
801 SvNumberformat
* pEntry
= it
->second
;
802 // Stored are all marked user defined formats and for each active
803 // (selected) locale the Standard/General format and
804 // NewStandardDefined.
805 if ( pEntry
->GetUsed() || (pEntry
->GetType() & NUMBERFORMAT_DEFINED
) ||
806 pEntry
->GetNewStandardDefined() || (it
->first
% SV_COUNTRY_LANGUAGE_OFFSET
== 0) )
809 << (sal_uInt16
) LANGUAGE_SYSTEM
810 << (sal_uInt16
) pEntry
->GetLanguage();
811 pEntry
->Save(rStream
, aHdr
);
815 rStream
<< NUMBERFORMAT_ENTRY_NOT_FOUND
; // end marker
817 // as of SV_NUMBERFORMATTER_VERSION_YEAR2000
819 rStream
<< (sal_uInt16
) GetYear2000();
822 return rStream
.GetError() ? false : true;
825 void SvNumberFormatter::GetUsedLanguages( std::vector
<sal_uInt16
>& rList
)
829 sal_uInt32 nOffset
= 0;
830 while (nOffset
<= MaxCLOffset
)
832 SvNumberformat
* pFormat
= GetFormatEntry(nOffset
);
835 rList
.push_back( pFormat
->GetLanguage() );
837 nOffset
+= SV_COUNTRY_LANGUAGE_OFFSET
;
842 void SvNumberFormatter::FillKeywordTable( NfKeywordTable
& rKeywords
,
846 const NfKeywordTable
& rTable
= pFormatScanner
->GetKeywords();
847 for ( sal_uInt16 i
= 0; i
< NF_KEYWORD_ENTRIES_COUNT
; ++i
)
849 rKeywords
[i
] = rTable
[i
];
854 OUString
SvNumberFormatter::GetKeyword( LanguageType eLnge
, sal_uInt16 nIndex
)
857 const NfKeywordTable
& rTable
= pFormatScanner
->GetKeywords();
858 if ( nIndex
< NF_KEYWORD_ENTRIES_COUNT
)
860 return rTable
[nIndex
];
862 SAL_WARN( "svl.numbers", "GetKeyword: invalid index");
867 OUString
SvNumberFormatter::GetStandardName( LanguageType eLnge
)
870 return pFormatScanner
->GetStandardName();
874 sal_uInt32
SvNumberFormatter::ImpGetCLOffset(LanguageType eLnge
) const
876 sal_uInt32 nOffset
= 0;
877 while (nOffset
<= MaxCLOffset
)
879 const SvNumberformat
* pFormat
= GetFormatEntry(nOffset
);
880 if (pFormat
&& pFormat
->GetLanguage() == eLnge
)
884 nOffset
+= SV_COUNTRY_LANGUAGE_OFFSET
;
889 sal_uInt32
SvNumberFormatter::ImpIsEntry(const OUString
& rString
,
890 sal_uInt32 nCLOffset
,
893 sal_uInt32 res
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
894 SvNumberFormatTable::iterator it
= aFTable
.find( nCLOffset
);
895 while ( res
== NUMBERFORMAT_ENTRY_NOT_FOUND
&&
896 it
!= aFTable
.end() && it
->second
->GetLanguage() == eLnge
)
898 if ( rString
== it
->second
->GetFormatstring() )
911 SvNumberFormatTable
& SvNumberFormatter::GetFirstEntryTable(
916 short eTypetmp
= eType
;
917 if (eType
== NUMBERFORMAT_ALL
) // empty cell or don't care
923 SvNumberformat
* pFormat
= GetFormatEntry(FIndex
);
927 eType
= NUMBERFORMAT_ALL
;
932 rLnge
= pFormat
->GetLanguage();
933 eType
= pFormat
->GetType()&~NUMBERFORMAT_DEFINED
;
936 eType
= NUMBERFORMAT_DEFINED
;
939 else if (eType
== NUMBERFORMAT_DATETIME
)
942 eType
= NUMBERFORMAT_DATE
;
951 return GetEntryTable(eTypetmp
, FIndex
, rLnge
);
954 sal_uInt32
SvNumberFormatter::ImpGenerateCL( LanguageType eLnge
, bool bNoAdditionalFormats
)
957 sal_uInt32 CLOffset
= ImpGetCLOffset(ActLnge
);
958 if (CLOffset
> MaxCLOffset
)
960 // new CL combination
961 if (LocaleDataWrapper::areChecksEnabled())
963 const LanguageTag
& rLoadedLocale
= xLocaleData
->getLoadedLanguageTag();
964 if ( !rLoadedLocale
.equals( maLanguageTag
, true) )
966 OUString
aMsg("SvNumberFormatter::ImpGenerateCL: locales don't match:");
967 LocaleDataWrapper::outputCheckMessage( xLocaleData
->appendLocaleInfo( aMsg
));
969 // test XML locale data FormatElement entries
971 uno::Sequence
< i18n::FormatElement
> xSeq
= xLocaleData
->getAllFormats();
972 // A test for completeness of formatindex="0" ...
973 // formatindex="47" is not needed here since it is done in
974 // ImpGenerateFormats().
976 // Test for dupes of formatindex="..."
977 for ( sal_Int32 j
= 0; j
< xSeq
.getLength(); j
++ )
979 sal_Int16 nIdx
= xSeq
[j
].formatIndex
;
980 OUStringBuffer aDupes
;
981 for ( sal_Int32 i
= 0; i
< xSeq
.getLength(); i
++ )
983 if ( i
!= j
&& xSeq
[i
].formatIndex
== nIdx
)
985 aDupes
.append(OUString::number( i
));
987 aDupes
.append(xSeq
[i
].formatKey
);
988 aDupes
.append( ") ");
991 if ( !aDupes
.isEmpty() )
993 OUStringBuffer
aMsg(aDupes
.getLength() + xSeq
[j
].formatKey
.getLength() + 100);
994 aMsg
.append("XML locale data FormatElement formatindex dupe: ");
995 aMsg
.append(OUString::number(nIdx
));
996 aMsg
.append("\nFormatElements: ");
997 aMsg
.append(OUString::number( j
));
999 aMsg
.append( xSeq
[j
].formatKey
);
1001 aMsg
.append(aDupes
.makeStringAndClear());
1002 LocaleDataWrapper::outputCheckMessage( xLocaleData
->appendLocaleInfo( aMsg
.makeStringAndClear() ));
1008 MaxCLOffset
+= SV_COUNTRY_LANGUAGE_OFFSET
;
1009 ImpGenerateFormats( MaxCLOffset
, bNoAdditionalFormats
);
1010 CLOffset
= MaxCLOffset
;
1015 SvNumberFormatTable
& SvNumberFormatter::ChangeCL(short eType
,
1019 ImpGenerateCL(eLnge
);
1020 return GetEntryTable(eType
, FIndex
, ActLnge
);
1023 SvNumberFormatTable
& SvNumberFormatter::GetEntryTable(
1030 pFormatTable
->clear();
1034 pFormatTable
= new SvNumberFormatTable
;
1037 sal_uInt32 CLOffset
= ImpGetCLOffset(ActLnge
);
1039 // Might generate and insert a default format for the given type
1040 // (e.g. currency) => has to be done before collecting formats.
1041 sal_uInt32 nDefaultIndex
= GetStandardFormat( eType
, ActLnge
);
1043 SvNumberFormatTable::iterator it
= aFTable
.find( CLOffset
);
1045 if (eType
== NUMBERFORMAT_ALL
)
1047 while (it
!= aFTable
.end() && it
->second
->GetLanguage() == ActLnge
)
1048 { // copy all entries to output table
1049 (*pFormatTable
)[ it
->first
] = it
->second
;
1055 while (it
!= aFTable
.end() && it
->second
->GetLanguage() == ActLnge
)
1056 { // copy entries of queried type to output table
1057 if ((it
->second
->GetType()) & eType
)
1058 (*pFormatTable
)[ it
->first
] = it
->second
;
1062 if ( !pFormatTable
->empty() )
1063 { // select default if queried format doesn't exist or queried type or
1064 // language differ from existing format
1065 SvNumberformat
* pEntry
= GetFormatEntry(FIndex
);
1066 if ( !pEntry
|| !(pEntry
->GetType() & eType
) || pEntry
->GetLanguage() != ActLnge
)
1068 FIndex
= nDefaultIndex
;
1071 return *pFormatTable
;
1074 bool SvNumberFormatter::IsNumberFormat(const OUString
& sString
,
1075 sal_uInt32
& F_Index
,
1079 const SvNumberformat
* pFormat
= GetFormatEntry(F_Index
);
1082 ChangeIntl(IniLnge
);
1083 FType
= NUMBERFORMAT_NUMBER
;
1087 FType
= pFormat
->GetType() &~NUMBERFORMAT_DEFINED
;
1090 FType
= NUMBERFORMAT_DEFINED
;
1092 ChangeIntl(pFormat
->GetLanguage());
1096 short RType
= FType
;
1097 if (RType
== NUMBERFORMAT_TEXT
)
1099 res
= false; // type text preset => no conversion to number
1103 res
= pStringScanner
->IsNumberFormat(sString
, RType
, fOutNumber
, pFormat
);
1105 if (res
&& !IsCompatible(FType
, RType
)) // non-matching type
1109 case NUMBERFORMAT_DATE
:
1110 // Preserve ISO 8601 input.
1111 if (pStringScanner
->CanForceToIso8601( DMY
))
1113 F_Index
= GetFormatIndex( NF_DATE_DIN_YYYYMMDD
, ActLnge
);
1117 F_Index
= GetStandardFormat( RType
, ActLnge
);
1120 case NUMBERFORMAT_TIME
:
1121 if ( pStringScanner
->GetDecPos() )
1124 if ( pStringScanner
->GetAnzNums() > 3 || fOutNumber
< 0.0 )
1126 F_Index
= GetFormatIndex( NF_TIME_HH_MMSS00
, ActLnge
);
1130 F_Index
= GetFormatIndex( NF_TIME_MMSS00
, ActLnge
);
1133 else if ( fOutNumber
>= 1.0 || fOutNumber
< 0.0 )
1135 F_Index
= GetFormatIndex( NF_TIME_HH_MMSS
, ActLnge
);
1139 F_Index
= GetStandardFormat( RType
, ActLnge
);
1143 F_Index
= GetStandardFormat( RType
, ActLnge
);
1149 bool SvNumberFormatter::IsCompatible(short eOldType
,
1152 if (eOldType
== eNewType
)
1156 else if (eOldType
== NUMBERFORMAT_DEFINED
)
1164 case NUMBERFORMAT_NUMBER
:
1167 case NUMBERFORMAT_PERCENT
:
1168 case NUMBERFORMAT_CURRENCY
:
1169 case NUMBERFORMAT_SCIENTIFIC
:
1170 case NUMBERFORMAT_FRACTION
:
1171 // case NUMBERFORMAT_LOGICAL:
1172 case NUMBERFORMAT_DEFINED
:
1178 case NUMBERFORMAT_DATE
:
1181 case NUMBERFORMAT_DATETIME
:
1187 case NUMBERFORMAT_TIME
:
1190 case NUMBERFORMAT_DATETIME
:
1196 case NUMBERFORMAT_DATETIME
:
1199 case NUMBERFORMAT_TIME
:
1200 case NUMBERFORMAT_DATE
:
1213 sal_uInt32
SvNumberFormatter::ImpGetDefaultFormat( short nType
)
1215 sal_uInt32 CLOffset
= ImpGetCLOffset( ActLnge
);
1219 case NUMBERFORMAT_DATE
:
1220 nSearch
= CLOffset
+ ZF_STANDARD_DATE
;
1222 case NUMBERFORMAT_TIME
:
1223 nSearch
= CLOffset
+ ZF_STANDARD_TIME
;
1225 case NUMBERFORMAT_DATETIME
:
1226 nSearch
= CLOffset
+ ZF_STANDARD_DATETIME
;
1228 case NUMBERFORMAT_PERCENT
:
1229 nSearch
= CLOffset
+ ZF_STANDARD_PERCENT
;
1231 case NUMBERFORMAT_SCIENTIFIC
:
1232 nSearch
= CLOffset
+ ZF_STANDARD_SCIENTIFIC
;
1235 nSearch
= CLOffset
+ ZF_STANDARD
;
1238 DefaultFormatKeysMap::iterator it
= aDefaultFormatKeys
.find( nSearch
);
1239 sal_uInt32 nDefaultFormat
= (it
!= aDefaultFormatKeys
.end() ?
1240 it
->second
: NUMBERFORMAT_ENTRY_NOT_FOUND
);
1241 if ( nDefaultFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
1243 // look for a defined standard
1244 sal_uInt32 nStopKey
= CLOffset
+ SV_COUNTRY_LANGUAGE_OFFSET
;
1246 SvNumberFormatTable::iterator it2
= aFTable
.find( CLOffset
);
1247 while ( it2
!= aFTable
.end() && (nKey
= it2
->first
) >= CLOffset
&& nKey
< nStopKey
)
1249 const SvNumberformat
* pEntry
= it2
->second
;
1250 if ( pEntry
->IsStandard() && ((pEntry
->GetType() &
1251 ~NUMBERFORMAT_DEFINED
) == nType
) )
1253 nDefaultFormat
= nKey
;
1259 if ( nDefaultFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
1260 { // none found, use old fixed standards
1263 case NUMBERFORMAT_DATE
:
1264 nDefaultFormat
= CLOffset
+ ZF_STANDARD_DATE
;
1266 case NUMBERFORMAT_TIME
:
1267 nDefaultFormat
= CLOffset
+ ZF_STANDARD_TIME
+1;
1269 case NUMBERFORMAT_DATETIME
:
1270 nDefaultFormat
= CLOffset
+ ZF_STANDARD_DATETIME
;
1272 case NUMBERFORMAT_PERCENT
:
1273 nDefaultFormat
= CLOffset
+ ZF_STANDARD_PERCENT
+1;
1275 case NUMBERFORMAT_SCIENTIFIC
:
1276 nDefaultFormat
= CLOffset
+ ZF_STANDARD_SCIENTIFIC
;
1279 nDefaultFormat
= CLOffset
+ ZF_STANDARD
;
1282 aDefaultFormatKeys
[ nSearch
] = nDefaultFormat
;
1284 return nDefaultFormat
;
1288 sal_uInt32
SvNumberFormatter::GetStandardFormat( short eType
, LanguageType eLnge
)
1290 if (eLnge
== LANGUAGE_DONTKNOW
)
1294 sal_uInt32 CLOffset
= ImpGenerateCL(eLnge
);
1297 case NUMBERFORMAT_CURRENCY
:
1298 return ( eLnge
== LANGUAGE_SYSTEM
) ? ImpGetDefaultSystemCurrencyFormat() : ImpGetDefaultCurrencyFormat();
1299 case NUMBERFORMAT_DATE
:
1300 case NUMBERFORMAT_TIME
:
1301 case NUMBERFORMAT_DATETIME
:
1302 case NUMBERFORMAT_PERCENT
:
1303 case NUMBERFORMAT_SCIENTIFIC
:
1304 return ImpGetDefaultFormat( eType
);
1305 case NUMBERFORMAT_FRACTION
:
1306 return CLOffset
+ ZF_STANDARD_FRACTION
;
1307 case NUMBERFORMAT_LOGICAL
:
1308 return CLOffset
+ ZF_STANDARD_LOGICAL
;
1309 case NUMBERFORMAT_TEXT
:
1310 return CLOffset
+ ZF_STANDARD_TEXT
;
1311 case NUMBERFORMAT_ALL
:
1312 case NUMBERFORMAT_DEFINED
:
1313 case NUMBERFORMAT_NUMBER
:
1314 case NUMBERFORMAT_UNDEFINED
:
1316 return CLOffset
+ ZF_STANDARD
;
1320 bool SvNumberFormatter::IsSpecialStandardFormat( sal_uInt32 nFIndex
,
1321 LanguageType eLnge
)
1324 nFIndex
== GetFormatIndex( NF_TIME_MMSS00
, eLnge
) ||
1325 nFIndex
== GetFormatIndex( NF_TIME_HH_MMSS00
, eLnge
) ||
1326 nFIndex
== GetFormatIndex( NF_TIME_HH_MMSS
, eLnge
)
1330 sal_uInt32
SvNumberFormatter::GetStandardFormat( sal_uInt32 nFIndex
, short eType
,
1331 LanguageType eLnge
)
1333 if ( IsSpecialStandardFormat( nFIndex
, eLnge
) )
1336 return GetStandardFormat( eType
, eLnge
);
1339 sal_uInt32
SvNumberFormatter::GetStandardFormat( double fNumber
, sal_uInt32 nFIndex
,
1340 short eType
, LanguageType eLnge
)
1342 if ( IsSpecialStandardFormat( nFIndex
, eLnge
) )
1347 case NUMBERFORMAT_TIME
:
1350 if ( fNumber
< 0.0 )
1357 double fSeconds
= fNumber
* 86400;
1358 if ( floor( fSeconds
+ 0.5 ) * 100 != floor( fSeconds
* 100 + 0.5 ) )
1359 { // with 100th seconds
1360 if ( bSign
|| fSeconds
>= 3600 )
1361 return GetFormatIndex( NF_TIME_HH_MMSS00
, eLnge
);
1363 return GetFormatIndex( NF_TIME_MMSS00
, eLnge
);
1367 if ( bSign
|| fNumber
>= 1.0 )
1368 return GetFormatIndex( NF_TIME_HH_MMSS
, eLnge
);
1370 return GetStandardFormat( eType
, eLnge
);
1374 return GetStandardFormat( eType
, eLnge
);
1378 sal_uInt32
SvNumberFormatter::GetEditFormat( double fNumber
, sal_uInt32 nFIndex
,
1379 short eType
, LanguageType eLang
,
1380 SvNumberformat
* pFormat
)
1382 sal_uInt32 nKey
= nFIndex
;
1385 // #61619# always edit using 4-digit year
1386 case NUMBERFORMAT_DATE
:
1387 if (rtl::math::approxFloor( fNumber
) != fNumber
)
1388 nKey
= GetFormatIndex( NF_DATETIME_SYS_DDMMYYYY_HHMMSS
, eLang
);
1389 // fdo#34977 preserve time when editing even if only date was
1391 /* FIXME: in case an ISO 8601 format was used, editing should
1392 * also use such. Unfortunately we have no builtin combined
1393 * date+time ISO format defined. Needs also locale data work.
1397 // Preserve ISO 8601 format.
1398 if ( nFIndex
== GetFormatIndex( NF_DATE_DIN_YYYYMMDD
, eLang
) ||
1399 nFIndex
== GetFormatIndex( NF_DATE_DIN_YYMMDD
, eLang
) ||
1400 nFIndex
== GetFormatIndex( NF_DATE_DIN_MMDD
, eLang
) ||
1401 (pFormat
&& pFormat
->IsIso8601( 0 )))
1402 nKey
= GetFormatIndex( NF_DATE_DIN_YYYYMMDD
, eLang
);
1404 nKey
= GetFormatIndex( NF_DATE_SYS_DDMMYYYY
, eLang
);
1407 case NUMBERFORMAT_TIME
:
1408 if (fNumber
< 0.0 || fNumber
>= 1.0)
1410 /* XXX NOTE: this is a purely arbitrary value within the limits
1411 * of a signed 16-bit. 32k hours are 3.7 years ... or
1412 * 1903-09-26 if date. */
1413 if (fabs( fNumber
) * 24 < 0x7fff)
1414 nKey
= GetFormatIndex( NF_TIME_HH_MMSS
, eLang
);
1415 // Preserve duration, use [HH]:MM:SS instead of time.
1417 nKey
= GetFormatIndex( NF_DATETIME_SYS_DDMMYYYY_HHMMSS
, eLang
);
1418 // Assume that a large value is a datetime with only time
1422 nKey
= GetStandardFormat( fNumber
, nFIndex
, eType
, eLang
);
1424 case NUMBERFORMAT_DATETIME
:
1425 nKey
= GetFormatIndex( NF_DATETIME_SYS_DDMMYYYY_HHMMSS
, eLang
);
1426 /* FIXME: in case an ISO 8601 format was used, editing should
1427 * also use such. Unfortunately we have no builtin combined
1428 * date+time ISO format defined. Needs also locale data work. */
1431 nKey
= GetStandardFormat( fNumber
, nFIndex
, eType
, eLang
);
1436 void SvNumberFormatter::GetInputLineString(const double& fOutNumber
,
1438 OUString
& sOutString
)
1441 SvNumberformat
* pFormat
= GetFormatEntry( nFIndex
);
1444 pFormat
= GetFormatEntry(ZF_STANDARD
);
1447 LanguageType eLang
= pFormat
->GetLanguage();
1448 ChangeIntl( eLang
);
1450 short eType
= pFormat
->GetType() & ~NUMBERFORMAT_DEFINED
;
1453 eType
= NUMBERFORMAT_DEFINED
;
1456 sal_uInt16 nOldPrec
= pFormatScanner
->GetStandardPrec();
1457 bool bPrecChanged
= false;
1458 if (eType
== NUMBERFORMAT_NUMBER
||
1459 eType
== NUMBERFORMAT_PERCENT
||
1460 eType
== NUMBERFORMAT_CURRENCY
||
1461 eType
== NUMBERFORMAT_SCIENTIFIC
||
1462 eType
== NUMBERFORMAT_FRACTION
)
1464 if (eType
!= NUMBERFORMAT_PERCENT
) // special treatment of % later
1466 eType
= NUMBERFORMAT_NUMBER
;
1468 ChangeStandardPrec(INPUTSTRING_PRECISION
);
1469 bPrecChanged
= true;
1472 sal_uInt32 nKey
= GetEditFormat( fOutNumber
, nFIndex
, eType
, eLang
, pFormat
);
1473 if ( nKey
!= nFIndex
)
1475 pFormat
= GetFormatEntry( nKey
);
1479 if ( eType
== NUMBERFORMAT_TIME
&& pFormat
->GetFormatPrecision() )
1481 ChangeStandardPrec(INPUTSTRING_PRECISION
);
1482 bPrecChanged
= true;
1484 pFormat
->GetOutputString(fOutNumber
, sOutString
, &pColor
);
1488 ChangeStandardPrec(nOldPrec
);
1492 void SvNumberFormatter::GetOutputString(const OUString
& sString
,
1494 OUString
& sOutString
,
1496 bool bUseStarFormat
)
1498 SvNumberformat
* pFormat
= GetFormatEntry( nFIndex
);
1501 pFormat
= GetFormatEntry(ZF_STANDARD_TEXT
);
1503 if (!pFormat
->IsTextFormat() && !pFormat
->HasTextFormat())
1506 sOutString
= sString
;
1510 ChangeIntl(pFormat
->GetLanguage());
1511 if ( bUseStarFormat
)
1513 pFormat
->SetStarFormatSupport( true );
1515 pFormat
->GetOutputString(sString
, sOutString
, ppColor
);
1516 if ( bUseStarFormat
)
1518 pFormat
->SetStarFormatSupport( false );
1523 void SvNumberFormatter::GetOutputString(const double& fOutNumber
,
1525 OUString
& sOutString
,
1527 bool bUseStarFormat
)
1529 if (bNoZero
&& fOutNumber
== 0.0)
1531 sOutString
= OUString();
1534 SvNumberformat
* pFormat
= GetFormatEntry( nFIndex
);
1536 pFormat
= GetFormatEntry(ZF_STANDARD
);
1537 ChangeIntl(pFormat
->GetLanguage());
1538 if ( bUseStarFormat
)
1539 pFormat
->SetStarFormatSupport( true );
1540 pFormat
->GetOutputString(fOutNumber
, sOutString
, ppColor
);
1541 if ( bUseStarFormat
)
1542 pFormat
->SetStarFormatSupport( false );
1545 bool SvNumberFormatter::GetPreviewString(const OUString
& sFormatString
,
1546 double fPreviewNumber
,
1547 OUString
& sOutString
,
1550 bool bUseStarFormat
)
1552 if (sFormatString
.isEmpty()) // no empty string
1557 if (eLnge
== LANGUAGE_DONTKNOW
)
1561 ChangeIntl(eLnge
); // change locale if necessary
1563 sal_Int32 nCheckPos
= -1;
1564 OUString sTmpString
= sFormatString
;
1565 SvNumberformat
* p_Entry
= new SvNumberformat(sTmpString
,
1570 if (nCheckPos
== 0) // String ok
1572 sal_uInt32 CLOffset
= ImpGenerateCL(eLnge
); // create new standard formats if necessary
1573 nKey
= ImpIsEntry(p_Entry
->GetFormatstring(),CLOffset
, eLnge
);
1574 if (nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
) // already present
1576 GetOutputString(fPreviewNumber
, nKey
, sOutString
, ppColor
, bUseStarFormat
);
1580 if ( bUseStarFormat
)
1582 p_Entry
->SetStarFormatSupport( true );
1584 p_Entry
->GetOutputString(fPreviewNumber
, sOutString
, ppColor
);
1585 if ( bUseStarFormat
)
1587 p_Entry
->SetStarFormatSupport( false );
1600 bool SvNumberFormatter::GetPreviewStringGuess( const OUString
& sFormatString
,
1601 double fPreviewNumber
,
1602 OUString
& sOutString
,
1604 LanguageType eLnge
)
1606 if (sFormatString
.isEmpty()) // no empty string
1610 if (eLnge
== LANGUAGE_DONTKNOW
)
1614 ChangeIntl( eLnge
);
1616 bool bEnglish
= (eLnge
== LANGUAGE_ENGLISH_US
);
1618 OUString
aFormatStringUpper( pCharClass
->uppercase( sFormatString
) );
1619 sal_uInt32 nCLOffset
= ImpGenerateCL( eLnge
);
1620 sal_uInt32 nKey
= ImpIsEntry( aFormatStringUpper
, nCLOffset
, eLnge
);
1621 if ( nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
1623 // Zielformat vorhanden
1624 GetOutputString( fPreviewNumber
, nKey
, sOutString
, ppColor
);
1628 SvNumberformat
*pEntry
= NULL
;
1629 sal_Int32 nCheckPos
= -1;
1630 OUString sTmpString
;
1634 sTmpString
= sFormatString
;
1635 pEntry
= new SvNumberformat( sTmpString
, pFormatScanner
,
1636 pStringScanner
, nCheckPos
, eLnge
);
1640 nCLOffset
= ImpGenerateCL( LANGUAGE_ENGLISH_US
);
1641 nKey
= ImpIsEntry( aFormatStringUpper
, nCLOffset
, LANGUAGE_ENGLISH_US
);
1642 bool bEnglishFormat
= (nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
);
1644 // try english --> other bzw. english nach other konvertieren
1645 LanguageType eFormatLang
= LANGUAGE_ENGLISH_US
;
1646 pFormatScanner
->SetConvertMode( LANGUAGE_ENGLISH_US
, eLnge
);
1647 sTmpString
= sFormatString
;
1648 pEntry
= new SvNumberformat( sTmpString
, pFormatScanner
,
1649 pStringScanner
, nCheckPos
, eFormatLang
);
1650 pFormatScanner
->SetConvertMode( false );
1651 ChangeIntl( eLnge
);
1653 if ( !bEnglishFormat
)
1655 if ( !(nCheckPos
== 0) || xTransliteration
->isEqual( sFormatString
,
1656 pEntry
->GetFormatstring() ) )
1660 sTmpString
= sFormatString
;
1661 pEntry
= new SvNumberformat( sTmpString
, pFormatScanner
,
1662 pStringScanner
, nCheckPos
, eLnge
);
1667 sal_Int32 nCheckPos2
= -1;
1668 // try other --> english
1669 eFormatLang
= eLnge
;
1670 pFormatScanner
->SetConvertMode( eLnge
, LANGUAGE_ENGLISH_US
);
1671 sTmpString
= sFormatString
;
1672 SvNumberformat
* pEntry2
= new SvNumberformat( sTmpString
, pFormatScanner
,
1673 pStringScanner
, nCheckPos2
, eFormatLang
);
1674 pFormatScanner
->SetConvertMode( false );
1675 ChangeIntl( eLnge
);
1676 if ( nCheckPos2
== 0 && !xTransliteration
->isEqual( sFormatString
,
1677 pEntry2
->GetFormatstring() ) )
1681 sTmpString
= sFormatString
;
1682 pEntry
= new SvNumberformat( sTmpString
, pFormatScanner
,
1683 pStringScanner
, nCheckPos
, eLnge
);
1690 if (nCheckPos
== 0) // String ok
1692 ImpGenerateCL( eLnge
); // create new standard formats if necessary
1693 pEntry
->GetOutputString( fPreviewNumber
, sOutString
, ppColor
);
1701 bool SvNumberFormatter::GetPreviewString( const OUString
& sFormatString
,
1702 const OUString
& sPreviewString
,
1703 OUString
& sOutString
,
1705 LanguageType eLnge
)
1707 if (sFormatString
.isEmpty()) // no empty string
1712 if (eLnge
== LANGUAGE_DONTKNOW
)
1716 ChangeIntl(eLnge
); // switch if needed
1718 sal_Int32 nCheckPos
= -1;
1719 OUString sTmpString
= sFormatString
;
1720 SvNumberformat
* p_Entry
= new SvNumberformat( sTmpString
,
1725 if (nCheckPos
== 0) // String ok
1727 // May have to create standard formats for this locale.
1728 sal_uInt32 CLOffset
= ImpGenerateCL(eLnge
);
1729 nKey
= ImpIsEntry( p_Entry
->GetFormatstring(), CLOffset
, eLnge
);
1730 if (nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
) // already present
1732 GetOutputString( sPreviewString
, nKey
, sOutString
, ppColor
);
1736 // If the format is valid but not a text format and does not
1737 // include a text subformat, an empty string would result. Same as
1738 // in SvNumberFormatter::GetOutputString()
1739 if (p_Entry
->IsTextFormat() || p_Entry
->HasTextFormat())
1741 p_Entry
->GetOutputString( sPreviewString
, sOutString
, ppColor
);
1746 sOutString
= sPreviewString
;
1759 sal_uInt32
SvNumberFormatter::TestNewString(const OUString
& sFormatString
,
1762 if (sFormatString
.isEmpty()) // no empty string
1764 return NUMBERFORMAT_ENTRY_NOT_FOUND
;
1766 if (eLnge
== LANGUAGE_DONTKNOW
)
1770 ChangeIntl(eLnge
); // change locale if necessary
1773 sal_Int32 nCheckPos
= -1;
1774 OUString sTmpString
= sFormatString
;
1775 SvNumberformat
* pEntry
= new SvNumberformat(sTmpString
,
1780 if (nCheckPos
== 0) // String ok
1782 sal_uInt32 CLOffset
= ImpGenerateCL(eLnge
); // create new standard formats if necessary
1783 nRes
= ImpIsEntry(pEntry
->GetFormatstring(),CLOffset
, eLnge
);
1788 nRes
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
1794 SvNumberformat
* SvNumberFormatter::ImpInsertFormat( const ::com::sun::star::i18n::NumberFormatCode
& rCode
,
1795 sal_uInt32 nPos
, bool bAfterChangingSystemCL
,
1796 sal_Int16 nOrgIndex
)
1798 OUString
aCodeStr( rCode
.Code
);
1799 if ( rCode
.Index
< NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS
&&
1800 rCode
.Usage
== ::com::sun::star::i18n::KNumberFormatUsage::CURRENCY
&&
1801 rCode
.Index
!= NF_CURRENCY_1000DEC2_CCC
)
1802 { // strip surrounding [$...] on automatic currency
1803 if ( aCodeStr
.indexOf( "[$" ) >= 0)
1804 aCodeStr
= SvNumberformat::StripNewCurrencyDelimiters( aCodeStr
, false );
1807 if (LocaleDataWrapper::areChecksEnabled() &&
1808 rCode
.Index
!= NF_CURRENCY_1000DEC2_CCC
)
1810 OUString
aMsg(OUString("SvNumberFormatter::ImpInsertFormat: no [$...] on currency format code, index ") +
1811 OUString::number( rCode
.Index
) +
1814 LocaleDataWrapper::outputCheckMessage( xLocaleData
->appendLocaleInfo( aMsg
));
1818 sal_Int32 nCheckPos
= 0;
1819 OUString
sTempIn(aCodeStr
);
1820 SvNumberformat
* pFormat
= new SvNumberformat(sTempIn
,
1826 if ( !pFormat
|| !(nCheckPos
== 0) )
1828 if (LocaleDataWrapper::areChecksEnabled())
1830 OUString
aMsg( OUString("SvNumberFormatter::ImpInsertFormat: bad format code, index " ) +
1831 OUString::number( rCode
.Index
) +
1834 LocaleDataWrapper::outputCheckMessage( xLocaleData
->appendLocaleInfo( aMsg
));
1839 if ( rCode
.Index
>= NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS
)
1841 sal_uInt32 nCLOffset
= nPos
- (nPos
% SV_COUNTRY_LANGUAGE_OFFSET
);
1842 sal_uInt32 nKey
= ImpIsEntry( aCodeStr
, nCLOffset
, ActLnge
);
1843 if ( nKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
1845 // If bAfterChangingSystemCL there will definitely be some dups,
1847 if (LocaleDataWrapper::areChecksEnabled() && !bAfterChangingSystemCL
)
1849 // Test for duplicate indexes in locale data.
1850 switch ( nOrgIndex
)
1852 // These may be dups of integer versions for locales where
1853 // currencies have no decimals like Italian Lira.
1854 case NF_CURRENCY_1000DEC2
: // NF_CURRENCY_1000INT
1855 case NF_CURRENCY_1000DEC2_RED
: // NF_CURRENCY_1000INT_RED
1856 case NF_CURRENCY_1000DEC2_DASHED
: // NF_CURRENCY_1000INT_RED
1860 OUString
aMsg("SvNumberFormatter::ImpInsertFormat: dup format code, index ");
1861 aMsg
+= OUString::number( rCode
.Index
);
1864 LocaleDataWrapper::outputCheckMessage( xLocaleData
->appendLocaleInfo( aMsg
));
1871 else if ( nPos
- nCLOffset
>= SV_COUNTRY_LANGUAGE_OFFSET
)
1873 if (LocaleDataWrapper::areChecksEnabled())
1875 OUString
aMsg( "SvNumberFormatter::ImpInsertFormat: too many format codes, index ");
1876 aMsg
+= OUString::number( rCode
.Index
);
1879 LocaleDataWrapper::outputCheckMessage( xLocaleData
->appendLocaleInfo( aMsg
));
1885 if ( !aFTable
.insert( make_pair( nPos
, pFormat
) ).second
)
1887 if (LocaleDataWrapper::areChecksEnabled())
1889 OUString
aMsg( "ImpInsertFormat: can't insert number format key pos: ");
1890 aMsg
+= OUString::number( nPos
);
1891 aMsg
+= ", code index ";
1892 aMsg
+= OUString::number( rCode
.Index
);
1895 LocaleDataWrapper::outputCheckMessage( xLocaleData
->appendLocaleInfo( aMsg
));
1899 SAL_WARN( "svl.numbers", "SvNumberFormatter::ImpInsertFormat: dup position");
1904 if ( rCode
.Default
)
1905 pFormat
->SetStandard();
1906 if ( !rCode
.DefaultName
.isEmpty() )
1907 pFormat
->SetComment( rCode
.DefaultName
);
1911 SvNumberformat
* SvNumberFormatter::ImpInsertNewStandardFormat(
1912 const ::com::sun::star::i18n::NumberFormatCode
& rCode
,
1913 sal_uInt32 nPos
, sal_uInt16 nVersion
, bool bAfterChangingSystemCL
,
1914 sal_Int16 nOrgIndex
)
1916 SvNumberformat
* pNewFormat
= ImpInsertFormat( rCode
, nPos
,
1917 bAfterChangingSystemCL
, nOrgIndex
);
1919 pNewFormat
->SetNewStandardDefined( nVersion
);
1920 // so that it gets saved, displayed properly, and converted by old versions
1924 void SvNumberFormatter::GetFormatSpecialInfo(sal_uInt32 nFormat
,
1927 sal_uInt16
& nPrecision
,
1928 sal_uInt16
& nAnzLeading
)
1931 SvNumberformat
* pFormat
= GetFormatEntry( nFormat
);
1933 pFormat
->GetFormatSpecialInfo(bThousand
, IsRed
,
1934 nPrecision
, nAnzLeading
);
1939 nPrecision
= pFormatScanner
->GetStandardPrec();
1944 sal_uInt16
SvNumberFormatter::GetFormatPrecision( sal_uInt32 nFormat
) const
1946 const SvNumberformat
* pFormat
= GetFormatEntry( nFormat
);
1948 return pFormat
->GetFormatPrecision();
1950 return pFormatScanner
->GetStandardPrec();
1954 OUString
SvNumberFormatter::GetFormatDecimalSep( sal_uInt32 nFormat
) const
1956 const SvNumberformat
* pFormat
= GetFormatEntry(nFormat
);
1957 if ( !pFormat
|| pFormat
->GetLanguage() == ActLnge
)
1959 return GetNumDecimalSep();
1962 LanguageType eSaveLang
= xLocaleData
.getCurrentLanguage();
1963 if ( pFormat
->GetLanguage() == eSaveLang
)
1965 aRet
= xLocaleData
->getNumDecimalSep();
1969 LanguageTag
aSaveLocale( xLocaleData
->getLanguageTag() );
1970 ((SvNumberFormatter
*)this)->xLocaleData
.changeLocale( LanguageTag( pFormat
->GetLanguage()) );
1971 aRet
= xLocaleData
->getNumDecimalSep();
1972 ((SvNumberFormatter
*)this)->xLocaleData
.changeLocale( aSaveLocale
);
1978 sal_uInt32
SvNumberFormatter::GetFormatSpecialInfo( const OUString
& rFormatString
,
1979 bool& bThousand
, bool& IsRed
, sal_uInt16
& nPrecision
,
1980 sal_uInt16
& nAnzLeading
, LanguageType eLnge
)
1983 if (eLnge
== LANGUAGE_DONTKNOW
)
1987 ChangeIntl(eLnge
); // change locale if necessary
1989 OUString
aTmpStr( rFormatString
);
1990 sal_Int32 nCheckPos
= 0;
1991 SvNumberformat
* pFormat
= new SvNumberformat( aTmpStr
, pFormatScanner
,
1992 pStringScanner
, nCheckPos
, eLnge
);
1993 if ( nCheckPos
== 0 )
1995 pFormat
->GetFormatSpecialInfo( bThousand
, IsRed
, nPrecision
, nAnzLeading
);
2001 nPrecision
= pFormatScanner
->GetStandardPrec();
2009 inline sal_uInt32
SetIndexTable( NfIndexTableOffset nTabOff
, sal_uInt32 nIndOff
)
2011 osl::MutexGuard
aGuard(&theIndexTable
.maMtx
);
2013 if (!theIndexTable
.mbInitialized
)
2015 DBG_ASSERT(theIndexTable
.maData
[nTabOff
] == NUMBERFORMAT_ENTRY_NOT_FOUND
,
2016 "SetIndexTable: theIndexTable[nTabOff] already occupied" );
2017 theIndexTable
.maData
[nTabOff
] = nIndOff
;
2023 sal_Int32
SvNumberFormatter::ImpGetFormatCodeIndex(
2024 ::com::sun::star::uno::Sequence
< ::com::sun::star::i18n::NumberFormatCode
>& rSeq
,
2025 const NfIndexTableOffset nTabOff
)
2027 const sal_Int32 nLen
= rSeq
.getLength();
2028 for ( sal_Int32 j
=0; j
<nLen
; j
++ )
2030 if ( rSeq
[j
].Index
== nTabOff
)
2033 if (LocaleDataWrapper::areChecksEnabled() && (nTabOff
< NF_CURRENCY_START
2034 || NF_CURRENCY_END
< nTabOff
|| nTabOff
== NF_CURRENCY_1000INT
2035 || nTabOff
== NF_CURRENCY_1000INT_RED
2036 || nTabOff
== NF_CURRENCY_1000DEC2_CCC
))
2037 { // currency entries with decimals might not exist, e.g. Italian Lira
2038 OUString
aMsg( "SvNumberFormatter::ImpGetFormatCodeIndex: not found: " );
2039 aMsg
+= OUString::number( nTabOff
);
2040 LocaleDataWrapper::outputCheckMessage( xLocaleData
->appendLocaleInfo(aMsg
));
2045 // look for a preset default
2046 for ( j
=0; j
<nLen
; j
++ )
2048 if ( rSeq
[j
].Default
)
2051 // currencies are special, not all format codes must exist, but all
2052 // builtin number format key index positions must have a format assigned
2053 if ( NF_CURRENCY_START
<= nTabOff
&& nTabOff
<= NF_CURRENCY_END
)
2055 // look for a format with decimals
2056 for ( j
=0; j
<nLen
; j
++ )
2058 if ( rSeq
[j
].Index
== NF_CURRENCY_1000DEC2
)
2061 // last resort: look for a format without decimals
2062 for ( j
=0; j
<nLen
; j
++ )
2064 if ( rSeq
[j
].Index
== NF_CURRENCY_1000INT
)
2070 { // we need at least _some_ format
2072 rSeq
[0] = ::com::sun::star::i18n::NumberFormatCode();
2073 rSeq
[0].Code
= OUStringBuffer().
2075 append(GetNumDecimalSep()).
2076 append("############").
2077 makeStringAndClear();
2083 sal_Int32
SvNumberFormatter::ImpAdjustFormatCodeDefault(
2084 ::com::sun::star::i18n::NumberFormatCode
* pFormatArr
,
2085 sal_Int32 nCnt
, bool bCheckCorrectness
)
2087 using namespace ::com::sun::star
;
2091 if (bCheckCorrectness
&& LocaleDataWrapper::areChecksEnabled())
2093 // check the locale data for correctness
2095 sal_Int32 nElem
, nShort
, nMedium
, nLong
, nShortDef
, nMediumDef
, nLongDef
;
2096 nShort
= nMedium
= nLong
= nShortDef
= nMediumDef
= nLongDef
= -1;
2097 for ( nElem
= 0; nElem
< nCnt
; nElem
++ )
2099 switch ( pFormatArr
[nElem
].Type
)
2101 case i18n::KNumberFormatType::SHORT
:
2104 case i18n::KNumberFormatType::MEDIUM
:
2107 case i18n::KNumberFormatType::LONG
:
2111 aMsg
.append("unknown type");
2113 if ( pFormatArr
[nElem
].Default
)
2115 switch ( pFormatArr
[nElem
].Type
)
2117 case i18n::KNumberFormatType::SHORT
:
2118 if ( nShortDef
!= -1 )
2119 aMsg
.append("dupe short type default");
2122 case i18n::KNumberFormatType::MEDIUM
:
2123 if ( nMediumDef
!= -1 )
2124 aMsg
.append("dupe medium type default");
2127 case i18n::KNumberFormatType::LONG
:
2128 if ( nLongDef
!= -1 )
2129 aMsg
.append("dupe long type default");
2134 if (!aMsg
.isEmpty())
2136 aMsg
.insert(0, "SvNumberFormatter::ImpAdjustFormatCodeDefault: ");
2137 aMsg
.append("\nXML locale data FormatElement formatindex: ");
2138 aMsg
.append(static_cast<sal_Int32
>(pFormatArr
[nElem
].Index
));
2139 OUString
aUMsg(OStringToOUString(aMsg
.makeStringAndClear(),
2140 RTL_TEXTENCODING_ASCII_US
));
2141 LocaleDataWrapper::outputCheckMessage(xLocaleData
->appendLocaleInfo(aUMsg
));
2144 if ( nShort
!= -1 && nShortDef
== -1 )
2145 aMsg
.append("no short type default ");
2146 if ( nMedium
!= -1 && nMediumDef
== -1 )
2147 aMsg
.append("no medium type default ");
2148 if ( nLong
!= -1 && nLongDef
== -1 )
2149 aMsg
.append("no long type default ");
2150 if (!aMsg
.isEmpty())
2152 aMsg
.insert(0, "SvNumberFormatter::ImpAdjustFormatCodeDefault: ");
2153 aMsg
.append("\nXML locale data FormatElement group of: ");
2154 OUString
aUMsg(OStringToOUString(aMsg
.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US
));
2155 LocaleDataWrapper::outputCheckMessage(
2156 xLocaleData
->appendLocaleInfo(aUMsg
+ pFormatArr
[0].NameID
));
2159 // find the default (medium preferred, then long) and reset all other defaults
2160 sal_Int32 nElem
, nDef
, nMedium
;
2161 nDef
= nMedium
= -1;
2162 for ( nElem
= 0; nElem
< nCnt
; nElem
++ )
2164 if ( pFormatArr
[nElem
].Default
)
2166 switch ( pFormatArr
[nElem
].Type
)
2168 case i18n::KNumberFormatType::MEDIUM
:
2169 nDef
= nMedium
= nElem
;
2171 case i18n::KNumberFormatType::LONG
:
2172 if ( nMedium
== -1 )
2178 pFormatArr
[nElem
].Default
= false;
2184 pFormatArr
[nDef
].Default
= true;
2188 SvNumberformat
* SvNumberFormatter::GetFormatEntry( sal_uInt32 nKey
)
2190 SvNumberFormatTable::iterator it
= aFTable
.find( nKey
);
2191 if (it
!= aFTable
.end())
2196 const SvNumberformat
* SvNumberFormatter::GetEntry( sal_uInt32 nKey
) const
2198 SvNumberFormatTable::const_iterator it
= aFTable
.find( nKey
);
2199 if (it
!= aFTable
.end())
2204 void SvNumberFormatter::ImpGenerateFormats( sal_uInt32 CLOffset
, bool bNoAdditionalFormats
)
2206 using namespace ::com::sun::star
;
2209 osl::MutexGuard
aGuard(&theIndexTable
.maMtx
);
2210 if (!theIndexTable
.mbInitialized
)
2212 for ( sal_uInt16 j
=0; j
<NF_INDEX_TABLE_ENTRIES
; j
++ )
2214 theIndexTable
.maData
[j
] = NUMBERFORMAT_ENTRY_NOT_FOUND
;
2219 bool bOldConvertMode
= pFormatScanner
->GetConvertMode();
2220 if (bOldConvertMode
)
2222 pFormatScanner
->SetConvertMode(false); // switch off for this function
2225 NumberFormatCodeWrapper
aNumberFormatCode( m_xContext
,
2226 GetLanguageTag().getLocale() );
2227 SvNumberformat
* pNewFormat
= NULL
;
2231 // Counter for additional builtin formats not fitting into the first 10
2232 // of a category (TLOT:=The Legacy Of Templin), altogether about 20 formats.
2233 // Has to be incremented on each ImpInsertNewStandardformat, new formats
2234 // must be appended, not inserted!
2235 sal_uInt16 nNewExtended
= ZF_STANDARD_NEWEXTENDED
;
2238 uno::Sequence
< i18n::NumberFormatCode
> aFormatSeq
=
2239 aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::FIXED_NUMBER
);
2240 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2243 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_STANDARD
);
2244 SvNumberformat
* pStdFormat
= ImpInsertFormat( aFormatSeq
[nIdx
],
2245 CLOffset
+ SetIndexTable( NF_NUMBER_STANDARD
, ZF_STANDARD
));
2248 // This is _the_ standard format.
2249 if (LocaleDataWrapper::areChecksEnabled() && pStdFormat
->GetType() != NUMBERFORMAT_NUMBER
)
2251 LocaleDataWrapper::outputCheckMessage( xLocaleData
->
2252 appendLocaleInfo( "SvNumberFormatter::ImpGenerateFormats: General format not NUMBER"));
2254 pStdFormat
->SetType( NUMBERFORMAT_NUMBER
);
2255 pStdFormat
->SetStandard();
2256 pStdFormat
->SetLastInsertKey( SV_MAX_ANZ_STANDARD_FORMATE
);
2260 if (LocaleDataWrapper::areChecksEnabled())
2262 LocaleDataWrapper::outputCheckMessage( xLocaleData
->
2263 appendLocaleInfo( "SvNumberFormatter::ImpGenerateFormats: General format not insertable, nothing will work"));
2268 OUString aFormatCode
= pFormatScanner
->GetBooleanString();
2269 sal_Int32 nCheckPos
= 0;
2271 pNewFormat
= new SvNumberformat( aFormatCode
, pFormatScanner
,
2272 pStringScanner
, nCheckPos
, ActLnge
);
2273 pNewFormat
->SetType(NUMBERFORMAT_LOGICAL
);
2274 pNewFormat
->SetStandard();
2275 if ( !aFTable
.insert(make_pair(
2276 CLOffset
+ SetIndexTable( NF_BOOLEAN
, ZF_STANDARD_LOGICAL
),
2277 pNewFormat
)).second
)
2279 SAL_WARN( "svl.numbers", "SvNumberFormatter::ImpGenerateFormats: dup position Boolean");
2285 pNewFormat
= new SvNumberformat( aFormatCode
, pFormatScanner
,
2286 pStringScanner
, nCheckPos
, ActLnge
);
2287 pNewFormat
->SetType(NUMBERFORMAT_TEXT
);
2288 pNewFormat
->SetStandard();
2289 if ( !aFTable
.insert(make_pair(
2290 CLOffset
+ SetIndexTable( NF_TEXT
, ZF_STANDARD_TEXT
),
2291 pNewFormat
)).second
)
2293 SAL_WARN( "svl.numbers", "SvNumberFormatter::ImpGenerateFormats: dup position Text");
2300 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_INT
);
2301 ImpInsertFormat( aFormatSeq
[nIdx
],
2302 CLOffset
+ SetIndexTable( NF_NUMBER_INT
, ZF_STANDARD
+1 ));
2305 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_DEC2
);
2306 ImpInsertFormat( aFormatSeq
[nIdx
],
2307 CLOffset
+ SetIndexTable( NF_NUMBER_DEC2
, ZF_STANDARD
+2 ));
2310 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_1000INT
);
2311 ImpInsertFormat( aFormatSeq
[nIdx
],
2312 CLOffset
+ SetIndexTable( NF_NUMBER_1000INT
, ZF_STANDARD
+3 ));
2315 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_1000DEC2
);
2316 ImpInsertFormat( aFormatSeq
[nIdx
],
2317 CLOffset
+ SetIndexTable( NF_NUMBER_1000DEC2
, ZF_STANDARD
+4 ));
2319 // #.##0,00 System country/language dependent since number formatter version 6
2320 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_NUMBER_SYSTEM
);
2321 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2322 CLOffset
+ SetIndexTable( NF_NUMBER_SYSTEM
, ZF_STANDARD
+5 ),
2323 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2327 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::PERCENT_NUMBER
);
2328 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2331 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_PERCENT_INT
);
2332 ImpInsertFormat( aFormatSeq
[nIdx
],
2333 CLOffset
+ SetIndexTable( NF_PERCENT_INT
, ZF_STANDARD_PERCENT
));
2336 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_PERCENT_DEC2
);
2337 ImpInsertFormat( aFormatSeq
[nIdx
],
2338 CLOffset
+ SetIndexTable( NF_PERCENT_DEC2
, ZF_STANDARD_PERCENT
+1 ));
2342 // Currency. NO default standard option! Default is determined of locale
2343 // data default currency and format is generated if needed.
2344 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::CURRENCY
);
2345 if (LocaleDataWrapper::areChecksEnabled())
2347 // though no default desired here, test for correctness of locale data
2348 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2352 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000INT
);
2353 bDefault
= aFormatSeq
[nIdx
].Default
;
2354 aFormatSeq
[nIdx
].Default
= false;
2355 ImpInsertFormat( aFormatSeq
[nIdx
],
2356 CLOffset
+ SetIndexTable( NF_CURRENCY_1000INT
, ZF_STANDARD_CURRENCY
));
2357 aFormatSeq
[nIdx
].Default
= bDefault
;
2360 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000DEC2
);
2361 bDefault
= aFormatSeq
[nIdx
].Default
;
2362 aFormatSeq
[nIdx
].Default
= false;
2363 ImpInsertFormat( aFormatSeq
[nIdx
],
2364 CLOffset
+ SetIndexTable( NF_CURRENCY_1000DEC2
, ZF_STANDARD_CURRENCY
+1 ));
2365 aFormatSeq
[nIdx
].Default
= bDefault
;
2367 // #,##0 negative red
2368 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000INT_RED
);
2369 bDefault
= aFormatSeq
[nIdx
].Default
;
2370 aFormatSeq
[nIdx
].Default
= false;
2371 ImpInsertFormat( aFormatSeq
[nIdx
],
2372 CLOffset
+ SetIndexTable( NF_CURRENCY_1000INT_RED
, ZF_STANDARD_CURRENCY
+2 ));
2373 aFormatSeq
[nIdx
].Default
= bDefault
;
2375 // #,##0.00 negative red
2376 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000DEC2_RED
);
2377 bDefault
= aFormatSeq
[nIdx
].Default
;
2378 aFormatSeq
[nIdx
].Default
= false;
2379 ImpInsertFormat( aFormatSeq
[nIdx
],
2380 CLOffset
+ SetIndexTable( NF_CURRENCY_1000DEC2_RED
, ZF_STANDARD_CURRENCY
+3 ));
2381 aFormatSeq
[nIdx
].Default
= bDefault
;
2383 // #,##0.00 USD since number formatter version 3
2384 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000DEC2_CCC
);
2385 bDefault
= aFormatSeq
[nIdx
].Default
;
2386 aFormatSeq
[nIdx
].Default
= false;
2387 pNewFormat
= ImpInsertFormat( aFormatSeq
[nIdx
],
2388 CLOffset
+ SetIndexTable( NF_CURRENCY_1000DEC2_CCC
, ZF_STANDARD_CURRENCY
+4 ));
2390 pNewFormat
->SetUsed(true); // must be saved for older versions
2391 aFormatSeq
[nIdx
].Default
= bDefault
;
2393 // #.##0,-- since number formatter version 6
2394 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_CURRENCY_1000DEC2_DASHED
);
2395 bDefault
= aFormatSeq
[nIdx
].Default
;
2396 aFormatSeq
[nIdx
].Default
= false;
2397 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2398 CLOffset
+ SetIndexTable( NF_CURRENCY_1000DEC2_DASHED
, ZF_STANDARD_CURRENCY
+5 ),
2399 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2400 aFormatSeq
[nIdx
].Default
= bDefault
;
2405 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::DATE
);
2406 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2409 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYSTEM_SHORT
);
2410 ImpInsertFormat( aFormatSeq
[nIdx
],
2411 CLOffset
+ SetIndexTable( NF_DATE_SYSTEM_SHORT
, ZF_STANDARD_DATE
));
2414 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DEF_NNDDMMMYY
);
2415 ImpInsertFormat( aFormatSeq
[nIdx
],
2416 CLOffset
+ SetIndexTable( NF_DATE_DEF_NNDDMMMYY
, ZF_STANDARD_DATE
+1 ));
2418 // DD.MM.YY def/System
2419 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_MMYY
);
2420 ImpInsertFormat( aFormatSeq
[nIdx
],
2421 CLOffset
+ SetIndexTable( NF_DATE_SYS_MMYY
, ZF_STANDARD_DATE
+2 ));
2424 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DDMMM
);
2425 ImpInsertFormat( aFormatSeq
[nIdx
],
2426 CLOffset
+ SetIndexTable( NF_DATE_SYS_DDMMM
, ZF_STANDARD_DATE
+3 ));
2429 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_MMMM
);
2430 ImpInsertFormat( aFormatSeq
[nIdx
],
2431 CLOffset
+ SetIndexTable( NF_DATE_MMMM
, ZF_STANDARD_DATE
+4 ));
2434 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_QQJJ
);
2435 ImpInsertFormat( aFormatSeq
[nIdx
],
2436 CLOffset
+ SetIndexTable( NF_DATE_QQJJ
, ZF_STANDARD_DATE
+5 ));
2438 // DD.MM.YYYY since number formatter version 2, was DD.MM.[YY]YY
2439 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DDMMYYYY
);
2440 pNewFormat
= ImpInsertFormat( aFormatSeq
[nIdx
],
2441 CLOffset
+ SetIndexTable( NF_DATE_SYS_DDMMYYYY
, ZF_STANDARD_DATE
+6 ));
2444 pNewFormat
->SetUsed(true); // must be saved for older versions
2446 // DD.MM.YY def/System, since number formatter version 6
2447 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DDMMYY
);
2448 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2449 CLOffset
+ SetIndexTable( NF_DATE_SYS_DDMMYY
, ZF_STANDARD_DATE
+7 ),
2450 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2452 // NNN, D. MMMM YYYY System
2453 // Long day of week: "NNNN" instead of "NNN," because of compatibility
2454 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYSTEM_LONG
);
2455 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2456 CLOffset
+ SetIndexTable( NF_DATE_SYSTEM_LONG
, ZF_STANDARD_DATE
+8 ),
2457 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2459 // Hard coded but system (regional settings) delimiters dependent long date formats
2460 // since numberformatter version 6
2462 // D. MMM YY def/System
2463 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DMMMYY
);
2464 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2465 CLOffset
+ SetIndexTable( NF_DATE_SYS_DMMMYY
, ZF_STANDARD_DATE
+9 ),
2466 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2468 //! Unfortunally TLOT intended only 10 builtin formats per category, more
2469 //! would overwrite the next category (ZF_STANDARD_TIME) :-((
2470 //! Therefore they are inserted with nNewExtended++ (which is also limited)
2472 // D. MMM YYYY def/System
2473 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DMMMYYYY
);
2474 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2475 CLOffset
+ SetIndexTable( NF_DATE_SYS_DMMMYYYY
, nNewExtended
++ ),
2476 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2478 // D. MMMM YYYY def/System
2479 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_DMMMMYYYY
);
2480 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2481 CLOffset
+ SetIndexTable( NF_DATE_SYS_DMMMMYYYY
, nNewExtended
++ ),
2482 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2484 // NN, D. MMM YY def/System
2485 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_NNDMMMYY
);
2486 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2487 CLOffset
+ SetIndexTable( NF_DATE_SYS_NNDMMMYY
, nNewExtended
++ ),
2488 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2490 // NN, D. MMMM YYYY def/System
2491 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_NNDMMMMYYYY
);
2492 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2493 CLOffset
+ SetIndexTable( NF_DATE_SYS_NNDMMMMYYYY
, nNewExtended
++ ),
2494 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2496 // NNN, D. MMMM YYYY def/System
2497 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_SYS_NNNNDMMMMYYYY
);
2498 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2499 CLOffset
+ SetIndexTable( NF_DATE_SYS_NNNNDMMMMYYYY
, nNewExtended
++ ),
2500 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2502 // Hard coded DIN (Deutsche Industrie Norm) and EN (European Norm) date formats
2504 // D. MMM. YYYY DIN/EN
2505 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DIN_DMMMYYYY
);
2506 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2507 CLOffset
+ SetIndexTable( NF_DATE_DIN_DMMMYYYY
, nNewExtended
++ ),
2508 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2510 // D. MMMM YYYY DIN/EN
2511 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DIN_DMMMMYYYY
);
2512 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2513 CLOffset
+ SetIndexTable( NF_DATE_DIN_DMMMMYYYY
, nNewExtended
++ ),
2514 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2517 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DIN_MMDD
);
2518 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2519 CLOffset
+ SetIndexTable( NF_DATE_DIN_MMDD
, nNewExtended
++ ),
2520 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2523 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DIN_YYMMDD
);
2524 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2525 CLOffset
+ SetIndexTable( NF_DATE_DIN_YYMMDD
, nNewExtended
++ ),
2526 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2528 // YYYY-MM-DD DIN/EN
2529 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATE_DIN_YYYYMMDD
);
2530 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2531 CLOffset
+ SetIndexTable( NF_DATE_DIN_YYYYMMDD
, nNewExtended
++ ),
2532 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD
);
2537 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::TIME
);
2538 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2541 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HHMM
);
2542 ImpInsertFormat( aFormatSeq
[nIdx
],
2543 CLOffset
+ SetIndexTable( NF_TIME_HHMM
, ZF_STANDARD_TIME
));
2546 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HHMMSS
);
2547 ImpInsertFormat( aFormatSeq
[nIdx
],
2548 CLOffset
+ SetIndexTable( NF_TIME_HHMMSS
, ZF_STANDARD_TIME
+1 ));
2551 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HHMMAMPM
);
2552 ImpInsertFormat( aFormatSeq
[nIdx
],
2553 CLOffset
+ SetIndexTable( NF_TIME_HHMMAMPM
, ZF_STANDARD_TIME
+2 ));
2556 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HHMMSSAMPM
);
2557 ImpInsertFormat( aFormatSeq
[nIdx
],
2558 CLOffset
+ SetIndexTable( NF_TIME_HHMMSSAMPM
, ZF_STANDARD_TIME
+3 ));
2561 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HH_MMSS
);
2562 ImpInsertFormat( aFormatSeq
[nIdx
],
2563 CLOffset
+ SetIndexTable( NF_TIME_HH_MMSS
, ZF_STANDARD_TIME
+4 ));
2566 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_MMSS00
);
2567 ImpInsertFormat( aFormatSeq
[nIdx
],
2568 CLOffset
+ SetIndexTable( NF_TIME_MMSS00
, ZF_STANDARD_TIME
+5 ));
2571 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_TIME_HH_MMSS00
);
2572 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2573 CLOffset
+ SetIndexTable( NF_TIME_HH_MMSS00
, ZF_STANDARD_TIME
+6 ),
2574 SV_NUMBERFORMATTER_VERSION_NF_TIME_HH_MMSS00
);
2579 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::DATE_TIME
);
2580 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2582 // DD.MM.YY HH:MM System
2583 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATETIME_SYSTEM_SHORT_HHMM
);
2584 ImpInsertFormat( aFormatSeq
[nIdx
],
2585 CLOffset
+ SetIndexTable( NF_DATETIME_SYSTEM_SHORT_HHMM
, ZF_STANDARD_DATETIME
));
2587 // DD.MM.YYYY HH:MM:SS System
2588 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_DATETIME_SYS_DDMMYYYY_HHMMSS
);
2589 ImpInsertNewStandardFormat( aFormatSeq
[nIdx
],
2590 CLOffset
+ SetIndexTable( NF_DATETIME_SYS_DDMMYYYY_HHMMSS
, ZF_STANDARD_DATETIME
+1 ),
2591 SV_NUMBERFORMATTER_VERSION_NF_DATETIME_SYS_DDMMYYYY_HHMMSS
);
2595 // Scientific number
2596 aFormatSeq
= aNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::SCIENTIFIC_NUMBER
);
2597 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), aFormatSeq
.getLength() );
2600 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_SCIENTIFIC_000E000
);
2601 ImpInsertFormat( aFormatSeq
[nIdx
],
2602 CLOffset
+ SetIndexTable( NF_SCIENTIFIC_000E000
, ZF_STANDARD_SCIENTIFIC
));
2605 nIdx
= ImpGetFormatCodeIndex( aFormatSeq
, NF_SCIENTIFIC_000E00
);
2606 ImpInsertFormat( aFormatSeq
[nIdx
],
2607 CLOffset
+ SetIndexTable( NF_SCIENTIFIC_000E00
, ZF_STANDARD_SCIENTIFIC
+1 ));
2611 // Fraction number (no default option)
2612 i18n::NumberFormatCode aSingleFormatCode
;
2613 aSingleFormatCode
.Usage
= i18n::KNumberFormatUsage::FRACTION_NUMBER
;
2616 aSingleFormatCode
.Code
= "# ?/?";
2617 ImpInsertFormat( aSingleFormatCode
,
2618 CLOffset
+ SetIndexTable( NF_FRACTION_1
, ZF_STANDARD_FRACTION
));
2621 //! "??/" would be interpreted by the compiler as a trigraph for '\'
2622 aSingleFormatCode
.Code
= "# ?\?/?\?";
2623 ImpInsertFormat( aSingleFormatCode
,
2624 CLOffset
+ SetIndexTable( NF_FRACTION_2
, ZF_STANDARD_FRACTION
+1 ));
2627 aSingleFormatCode
.Code
= "# ?/4";
2628 ImpInsertNewStandardFormat( aSingleFormatCode
,
2629 CLOffset
+ SetIndexTable( NF_FRACTION_3
, ZF_STANDARD_FRACTION
+2 ),
2630 SV_NUMBERFORMATTER_VERSION_FIXED_FRACTION
);
2633 aSingleFormatCode
.Code
= "# ?\?/100";
2634 ImpInsertNewStandardFormat( aSingleFormatCode
,
2635 CLOffset
+ SetIndexTable( NF_FRACTION_4
, ZF_STANDARD_FRACTION
+3 ),
2636 SV_NUMBERFORMATTER_VERSION_FIXED_FRACTION
);
2640 // Week of year must be appended here because of nNewExtended
2641 const NfKeywordTable
& rKeyword
= pFormatScanner
->GetKeywords();
2642 aSingleFormatCode
.Code
= rKeyword
[NF_KEY_WW
];
2643 ImpInsertNewStandardFormat( aSingleFormatCode
,
2644 CLOffset
+ SetIndexTable( NF_DATE_WW
, nNewExtended
++ ),
2645 SV_NUMBERFORMATTER_VERSION_NF_DATE_WW
);
2648 osl::MutexGuard
aGuard(&theIndexTable
.maMtx
);
2649 theIndexTable
.mbInitialized
= true;
2651 SAL_WARN_IF( nNewExtended
> ZF_STANDARD_NEWEXTENDEDMAX
, "svl.numbers",
2652 "ImpGenerateFormats: overflow of nNewExtended standard formats" );
2654 // Now all additional format codes provided by I18N, but only if not
2655 // changing SystemCL, then they are appended last after user defined.
2656 if ( !bNoAdditionalFormats
)
2658 ImpGenerateAdditionalFormats( CLOffset
, aNumberFormatCode
, false );
2660 if (bOldConvertMode
)
2662 pFormatScanner
->SetConvertMode(true);
2667 void SvNumberFormatter::ImpGenerateAdditionalFormats( sal_uInt32 CLOffset
,
2668 NumberFormatCodeWrapper
& rNumberFormatCode
, bool bAfterChangingSystemCL
)
2670 using namespace ::com::sun::star
;
2672 SvNumberformat
* pStdFormat
= GetFormatEntry( CLOffset
+ ZF_STANDARD
);
2675 SAL_WARN( "svl.numbers", "ImpGenerateAdditionalFormats: no GENERAL format" );
2678 sal_uInt32 nPos
= CLOffset
+ pStdFormat
->GetLastInsertKey();
2679 rNumberFormatCode
.setLocale( GetLanguageTag().getLocale() );
2682 // All currencies, this time with [$...] which was stripped in
2683 // ImpGenerateFormats for old "automatic" currency formats.
2684 uno::Sequence
< i18n::NumberFormatCode
> aFormatSeq
=
2685 rNumberFormatCode
.getAllFormatCode( i18n::KNumberFormatUsage::CURRENCY
);
2686 i18n::NumberFormatCode
* pFormatArr
= aFormatSeq
.getArray();
2687 sal_Int32 nCodes
= aFormatSeq
.getLength();
2688 ImpAdjustFormatCodeDefault( aFormatSeq
.getArray(), nCodes
);
2689 for ( j
= 0; j
< nCodes
; j
++ )
2691 if ( nPos
- CLOffset
>= SV_COUNTRY_LANGUAGE_OFFSET
)
2693 SAL_WARN( "svl.numbers", "ImpGenerateAdditionalFormats: too many formats" );
2696 if ( pFormatArr
[j
].Index
< NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS
&&
2697 pFormatArr
[j
].Index
!= NF_CURRENCY_1000DEC2_CCC
)
2698 { // Insert only if not already inserted, but internal index must be
2699 // above so ImpInsertFormat can distinguish it.
2700 sal_Int16 nOrgIndex
= pFormatArr
[j
].Index
;
2701 pFormatArr
[j
].Index
= sal::static_int_cast
< sal_Int16
>(
2702 pFormatArr
[j
].Index
+ nCodes
+ NF_INDEX_TABLE_ENTRIES
);
2703 //! no default on currency
2704 bool bDefault
= aFormatSeq
[j
].Default
;
2705 aFormatSeq
[j
].Default
= false;
2706 if ( ImpInsertNewStandardFormat( pFormatArr
[j
], nPos
+1,
2707 SV_NUMBERFORMATTER_VERSION_ADDITIONAL_I18N_FORMATS
,
2708 bAfterChangingSystemCL
, nOrgIndex
) )
2710 pFormatArr
[j
].Index
= nOrgIndex
;
2711 aFormatSeq
[j
].Default
= bDefault
;
2715 // all additional format codes provided by I18N that are not old standard index
2716 aFormatSeq
= rNumberFormatCode
.getAllFormatCodes();
2717 nCodes
= aFormatSeq
.getLength();
2720 pFormatArr
= aFormatSeq
.getArray();
2722 sal_Int32 nDef
= ImpAdjustFormatCodeDefault( pFormatArr
, nCodes
, false);
2723 // don't have any defaults here
2724 pFormatArr
[nDef
].Default
= false;
2725 for ( j
= 0; j
< nCodes
; j
++ )
2727 if ( nPos
- CLOffset
>= SV_COUNTRY_LANGUAGE_OFFSET
)
2729 SAL_WARN( "svl.numbers", "ImpGenerateAdditionalFormats: too many formats" );
2732 if ( pFormatArr
[j
].Index
>= NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS
)
2733 if ( ImpInsertNewStandardFormat( pFormatArr
[j
], nPos
+1,
2734 SV_NUMBERFORMATTER_VERSION_ADDITIONAL_I18N_FORMATS
,
2735 bAfterChangingSystemCL
) )
2740 pStdFormat
->SetLastInsertKey( (sal_uInt16
)(nPos
- CLOffset
) );
2744 void SvNumberFormatter::ImpGetPosCurrFormat(OUStringBuffer
& sPosStr
, const OUString
& rCurrSymbol
)
2746 NfCurrencyEntry::CompletePositiveFormatString( sPosStr
,
2747 rCurrSymbol
, xLocaleData
->getCurrPositiveFormat() );
2750 void SvNumberFormatter::ImpGetNegCurrFormat(OUStringBuffer
& sNegStr
, const OUString
& rCurrSymbol
)
2752 NfCurrencyEntry::CompleteNegativeFormatString( sNegStr
,
2753 rCurrSymbol
, xLocaleData
->getCurrNegativeFormat() );
2756 OUString
SvNumberFormatter::GenerateFormat(sal_uInt32 nIndex
,
2760 sal_uInt16 nPrecision
,
2761 sal_uInt16 nAnzLeading
)
2763 if (eLnge
== LANGUAGE_DONTKNOW
)
2767 short eType
= GetType(nIndex
);
2769 ImpGenerateCL(eLnge
); // create new standard formats if necessary
2771 utl::DigitGroupingIterator
aGrouping( xLocaleData
->getDigitGrouping());
2772 const sal_Int32 nDigitsInFirstGroup
= aGrouping
.get();
2773 const OUString
& rThSep
= GetNumThousandSep();
2775 SvNumberformat
* pFormat
= GetFormatEntry( nIndex
);
2777 OUStringBuffer sString
;
2778 using comphelper::string::padToLength
;
2780 if (nAnzLeading
== 0)
2783 sString
.append('#');
2786 sString
.append('#');
2787 sString
.append(rThSep
);
2788 padToLength(sString
, sString
.getLength() + nDigitsInFirstGroup
, '#');
2793 for (i
= 0; i
< nAnzLeading
; i
++)
2795 if (bThousand
&& i
> 0 && i
== aGrouping
.getPos())
2797 sString
.insert(0, rThSep
);
2798 aGrouping
.advance();
2800 sString
.insert(0, '0');
2802 if (bThousand
&& nAnzLeading
< nDigitsInFirstGroup
+ 1)
2804 for (i
= nAnzLeading
; i
< nDigitsInFirstGroup
+ 1; i
++)
2806 if (bThousand
&& i
% nDigitsInFirstGroup
== 0)
2807 sString
.insert(0, rThSep
);
2808 sString
.insert(0, '#');
2814 sString
.append(GetNumDecimalSep());
2815 padToLength(sString
, sString
.getLength() + nPrecision
, '0');
2817 if (eType
== NUMBERFORMAT_PERCENT
)
2819 sString
.append('%');
2821 else if (eType
== NUMBERFORMAT_CURRENCY
)
2823 OUStringBuffer
sNegStr(sString
);
2825 const NfCurrencyEntry
* pEntry
;
2827 if ( GetNewCurrencySymbolString( nIndex
, aCurr
, &pEntry
, &bBank
) )
2831 sal_uInt16 nPosiForm
= NfCurrencyEntry::GetEffectivePositiveFormat(
2832 xLocaleData
->getCurrPositiveFormat(),
2833 pEntry
->GetPositiveFormat(), bBank
);
2834 sal_uInt16 nNegaForm
= NfCurrencyEntry::GetEffectiveNegativeFormat(
2835 xLocaleData
->getCurrNegativeFormat(),
2836 pEntry
->GetNegativeFormat(), bBank
);
2837 pEntry
->CompletePositiveFormatString( sString
, bBank
, nPosiForm
);
2838 pEntry
->CompleteNegativeFormatString( sNegStr
, bBank
, nNegaForm
);
2841 { // assume currency abbreviation (AKA banking symbol), not symbol
2842 sal_uInt16 nPosiForm
= NfCurrencyEntry::GetEffectivePositiveFormat(
2843 xLocaleData
->getCurrPositiveFormat(),
2844 xLocaleData
->getCurrPositiveFormat(), true );
2845 sal_uInt16 nNegaForm
= NfCurrencyEntry::GetEffectiveNegativeFormat(
2846 xLocaleData
->getCurrNegativeFormat(),
2847 xLocaleData
->getCurrNegativeFormat(), true );
2848 NfCurrencyEntry::CompletePositiveFormatString( sString
, aCurr
, nPosiForm
);
2849 NfCurrencyEntry::CompleteNegativeFormatString( sNegStr
, aCurr
, nNegaForm
);
2853 { // "automatic" old style
2854 OUString aSymbol
, aAbbrev
;
2855 GetCompatibilityCurrency( aSymbol
, aAbbrev
);
2856 ImpGetPosCurrFormat( sString
, aSymbol
);
2857 ImpGetNegCurrFormat( sNegStr
, aSymbol
);
2861 sString
.append(';');
2862 sString
.append('[');
2863 sString
.append(pFormatScanner
->GetRedString());
2864 sString
.append(']');
2868 sString
.append(';');
2870 sString
.append(sNegStr
.makeStringAndClear());
2872 if (eType
!= NUMBERFORMAT_CURRENCY
)
2874 bool insertBrackets
= false;
2875 if ( eType
!= NUMBERFORMAT_UNDEFINED
)
2877 insertBrackets
= pFormat
->IsNegativeInBracket();
2879 if (IsRed
|| insertBrackets
)
2881 OUStringBuffer
sTmpStr(sString
);
2883 if ( pFormat
->HasPositiveBracketPlaceholder() )
2885 sTmpStr
.append('_');
2886 sTmpStr
.append(')');
2888 sTmpStr
.append(';');
2892 sTmpStr
.append('[');
2893 sTmpStr
.append(pFormatScanner
->GetRedString());
2894 sTmpStr
.append(']');
2899 sTmpStr
.append('(');
2900 sTmpStr
.append(sString
.toString());
2901 sTmpStr
.append(')');
2905 sTmpStr
.append('-');
2906 sTmpStr
.append(sString
.toString());
2911 return sString
.makeStringAndClear();
2914 bool SvNumberFormatter::IsUserDefined(const OUString
& sStr
,
2917 if (eLnge
== LANGUAGE_DONTKNOW
)
2921 sal_uInt32 CLOffset
= ImpGenerateCL(eLnge
); // create new standard formats if necessary
2924 sal_uInt32 nKey
= ImpIsEntry(sStr
, CLOffset
, eLnge
);
2925 if (nKey
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
2929 SvNumberformat
* pEntry
= GetFormatEntry( nKey
);
2930 if ( pEntry
&& ((pEntry
->GetType() & NUMBERFORMAT_DEFINED
) != 0) )
2937 sal_uInt32
SvNumberFormatter::GetEntryKey(const OUString
& sStr
,
2940 if (eLnge
== LANGUAGE_DONTKNOW
)
2944 sal_uInt32 CLOffset
= ImpGenerateCL(eLnge
); // create new standard formats if necessary
2945 return ImpIsEntry(sStr
, CLOffset
, eLnge
);
2948 sal_uInt32
SvNumberFormatter::GetStandardIndex(LanguageType eLnge
)
2950 if (eLnge
== LANGUAGE_DONTKNOW
)
2954 return GetStandardFormat(NUMBERFORMAT_NUMBER
, eLnge
);
2957 short SvNumberFormatter::GetType(sal_uInt32 nFIndex
)
2960 SvNumberformat
* pFormat
= GetFormatEntry( nFIndex
);
2963 eType
= NUMBERFORMAT_UNDEFINED
;
2967 eType
= pFormat
->GetType() &~NUMBERFORMAT_DEFINED
;
2970 eType
= NUMBERFORMAT_DEFINED
;
2976 void SvNumberFormatter::ClearMergeTable()
2980 pMergeTable
->clear();
2984 SvNumberFormatterIndexTable
* SvNumberFormatter::MergeFormatter(SvNumberFormatter
& rTable
)
2992 pMergeTable
= new SvNumberFormatterIndexTable
;
2995 sal_uInt32 nCLOffset
= 0;
2996 sal_uInt32 nOldKey
, nOffset
, nNewKey
;
2997 SvNumberformat
* pNewEntry
;
2999 SvNumberFormatTable::iterator it
= rTable
.aFTable
.begin();
3000 while (it
!= rTable
.aFTable
.end())
3002 SvNumberformat
* pFormat
= it
->second
;
3003 nOldKey
= it
->first
;
3004 nOffset
= nOldKey
% SV_COUNTRY_LANGUAGE_OFFSET
; // relative index
3005 if (nOffset
== 0) // 1st format of CL
3007 nCLOffset
= ImpGenerateCL(pFormat
->GetLanguage());
3009 if (nOffset
<= SV_MAX_ANZ_STANDARD_FORMATE
) // Std.form.
3011 nNewKey
= nCLOffset
+ nOffset
;
3012 if (aFTable
.find( nNewKey
) == aFTable
.end()) // not already present
3014 // pNewEntry = new SvNumberformat(*pFormat); // Copy is not sufficient!
3015 pNewEntry
= new SvNumberformat( *pFormat
, *pFormatScanner
);
3016 if (!aFTable
.insert(make_pair( nNewKey
, pNewEntry
)).second
)
3018 SAL_WARN( "svl.numbers", "SvNumberFormatter::MergeFormatter: dup position");
3022 if (nNewKey
!= nOldKey
) // new index
3024 (*pMergeTable
)[nOldKey
] = nNewKey
;
3027 else // user defined
3029 // pNewEntry = new SvNumberformat(*pFormat); // Copy is not sufficient!
3030 pNewEntry
= new SvNumberformat( *pFormat
, *pFormatScanner
);
3031 nNewKey
= ImpIsEntry(pNewEntry
->GetFormatstring(),
3033 pFormat
->GetLanguage());
3034 if (nNewKey
!= NUMBERFORMAT_ENTRY_NOT_FOUND
) // already present
3040 SvNumberformat
* pStdFormat
= GetFormatEntry(nCLOffset
+ ZF_STANDARD
);
3041 sal_uInt32 nPos
= nCLOffset
+ pStdFormat
->GetLastInsertKey();
3043 if (nNewKey
- nCLOffset
>= SV_COUNTRY_LANGUAGE_OFFSET
)
3045 SAL_WARN( "svl.numbers", "SvNumberFormatter::MergeFormatter: too many formats for CL");
3048 else if (!aFTable
.insert(make_pair( nNewKey
, pNewEntry
)).second
)
3050 SAL_WARN( "svl.numbers", "SvNumberFormatter::MergeFormatter: dup position");
3055 pStdFormat
->SetLastInsertKey((sal_uInt16
) (nNewKey
- nCLOffset
));
3058 if (nNewKey
!= nOldKey
) // new index
3060 (*pMergeTable
)[nOldKey
] = nNewKey
;
3069 SvNumberFormatterMergeMap
SvNumberFormatter::ConvertMergeTableToMap()
3071 if (!HasMergeFmtTbl())
3073 return SvNumberFormatterMergeMap();
3075 SvNumberFormatterMergeMap aMap
;
3076 for (SvNumberFormatterIndexTable::iterator it
= pMergeTable
->begin(); it
!= pMergeTable
->end(); ++it
)
3078 sal_uInt32 nOldKey
= it
->first
;
3079 aMap
[ nOldKey
] = it
->second
;
3086 sal_uInt32
SvNumberFormatter::GetFormatForLanguageIfBuiltIn( sal_uInt32 nFormat
,
3087 LanguageType eLnge
)
3089 if ( eLnge
== LANGUAGE_DONTKNOW
)
3093 if ( nFormat
< SV_COUNTRY_LANGUAGE_OFFSET
&& eLnge
== IniLnge
)
3095 return nFormat
; // it stays as it is
3097 sal_uInt32 nOffset
= nFormat
% SV_COUNTRY_LANGUAGE_OFFSET
; // relative index
3098 if ( nOffset
> SV_MAX_ANZ_STANDARD_FORMATE
)
3100 return nFormat
; // not a built-in format
3102 sal_uInt32 nCLOffset
= ImpGenerateCL(eLnge
); // create new standard formats if necessary
3103 return nCLOffset
+ nOffset
;
3107 sal_uInt32
SvNumberFormatter::GetFormatIndex( NfIndexTableOffset nTabOff
,
3108 LanguageType eLnge
)
3110 if (nTabOff
>= NF_INDEX_TABLE_ENTRIES
)
3111 return NUMBERFORMAT_ENTRY_NOT_FOUND
;
3113 if (eLnge
== LANGUAGE_DONTKNOW
)
3117 osl::MutexGuard
aGuard(&theIndexTable
.maMtx
);
3118 if (theIndexTable
.maData
[nTabOff
] == NUMBERFORMAT_ENTRY_NOT_FOUND
)
3119 return NUMBERFORMAT_ENTRY_NOT_FOUND
;
3122 sal_uInt32 nCLOffset
= ImpGenerateCL(eLnge
); // create new standard formats if necessary
3125 osl::MutexGuard
aGuard(&theIndexTable
.maMtx
);
3126 return nCLOffset
+ theIndexTable
.maData
[nTabOff
];
3131 NfIndexTableOffset
SvNumberFormatter::GetIndexTableOffset( sal_uInt32 nFormat
) const
3133 sal_uInt32 nOffset
= nFormat
% SV_COUNTRY_LANGUAGE_OFFSET
; // relative index
3134 if ( nOffset
> SV_MAX_ANZ_STANDARD_FORMATE
)
3136 return NF_INDEX_TABLE_ENTRIES
; // not a built-in format
3140 osl::MutexGuard
aGuard(&theIndexTable
.maMtx
);
3141 for ( sal_uInt16 j
= 0; j
< NF_INDEX_TABLE_ENTRIES
; j
++ )
3143 if (theIndexTable
.maData
[j
] == nOffset
)
3144 return (NfIndexTableOffset
) j
;
3147 return NF_INDEX_TABLE_ENTRIES
; // bad luck
3151 void SvNumberFormatter::SetYear2000( sal_uInt16 nVal
)
3153 pStringScanner
->SetYear2000( nVal
);
3157 sal_uInt16
SvNumberFormatter::GetYear2000() const
3159 return pStringScanner
->GetYear2000();
3163 sal_uInt16
SvNumberFormatter::ExpandTwoDigitYear( sal_uInt16 nYear
) const
3166 return SvNumberFormatter::ExpandTwoDigitYear( nYear
,
3167 pStringScanner
->GetYear2000() );
3173 sal_uInt16
SvNumberFormatter::GetYear2000Default()
3175 return (sal_uInt16
) ::utl::MiscCfg().GetYear2000();
3180 const NfCurrencyTable
& SvNumberFormatter::GetTheCurrencyTable()
3182 ::osl::MutexGuard
aGuard( GetMutex() );
3183 while ( !bCurrencyTableInitialized
)
3184 ImpInitCurrencyTable();
3185 return theCurrencyTable::get();
3190 const NfCurrencyEntry
* SvNumberFormatter::MatchSystemCurrency()
3192 // MUST call GetTheCurrencyTable() before accessing nSystemCurrencyPosition
3193 const NfCurrencyTable
& rTable
= GetTheCurrencyTable();
3194 return nSystemCurrencyPosition
? &rTable
[nSystemCurrencyPosition
] : NULL
;
3199 const NfCurrencyEntry
& SvNumberFormatter::GetCurrencyEntry( LanguageType eLang
)
3201 if ( eLang
== LANGUAGE_SYSTEM
)
3203 const NfCurrencyEntry
* pCurr
= MatchSystemCurrency();
3204 return pCurr
? *pCurr
: GetTheCurrencyTable()[0];
3208 eLang
= MsLangId::getRealLanguage( eLang
);
3209 const NfCurrencyTable
& rTable
= GetTheCurrencyTable();
3210 sal_uInt16 nCount
= rTable
.size();
3211 for ( sal_uInt16 j
= 0; j
< nCount
; j
++ )
3213 if ( rTable
[j
].GetLanguage() == eLang
)
3222 const NfCurrencyEntry
* SvNumberFormatter::GetCurrencyEntry(const OUString
& rAbbrev
, LanguageType eLang
)
3224 eLang
= MsLangId::getRealLanguage( eLang
);
3225 const NfCurrencyTable
& rTable
= GetTheCurrencyTable();
3226 sal_uInt16 nCount
= rTable
.size();
3227 for ( sal_uInt16 j
= 0; j
< nCount
; j
++ )
3229 if ( rTable
[j
].GetLanguage() == eLang
&&
3230 rTable
[j
].GetBankSymbol() == rAbbrev
)
3240 const NfCurrencyEntry
* SvNumberFormatter::GetLegacyOnlyCurrencyEntry( const OUString
& rSymbol
,
3241 const OUString
& rAbbrev
)
3243 if (!bCurrencyTableInitialized
)
3245 GetTheCurrencyTable(); // just for initialization
3247 const NfCurrencyTable
& rTable
= theLegacyOnlyCurrencyTable::get();
3248 sal_uInt16 nCount
= rTable
.size();
3249 for ( sal_uInt16 j
= 0; j
< nCount
; j
++ )
3251 if ( rTable
[j
].GetSymbol() == rSymbol
&&
3252 rTable
[j
].GetBankSymbol() == rAbbrev
)
3262 IMPL_STATIC_LINK_NOINSTANCE( SvNumberFormatter
, CurrencyChangeLink
, SAL_UNUSED_PARAMETER
void*, EMPTYARG
)
3264 ::osl::MutexGuard
aGuard( GetMutex() );
3266 LanguageType eLang
= LANGUAGE_SYSTEM
;
3267 SvtSysLocaleOptions().GetCurrencyAbbrevAndLanguage( aAbbrev
, eLang
);
3268 SetDefaultSystemCurrency( aAbbrev
, eLang
);
3274 void SvNumberFormatter::SetDefaultSystemCurrency( const OUString
& rAbbrev
, LanguageType eLang
)
3276 ::osl::MutexGuard
aGuard( GetMutex() );
3277 if ( eLang
== LANGUAGE_SYSTEM
)
3279 eLang
= SvtSysLocale().GetLanguageTag().getLanguageType();
3281 const NfCurrencyTable
& rTable
= GetTheCurrencyTable();
3282 sal_uInt16 nCount
= rTable
.size();
3283 if ( !rAbbrev
.isEmpty() )
3285 for ( sal_uInt16 j
= 0; j
< nCount
; j
++ )
3287 if ( rTable
[j
].GetLanguage() == eLang
&& rTable
[j
].GetBankSymbol() == rAbbrev
)
3289 nSystemCurrencyPosition
= j
;
3296 for ( sal_uInt16 j
= 0; j
< nCount
; j
++ )
3298 if ( rTable
[j
].GetLanguage() == eLang
)
3300 nSystemCurrencyPosition
= j
;
3305 nSystemCurrencyPosition
= 0; // not found => simple SYSTEM
3309 void SvNumberFormatter::ResetDefaultSystemCurrency()
3311 nDefaultSystemCurrencyFormat
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
3315 void SvNumberFormatter::InvalidateDateAcceptancePatterns()
3317 pStringScanner
->InvalidateDateAcceptancePatterns();
3321 sal_uInt32
SvNumberFormatter::ImpGetDefaultSystemCurrencyFormat()
3323 if ( nDefaultSystemCurrencyFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
3327 NfWSStringsDtor aCurrList
;
3328 sal_uInt16 nDefault
= GetCurrencyFormatStrings( aCurrList
,
3329 GetCurrencyEntry( LANGUAGE_SYSTEM
), false );
3330 DBG_ASSERT( aCurrList
.size(), "where is the NewCurrency System standard format?!?" );
3331 // if already loaded or user defined nDefaultSystemCurrencyFormat
3332 // will be set to the right value
3333 PutEntry( aCurrList
[ nDefault
], nCheck
, nType
,
3334 nDefaultSystemCurrencyFormat
, LANGUAGE_SYSTEM
);
3335 DBG_ASSERT( nCheck
== 0, "NewCurrency CheckError" );
3336 DBG_ASSERT( nDefaultSystemCurrencyFormat
!= NUMBERFORMAT_ENTRY_NOT_FOUND
,
3337 "nDefaultSystemCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND" );
3339 return nDefaultSystemCurrencyFormat
;
3343 sal_uInt32
SvNumberFormatter::ImpGetDefaultCurrencyFormat()
3345 sal_uInt32 CLOffset
= ImpGetCLOffset( ActLnge
);
3346 DefaultFormatKeysMap::iterator it
= aDefaultFormatKeys
.find( CLOffset
+ ZF_STANDARD_CURRENCY
);
3347 sal_uInt32 nDefaultCurrencyFormat
= (it
!= aDefaultFormatKeys
.end() ?
3348 it
->second
: NUMBERFORMAT_ENTRY_NOT_FOUND
);
3349 if ( nDefaultCurrencyFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
3351 // look for a defined standard
3352 sal_uInt32 nStopKey
= CLOffset
+ SV_COUNTRY_LANGUAGE_OFFSET
;
3354 SvNumberFormatTable::iterator it2
= aFTable
.lower_bound( CLOffset
);
3355 while ( it2
!= aFTable
.end() && (nKey
= it2
->first
) >= CLOffset
&& nKey
< nStopKey
)
3357 const SvNumberformat
* pEntry
= it2
->second
;
3358 if ( pEntry
->IsStandard() && (pEntry
->GetType() & NUMBERFORMAT_CURRENCY
) )
3360 nDefaultCurrencyFormat
= nKey
;
3366 if ( nDefaultCurrencyFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
3367 { // none found, create one
3369 NfWSStringsDtor aCurrList
;
3370 sal_uInt16 nDefault
= GetCurrencyFormatStrings( aCurrList
,
3371 GetCurrencyEntry( ActLnge
), false );
3372 DBG_ASSERT( aCurrList
.size(), "where is the NewCurrency standard format?" );
3373 if ( !aCurrList
.empty() )
3375 // if already loaded or user defined nDefaultSystemCurrencyFormat
3376 // will be set to the right value
3378 PutEntry( aCurrList
[ nDefault
], nCheck
, nType
,
3379 nDefaultCurrencyFormat
, ActLnge
);
3380 DBG_ASSERT( nCheck
== 0, "NewCurrency CheckError" );
3381 DBG_ASSERT( nDefaultCurrencyFormat
!= NUMBERFORMAT_ENTRY_NOT_FOUND
,
3382 "nDefaultCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND" );
3384 // old automatic currency format as a last resort
3385 if ( nDefaultCurrencyFormat
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
3386 nDefaultCurrencyFormat
= CLOffset
+ ZF_STANDARD_CURRENCY
+3;
3388 { // mark as standard so that it is found next time
3389 SvNumberformat
* pEntry
= GetFormatEntry( nDefaultCurrencyFormat
);
3391 pEntry
->SetStandard();
3394 aDefaultFormatKeys
[ CLOffset
+ ZF_STANDARD_CURRENCY
] = nDefaultCurrencyFormat
;
3396 return nDefaultCurrencyFormat
;
3401 // try to make it inline if possible since this a loop body
3402 // true: continue; false: break loop, if pFoundEntry==NULL dupe found
3406 bool SvNumberFormatter::ImpLookupCurrencyEntryLoopBody( const NfCurrencyEntry
*& pFoundEntry
, bool& bFoundBank
,
3407 const NfCurrencyEntry
* pData
, sal_uInt16 nPos
,
3408 const OUString
& rSymbol
)
3411 if ( pData
->GetSymbol() == rSymbol
)
3416 else if ( pData
->GetBankSymbol() == rSymbol
)
3425 if ( pFoundEntry
&& pFoundEntry
!= pData
)
3428 return false; // break loop, not unique
3431 { // first entry is SYSTEM
3432 pFoundEntry
= MatchSystemCurrency();
3435 return false; // break loop
3436 // even if there are more matching entries
3437 // this one is propably the one we are looking for
3441 pFoundEntry
= pData
;
3446 pFoundEntry
= pData
;
3453 bool SvNumberFormatter::GetNewCurrencySymbolString( sal_uInt32 nFormat
, OUString
& rStr
,
3454 const NfCurrencyEntry
** ppEntry
/* = NULL */,
3455 bool* pBank
/* = NULL */ ) const
3462 const SvNumberformat
* pFormat
= GetFormatEntry(nFormat
);
3465 OUStringBuffer
sBuff(128); // guess-estimate of a value that will pretty much garantee no re-alloc
3466 OUString aSymbol
, aExtension
;
3467 if ( pFormat
->GetNewCurrencySymbol( aSymbol
, aExtension
) )
3471 bool bFoundBank
= false;
3472 // we definiteley need an entry matching the format code string
3473 const NfCurrencyEntry
* pFoundEntry
= GetCurrencyEntry(
3474 bFoundBank
, aSymbol
, aExtension
, pFormat
->GetLanguage(),
3478 *ppEntry
= pFoundEntry
;
3480 *pBank
= bFoundBank
;
3481 rStr
= pFoundEntry
->BuildSymbolString(bFoundBank
);
3484 if ( rStr
.isEmpty() )
3485 { // analog to BuildSymbolString
3487 if ( aSymbol
.indexOf( '-' ) != -1 ||
3488 aSymbol
.indexOf( ']' ) != -1 )
3491 sBuff
.append( aSymbol
);
3496 sBuff
.append(aSymbol
);
3498 if ( !aExtension
.isEmpty() )
3500 sBuff
.append(aExtension
);
3504 rStr
= sBuff
.toString();
3514 const NfCurrencyEntry
* SvNumberFormatter::GetCurrencyEntry( bool & bFoundBank
,
3515 const OUString
& rSymbol
,
3516 const OUString
& rExtension
,
3517 LanguageType eFormatLanguage
,
3518 bool bOnlyStringLanguage
)
3520 sal_Int32 nExtLen
= rExtension
.getLength();
3521 LanguageType eExtLang
;
3524 // rExtension should be a 16-bit hex value max FFFF which may contain a
3525 // leading "-" separator (that is not a minus sign, but toInt32 can be
3526 // used to parse it, with post-processing as necessary):
3527 sal_Int32 nExtLang
= rExtension
.toInt32( 16 );
3530 eExtLang
= LANGUAGE_DONTKNOW
;
3534 eExtLang
= (LanguageType
) ((nExtLang
< 0) ? -nExtLang
: nExtLang
);
3539 eExtLang
= LANGUAGE_DONTKNOW
;
3541 const NfCurrencyEntry
* pFoundEntry
= NULL
;
3542 const NfCurrencyTable
& rTable
= GetTheCurrencyTable();
3543 sal_uInt16 nCount
= rTable
.size();
3546 // first try with given extension language/country
3549 for ( sal_uInt16 j
= 0; j
< nCount
&& bCont
; j
++ )
3551 LanguageType eLang
= rTable
[j
].GetLanguage();
3552 if ( eLang
== eExtLang
||
3553 ((eExtLang
== LANGUAGE_DONTKNOW
) &&
3554 (eLang
== LANGUAGE_SYSTEM
)))
3556 bCont
= ImpLookupCurrencyEntryLoopBody( pFoundEntry
, bFoundBank
,
3557 &rTable
[j
], j
, rSymbol
);
3563 if ( pFoundEntry
|| !bCont
|| (bOnlyStringLanguage
&& nExtLen
) )
3567 if ( !bOnlyStringLanguage
)
3569 // now try the language/country of the number format
3570 for ( sal_uInt16 j
= 0; j
< nCount
&& bCont
; j
++ )
3572 LanguageType eLang
= rTable
[j
].GetLanguage();
3573 if ( eLang
== eFormatLanguage
||
3574 ((eFormatLanguage
== LANGUAGE_DONTKNOW
) &&
3575 (eLang
== LANGUAGE_SYSTEM
)))
3577 bCont
= ImpLookupCurrencyEntryLoopBody( pFoundEntry
, bFoundBank
,
3578 &rTable
[j
], j
, rSymbol
);
3583 if ( pFoundEntry
|| !bCont
)
3589 // then try without language/country if no extension specified
3592 for ( sal_uInt16 j
= 0; j
< nCount
&& bCont
; j
++ )
3594 bCont
= ImpLookupCurrencyEntryLoopBody( pFoundEntry
, bFoundBank
,
3595 &rTable
[j
], j
, rSymbol
);
3603 void SvNumberFormatter::GetCompatibilityCurrency( OUString
& rSymbol
, OUString
& rAbbrev
) const
3605 ::com::sun::star::uno::Sequence
< ::com::sun::star::i18n::Currency2
>
3606 xCurrencies( xLocaleData
->getAllCurrencies() );
3608 const ::com::sun::star::i18n::Currency2
*pCurrencies
= xCurrencies
.getConstArray();
3609 sal_Int32 nCurrencies
= xCurrencies
.getLength();
3612 for ( j
=0; j
< nCurrencies
; ++j
)
3614 if ( pCurrencies
[j
].UsedInCompatibleFormatCodes
)
3616 rSymbol
= pCurrencies
[j
].Symbol
;
3617 rAbbrev
= pCurrencies
[j
].BankSymbol
;
3621 if ( j
>= nCurrencies
)
3623 if (LocaleDataWrapper::areChecksEnabled())
3625 LocaleDataWrapper::outputCheckMessage( xLocaleData
->
3626 appendLocaleInfo( "GetCompatibilityCurrency: none?"));
3628 rSymbol
= xLocaleData
->getCurrSymbol();
3629 rAbbrev
= xLocaleData
->getCurrBankSymbol();
3634 static void lcl_CheckCurrencySymbolPosition( const NfCurrencyEntry
& rCurr
)
3636 switch ( rCurr
.GetPositiveFormat() )
3644 LocaleDataWrapper::outputCheckMessage( "lcl_CheckCurrencySymbolPosition: unknown PositiveFormat");
3647 switch ( rCurr
.GetNegativeFormat() )
3667 LocaleDataWrapper::outputCheckMessage( "lcl_CheckCurrencySymbolPosition: unknown NegativeFormat");
3673 bool SvNumberFormatter::IsLocaleInstalled( LanguageType eLang
)
3675 // The set is initialized as a side effect of the currency table
3676 // created, make sure that exists, which usually is the case unless a
3677 // SvNumberFormatter was never instanciated.
3678 GetTheCurrencyTable();
3679 const NfInstalledLocales
&rInstalledLocales
= theInstalledLocales::get();
3680 return rInstalledLocales
.find( eLang
) != rInstalledLocales
.end();
3684 void SvNumberFormatter::ImpInitCurrencyTable()
3686 // racing condition possible:
3687 // ::osl::MutexGuard aGuard( GetMutex() );
3688 // while ( !bCurrencyTableInitialized )
3689 // ImpInitCurrencyTable();
3690 static bool bInitializing
= false;
3691 if ( bCurrencyTableInitialized
|| bInitializing
)
3695 bInitializing
= true;
3697 LanguageType eSysLang
= SvtSysLocale().GetLanguageTag().getLanguageType();
3698 LocaleDataWrapper
* pLocaleData
= new LocaleDataWrapper(
3699 ::comphelper::getProcessComponentContext(),
3700 SvtSysLocale().GetLanguageTag() );
3701 // get user configured currency
3702 OUString aConfiguredCurrencyAbbrev
;
3703 LanguageType eConfiguredCurrencyLanguage
= LANGUAGE_SYSTEM
;
3704 SvtSysLocaleOptions().GetCurrencyAbbrevAndLanguage(
3705 aConfiguredCurrencyAbbrev
, eConfiguredCurrencyLanguage
);
3706 sal_uInt16 nSecondarySystemCurrencyPosition
= 0;
3707 sal_uInt16 nMatchingSystemCurrencyPosition
= 0;
3708 NfCurrencyEntry
* pEntry
;
3710 // first entry is SYSTEM
3711 pEntry
= new NfCurrencyEntry( *pLocaleData
, LANGUAGE_SYSTEM
);
3712 theCurrencyTable::get().insert( theCurrencyTable::get().begin(), pEntry
);
3713 sal_uInt16 nCurrencyPos
= 1;
3715 ::com::sun::star::uno::Sequence
< ::com::sun::star::lang::Locale
> xLoc
=
3716 LocaleDataWrapper::getInstalledLocaleNames();
3717 sal_Int32 nLocaleCount
= xLoc
.getLength();
3718 SAL_INFO( "svl.numbers", "number of locales: \"" << nLocaleCount
<< "\"" );
3719 Locale
const * const pLocales
= xLoc
.getConstArray();
3720 NfCurrencyTable
&rCurrencyTable
= theCurrencyTable::get();
3721 NfCurrencyTable
&rLegacyOnlyCurrencyTable
= theLegacyOnlyCurrencyTable::get();
3722 NfInstalledLocales
&rInstalledLocales
= theInstalledLocales::get();
3723 sal_uInt16 nLegacyOnlyCurrencyPos
= 0;
3724 for ( sal_Int32 nLocale
= 0; nLocale
< nLocaleCount
; nLocale
++ )
3726 LanguageType eLang
= LanguageTag::convertToLanguageType( pLocales
[nLocale
], false);
3727 rInstalledLocales
.insert( eLang
);
3728 pLocaleData
->setLanguageTag( LanguageTag( pLocales
[nLocale
]) );
3729 Sequence
< Currency2
> aCurrSeq
= pLocaleData
->getAllCurrencies();
3730 sal_Int32 nCurrencyCount
= aCurrSeq
.getLength();
3731 Currency2
const * const pCurrencies
= aCurrSeq
.getConstArray();
3733 // one default currency for each locale, insert first so it is found first
3735 for ( nDefault
= 0; nDefault
< nCurrencyCount
; nDefault
++ )
3737 if ( pCurrencies
[nDefault
].Default
)
3740 if ( nDefault
< nCurrencyCount
)
3742 pEntry
= new NfCurrencyEntry( pCurrencies
[nDefault
], *pLocaleData
, eLang
);
3746 pEntry
= new NfCurrencyEntry( *pLocaleData
, eLang
); // first or ShellsAndPebbles
3748 if (LocaleDataWrapper::areChecksEnabled())
3750 lcl_CheckCurrencySymbolPosition( *pEntry
);
3752 rCurrencyTable
.insert( rCurrencyTable
.begin() + nCurrencyPos
++, pEntry
);
3753 if ( !nSystemCurrencyPosition
&& (!aConfiguredCurrencyAbbrev
.isEmpty() ?
3754 pEntry
->GetBankSymbol() == aConfiguredCurrencyAbbrev
&&
3755 pEntry
->GetLanguage() == eConfiguredCurrencyLanguage
: false) )
3757 nSystemCurrencyPosition
= nCurrencyPos
-1;
3759 if ( !nMatchingSystemCurrencyPosition
&&
3760 pEntry
->GetLanguage() == eSysLang
)
3762 nMatchingSystemCurrencyPosition
= nCurrencyPos
-1;
3764 // all remaining currencies for each locale
3765 if ( nCurrencyCount
> 1 )
3767 sal_Int32 nCurrency
;
3768 for ( nCurrency
= 0; nCurrency
< nCurrencyCount
; nCurrency
++ )
3770 if (pCurrencies
[nCurrency
].LegacyOnly
)
3772 pEntry
= new NfCurrencyEntry( pCurrencies
[nCurrency
], *pLocaleData
, eLang
);
3773 rLegacyOnlyCurrencyTable
.insert( rLegacyOnlyCurrencyTable
.begin() + nLegacyOnlyCurrencyPos
++, pEntry
);
3775 else if ( nCurrency
!= nDefault
)
3777 pEntry
= new NfCurrencyEntry( pCurrencies
[nCurrency
], *pLocaleData
, eLang
);
3779 bool bInsert
= true;
3780 sal_uInt16 n
= rCurrencyTable
.size();
3781 sal_uInt16 aCurrencyIndex
= 1; // skip first SYSTEM entry
3782 for ( sal_uInt16 j
=1; j
<n
; j
++ )
3784 if ( rCurrencyTable
[aCurrencyIndex
++] == *pEntry
)
3796 rCurrencyTable
.insert( rCurrencyTable
.begin() + nCurrencyPos
++, pEntry
);
3797 if ( !nSecondarySystemCurrencyPosition
&&
3798 (!aConfiguredCurrencyAbbrev
.isEmpty() ?
3799 pEntry
->GetBankSymbol() == aConfiguredCurrencyAbbrev
:
3800 pEntry
->GetLanguage() == eConfiguredCurrencyLanguage
) )
3802 nSecondarySystemCurrencyPosition
= nCurrencyPos
-1;
3804 if ( !nMatchingSystemCurrencyPosition
&&
3805 pEntry
->GetLanguage() == eSysLang
)
3807 nMatchingSystemCurrencyPosition
= nCurrencyPos
-1;
3814 if ( !nSystemCurrencyPosition
)
3816 nSystemCurrencyPosition
= nSecondarySystemCurrencyPosition
;
3818 if ((!aConfiguredCurrencyAbbrev
.isEmpty() && !nSystemCurrencyPosition
) &&
3819 LocaleDataWrapper::areChecksEnabled())
3821 LocaleDataWrapper::outputCheckMessage(
3822 "SvNumberFormatter::ImpInitCurrencyTable: configured currency not in I18N locale data.");
3824 // match SYSTEM if no configured currency found
3825 if ( !nSystemCurrencyPosition
)
3827 nSystemCurrencyPosition
= nMatchingSystemCurrencyPosition
;
3829 if ((aConfiguredCurrencyAbbrev
.isEmpty() && !nSystemCurrencyPosition
) &&
3830 LocaleDataWrapper::areChecksEnabled())
3832 LocaleDataWrapper::outputCheckMessage(
3833 "SvNumberFormatter::ImpInitCurrencyTable: system currency not in I18N locale data.");
3836 SvtSysLocaleOptions::SetCurrencyChangeLink( STATIC_LINK( NULL
, SvNumberFormatter
, CurrencyChangeLink
) );
3837 bInitializing
= false;
3838 bCurrencyTableInitialized
= true;
3842 sal_uInt16
SvNumberFormatter::GetCurrencyFormatStrings( NfWSStringsDtor
& rStrArr
,
3843 const NfCurrencyEntry
& rCurr
,
3846 OUString aRed
= OUStringBuffer().
3848 append(pFormatScanner
->GetRedString()).
3849 append(']').makeStringAndClear();
3851 sal_uInt16 nDefault
= 0;
3854 // Only bank symbols.
3855 OUString aPositiveBank
= rCurr
.BuildPositiveFormatString(true, *xLocaleData
, 1);
3856 OUString aNegativeBank
= rCurr
.BuildNegativeFormatString(true, *xLocaleData
, 1 );
3858 OUStringBuffer
format1(aPositiveBank
);
3859 format1
.append(';');
3860 format1
.append(aNegativeBank
);
3861 rStrArr
.push_back(format1
.makeStringAndClear());
3863 OUStringBuffer
format2(aPositiveBank
);
3864 format2
.append(';');
3866 format2
.append(aRed
);
3868 format2
.append(aNegativeBank
);
3869 rStrArr
.push_back(format2
.makeStringAndClear());
3871 nDefault
= rStrArr
.size() - 1;
3875 // Mixed formats like in SvNumberFormatter::ImpGenerateFormats() but no
3876 // duplicates if no decimals in currency.
3877 OUString aPositive
= rCurr
.BuildPositiveFormatString(false, *xLocaleData
, 1);
3878 OUString aNegative
= rCurr
.BuildNegativeFormatString(false, *xLocaleData
, 1 );
3879 OUStringBuffer format1
;
3880 OUStringBuffer format2
;
3881 OUStringBuffer format3
;
3882 OUStringBuffer format4
;
3883 OUStringBuffer format5
;
3884 if (rCurr
.GetDigits())
3886 OUString aPositiveNoDec
= rCurr
.BuildPositiveFormatString(false, *xLocaleData
, 0);
3887 OUString aNegativeNoDec
= rCurr
.BuildNegativeFormatString(false, *xLocaleData
, 0 );
3888 OUString aPositiveDashed
= rCurr
.BuildPositiveFormatString(false, *xLocaleData
, 2);
3889 OUString aNegativeDashed
= rCurr
.BuildNegativeFormatString(false, *xLocaleData
, 2);
3891 format1
.append(aPositiveNoDec
);
3892 format1
.append(';');
3893 format1
.append(aNegativeNoDec
);
3895 format3
.append(aPositiveNoDec
);
3896 format3
.append(';');
3897 format3
.append(aRed
);
3898 format3
.append(aNegativeNoDec
);
3900 format5
.append(aPositiveDashed
);
3901 format5
.append(';');
3902 format5
.append(aRed
);
3903 format5
.append(aNegativeDashed
);
3906 format2
.append(aPositive
);
3907 format2
.append(';');
3908 format2
.append(aNegative
);
3910 format4
.append(aPositive
);
3911 format4
.append(';');
3912 format4
.append(aRed
);
3913 format4
.append(aNegative
);
3915 if (rCurr
.GetDigits())
3917 rStrArr
.push_back(format1
.makeStringAndClear());
3919 rStrArr
.push_back(format2
.makeStringAndClear());
3920 if (rCurr
.GetDigits())
3922 rStrArr
.push_back(format3
.makeStringAndClear());
3924 rStrArr
.push_back(format4
.makeStringAndClear());
3925 nDefault
= rStrArr
.size() - 1;
3926 if (rCurr
.GetDigits())
3928 rStrArr
.push_back(format5
.makeStringAndClear());
3935 //--- NfCurrencyEntry ----------------------------------------------------
3938 NfCurrencyEntry::NfCurrencyEntry( const LocaleDataWrapper
& rLocaleData
, LanguageType eLang
)
3940 aSymbol
= rLocaleData
.getCurrSymbol();
3941 aBankSymbol
= rLocaleData
.getCurrBankSymbol();
3943 nPositiveFormat
= rLocaleData
.getCurrPositiveFormat();
3944 nNegativeFormat
= rLocaleData
.getCurrNegativeFormat();
3945 nDigits
= rLocaleData
.getCurrDigits();
3946 cZeroChar
= rLocaleData
.getCurrZeroChar();
3950 NfCurrencyEntry::NfCurrencyEntry( const ::com::sun::star::i18n::Currency
& rCurr
,
3951 const LocaleDataWrapper
& rLocaleData
, LanguageType eLang
)
3953 aSymbol
= rCurr
.Symbol
;
3954 aBankSymbol
= rCurr
.BankSymbol
;
3956 nPositiveFormat
= rLocaleData
.getCurrPositiveFormat();
3957 nNegativeFormat
= rLocaleData
.getCurrNegativeFormat();
3958 nDigits
= rCurr
.DecimalPlaces
;
3959 cZeroChar
= rLocaleData
.getCurrZeroChar();
3963 bool NfCurrencyEntry::operator==( const NfCurrencyEntry
& r
) const
3965 return aSymbol
== r
.aSymbol
3966 && aBankSymbol
== r
.aBankSymbol
3967 && eLanguage
== r
.eLanguage
3971 OUString
NfCurrencyEntry::BuildSymbolString(bool bBank
,
3972 bool bWithoutExtension
) const
3974 OUStringBuffer
aBuf("[$");
3977 aBuf
.append(aBankSymbol
);
3981 if ( aSymbol
.indexOf( (sal_Unicode
)'-' ) >= 0 ||
3982 aSymbol
.indexOf( (sal_Unicode
)']' ) >= 0)
3984 aBuf
.append('"').append(aSymbol
).append('"');
3988 aBuf
.append(aSymbol
);
3990 if ( !bWithoutExtension
&& eLanguage
!= LANGUAGE_DONTKNOW
&& eLanguage
!= LANGUAGE_SYSTEM
)
3992 sal_Int32 nLang
= static_cast<sal_Int32
>(eLanguage
);
3993 aBuf
.append('-').append( OUString::number(nLang
, 16).toAsciiUpperCase());
3997 return aBuf
.makeStringAndClear();
4000 OUString
NfCurrencyEntry::Impl_BuildFormatStringNumChars( const LocaleDataWrapper
& rLoc
,
4001 sal_uInt16 nDecimalFormat
) const
4003 OUStringBuffer aBuf
;
4004 aBuf
.append('#').append(rLoc
.getNumThousandSep()).append("##0");
4005 if (nDecimalFormat
&& nDigits
)
4007 aBuf
.append(rLoc
.getNumDecimalSep());
4008 sal_Unicode cDecimalChar
= nDecimalFormat
== 2 ? '-' : cZeroChar
;
4009 for (sal_uInt16 i
= 0; i
< nDigits
; ++i
)
4011 aBuf
.append(cDecimalChar
);
4014 return aBuf
.makeStringAndClear();
4018 OUString
NfCurrencyEntry::BuildPositiveFormatString(bool bBank
, const LocaleDataWrapper
& rLoc
,
4019 sal_uInt16 nDecimalFormat
) const
4021 OUStringBuffer
sBuf(Impl_BuildFormatStringNumChars(rLoc
, nDecimalFormat
));
4022 sal_uInt16 nPosiForm
= NfCurrencyEntry::GetEffectivePositiveFormat( rLoc
.getCurrPositiveFormat(),
4023 nPositiveFormat
, bBank
);
4024 CompletePositiveFormatString(sBuf
, bBank
, nPosiForm
);
4025 return sBuf
.makeStringAndClear();
4029 OUString
NfCurrencyEntry::BuildNegativeFormatString(bool bBank
,
4030 const LocaleDataWrapper
& rLoc
, sal_uInt16 nDecimalFormat
) const
4032 OUStringBuffer
sBuf(Impl_BuildFormatStringNumChars(rLoc
, nDecimalFormat
));
4033 sal_uInt16 nNegaForm
= NfCurrencyEntry::GetEffectiveNegativeFormat( rLoc
.getCurrNegativeFormat(),
4034 nNegativeFormat
, bBank
);
4035 CompleteNegativeFormatString(sBuf
, bBank
, nNegaForm
);
4036 return sBuf
.makeStringAndClear();
4040 void NfCurrencyEntry::CompletePositiveFormatString(OUStringBuffer
& rStr
, bool bBank
,
4041 sal_uInt16 nPosiForm
) const
4043 OUString aSymStr
= BuildSymbolString(bBank
);
4044 NfCurrencyEntry::CompletePositiveFormatString( rStr
, aSymStr
, nPosiForm
);
4048 void NfCurrencyEntry::CompleteNegativeFormatString(OUStringBuffer
& rStr
, bool bBank
,
4049 sal_uInt16 nNegaForm
) const
4051 OUString aSymStr
= BuildSymbolString(bBank
);
4052 NfCurrencyEntry::CompleteNegativeFormatString( rStr
, aSymStr
, nNegaForm
);
4057 void NfCurrencyEntry::CompletePositiveFormatString(OUStringBuffer
& rStr
, const OUString
& rSymStr
,
4058 sal_uInt16 nPositiveFormat
)
4060 switch( nPositiveFormat
)
4063 rStr
.insert(0, rSymStr
);
4066 rStr
.append(rSymStr
);
4070 rStr
.insert(0, ' ');
4071 rStr
.insert(0, rSymStr
);
4077 rStr
.append(rSymStr
);
4081 SAL_WARN( "svl.numbers", "NfCurrencyEntry::CompletePositiveFormatString: unknown option");
4088 void NfCurrencyEntry::CompleteNegativeFormatString(OUStringBuffer
& rStr
,
4089 const OUString
& rSymStr
,
4090 sal_uInt16 nNegativeFormat
)
4092 switch( nNegativeFormat
)
4096 rStr
.insert(0, rSymStr
);
4097 rStr
.insert(0, '(');
4103 rStr
.insert(0, rSymStr
);
4104 rStr
.insert(0, '-');
4109 rStr
.insert(0, '-');
4110 rStr
.insert(0, rSymStr
);
4115 rStr
.insert(0, rSymStr
);
4121 rStr
.insert(0, '(');
4122 rStr
.append(rSymStr
);
4128 rStr
.append(rSymStr
);
4129 rStr
.insert(0, '-');
4135 rStr
.append(rSymStr
);
4140 rStr
.append(rSymStr
);
4147 rStr
.append(rSymStr
);
4148 rStr
.insert(0, '-');
4153 rStr
.insert(0, ' ');
4154 rStr
.insert(0, rSymStr
);
4155 rStr
.insert(0, '-');
4161 rStr
.append(rSymStr
);
4167 rStr
.insert(0, " -");
4168 rStr
.insert(0, rSymStr
);
4173 rStr
.insert(0, ' ');
4174 rStr
.insert(0, rSymStr
);
4182 rStr
.append(rSymStr
);
4187 rStr
.insert(0, ' ');
4188 rStr
.insert(0, rSymStr
);
4189 rStr
.insert(0, '(');
4195 rStr
.insert(0, '(');
4197 rStr
.append(rSymStr
);
4202 SAL_WARN( "svl.numbers", "NfCurrencyEntry::CompleteNegativeFormatString: unknown option");
4209 sal_uInt16
NfCurrencyEntry::GetEffectivePositiveFormat( sal_uInt16 nIntlFormat
,
4210 sal_uInt16 nCurrFormat
, bool bBank
)
4214 #if NF_BANKSYMBOL_FIX_POSITION
4215 (void) nIntlFormat
; // avoid warnings
4218 switch ( nIntlFormat
)
4221 nIntlFormat
= 2; // $ 1
4224 nIntlFormat
= 3; // 1 $
4231 SAL_WARN( "svl.numbers", "NfCurrencyEntry::GetEffectivePositiveFormat: unknown option");
4242 //! Call this only if nCurrFormat is really with parentheses!
4243 static sal_uInt16
lcl_MergeNegativeParenthesisFormat( sal_uInt16 nIntlFormat
, sal_uInt16 nCurrFormat
)
4245 short nSign
= 0; // -1:=Klammer 0:=links, 1:=mitte, 2:=rechts
4246 switch ( nIntlFormat
)
4272 SAL_WARN( "svl.numbers", "lcl_MergeNegativeParenthesisFormat: unknown option");
4276 switch ( nCurrFormat
)
4328 sal_uInt16
NfCurrencyEntry::GetEffectiveNegativeFormat( sal_uInt16 nIntlFormat
,
4329 sal_uInt16 nCurrFormat
, bool bBank
)
4333 #if NF_BANKSYMBOL_FIX_POSITION
4336 switch ( nIntlFormat
)
4339 // nIntlFormat = 14; // ($ 1)
4340 nIntlFormat
= 9; // -$ 1
4343 nIntlFormat
= 9; // -$ 1
4346 nIntlFormat
= 11; // $ -1
4349 nIntlFormat
= 12; // $ 1-
4352 // nIntlFormat = 15; // (1 $)
4353 nIntlFormat
= 8; // -1 $
4356 nIntlFormat
= 8; // -1 $
4359 nIntlFormat
= 13; // 1- $
4362 nIntlFormat
= 10; // 1 $-
4377 // nIntlFormat = 14; // ($ 1)
4378 nIntlFormat
= 9; // -$ 1
4381 // nIntlFormat = 15; // (1 $)
4382 nIntlFormat
= 8; // -1 $
4385 SAL_WARN( "svl.numbers", "NfCurrencyEntry::GetEffectiveNegativeFormat: unknown option");
4390 else if ( nIntlFormat
!= nCurrFormat
)
4392 switch ( nCurrFormat
)
4395 nIntlFormat
= lcl_MergeNegativeParenthesisFormat(
4396 nIntlFormat
, nCurrFormat
);
4399 nIntlFormat
= nCurrFormat
;
4402 nIntlFormat
= nCurrFormat
;
4405 nIntlFormat
= nCurrFormat
;
4408 nIntlFormat
= lcl_MergeNegativeParenthesisFormat(
4409 nIntlFormat
, nCurrFormat
);
4412 nIntlFormat
= nCurrFormat
;
4415 nIntlFormat
= nCurrFormat
;
4418 nIntlFormat
= nCurrFormat
;
4421 nIntlFormat
= nCurrFormat
;
4424 nIntlFormat
= nCurrFormat
;
4427 nIntlFormat
= nCurrFormat
;
4430 nIntlFormat
= nCurrFormat
;
4433 nIntlFormat
= nCurrFormat
;
4436 nIntlFormat
= nCurrFormat
;
4439 nIntlFormat
= lcl_MergeNegativeParenthesisFormat(
4440 nIntlFormat
, nCurrFormat
);
4443 nIntlFormat
= lcl_MergeNegativeParenthesisFormat(
4444 nIntlFormat
, nCurrFormat
);
4447 SAL_WARN( "svl.numbers", "NfCurrencyEntry::GetEffectiveNegativeFormat: unknown option");
4455 // we only support default encodings here
4457 sal_Char
NfCurrencyEntry::GetEuroSymbol( rtl_TextEncoding eTextEncoding
)
4459 switch ( eTextEncoding
)
4461 case RTL_TEXTENCODING_MS_1252
:
4462 case RTL_TEXTENCODING_ISO_8859_1
:
4464 case RTL_TEXTENCODING_ISO_8859_15
:
4466 case RTL_TEXTENCODING_IBM_850
:
4468 case RTL_TEXTENCODING_APPLE_ROMAN
:
4471 return '\x80'; // Windows code for the converted TrueType fonts (whatever that means)
4477 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */