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

Generated by: LCOV version 1.11