xref: /AOO41X/main/svl/source/numbers/zforlist.cxx (revision 056bc390d7626c14686eded1772108358b4b9f9a)
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