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