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