LCOV - code coverage report
Current view: top level - libreoffice/svl/source/numbers - zforlist.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1067 2092 51.0 %
Date: 2012-12-27 Functions: 86 120 71.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10