Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <sal/config.h>
21 :
22 : #include <sal/log.hxx>
23 : #include <svl/zforlist.hxx>
24 : #include <svl/currencytable.hxx>
25 :
26 : #include <comphelper/string.hxx>
27 : #include <tools/debug.hxx>
28 : #include <unotools/charclass.hxx>
29 : #include <i18nlangtag/mslangid.hxx>
30 : #include <unotools/localedatawrapper.hxx>
31 : #include <unotools/numberformatcodewrapper.hxx>
32 : #include <unotools/calendarwrapper.hxx>
33 : #include <com/sun/star/i18n/KNumberFormatUsage.hpp>
34 : #include <com/sun/star/i18n/KNumberFormatType.hpp>
35 : #include <comphelper/processfactory.hxx>
36 : #include <unotools/misccfg.hxx>
37 :
38 :
39 : #include <osl/mutex.hxx>
40 :
41 : #include "zforscan.hxx"
42 : #include "zforfind.hxx"
43 : #include <svl/zformat.hxx>
44 :
45 : #include <unotools/syslocaleoptions.hxx>
46 : #include <unotools/digitgroupingiterator.hxx>
47 : #include <rtl/instance.hxx>
48 : #include <rtl/strbuf.hxx>
49 :
50 : #include <math.h>
51 : #include <limits>
52 : #include <boost/scoped_ptr.hpp>
53 :
54 : using namespace ::com::sun::star;
55 : using namespace ::com::sun::star::uno;
56 : using namespace ::com::sun::star::i18n;
57 : using namespace ::com::sun::star::lang;
58 : using namespace ::std;
59 :
60 : // Constants for type offsets per Country/Language (CL)
61 : #define ZF_STANDARD 0
62 : #define ZF_STANDARD_PERCENT 10
63 : #define ZF_STANDARD_CURRENCY 20
64 : #define ZF_STANDARD_DATE 30
65 : #define ZF_STANDARD_TIME 40
66 : #define ZF_STANDARD_DATETIME 50
67 : #define ZF_STANDARD_SCIENTIFIC 60
68 : #define ZF_STANDARD_FRACTION 70
69 : #define ZF_STANDARD_NEWEXTENDED 75
70 : #define ZF_STANDARD_NEWEXTENDEDMAX SV_MAX_ANZ_STANDARD_FORMATE-2 // 98
71 : #define ZF_STANDARD_LOGICAL SV_MAX_ANZ_STANDARD_FORMATE-1 // 99
72 : #define ZF_STANDARD_TEXT SV_MAX_ANZ_STANDARD_FORMATE // 100
73 :
74 : /* Locale that is set if an unknown locale (from another system) is loaded of
75 : * legacy documents. Can not be SYSTEM because else, for example, a German "DM"
76 : * (old currency) is recognized as a date (#53155#). */
77 : #define UNKNOWN_SUBSTITUTE LANGUAGE_ENGLISH_US
78 :
79 273 : struct IndexTable
80 : {
81 : bool mbInitialized;
82 : sal_uInt32 maData[NF_INDEX_TABLE_ENTRIES];
83 : osl::Mutex maMtx;
84 :
85 273 : IndexTable() : mbInitialized(false) {}
86 : };
87 :
88 273 : static IndexTable theIndexTable;
89 :
90 :
91 :
92 : /**
93 : instead of every number formatter being a listener we have a registry which
94 : also handles one instance of the SysLocale options
95 : */
96 :
97 : typedef ::std::vector< SvNumberFormatter* > SvNumberFormatterList_impl;
98 :
99 : class SvNumberFormatterRegistry_Impl : public utl::ConfigurationListener
100 : {
101 : SvNumberFormatterList_impl aFormatters;
102 : SvtSysLocaleOptions aSysLocaleOptions;
103 : LanguageType eSysLanguage;
104 :
105 : public:
106 : SvNumberFormatterRegistry_Impl();
107 : virtual ~SvNumberFormatterRegistry_Impl();
108 :
109 4232 : void Insert( SvNumberFormatter* pThis )
110 4232 : { aFormatters.push_back( pThis ); }
111 :
112 : SvNumberFormatter* Remove( SvNumberFormatter* pThis );
113 :
114 4196 : size_t Count()
115 4196 : { return aFormatters.size(); }
116 :
117 : virtual void ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 ) SAL_OVERRIDE;
118 : };
119 :
120 3168 : SvNumberFormatterRegistry_Impl::SvNumberFormatterRegistry_Impl()
121 : {
122 3168 : eSysLanguage = MsLangId::getRealLanguage( LANGUAGE_SYSTEM );
123 3168 : aSysLocaleOptions.AddListener( this );
124 3168 : }
125 :
126 :
127 9462 : SvNumberFormatterRegistry_Impl::~SvNumberFormatterRegistry_Impl()
128 : {
129 3154 : aSysLocaleOptions.RemoveListener( this );
130 6308 : }
131 :
132 :
133 4196 : SvNumberFormatter* SvNumberFormatterRegistry_Impl::Remove( SvNumberFormatter* pThis )
134 : {
135 17592 : for (SvNumberFormatterList_impl::iterator it = aFormatters.begin();
136 11728 : it != aFormatters.end(); ++it)
137 : {
138 5864 : if ( *it == pThis )
139 : {
140 4196 : aFormatters.erase( it );
141 4196 : break;
142 : }
143 : }
144 4196 : return pThis;
145 : }
146 :
147 0 : void SvNumberFormatterRegistry_Impl::ConfigurationChanged( utl::ConfigurationBroadcaster*,
148 : sal_uInt32 nHint)
149 : {
150 0 : ::osl::MutexGuard aGuard( SvNumberFormatter::GetMutex() );
151 :
152 0 : if ( nHint & SYSLOCALEOPTIONS_HINT_LOCALE )
153 : {
154 0 : for( size_t i = 0, n = aFormatters.size(); i < n; ++i )
155 0 : aFormatters[ i ]->ReplaceSystemCL( eSysLanguage );
156 0 : eSysLanguage = MsLangId::getRealLanguage( LANGUAGE_SYSTEM );
157 : }
158 0 : if ( nHint & SYSLOCALEOPTIONS_HINT_CURRENCY )
159 : {
160 0 : for( size_t i = 0, n = aFormatters.size(); i < n; ++i )
161 0 : aFormatters[ i ]->ResetDefaultSystemCurrency();
162 : }
163 0 : if ( nHint & SYSLOCALEOPTIONS_HINT_DATEPATTERNS )
164 : {
165 0 : for( size_t i = 0, n = aFormatters.size(); i < n; ++i )
166 0 : aFormatters[ i ]->InvalidateDateAcceptancePatterns();
167 0 : }
168 0 : }
169 :
170 :
171 :
172 :
173 : SvNumberFormatterRegistry_Impl* SvNumberFormatter::pFormatterRegistry = NULL;
174 : bool SvNumberFormatter::bCurrencyTableInitialized = false;
175 : namespace
176 : {
177 : struct theCurrencyTable :
178 : public rtl::Static< NfCurrencyTable, theCurrencyTable > {};
179 :
180 : struct theLegacyOnlyCurrencyTable :
181 : public rtl::Static< NfCurrencyTable, theLegacyOnlyCurrencyTable > {};
182 :
183 : /** THE set of installed locales. */
184 : struct theInstalledLocales :
185 : public rtl::Static< NfInstalledLocales, theInstalledLocales> {};
186 :
187 : }
188 : sal_uInt16 SvNumberFormatter::nSystemCurrencyPosition = 0;
189 :
190 : // Whether BankSymbol (not CurrencySymbol!) is always at the end (1 $;-1 $) or
191 : // language dependent.
192 : #define NF_BANKSYMBOL_FIX_POSITION 1
193 :
194 : const sal_uInt16 SvNumberFormatter::UNLIMITED_PRECISION = ::std::numeric_limits<sal_uInt16>::max();
195 : const sal_uInt16 SvNumberFormatter::INPUTSTRING_PRECISION = ::std::numeric_limits<sal_uInt16>::max()-1;
196 :
197 4232 : SvNumberFormatter::SvNumberFormatter( const Reference< XComponentContext >& rxContext,
198 : LanguageType eLang )
199 : : m_xContext( rxContext )
200 4232 : , maLanguageTag( eLang)
201 : {
202 4232 : ImpConstruct( eLang );
203 4232 : }
204 :
205 8392 : SvNumberFormatter::~SvNumberFormatter()
206 : {
207 : {
208 4196 : ::osl::MutexGuard aGuard( GetMutex() );
209 4196 : pFormatterRegistry->Remove( this );
210 4196 : if ( !pFormatterRegistry->Count() )
211 : {
212 3154 : delete pFormatterRegistry;
213 3154 : pFormatterRegistry = NULL;
214 4196 : }
215 : }
216 :
217 351410 : for (SvNumberFormatTable::iterator it = aFTable.begin(); it != aFTable.end(); ++it)
218 347214 : delete it->second;
219 4196 : delete pFormatTable;
220 4196 : delete pCharClass;
221 4196 : delete pStringScanner;
222 4196 : delete pFormatScanner;
223 4196 : ClearMergeTable();
224 4196 : delete pMergeTable;
225 4196 : }
226 :
227 :
228 4232 : void SvNumberFormatter::ImpConstruct( LanguageType eLang )
229 : {
230 4232 : if ( eLang == LANGUAGE_DONTKNOW )
231 : {
232 0 : eLang = UNKNOWN_SUBSTITUTE;
233 : }
234 4232 : IniLnge = eLang;
235 4232 : ActLnge = eLang;
236 4232 : eEvalDateFormat = NF_EVALDATEFORMAT_INTL;
237 4232 : nDefaultSystemCurrencyFormat = NUMBERFORMAT_ENTRY_NOT_FOUND;
238 :
239 4232 : maLanguageTag.reset( eLang );
240 4232 : pCharClass = new CharClass( m_xContext, maLanguageTag );
241 4232 : xLocaleData.init( m_xContext, maLanguageTag );
242 4232 : xCalendar.init( m_xContext, maLanguageTag.getLocale() );
243 : xTransliteration.init( m_xContext, eLang,
244 4232 : ::com::sun::star::i18n::TransliterationModules_IGNORE_CASE );
245 4232 : xNatNum.init( m_xContext );
246 :
247 : // cached locale data items
248 4232 : const LocaleDataWrapper* pLoc = GetLocaleData();
249 4232 : aDecimalSep = pLoc->getNumDecimalSep();
250 4232 : aThousandSep = pLoc->getNumThousandSep();
251 4232 : aDateSep = pLoc->getDateSep();
252 :
253 4232 : pStringScanner = new ImpSvNumberInputScan( this );
254 4232 : pFormatScanner = new ImpSvNumberformatScan( this );
255 4232 : pFormatTable = NULL;
256 4232 : MaxCLOffset = 0;
257 4232 : ImpGenerateFormats( 0, false ); // 0 .. 999 for initialized language formats
258 4232 : pMergeTable = NULL;
259 4232 : bNoZero = false;
260 :
261 4232 : ::osl::MutexGuard aGuard( GetMutex() );
262 4232 : GetFormatterRegistry().Insert( this );
263 4232 : }
264 :
265 :
266 199742 : void SvNumberFormatter::ChangeIntl(LanguageType eLnge)
267 : {
268 199742 : if (ActLnge != eLnge)
269 : {
270 16696 : ActLnge = eLnge;
271 :
272 16696 : maLanguageTag.reset( eLnge );
273 16696 : pCharClass->setLanguageTag( maLanguageTag );
274 16696 : xLocaleData.changeLocale( maLanguageTag );
275 16696 : xCalendar.changeLocale( maLanguageTag.getLocale() );
276 16696 : xTransliteration.changeLocale( eLnge );
277 :
278 : // cached locale data items, initialize BEFORE calling ChangeIntl below
279 16696 : const LocaleDataWrapper* pLoc = GetLocaleData();
280 16696 : aDecimalSep = pLoc->getNumDecimalSep();
281 16696 : aThousandSep = pLoc->getNumThousandSep();
282 16696 : aDateSep = pLoc->getDateSep();
283 :
284 16696 : pFormatScanner->ChangeIntl();
285 16696 : pStringScanner->ChangeIntl();
286 : }
287 199742 : }
288 :
289 :
290 : // static
291 13518 : ::osl::Mutex& SvNumberFormatter::GetMutex()
292 : {
293 : static ::osl::Mutex* pMutex = NULL;
294 13518 : if( !pMutex )
295 : {
296 119 : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
297 119 : if( !pMutex )
298 : {
299 : // #i77768# Due to a static reference in the toolkit lib
300 : // we need a mutex that lives longer than the svl library.
301 : // Otherwise the dtor would use a destructed mutex!!
302 119 : pMutex = new ::osl::Mutex;
303 119 : }
304 : }
305 13518 : return *pMutex;
306 : }
307 :
308 :
309 : // static
310 4232 : SvNumberFormatterRegistry_Impl& SvNumberFormatter::GetFormatterRegistry()
311 : {
312 4232 : ::osl::MutexGuard aGuard( GetMutex() );
313 4232 : if ( !pFormatterRegistry )
314 : {
315 3168 : pFormatterRegistry = new SvNumberFormatterRegistry_Impl;
316 : }
317 4232 : return *pFormatterRegistry;
318 : }
319 :
320 2487 : void SvNumberFormatter::SetColorLink( const Link<>& rColorTableCallBack )
321 : {
322 2487 : aColorLink = rColorTableCallBack;
323 2487 : }
324 :
325 0 : Color* SvNumberFormatter::GetUserDefColor(sal_uInt16 nIndex)
326 : {
327 0 : if( aColorLink.IsSet() )
328 : {
329 0 : return reinterpret_cast<Color*>( aColorLink.Call( static_cast<void*>(&nIndex) )) ;
330 : }
331 : else
332 : {
333 0 : return NULL;
334 : }
335 : }
336 :
337 8303 : void SvNumberFormatter::ChangeNullDate(sal_uInt16 nDay,
338 : sal_uInt16 nMonth,
339 : sal_uInt16 nYear)
340 : {
341 8303 : pFormatScanner->ChangeNullDate(nDay, nMonth, nYear);
342 8303 : pStringScanner->ChangeNullDate(nDay, nMonth, nYear);
343 8303 : }
344 :
345 4989 : Date* SvNumberFormatter::GetNullDate()
346 : {
347 4989 : return pFormatScanner->GetNullDate();
348 : }
349 :
350 4608 : void SvNumberFormatter::ChangeStandardPrec(short nPrec)
351 : {
352 4608 : pFormatScanner->ChangeStandardPrec(nPrec);
353 4608 : }
354 :
355 0 : void SvNumberFormatter::SetNoZero(bool bNZ)
356 : {
357 0 : bNoZero = bNZ;
358 0 : }
359 :
360 1 : sal_uInt16 SvNumberFormatter::GetStandardPrec()
361 : {
362 1 : return pFormatScanner->GetStandardPrec();
363 : }
364 :
365 1 : bool SvNumberFormatter::GetNoZero()
366 : {
367 1 : return bNoZero;
368 : }
369 :
370 0 : void SvNumberFormatter::ReplaceSystemCL( LanguageType eOldLanguage )
371 : {
372 0 : sal_uInt32 nCLOffset = ImpGetCLOffset( LANGUAGE_SYSTEM );
373 0 : if ( nCLOffset > MaxCLOffset )
374 : {
375 0 : return ; // no SYSTEM entries to replace
376 : }
377 0 : const sal_uInt32 nMaxBuiltin = nCLOffset + SV_MAX_ANZ_STANDARD_FORMATE;
378 0 : const sal_uInt32 nNextCL = nCLOffset + SV_COUNTRY_LANGUAGE_OFFSET;
379 : sal_uInt32 nKey;
380 :
381 : // remove old builtin formats
382 0 : SvNumberFormatTable::iterator it = aFTable.find( nCLOffset );
383 0 : while ( it != aFTable.end() && (nKey = it->first) >= nCLOffset && nKey <= nMaxBuiltin )
384 : {
385 0 : delete it->second;
386 0 : it = aFTable.erase(it);
387 : }
388 :
389 : // move additional and user defined to temporary table
390 0 : SvNumberFormatTable aOldTable;
391 0 : while ( it != aFTable.end() && (nKey = it->first) >= nCLOffset && nKey < nNextCL )
392 : {
393 0 : aOldTable[ nKey ] = it->second;
394 0 : it = aFTable.erase(it);
395 : }
396 :
397 : // generate new old builtin formats
398 : // reset ActLnge otherwise ChangeIntl() wouldn't switch if already LANGUAGE_SYSTEM
399 0 : ActLnge = LANGUAGE_DONTKNOW;
400 0 : ChangeIntl( LANGUAGE_SYSTEM );
401 0 : ImpGenerateFormats( nCLOffset, true );
402 :
403 : // convert additional and user defined from old system to new system
404 0 : SvNumberformat* pStdFormat = GetFormatEntry( nCLOffset + ZF_STANDARD );
405 0 : sal_uInt32 nLastKey = nMaxBuiltin;
406 0 : pFormatScanner->SetConvertMode( eOldLanguage, LANGUAGE_SYSTEM, true );
407 0 : while ( !aOldTable.empty() )
408 : {
409 0 : nKey = aOldTable.begin()->first;
410 0 : if ( nLastKey < nKey )
411 : {
412 0 : nLastKey = nKey;
413 : }
414 0 : SvNumberformat* pOldEntry = aOldTable.begin()->second;
415 0 : aOldTable.erase( nKey );
416 0 : OUString aString( pOldEntry->GetFormatstring() );
417 :
418 : // Same as PutEntry() but assures key position even if format code is
419 : // a duplicate. Also won't mix up any LastInsertKey.
420 0 : ChangeIntl( eOldLanguage );
421 0 : LanguageType eLge = eOldLanguage; // ConvertMode changes this
422 0 : bool bCheck = false;
423 0 : sal_Int32 nCheckPos = -1;
424 : SvNumberformat* pNewEntry = new SvNumberformat( aString, pFormatScanner,
425 0 : pStringScanner, nCheckPos, eLge );
426 0 : if ( nCheckPos != 0 )
427 : {
428 0 : delete pNewEntry;
429 : }
430 : else
431 : {
432 0 : short eCheckType = pNewEntry->GetType();
433 0 : if ( eCheckType != css::util::NumberFormat::UNDEFINED )
434 : {
435 0 : pNewEntry->SetType( eCheckType | css::util::NumberFormat::DEFINED );
436 : }
437 : else
438 : {
439 0 : pNewEntry->SetType( css::util::NumberFormat::DEFINED );
440 : }
441 :
442 0 : if ( !aFTable.insert( make_pair( nKey, pNewEntry) ).second )
443 : {
444 0 : delete pNewEntry;
445 : }
446 : else
447 : {
448 0 : bCheck = true;
449 : }
450 : }
451 : DBG_ASSERT( bCheck, "SvNumberFormatter::ReplaceSystemCL: couldn't convert" );
452 : (void)bCheck;
453 :
454 0 : delete pOldEntry;
455 0 : }
456 0 : pFormatScanner->SetConvertMode(false);
457 0 : pStdFormat->SetLastInsertKey( sal_uInt16(nLastKey - nCLOffset) );
458 :
459 : // append new system additional formats
460 : NumberFormatCodeWrapper aNumberFormatCode( m_xContext,
461 0 : GetLanguageTag().getLocale() );
462 0 : ImpGenerateAdditionalFormats( nCLOffset, aNumberFormatCode, true );
463 : }
464 :
465 18956 : css::uno::Reference<css::uno::XComponentContext> SvNumberFormatter::GetComponentContext() const
466 : {
467 18956 : return m_xContext;
468 : }
469 :
470 4000 : const ImpSvNumberformatScan* SvNumberFormatter::GetFormatScanner() const { return pFormatScanner; }
471 :
472 12392 : const LanguageTag& SvNumberFormatter::GetLanguageTag() const { return maLanguageTag; }
473 :
474 5361 : const ::utl::TransliterationWrapper* SvNumberFormatter::GetTransliteration() const
475 : {
476 5361 : return xTransliteration.get();
477 : }
478 :
479 5758503 : const CharClass* SvNumberFormatter::GetCharClass() const { return pCharClass; }
480 :
481 4616535 : const LocaleDataWrapper* SvNumberFormatter::GetLocaleData() const { return xLocaleData.get(); }
482 :
483 13740 : CalendarWrapper* SvNumberFormatter::GetCalendar() const { return xCalendar.get(); }
484 :
485 2 : const NativeNumberWrapper* SvNumberFormatter::GetNatNum() const { return xNatNum.get(); }
486 :
487 2570237 : const OUString& SvNumberFormatter::GetNumDecimalSep() const { return aDecimalSep; }
488 :
489 3051135 : const OUString& SvNumberFormatter::GetNumThousandSep() const { return aThousandSep; }
490 :
491 1545353 : const OUString& SvNumberFormatter::GetDateSep() const { return aDateSep; }
492 :
493 2344 : bool SvNumberFormatter::IsTextFormat(sal_uInt32 F_Index) const
494 : {
495 2344 : const SvNumberformat* pFormat = GetFormatEntry(F_Index);
496 :
497 2344 : return pFormat && pFormat->IsTextFormat();
498 : }
499 :
500 16414 : bool SvNumberFormatter::PutEntry(OUString& rString,
501 : sal_Int32& nCheckPos,
502 : short& nType,
503 : sal_uInt32& nKey, // format key
504 : LanguageType eLnge)
505 : {
506 16414 : nKey = 0;
507 16414 : if (rString.isEmpty()) // empty string
508 : {
509 37 : nCheckPos = 1; // -> Error
510 37 : return false;
511 : }
512 16377 : if (eLnge == LANGUAGE_DONTKNOW)
513 : {
514 3 : eLnge = IniLnge;
515 : }
516 16377 : ChangeIntl(eLnge); // change locale if necessary
517 16377 : LanguageType eLge = eLnge; // non-const for ConvertMode
518 16377 : bool bCheck = false;
519 : SvNumberformat* p_Entry = new SvNumberformat(rString,
520 : pFormatScanner,
521 : pStringScanner,
522 : nCheckPos,
523 16377 : eLge);
524 :
525 16377 : if (nCheckPos == 0) // Format ok
526 : { // Type comparison:
527 16374 : short eCheckType = p_Entry->GetType();
528 16374 : if ( eCheckType != css::util::NumberFormat::UNDEFINED)
529 : {
530 16374 : p_Entry->SetType(eCheckType | css::util::NumberFormat::DEFINED);
531 16374 : nType = eCheckType;
532 : }
533 : else
534 : {
535 0 : p_Entry->SetType(css::util::NumberFormat::DEFINED);
536 0 : nType = css::util::NumberFormat::DEFINED;
537 : }
538 :
539 16374 : sal_uInt32 CLOffset = ImpGenerateCL(eLge); // create new standard formats if necessary
540 :
541 16374 : nKey = ImpIsEntry(p_Entry->GetFormatstring(),CLOffset, eLge);
542 16374 : if (nKey != NUMBERFORMAT_ENTRY_NOT_FOUND) // already present
543 : {
544 9034 : delete p_Entry;
545 : }
546 : else
547 : {
548 7340 : SvNumberformat* pStdFormat = GetFormatEntry(CLOffset + ZF_STANDARD);
549 7340 : sal_uInt32 nPos = CLOffset + pStdFormat->GetLastInsertKey();
550 7340 : if (nPos+1 - CLOffset >= SV_COUNTRY_LANGUAGE_OFFSET)
551 : {
552 : SAL_WARN( "svl.numbers", "SvNumberFormatter::PutEntry: too many formats for CL");
553 0 : delete p_Entry;
554 : }
555 7340 : else if (!aFTable.insert(make_pair( nPos+1,p_Entry)).second)
556 : {
557 : SAL_WARN( "svl.numbers", "SvNumberFormatter::PutEntry: dup position");
558 0 : delete p_Entry;
559 : }
560 : else
561 : {
562 7340 : bCheck = true;
563 7340 : nKey = nPos+1;
564 7340 : pStdFormat->SetLastInsertKey((sal_uInt16) (nKey-CLOffset));
565 : }
566 : }
567 : }
568 : else
569 : {
570 3 : delete p_Entry;
571 : }
572 16377 : return bCheck;
573 : }
574 :
575 14738 : bool SvNumberFormatter::PutandConvertEntry(OUString& rString,
576 : sal_Int32& nCheckPos,
577 : short& nType,
578 : sal_uInt32& nKey,
579 : LanguageType eLnge,
580 : LanguageType eNewLnge)
581 : {
582 : bool bRes;
583 14738 : if (eNewLnge == LANGUAGE_DONTKNOW)
584 : {
585 0 : eNewLnge = IniLnge;
586 : }
587 14738 : pFormatScanner->SetConvertMode(eLnge, eNewLnge);
588 14738 : bRes = PutEntry(rString, nCheckPos, nType, nKey, eLnge);
589 14738 : pFormatScanner->SetConvertMode(false);
590 14738 : return bRes;
591 : }
592 :
593 0 : bool SvNumberFormatter::PutandConvertEntrySystem(OUString& rString,
594 : sal_Int32& nCheckPos,
595 : short& nType,
596 : sal_uInt32& nKey,
597 : LanguageType eLnge,
598 : LanguageType eNewLnge)
599 : {
600 : bool bRes;
601 0 : if (eNewLnge == LANGUAGE_DONTKNOW)
602 : {
603 0 : eNewLnge = IniLnge;
604 : }
605 0 : pFormatScanner->SetConvertMode(eLnge, eNewLnge, true);
606 0 : bRes = PutEntry(rString, nCheckPos, nType, nKey, eLnge);
607 0 : pFormatScanner->SetConvertMode(false);
608 0 : return bRes;
609 : }
610 :
611 0 : sal_uInt32 SvNumberFormatter::GetIndexPuttingAndConverting( OUString & rString, LanguageType eLnge,
612 : LanguageType eSysLnge, short & rType,
613 : bool & rNewInserted, sal_Int32 & rCheckPos )
614 : {
615 0 : sal_uInt32 nKey = NUMBERFORMAT_ENTRY_NOT_FOUND;
616 0 : rNewInserted = false;
617 0 : rCheckPos = 0;
618 :
619 : // #62389# empty format string (of Writer) => General standard format
620 0 : if (rString.isEmpty())
621 : {
622 : // nothing
623 : }
624 0 : else if (eLnge == LANGUAGE_SYSTEM && eSysLnge != SvtSysLocale().GetLanguageTag().getLanguageType())
625 : {
626 0 : sal_uInt32 nOrig = GetEntryKey( rString, eSysLnge );
627 0 : if (nOrig == NUMBERFORMAT_ENTRY_NOT_FOUND)
628 : {
629 0 : nKey = nOrig; // none available, maybe user-defined
630 : }
631 : else
632 : {
633 0 : nKey = GetFormatForLanguageIfBuiltIn( nOrig, SvtSysLocale().GetLanguageTag().getLanguageType() );
634 : }
635 0 : if (nKey == nOrig)
636 : {
637 : // Not a builtin format, convert.
638 : // The format code string may get modified and adapted to the real
639 : // language and wouldn't match eSysLnge anymore, do that on a copy.
640 0 : OUString aTmp( rString);
641 : rNewInserted = PutandConvertEntrySystem( aTmp, rCheckPos, rType,
642 0 : nKey, eLnge, SvtSysLocale().GetLanguageTag().getLanguageType());
643 0 : if (rCheckPos > 0)
644 : {
645 : SAL_WARN( "svl.numbers", "SvNumberFormatter::GetIndexPuttingAndConverting: bad format code string for current locale");
646 0 : nKey = NUMBERFORMAT_ENTRY_NOT_FOUND;
647 0 : }
648 : }
649 : }
650 : else
651 : {
652 0 : nKey = GetEntryKey( rString, eLnge);
653 0 : if (nKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
654 : {
655 0 : rNewInserted = PutEntry( rString, rCheckPos, rType, nKey, eLnge);
656 0 : if (rCheckPos > 0)
657 : {
658 : SAL_WARN( "svl.numbers", "SvNumberFormatter::GetIndexPuttingAndConverting: bad format code string for specified locale");
659 0 : nKey = NUMBERFORMAT_ENTRY_NOT_FOUND;
660 : }
661 : }
662 : }
663 0 : if (nKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
664 : {
665 0 : nKey = GetStandardIndex( eLnge);
666 : }
667 0 : rType = GetType( nKey);
668 : // Convert any (!) old "automatic" currency format to new fixed currency
669 : // default format.
670 0 : if ((rType & css::util::NumberFormat::CURRENCY) != 0)
671 : {
672 0 : const SvNumberformat* pFormat = GetEntry( nKey);
673 0 : if (!pFormat->HasNewCurrency())
674 : {
675 0 : if (rNewInserted)
676 : {
677 0 : DeleteEntry( nKey); // don't leave trails of rubbish
678 0 : rNewInserted = false;
679 : }
680 0 : nKey = GetStandardFormat( css::util::NumberFormat::CURRENCY, eLnge);
681 : }
682 : }
683 0 : return nKey;
684 : }
685 :
686 492 : void SvNumberFormatter::DeleteEntry(sal_uInt32 nKey)
687 : {
688 492 : delete aFTable[nKey];
689 492 : aFTable.erase(nKey);
690 492 : }
691 :
692 125 : void SvNumberFormatter::GetUsedLanguages( std::vector<sal_uInt16>& rList )
693 : {
694 125 : rList.clear();
695 :
696 125 : sal_uInt32 nOffset = 0;
697 382 : while (nOffset <= MaxCLOffset)
698 : {
699 132 : SvNumberformat* pFormat = GetFormatEntry(nOffset);
700 132 : if (pFormat)
701 : {
702 132 : rList.push_back( pFormat->GetLanguage() );
703 : }
704 132 : nOffset += SV_COUNTRY_LANGUAGE_OFFSET;
705 : }
706 125 : }
707 :
708 :
709 144 : void SvNumberFormatter::FillKeywordTable( NfKeywordTable& rKeywords,
710 : LanguageType eLang )
711 : {
712 144 : ChangeIntl( eLang );
713 144 : const NfKeywordTable & rTable = pFormatScanner->GetKeywords();
714 8064 : for ( sal_uInt16 i = 0; i < NF_KEYWORD_ENTRIES_COUNT; ++i )
715 : {
716 7920 : rKeywords[i] = rTable[i];
717 : }
718 144 : }
719 :
720 :
721 1193 : OUString SvNumberFormatter::GetKeyword( LanguageType eLnge, sal_uInt16 nIndex )
722 : {
723 1193 : ChangeIntl(eLnge);
724 1193 : const NfKeywordTable & rTable = pFormatScanner->GetKeywords();
725 1193 : if ( nIndex < NF_KEYWORD_ENTRIES_COUNT )
726 : {
727 1193 : return rTable[nIndex];
728 : }
729 : SAL_WARN( "svl.numbers", "GetKeyword: invalid index");
730 0 : return OUString();
731 : }
732 :
733 :
734 275 : OUString SvNumberFormatter::GetStandardName( LanguageType eLnge )
735 : {
736 275 : ChangeIntl( eLnge );
737 275 : return pFormatScanner->GetStandardName();
738 : }
739 :
740 :
741 62321 : sal_uInt32 SvNumberFormatter::ImpGetCLOffset(LanguageType eLnge) const
742 : {
743 62321 : sal_uInt32 nOffset = 0;
744 159699 : while (nOffset <= MaxCLOffset)
745 : {
746 96797 : const SvNumberformat* pFormat = GetFormatEntry(nOffset);
747 96797 : if (pFormat && pFormat->GetLanguage() == eLnge)
748 : {
749 61740 : return nOffset;
750 : }
751 35057 : nOffset += SV_COUNTRY_LANGUAGE_OFFSET;
752 : }
753 581 : return nOffset;
754 : }
755 :
756 118742 : sal_uInt32 SvNumberFormatter::ImpIsEntry(const OUString& rString,
757 : sal_uInt32 nCLOffset,
758 : LanguageType eLnge)
759 : {
760 118742 : sal_uInt32 res = NUMBERFORMAT_ENTRY_NOT_FOUND;
761 118742 : SvNumberFormatTable::iterator it = aFTable.find( nCLOffset);
762 30985335 : while ( res == NUMBERFORMAT_ENTRY_NOT_FOUND &&
763 38455833 : it != aFTable.end() && it->second->GetLanguage() == eLnge )
764 : {
765 7601702 : if ( rString == it->second->GetFormatstring() )
766 : {
767 15183 : res = it->first;
768 : }
769 : else
770 : {
771 7586519 : ++it;
772 : }
773 : }
774 118742 : return res;
775 : }
776 :
777 :
778 0 : SvNumberFormatTable& SvNumberFormatter::GetFirstEntryTable(
779 : short& eType,
780 : sal_uInt32& FIndex,
781 : LanguageType& rLnge)
782 : {
783 0 : short eTypetmp = eType;
784 0 : if (eType == css::util::NumberFormat::ALL) // empty cell or don't care
785 : {
786 0 : rLnge = IniLnge;
787 : }
788 : else
789 : {
790 0 : SvNumberformat* pFormat = GetFormatEntry(FIndex);
791 0 : if (!pFormat)
792 : {
793 0 : rLnge = IniLnge;
794 0 : eType = css::util::NumberFormat::ALL;
795 0 : eTypetmp = eType;
796 : }
797 : else
798 : {
799 0 : rLnge = pFormat->GetLanguage();
800 0 : eType = pFormat->GetType()&~css::util::NumberFormat::DEFINED;
801 0 : if (eType == 0)
802 : {
803 0 : eType = css::util::NumberFormat::DEFINED;
804 0 : eTypetmp = eType;
805 : }
806 0 : else if (eType == css::util::NumberFormat::DATETIME)
807 : {
808 0 : eTypetmp = eType;
809 0 : eType = css::util::NumberFormat::DATE;
810 : }
811 : else
812 : {
813 0 : eTypetmp = eType;
814 : }
815 : }
816 : }
817 0 : ChangeIntl(rLnge);
818 0 : return GetEntryTable(eTypetmp, FIndex, rLnge);
819 : }
820 :
821 56579 : sal_uInt32 SvNumberFormatter::ImpGenerateCL( LanguageType eLnge, bool bNoAdditionalFormats )
822 : {
823 56579 : ChangeIntl(eLnge);
824 56579 : sal_uInt32 CLOffset = ImpGetCLOffset(ActLnge);
825 56579 : if (CLOffset > MaxCLOffset)
826 : {
827 : // new CL combination
828 581 : if (LocaleDataWrapper::areChecksEnabled())
829 : {
830 0 : const LanguageTag& rLoadedLocale = xLocaleData->getLoadedLanguageTag();
831 0 : if ( !rLoadedLocale.equals( maLanguageTag, true) )
832 : {
833 0 : OUString aMsg("SvNumberFormatter::ImpGenerateCL: locales don't match:");
834 0 : LocaleDataWrapper::outputCheckMessage( xLocaleData->appendLocaleInfo( aMsg ));
835 : }
836 : // test XML locale data FormatElement entries
837 : {
838 0 : uno::Sequence< i18n::FormatElement > xSeq = xLocaleData->getAllFormats();
839 : // A test for completeness of formatindex="0" ...
840 : // formatindex="47" is not needed here since it is done in
841 : // ImpGenerateFormats().
842 :
843 : // Test for dupes of formatindex="..."
844 0 : for ( sal_Int32 j = 0; j < xSeq.getLength(); j++ )
845 : {
846 0 : sal_Int16 nIdx = xSeq[j].formatIndex;
847 0 : OUStringBuffer aDupes;
848 0 : for ( sal_Int32 i = 0; i < xSeq.getLength(); i++ )
849 : {
850 0 : if ( i != j && xSeq[i].formatIndex == nIdx )
851 : {
852 0 : aDupes.append(OUString::number( i ));
853 0 : aDupes.append("(");
854 0 : aDupes.append(xSeq[i].formatKey);
855 0 : aDupes.append( ") ");
856 : }
857 : }
858 0 : if ( !aDupes.isEmpty() )
859 : {
860 0 : OUStringBuffer aMsg(aDupes.getLength() + xSeq[j].formatKey.getLength() + 100);
861 0 : aMsg.append("XML locale data FormatElement formatindex dupe: ");
862 0 : aMsg.append(OUString::number(nIdx));
863 0 : aMsg.append("\nFormatElements: ");
864 0 : aMsg.append(OUString::number( j ));
865 0 : aMsg.append("(");
866 0 : aMsg.append( xSeq[j].formatKey );
867 0 : aMsg.append( ") ");
868 0 : aMsg.append(aDupes.makeStringAndClear());
869 0 : LocaleDataWrapper::outputCheckMessage( xLocaleData->appendLocaleInfo( aMsg.makeStringAndClear() ));
870 : }
871 0 : }
872 0 : }
873 : }
874 :
875 581 : MaxCLOffset += SV_COUNTRY_LANGUAGE_OFFSET;
876 581 : ImpGenerateFormats( MaxCLOffset, bNoAdditionalFormats );
877 581 : CLOffset = MaxCLOffset;
878 : }
879 56579 : return CLOffset;
880 : }
881 :
882 2735 : SvNumberFormatTable& SvNumberFormatter::ChangeCL(short eType,
883 : sal_uInt32& FIndex,
884 : LanguageType eLnge)
885 : {
886 2735 : ImpGenerateCL(eLnge);
887 2735 : return GetEntryTable(eType, FIndex, ActLnge);
888 : }
889 :
890 2867 : SvNumberFormatTable& SvNumberFormatter::GetEntryTable(
891 : short eType,
892 : sal_uInt32& FIndex,
893 : LanguageType eLnge)
894 : {
895 2867 : if ( pFormatTable )
896 : {
897 2651 : pFormatTable->clear();
898 : }
899 : else
900 : {
901 216 : pFormatTable = new SvNumberFormatTable;
902 : }
903 2867 : ChangeIntl(eLnge);
904 2867 : sal_uInt32 CLOffset = ImpGetCLOffset(ActLnge);
905 :
906 : // Might generate and insert a default format for the given type
907 : // (e.g. currency) => has to be done before collecting formats.
908 2867 : sal_uInt32 nDefaultIndex = GetStandardFormat( eType, ActLnge );
909 :
910 2867 : SvNumberFormatTable::iterator it = aFTable.find( CLOffset);
911 :
912 2867 : if (eType == css::util::NumberFormat::ALL)
913 : {
914 0 : while (it != aFTable.end() && it->second->GetLanguage() == ActLnge)
915 : { // copy all entries to output table
916 0 : (*pFormatTable)[ it->first ] = it->second;
917 0 : ++it;
918 : }
919 : }
920 : else
921 : {
922 212324 : while (it != aFTable.end() && it->second->GetLanguage() == ActLnge)
923 : { // copy entries of queried type to output table
924 206590 : if ((it->second->GetType()) & eType)
925 85850 : (*pFormatTable)[ it->first ] = it->second;
926 206590 : ++it;
927 : }
928 : }
929 2867 : if ( !pFormatTable->empty() )
930 : { // select default if queried format doesn't exist or queried type or
931 : // language differ from existing format
932 2748 : SvNumberformat* pEntry = GetFormatEntry(FIndex);
933 2748 : if ( !pEntry || !(pEntry->GetType() & eType) || pEntry->GetLanguage() != ActLnge )
934 : {
935 2748 : FIndex = nDefaultIndex;
936 : }
937 : }
938 2867 : return *pFormatTable;
939 : }
940 :
941 12335 : bool SvNumberFormatter::IsNumberFormat(const OUString& sString,
942 : sal_uInt32& F_Index,
943 : double& fOutNumber)
944 : {
945 : short FType;
946 12335 : const SvNumberformat* pFormat = GetFormatEntry(F_Index);
947 12335 : if (!pFormat)
948 : {
949 17 : ChangeIntl(IniLnge);
950 17 : FType = css::util::NumberFormat::NUMBER;
951 : }
952 : else
953 : {
954 12318 : FType = pFormat->GetType() &~css::util::NumberFormat::DEFINED;
955 12318 : if (FType == 0)
956 : {
957 0 : FType = css::util::NumberFormat::DEFINED;
958 : }
959 12318 : ChangeIntl(pFormat->GetLanguage());
960 : }
961 :
962 : bool res;
963 12335 : short RType = FType;
964 12335 : if (RType == css::util::NumberFormat::TEXT)
965 : {
966 1 : res = false; // type text preset => no conversion to number
967 : }
968 : else
969 : {
970 12334 : res = pStringScanner->IsNumberFormat(sString, RType, fOutNumber, pFormat);
971 : }
972 12335 : if (res && !IsCompatible(FType, RType)) // non-matching type
973 : {
974 694 : switch ( RType )
975 : {
976 : case css::util::NumberFormat::DATE :
977 : // Preserve ISO 8601 input.
978 640 : if (pStringScanner->CanForceToIso8601( DMY))
979 : {
980 634 : F_Index = GetFormatIndex( NF_DATE_DIN_YYYYMMDD, ActLnge );
981 : }
982 : else
983 : {
984 6 : F_Index = GetStandardFormat( RType, ActLnge );
985 : }
986 640 : break;
987 : case css::util::NumberFormat::TIME :
988 46 : if ( pStringScanner->GetDecPos() )
989 : {
990 : // 100th seconds
991 0 : if ( pStringScanner->GetAnzNums() > 3 || fOutNumber < 0.0 )
992 : {
993 0 : F_Index = GetFormatIndex( NF_TIME_HH_MMSS00, ActLnge );
994 : }
995 : else
996 : {
997 0 : F_Index = GetFormatIndex( NF_TIME_MMSS00, ActLnge );
998 : }
999 : }
1000 46 : else if ( fOutNumber >= 1.0 || fOutNumber < 0.0 )
1001 : {
1002 0 : F_Index = GetFormatIndex( NF_TIME_HH_MMSS, ActLnge );
1003 : }
1004 : else
1005 : {
1006 46 : F_Index = GetStandardFormat( RType, ActLnge );
1007 : }
1008 46 : break;
1009 : default:
1010 8 : F_Index = GetStandardFormat( RType, ActLnge );
1011 : }
1012 : }
1013 12335 : return res;
1014 : }
1015 :
1016 1 : LanguageType SvNumberFormatter::GetLanguage() const
1017 : {
1018 1 : return IniLnge;
1019 : }
1020 :
1021 5070 : bool SvNumberFormatter::IsCompatible(short eOldType,
1022 : short eNewType)
1023 : {
1024 5070 : if (eOldType == eNewType)
1025 : {
1026 4371 : return true;
1027 : }
1028 699 : else if (eOldType == css::util::NumberFormat::DEFINED)
1029 : {
1030 0 : return true;
1031 : }
1032 : else
1033 : {
1034 699 : switch (eNewType)
1035 : {
1036 : case css::util::NumberFormat::NUMBER:
1037 5 : switch (eOldType)
1038 : {
1039 : case css::util::NumberFormat::PERCENT:
1040 : case css::util::NumberFormat::CURRENCY:
1041 : case css::util::NumberFormat::SCIENTIFIC:
1042 : case css::util::NumberFormat::FRACTION:
1043 : // case css::util::NumberFormat::LOGICAL:
1044 : case css::util::NumberFormat::DEFINED:
1045 5 : return true;
1046 : default:
1047 0 : return false;
1048 : }
1049 : break;
1050 : case css::util::NumberFormat::DATE:
1051 640 : switch (eOldType)
1052 : {
1053 : case css::util::NumberFormat::DATETIME:
1054 0 : return true;
1055 : default:
1056 640 : return false;
1057 : }
1058 : break;
1059 : case css::util::NumberFormat::TIME:
1060 46 : switch (eOldType)
1061 : {
1062 : case css::util::NumberFormat::DATETIME:
1063 0 : return true;
1064 : default:
1065 46 : return false;
1066 : }
1067 : break;
1068 : case css::util::NumberFormat::DATETIME:
1069 8 : switch (eOldType)
1070 : {
1071 : case css::util::NumberFormat::TIME:
1072 : case css::util::NumberFormat::DATE:
1073 0 : return true;
1074 : default:
1075 8 : return false;
1076 : }
1077 : break;
1078 : default:
1079 0 : return false;
1080 : }
1081 : }
1082 : }
1083 :
1084 :
1085 2875 : sal_uInt32 SvNumberFormatter::ImpGetDefaultFormat( short nType )
1086 : {
1087 2875 : sal_uInt32 CLOffset = ImpGetCLOffset( ActLnge );
1088 : sal_uInt32 nSearch;
1089 2875 : switch( nType )
1090 : {
1091 : case css::util::NumberFormat::DATE:
1092 2648 : nSearch = CLOffset + ZF_STANDARD_DATE;
1093 2648 : break;
1094 : case css::util::NumberFormat::TIME:
1095 71 : nSearch = CLOffset + ZF_STANDARD_TIME;
1096 71 : break;
1097 : case css::util::NumberFormat::DATETIME:
1098 10 : nSearch = CLOffset + ZF_STANDARD_DATETIME;
1099 10 : break;
1100 : case css::util::NumberFormat::PERCENT:
1101 146 : nSearch = CLOffset + ZF_STANDARD_PERCENT;
1102 146 : break;
1103 : case css::util::NumberFormat::SCIENTIFIC:
1104 0 : nSearch = CLOffset + ZF_STANDARD_SCIENTIFIC;
1105 0 : break;
1106 : default:
1107 0 : nSearch = CLOffset + ZF_STANDARD;
1108 : }
1109 :
1110 2875 : DefaultFormatKeysMap::iterator it = aDefaultFormatKeys.find( nSearch);
1111 5750 : sal_uInt32 nDefaultFormat = (it != aDefaultFormatKeys.end() ?
1112 2875 : it->second : NUMBERFORMAT_ENTRY_NOT_FOUND);
1113 2875 : if ( nDefaultFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
1114 : {
1115 : // look for a defined standard
1116 117 : sal_uInt32 nStopKey = CLOffset + SV_COUNTRY_LANGUAGE_OFFSET;
1117 117 : sal_uInt32 nKey(0);
1118 117 : SvNumberFormatTable::iterator it2 = aFTable.find( CLOffset );
1119 2653 : while ( it2 != aFTable.end() && (nKey = it2->first ) >= CLOffset && nKey < nStopKey )
1120 : {
1121 2536 : const SvNumberformat* pEntry = it2->second;
1122 2890 : if ( pEntry->IsStandard() && ((pEntry->GetType() &
1123 354 : ~css::util::NumberFormat::DEFINED) == nType) )
1124 : {
1125 117 : nDefaultFormat = nKey;
1126 117 : break; // while
1127 : }
1128 2419 : ++it2;
1129 : }
1130 :
1131 117 : if ( nDefaultFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
1132 : { // none found, use old fixed standards
1133 0 : switch( nType )
1134 : {
1135 : case css::util::NumberFormat::DATE:
1136 0 : nDefaultFormat = CLOffset + ZF_STANDARD_DATE;
1137 0 : break;
1138 : case css::util::NumberFormat::TIME:
1139 0 : nDefaultFormat = CLOffset + ZF_STANDARD_TIME+1;
1140 0 : break;
1141 : case css::util::NumberFormat::DATETIME:
1142 0 : nDefaultFormat = CLOffset + ZF_STANDARD_DATETIME;
1143 0 : break;
1144 : case css::util::NumberFormat::PERCENT:
1145 0 : nDefaultFormat = CLOffset + ZF_STANDARD_PERCENT+1;
1146 0 : break;
1147 : case css::util::NumberFormat::SCIENTIFIC:
1148 0 : nDefaultFormat = CLOffset + ZF_STANDARD_SCIENTIFIC;
1149 0 : break;
1150 : default:
1151 0 : nDefaultFormat = CLOffset + ZF_STANDARD;
1152 : }
1153 : }
1154 117 : aDefaultFormatKeys[ nSearch ] = nDefaultFormat;
1155 : }
1156 2875 : return nDefaultFormat;
1157 : }
1158 :
1159 :
1160 14851 : sal_uInt32 SvNumberFormatter::GetStandardFormat( short eType, LanguageType eLnge )
1161 : {
1162 14851 : if (eLnge == LANGUAGE_DONTKNOW)
1163 : {
1164 286 : eLnge = IniLnge;
1165 : }
1166 14851 : sal_uInt32 CLOffset = ImpGenerateCL(eLnge);
1167 14851 : switch(eType)
1168 : {
1169 : case css::util::NumberFormat::CURRENCY:
1170 346 : return ( eLnge == LANGUAGE_SYSTEM ) ? ImpGetDefaultSystemCurrencyFormat() : ImpGetDefaultCurrencyFormat();
1171 : case css::util::NumberFormat::DATE:
1172 : case css::util::NumberFormat::TIME:
1173 : case css::util::NumberFormat::DATETIME:
1174 : case css::util::NumberFormat::PERCENT:
1175 : case css::util::NumberFormat::SCIENTIFIC:
1176 2875 : return ImpGetDefaultFormat( eType );
1177 : case css::util::NumberFormat::FRACTION:
1178 0 : return CLOffset + ZF_STANDARD_FRACTION;
1179 : case css::util::NumberFormat::LOGICAL:
1180 52 : return CLOffset + ZF_STANDARD_LOGICAL;
1181 : case css::util::NumberFormat::TEXT:
1182 707 : return CLOffset + ZF_STANDARD_TEXT;
1183 : case css::util::NumberFormat::ALL:
1184 : case css::util::NumberFormat::DEFINED:
1185 : case css::util::NumberFormat::NUMBER:
1186 : case css::util::NumberFormat::UNDEFINED:
1187 : default:
1188 10871 : return CLOffset + ZF_STANDARD;
1189 : }
1190 : }
1191 :
1192 2604 : bool SvNumberFormatter::IsSpecialStandardFormat( sal_uInt32 nFIndex,
1193 : LanguageType eLnge )
1194 : {
1195 : return
1196 5208 : nFIndex == GetFormatIndex( NF_TIME_MMSS00, eLnge ) ||
1197 5208 : nFIndex == GetFormatIndex( NF_TIME_HH_MMSS00, eLnge ) ||
1198 5208 : nFIndex == GetFormatIndex( NF_TIME_HH_MMSS, eLnge )
1199 : ;
1200 : }
1201 :
1202 1739 : sal_uInt32 SvNumberFormatter::GetStandardFormat( sal_uInt32 nFIndex, short eType,
1203 : LanguageType eLnge )
1204 : {
1205 1739 : if ( IsSpecialStandardFormat( nFIndex, eLnge ) )
1206 0 : return nFIndex;
1207 : else
1208 1739 : return GetStandardFormat( eType, eLnge );
1209 : }
1210 :
1211 865 : sal_uInt32 SvNumberFormatter::GetStandardFormat( double fNumber, sal_uInt32 nFIndex,
1212 : short eType, LanguageType eLnge )
1213 : {
1214 865 : if ( IsSpecialStandardFormat( nFIndex, eLnge ) )
1215 0 : return nFIndex;
1216 :
1217 865 : switch( eType )
1218 : {
1219 : case css::util::NumberFormat::TIME :
1220 : {
1221 : bool bSign;
1222 0 : if ( fNumber < 0.0 )
1223 : {
1224 0 : bSign = true;
1225 0 : fNumber = -fNumber;
1226 : }
1227 : else
1228 0 : bSign = false;
1229 0 : double fSeconds = fNumber * 86400;
1230 0 : if ( floor( fSeconds + 0.5 ) * 100 != floor( fSeconds * 100 + 0.5 ) )
1231 : { // with 100th seconds
1232 0 : if ( bSign || fSeconds >= 3600 )
1233 0 : return GetFormatIndex( NF_TIME_HH_MMSS00, eLnge );
1234 : else
1235 0 : return GetFormatIndex( NF_TIME_MMSS00, eLnge );
1236 : }
1237 : else
1238 : {
1239 0 : if ( bSign || fNumber >= 1.0 )
1240 0 : return GetFormatIndex( NF_TIME_HH_MMSS, eLnge );
1241 : else
1242 0 : return GetStandardFormat( eType, eLnge );
1243 : }
1244 : }
1245 : default:
1246 865 : return GetStandardFormat( eType, eLnge );
1247 : }
1248 : }
1249 :
1250 875 : sal_uInt32 SvNumberFormatter::GetEditFormat( double fNumber, sal_uInt32 nFIndex,
1251 : short eType, LanguageType eLang,
1252 : SvNumberformat* pFormat )
1253 : {
1254 875 : sal_uInt32 nKey = nFIndex;
1255 875 : switch ( eType )
1256 : {
1257 : // #61619# always edit using 4-digit year
1258 : case css::util::NumberFormat::DATE :
1259 10 : if (rtl::math::approxFloor( fNumber) != fNumber)
1260 0 : nKey = GetFormatIndex( NF_DATETIME_SYS_DDMMYYYY_HHMMSS, eLang );
1261 : // fdo#34977 preserve time when editing even if only date was
1262 : // displayed.
1263 : /* FIXME: in case an ISO 8601 format was used, editing should
1264 : * also use such. Unfortunately we have no builtin combined
1265 : * date+time ISO format defined. Needs also locale data work.
1266 : * */
1267 : else
1268 : {
1269 : // Preserve ISO 8601 format.
1270 30 : if ( nFIndex == GetFormatIndex( NF_DATE_DIN_YYYYMMDD, eLang) ||
1271 20 : nFIndex == GetFormatIndex( NF_DATE_DIN_YYMMDD, eLang) ||
1272 30 : nFIndex == GetFormatIndex( NF_DATE_DIN_MMDD, eLang) ||
1273 10 : (pFormat && pFormat->IsIso8601( 0 )))
1274 0 : nKey = GetFormatIndex( NF_DATE_DIN_YYYYMMDD, eLang);
1275 : else
1276 10 : nKey = GetFormatIndex( NF_DATE_SYS_DDMMYYYY, eLang );
1277 : }
1278 10 : break;
1279 : case css::util::NumberFormat::TIME :
1280 0 : if (fNumber < 0.0 || fNumber >= 1.0)
1281 : {
1282 : /* XXX NOTE: this is a purely arbitrary value within the limits
1283 : * of a signed 16-bit. 32k hours are 3.7 years ... or
1284 : * 1903-09-26 if date. */
1285 0 : if (fabs( fNumber) * 24 < 0x7fff)
1286 0 : nKey = GetFormatIndex( NF_TIME_HH_MMSS, eLang );
1287 : // Preserve duration, use [HH]:MM:SS instead of time.
1288 : else
1289 0 : nKey = GetFormatIndex( NF_DATETIME_SYS_DDMMYYYY_HHMMSS, eLang );
1290 : // Assume that a large value is a datetime with only time
1291 : // displayed.
1292 : }
1293 : else
1294 0 : nKey = GetStandardFormat( fNumber, nFIndex, eType, eLang );
1295 0 : break;
1296 : case css::util::NumberFormat::DATETIME :
1297 0 : nKey = GetFormatIndex( NF_DATETIME_SYS_DDMMYYYY_HHMMSS, eLang );
1298 : /* FIXME: in case an ISO 8601 format was used, editing should
1299 : * also use such. Unfortunately we have no builtin combined
1300 : * date+time ISO format defined. Needs also locale data work. */
1301 0 : break;
1302 : default:
1303 865 : nKey = GetStandardFormat( fNumber, nFIndex, eType, eLang );
1304 : }
1305 875 : return nKey;
1306 : }
1307 :
1308 875 : void SvNumberFormatter::GetInputLineString(const double& fOutNumber,
1309 : sal_uInt32 nFIndex,
1310 : OUString& sOutString)
1311 : {
1312 : Color* pColor;
1313 875 : SvNumberformat* pFormat = GetFormatEntry( nFIndex );
1314 875 : if (!pFormat)
1315 : {
1316 0 : pFormat = GetFormatEntry(ZF_STANDARD);
1317 : }
1318 :
1319 875 : LanguageType eLang = pFormat->GetLanguage();
1320 875 : ChangeIntl( eLang );
1321 :
1322 875 : short eType = pFormat->GetType() & ~css::util::NumberFormat::DEFINED;
1323 875 : if (eType == 0)
1324 : {
1325 0 : eType = css::util::NumberFormat::DEFINED;
1326 : }
1327 :
1328 875 : sal_uInt16 nOldPrec = pFormatScanner->GetStandardPrec();
1329 875 : bool bPrecChanged = false;
1330 875 : if (eType == css::util::NumberFormat::NUMBER ||
1331 11 : eType == css::util::NumberFormat::PERCENT ||
1332 11 : eType == css::util::NumberFormat::CURRENCY ||
1333 11 : eType == css::util::NumberFormat::SCIENTIFIC ||
1334 : eType == css::util::NumberFormat::FRACTION)
1335 : {
1336 864 : if (eType != css::util::NumberFormat::PERCENT) // special treatment of % later
1337 : {
1338 864 : eType = css::util::NumberFormat::NUMBER;
1339 : }
1340 864 : ChangeStandardPrec(INPUTSTRING_PRECISION);
1341 864 : bPrecChanged = true;
1342 : }
1343 :
1344 875 : sal_uInt32 nKey = GetEditFormat( fOutNumber, nFIndex, eType, eLang, pFormat);
1345 875 : if ( nKey != nFIndex )
1346 : {
1347 11 : pFormat = GetFormatEntry( nKey );
1348 : }
1349 875 : if (pFormat)
1350 : {
1351 875 : if ( eType == css::util::NumberFormat::TIME && pFormat->GetFormatPrecision() )
1352 : {
1353 0 : ChangeStandardPrec(INPUTSTRING_PRECISION);
1354 0 : bPrecChanged = true;
1355 : }
1356 875 : pFormat->GetOutputString(fOutNumber, sOutString, &pColor);
1357 : }
1358 875 : if (bPrecChanged)
1359 : {
1360 864 : ChangeStandardPrec(nOldPrec);
1361 : }
1362 875 : }
1363 :
1364 25112 : void SvNumberFormatter::GetOutputString(const OUString& sString,
1365 : sal_uInt32 nFIndex,
1366 : OUString& sOutString,
1367 : Color** ppColor,
1368 : bool bUseStarFormat )
1369 : {
1370 25112 : SvNumberformat* pFormat = GetFormatEntry( nFIndex );
1371 25112 : if (!pFormat)
1372 : {
1373 144 : pFormat = GetFormatEntry(ZF_STANDARD_TEXT);
1374 : }
1375 25112 : if (!pFormat->IsTextFormat() && !pFormat->HasTextFormat())
1376 : {
1377 24656 : *ppColor = NULL;
1378 24656 : sOutString = sString;
1379 : }
1380 : else
1381 : {
1382 456 : ChangeIntl(pFormat->GetLanguage());
1383 456 : if ( bUseStarFormat )
1384 : {
1385 87 : pFormat->SetStarFormatSupport( true );
1386 : }
1387 456 : pFormat->GetOutputString(sString, sOutString, ppColor);
1388 456 : if ( bUseStarFormat )
1389 : {
1390 87 : pFormat->SetStarFormatSupport( false );
1391 : }
1392 : }
1393 25112 : }
1394 :
1395 64700 : void SvNumberFormatter::GetOutputString(const double& fOutNumber,
1396 : sal_uInt32 nFIndex,
1397 : OUString& sOutString,
1398 : Color** ppColor,
1399 : bool bUseStarFormat )
1400 : {
1401 64700 : if (bNoZero && fOutNumber == 0.0)
1402 : {
1403 0 : sOutString.clear();
1404 64700 : return;
1405 : }
1406 64700 : SvNumberformat* pFormat = GetFormatEntry( nFIndex );
1407 64700 : if (!pFormat)
1408 216 : pFormat = GetFormatEntry(ZF_STANDARD);
1409 64700 : ChangeIntl(pFormat->GetLanguage());
1410 64700 : if ( bUseStarFormat )
1411 10971 : pFormat->SetStarFormatSupport( true );
1412 64700 : pFormat->GetOutputString(fOutNumber, sOutString, ppColor);
1413 64700 : if ( bUseStarFormat )
1414 10971 : pFormat->SetStarFormatSupport( false );
1415 : }
1416 :
1417 7 : bool SvNumberFormatter::GetPreviewString(const OUString& sFormatString,
1418 : double fPreviewNumber,
1419 : OUString& sOutString,
1420 : Color** ppColor,
1421 : LanguageType eLnge,
1422 : bool bUseStarFormat )
1423 : {
1424 7 : if (sFormatString.isEmpty()) // no empty string
1425 : {
1426 0 : return false;
1427 : }
1428 : sal_uInt32 nKey;
1429 7 : if (eLnge == LANGUAGE_DONTKNOW)
1430 : {
1431 0 : eLnge = IniLnge;
1432 : }
1433 7 : ChangeIntl(eLnge); // change locale if necessary
1434 7 : eLnge = ActLnge;
1435 7 : sal_Int32 nCheckPos = -1;
1436 7 : OUString sTmpString = sFormatString;
1437 : boost::scoped_ptr<SvNumberformat> p_Entry(new SvNumberformat(sTmpString,
1438 : pFormatScanner,
1439 : pStringScanner,
1440 : nCheckPos,
1441 14 : eLnge));
1442 7 : if (nCheckPos == 0) // String ok
1443 : {
1444 7 : sal_uInt32 CLOffset = ImpGenerateCL(eLnge); // create new standard formats if necessary
1445 7 : nKey = ImpIsEntry(p_Entry->GetFormatstring(),CLOffset, eLnge);
1446 7 : if (nKey != NUMBERFORMAT_ENTRY_NOT_FOUND) // already present
1447 : {
1448 2 : GetOutputString(fPreviewNumber, nKey, sOutString, ppColor, bUseStarFormat);
1449 : }
1450 : else
1451 : {
1452 5 : if ( bUseStarFormat )
1453 : {
1454 0 : p_Entry->SetStarFormatSupport( true );
1455 : }
1456 5 : p_Entry->GetOutputString(fPreviewNumber, sOutString, ppColor);
1457 5 : if ( bUseStarFormat )
1458 : {
1459 0 : p_Entry->SetStarFormatSupport( false );
1460 : }
1461 : }
1462 7 : return true;
1463 : }
1464 : else
1465 : {
1466 0 : return false;
1467 7 : }
1468 : }
1469 :
1470 2 : bool SvNumberFormatter::GetPreviewStringGuess( const OUString& sFormatString,
1471 : double fPreviewNumber,
1472 : OUString& sOutString,
1473 : Color** ppColor,
1474 : LanguageType eLnge )
1475 : {
1476 2 : if (sFormatString.isEmpty()) // no empty string
1477 : {
1478 0 : return false;
1479 : }
1480 2 : if (eLnge == LANGUAGE_DONTKNOW)
1481 : {
1482 0 : eLnge = IniLnge;
1483 : }
1484 2 : ChangeIntl( eLnge );
1485 2 : eLnge = ActLnge;
1486 2 : bool bEnglish = (eLnge == LANGUAGE_ENGLISH_US);
1487 :
1488 2 : OUString aFormatStringUpper( pCharClass->uppercase( sFormatString ) );
1489 2 : sal_uInt32 nCLOffset = ImpGenerateCL( eLnge );
1490 2 : sal_uInt32 nKey = ImpIsEntry( aFormatStringUpper, nCLOffset, eLnge );
1491 2 : if ( nKey != NUMBERFORMAT_ENTRY_NOT_FOUND )
1492 : {
1493 : // Target format present
1494 0 : GetOutputString( fPreviewNumber, nKey, sOutString, ppColor );
1495 0 : return true;
1496 : }
1497 :
1498 4 : boost::scoped_ptr<SvNumberformat> pEntry;
1499 2 : sal_Int32 nCheckPos = -1;
1500 4 : OUString sTmpString;
1501 :
1502 2 : if ( bEnglish )
1503 : {
1504 0 : sTmpString = sFormatString;
1505 : pEntry.reset(new SvNumberformat( sTmpString, pFormatScanner,
1506 0 : pStringScanner, nCheckPos, eLnge ));
1507 : }
1508 : else
1509 : {
1510 2 : nCLOffset = ImpGenerateCL( LANGUAGE_ENGLISH_US );
1511 2 : nKey = ImpIsEntry( aFormatStringUpper, nCLOffset, LANGUAGE_ENGLISH_US );
1512 2 : bool bEnglishFormat = (nKey != NUMBERFORMAT_ENTRY_NOT_FOUND);
1513 :
1514 : // Try English -> other or convert english to other
1515 2 : LanguageType eFormatLang = LANGUAGE_ENGLISH_US;
1516 2 : pFormatScanner->SetConvertMode( LANGUAGE_ENGLISH_US, eLnge );
1517 2 : sTmpString = sFormatString;
1518 : pEntry.reset(new SvNumberformat( sTmpString, pFormatScanner,
1519 2 : pStringScanner, nCheckPos, eFormatLang ));
1520 2 : pFormatScanner->SetConvertMode( false );
1521 2 : ChangeIntl( eLnge );
1522 :
1523 2 : if ( !bEnglishFormat )
1524 : {
1525 4 : if ( !(nCheckPos == 0) || xTransliteration->isEqual( sFormatString,
1526 2 : pEntry->GetFormatstring() ) )
1527 : {
1528 : // other Format
1529 2 : sTmpString = sFormatString;
1530 : pEntry.reset(new SvNumberformat( sTmpString, pFormatScanner,
1531 2 : pStringScanner, nCheckPos, eLnge ));
1532 : }
1533 : else
1534 : {
1535 : // verify english
1536 0 : sal_Int32 nCheckPos2 = -1;
1537 : // try other --> english
1538 0 : eFormatLang = eLnge;
1539 0 : pFormatScanner->SetConvertMode( eLnge, LANGUAGE_ENGLISH_US );
1540 0 : sTmpString = sFormatString;
1541 : boost::scoped_ptr<SvNumberformat> pEntry2(new SvNumberformat( sTmpString, pFormatScanner,
1542 0 : pStringScanner, nCheckPos2, eFormatLang ));
1543 0 : pFormatScanner->SetConvertMode( false );
1544 0 : ChangeIntl( eLnge );
1545 0 : if ( nCheckPos2 == 0 && !xTransliteration->isEqual( sFormatString,
1546 0 : pEntry2->GetFormatstring() ) )
1547 : {
1548 : // other Format
1549 0 : sTmpString = sFormatString;
1550 : pEntry.reset(new SvNumberformat( sTmpString, pFormatScanner,
1551 0 : pStringScanner, nCheckPos, eLnge ));
1552 0 : }
1553 : }
1554 : }
1555 : }
1556 :
1557 2 : if (nCheckPos == 0) // String ok
1558 : {
1559 2 : ImpGenerateCL( eLnge ); // create new standard formats if necessary
1560 2 : pEntry->GetOutputString( fPreviewNumber, sOutString, ppColor );
1561 2 : return true;
1562 : }
1563 2 : return false;
1564 : }
1565 :
1566 0 : bool SvNumberFormatter::GetPreviewString( const OUString& sFormatString,
1567 : const OUString& sPreviewString,
1568 : OUString& sOutString,
1569 : Color** ppColor,
1570 : LanguageType eLnge )
1571 : {
1572 0 : if (sFormatString.isEmpty()) // no empty string
1573 : {
1574 0 : return false;
1575 : }
1576 : sal_uInt32 nKey;
1577 0 : if (eLnge == LANGUAGE_DONTKNOW)
1578 : {
1579 0 : eLnge = IniLnge;
1580 : }
1581 0 : ChangeIntl(eLnge); // switch if needed
1582 0 : eLnge = ActLnge;
1583 0 : sal_Int32 nCheckPos = -1;
1584 0 : OUString sTmpString = sFormatString;
1585 : boost::scoped_ptr<SvNumberformat> p_Entry(new SvNumberformat( sTmpString,
1586 : pFormatScanner,
1587 : pStringScanner,
1588 : nCheckPos,
1589 0 : eLnge));
1590 0 : if (nCheckPos == 0) // String ok
1591 : {
1592 : // May have to create standard formats for this locale.
1593 0 : sal_uInt32 CLOffset = ImpGenerateCL(eLnge);
1594 0 : nKey = ImpIsEntry( p_Entry->GetFormatstring(), CLOffset, eLnge);
1595 0 : if (nKey != NUMBERFORMAT_ENTRY_NOT_FOUND) // already present
1596 : {
1597 0 : GetOutputString( sPreviewString, nKey, sOutString, ppColor);
1598 : }
1599 : else
1600 : {
1601 : // If the format is valid but not a text format and does not
1602 : // include a text subformat, an empty string would result. Same as
1603 : // in SvNumberFormatter::GetOutputString()
1604 0 : if (p_Entry->IsTextFormat() || p_Entry->HasTextFormat())
1605 : {
1606 0 : p_Entry->GetOutputString( sPreviewString, sOutString, ppColor);
1607 : }
1608 : else
1609 : {
1610 0 : *ppColor = NULL;
1611 0 : sOutString = sPreviewString;
1612 : }
1613 : }
1614 0 : return true;
1615 : }
1616 : else
1617 : {
1618 0 : return false;
1619 0 : }
1620 : }
1621 :
1622 112 : sal_uInt32 SvNumberFormatter::TestNewString(const OUString& sFormatString,
1623 : LanguageType eLnge)
1624 : {
1625 112 : if (sFormatString.isEmpty()) // no empty string
1626 : {
1627 0 : return NUMBERFORMAT_ENTRY_NOT_FOUND;
1628 : }
1629 112 : if (eLnge == LANGUAGE_DONTKNOW)
1630 : {
1631 1 : eLnge = IniLnge;
1632 : }
1633 112 : ChangeIntl(eLnge); // change locale if necessary
1634 112 : eLnge = ActLnge;
1635 : sal_uInt32 nRes;
1636 112 : sal_Int32 nCheckPos = -1;
1637 112 : OUString sTmpString = sFormatString;
1638 : boost::scoped_ptr<SvNumberformat> pEntry(new SvNumberformat(sTmpString,
1639 : pFormatScanner,
1640 : pStringScanner,
1641 : nCheckPos,
1642 224 : eLnge));
1643 112 : if (nCheckPos == 0) // String ok
1644 : {
1645 112 : sal_uInt32 CLOffset = ImpGenerateCL(eLnge); // create new standard formats if necessary
1646 112 : nRes = ImpIsEntry(pEntry->GetFormatstring(),CLOffset, eLnge);
1647 : // already present?
1648 : }
1649 : else
1650 : {
1651 0 : nRes = NUMBERFORMAT_ENTRY_NOT_FOUND;
1652 : }
1653 224 : return nRes;
1654 : }
1655 :
1656 335415 : SvNumberformat* SvNumberFormatter::ImpInsertFormat( const ::com::sun::star::i18n::NumberFormatCode& rCode,
1657 : sal_uInt32 nPos, bool bAfterChangingSystemCL,
1658 : sal_Int16 nOrgIndex )
1659 : {
1660 335415 : OUString aCodeStr( rCode.Code );
1661 576065 : if ( rCode.Index < NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS &&
1662 269528 : rCode.Usage == ::com::sun::star::i18n::KNumberFormatUsage::CURRENCY &&
1663 28878 : rCode.Index != NF_CURRENCY_1000DEC2_CCC )
1664 : { // strip surrounding [$...] on automatic currency
1665 24065 : if ( aCodeStr.indexOf( "[$" ) >= 0)
1666 24065 : aCodeStr = SvNumberformat::StripNewCurrencyDelimiters( aCodeStr, false );
1667 : else
1668 : {
1669 0 : if (LocaleDataWrapper::areChecksEnabled() &&
1670 0 : rCode.Index != NF_CURRENCY_1000DEC2_CCC )
1671 : {
1672 0 : OUString aMsg = "SvNumberFormatter::ImpInsertFormat: no [$...] on currency format code, index " +
1673 0 : OUString::number( rCode.Index) +
1674 0 : ":\n" +
1675 0 : rCode.Code;
1676 0 : LocaleDataWrapper::outputCheckMessage( xLocaleData->appendLocaleInfo( aMsg));
1677 : }
1678 : }
1679 : }
1680 335415 : sal_Int32 nCheckPos = 0;
1681 : SvNumberformat* pFormat = new SvNumberformat(aCodeStr,
1682 : pFormatScanner,
1683 : pStringScanner,
1684 : nCheckPos,
1685 335415 : ActLnge);
1686 335415 : if (nCheckPos != 0)
1687 : {
1688 0 : if (LocaleDataWrapper::areChecksEnabled())
1689 : {
1690 0 : OUString aMsg = "SvNumberFormatter::ImpInsertFormat: bad format code, index " +
1691 0 : OUString::number( rCode.Index ) +
1692 0 : "\n" +
1693 0 : rCode.Code;
1694 0 : LocaleDataWrapper::outputCheckMessage( xLocaleData->appendLocaleInfo( aMsg));
1695 : }
1696 0 : delete pFormat;
1697 0 : return NULL;
1698 : }
1699 335415 : if ( rCode.Index >= NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS )
1700 : {
1701 94765 : sal_uInt32 nCLOffset = nPos - (nPos % SV_COUNTRY_LANGUAGE_OFFSET);
1702 94765 : sal_uInt32 nKey = ImpIsEntry( aCodeStr, nCLOffset, ActLnge );
1703 94765 : if ( nKey != NUMBERFORMAT_ENTRY_NOT_FOUND )
1704 : {
1705 : // If bAfterChangingSystemCL there will definitely be some dups,
1706 : // don't cry then.
1707 0 : if (LocaleDataWrapper::areChecksEnabled() && !bAfterChangingSystemCL)
1708 : {
1709 : // Test for duplicate indexes in locale data.
1710 0 : switch ( nOrgIndex )
1711 : {
1712 : // These may be dups of integer versions for locales where
1713 : // currencies have no decimals like Italian Lira.
1714 : case NF_CURRENCY_1000DEC2 : // NF_CURRENCY_1000INT
1715 : case NF_CURRENCY_1000DEC2_RED : // NF_CURRENCY_1000INT_RED
1716 : case NF_CURRENCY_1000DEC2_DASHED : // NF_CURRENCY_1000INT_RED
1717 0 : break;
1718 : default:
1719 : {
1720 0 : OUString aMsg("SvNumberFormatter::ImpInsertFormat: dup format code, index ");
1721 0 : aMsg += OUString::number( rCode.Index );
1722 0 : aMsg += "\n";
1723 0 : aMsg += rCode.Code;
1724 0 : LocaleDataWrapper::outputCheckMessage( xLocaleData->appendLocaleInfo( aMsg));
1725 : }
1726 : }
1727 : }
1728 0 : delete pFormat;
1729 0 : return NULL;
1730 : }
1731 94765 : else if ( nPos - nCLOffset >= SV_COUNTRY_LANGUAGE_OFFSET )
1732 : {
1733 0 : if (LocaleDataWrapper::areChecksEnabled())
1734 : {
1735 0 : OUString aMsg( "SvNumberFormatter::ImpInsertFormat: too many format codes, index ");
1736 0 : aMsg += OUString::number( rCode.Index );
1737 0 : aMsg += "\n";
1738 0 : aMsg += rCode.Code;
1739 0 : LocaleDataWrapper::outputCheckMessage( xLocaleData->appendLocaleInfo( aMsg));
1740 : }
1741 0 : delete pFormat;
1742 0 : return NULL;
1743 : }
1744 : }
1745 335415 : if ( !aFTable.insert( make_pair( nPos, pFormat) ).second )
1746 : {
1747 0 : if (LocaleDataWrapper::areChecksEnabled())
1748 : {
1749 0 : OUString aMsg( "ImpInsertFormat: can't insert number format key pos: ");
1750 0 : aMsg += OUString::number( nPos );
1751 0 : aMsg += ", code index ";
1752 0 : aMsg += OUString::number( rCode.Index );
1753 0 : aMsg += "\n";
1754 0 : aMsg += rCode.Code;
1755 0 : LocaleDataWrapper::outputCheckMessage( xLocaleData->appendLocaleInfo( aMsg));
1756 : }
1757 : else
1758 : {
1759 : SAL_WARN( "svl.numbers", "SvNumberFormatter::ImpInsertFormat: dup position");
1760 : }
1761 0 : delete pFormat;
1762 0 : return NULL;
1763 : }
1764 335415 : if ( rCode.Default )
1765 28878 : pFormat->SetStandard();
1766 335415 : if ( !rCode.DefaultName.isEmpty() )
1767 4813 : pFormat->SetComment( rCode.DefaultName );
1768 335415 : return pFormat;
1769 : }
1770 :
1771 367 : void SvNumberFormatter::GetFormatSpecialInfo(sal_uInt32 nFormat,
1772 : bool& bThousand,
1773 : bool& IsRed,
1774 : sal_uInt16& nPrecision,
1775 : sal_uInt16& nAnzLeading)
1776 :
1777 : {
1778 367 : SvNumberformat* pFormat = GetFormatEntry( nFormat );
1779 367 : if (pFormat)
1780 : pFormat->GetFormatSpecialInfo(bThousand, IsRed,
1781 367 : nPrecision, nAnzLeading);
1782 : else
1783 : {
1784 0 : bThousand = false;
1785 0 : IsRed = false;
1786 0 : nPrecision = pFormatScanner->GetStandardPrec();
1787 0 : nAnzLeading = 0;
1788 : }
1789 367 : }
1790 :
1791 2 : sal_uInt16 SvNumberFormatter::GetFormatPrecision( sal_uInt32 nFormat ) const
1792 : {
1793 2 : const SvNumberformat* pFormat = GetFormatEntry( nFormat );
1794 2 : if ( pFormat )
1795 2 : return pFormat->GetFormatPrecision();
1796 : else
1797 0 : return pFormatScanner->GetStandardPrec();
1798 : }
1799 :
1800 0 : sal_uInt16 SvNumberFormatter::GetFormatIntegerDigits( sal_uInt32 nFormat ) const
1801 : {
1802 0 : const SvNumberformat* pFormat = GetFormatEntry( nFormat );
1803 0 : if ( pFormat )
1804 0 : return pFormat->GetFormatIntegerDigits();
1805 : else
1806 0 : return 1;
1807 : }
1808 :
1809 0 : sal_Unicode SvNumberFormatter::GetDecSep() const
1810 : {
1811 0 : return GetNumDecimalSep()[0];
1812 : }
1813 :
1814 0 : OUString SvNumberFormatter::GetFormatDecimalSep( sal_uInt32 nFormat ) const
1815 : {
1816 0 : const SvNumberformat* pFormat = GetFormatEntry(nFormat);
1817 0 : if ( !pFormat || pFormat->GetLanguage() == ActLnge )
1818 : {
1819 0 : return GetNumDecimalSep();
1820 : }
1821 0 : OUString aRet;
1822 0 : LanguageType eSaveLang = xLocaleData.getCurrentLanguage();
1823 0 : if ( pFormat->GetLanguage() == eSaveLang )
1824 : {
1825 0 : aRet = xLocaleData->getNumDecimalSep();
1826 : }
1827 : else
1828 : {
1829 0 : LanguageTag aSaveLocale( xLocaleData->getLanguageTag() );
1830 0 : const_cast<SvNumberFormatter*>(this)->xLocaleData.changeLocale( LanguageTag( pFormat->GetLanguage()) );
1831 0 : aRet = xLocaleData->getNumDecimalSep();
1832 0 : const_cast<SvNumberFormatter*>(this)->xLocaleData.changeLocale( aSaveLocale );
1833 : }
1834 0 : return aRet;
1835 : }
1836 :
1837 :
1838 0 : sal_uInt32 SvNumberFormatter::GetFormatSpecialInfo( const OUString& rFormatString,
1839 : bool& bThousand, bool& IsRed, sal_uInt16& nPrecision,
1840 : sal_uInt16& nAnzLeading, LanguageType eLnge )
1841 :
1842 : {
1843 0 : if (eLnge == LANGUAGE_DONTKNOW)
1844 : {
1845 0 : eLnge = IniLnge;
1846 : }
1847 0 : ChangeIntl(eLnge); // change locale if necessary
1848 0 : eLnge = ActLnge;
1849 0 : OUString aTmpStr( rFormatString );
1850 0 : sal_Int32 nCheckPos = 0;
1851 : boost::scoped_ptr<SvNumberformat> pFormat(new SvNumberformat( aTmpStr, pFormatScanner,
1852 0 : pStringScanner, nCheckPos, eLnge ));
1853 0 : if ( nCheckPos == 0 )
1854 : {
1855 0 : pFormat->GetFormatSpecialInfo( bThousand, IsRed, nPrecision, nAnzLeading );
1856 : }
1857 : else
1858 : {
1859 0 : bThousand = false;
1860 0 : IsRed = false;
1861 0 : nPrecision = pFormatScanner->GetStandardPrec();
1862 0 : nAnzLeading = 0;
1863 : }
1864 0 : return nCheckPos;
1865 : }
1866 :
1867 :
1868 250276 : inline sal_uInt32 SetIndexTable( NfIndexTableOffset nTabOff, sal_uInt32 nIndOff )
1869 : {
1870 250276 : osl::MutexGuard aGuard(&theIndexTable.maMtx);
1871 :
1872 250276 : if (!theIndexTable.mbInitialized)
1873 : {
1874 : DBG_ASSERT(theIndexTable.maData[nTabOff] == NUMBERFORMAT_ENTRY_NOT_FOUND,
1875 : "SetIndexTable: theIndexTable[nTabOff] already occupied" );
1876 6188 : theIndexTable.maData[nTabOff] = nIndOff;
1877 : }
1878 250276 : return nIndOff;
1879 : }
1880 :
1881 :
1882 216585 : sal_Int32 SvNumberFormatter::ImpGetFormatCodeIndex(
1883 : ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::NumberFormatCode >& rSeq,
1884 : const NfIndexTableOffset nTabOff )
1885 : {
1886 216585 : const sal_Int32 nLen = rSeq.getLength();
1887 1390957 : for ( sal_Int32 j=0; j<nLen; j++ )
1888 : {
1889 1390957 : if ( rSeq[j].Index == nTabOff )
1890 216585 : return j;
1891 : }
1892 0 : if (LocaleDataWrapper::areChecksEnabled() && (nTabOff < NF_CURRENCY_START
1893 0 : || NF_CURRENCY_END < nTabOff || nTabOff == NF_CURRENCY_1000INT
1894 0 : || nTabOff == NF_CURRENCY_1000INT_RED
1895 0 : || nTabOff == NF_CURRENCY_1000DEC2_CCC))
1896 : { // currency entries with decimals might not exist, e.g. Italian Lira
1897 0 : OUString aMsg( "SvNumberFormatter::ImpGetFormatCodeIndex: not found: " );
1898 0 : aMsg += OUString::number( nTabOff );
1899 0 : LocaleDataWrapper::outputCheckMessage( xLocaleData->appendLocaleInfo(aMsg));
1900 : }
1901 0 : if ( nLen )
1902 : {
1903 : sal_Int32 j;
1904 : // look for a preset default
1905 0 : for ( j=0; j<nLen; j++ )
1906 : {
1907 0 : if ( rSeq[j].Default )
1908 0 : return j;
1909 : }
1910 : // currencies are special, not all format codes must exist, but all
1911 : // builtin number format key index positions must have a format assigned
1912 0 : if ( NF_CURRENCY_START <= nTabOff && nTabOff <= NF_CURRENCY_END )
1913 : {
1914 : // look for a format with decimals
1915 0 : for ( j=0; j<nLen; j++ )
1916 : {
1917 0 : if ( rSeq[j].Index == NF_CURRENCY_1000DEC2 )
1918 0 : return j;
1919 : }
1920 : // last resort: look for a format without decimals
1921 0 : for ( j=0; j<nLen; j++ )
1922 : {
1923 0 : if ( rSeq[j].Index == NF_CURRENCY_1000INT )
1924 0 : return j;
1925 : }
1926 : }
1927 : }
1928 : else
1929 : { // we need at least _some_ format
1930 0 : rSeq.realloc(1);
1931 0 : rSeq[0] = ::com::sun::star::i18n::NumberFormatCode();
1932 0 : rSeq[0].Code = OUStringBuffer().
1933 0 : append('0').
1934 0 : append(GetNumDecimalSep()).
1935 0 : append("############").
1936 0 : makeStringAndClear();
1937 : }
1938 0 : return 0;
1939 : }
1940 :
1941 :
1942 33691 : sal_Int32 SvNumberFormatter::ImpAdjustFormatCodeDefault(
1943 : ::com::sun::star::i18n::NumberFormatCode * pFormatArr,
1944 : sal_Int32 nCnt, bool bCheckCorrectness )
1945 : {
1946 : using namespace ::com::sun::star;
1947 :
1948 33691 : if ( !nCnt )
1949 0 : return -1;
1950 33691 : if (bCheckCorrectness && LocaleDataWrapper::areChecksEnabled())
1951 : {
1952 : // check the locale data for correctness
1953 0 : OStringBuffer aMsg;
1954 : sal_Int32 nElem, nShort, nMedium, nLong, nShortDef, nMediumDef, nLongDef;
1955 0 : nShort = nMedium = nLong = nShortDef = nMediumDef = nLongDef = -1;
1956 0 : for ( nElem = 0; nElem < nCnt; nElem++ )
1957 : {
1958 0 : switch ( pFormatArr[nElem].Type )
1959 : {
1960 : case i18n::KNumberFormatType::SHORT :
1961 0 : nShort = nElem;
1962 0 : break;
1963 : case i18n::KNumberFormatType::MEDIUM :
1964 0 : nMedium = nElem;
1965 0 : break;
1966 : case i18n::KNumberFormatType::LONG :
1967 0 : nLong = nElem;
1968 0 : break;
1969 : default:
1970 0 : aMsg.append("unknown type");
1971 : }
1972 0 : if ( pFormatArr[nElem].Default )
1973 : {
1974 0 : switch ( pFormatArr[nElem].Type )
1975 : {
1976 : case i18n::KNumberFormatType::SHORT :
1977 0 : if ( nShortDef != -1 )
1978 0 : aMsg.append("dupe short type default");
1979 0 : nShortDef = nElem;
1980 0 : break;
1981 : case i18n::KNumberFormatType::MEDIUM :
1982 0 : if ( nMediumDef != -1 )
1983 0 : aMsg.append("dupe medium type default");
1984 0 : nMediumDef = nElem;
1985 0 : break;
1986 : case i18n::KNumberFormatType::LONG :
1987 0 : if ( nLongDef != -1 )
1988 0 : aMsg.append("dupe long type default");
1989 0 : nLongDef = nElem;
1990 0 : break;
1991 : }
1992 : }
1993 0 : if (!aMsg.isEmpty())
1994 : {
1995 0 : aMsg.insert(0, "SvNumberFormatter::ImpAdjustFormatCodeDefault: ");
1996 0 : aMsg.append("\nXML locale data FormatElement formatindex: ");
1997 0 : aMsg.append(static_cast<sal_Int32>(pFormatArr[nElem].Index));
1998 : OUString aUMsg(OStringToOUString(aMsg.makeStringAndClear(),
1999 0 : RTL_TEXTENCODING_ASCII_US));
2000 0 : LocaleDataWrapper::outputCheckMessage(xLocaleData->appendLocaleInfo(aUMsg));
2001 : }
2002 : }
2003 0 : if ( nShort != -1 && nShortDef == -1 )
2004 0 : aMsg.append("no short type default ");
2005 0 : if ( nMedium != -1 && nMediumDef == -1 )
2006 0 : aMsg.append("no medium type default ");
2007 0 : if ( nLong != -1 && nLongDef == -1 )
2008 0 : aMsg.append("no long type default ");
2009 0 : if (!aMsg.isEmpty())
2010 : {
2011 0 : aMsg.insert(0, "SvNumberFormatter::ImpAdjustFormatCodeDefault: ");
2012 0 : aMsg.append("\nXML locale data FormatElement group of: ");
2013 0 : OUString aUMsg(OStringToOUString(aMsg.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US));
2014 : LocaleDataWrapper::outputCheckMessage(
2015 0 : xLocaleData->appendLocaleInfo(aUMsg + pFormatArr[0].NameID));
2016 0 : }
2017 : }
2018 : // find the default (medium preferred, then long) and reset all other defaults
2019 : sal_Int32 nElem, nDef, nMedium;
2020 33691 : nDef = nMedium = -1;
2021 325789 : for ( nElem = 0; nElem < nCnt; nElem++ )
2022 : {
2023 292098 : if ( pFormatArr[nElem].Default )
2024 : {
2025 62568 : switch ( pFormatArr[nElem].Type )
2026 : {
2027 : case i18n::KNumberFormatType::MEDIUM :
2028 28875 : nDef = nMedium = nElem;
2029 28875 : break;
2030 : case i18n::KNumberFormatType::LONG :
2031 9633 : if ( nMedium == -1 )
2032 9590 : nDef = nElem;
2033 : // fallthru
2034 : default:
2035 33693 : if ( nDef == -1 )
2036 19246 : nDef = nElem;
2037 33693 : pFormatArr[nElem].Default = false;
2038 : }
2039 : }
2040 : }
2041 33691 : if ( nDef == -1 )
2042 0 : nDef = 0;
2043 33691 : pFormatArr[nDef].Default = true;
2044 33691 : return nDef;
2045 : }
2046 :
2047 152546 : SvNumberformat* SvNumberFormatter::GetFormatEntry( sal_uInt32 nKey )
2048 : {
2049 152546 : SvNumberFormatTable::iterator it = aFTable.find( nKey);
2050 152546 : if (it != aFTable.end())
2051 152169 : return it->second;
2052 377 : return 0;
2053 : }
2054 :
2055 99183 : const SvNumberformat* SvNumberFormatter::GetFormatEntry( sal_uInt32 nKey ) const
2056 : {
2057 99183 : return GetEntry( nKey);
2058 : }
2059 :
2060 142029 : const SvNumberformat* SvNumberFormatter::GetEntry( sal_uInt32 nKey ) const
2061 : {
2062 142029 : SvNumberFormatTable::const_iterator it = aFTable.find( nKey);
2063 142029 : if (it != aFTable.end())
2064 141710 : return it->second;
2065 319 : return 0;
2066 : }
2067 :
2068 4813 : void SvNumberFormatter::ImpGenerateFormats( sal_uInt32 CLOffset, bool bNoAdditionalFormats )
2069 : {
2070 : using namespace ::com::sun::star;
2071 :
2072 : {
2073 4813 : osl::MutexGuard aGuard(&theIndexTable.maMtx);
2074 4813 : if (!theIndexTable.mbInitialized)
2075 : {
2076 6307 : for ( sal_uInt16 j=0; j<NF_INDEX_TABLE_ENTRIES; j++ )
2077 : {
2078 6188 : theIndexTable.maData[j] = NUMBERFORMAT_ENTRY_NOT_FOUND;
2079 : }
2080 4813 : }
2081 : }
2082 :
2083 4813 : bool bOldConvertMode = pFormatScanner->GetConvertMode();
2084 4813 : if (bOldConvertMode)
2085 : {
2086 238 : pFormatScanner->SetConvertMode(false); // switch off for this function
2087 : }
2088 :
2089 : NumberFormatCodeWrapper aNumberFormatCode( m_xContext,
2090 4813 : GetLanguageTag().getLocale() );
2091 4813 : SvNumberformat* pNewFormat = NULL;
2092 : sal_Int32 nIdx;
2093 : bool bDefault;
2094 :
2095 : // Counter for additional builtin formats not fitting into the first 10
2096 : // of a category (TLOT:=The Legacy Of Templin), altogether about 20 formats.
2097 : // Has to be incremented on each ImpInsertNewStandardformat, new formats
2098 : // must be appended, not inserted!
2099 4813 : sal_uInt16 nNewExtended = ZF_STANDARD_NEWEXTENDED;
2100 :
2101 : // Number
2102 : uno::Sequence< i18n::NumberFormatCode > aFormatSeq =
2103 9626 : aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::FIXED_NUMBER );
2104 4813 : ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() );
2105 :
2106 : // General
2107 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_STANDARD );
2108 4813 : SvNumberformat* pStdFormat = ImpInsertFormat( aFormatSeq[nIdx],
2109 9626 : CLOffset + SetIndexTable( NF_NUMBER_STANDARD, ZF_STANDARD ));
2110 4813 : if (pStdFormat)
2111 : {
2112 : // This is _the_ standard format.
2113 4813 : if (LocaleDataWrapper::areChecksEnabled() && pStdFormat->GetType() != css::util::NumberFormat::NUMBER)
2114 : {
2115 : LocaleDataWrapper::outputCheckMessage( xLocaleData->
2116 0 : appendLocaleInfo( "SvNumberFormatter::ImpGenerateFormats: General format not NUMBER"));
2117 : }
2118 4813 : pStdFormat->SetType( css::util::NumberFormat::NUMBER );
2119 4813 : pStdFormat->SetStandard();
2120 4813 : pStdFormat->SetLastInsertKey( SV_MAX_ANZ_STANDARD_FORMATE );
2121 : }
2122 : else
2123 : {
2124 0 : if (LocaleDataWrapper::areChecksEnabled())
2125 : {
2126 : LocaleDataWrapper::outputCheckMessage( xLocaleData->
2127 0 : appendLocaleInfo( "SvNumberFormatter::ImpGenerateFormats: General format not insertable, nothing will work"));
2128 : }
2129 : }
2130 :
2131 : // Boolean
2132 9626 : OUString aFormatCode = pFormatScanner->GetBooleanString();
2133 4813 : sal_Int32 nCheckPos = 0;
2134 :
2135 : pNewFormat = new SvNumberformat( aFormatCode, pFormatScanner,
2136 4813 : pStringScanner, nCheckPos, ActLnge );
2137 4813 : pNewFormat->SetType(css::util::NumberFormat::LOGICAL);
2138 4813 : pNewFormat->SetStandard();
2139 9626 : if ( !aFTable.insert(make_pair(
2140 4813 : CLOffset + SetIndexTable( NF_BOOLEAN, ZF_STANDARD_LOGICAL ),
2141 9626 : pNewFormat)).second)
2142 : {
2143 : SAL_WARN( "svl.numbers", "SvNumberFormatter::ImpGenerateFormats: dup position Boolean");
2144 0 : delete pNewFormat;
2145 : }
2146 :
2147 : // Text
2148 4813 : aFormatCode = "@";
2149 : pNewFormat = new SvNumberformat( aFormatCode, pFormatScanner,
2150 4813 : pStringScanner, nCheckPos, ActLnge );
2151 4813 : pNewFormat->SetType(css::util::NumberFormat::TEXT);
2152 4813 : pNewFormat->SetStandard();
2153 9626 : if ( !aFTable.insert(make_pair(
2154 4813 : CLOffset + SetIndexTable( NF_TEXT, ZF_STANDARD_TEXT ),
2155 9626 : pNewFormat)).second)
2156 : {
2157 : SAL_WARN( "svl.numbers", "SvNumberFormatter::ImpGenerateFormats: dup position Text");
2158 0 : delete pNewFormat;
2159 : }
2160 :
2161 :
2162 :
2163 : // 0
2164 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_INT );
2165 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2166 9626 : CLOffset + SetIndexTable( NF_NUMBER_INT, ZF_STANDARD+1 ));
2167 :
2168 : // 0.00
2169 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_DEC2 );
2170 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2171 9626 : CLOffset + SetIndexTable( NF_NUMBER_DEC2, ZF_STANDARD+2 ));
2172 :
2173 : // #,##0
2174 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_1000INT );
2175 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2176 9626 : CLOffset + SetIndexTable( NF_NUMBER_1000INT, ZF_STANDARD+3 ));
2177 :
2178 : // #,##0.00
2179 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_1000DEC2 );
2180 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2181 9626 : CLOffset + SetIndexTable( NF_NUMBER_1000DEC2, ZF_STANDARD+4 ));
2182 :
2183 : // #.##0,00 System country/language dependent
2184 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_SYSTEM );
2185 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2186 9626 : CLOffset + SetIndexTable( NF_NUMBER_SYSTEM, ZF_STANDARD+5 ));
2187 :
2188 :
2189 : // Percent number
2190 4813 : aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::PERCENT_NUMBER );
2191 4813 : ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() );
2192 :
2193 : // 0%
2194 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_PERCENT_INT );
2195 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2196 9626 : CLOffset + SetIndexTable( NF_PERCENT_INT, ZF_STANDARD_PERCENT ));
2197 :
2198 : // 0.00%
2199 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_PERCENT_DEC2 );
2200 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2201 9626 : CLOffset + SetIndexTable( NF_PERCENT_DEC2, ZF_STANDARD_PERCENT+1 ));
2202 :
2203 :
2204 :
2205 : // Currency. NO default standard option! Default is determined of locale
2206 : // data default currency and format is generated if needed.
2207 4813 : aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::CURRENCY );
2208 4813 : if (LocaleDataWrapper::areChecksEnabled())
2209 : {
2210 : // though no default desired here, test for correctness of locale data
2211 0 : ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() );
2212 : }
2213 :
2214 : // #,##0
2215 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000INT );
2216 4813 : bDefault = aFormatSeq[nIdx].Default;
2217 4813 : aFormatSeq[nIdx].Default = false;
2218 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2219 9626 : CLOffset + SetIndexTable( NF_CURRENCY_1000INT, ZF_STANDARD_CURRENCY ));
2220 4813 : aFormatSeq[nIdx].Default = bDefault;
2221 :
2222 : // #,##0.00
2223 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000DEC2 );
2224 4813 : bDefault = aFormatSeq[nIdx].Default;
2225 4813 : aFormatSeq[nIdx].Default = false;
2226 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2227 9626 : CLOffset + SetIndexTable( NF_CURRENCY_1000DEC2, ZF_STANDARD_CURRENCY+1 ));
2228 4813 : aFormatSeq[nIdx].Default = bDefault;
2229 :
2230 : // #,##0 negative red
2231 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000INT_RED );
2232 4813 : bDefault = aFormatSeq[nIdx].Default;
2233 4813 : aFormatSeq[nIdx].Default = false;
2234 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2235 9626 : CLOffset + SetIndexTable( NF_CURRENCY_1000INT_RED, ZF_STANDARD_CURRENCY+2 ));
2236 4813 : aFormatSeq[nIdx].Default = bDefault;
2237 :
2238 : // #,##0.00 negative red
2239 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000DEC2_RED );
2240 4813 : bDefault = aFormatSeq[nIdx].Default;
2241 4813 : aFormatSeq[nIdx].Default = false;
2242 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2243 9626 : CLOffset + SetIndexTable( NF_CURRENCY_1000DEC2_RED, ZF_STANDARD_CURRENCY+3 ));
2244 4813 : aFormatSeq[nIdx].Default = bDefault;
2245 :
2246 : // #,##0.00 USD
2247 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000DEC2_CCC );
2248 4813 : bDefault = aFormatSeq[nIdx].Default;
2249 4813 : aFormatSeq[nIdx].Default = false;
2250 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2251 9626 : CLOffset + SetIndexTable( NF_CURRENCY_1000DEC2_CCC, ZF_STANDARD_CURRENCY+4 ));
2252 4813 : aFormatSeq[nIdx].Default = bDefault;
2253 :
2254 : // #.##0,--
2255 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000DEC2_DASHED );
2256 4813 : bDefault = aFormatSeq[nIdx].Default;
2257 4813 : aFormatSeq[nIdx].Default = false;
2258 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2259 9626 : CLOffset + SetIndexTable( NF_CURRENCY_1000DEC2_DASHED, ZF_STANDARD_CURRENCY+5 ));
2260 4813 : aFormatSeq[nIdx].Default = bDefault;
2261 :
2262 :
2263 :
2264 : // Date
2265 4813 : aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::DATE );
2266 4813 : ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() );
2267 :
2268 : // DD.MM.YY System
2269 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYSTEM_SHORT );
2270 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2271 9626 : CLOffset + SetIndexTable( NF_DATE_SYSTEM_SHORT, ZF_STANDARD_DATE ));
2272 :
2273 : // NN DD.MMM YY
2274 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DEF_NNDDMMMYY );
2275 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2276 9626 : CLOffset + SetIndexTable( NF_DATE_DEF_NNDDMMMYY, ZF_STANDARD_DATE+1 ));
2277 :
2278 : // DD.MM.YY def/System
2279 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_MMYY );
2280 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2281 9626 : CLOffset + SetIndexTable( NF_DATE_SYS_MMYY, ZF_STANDARD_DATE+2 ));
2282 :
2283 : // DD MMM
2284 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DDMMM );
2285 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2286 9626 : CLOffset + SetIndexTable( NF_DATE_SYS_DDMMM, ZF_STANDARD_DATE+3 ));
2287 :
2288 : // MMMM
2289 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_MMMM );
2290 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2291 9626 : CLOffset + SetIndexTable( NF_DATE_MMMM, ZF_STANDARD_DATE+4 ));
2292 :
2293 : // QQ YY
2294 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_QQJJ );
2295 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2296 9626 : CLOffset + SetIndexTable( NF_DATE_QQJJ, ZF_STANDARD_DATE+5 ));
2297 :
2298 : // DD.MM.YYYY was DD.MM.[YY]YY
2299 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DDMMYYYY );
2300 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2301 9626 : CLOffset + SetIndexTable( NF_DATE_SYS_DDMMYYYY, ZF_STANDARD_DATE+6 ));
2302 :
2303 : // DD.MM.YY def/System
2304 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DDMMYY );
2305 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2306 9626 : CLOffset + SetIndexTable( NF_DATE_SYS_DDMMYY, ZF_STANDARD_DATE+7 ));
2307 :
2308 : // NNN, D. MMMM YYYY System
2309 : // Long day of week: "NNNN" instead of "NNN," because of compatibility
2310 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYSTEM_LONG );
2311 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2312 9626 : CLOffset + SetIndexTable( NF_DATE_SYSTEM_LONG, ZF_STANDARD_DATE+8 ));
2313 :
2314 : // Hard coded but system (regional settings) delimiters dependent long date formats
2315 :
2316 : // D. MMM YY def/System
2317 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DMMMYY );
2318 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2319 9626 : CLOffset + SetIndexTable( NF_DATE_SYS_DMMMYY, ZF_STANDARD_DATE+9 ));
2320 :
2321 : //! Unfortunately TLOT intended only 10 builtin formats per category, more
2322 : //! would overwrite the next category (ZF_STANDARD_TIME) :-((
2323 : //! Therefore they are inserted with nNewExtended++ (which is also limited)
2324 :
2325 : // D. MMM YYYY def/System
2326 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DMMMYYYY );
2327 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2328 9626 : CLOffset + SetIndexTable( NF_DATE_SYS_DMMMYYYY, nNewExtended++ ));
2329 :
2330 : // D. MMMM YYYY def/System
2331 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DMMMMYYYY );
2332 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2333 9626 : CLOffset + SetIndexTable( NF_DATE_SYS_DMMMMYYYY, nNewExtended++ ));
2334 :
2335 : // NN, D. MMM YY def/System
2336 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_NNDMMMYY );
2337 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2338 9626 : CLOffset + SetIndexTable( NF_DATE_SYS_NNDMMMYY, nNewExtended++ ));
2339 :
2340 : // NN, D. MMMM YYYY def/System
2341 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_NNDMMMMYYYY );
2342 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2343 9626 : CLOffset + SetIndexTable( NF_DATE_SYS_NNDMMMMYYYY, nNewExtended++ ));
2344 :
2345 : // NNN, D. MMMM YYYY def/System
2346 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_NNNNDMMMMYYYY );
2347 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2348 9626 : CLOffset + SetIndexTable( NF_DATE_SYS_NNNNDMMMMYYYY, nNewExtended++ ));
2349 :
2350 : // Hard coded DIN (Deutsche Industrie Norm) and EN (European Norm) date formats
2351 :
2352 : // D. MMM. YYYY DIN/EN
2353 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_DMMMYYYY );
2354 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2355 9626 : CLOffset + SetIndexTable( NF_DATE_DIN_DMMMYYYY, nNewExtended++ ));
2356 :
2357 : // D. MMMM YYYY DIN/EN
2358 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_DMMMMYYYY );
2359 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2360 9626 : CLOffset + SetIndexTable( NF_DATE_DIN_DMMMMYYYY, nNewExtended++ ));
2361 :
2362 : // MM-DD DIN/EN
2363 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_MMDD );
2364 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2365 9626 : CLOffset + SetIndexTable( NF_DATE_DIN_MMDD, nNewExtended++ ));
2366 :
2367 : // YY-MM-DD DIN/EN
2368 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_YYMMDD );
2369 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2370 9626 : CLOffset + SetIndexTable( NF_DATE_DIN_YYMMDD, nNewExtended++ ));
2371 :
2372 : // YYYY-MM-DD DIN/EN
2373 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_YYYYMMDD );
2374 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2375 9626 : CLOffset + SetIndexTable( NF_DATE_DIN_YYYYMMDD, nNewExtended++ ));
2376 :
2377 :
2378 :
2379 : // Time
2380 4813 : aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::TIME );
2381 4813 : ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() );
2382 :
2383 : // HH:MM
2384 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HHMM );
2385 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2386 9626 : CLOffset + SetIndexTable( NF_TIME_HHMM, ZF_STANDARD_TIME ));
2387 :
2388 : // HH:MM:SS
2389 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HHMMSS );
2390 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2391 9626 : CLOffset + SetIndexTable( NF_TIME_HHMMSS, ZF_STANDARD_TIME+1 ));
2392 :
2393 : // HH:MM AM/PM
2394 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HHMMAMPM );
2395 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2396 9626 : CLOffset + SetIndexTable( NF_TIME_HHMMAMPM, ZF_STANDARD_TIME+2 ));
2397 :
2398 : // HH:MM:SS AM/PM
2399 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HHMMSSAMPM );
2400 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2401 9626 : CLOffset + SetIndexTable( NF_TIME_HHMMSSAMPM, ZF_STANDARD_TIME+3 ));
2402 :
2403 : // [HH]:MM:SS
2404 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HH_MMSS );
2405 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2406 9626 : CLOffset + SetIndexTable( NF_TIME_HH_MMSS, ZF_STANDARD_TIME+4 ));
2407 :
2408 : // MM:SS,00
2409 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_MMSS00 );
2410 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2411 9626 : CLOffset + SetIndexTable( NF_TIME_MMSS00, ZF_STANDARD_TIME+5 ));
2412 :
2413 : // [HH]:MM:SS,00
2414 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HH_MMSS00 );
2415 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2416 9626 : CLOffset + SetIndexTable( NF_TIME_HH_MMSS00, ZF_STANDARD_TIME+6 ));
2417 :
2418 :
2419 :
2420 : // DateTime
2421 4813 : aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::DATE_TIME );
2422 4813 : ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() );
2423 :
2424 : // DD.MM.YY HH:MM System
2425 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATETIME_SYSTEM_SHORT_HHMM );
2426 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2427 9626 : CLOffset + SetIndexTable( NF_DATETIME_SYSTEM_SHORT_HHMM, ZF_STANDARD_DATETIME ));
2428 :
2429 : // DD.MM.YYYY HH:MM:SS System
2430 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATETIME_SYS_DDMMYYYY_HHMMSS );
2431 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2432 9626 : CLOffset + SetIndexTable( NF_DATETIME_SYS_DDMMYYYY_HHMMSS, ZF_STANDARD_DATETIME+1 ));
2433 :
2434 :
2435 :
2436 : // Scientific number
2437 4813 : aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::SCIENTIFIC_NUMBER );
2438 4813 : ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() );
2439 :
2440 : // 0.00E+000
2441 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_SCIENTIFIC_000E000 );
2442 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2443 9626 : CLOffset + SetIndexTable( NF_SCIENTIFIC_000E000, ZF_STANDARD_SCIENTIFIC ));
2444 :
2445 : // 0.00E+00
2446 4813 : nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_SCIENTIFIC_000E00 );
2447 4813 : ImpInsertFormat( aFormatSeq[nIdx],
2448 9626 : CLOffset + SetIndexTable( NF_SCIENTIFIC_000E00, ZF_STANDARD_SCIENTIFIC+1 ));
2449 :
2450 :
2451 :
2452 : // Fraction number (no default option)
2453 9626 : i18n::NumberFormatCode aSingleFormatCode;
2454 4813 : aSingleFormatCode.Usage = i18n::KNumberFormatUsage::FRACTION_NUMBER;
2455 :
2456 : // # ?/?
2457 4813 : aSingleFormatCode.Code = "# ?/?";
2458 : ImpInsertFormat( aSingleFormatCode,
2459 4813 : CLOffset + SetIndexTable( NF_FRACTION_1, ZF_STANDARD_FRACTION ));
2460 :
2461 : // # ??/??
2462 : //! "??/" would be interpreted by the compiler as a trigraph for '\'
2463 4813 : aSingleFormatCode.Code = "# ?\?/?\?";
2464 : ImpInsertFormat( aSingleFormatCode,
2465 4813 : CLOffset + SetIndexTable( NF_FRACTION_2, ZF_STANDARD_FRACTION+1 ));
2466 :
2467 : // # ?/4
2468 4813 : aSingleFormatCode.Code = "# ?/4";
2469 : ImpInsertFormat( aSingleFormatCode,
2470 4813 : CLOffset + SetIndexTable( NF_FRACTION_3, ZF_STANDARD_FRACTION+2 ));
2471 :
2472 : // # ??/100
2473 4813 : aSingleFormatCode.Code = "# ?\?/100";
2474 : ImpInsertFormat( aSingleFormatCode,
2475 4813 : CLOffset + SetIndexTable( NF_FRACTION_4, ZF_STANDARD_FRACTION+3 ));
2476 :
2477 :
2478 :
2479 : // Week of year must be appended here because of nNewExtended
2480 4813 : const NfKeywordTable & rKeyword = pFormatScanner->GetKeywords();
2481 4813 : aSingleFormatCode.Code = rKeyword[NF_KEY_WW];
2482 : ImpInsertFormat( aSingleFormatCode,
2483 4813 : CLOffset + SetIndexTable( NF_DATE_WW, nNewExtended++ ));
2484 :
2485 : {
2486 4813 : osl::MutexGuard aGuard(&theIndexTable.maMtx);
2487 4813 : theIndexTable.mbInitialized = true;
2488 : }
2489 : SAL_WARN_IF( nNewExtended > ZF_STANDARD_NEWEXTENDEDMAX, "svl.numbers",
2490 : "ImpGenerateFormats: overflow of nNewExtended standard formats" );
2491 : assert( nNewExtended <= ZF_STANDARD_NEWEXTENDEDMAX );
2492 :
2493 : // Now all additional format codes provided by I18N, but only if not
2494 : // changing SystemCL, then they are appended last after user defined.
2495 4813 : if ( !bNoAdditionalFormats )
2496 : {
2497 4813 : ImpGenerateAdditionalFormats( CLOffset, aNumberFormatCode, false );
2498 : }
2499 4813 : if (bOldConvertMode)
2500 : {
2501 238 : pFormatScanner->SetConvertMode(true);
2502 4813 : }
2503 4813 : }
2504 :
2505 :
2506 4813 : void SvNumberFormatter::ImpGenerateAdditionalFormats( sal_uInt32 CLOffset,
2507 : NumberFormatCodeWrapper& rNumberFormatCode, bool bAfterChangingSystemCL )
2508 : {
2509 : using namespace ::com::sun::star;
2510 :
2511 4813 : SvNumberformat* pStdFormat = GetFormatEntry( CLOffset + ZF_STANDARD );
2512 4813 : if ( !pStdFormat )
2513 : {
2514 : SAL_WARN( "svl.numbers", "ImpGenerateAdditionalFormats: no GENERAL format" );
2515 0 : return ;
2516 : }
2517 4813 : sal_uInt32 nPos = CLOffset + pStdFormat->GetLastInsertKey();
2518 4813 : rNumberFormatCode.setLocale( GetLanguageTag().getLocale() );
2519 : sal_Int32 j;
2520 :
2521 : // All currencies, this time with [$...] which was stripped in
2522 : // ImpGenerateFormats for old "automatic" currency formats.
2523 : uno::Sequence< i18n::NumberFormatCode > aFormatSeq =
2524 4813 : rNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::CURRENCY );
2525 4813 : i18n::NumberFormatCode * pFormatArr = aFormatSeq.getArray();
2526 4813 : sal_Int32 nCodes = aFormatSeq.getLength();
2527 4813 : ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), nCodes );
2528 43153 : for ( j = 0; j < nCodes; j++ )
2529 : {
2530 38340 : if ( nPos - CLOffset >= SV_COUNTRY_LANGUAGE_OFFSET )
2531 : {
2532 : SAL_WARN( "svl.numbers", "ImpGenerateAdditionalFormats: too many formats" );
2533 0 : break; // for
2534 : }
2535 67218 : if ( pFormatArr[j].Index < NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS &&
2536 28878 : pFormatArr[j].Index != NF_CURRENCY_1000DEC2_CCC )
2537 : { // Insert only if not already inserted, but internal index must be
2538 : // above so ImpInsertFormat can distinguish it.
2539 24065 : sal_Int16 nOrgIndex = pFormatArr[j].Index;
2540 24065 : pFormatArr[j].Index = sal::static_int_cast< sal_Int16 >(
2541 24065 : pFormatArr[j].Index + nCodes + NF_INDEX_TABLE_ENTRIES);
2542 : //! no default on currency
2543 24065 : bool bDefault = aFormatSeq[j].Default;
2544 24065 : aFormatSeq[j].Default = false;
2545 24065 : if ( SvNumberformat* pNewFormat = ImpInsertFormat( pFormatArr[j], nPos+1,
2546 24065 : bAfterChangingSystemCL, nOrgIndex ) )
2547 : {
2548 24065 : pNewFormat->SetAdditionalBuiltin();
2549 24065 : nPos++;
2550 : }
2551 24065 : pFormatArr[j].Index = nOrgIndex;
2552 24065 : aFormatSeq[j].Default = bDefault;
2553 : }
2554 : }
2555 :
2556 : // All additional format codes provided by I18N that are not old standard
2557 : // index. Additional formats may define defaults, currently there is no
2558 : // check if more than one default of a usage/type combination is provided,
2559 : // like it is done for usage groups with ImpAdjustFormatCodeDefault().
2560 : // There is no harm though, on first invocation ImpGetDefaultFormat() will
2561 : // use the first default encountered.
2562 4813 : aFormatSeq = rNumberFormatCode.getAllFormatCodes();
2563 4813 : nCodes = aFormatSeq.getLength();
2564 4813 : if ( nCodes )
2565 : {
2566 4813 : pFormatArr = aFormatSeq.getArray();
2567 296911 : for ( j = 0; j < nCodes; j++ )
2568 : {
2569 292098 : if ( nPos - CLOffset >= SV_COUNTRY_LANGUAGE_OFFSET )
2570 : {
2571 : SAL_WARN( "svl.numbers", "ImpGenerateAdditionalFormats: too many formats" );
2572 0 : break; // for
2573 : }
2574 292098 : if ( pFormatArr[j].Index >= NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS )
2575 : {
2576 70700 : if ( SvNumberformat* pNewFormat = ImpInsertFormat( pFormatArr[j], nPos+1,
2577 70700 : bAfterChangingSystemCL ) )
2578 : {
2579 70700 : pNewFormat->SetAdditionalBuiltin();
2580 70700 : nPos++;
2581 : }
2582 : }
2583 : }
2584 : }
2585 :
2586 4813 : pStdFormat->SetLastInsertKey( (sal_uInt16)(nPos - CLOffset) );
2587 : }
2588 :
2589 :
2590 0 : void SvNumberFormatter::ImpGetPosCurrFormat(OUStringBuffer& sPosStr, const OUString& rCurrSymbol)
2591 : {
2592 : NfCurrencyEntry::CompletePositiveFormatString( sPosStr,
2593 0 : rCurrSymbol, xLocaleData->getCurrPositiveFormat() );
2594 0 : }
2595 :
2596 0 : void SvNumberFormatter::ImpGetNegCurrFormat(OUStringBuffer& sNegStr, const OUString& rCurrSymbol)
2597 : {
2598 : NfCurrencyEntry::CompleteNegativeFormatString( sNegStr,
2599 0 : rCurrSymbol, xLocaleData->getCurrNegativeFormat() );
2600 0 : }
2601 :
2602 0 : sal_Int32 SvNumberFormatter::ImpPosToken ( const OUStringBuffer & sFormat, sal_Unicode token, sal_Int32 nStartPos /* = 0*/ )
2603 : {
2604 0 : sal_Int32 nLength = sFormat.getLength();
2605 0 : for ( sal_Int32 i=nStartPos; i<nLength && i>=0 ; i++ )
2606 : {
2607 0 : switch(sFormat[i])
2608 : {
2609 : case '\"' : // skip text
2610 0 : i = sFormat.indexOf('\"',i+1);
2611 0 : break;
2612 : case '[' : // skip condition
2613 0 : i = sFormat.indexOf(']',i+1);
2614 0 : break;
2615 : case '\\' : // skip escaped character
2616 0 : i++;
2617 0 : break;
2618 : case ';' :
2619 0 : if (token == ';')
2620 0 : return i;
2621 0 : break;
2622 : case 'e' :
2623 : case 'E' :
2624 0 : if (token == 'E')
2625 0 : return i; // if 'E' is outside "" and [] it must be the 'E' exponent
2626 0 : break;
2627 0 : default : break;
2628 : }
2629 0 : if ( i<0 )
2630 0 : i--;
2631 : }
2632 0 : return -2;
2633 : }
2634 :
2635 1375 : OUString SvNumberFormatter::GenerateFormat(sal_uInt32 nIndex,
2636 : LanguageType eLnge,
2637 : bool bThousand,
2638 : bool IsRed,
2639 : sal_uInt16 nPrecision,
2640 : sal_uInt16 nLeadingZeros)
2641 : {
2642 1375 : if (eLnge == LANGUAGE_DONTKNOW)
2643 : {
2644 0 : eLnge = IniLnge;
2645 : }
2646 1375 : short eType = GetType(nIndex);
2647 : sal_uInt16 i;
2648 1375 : ImpGenerateCL(eLnge); // create new standard formats if necessary
2649 :
2650 1375 : utl::DigitGroupingIterator aGrouping( xLocaleData->getDigitGrouping());
2651 : // always group of 3 for Engineering notation
2652 1375 : const sal_Int32 nDigitsInFirstGroup = ( bThousand && (eType == css::util::NumberFormat::SCIENTIFIC) ) ? 3 : aGrouping.get();
2653 1375 : const OUString& rThSep = GetNumThousandSep();
2654 :
2655 1375 : SvNumberformat* pFormat = GetFormatEntry( nIndex );
2656 :
2657 2750 : OUStringBuffer sString;
2658 : using comphelper::string::padToLength;
2659 :
2660 1375 : if (nLeadingZeros == 0)
2661 : {
2662 50 : if (!bThousand)
2663 50 : sString.append('#');
2664 : else
2665 : {
2666 0 : if (eType == css::util::NumberFormat::SCIENTIFIC)
2667 : { // for scientific, bThousand is used for Engineering notation
2668 0 : sString.append("###");
2669 : }
2670 : else
2671 : {
2672 0 : sString.append('#');
2673 0 : sString.append(rThSep);
2674 0 : padToLength(sString, sString.getLength() + nDigitsInFirstGroup, '#');
2675 : }
2676 : }
2677 : }
2678 : else
2679 : {
2680 2685 : for (i = 0; i < nLeadingZeros; i++)
2681 : {
2682 1360 : if (bThousand && i > 0 && i == aGrouping.getPos())
2683 : {
2684 0 : sString.insert(0, rThSep);
2685 0 : aGrouping.advance();
2686 : }
2687 1360 : sString.insert(0, '0');
2688 : }
2689 1325 : if ( bThousand )
2690 : {
2691 983 : sal_Int32 nDigits = (eType == css::util::NumberFormat::SCIENTIFIC) ? 3*((nLeadingZeros-1)/3 + 1) : nDigitsInFirstGroup + 1;
2692 3932 : for (i = nLeadingZeros; i < nDigits; i++)
2693 : {
2694 2949 : if ( i % nDigitsInFirstGroup == 0 )
2695 983 : sString.insert(0, rThSep);
2696 2949 : sString.insert(0, '#');
2697 : }
2698 : }
2699 : }
2700 1375 : if (nPrecision > 0)
2701 : {
2702 1032 : sString.append(GetNumDecimalSep());
2703 1032 : padToLength(sString, sString.getLength() + nPrecision, '0');
2704 : }
2705 1375 : if (eType == css::util::NumberFormat::PERCENT)
2706 : {
2707 0 : sString.append('%');
2708 : }
2709 1375 : else if (eType == css::util::NumberFormat::SCIENTIFIC)
2710 : {
2711 0 : OUStringBuffer sOldFormatString = pFormat->GetFormatstring();
2712 0 : sal_Int32 nIndexE = ImpPosToken( sOldFormatString, 'E' );
2713 0 : if (nIndexE > -1)
2714 : {
2715 0 : sal_Int32 nIndexSep = ImpPosToken( sOldFormatString, ';', nIndexE );
2716 0 : if (nIndexSep > nIndexE)
2717 0 : sString.append( sOldFormatString.copy(nIndexE, nIndexSep - nIndexE) );
2718 : else
2719 0 : sString.append( sOldFormatString.copy(nIndexE) );
2720 0 : }
2721 : }
2722 1375 : else if (eType == css::util::NumberFormat::CURRENCY)
2723 : {
2724 40 : OUStringBuffer sNegStr(sString);
2725 80 : OUString aCurr;
2726 : const NfCurrencyEntry* pEntry;
2727 : bool bBank;
2728 40 : if ( GetNewCurrencySymbolString( nIndex, aCurr, &pEntry, &bBank ) )
2729 : {
2730 40 : if ( pEntry )
2731 : {
2732 : sal_uInt16 nPosiForm = NfCurrencyEntry::GetEffectivePositiveFormat(
2733 10 : xLocaleData->getCurrPositiveFormat(),
2734 20 : pEntry->GetPositiveFormat(), bBank );
2735 : sal_uInt16 nNegaForm = NfCurrencyEntry::GetEffectiveNegativeFormat(
2736 10 : xLocaleData->getCurrNegativeFormat(),
2737 20 : pEntry->GetNegativeFormat(), bBank );
2738 10 : pEntry->CompletePositiveFormatString( sString, bBank, nPosiForm );
2739 10 : pEntry->CompleteNegativeFormatString( sNegStr, bBank, nNegaForm );
2740 : }
2741 : else
2742 : { // assume currency abbreviation (AKA banking symbol), not symbol
2743 : sal_uInt16 nPosiForm = NfCurrencyEntry::GetEffectivePositiveFormat(
2744 30 : xLocaleData->getCurrPositiveFormat(),
2745 60 : xLocaleData->getCurrPositiveFormat(), true );
2746 : sal_uInt16 nNegaForm = NfCurrencyEntry::GetEffectiveNegativeFormat(
2747 30 : xLocaleData->getCurrNegativeFormat(),
2748 60 : xLocaleData->getCurrNegativeFormat(), true );
2749 30 : NfCurrencyEntry::CompletePositiveFormatString( sString, aCurr, nPosiForm );
2750 30 : NfCurrencyEntry::CompleteNegativeFormatString( sNegStr, aCurr, nNegaForm );
2751 : }
2752 : }
2753 : else
2754 : { // "automatic" old style
2755 0 : OUString aSymbol, aAbbrev;
2756 0 : GetCompatibilityCurrency( aSymbol, aAbbrev );
2757 0 : ImpGetPosCurrFormat( sString, aSymbol );
2758 0 : ImpGetNegCurrFormat( sNegStr, aSymbol );
2759 : }
2760 40 : if (IsRed)
2761 : {
2762 0 : sString.append(';');
2763 0 : sString.append('[');
2764 0 : sString.append(pFormatScanner->GetRedString());
2765 0 : sString.append(']');
2766 : }
2767 : else
2768 : {
2769 40 : sString.append(';');
2770 : }
2771 80 : sString.append(sNegStr.makeStringAndClear());
2772 : }
2773 1375 : if (eType != css::util::NumberFormat::CURRENCY)
2774 : {
2775 1335 : bool insertBrackets = false;
2776 1335 : if ( eType != css::util::NumberFormat::UNDEFINED)
2777 : {
2778 1335 : insertBrackets = pFormat->IsNegativeInBracket();
2779 : }
2780 1335 : if (IsRed || insertBrackets)
2781 : {
2782 0 : OUStringBuffer sTmpStr(sString);
2783 :
2784 0 : if ( pFormat->HasPositiveBracketPlaceholder() )
2785 : {
2786 0 : sTmpStr.append('_');
2787 0 : sTmpStr.append(')');
2788 : }
2789 0 : sTmpStr.append(';');
2790 :
2791 0 : if (IsRed)
2792 : {
2793 0 : sTmpStr.append('[');
2794 0 : sTmpStr.append(pFormatScanner->GetRedString());
2795 0 : sTmpStr.append(']');
2796 : }
2797 :
2798 0 : if (insertBrackets)
2799 : {
2800 0 : sTmpStr.append('(');
2801 0 : sTmpStr.append(sString.toString());
2802 0 : sTmpStr.append(')');
2803 : }
2804 : else
2805 : {
2806 0 : sTmpStr.append('-');
2807 0 : sTmpStr.append(sString.toString());
2808 : }
2809 0 : sString = sTmpStr;
2810 : }
2811 : }
2812 2750 : return sString.makeStringAndClear();
2813 : }
2814 :
2815 0 : bool SvNumberFormatter::IsUserDefined(const OUString& sStr,
2816 : LanguageType eLnge)
2817 : {
2818 0 : if (eLnge == LANGUAGE_DONTKNOW)
2819 : {
2820 0 : eLnge = IniLnge;
2821 : }
2822 0 : sal_uInt32 CLOffset = ImpGenerateCL(eLnge); // create new standard formats if necessary
2823 0 : eLnge = ActLnge;
2824 :
2825 0 : sal_uInt32 nKey = ImpIsEntry(sStr, CLOffset, eLnge);
2826 0 : if (nKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
2827 : {
2828 0 : return true;
2829 : }
2830 0 : SvNumberformat* pEntry = GetFormatEntry( nKey );
2831 0 : if ( pEntry && ((pEntry->GetType() & css::util::NumberFormat::DEFINED) != 0) )
2832 : {
2833 0 : return true;
2834 : }
2835 0 : return false;
2836 : }
2837 :
2838 2602 : sal_uInt32 SvNumberFormatter::GetEntryKey(const OUString& sStr,
2839 : LanguageType eLnge)
2840 : {
2841 2602 : if (eLnge == LANGUAGE_DONTKNOW)
2842 : {
2843 0 : eLnge = IniLnge;
2844 : }
2845 2602 : sal_uInt32 CLOffset = ImpGenerateCL(eLnge); // create new standard formats if necessary
2846 2602 : return ImpIsEntry(sStr, CLOffset, eLnge);
2847 : }
2848 :
2849 7605 : sal_uInt32 SvNumberFormatter::GetStandardIndex(LanguageType eLnge)
2850 : {
2851 7605 : if (eLnge == LANGUAGE_DONTKNOW)
2852 : {
2853 0 : eLnge = IniLnge;
2854 : }
2855 7605 : return GetStandardFormat(css::util::NumberFormat::NUMBER, eLnge);
2856 : }
2857 :
2858 32345 : short SvNumberFormatter::GetType(sal_uInt32 nFIndex)
2859 : {
2860 : short eType;
2861 32345 : SvNumberformat* pFormat = GetFormatEntry( nFIndex );
2862 32345 : if (!pFormat)
2863 : {
2864 0 : eType = css::util::NumberFormat::UNDEFINED;
2865 : }
2866 : else
2867 : {
2868 32345 : eType = pFormat->GetType() &~css::util::NumberFormat::DEFINED;
2869 32345 : if (eType == 0)
2870 : {
2871 0 : eType = css::util::NumberFormat::DEFINED;
2872 : }
2873 : }
2874 32345 : return eType;
2875 : }
2876 :
2877 4464 : void SvNumberFormatter::ClearMergeTable()
2878 : {
2879 4464 : if ( pMergeTable )
2880 : {
2881 348 : pMergeTable->clear();
2882 : }
2883 4464 : }
2884 :
2885 187 : SvNumberFormatterIndexTable* SvNumberFormatter::MergeFormatter(SvNumberFormatter& rTable)
2886 : {
2887 187 : if ( pMergeTable )
2888 : {
2889 106 : ClearMergeTable();
2890 : }
2891 : else
2892 : {
2893 81 : pMergeTable = new SvNumberFormatterIndexTable;
2894 : }
2895 :
2896 187 : sal_uInt32 nCLOffset = 0;
2897 : sal_uInt32 nOldKey, nOffset, nNewKey;
2898 : SvNumberformat* pNewEntry;
2899 :
2900 187 : SvNumberFormatTable::iterator it = rTable.aFTable.begin();
2901 20228 : while (it != rTable.aFTable.end())
2902 : {
2903 19854 : SvNumberformat* pFormat = it->second;
2904 19854 : nOldKey = it->first;
2905 19854 : nOffset = nOldKey % SV_COUNTRY_LANGUAGE_OFFSET; // relative index
2906 19854 : if (nOffset == 0) // 1st format of CL
2907 : {
2908 288 : nCLOffset = ImpGenerateCL(pFormat->GetLanguage());
2909 : }
2910 19854 : if (nOffset <= SV_MAX_ANZ_STANDARD_FORMATE) // Std.form.
2911 : {
2912 14976 : nNewKey = nCLOffset + nOffset;
2913 14976 : if (aFTable.find( nNewKey) == aFTable.end()) // not already present
2914 : {
2915 : // pNewEntry = new SvNumberformat(*pFormat); // Copy is not sufficient!
2916 0 : pNewEntry = new SvNumberformat( *pFormat, *pFormatScanner );
2917 0 : if (!aFTable.insert(make_pair( nNewKey, pNewEntry)).second)
2918 : {
2919 : SAL_WARN( "svl.numbers", "SvNumberFormatter::MergeFormatter: dup position");
2920 0 : delete pNewEntry;
2921 : }
2922 : }
2923 14976 : if (nNewKey != nOldKey) // new index
2924 : {
2925 0 : (*pMergeTable)[nOldKey] = nNewKey;
2926 : }
2927 : }
2928 : else // user defined
2929 : {
2930 : // pNewEntry = new SvNumberformat(*pFormat); // Copy is not sufficient!
2931 4878 : pNewEntry = new SvNumberformat( *pFormat, *pFormatScanner );
2932 4878 : nNewKey = ImpIsEntry(pNewEntry->GetFormatstring(),
2933 : nCLOffset,
2934 9756 : pFormat->GetLanguage());
2935 4878 : if (nNewKey != NUMBERFORMAT_ENTRY_NOT_FOUND) // already present
2936 : {
2937 4845 : delete pNewEntry;
2938 : }
2939 : else
2940 : {
2941 33 : SvNumberformat* pStdFormat = GetFormatEntry(nCLOffset + ZF_STANDARD);
2942 33 : sal_uInt32 nPos = nCLOffset + pStdFormat->GetLastInsertKey();
2943 33 : nNewKey = nPos+1;
2944 33 : if (nNewKey - nCLOffset >= SV_COUNTRY_LANGUAGE_OFFSET)
2945 : {
2946 : SAL_WARN( "svl.numbers", "SvNumberFormatter::MergeFormatter: too many formats for CL");
2947 0 : delete pNewEntry;
2948 : }
2949 33 : else if (!aFTable.insert(make_pair( nNewKey, pNewEntry)).second)
2950 : {
2951 : SAL_WARN( "svl.numbers", "SvNumberFormatter::MergeFormatter: dup position");
2952 0 : delete pNewEntry;
2953 : }
2954 : else
2955 : {
2956 33 : pStdFormat->SetLastInsertKey((sal_uInt16) (nNewKey - nCLOffset));
2957 : }
2958 : }
2959 4878 : if (nNewKey != nOldKey) // new index
2960 : {
2961 6 : (*pMergeTable)[nOldKey] = nNewKey;
2962 : }
2963 : }
2964 19854 : ++it;
2965 : }
2966 187 : return pMergeTable;
2967 : }
2968 :
2969 :
2970 7 : SvNumberFormatterMergeMap SvNumberFormatter::ConvertMergeTableToMap()
2971 : {
2972 7 : if (!HasMergeFormatTable())
2973 : {
2974 6 : return SvNumberFormatterMergeMap();
2975 : }
2976 1 : SvNumberFormatterMergeMap aMap;
2977 2 : for (SvNumberFormatterIndexTable::iterator it = pMergeTable->begin(); it != pMergeTable->end(); ++it)
2978 : {
2979 1 : sal_uInt32 nOldKey = it->first;
2980 1 : aMap[ nOldKey ] = it->second;
2981 : }
2982 1 : ClearMergeTable();
2983 1 : return aMap;
2984 : }
2985 :
2986 :
2987 73637 : sal_uInt32 SvNumberFormatter::GetFormatForLanguageIfBuiltIn( sal_uInt32 nFormat,
2988 : LanguageType eLnge )
2989 : {
2990 73637 : if ( eLnge == LANGUAGE_DONTKNOW )
2991 : {
2992 0 : eLnge = IniLnge;
2993 : }
2994 73637 : if ( nFormat < SV_COUNTRY_LANGUAGE_OFFSET && eLnge == IniLnge )
2995 : {
2996 72684 : return nFormat; // it stays as it is
2997 : }
2998 953 : sal_uInt32 nOffset = nFormat % SV_COUNTRY_LANGUAGE_OFFSET; // relative index
2999 953 : if ( nOffset > SV_MAX_ANZ_STANDARD_FORMATE )
3000 : {
3001 6 : return nFormat; // not a built-in format
3002 : }
3003 947 : sal_uInt32 nCLOffset = ImpGenerateCL(eLnge); // create new standard formats if necessary
3004 947 : return nCLOffset + nOffset;
3005 : }
3006 :
3007 :
3008 17282 : sal_uInt32 SvNumberFormatter::GetFormatIndex( NfIndexTableOffset nTabOff,
3009 : LanguageType eLnge )
3010 : {
3011 17282 : if (nTabOff >= NF_INDEX_TABLE_ENTRIES)
3012 0 : return NUMBERFORMAT_ENTRY_NOT_FOUND;
3013 :
3014 17282 : if (eLnge == LANGUAGE_DONTKNOW)
3015 21 : eLnge = IniLnge;
3016 :
3017 : {
3018 17282 : osl::MutexGuard aGuard(&theIndexTable.maMtx);
3019 17282 : if (theIndexTable.maData[nTabOff] == NUMBERFORMAT_ENTRY_NOT_FOUND)
3020 0 : return NUMBERFORMAT_ENTRY_NOT_FOUND;
3021 : }
3022 :
3023 17282 : sal_uInt32 nCLOffset = ImpGenerateCL(eLnge); // create new standard formats if necessary
3024 :
3025 : {
3026 17282 : osl::MutexGuard aGuard(&theIndexTable.maMtx);
3027 17282 : return nCLOffset + theIndexTable.maData[nTabOff];
3028 : }
3029 : }
3030 :
3031 :
3032 2664 : NfIndexTableOffset SvNumberFormatter::GetIndexTableOffset( sal_uInt32 nFormat ) const
3033 : {
3034 2664 : sal_uInt32 nOffset = nFormat % SV_COUNTRY_LANGUAGE_OFFSET; // relative index
3035 2664 : if ( nOffset > SV_MAX_ANZ_STANDARD_FORMATE )
3036 : {
3037 1675 : return NF_INDEX_TABLE_ENTRIES; // not a built-in format
3038 : }
3039 :
3040 : {
3041 989 : osl::MutexGuard aGuard(&theIndexTable.maMtx);
3042 8374 : for ( sal_uInt16 j = 0; j < NF_INDEX_TABLE_ENTRIES; j++ )
3043 : {
3044 8374 : if (theIndexTable.maData[j] == nOffset)
3045 989 : return (NfIndexTableOffset) j;
3046 0 : }
3047 : }
3048 0 : return NF_INDEX_TABLE_ENTRIES; // bad luck
3049 : }
3050 :
3051 3767 : void SvNumberFormatter::SetEvalDateFormat( NfEvalDateFormat eEDF )
3052 : {
3053 3767 : eEvalDateFormat = eEDF;
3054 3767 : }
3055 :
3056 8 : NfEvalDateFormat SvNumberFormatter::GetEvalDateFormat() const
3057 : {
3058 8 : return eEvalDateFormat;
3059 : }
3060 :
3061 5661 : void SvNumberFormatter::SetYear2000( sal_uInt16 nVal )
3062 : {
3063 5661 : pStringScanner->SetYear2000( nVal );
3064 5661 : }
3065 :
3066 :
3067 79 : sal_uInt16 SvNumberFormatter::GetYear2000() const
3068 : {
3069 79 : return pStringScanner->GetYear2000();
3070 : }
3071 :
3072 :
3073 0 : sal_uInt16 SvNumberFormatter::ExpandTwoDigitYear( sal_uInt16 nYear ) const
3074 : {
3075 0 : if ( nYear < 100 )
3076 : return SvNumberFormatter::ExpandTwoDigitYear( nYear,
3077 0 : pStringScanner->GetYear2000() );
3078 0 : return nYear;
3079 : }
3080 :
3081 :
3082 : // static
3083 7926 : sal_uInt16 SvNumberFormatter::GetYear2000Default()
3084 : {
3085 7926 : return (sal_uInt16) ::utl::MiscCfg().GetYear2000();
3086 : }
3087 :
3088 :
3089 : // static
3090 858 : const NfCurrencyTable& SvNumberFormatter::GetTheCurrencyTable()
3091 : {
3092 858 : ::osl::MutexGuard aGuard( GetMutex() );
3093 1759 : while ( !bCurrencyTableInitialized )
3094 43 : ImpInitCurrencyTable();
3095 858 : return theCurrencyTable::get();
3096 : }
3097 :
3098 :
3099 : // static
3100 506 : const NfCurrencyEntry* SvNumberFormatter::MatchSystemCurrency()
3101 : {
3102 : // MUST call GetTheCurrencyTable() before accessing nSystemCurrencyPosition
3103 506 : const NfCurrencyTable& rTable = GetTheCurrencyTable();
3104 506 : return nSystemCurrencyPosition ? &rTable[nSystemCurrencyPosition] : NULL;
3105 : }
3106 :
3107 :
3108 : // static
3109 769 : const NfCurrencyEntry& SvNumberFormatter::GetCurrencyEntry( LanguageType eLang )
3110 : {
3111 769 : if ( eLang == LANGUAGE_SYSTEM )
3112 : {
3113 496 : const NfCurrencyEntry* pCurr = MatchSystemCurrency();
3114 496 : return pCurr ? *pCurr : GetTheCurrencyTable()[0];
3115 : }
3116 : else
3117 : {
3118 273 : eLang = MsLangId::getRealLanguage( eLang );
3119 273 : const NfCurrencyTable& rTable = GetTheCurrencyTable();
3120 273 : sal_uInt16 nCount = rTable.size();
3121 550 : for ( sal_uInt16 j = 0; j < nCount; j++ )
3122 : {
3123 550 : if ( rTable[j].GetLanguage() == eLang )
3124 273 : return rTable[j];
3125 : }
3126 0 : return rTable[0];
3127 : }
3128 : }
3129 :
3130 :
3131 : // static
3132 0 : const NfCurrencyEntry* SvNumberFormatter::GetCurrencyEntry(const OUString& rAbbrev, LanguageType eLang )
3133 : {
3134 0 : eLang = MsLangId::getRealLanguage( eLang );
3135 0 : const NfCurrencyTable& rTable = GetTheCurrencyTable();
3136 0 : sal_uInt16 nCount = rTable.size();
3137 0 : for ( sal_uInt16 j = 0; j < nCount; j++ )
3138 : {
3139 0 : if ( rTable[j].GetLanguage() == eLang &&
3140 0 : rTable[j].GetBankSymbol() == rAbbrev )
3141 : {
3142 0 : return &rTable[j];
3143 : }
3144 : }
3145 0 : return NULL;
3146 : }
3147 :
3148 :
3149 : // static
3150 0 : const NfCurrencyEntry* SvNumberFormatter::GetLegacyOnlyCurrencyEntry( const OUString& rSymbol,
3151 : const OUString& rAbbrev )
3152 : {
3153 0 : if (!bCurrencyTableInitialized)
3154 : {
3155 0 : GetTheCurrencyTable(); // just for initialization
3156 : }
3157 0 : const NfCurrencyTable& rTable = theLegacyOnlyCurrencyTable::get();
3158 0 : sal_uInt16 nCount = rTable.size();
3159 0 : for ( sal_uInt16 j = 0; j < nCount; j++ )
3160 : {
3161 0 : if ( rTable[j].GetSymbol() == rSymbol &&
3162 0 : rTable[j].GetBankSymbol() == rAbbrev )
3163 : {
3164 0 : return &rTable[j];
3165 : }
3166 : }
3167 0 : return NULL;
3168 : }
3169 :
3170 :
3171 : // static
3172 0 : IMPL_STATIC_LINK_NOARG( SvNumberFormatter, CurrencyChangeLink )
3173 : {
3174 0 : ::osl::MutexGuard aGuard( GetMutex() );
3175 0 : OUString aAbbrev;
3176 0 : LanguageType eLang = LANGUAGE_SYSTEM;
3177 0 : SvtSysLocaleOptions().GetCurrencyAbbrevAndLanguage( aAbbrev, eLang );
3178 0 : SetDefaultSystemCurrency( aAbbrev, eLang );
3179 0 : return 0;
3180 : }
3181 :
3182 :
3183 : // static
3184 0 : void SvNumberFormatter::SetDefaultSystemCurrency( const OUString& rAbbrev, LanguageType eLang )
3185 : {
3186 0 : ::osl::MutexGuard aGuard( GetMutex() );
3187 0 : if ( eLang == LANGUAGE_SYSTEM )
3188 : {
3189 0 : eLang = SvtSysLocale().GetLanguageTag().getLanguageType();
3190 : }
3191 0 : const NfCurrencyTable& rTable = GetTheCurrencyTable();
3192 0 : sal_uInt16 nCount = rTable.size();
3193 0 : if ( !rAbbrev.isEmpty() )
3194 : {
3195 0 : for ( sal_uInt16 j = 0; j < nCount; j++ )
3196 : {
3197 0 : if ( rTable[j].GetLanguage() == eLang && rTable[j].GetBankSymbol() == rAbbrev )
3198 : {
3199 0 : nSystemCurrencyPosition = j;
3200 0 : return ;
3201 : }
3202 : }
3203 : }
3204 : else
3205 : {
3206 0 : for ( sal_uInt16 j = 0; j < nCount; j++ )
3207 : {
3208 0 : if ( rTable[j].GetLanguage() == eLang )
3209 : {
3210 0 : nSystemCurrencyPosition = j;
3211 0 : return ;
3212 : }
3213 : }
3214 : }
3215 0 : nSystemCurrencyPosition = 0; // not found => simple SYSTEM
3216 : }
3217 :
3218 :
3219 0 : void SvNumberFormatter::ResetDefaultSystemCurrency()
3220 : {
3221 0 : nDefaultSystemCurrencyFormat = NUMBERFORMAT_ENTRY_NOT_FOUND;
3222 0 : }
3223 :
3224 :
3225 0 : void SvNumberFormatter::InvalidateDateAcceptancePatterns()
3226 : {
3227 0 : pStringScanner->InvalidateDateAcceptancePatterns();
3228 0 : }
3229 :
3230 :
3231 346 : sal_uInt32 SvNumberFormatter::ImpGetDefaultSystemCurrencyFormat()
3232 : {
3233 346 : if ( nDefaultSystemCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
3234 : {
3235 : sal_Int32 nCheck;
3236 : short nType;
3237 176 : NfWSStringsDtor aCurrList;
3238 : sal_uInt16 nDefault = GetCurrencyFormatStrings( aCurrList,
3239 176 : GetCurrencyEntry( LANGUAGE_SYSTEM ), false );
3240 : DBG_ASSERT( aCurrList.size(), "where is the NewCurrency System standard format?!?" );
3241 : // if already loaded or user defined nDefaultSystemCurrencyFormat
3242 : // will be set to the right value
3243 176 : PutEntry( aCurrList[ nDefault ], nCheck, nType,
3244 352 : nDefaultSystemCurrencyFormat, LANGUAGE_SYSTEM );
3245 : DBG_ASSERT( nCheck == 0, "NewCurrency CheckError" );
3246 : DBG_ASSERT( nDefaultSystemCurrencyFormat != NUMBERFORMAT_ENTRY_NOT_FOUND,
3247 176 : "nDefaultSystemCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND" );
3248 : }
3249 346 : return nDefaultSystemCurrencyFormat;
3250 : }
3251 :
3252 :
3253 0 : sal_uInt32 SvNumberFormatter::ImpGetDefaultCurrencyFormat()
3254 : {
3255 0 : sal_uInt32 CLOffset = ImpGetCLOffset( ActLnge );
3256 0 : DefaultFormatKeysMap::iterator it = aDefaultFormatKeys.find( CLOffset + ZF_STANDARD_CURRENCY );
3257 0 : sal_uInt32 nDefaultCurrencyFormat = (it != aDefaultFormatKeys.end() ?
3258 0 : it->second : NUMBERFORMAT_ENTRY_NOT_FOUND);
3259 0 : if ( nDefaultCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
3260 : {
3261 : // look for a defined standard
3262 0 : sal_uInt32 nStopKey = CLOffset + SV_COUNTRY_LANGUAGE_OFFSET;
3263 0 : sal_uInt32 nKey(0);
3264 0 : SvNumberFormatTable::iterator it2 = aFTable.lower_bound( CLOffset );
3265 0 : while ( it2 != aFTable.end() && (nKey = it2->first) >= CLOffset && nKey < nStopKey )
3266 : {
3267 0 : const SvNumberformat* pEntry = it2->second;
3268 0 : if ( pEntry->IsStandard() && (pEntry->GetType() & css::util::NumberFormat::CURRENCY) )
3269 : {
3270 0 : nDefaultCurrencyFormat = nKey;
3271 0 : break; // while
3272 : }
3273 0 : ++it2;
3274 : }
3275 :
3276 0 : if ( nDefaultCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
3277 : { // none found, create one
3278 : sal_Int32 nCheck;
3279 0 : NfWSStringsDtor aCurrList;
3280 : sal_uInt16 nDefault = GetCurrencyFormatStrings( aCurrList,
3281 0 : GetCurrencyEntry( ActLnge ), false );
3282 : DBG_ASSERT( aCurrList.size(), "where is the NewCurrency standard format?" );
3283 0 : if ( !aCurrList.empty() )
3284 : {
3285 : // if already loaded or user defined nDefaultSystemCurrencyFormat
3286 : // will be set to the right value
3287 : short nType;
3288 0 : PutEntry( aCurrList[ nDefault ], nCheck, nType,
3289 0 : nDefaultCurrencyFormat, ActLnge );
3290 : DBG_ASSERT( nCheck == 0, "NewCurrency CheckError" );
3291 : DBG_ASSERT( nDefaultCurrencyFormat != NUMBERFORMAT_ENTRY_NOT_FOUND,
3292 : "nDefaultCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND" );
3293 : }
3294 : // old automatic currency format as a last resort
3295 0 : if ( nDefaultCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
3296 0 : nDefaultCurrencyFormat = CLOffset + ZF_STANDARD_CURRENCY+3;
3297 : else
3298 : { // mark as standard so that it is found next time
3299 0 : SvNumberformat* pEntry = GetFormatEntry( nDefaultCurrencyFormat );
3300 0 : if ( pEntry )
3301 0 : pEntry->SetStandard();
3302 0 : }
3303 : }
3304 0 : aDefaultFormatKeys[ CLOffset + ZF_STANDARD_CURRENCY ] = nDefaultCurrencyFormat;
3305 : }
3306 0 : return nDefaultCurrencyFormat;
3307 : }
3308 :
3309 :
3310 : // static
3311 : // true: continue; false: break loop, if pFoundEntry==NULL dupe found
3312 9246 : bool SvNumberFormatter::ImpLookupCurrencyEntryLoopBody(
3313 : const NfCurrencyEntry*& pFoundEntry, bool& bFoundBank, const NfCurrencyEntry* pData,
3314 : sal_uInt16 nPos, const OUString& rSymbol )
3315 : {
3316 : bool bFound;
3317 9246 : if ( pData->GetSymbol() == rSymbol )
3318 : {
3319 36 : bFound = true;
3320 36 : bFoundBank = false;
3321 : }
3322 9210 : else if ( pData->GetBankSymbol() == rSymbol )
3323 : {
3324 0 : bFound = true;
3325 0 : bFoundBank = true;
3326 : }
3327 : else
3328 9210 : bFound = false;
3329 9246 : if ( bFound )
3330 : {
3331 36 : if ( pFoundEntry && pFoundEntry != pData )
3332 : {
3333 0 : pFoundEntry = NULL;
3334 0 : return false; // break loop, not unique
3335 : }
3336 36 : if ( nPos == 0 )
3337 : { // first entry is SYSTEM
3338 10 : pFoundEntry = MatchSystemCurrency();
3339 10 : if ( pFoundEntry )
3340 : {
3341 10 : return false; // break loop
3342 : // even if there are more matching entries
3343 : // this one is probably the one we are looking for
3344 : }
3345 : else
3346 : {
3347 0 : pFoundEntry = pData;
3348 : }
3349 : }
3350 : else
3351 : {
3352 26 : pFoundEntry = pData;
3353 : }
3354 : }
3355 9236 : return true;
3356 : }
3357 :
3358 :
3359 40 : bool SvNumberFormatter::GetNewCurrencySymbolString( sal_uInt32 nFormat, OUString& rStr,
3360 : const NfCurrencyEntry** ppEntry /* = NULL */,
3361 : bool* pBank /* = NULL */ ) const
3362 : {
3363 40 : if ( ppEntry )
3364 40 : *ppEntry = NULL;
3365 40 : if ( pBank )
3366 40 : *pBank = false;
3367 :
3368 40 : const SvNumberformat* pFormat = GetFormatEntry(nFormat);
3369 40 : if ( pFormat )
3370 : {
3371 40 : OUStringBuffer sBuff(128); // guess-estimate of a value that will pretty much guarantee no re-alloc
3372 40 : OUString aSymbol, aExtension;
3373 40 : if ( pFormat->GetNewCurrencySymbol( aSymbol, aExtension ) )
3374 : {
3375 40 : if ( ppEntry )
3376 : {
3377 40 : bool bFoundBank = false;
3378 : // we definiteley need an entry matching the format code string
3379 : const NfCurrencyEntry* pFoundEntry = GetCurrencyEntry(
3380 40 : bFoundBank, aSymbol, aExtension, pFormat->GetLanguage(),
3381 40 : true );
3382 40 : if ( pFoundEntry )
3383 : {
3384 10 : *ppEntry = pFoundEntry;
3385 10 : if ( pBank )
3386 10 : *pBank = bFoundBank;
3387 10 : rStr = pFoundEntry->BuildSymbolString(bFoundBank);
3388 : }
3389 : }
3390 40 : if ( rStr.isEmpty() )
3391 : { // analog to BuildSymbolString
3392 30 : sBuff.append("[$");
3393 60 : if ( aSymbol.indexOf( '-' ) != -1 ||
3394 30 : aSymbol.indexOf( ']' ) != -1 )
3395 : {
3396 0 : sBuff.append('"');
3397 0 : sBuff.append( aSymbol);
3398 0 : sBuff.append('"');
3399 : }
3400 : else
3401 : {
3402 30 : sBuff.append(aSymbol);
3403 : }
3404 30 : if ( !aExtension.isEmpty() )
3405 : {
3406 0 : sBuff.append(aExtension);
3407 : }
3408 30 : sBuff.append(']');
3409 : }
3410 40 : rStr = sBuff.toString();
3411 40 : return true;
3412 0 : }
3413 : }
3414 0 : rStr.clear();
3415 0 : return false;
3416 : }
3417 :
3418 :
3419 : // static
3420 66 : const NfCurrencyEntry* SvNumberFormatter::GetCurrencyEntry( bool & bFoundBank,
3421 : const OUString& rSymbol,
3422 : const OUString& rExtension,
3423 : LanguageType eFormatLanguage,
3424 : bool bOnlyStringLanguage )
3425 : {
3426 66 : sal_Int32 nExtLen = rExtension.getLength();
3427 : LanguageType eExtLang;
3428 66 : if ( nExtLen )
3429 : {
3430 : // rExtension should be a 16-bit hex value max FFFF which may contain a
3431 : // leading "-" separator (that is not a minus sign, but toInt32 can be
3432 : // used to parse it, with post-processing as necessary):
3433 26 : sal_Int32 nExtLang = rExtension.toInt32( 16 );
3434 26 : if ( !nExtLang )
3435 : {
3436 0 : eExtLang = LANGUAGE_DONTKNOW;
3437 : }
3438 : else
3439 : {
3440 26 : eExtLang = (LanguageType) ((nExtLang < 0) ? -nExtLang : nExtLang);
3441 : }
3442 : }
3443 : else
3444 : {
3445 40 : eExtLang = LANGUAGE_DONTKNOW;
3446 : }
3447 66 : const NfCurrencyEntry* pFoundEntry = NULL;
3448 66 : const NfCurrencyTable& rTable = GetTheCurrencyTable();
3449 66 : sal_uInt16 nCount = rTable.size();
3450 66 : bool bCont = true;
3451 :
3452 : // first try with given extension language/country
3453 66 : if ( nExtLen )
3454 : {
3455 8008 : for ( sal_uInt16 j = 0; j < nCount && bCont; j++ )
3456 : {
3457 7982 : LanguageType eLang = rTable[j].GetLanguage();
3458 7982 : if ( eLang == eExtLang ||
3459 0 : ((eExtLang == LANGUAGE_DONTKNOW) &&
3460 : (eLang == LANGUAGE_SYSTEM)))
3461 : {
3462 : bCont = ImpLookupCurrencyEntryLoopBody( pFoundEntry, bFoundBank,
3463 26 : &rTable[j], j, rSymbol );
3464 : }
3465 : }
3466 : }
3467 :
3468 : // ok?
3469 66 : if ( pFoundEntry || !bCont || (bOnlyStringLanguage && nExtLen) )
3470 : {
3471 26 : return pFoundEntry;
3472 : }
3473 40 : if ( !bOnlyStringLanguage )
3474 : {
3475 : // now try the language/country of the number format
3476 0 : for ( sal_uInt16 j = 0; j < nCount && bCont; j++ )
3477 : {
3478 0 : LanguageType eLang = rTable[j].GetLanguage();
3479 0 : if ( eLang == eFormatLanguage ||
3480 0 : ((eFormatLanguage == LANGUAGE_DONTKNOW) &&
3481 : (eLang == LANGUAGE_SYSTEM)))
3482 : {
3483 : bCont = ImpLookupCurrencyEntryLoopBody( pFoundEntry, bFoundBank,
3484 0 : &rTable[j], j, rSymbol );
3485 : }
3486 : }
3487 :
3488 : // ok?
3489 0 : if ( pFoundEntry || !bCont )
3490 : {
3491 0 : return pFoundEntry;
3492 : }
3493 : }
3494 :
3495 : // then try without language/country if no extension specified
3496 40 : if ( !nExtLen )
3497 : {
3498 9260 : for ( sal_uInt16 j = 0; j < nCount && bCont; j++ )
3499 : {
3500 : bCont = ImpLookupCurrencyEntryLoopBody( pFoundEntry, bFoundBank,
3501 9220 : &rTable[j], j, rSymbol );
3502 : }
3503 : }
3504 :
3505 40 : return pFoundEntry;
3506 : }
3507 :
3508 :
3509 16110 : void SvNumberFormatter::GetCompatibilityCurrency( OUString& rSymbol, OUString& rAbbrev ) const
3510 : {
3511 : ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Currency2 >
3512 16110 : xCurrencies( xLocaleData->getAllCurrencies() );
3513 :
3514 16110 : const ::com::sun::star::i18n::Currency2 *pCurrencies = xCurrencies.getConstArray();
3515 16110 : sal_Int32 nCurrencies = xCurrencies.getLength();
3516 :
3517 : sal_Int32 j;
3518 16150 : for ( j=0; j < nCurrencies; ++j )
3519 : {
3520 16150 : if ( pCurrencies[j].UsedInCompatibleFormatCodes )
3521 : {
3522 16110 : rSymbol = pCurrencies[j].Symbol;
3523 16110 : rAbbrev = pCurrencies[j].BankSymbol;
3524 16110 : break;
3525 : }
3526 : }
3527 16110 : if ( j >= nCurrencies )
3528 : {
3529 0 : if (LocaleDataWrapper::areChecksEnabled())
3530 : {
3531 : LocaleDataWrapper::outputCheckMessage( xLocaleData->
3532 0 : appendLocaleInfo( "GetCompatibilityCurrency: none?"));
3533 : }
3534 0 : rSymbol = xLocaleData->getCurrSymbol();
3535 0 : rAbbrev = xLocaleData->getCurrBankSymbol();
3536 16110 : }
3537 16110 : }
3538 :
3539 :
3540 0 : static void lcl_CheckCurrencySymbolPosition( const NfCurrencyEntry& rCurr )
3541 : {
3542 0 : switch ( rCurr.GetPositiveFormat() )
3543 : {
3544 : case 0: // $1
3545 : case 1: // 1$
3546 : case 2: // $ 1
3547 : case 3: // 1 $
3548 0 : break;
3549 : default:
3550 0 : LocaleDataWrapper::outputCheckMessage( "lcl_CheckCurrencySymbolPosition: unknown PositiveFormat");
3551 0 : break;
3552 : }
3553 0 : switch ( rCurr.GetNegativeFormat() )
3554 : {
3555 : case 0: // ($1)
3556 : case 1: // -$1
3557 : case 2: // $-1
3558 : case 3: // $1-
3559 : case 4: // (1$)
3560 : case 5: // -1$
3561 : case 6: // 1-$
3562 : case 7: // 1$-
3563 : case 8: // -1 $
3564 : case 9: // -$ 1
3565 : case 10: // 1 $-
3566 : case 11: // $ -1
3567 : case 12 : // $ 1-
3568 : case 13 : // 1- $
3569 : case 14 : // ($ 1)
3570 : case 15 : // (1 $)
3571 0 : break;
3572 : default:
3573 0 : LocaleDataWrapper::outputCheckMessage( "lcl_CheckCurrencySymbolPosition: unknown NegativeFormat");
3574 0 : break;
3575 : }
3576 0 : }
3577 :
3578 : // static
3579 13 : bool SvNumberFormatter::IsLocaleInstalled( LanguageType eLang )
3580 : {
3581 : // The set is initialized as a side effect of the currency table
3582 : // created, make sure that exists, which usually is the case unless a
3583 : // SvNumberFormatter was never instantiated.
3584 13 : GetTheCurrencyTable();
3585 13 : const NfInstalledLocales &rInstalledLocales = theInstalledLocales::get();
3586 13 : return rInstalledLocales.find( eLang) != rInstalledLocales.end();
3587 : }
3588 :
3589 : // static
3590 43 : void SvNumberFormatter::ImpInitCurrencyTable()
3591 : {
3592 : // Race condition possible:
3593 : // ::osl::MutexGuard aGuard( GetMutex() );
3594 : // while ( !bCurrencyTableInitialized )
3595 : // ImpInitCurrencyTable();
3596 : static bool bInitializing = false;
3597 43 : if ( bCurrencyTableInitialized || bInitializing )
3598 : {
3599 43 : return ;
3600 : }
3601 43 : bInitializing = true;
3602 :
3603 43 : LanguageType eSysLang = SvtSysLocale().GetLanguageTag().getLanguageType();
3604 : boost::scoped_ptr<LocaleDataWrapper> pLocaleData(new LocaleDataWrapper(
3605 : ::comphelper::getProcessComponentContext(),
3606 43 : SvtSysLocale().GetLanguageTag() ));
3607 : // get user configured currency
3608 86 : OUString aConfiguredCurrencyAbbrev;
3609 43 : LanguageType eConfiguredCurrencyLanguage = LANGUAGE_SYSTEM;
3610 : SvtSysLocaleOptions().GetCurrencyAbbrevAndLanguage(
3611 43 : aConfiguredCurrencyAbbrev, eConfiguredCurrencyLanguage );
3612 43 : sal_uInt16 nSecondarySystemCurrencyPosition = 0;
3613 43 : sal_uInt16 nMatchingSystemCurrencyPosition = 0;
3614 : NfCurrencyEntry* pEntry;
3615 :
3616 : // first entry is SYSTEM
3617 43 : pEntry = new NfCurrencyEntry( *pLocaleData, LANGUAGE_SYSTEM );
3618 43 : theCurrencyTable::get().insert( theCurrencyTable::get().begin(), pEntry );
3619 43 : sal_uInt16 nCurrencyPos = 1;
3620 :
3621 : ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > xLoc =
3622 86 : LocaleDataWrapper::getInstalledLocaleNames();
3623 43 : sal_Int32 nLocaleCount = xLoc.getLength();
3624 : SAL_INFO( "svl.numbers", "number of locales: \"" << nLocaleCount << "\"" );
3625 43 : css::lang::Locale const * const pLocales = xLoc.getConstArray();
3626 43 : NfCurrencyTable &rCurrencyTable = theCurrencyTable::get();
3627 43 : NfCurrencyTable &rLegacyOnlyCurrencyTable = theLegacyOnlyCurrencyTable::get();
3628 43 : NfInstalledLocales &rInstalledLocales = theInstalledLocales::get();
3629 43 : sal_uInt16 nLegacyOnlyCurrencyPos = 0;
3630 10578 : for ( sal_Int32 nLocale = 0; nLocale < nLocaleCount; nLocale++ )
3631 : {
3632 10535 : LanguageType eLang = LanguageTag::convertToLanguageType( pLocales[nLocale], false);
3633 10535 : rInstalledLocales.insert( eLang);
3634 10535 : pLocaleData->setLanguageTag( LanguageTag( pLocales[nLocale]) );
3635 10535 : Sequence< Currency2 > aCurrSeq = pLocaleData->getAllCurrencies();
3636 10535 : sal_Int32 nCurrencyCount = aCurrSeq.getLength();
3637 10535 : Currency2 const * const pCurrencies = aCurrSeq.getConstArray();
3638 :
3639 : // one default currency for each locale, insert first so it is found first
3640 : sal_Int32 nDefault;
3641 11008 : for ( nDefault = 0; nDefault < nCurrencyCount; nDefault++ )
3642 : {
3643 11008 : if ( pCurrencies[nDefault].Default )
3644 10535 : break;
3645 : }
3646 10535 : if ( nDefault < nCurrencyCount )
3647 : {
3648 10535 : pEntry = new NfCurrencyEntry( pCurrencies[nDefault], *pLocaleData, eLang );
3649 : }
3650 : else
3651 : {
3652 0 : pEntry = new NfCurrencyEntry( *pLocaleData, eLang ); // first or ShellsAndPebbles
3653 : }
3654 10535 : if (LocaleDataWrapper::areChecksEnabled())
3655 : {
3656 0 : lcl_CheckCurrencySymbolPosition( *pEntry );
3657 : }
3658 10535 : rCurrencyTable.insert( rCurrencyTable.begin() + nCurrencyPos++, pEntry );
3659 31605 : if ( !nSystemCurrencyPosition && !aConfiguredCurrencyAbbrev.isEmpty() &&
3660 10535 : pEntry->GetBankSymbol() == aConfiguredCurrencyAbbrev &&
3661 0 : pEntry->GetLanguage() == eConfiguredCurrencyLanguage )
3662 : {
3663 0 : nSystemCurrencyPosition = nCurrencyPos-1;
3664 : }
3665 10578 : if ( !nMatchingSystemCurrencyPosition &&
3666 43 : pEntry->GetLanguage() == eSysLang )
3667 : {
3668 43 : nMatchingSystemCurrencyPosition = nCurrencyPos-1;
3669 : }
3670 : // all remaining currencies for each locale
3671 10535 : if ( nCurrencyCount > 1 )
3672 : {
3673 : sal_Int32 nCurrency;
3674 11266 : for ( nCurrency = 0; nCurrency < nCurrencyCount; nCurrency++ )
3675 : {
3676 7826 : if (pCurrencies[nCurrency].LegacyOnly)
3677 : {
3678 1763 : pEntry = new NfCurrencyEntry( pCurrencies[nCurrency], *pLocaleData, eLang );
3679 1763 : rLegacyOnlyCurrencyTable.insert( rLegacyOnlyCurrencyTable.begin() + nLegacyOnlyCurrencyPos++, pEntry );
3680 : }
3681 6063 : else if ( nCurrency != nDefault )
3682 : {
3683 2623 : pEntry = new NfCurrencyEntry( pCurrencies[nCurrency], *pLocaleData, eLang );
3684 : // no dupes
3685 2623 : bool bInsert = true;
3686 2623 : sal_uInt16 n = rCurrencyTable.size();
3687 2623 : sal_uInt16 aCurrencyIndex = 1; // skip first SYSTEM entry
3688 287283 : for ( sal_uInt16 j=1; j<n; j++ )
3689 : {
3690 284660 : if ( rCurrencyTable[aCurrencyIndex++] == *pEntry )
3691 : {
3692 0 : bInsert = false;
3693 0 : break; // for
3694 : }
3695 : }
3696 2623 : if ( !bInsert )
3697 : {
3698 0 : delete pEntry;
3699 : }
3700 : else
3701 : {
3702 2623 : rCurrencyTable.insert( rCurrencyTable.begin() + nCurrencyPos++, pEntry );
3703 7869 : if ( !nSecondarySystemCurrencyPosition &&
3704 2623 : (!aConfiguredCurrencyAbbrev.isEmpty() ?
3705 0 : pEntry->GetBankSymbol() == aConfiguredCurrencyAbbrev :
3706 2623 : pEntry->GetLanguage() == eConfiguredCurrencyLanguage) )
3707 : {
3708 0 : nSecondarySystemCurrencyPosition = nCurrencyPos-1;
3709 : }
3710 2623 : if ( !nMatchingSystemCurrencyPosition &&
3711 0 : pEntry->GetLanguage() == eSysLang )
3712 : {
3713 0 : nMatchingSystemCurrencyPosition = nCurrencyPos-1;
3714 : }
3715 : }
3716 : }
3717 : }
3718 : }
3719 10535 : }
3720 43 : if ( !nSystemCurrencyPosition )
3721 : {
3722 43 : nSystemCurrencyPosition = nSecondarySystemCurrencyPosition;
3723 : }
3724 43 : if ((!aConfiguredCurrencyAbbrev.isEmpty() && !nSystemCurrencyPosition) &&
3725 0 : LocaleDataWrapper::areChecksEnabled())
3726 : {
3727 : LocaleDataWrapper::outputCheckMessage(
3728 0 : "SvNumberFormatter::ImpInitCurrencyTable: configured currency not in I18N locale data.");
3729 : }
3730 : // match SYSTEM if no configured currency found
3731 43 : if ( !nSystemCurrencyPosition )
3732 : {
3733 43 : nSystemCurrencyPosition = nMatchingSystemCurrencyPosition;
3734 : }
3735 43 : if ((aConfiguredCurrencyAbbrev.isEmpty() && !nSystemCurrencyPosition) &&
3736 0 : LocaleDataWrapper::areChecksEnabled())
3737 : {
3738 : LocaleDataWrapper::outputCheckMessage(
3739 0 : "SvNumberFormatter::ImpInitCurrencyTable: system currency not in I18N locale data.");
3740 : }
3741 43 : pLocaleData.reset();
3742 43 : SvtSysLocaleOptions::SetCurrencyChangeLink( LINK( NULL, SvNumberFormatter, CurrencyChangeLink ) );
3743 43 : bInitializing = false;
3744 86 : bCurrencyTableInitialized = true;
3745 : }
3746 :
3747 :
3748 176 : sal_uInt16 SvNumberFormatter::GetCurrencyFormatStrings( NfWSStringsDtor& rStrArr,
3749 : const NfCurrencyEntry& rCurr,
3750 : bool bBank ) const
3751 : {
3752 : OUString aRed = OUStringBuffer().
3753 352 : append('[').
3754 352 : append(pFormatScanner->GetRedString()).
3755 176 : append(']').makeStringAndClear();
3756 :
3757 176 : sal_uInt16 nDefault = 0;
3758 176 : if ( bBank )
3759 : {
3760 : // Only bank symbols.
3761 0 : OUString aPositiveBank = rCurr.BuildPositiveFormatString(true, *xLocaleData, 1);
3762 0 : OUString aNegativeBank = rCurr.BuildNegativeFormatString(true, *xLocaleData, 1 );
3763 :
3764 0 : OUStringBuffer format1(aPositiveBank);
3765 0 : format1.append(';');
3766 0 : format1.append(aNegativeBank);
3767 0 : rStrArr.push_back(format1.makeStringAndClear());
3768 :
3769 0 : OUStringBuffer format2(aPositiveBank);
3770 0 : format2.append(';');
3771 :
3772 0 : format2.append(aRed);
3773 :
3774 0 : format2.append(aNegativeBank);
3775 0 : rStrArr.push_back(format2.makeStringAndClear());
3776 :
3777 0 : nDefault = rStrArr.size() - 1;
3778 : }
3779 : else
3780 : {
3781 : // Mixed formats like in SvNumberFormatter::ImpGenerateFormats() but no
3782 : // duplicates if no decimals in currency.
3783 176 : OUString aPositive = rCurr.BuildPositiveFormatString(false, *xLocaleData, 1);
3784 352 : OUString aNegative = rCurr.BuildNegativeFormatString(false, *xLocaleData, 1 );
3785 352 : OUStringBuffer format1;
3786 352 : OUStringBuffer format2;
3787 352 : OUStringBuffer format3;
3788 352 : OUStringBuffer format4;
3789 352 : OUStringBuffer format5;
3790 176 : if (rCurr.GetDigits())
3791 : {
3792 176 : OUString aPositiveNoDec = rCurr.BuildPositiveFormatString(false, *xLocaleData, 0);
3793 352 : OUString aNegativeNoDec = rCurr.BuildNegativeFormatString(false, *xLocaleData, 0 );
3794 352 : OUString aPositiveDashed = rCurr.BuildPositiveFormatString(false, *xLocaleData, 2);
3795 352 : OUString aNegativeDashed = rCurr.BuildNegativeFormatString(false, *xLocaleData, 2);
3796 :
3797 176 : format1.append(aPositiveNoDec);
3798 176 : format1.append(';');
3799 176 : format1.append(aNegativeNoDec);
3800 :
3801 176 : format3.append(aPositiveNoDec);
3802 176 : format3.append(';');
3803 176 : format3.append(aRed);
3804 176 : format3.append(aNegativeNoDec);
3805 :
3806 176 : format5.append(aPositiveDashed);
3807 176 : format5.append(';');
3808 176 : format5.append(aRed);
3809 352 : format5.append(aNegativeDashed);
3810 : }
3811 :
3812 176 : format2.append(aPositive);
3813 176 : format2.append(';');
3814 176 : format2.append(aNegative);
3815 :
3816 176 : format4.append(aPositive);
3817 176 : format4.append(';');
3818 176 : format4.append(aRed);
3819 176 : format4.append(aNegative);
3820 :
3821 176 : if (rCurr.GetDigits())
3822 : {
3823 176 : rStrArr.push_back(format1.makeStringAndClear());
3824 : }
3825 176 : rStrArr.push_back(format2.makeStringAndClear());
3826 176 : if (rCurr.GetDigits())
3827 : {
3828 176 : rStrArr.push_back(format3.makeStringAndClear());
3829 : }
3830 176 : rStrArr.push_back(format4.makeStringAndClear());
3831 176 : nDefault = rStrArr.size() - 1;
3832 176 : if (rCurr.GetDigits())
3833 : {
3834 176 : rStrArr.push_back(format5.makeStringAndClear());
3835 176 : }
3836 : }
3837 176 : return nDefault;
3838 : }
3839 :
3840 0 : sal_uInt32 SvNumberFormatter::GetMergeFormatIndex( sal_uInt32 nOldFmt ) const
3841 : {
3842 0 : if (pMergeTable)
3843 : {
3844 0 : SvNumberFormatterIndexTable::iterator it = pMergeTable->find(nOldFmt);
3845 0 : if (it != pMergeTable->end())
3846 : {
3847 0 : return it->second;
3848 : }
3849 : }
3850 0 : return nOldFmt;
3851 : }
3852 :
3853 112 : bool SvNumberFormatter::HasMergeFormatTable() const
3854 : {
3855 112 : return pMergeTable && !pMergeTable->empty();
3856 : }
3857 :
3858 : // static
3859 4 : sal_uInt16 SvNumberFormatter::ExpandTwoDigitYear( sal_uInt16 nYear, sal_uInt16 nTwoDigitYearStart )
3860 : {
3861 4 : if ( nYear < 100 )
3862 : {
3863 4 : if ( nYear < (nTwoDigitYearStart % 100) )
3864 : {
3865 4 : return nYear + (((nTwoDigitYearStart / 100) + 1) * 100);
3866 : }
3867 : else
3868 : {
3869 0 : return nYear + ((nTwoDigitYearStart / 100) * 100);
3870 : }
3871 : }
3872 0 : return nYear;
3873 : }
3874 :
3875 43 : NfCurrencyEntry::NfCurrencyEntry( const LocaleDataWrapper& rLocaleData, LanguageType eLang )
3876 : {
3877 43 : aSymbol = rLocaleData.getCurrSymbol();
3878 43 : aBankSymbol = rLocaleData.getCurrBankSymbol();
3879 43 : eLanguage = eLang;
3880 43 : nPositiveFormat = rLocaleData.getCurrPositiveFormat();
3881 43 : nNegativeFormat = rLocaleData.getCurrNegativeFormat();
3882 43 : nDigits = rLocaleData.getCurrDigits();
3883 43 : cZeroChar = rLocaleData.getCurrZeroChar();
3884 43 : }
3885 :
3886 :
3887 14921 : NfCurrencyEntry::NfCurrencyEntry( const ::com::sun::star::i18n::Currency & rCurr,
3888 14921 : const LocaleDataWrapper& rLocaleData, LanguageType eLang )
3889 : {
3890 14921 : aSymbol = rCurr.Symbol;
3891 14921 : aBankSymbol = rCurr.BankSymbol;
3892 14921 : eLanguage = eLang;
3893 14921 : nPositiveFormat = rLocaleData.getCurrPositiveFormat();
3894 14921 : nNegativeFormat = rLocaleData.getCurrNegativeFormat();
3895 14921 : nDigits = rCurr.DecimalPlaces;
3896 14921 : cZeroChar = rLocaleData.getCurrZeroChar();
3897 14921 : }
3898 :
3899 284660 : bool NfCurrencyEntry::operator==( const NfCurrencyEntry& r ) const
3900 : {
3901 284660 : return aSymbol == r.aSymbol
3902 7181 : && aBankSymbol == r.aBankSymbol
3903 289519 : && eLanguage == r.eLanguage
3904 : ;
3905 : }
3906 :
3907 1086 : OUString NfCurrencyEntry::BuildSymbolString(bool bBank,
3908 : bool bWithoutExtension) const
3909 : {
3910 1086 : OUStringBuffer aBuf("[$");
3911 1086 : if (bBank)
3912 : {
3913 0 : aBuf.append(aBankSymbol);
3914 : }
3915 : else
3916 : {
3917 2172 : if ( aSymbol.indexOf( (sal_Unicode)'-' ) >= 0 ||
3918 1086 : aSymbol.indexOf( (sal_Unicode)']' ) >= 0)
3919 : {
3920 0 : aBuf.append('"').append(aSymbol).append('"');
3921 : }
3922 : else
3923 : {
3924 1086 : aBuf.append(aSymbol);
3925 : }
3926 1086 : if ( !bWithoutExtension && eLanguage != LANGUAGE_DONTKNOW && eLanguage != LANGUAGE_SYSTEM )
3927 : {
3928 1086 : sal_Int32 nLang = static_cast<sal_Int32>(eLanguage);
3929 1086 : aBuf.append('-').append( OUString::number(nLang, 16).toAsciiUpperCase());
3930 : }
3931 : }
3932 1086 : aBuf.append(']');
3933 1086 : return aBuf.makeStringAndClear();
3934 : }
3935 :
3936 1056 : OUString NfCurrencyEntry::Impl_BuildFormatStringNumChars( const LocaleDataWrapper& rLoc,
3937 : sal_uInt16 nDecimalFormat) const
3938 : {
3939 1056 : OUStringBuffer aBuf;
3940 1056 : aBuf.append('#').append(rLoc.getNumThousandSep()).append("##0");
3941 1056 : if (nDecimalFormat && nDigits)
3942 : {
3943 704 : aBuf.append(rLoc.getNumDecimalSep());
3944 704 : sal_Unicode cDecimalChar = nDecimalFormat == 2 ? '-' : cZeroChar;
3945 2112 : for (sal_uInt16 i = 0; i < nDigits; ++i)
3946 : {
3947 1408 : aBuf.append(cDecimalChar);
3948 : }
3949 : }
3950 1056 : return aBuf.makeStringAndClear();
3951 : }
3952 :
3953 :
3954 528 : OUString NfCurrencyEntry::BuildPositiveFormatString(bool bBank, const LocaleDataWrapper& rLoc,
3955 : sal_uInt16 nDecimalFormat) const
3956 : {
3957 528 : OUStringBuffer sBuf(Impl_BuildFormatStringNumChars(rLoc, nDecimalFormat));
3958 528 : sal_uInt16 nPosiForm = NfCurrencyEntry::GetEffectivePositiveFormat( rLoc.getCurrPositiveFormat(),
3959 1056 : nPositiveFormat, bBank );
3960 528 : CompletePositiveFormatString(sBuf, bBank, nPosiForm);
3961 528 : return sBuf.makeStringAndClear();
3962 : }
3963 :
3964 :
3965 528 : OUString NfCurrencyEntry::BuildNegativeFormatString(bool bBank,
3966 : const LocaleDataWrapper& rLoc, sal_uInt16 nDecimalFormat ) const
3967 : {
3968 528 : OUStringBuffer sBuf(Impl_BuildFormatStringNumChars(rLoc, nDecimalFormat));
3969 528 : sal_uInt16 nNegaForm = NfCurrencyEntry::GetEffectiveNegativeFormat( rLoc.getCurrNegativeFormat(),
3970 1056 : nNegativeFormat, bBank );
3971 528 : CompleteNegativeFormatString(sBuf, bBank, nNegaForm);
3972 528 : return sBuf.makeStringAndClear();
3973 : }
3974 :
3975 :
3976 538 : void NfCurrencyEntry::CompletePositiveFormatString(OUStringBuffer& rStr, bool bBank,
3977 : sal_uInt16 nPosiForm) const
3978 : {
3979 538 : OUString aSymStr = BuildSymbolString(bBank);
3980 538 : NfCurrencyEntry::CompletePositiveFormatString( rStr, aSymStr, nPosiForm );
3981 538 : }
3982 :
3983 :
3984 538 : void NfCurrencyEntry::CompleteNegativeFormatString(OUStringBuffer& rStr, bool bBank,
3985 : sal_uInt16 nNegaForm) const
3986 : {
3987 538 : OUString aSymStr = BuildSymbolString(bBank);
3988 538 : NfCurrencyEntry::CompleteNegativeFormatString( rStr, aSymStr, nNegaForm );
3989 538 : }
3990 :
3991 :
3992 : // static
3993 568 : void NfCurrencyEntry::CompletePositiveFormatString(OUStringBuffer& rStr, const OUString& rSymStr,
3994 : sal_uInt16 nPositiveFormat)
3995 : {
3996 568 : switch( nPositiveFormat )
3997 : {
3998 : case 0: // $1
3999 538 : rStr.insert(0, rSymStr);
4000 538 : break;
4001 : case 1: // 1$
4002 0 : rStr.append(rSymStr);
4003 0 : break;
4004 : case 2: // $ 1
4005 : {
4006 0 : rStr.insert(0, ' ');
4007 0 : rStr.insert(0, rSymStr);
4008 : }
4009 0 : break;
4010 : case 3: // 1 $
4011 : {
4012 30 : rStr.append(' ');
4013 30 : rStr.append(rSymStr);
4014 : }
4015 30 : break;
4016 : default:
4017 : SAL_WARN( "svl.numbers", "NfCurrencyEntry::CompletePositiveFormatString: unknown option");
4018 0 : break;
4019 : }
4020 568 : }
4021 :
4022 :
4023 : // static
4024 568 : void NfCurrencyEntry::CompleteNegativeFormatString(OUStringBuffer& rStr,
4025 : const OUString& rSymStr,
4026 : sal_uInt16 nNegativeFormat)
4027 : {
4028 568 : switch( nNegativeFormat )
4029 : {
4030 : case 0: // ($1)
4031 : {
4032 0 : rStr.insert(0, rSymStr);
4033 0 : rStr.insert(0, '(');
4034 0 : rStr.append(')');
4035 : }
4036 0 : break;
4037 : case 1: // -$1
4038 : {
4039 538 : rStr.insert(0, rSymStr);
4040 538 : rStr.insert(0, '-');
4041 : }
4042 538 : break;
4043 : case 2: // $-1
4044 : {
4045 0 : rStr.insert(0, '-');
4046 0 : rStr.insert(0, rSymStr);
4047 : }
4048 0 : break;
4049 : case 3: // $1-
4050 : {
4051 0 : rStr.insert(0, rSymStr);
4052 0 : rStr.append('-');
4053 : }
4054 0 : break;
4055 : case 4: // (1$)
4056 : {
4057 0 : rStr.insert(0, '(');
4058 0 : rStr.append(rSymStr);
4059 0 : rStr.append(')');
4060 : }
4061 0 : break;
4062 : case 5: // -1$
4063 : {
4064 0 : rStr.append(rSymStr);
4065 0 : rStr.insert(0, '-');
4066 : }
4067 0 : break;
4068 : case 6: // 1-$
4069 : {
4070 0 : rStr.append('-');
4071 0 : rStr.append(rSymStr);
4072 : }
4073 0 : break;
4074 : case 7: // 1$-
4075 : {
4076 0 : rStr.append(rSymStr);
4077 0 : rStr.append('-');
4078 : }
4079 0 : break;
4080 : case 8: // -1 $
4081 : {
4082 30 : rStr.append(' ');
4083 30 : rStr.append(rSymStr);
4084 30 : rStr.insert(0, '-');
4085 : }
4086 30 : break;
4087 : case 9: // -$ 1
4088 : {
4089 0 : rStr.insert(0, ' ');
4090 0 : rStr.insert(0, rSymStr);
4091 0 : rStr.insert(0, '-');
4092 : }
4093 0 : break;
4094 : case 10: // 1 $-
4095 : {
4096 0 : rStr.append(' ');
4097 0 : rStr.append(rSymStr);
4098 0 : rStr.append('-');
4099 : }
4100 0 : break;
4101 : case 11: // $ -1
4102 : {
4103 0 : rStr.insert(0, " -");
4104 0 : rStr.insert(0, rSymStr);
4105 : }
4106 0 : break;
4107 : case 12 : // $ 1-
4108 : {
4109 0 : rStr.insert(0, ' ');
4110 0 : rStr.insert(0, rSymStr);
4111 0 : rStr.append('-');
4112 : }
4113 0 : break;
4114 : case 13 : // 1- $
4115 : {
4116 0 : rStr.append('-');
4117 0 : rStr.append(' ');
4118 0 : rStr.append(rSymStr);
4119 : }
4120 0 : break;
4121 : case 14 : // ($ 1)
4122 : {
4123 0 : rStr.insert(0, ' ');
4124 0 : rStr.insert(0, rSymStr);
4125 0 : rStr.insert(0, '(');
4126 0 : rStr.append(')');
4127 : }
4128 0 : break;
4129 : case 15 : // (1 $)
4130 : {
4131 0 : rStr.insert(0, '(');
4132 0 : rStr.append(' ');
4133 0 : rStr.append(rSymStr);
4134 0 : rStr.append(')');
4135 : }
4136 0 : break;
4137 : default:
4138 : SAL_WARN( "svl.numbers", "NfCurrencyEntry::CompleteNegativeFormatString: unknown option");
4139 0 : break;
4140 : }
4141 568 : }
4142 :
4143 :
4144 : // static
4145 568 : sal_uInt16 NfCurrencyEntry::GetEffectivePositiveFormat( sal_uInt16 nIntlFormat,
4146 : sal_uInt16 nCurrFormat, bool bBank )
4147 : {
4148 568 : if ( bBank )
4149 : {
4150 : #if NF_BANKSYMBOL_FIX_POSITION
4151 : (void) nIntlFormat; // avoid warnings
4152 30 : return 3;
4153 : #else
4154 : switch ( nIntlFormat )
4155 : {
4156 : case 0: // $1
4157 : nIntlFormat = 2; // $ 1
4158 : break;
4159 : case 1: // 1$
4160 : nIntlFormat = 3; // 1 $
4161 : break;
4162 : case 2: // $ 1
4163 : break;
4164 : case 3: // 1 $
4165 : break;
4166 : default:
4167 : SAL_WARN( "svl.numbers", "NfCurrencyEntry::GetEffectivePositiveFormat: unknown option");
4168 : break;
4169 : }
4170 : return nIntlFormat;
4171 : #endif
4172 : }
4173 : else
4174 538 : return nCurrFormat;
4175 : }
4176 :
4177 :
4178 : //! Call this only if nCurrFormat is really with parentheses!
4179 0 : static sal_uInt16 lcl_MergeNegativeParenthesisFormat( sal_uInt16 nIntlFormat, sal_uInt16 nCurrFormat )
4180 : {
4181 0 : short nSign = 0; // -1:=Klammer 0:=links, 1:=mitte, 2:=rechts
4182 0 : switch ( nIntlFormat )
4183 : {
4184 : case 0: // ($1)
4185 : case 4: // (1$)
4186 : case 14 : // ($ 1)
4187 : case 15 : // (1 $)
4188 0 : return nCurrFormat;
4189 : case 1: // -$1
4190 : case 5: // -1$
4191 : case 8: // -1 $
4192 : case 9: // -$ 1
4193 0 : nSign = 0;
4194 0 : break;
4195 : case 2: // $-1
4196 : case 6: // 1-$
4197 : case 11 : // $ -1
4198 : case 13 : // 1- $
4199 0 : nSign = 1;
4200 0 : break;
4201 : case 3: // $1-
4202 : case 7: // 1$-
4203 : case 10: // 1 $-
4204 : case 12 : // $ 1-
4205 0 : nSign = 2;
4206 0 : break;
4207 : default:
4208 : SAL_WARN( "svl.numbers", "lcl_MergeNegativeParenthesisFormat: unknown option");
4209 0 : break;
4210 : }
4211 :
4212 0 : switch ( nCurrFormat )
4213 : {
4214 : case 0: // ($1)
4215 0 : switch ( nSign )
4216 : {
4217 : case 0:
4218 0 : return 1; // -$1
4219 : case 1:
4220 0 : return 2; // $-1
4221 : case 2:
4222 0 : return 3; // $1-
4223 : }
4224 0 : break;
4225 : case 4: // (1$)
4226 0 : switch ( nSign )
4227 : {
4228 : case 0:
4229 0 : return 5; // -1$
4230 : case 1:
4231 0 : return 6; // 1-$
4232 : case 2:
4233 0 : return 7; // 1$-
4234 : }
4235 0 : break;
4236 : case 14 : // ($ 1)
4237 0 : switch ( nSign )
4238 : {
4239 : case 0:
4240 0 : return 9; // -$ 1
4241 : case 1:
4242 0 : return 11; // $ -1
4243 : case 2:
4244 0 : return 12; // $ 1-
4245 : }
4246 0 : break;
4247 : case 15 : // (1 $)
4248 0 : switch ( nSign )
4249 : {
4250 : case 0:
4251 0 : return 8; // -1 $
4252 : case 1:
4253 0 : return 13; // 1- $
4254 : case 2:
4255 0 : return 10; // 1 $-
4256 : }
4257 0 : break;
4258 : }
4259 0 : return nCurrFormat;
4260 : }
4261 :
4262 :
4263 : // static
4264 568 : sal_uInt16 NfCurrencyEntry::GetEffectiveNegativeFormat( sal_uInt16 nIntlFormat,
4265 : sal_uInt16 nCurrFormat, bool bBank )
4266 : {
4267 568 : if ( bBank )
4268 : {
4269 : #if NF_BANKSYMBOL_FIX_POSITION
4270 30 : return 8;
4271 : #else
4272 : switch ( nIntlFormat )
4273 : {
4274 : case 0: // ($1)
4275 : // nIntlFormat = 14; // ($ 1)
4276 : nIntlFormat = 9; // -$ 1
4277 : break;
4278 : case 1: // -$1
4279 : nIntlFormat = 9; // -$ 1
4280 : break;
4281 : case 2: // $-1
4282 : nIntlFormat = 11; // $ -1
4283 : break;
4284 : case 3: // $1-
4285 : nIntlFormat = 12; // $ 1-
4286 : break;
4287 : case 4: // (1$)
4288 : // nIntlFormat = 15; // (1 $)
4289 : nIntlFormat = 8; // -1 $
4290 : break;
4291 : case 5: // -1$
4292 : nIntlFormat = 8; // -1 $
4293 : break;
4294 : case 6: // 1-$
4295 : nIntlFormat = 13; // 1- $
4296 : break;
4297 : case 7: // 1$-
4298 : nIntlFormat = 10; // 1 $-
4299 : break;
4300 : case 8: // -1 $
4301 : break;
4302 : case 9: // -$ 1
4303 : break;
4304 : case 10: // 1 $-
4305 : break;
4306 : case 11: // $ -1
4307 : break;
4308 : case 12 : // $ 1-
4309 : break;
4310 : case 13 : // 1- $
4311 : break;
4312 : case 14 : // ($ 1)
4313 : // nIntlFormat = 14; // ($ 1)
4314 : nIntlFormat = 9; // -$ 1
4315 : break;
4316 : case 15 : // (1 $)
4317 : // nIntlFormat = 15; // (1 $)
4318 : nIntlFormat = 8; // -1 $
4319 : break;
4320 : default:
4321 : SAL_WARN( "svl.numbers", "NfCurrencyEntry::GetEffectiveNegativeFormat: unknown option");
4322 : break;
4323 : }
4324 : #endif
4325 : }
4326 538 : else if ( nIntlFormat != nCurrFormat )
4327 : {
4328 0 : switch ( nCurrFormat )
4329 : {
4330 : case 0: // ($1)
4331 : nIntlFormat = lcl_MergeNegativeParenthesisFormat(
4332 0 : nIntlFormat, nCurrFormat );
4333 0 : break;
4334 : case 1: // -$1
4335 0 : nIntlFormat = nCurrFormat;
4336 0 : break;
4337 : case 2: // $-1
4338 0 : nIntlFormat = nCurrFormat;
4339 0 : break;
4340 : case 3: // $1-
4341 0 : nIntlFormat = nCurrFormat;
4342 0 : break;
4343 : case 4: // (1$)
4344 : nIntlFormat = lcl_MergeNegativeParenthesisFormat(
4345 0 : nIntlFormat, nCurrFormat );
4346 0 : break;
4347 : case 5: // -1$
4348 0 : nIntlFormat = nCurrFormat;
4349 0 : break;
4350 : case 6: // 1-$
4351 0 : nIntlFormat = nCurrFormat;
4352 0 : break;
4353 : case 7: // 1$-
4354 0 : nIntlFormat = nCurrFormat;
4355 0 : break;
4356 : case 8: // -1 $
4357 0 : nIntlFormat = nCurrFormat;
4358 0 : break;
4359 : case 9: // -$ 1
4360 0 : nIntlFormat = nCurrFormat;
4361 0 : break;
4362 : case 10: // 1 $-
4363 0 : nIntlFormat = nCurrFormat;
4364 0 : break;
4365 : case 11: // $ -1
4366 0 : nIntlFormat = nCurrFormat;
4367 0 : break;
4368 : case 12 : // $ 1-
4369 0 : nIntlFormat = nCurrFormat;
4370 0 : break;
4371 : case 13 : // 1- $
4372 0 : nIntlFormat = nCurrFormat;
4373 0 : break;
4374 : case 14 : // ($ 1)
4375 : nIntlFormat = lcl_MergeNegativeParenthesisFormat(
4376 0 : nIntlFormat, nCurrFormat );
4377 0 : break;
4378 : case 15 : // (1 $)
4379 : nIntlFormat = lcl_MergeNegativeParenthesisFormat(
4380 0 : nIntlFormat, nCurrFormat );
4381 0 : break;
4382 : default:
4383 : SAL_WARN( "svl.numbers", "NfCurrencyEntry::GetEffectiveNegativeFormat: unknown option");
4384 0 : break;
4385 : }
4386 : }
4387 538 : return nIntlFormat;
4388 819 : }
4389 :
4390 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|