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