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

Generated by: LCOV version 1.10