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