LCOV - code coverage report
Current view: top level - svl/source/numbers - zforlist.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1235 2088 59.1 %
Date: 2014-11-03 Functions: 95 122 77.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10