LCOV - code coverage report
Current view: top level - svl/source/numbers - zforlist.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 4 2103 0.2 %
Date: 2014-04-14 Functions: 4 121 3.3 %
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           1 : struct IndexTable
      75             : {
      76             :     bool mbInitialized;
      77             :     sal_uInt32 maData[NF_INDEX_TABLE_ENTRIES];
      78             :     osl::Mutex maMtx;
      79             : 
      80           1 :     IndexTable() : mbInitialized(false) {}
      81             : };
      82             : 
      83           1 : 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           0 :     void                    Insert( SvNumberFormatter* pThis )
     105           0 :                                 { aFormatters.push_back( pThis ); }
     106             : 
     107             :     SvNumberFormatter*      Remove( SvNumberFormatter* pThis );
     108             : 
     109           0 :     size_t                  Count()
     110           0 :                                 { return aFormatters.size(); }
     111             : 
     112             :     virtual void            ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 ) SAL_OVERRIDE;
     113             : };
     114             : 
     115           0 : SvNumberFormatterRegistry_Impl::SvNumberFormatterRegistry_Impl()
     116             : {
     117           0 :     eSysLanguage = MsLangId::getRealLanguage( LANGUAGE_SYSTEM );
     118           0 :     aSysLocaleOptions.AddListener( this );
     119           0 : }
     120             : 
     121             : 
     122           0 : SvNumberFormatterRegistry_Impl::~SvNumberFormatterRegistry_Impl()
     123             : {
     124           0 :     aSysLocaleOptions.RemoveListener( this );
     125           0 : }
     126             : 
     127             : 
     128           0 : SvNumberFormatter* SvNumberFormatterRegistry_Impl::Remove( SvNumberFormatter* pThis )
     129             : {
     130           0 :     for (SvNumberFormatterList_impl::iterator it = aFormatters.begin();
     131           0 :             it != aFormatters.end(); ++it)
     132             :     {
     133           0 :         if ( *it == pThis )
     134             :         {
     135           0 :             aFormatters.erase( it );
     136           0 :             break;
     137             :         }
     138             :     }
     139           0 :     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           0 : SvNumberFormatter::SvNumberFormatter( const Reference< XComponentContext >& rxContext,
     196             :                                       LanguageType eLang )
     197             :     : m_xContext( rxContext )
     198           0 :     , maLanguageTag( eLang)
     199             : {
     200           0 :     ImpConstruct( eLang );
     201           0 : }
     202             : 
     203             : 
     204           0 : SvNumberFormatter::~SvNumberFormatter()
     205             : {
     206             :     {
     207           0 :         ::osl::MutexGuard aGuard( GetMutex() );
     208           0 :         pFormatterRegistry->Remove( this );
     209           0 :         if ( !pFormatterRegistry->Count() )
     210             :         {
     211           0 :             delete pFormatterRegistry;
     212           0 :             pFormatterRegistry = NULL;
     213           0 :         }
     214             :     }
     215             : 
     216           0 :     for (SvNumberFormatTable::iterator it = aFTable.begin(); it != aFTable.end(); ++it)
     217           0 :         delete it->second;
     218           0 :     delete pFormatTable;
     219           0 :     delete pCharClass;
     220           0 :     delete pStringScanner;
     221           0 :     delete pFormatScanner;
     222           0 :     ClearMergeTable();
     223           0 :     delete pMergeTable;
     224           0 : }
     225             : 
     226             : 
     227           0 : void SvNumberFormatter::ImpConstruct( LanguageType eLang )
     228             : {
     229           0 :     if ( eLang == LANGUAGE_DONTKNOW )
     230             :     {
     231           0 :         eLang = UNKNOWN_SUBSTITUTE;
     232             :     }
     233           0 :     IniLnge = eLang;
     234           0 :     ActLnge = eLang;
     235           0 :     eEvalDateFormat = NF_EVALDATEFORMAT_INTL;
     236           0 :     nDefaultSystemCurrencyFormat = NUMBERFORMAT_ENTRY_NOT_FOUND;
     237             : 
     238           0 :     maLanguageTag.reset( eLang );
     239           0 :     pCharClass = new CharClass( m_xContext, maLanguageTag );
     240           0 :     xLocaleData.init( m_xContext, maLanguageTag );
     241           0 :     xCalendar.init( m_xContext, maLanguageTag.getLocale() );
     242             :     xTransliteration.init( m_xContext, eLang,
     243           0 :                            ::com::sun::star::i18n::TransliterationModules_IGNORE_CASE );
     244           0 :     xNatNum.init( m_xContext );
     245             : 
     246             :     // cached locale data items
     247           0 :     const LocaleDataWrapper* pLoc = GetLocaleData();
     248           0 :     aDecimalSep = pLoc->getNumDecimalSep();
     249           0 :     aThousandSep = pLoc->getNumThousandSep();
     250           0 :     aDateSep = pLoc->getDateSep();
     251             : 
     252           0 :     pStringScanner = new ImpSvNumberInputScan( this );
     253           0 :     pFormatScanner = new ImpSvNumberformatScan( this );
     254           0 :     pFormatTable = NULL;
     255           0 :     MaxCLOffset = 0;
     256           0 :     ImpGenerateFormats( 0, false );     // 0 .. 999 for initialized language formats
     257           0 :     pMergeTable = NULL;
     258           0 :     bNoZero = false;
     259             : 
     260           0 :     ::osl::MutexGuard aGuard( GetMutex() );
     261           0 :     GetFormatterRegistry().Insert( this );
     262           0 : }
     263             : 
     264             : 
     265           0 : void SvNumberFormatter::ChangeIntl(LanguageType eLnge)
     266             : {
     267           0 :     if (ActLnge != eLnge)
     268             :     {
     269           0 :         ActLnge = eLnge;
     270             : 
     271           0 :         maLanguageTag.reset( eLnge );
     272           0 :         pCharClass->setLanguageTag( maLanguageTag );
     273           0 :         xLocaleData.changeLocale( maLanguageTag );
     274           0 :         xCalendar.changeLocale( maLanguageTag.getLocale() );
     275           0 :         xTransliteration.changeLocale( eLnge );
     276             : 
     277             :         // cached locale data items, initialize BEFORE calling ChangeIntl below
     278           0 :         const LocaleDataWrapper* pLoc = GetLocaleData();
     279           0 :         aDecimalSep = pLoc->getNumDecimalSep();
     280           0 :         aThousandSep = pLoc->getNumThousandSep();
     281           0 :         aDateSep = pLoc->getDateSep();
     282             : 
     283           0 :         pFormatScanner->ChangeIntl();
     284           0 :         pStringScanner->ChangeIntl();
     285             :     }
     286           0 : }
     287             : 
     288             : 
     289             : // static
     290           0 : ::osl::Mutex& SvNumberFormatter::GetMutex()
     291             : {
     292             :     static ::osl::Mutex* pMutex = NULL;
     293           0 :     if( !pMutex )
     294             :     {
     295           0 :         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
     296           0 :         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           0 :             pMutex = new ::osl::Mutex;
     302           0 :         }
     303             :     }
     304           0 :     return *pMutex;
     305             : }
     306             : 
     307             : 
     308             : // static
     309           0 : SvNumberFormatterRegistry_Impl& SvNumberFormatter::GetFormatterRegistry()
     310             : {
     311           0 :     ::osl::MutexGuard aGuard( GetMutex() );
     312           0 :     if ( !pFormatterRegistry )
     313             :     {
     314           0 :         pFormatterRegistry = new SvNumberFormatterRegistry_Impl;
     315             :     }
     316           0 :     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           0 : void SvNumberFormatter::ChangeNullDate(sal_uInt16 nDay,
     333             :                                        sal_uInt16 nMonth,
     334             :                                        sal_uInt16 nYear)
     335             : {
     336           0 :     pFormatScanner->ChangeNullDate(nDay, nMonth, nYear);
     337           0 :     pStringScanner->ChangeNullDate(nDay, nMonth, nYear);
     338           0 : }
     339             : 
     340           0 : Date* SvNumberFormatter::GetNullDate()
     341             : {
     342           0 :     return pFormatScanner->GetNullDate();
     343             : }
     344             : 
     345           0 : void SvNumberFormatter::ChangeStandardPrec(short nPrec)
     346             : {
     347           0 :     pFormatScanner->ChangeStandardPrec(nPrec);
     348           0 : }
     349             : 
     350           0 : sal_uInt16 SvNumberFormatter::GetStandardPrec()
     351             : {
     352           0 :     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           0 : bool SvNumberFormatter::IsTextFormat(sal_uInt32 F_Index) const
     486             : {
     487           0 :     const SvNumberformat* pFormat = GetFormatEntry(F_Index);
     488             : 
     489           0 :     return pFormat ? pFormat->IsTextFormat() : false;
     490             : }
     491             : 
     492           0 : bool SvNumberFormatter::PutEntry(OUString& rString,
     493             :                                  sal_Int32& nCheckPos,
     494             :                                  short& nType,
     495             :                                  sal_uInt32& nKey,      // format key
     496             :                                  LanguageType eLnge)
     497             : {
     498           0 :     nKey = 0;
     499           0 :     if (rString.isEmpty())                             // empty string
     500             :     {
     501           0 :         nCheckPos = 1;                                  // -> Error
     502           0 :         return false;
     503             :     }
     504           0 :     if (eLnge == LANGUAGE_DONTKNOW)
     505             :     {
     506           0 :         eLnge = IniLnge;
     507             :     }
     508           0 :     ChangeIntl(eLnge);                                  // change locale if necessary
     509           0 :     LanguageType eLge = eLnge;                          // non-const for ConvertMode
     510           0 :     bool bCheck = false;
     511             :     SvNumberformat* p_Entry = new SvNumberformat(rString,
     512             :                                                  pFormatScanner,
     513             :                                                  pStringScanner,
     514             :                                                  nCheckPos,
     515           0 :                                                  eLge);
     516             : 
     517           0 :     if (nCheckPos == 0)                         // Format ok
     518             :     {                                           // Type comparison:
     519           0 :         short eCheckType = p_Entry->GetType();
     520           0 :         if ( eCheckType != NUMBERFORMAT_UNDEFINED)
     521             :         {
     522           0 :             p_Entry->SetType(eCheckType | NUMBERFORMAT_DEFINED);
     523           0 :             nType = eCheckType;
     524             :         }
     525             :         else
     526             :         {
     527           0 :             p_Entry->SetType(NUMBERFORMAT_DEFINED);
     528           0 :             nType = NUMBERFORMAT_DEFINED;
     529             :         }
     530             : 
     531           0 :         sal_uInt32 CLOffset = ImpGenerateCL(eLge);  // create new standard formats if necessary
     532             : 
     533           0 :         nKey = ImpIsEntry(p_Entry->GetFormatstring(),CLOffset, eLge);
     534           0 :         if (nKey != NUMBERFORMAT_ENTRY_NOT_FOUND)   // already present
     535             :         {
     536           0 :             delete p_Entry;
     537             :         }
     538             :         else
     539             :         {
     540           0 :             SvNumberformat* pStdFormat = GetFormatEntry(CLOffset + ZF_STANDARD);
     541           0 :             sal_uInt32 nPos = CLOffset + pStdFormat->GetLastInsertKey();
     542           0 :             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           0 :             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           0 :                 bCheck = true;
     555           0 :                 nKey = nPos+1;
     556           0 :                 pStdFormat->SetLastInsertKey((sal_uInt16) (nKey-CLOffset));
     557             :             }
     558             :         }
     559             :     }
     560             :     else
     561             :     {
     562           0 :         delete p_Entry;
     563             :     }
     564           0 :     return bCheck;
     565             : }
     566             : 
     567           0 : 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           0 :     if (eNewLnge == LANGUAGE_DONTKNOW)
     576             :     {
     577           0 :         eNewLnge = IniLnge;
     578             :     }
     579           0 :     pFormatScanner->SetConvertMode(eLnge, eNewLnge);
     580           0 :     bRes = PutEntry(rString, nCheckPos, nType, nKey, eLnge);
     581           0 :     pFormatScanner->SetConvertMode(false);
     582           0 :     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           0 : void SvNumberFormatter::DeleteEntry(sal_uInt32 nKey)
     680             : {
     681           0 :     delete aFTable[nKey];
     682           0 :     aFTable.erase(nKey);
     683           0 : }
     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           0 : void SvNumberFormatter::GetUsedLanguages( std::vector<sal_uInt16>& rList )
     826             : {
     827           0 :     rList.clear();
     828             : 
     829           0 :     sal_uInt32 nOffset = 0;
     830           0 :     while (nOffset <= MaxCLOffset)
     831             :     {
     832           0 :         SvNumberformat* pFormat = GetFormatEntry(nOffset);
     833           0 :         if (pFormat)
     834             :         {
     835           0 :             rList.push_back( pFormat->GetLanguage() );
     836             :         }
     837           0 :         nOffset += SV_COUNTRY_LANGUAGE_OFFSET;
     838             :     }
     839           0 : }
     840             : 
     841             : 
     842           0 : void SvNumberFormatter::FillKeywordTable( NfKeywordTable& rKeywords,
     843             :                                           LanguageType eLang )
     844             : {
     845           0 :     ChangeIntl( eLang );
     846           0 :     const NfKeywordTable & rTable = pFormatScanner->GetKeywords();
     847           0 :     for ( sal_uInt16 i = 0; i < NF_KEYWORD_ENTRIES_COUNT; ++i )
     848             :     {
     849           0 :         rKeywords[i] = rTable[i];
     850             :     }
     851           0 : }
     852             : 
     853             : 
     854           0 : OUString SvNumberFormatter::GetKeyword( LanguageType eLnge, sal_uInt16 nIndex )
     855             : {
     856           0 :     ChangeIntl(eLnge);
     857           0 :     const NfKeywordTable & rTable = pFormatScanner->GetKeywords();
     858           0 :     if ( nIndex < NF_KEYWORD_ENTRIES_COUNT )
     859             :     {
     860           0 :         return rTable[nIndex];
     861             :     }
     862             :     SAL_WARN( "svl.numbers", "GetKeyword: invalid index");
     863           0 :     return OUString();
     864             : }
     865             : 
     866             : 
     867           0 : OUString SvNumberFormatter::GetStandardName( LanguageType eLnge )
     868             : {
     869           0 :     ChangeIntl( eLnge );
     870           0 :     return pFormatScanner->GetStandardName();
     871             : }
     872             : 
     873             : 
     874           0 : sal_uInt32 SvNumberFormatter::ImpGetCLOffset(LanguageType eLnge) const
     875             : {
     876           0 :     sal_uInt32 nOffset = 0;
     877           0 :     while (nOffset <= MaxCLOffset)
     878             :     {
     879           0 :         const SvNumberformat* pFormat = GetFormatEntry(nOffset);
     880           0 :         if (pFormat && pFormat->GetLanguage() == eLnge)
     881             :         {
     882           0 :             return nOffset;
     883             :         }
     884           0 :         nOffset += SV_COUNTRY_LANGUAGE_OFFSET;
     885             :     }
     886           0 :     return nOffset;
     887             : }
     888             : 
     889           0 : sal_uInt32 SvNumberFormatter::ImpIsEntry(const OUString& rString,
     890             :                                          sal_uInt32 nCLOffset,
     891             :                                          LanguageType eLnge)
     892             : {
     893           0 :     sal_uInt32 res = NUMBERFORMAT_ENTRY_NOT_FOUND;
     894           0 :     SvNumberFormatTable::iterator it = aFTable.find( nCLOffset);
     895           0 :     while ( res == NUMBERFORMAT_ENTRY_NOT_FOUND &&
     896           0 :             it != aFTable.end() && it->second->GetLanguage() == eLnge )
     897             :     {
     898           0 :         if ( rString == it->second->GetFormatstring() )
     899             :         {
     900           0 :             res = it->first;
     901             :         }
     902             :         else
     903             :         {
     904           0 :             ++it;
     905             :         }
     906             :     }
     907           0 :     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           0 : sal_uInt32 SvNumberFormatter::ImpGenerateCL( LanguageType eLnge, bool bNoAdditionalFormats )
     955             : {
     956           0 :     ChangeIntl(eLnge);
     957           0 :     sal_uInt32 CLOffset = ImpGetCLOffset(ActLnge);
     958           0 :     if (CLOffset > MaxCLOffset)
     959             :     {
     960             :         // new CL combination
     961           0 :         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           0 :         MaxCLOffset += SV_COUNTRY_LANGUAGE_OFFSET;
    1009           0 :         ImpGenerateFormats( MaxCLOffset, bNoAdditionalFormats );
    1010           0 :         CLOffset = MaxCLOffset;
    1011             :     }
    1012           0 :     return CLOffset;
    1013             : }
    1014             : 
    1015           0 : SvNumberFormatTable& SvNumberFormatter::ChangeCL(short eType,
    1016             :                                                  sal_uInt32& FIndex,
    1017             :                                                  LanguageType eLnge)
    1018             : {
    1019           0 :     ImpGenerateCL(eLnge);
    1020           0 :     return GetEntryTable(eType, FIndex, ActLnge);
    1021             : }
    1022             : 
    1023           0 : SvNumberFormatTable& SvNumberFormatter::GetEntryTable(
    1024             :                                                     short eType,
    1025             :                                                     sal_uInt32& FIndex,
    1026             :                                                     LanguageType eLnge)
    1027             : {
    1028           0 :     if ( pFormatTable )
    1029             :     {
    1030           0 :         pFormatTable->clear();
    1031             :     }
    1032             :     else
    1033             :     {
    1034           0 :         pFormatTable = new SvNumberFormatTable;
    1035             :     }
    1036           0 :     ChangeIntl(eLnge);
    1037           0 :     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           0 :     sal_uInt32 nDefaultIndex = GetStandardFormat( eType, ActLnge );
    1042             : 
    1043           0 :     SvNumberFormatTable::iterator it = aFTable.find( CLOffset);
    1044             : 
    1045           0 :     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           0 :         while (it != aFTable.end() && it->second->GetLanguage() == ActLnge)
    1056             :         {   // copy entries of queried type to output table
    1057           0 :             if ((it->second->GetType()) & eType)
    1058           0 :                 (*pFormatTable)[ it->first ] = it->second;
    1059           0 :             ++it;
    1060             :         }
    1061             :     }
    1062           0 :     if ( !pFormatTable->empty() )
    1063             :     {   // select default if queried format doesn't exist or queried type or
    1064             :         // language differ from existing format
    1065           0 :         SvNumberformat* pEntry = GetFormatEntry(FIndex);
    1066           0 :         if ( !pEntry || !(pEntry->GetType() & eType) || pEntry->GetLanguage() != ActLnge )
    1067             :         {
    1068           0 :             FIndex = nDefaultIndex;
    1069             :         }
    1070             :     }
    1071           0 :     return *pFormatTable;
    1072             : }
    1073             : 
    1074           0 : bool SvNumberFormatter::IsNumberFormat(const OUString& sString,
    1075             :                                        sal_uInt32& F_Index,
    1076             :                                        double& fOutNumber)
    1077             : {
    1078             :     short FType;
    1079           0 :     const SvNumberformat* pFormat = GetFormatEntry(F_Index);
    1080           0 :     if (!pFormat)
    1081             :     {
    1082           0 :         ChangeIntl(IniLnge);
    1083           0 :         FType = NUMBERFORMAT_NUMBER;
    1084             :     }
    1085             :     else
    1086             :     {
    1087           0 :         FType = pFormat->GetType() &~NUMBERFORMAT_DEFINED;
    1088           0 :         if (FType == 0)
    1089             :         {
    1090           0 :             FType = NUMBERFORMAT_DEFINED;
    1091             :         }
    1092           0 :         ChangeIntl(pFormat->GetLanguage());
    1093             :     }
    1094             : 
    1095             :     bool res;
    1096           0 :     short RType = FType;
    1097           0 :     if (RType == NUMBERFORMAT_TEXT)
    1098             :     {
    1099           0 :         res = false;        // type text preset => no conversion to number
    1100             :     }
    1101             :     else
    1102             :     {
    1103           0 :         res = pStringScanner->IsNumberFormat(sString, RType, fOutNumber, pFormat);
    1104             :     }
    1105           0 :     if (res && !IsCompatible(FType, RType))     // non-matching type
    1106             :     {
    1107           0 :         switch ( RType )
    1108             :         {
    1109             :         case NUMBERFORMAT_DATE :
    1110             :             // Preserve ISO 8601 input.
    1111           0 :             if (pStringScanner->CanForceToIso8601( DMY))
    1112             :             {
    1113           0 :                 F_Index = GetFormatIndex( NF_DATE_DIN_YYYYMMDD, ActLnge );
    1114             :             }
    1115             :             else
    1116             :             {
    1117           0 :                 F_Index = GetStandardFormat( RType, ActLnge );
    1118             :             }
    1119           0 :             break;
    1120             :         case NUMBERFORMAT_TIME :
    1121           0 :             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           0 :             else if ( fOutNumber >= 1.0 || fOutNumber < 0.0 )
    1134             :             {
    1135           0 :                 F_Index = GetFormatIndex( NF_TIME_HH_MMSS, ActLnge );
    1136             :             }
    1137             :             else
    1138             :             {
    1139           0 :                 F_Index = GetStandardFormat( RType, ActLnge );
    1140             :             }
    1141           0 :             break;
    1142             :         default:
    1143           0 :             F_Index = GetStandardFormat( RType, ActLnge );
    1144             :         }
    1145             :     }
    1146           0 :     return res;
    1147             : }
    1148             : 
    1149           0 : bool SvNumberFormatter::IsCompatible(short eOldType,
    1150             :                                      short eNewType)
    1151             : {
    1152           0 :     if (eOldType == eNewType)
    1153             :     {
    1154           0 :         return true;
    1155             :     }
    1156           0 :     else if (eOldType == NUMBERFORMAT_DEFINED)
    1157             :     {
    1158           0 :         return true;
    1159             :     }
    1160             :     else
    1161             :     {
    1162           0 :         switch (eNewType)
    1163             :         {
    1164             :         case NUMBERFORMAT_NUMBER:
    1165           0 :             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           0 :                 return true;
    1174             :             default:
    1175           0 :                 return false;
    1176             :             }
    1177             :             break;
    1178             :         case NUMBERFORMAT_DATE:
    1179           0 :             switch (eOldType)
    1180             :             {
    1181             :             case NUMBERFORMAT_DATETIME:
    1182           0 :                 return true;
    1183             :             default:
    1184           0 :                 return false;
    1185             :             }
    1186             :             break;
    1187             :         case NUMBERFORMAT_TIME:
    1188           0 :             switch (eOldType)
    1189             :             {
    1190             :             case NUMBERFORMAT_DATETIME:
    1191           0 :                 return true;
    1192             :             default:
    1193           0 :                 return false;
    1194             :             }
    1195             :             break;
    1196             :         case NUMBERFORMAT_DATETIME:
    1197           0 :             switch (eOldType)
    1198             :             {
    1199             :             case NUMBERFORMAT_TIME:
    1200             :             case NUMBERFORMAT_DATE:
    1201           0 :                 return true;
    1202             :             default:
    1203           0 :                 return false;
    1204             :             }
    1205             :             break;
    1206             :         default:
    1207           0 :             return false;
    1208             :         }
    1209             :     }
    1210             : }
    1211             : 
    1212             : 
    1213           0 : sal_uInt32 SvNumberFormatter::ImpGetDefaultFormat( short nType )
    1214             : {
    1215           0 :     sal_uInt32 CLOffset = ImpGetCLOffset( ActLnge );
    1216             :     sal_uInt32 nSearch;
    1217           0 :     switch( nType )
    1218             :     {
    1219             :     case NUMBERFORMAT_DATE:
    1220           0 :         nSearch = CLOffset + ZF_STANDARD_DATE;
    1221           0 :         break;
    1222             :     case NUMBERFORMAT_TIME:
    1223           0 :         nSearch = CLOffset + ZF_STANDARD_TIME;
    1224           0 :         break;
    1225             :     case NUMBERFORMAT_DATETIME:
    1226           0 :         nSearch = CLOffset + ZF_STANDARD_DATETIME;
    1227           0 :         break;
    1228             :     case NUMBERFORMAT_PERCENT:
    1229           0 :         nSearch = CLOffset + ZF_STANDARD_PERCENT;
    1230           0 :         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           0 :     DefaultFormatKeysMap::iterator it = aDefaultFormatKeys.find( nSearch);
    1239           0 :     sal_uInt32 nDefaultFormat = (it != aDefaultFormatKeys.end() ?
    1240           0 :                                  it->second : NUMBERFORMAT_ENTRY_NOT_FOUND);
    1241           0 :     if ( nDefaultFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
    1242             :     {
    1243             :         // look for a defined standard
    1244           0 :         sal_uInt32 nStopKey = CLOffset + SV_COUNTRY_LANGUAGE_OFFSET;
    1245           0 :         sal_uInt32 nKey(0);
    1246           0 :         SvNumberFormatTable::iterator it2 = aFTable.find( CLOffset );
    1247           0 :         while ( it2 != aFTable.end() && (nKey = it2->first ) >= CLOffset && nKey < nStopKey )
    1248             :         {
    1249           0 :             const SvNumberformat* pEntry = it2->second;
    1250           0 :             if ( pEntry->IsStandard() && ((pEntry->GetType() &
    1251           0 :                             ~NUMBERFORMAT_DEFINED) == nType) )
    1252             :             {
    1253           0 :                 nDefaultFormat = nKey;
    1254           0 :                 break;  // while
    1255             :             }
    1256           0 :             ++it2;
    1257             :         }
    1258             : 
    1259           0 :         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           0 :         aDefaultFormatKeys[ nSearch ] = nDefaultFormat;
    1283             :     }
    1284           0 :     return nDefaultFormat;
    1285             : }
    1286             : 
    1287             : 
    1288           0 : sal_uInt32 SvNumberFormatter::GetStandardFormat( short eType, LanguageType eLnge )
    1289             : {
    1290           0 :     if (eLnge == LANGUAGE_DONTKNOW)
    1291             :     {
    1292           0 :         eLnge = IniLnge;
    1293             :     }
    1294           0 :     sal_uInt32 CLOffset = ImpGenerateCL(eLnge);
    1295           0 :     switch(eType)
    1296             :     {
    1297             :     case NUMBERFORMAT_CURRENCY:
    1298           0 :         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           0 :         return ImpGetDefaultFormat( eType );
    1305             :     case NUMBERFORMAT_FRACTION:
    1306           0 :         return CLOffset + ZF_STANDARD_FRACTION;
    1307             :     case NUMBERFORMAT_LOGICAL:
    1308           0 :         return CLOffset + ZF_STANDARD_LOGICAL;
    1309             :     case NUMBERFORMAT_TEXT:
    1310           0 :         return CLOffset + ZF_STANDARD_TEXT;
    1311             :     case NUMBERFORMAT_ALL:
    1312             :     case NUMBERFORMAT_DEFINED:
    1313             :     case NUMBERFORMAT_NUMBER:
    1314             :     case NUMBERFORMAT_UNDEFINED:
    1315             :     default:
    1316           0 :         return CLOffset + ZF_STANDARD;
    1317             :     }
    1318             : }
    1319             : 
    1320           0 : bool SvNumberFormatter::IsSpecialStandardFormat( sal_uInt32 nFIndex,
    1321             :                                                  LanguageType eLnge )
    1322             : {
    1323             :     return
    1324           0 :         nFIndex == GetFormatIndex( NF_TIME_MMSS00, eLnge ) ||
    1325           0 :         nFIndex == GetFormatIndex( NF_TIME_HH_MMSS00, eLnge ) ||
    1326           0 :         nFIndex == GetFormatIndex( NF_TIME_HH_MMSS, eLnge )
    1327             :         ;
    1328             : }
    1329             : 
    1330           0 : sal_uInt32 SvNumberFormatter::GetStandardFormat( sal_uInt32 nFIndex, short eType,
    1331             :                                                  LanguageType eLnge )
    1332             : {
    1333           0 :     if ( IsSpecialStandardFormat( nFIndex, eLnge ) )
    1334           0 :         return nFIndex;
    1335             :     else
    1336           0 :         return GetStandardFormat( eType, eLnge );
    1337             : }
    1338             : 
    1339           0 : sal_uInt32 SvNumberFormatter::GetStandardFormat( double fNumber, sal_uInt32 nFIndex,
    1340             :                                                  short eType, LanguageType eLnge )
    1341             : {
    1342           0 :     if ( IsSpecialStandardFormat( nFIndex, eLnge ) )
    1343           0 :         return nFIndex;
    1344             : 
    1345           0 :     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           0 :             return GetStandardFormat( eType, eLnge );
    1375             :     }
    1376             : }
    1377             : 
    1378           0 : sal_uInt32 SvNumberFormatter::GetEditFormat( double fNumber, sal_uInt32 nFIndex,
    1379             :                                              short eType, LanguageType eLang,
    1380             :                                              SvNumberformat* pFormat )
    1381             : {
    1382           0 :     sal_uInt32 nKey = nFIndex;
    1383           0 :     switch ( eType )
    1384             :     {
    1385             :     // #61619# always edit using 4-digit year
    1386             :     case NUMBERFORMAT_DATE :
    1387           0 :         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           0 :             if (    nFIndex == GetFormatIndex( NF_DATE_DIN_YYYYMMDD, eLang) ||
    1399           0 :                     nFIndex == GetFormatIndex( NF_DATE_DIN_YYMMDD, eLang) ||
    1400           0 :                     nFIndex == GetFormatIndex( NF_DATE_DIN_MMDD, eLang) ||
    1401           0 :                     (pFormat && pFormat->IsIso8601( 0 )))
    1402           0 :                 nKey = GetFormatIndex( NF_DATE_DIN_YYYYMMDD, eLang);
    1403             :             else
    1404           0 :                 nKey = GetFormatIndex( NF_DATE_SYS_DDMMYYYY, eLang );
    1405             :         }
    1406           0 :         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           0 :         nKey = GetStandardFormat( fNumber, nFIndex, eType, eLang );
    1432             :     }
    1433           0 :     return nKey;
    1434             : }
    1435             : 
    1436           0 : void SvNumberFormatter::GetInputLineString(const double& fOutNumber,
    1437             :                                            sal_uInt32 nFIndex,
    1438             :                                            OUString& sOutString)
    1439             : {
    1440             :     Color* pColor;
    1441           0 :     SvNumberformat* pFormat = GetFormatEntry( nFIndex );
    1442           0 :     if (!pFormat)
    1443             :     {
    1444           0 :         pFormat = GetFormatEntry(ZF_STANDARD);
    1445             :     }
    1446             : 
    1447           0 :     LanguageType eLang = pFormat->GetLanguage();
    1448           0 :     ChangeIntl( eLang );
    1449             : 
    1450           0 :     short eType = pFormat->GetType() & ~NUMBERFORMAT_DEFINED;
    1451           0 :     if (eType == 0)
    1452             :     {
    1453           0 :         eType = NUMBERFORMAT_DEFINED;
    1454             :     }
    1455             : 
    1456           0 :     sal_uInt16 nOldPrec = pFormatScanner->GetStandardPrec();
    1457           0 :     bool bPrecChanged = false;
    1458           0 :     if (eType == NUMBERFORMAT_NUMBER ||
    1459           0 :         eType == NUMBERFORMAT_PERCENT ||
    1460           0 :         eType == NUMBERFORMAT_CURRENCY ||
    1461           0 :         eType == NUMBERFORMAT_SCIENTIFIC ||
    1462             :         eType == NUMBERFORMAT_FRACTION)
    1463             :     {
    1464           0 :         if (eType != NUMBERFORMAT_PERCENT)  // special treatment of % later
    1465             :         {
    1466           0 :             eType = NUMBERFORMAT_NUMBER;
    1467             :         }
    1468           0 :         ChangeStandardPrec(INPUTSTRING_PRECISION);
    1469           0 :         bPrecChanged = true;
    1470             :     }
    1471             : 
    1472           0 :     sal_uInt32 nKey = GetEditFormat( fOutNumber, nFIndex, eType, eLang, pFormat);
    1473           0 :     if ( nKey != nFIndex )
    1474             :     {
    1475           0 :         pFormat = GetFormatEntry( nKey );
    1476             :     }
    1477           0 :     if (pFormat)
    1478             :     {
    1479           0 :         if ( eType == NUMBERFORMAT_TIME && pFormat->GetFormatPrecision() )
    1480             :         {
    1481           0 :             ChangeStandardPrec(INPUTSTRING_PRECISION);
    1482           0 :             bPrecChanged = true;
    1483             :         }
    1484           0 :         pFormat->GetOutputString(fOutNumber, sOutString, &pColor);
    1485             :     }
    1486           0 :     if (bPrecChanged)
    1487             :     {
    1488           0 :         ChangeStandardPrec(nOldPrec);
    1489             :     }
    1490           0 : }
    1491             : 
    1492           0 : void SvNumberFormatter::GetOutputString(const OUString& sString,
    1493             :                                         sal_uInt32 nFIndex,
    1494             :                                         OUString& sOutString,
    1495             :                                         Color** ppColor,
    1496             :                                         bool bUseStarFormat )
    1497             : {
    1498           0 :     SvNumberformat* pFormat = GetFormatEntry( nFIndex );
    1499           0 :     if (!pFormat)
    1500             :     {
    1501           0 :         pFormat = GetFormatEntry(ZF_STANDARD_TEXT);
    1502             :     }
    1503           0 :     if (!pFormat->IsTextFormat() && !pFormat->HasTextFormat())
    1504             :     {
    1505           0 :         *ppColor = NULL;
    1506           0 :         sOutString = sString;
    1507             :     }
    1508             :     else
    1509             :     {
    1510           0 :         ChangeIntl(pFormat->GetLanguage());
    1511           0 :         if ( bUseStarFormat )
    1512             :         {
    1513           0 :            pFormat->SetStarFormatSupport( true );
    1514             :         }
    1515           0 :         pFormat->GetOutputString(sString, sOutString, ppColor);
    1516           0 :         if ( bUseStarFormat )
    1517             :         {
    1518           0 :            pFormat->SetStarFormatSupport( false );
    1519             :         }
    1520             :     }
    1521           0 : }
    1522             : 
    1523           0 : void SvNumberFormatter::GetOutputString(const double& fOutNumber,
    1524             :                                         sal_uInt32 nFIndex,
    1525             :                                         OUString& sOutString,
    1526             :                                         Color** ppColor,
    1527             :                                         bool bUseStarFormat )
    1528             : {
    1529           0 :     if (bNoZero && fOutNumber == 0.0)
    1530             :     {
    1531           0 :         sOutString = OUString();
    1532           0 :         return;
    1533             :     }
    1534           0 :     SvNumberformat* pFormat = GetFormatEntry( nFIndex );
    1535           0 :     if (!pFormat)
    1536           0 :         pFormat = GetFormatEntry(ZF_STANDARD);
    1537           0 :     ChangeIntl(pFormat->GetLanguage());
    1538           0 :     if ( bUseStarFormat )
    1539           0 :         pFormat->SetStarFormatSupport( true );
    1540           0 :     pFormat->GetOutputString(fOutNumber, sOutString, ppColor);
    1541           0 :     if ( bUseStarFormat )
    1542           0 :         pFormat->SetStarFormatSupport( false );
    1543             : }
    1544             : 
    1545           0 : bool SvNumberFormatter::GetPreviewString(const OUString& sFormatString,
    1546             :                                          double fPreviewNumber,
    1547             :                                          OUString& sOutString,
    1548             :                                          Color** ppColor,
    1549             :                                          LanguageType eLnge,
    1550             :                                          bool bUseStarFormat )
    1551             : {
    1552           0 :     if (sFormatString.isEmpty())                       // no empty string
    1553             :     {
    1554           0 :         return false;
    1555             :     }
    1556             :     sal_uInt32 nKey;
    1557           0 :     if (eLnge == LANGUAGE_DONTKNOW)
    1558             :     {
    1559           0 :         eLnge = IniLnge;
    1560             :     }
    1561           0 :     ChangeIntl(eLnge);                          // change locale if necessary
    1562           0 :     eLnge = ActLnge;
    1563           0 :     sal_Int32 nCheckPos = -1;
    1564           0 :     OUString sTmpString = sFormatString;
    1565             :     SvNumberformat* p_Entry = new SvNumberformat(sTmpString,
    1566             :                                                  pFormatScanner,
    1567             :                                                  pStringScanner,
    1568             :                                                  nCheckPos,
    1569           0 :                                                  eLnge);
    1570           0 :     if (nCheckPos == 0)                                 // String ok
    1571             :     {
    1572           0 :         sal_uInt32 CLOffset = ImpGenerateCL(eLnge);     // create new standard formats if necessary
    1573           0 :         nKey = ImpIsEntry(p_Entry->GetFormatstring(),CLOffset, eLnge);
    1574           0 :         if (nKey != NUMBERFORMAT_ENTRY_NOT_FOUND)       // already present
    1575             :         {
    1576           0 :             GetOutputString(fPreviewNumber, nKey, sOutString, ppColor, bUseStarFormat);
    1577             :         }
    1578             :         else
    1579             :         {
    1580           0 :             if ( bUseStarFormat )
    1581             :             {
    1582           0 :                 p_Entry->SetStarFormatSupport( true );
    1583             :             }
    1584           0 :             p_Entry->GetOutputString(fPreviewNumber, sOutString, ppColor);
    1585           0 :             if ( bUseStarFormat )
    1586             :             {
    1587           0 :                 p_Entry->SetStarFormatSupport( false );
    1588             :             }
    1589             :         }
    1590           0 :         delete p_Entry;
    1591           0 :         return true;
    1592             :     }
    1593             :     else
    1594             :     {
    1595           0 :         delete p_Entry;
    1596           0 :         return false;
    1597           0 :     }
    1598             : }
    1599             : 
    1600           0 : bool SvNumberFormatter::GetPreviewStringGuess( const OUString& sFormatString,
    1601             :                                                double fPreviewNumber,
    1602             :                                                OUString& sOutString,
    1603             :                                                Color** ppColor,
    1604             :                                                LanguageType eLnge )
    1605             : {
    1606           0 :     if (sFormatString.isEmpty())                       // no empty string
    1607             :     {
    1608           0 :         return false;
    1609             :     }
    1610           0 :     if (eLnge == LANGUAGE_DONTKNOW)
    1611             :     {
    1612           0 :         eLnge = IniLnge;
    1613             :     }
    1614           0 :     ChangeIntl( eLnge );
    1615           0 :     eLnge = ActLnge;
    1616           0 :     bool bEnglish = (eLnge == LANGUAGE_ENGLISH_US);
    1617             : 
    1618           0 :     OUString aFormatStringUpper( pCharClass->uppercase( sFormatString ) );
    1619           0 :     sal_uInt32 nCLOffset = ImpGenerateCL( eLnge );
    1620           0 :     sal_uInt32 nKey = ImpIsEntry( aFormatStringUpper, nCLOffset, eLnge );
    1621           0 :     if ( nKey != NUMBERFORMAT_ENTRY_NOT_FOUND )
    1622             :     {
    1623             :         // Zielformat vorhanden
    1624           0 :         GetOutputString( fPreviewNumber, nKey, sOutString, ppColor );
    1625           0 :         return true;
    1626             :     }
    1627             : 
    1628           0 :     SvNumberformat *pEntry = NULL;
    1629           0 :     sal_Int32 nCheckPos = -1;
    1630           0 :     OUString sTmpString;
    1631             : 
    1632           0 :     if ( bEnglish )
    1633             :     {
    1634           0 :         sTmpString = sFormatString;
    1635             :         pEntry = new SvNumberformat( sTmpString, pFormatScanner,
    1636           0 :                                      pStringScanner, nCheckPos, eLnge );
    1637             :     }
    1638             :     else
    1639             :     {
    1640           0 :         nCLOffset = ImpGenerateCL( LANGUAGE_ENGLISH_US );
    1641           0 :         nKey = ImpIsEntry( aFormatStringUpper, nCLOffset, LANGUAGE_ENGLISH_US );
    1642           0 :         bool bEnglishFormat = (nKey != NUMBERFORMAT_ENTRY_NOT_FOUND);
    1643             : 
    1644             :         // try english --> other bzw. english nach other konvertieren
    1645           0 :         LanguageType eFormatLang = LANGUAGE_ENGLISH_US;
    1646           0 :         pFormatScanner->SetConvertMode( LANGUAGE_ENGLISH_US, eLnge );
    1647           0 :         sTmpString = sFormatString;
    1648             :         pEntry = new SvNumberformat( sTmpString, pFormatScanner,
    1649           0 :                                      pStringScanner, nCheckPos, eFormatLang );
    1650           0 :         pFormatScanner->SetConvertMode( false );
    1651           0 :         ChangeIntl( eLnge );
    1652             : 
    1653           0 :         if ( !bEnglishFormat )
    1654             :         {
    1655           0 :             if ( !(nCheckPos == 0) || xTransliteration->isEqual( sFormatString,
    1656           0 :                                                                  pEntry->GetFormatstring() ) )
    1657             :             {
    1658             :                 // other Format
    1659           0 :                 delete pEntry;
    1660           0 :                 sTmpString = sFormatString;
    1661             :                 pEntry = new SvNumberformat( sTmpString, pFormatScanner,
    1662           0 :                                              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           0 :     if (nCheckPos == 0)                                 // String ok
    1691             :     {
    1692           0 :         ImpGenerateCL( eLnge );     // create new standard formats if necessary
    1693           0 :         pEntry->GetOutputString( fPreviewNumber, sOutString, ppColor );
    1694           0 :         delete pEntry;
    1695           0 :         return true;
    1696             :     }
    1697           0 :     delete pEntry;
    1698           0 :     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           0 : sal_uInt32 SvNumberFormatter::TestNewString(const OUString& sFormatString,
    1760             :                                             LanguageType eLnge)
    1761             : {
    1762           0 :     if (sFormatString.isEmpty())                       // no empty string
    1763             :     {
    1764           0 :         return NUMBERFORMAT_ENTRY_NOT_FOUND;
    1765             :     }
    1766           0 :     if (eLnge == LANGUAGE_DONTKNOW)
    1767             :     {
    1768           0 :         eLnge = IniLnge;
    1769             :     }
    1770           0 :     ChangeIntl(eLnge);                                  // change locale if necessary
    1771           0 :     eLnge = ActLnge;
    1772             :     sal_uInt32 nRes;
    1773           0 :     sal_Int32 nCheckPos = -1;
    1774           0 :     OUString sTmpString = sFormatString;
    1775             :     SvNumberformat* pEntry = new SvNumberformat(sTmpString,
    1776             :                                                 pFormatScanner,
    1777             :                                                 pStringScanner,
    1778             :                                                 nCheckPos,
    1779           0 :                                                 eLnge);
    1780           0 :     if (nCheckPos == 0)                                 // String ok
    1781             :     {
    1782           0 :         sal_uInt32 CLOffset = ImpGenerateCL(eLnge);     // create new standard formats if necessary
    1783           0 :         nRes = ImpIsEntry(pEntry->GetFormatstring(),CLOffset, eLnge);
    1784             :                                                         // already present?
    1785             :     }
    1786             :     else
    1787             :     {
    1788           0 :         nRes = NUMBERFORMAT_ENTRY_NOT_FOUND;
    1789             :     }
    1790           0 :     delete pEntry;
    1791           0 :     return nRes;
    1792             : }
    1793             : 
    1794           0 : SvNumberformat* SvNumberFormatter::ImpInsertFormat( const ::com::sun::star::i18n::NumberFormatCode& rCode,
    1795             :                                                     sal_uInt32 nPos, bool bAfterChangingSystemCL,
    1796             :                                                     sal_Int16 nOrgIndex )
    1797             : {
    1798           0 :     OUString aCodeStr( rCode.Code );
    1799           0 :     if ( rCode.Index < NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS &&
    1800           0 :             rCode.Usage == ::com::sun::star::i18n::KNumberFormatUsage::CURRENCY &&
    1801           0 :             rCode.Index != NF_CURRENCY_1000DEC2_CCC )
    1802             :     {   // strip surrounding [$...] on automatic currency
    1803           0 :         if ( aCodeStr.indexOf( "[$" ) >= 0)
    1804           0 :             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           0 :     sal_Int32 nCheckPos = 0;
    1819           0 :     OUString sTempIn(aCodeStr);
    1820             :     SvNumberformat* pFormat = new SvNumberformat(sTempIn,
    1821             :                                                  pFormatScanner,
    1822             :                                                  pStringScanner,
    1823             :                                                  nCheckPos,
    1824           0 :                                                  ActLnge);
    1825           0 :     aCodeStr = sTempIn;
    1826           0 :     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           0 :     if ( rCode.Index >= NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS )
    1840             :     {
    1841           0 :         sal_uInt32 nCLOffset = nPos - (nPos % SV_COUNTRY_LANGUAGE_OFFSET);
    1842           0 :         sal_uInt32 nKey = ImpIsEntry( aCodeStr, nCLOffset, ActLnge );
    1843           0 :         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           0 :         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           0 :     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           0 :     if ( rCode.Default )
    1905           0 :         pFormat->SetStandard();
    1906           0 :     if ( !rCode.DefaultName.isEmpty() )
    1907           0 :         pFormat->SetComment( rCode.DefaultName );
    1908           0 :     return pFormat;
    1909             : }
    1910             : 
    1911           0 : 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           0 :         bAfterChangingSystemCL, nOrgIndex );
    1918           0 :     if (pNewFormat)
    1919           0 :         pNewFormat->SetNewStandardDefined( nVersion );
    1920             :         // so that it gets saved, displayed properly, and converted by old versions
    1921           0 :     return pNewFormat;
    1922             : }
    1923             : 
    1924           0 : void SvNumberFormatter::GetFormatSpecialInfo(sal_uInt32 nFormat,
    1925             :                                              bool& bThousand,
    1926             :                                              bool& IsRed,
    1927             :                                              sal_uInt16& nPrecision,
    1928             :                                              sal_uInt16& nAnzLeading)
    1929             : 
    1930             : {
    1931           0 :     SvNumberformat* pFormat = GetFormatEntry( nFormat );
    1932           0 :     if (pFormat)
    1933             :         pFormat->GetFormatSpecialInfo(bThousand, IsRed,
    1934           0 :                                       nPrecision, nAnzLeading);
    1935             :     else
    1936             :     {
    1937           0 :         bThousand = false;
    1938           0 :         IsRed = false;
    1939           0 :         nPrecision = pFormatScanner->GetStandardPrec();
    1940           0 :         nAnzLeading = 0;
    1941             :     }
    1942           0 : }
    1943             : 
    1944           0 : sal_uInt16 SvNumberFormatter::GetFormatPrecision( sal_uInt32 nFormat ) const
    1945             : {
    1946           0 :     const SvNumberformat* pFormat = GetFormatEntry( nFormat );
    1947           0 :     if ( pFormat )
    1948           0 :         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           0 : inline sal_uInt32 SetIndexTable( NfIndexTableOffset nTabOff, sal_uInt32 nIndOff )
    2010             : {
    2011           0 :     osl::MutexGuard aGuard(&theIndexTable.maMtx);
    2012             : 
    2013           0 :     if (!theIndexTable.mbInitialized)
    2014             :     {
    2015             :         DBG_ASSERT(theIndexTable.maData[nTabOff] == NUMBERFORMAT_ENTRY_NOT_FOUND,
    2016             :             "SetIndexTable: theIndexTable[nTabOff] already occupied" );
    2017           0 :         theIndexTable.maData[nTabOff] = nIndOff;
    2018             :     }
    2019           0 :     return nIndOff;
    2020             : }
    2021             : 
    2022             : 
    2023           0 : sal_Int32 SvNumberFormatter::ImpGetFormatCodeIndex(
    2024             :             ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::NumberFormatCode >& rSeq,
    2025             :             const NfIndexTableOffset nTabOff )
    2026             : {
    2027           0 :     const sal_Int32 nLen = rSeq.getLength();
    2028           0 :     for ( sal_Int32 j=0; j<nLen; j++ )
    2029             :     {
    2030           0 :         if ( rSeq[j].Index == nTabOff )
    2031           0 :             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           0 : 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           0 :     if ( !nCnt )
    2090           0 :         return -1;
    2091           0 :     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           0 :     nDef = nMedium = -1;
    2162           0 :     for ( nElem = 0; nElem < nCnt; nElem++ )
    2163             :     {
    2164           0 :         if ( pFormatArr[nElem].Default )
    2165             :         {
    2166           0 :             switch ( pFormatArr[nElem].Type )
    2167             :             {
    2168             :             case i18n::KNumberFormatType::MEDIUM :
    2169           0 :                 nDef = nMedium = nElem;
    2170           0 :                 break;
    2171             :             case i18n::KNumberFormatType::LONG :
    2172           0 :                 if ( nMedium == -1 )
    2173           0 :                     nDef = nElem;
    2174             :                 // fallthru
    2175             :             default:
    2176           0 :                 if ( nDef == -1 )
    2177           0 :                     nDef = nElem;
    2178           0 :                 pFormatArr[nElem].Default = false;
    2179             :             }
    2180             :         }
    2181             :     }
    2182           0 :     if ( nDef == -1 )
    2183           0 :         nDef = 0;
    2184           0 :     pFormatArr[nDef].Default = true;
    2185           0 :     return nDef;
    2186             : }
    2187             : 
    2188           0 : SvNumberformat* SvNumberFormatter::GetFormatEntry( sal_uInt32 nKey )
    2189             : {
    2190           0 :     SvNumberFormatTable::iterator it = aFTable.find( nKey);
    2191           0 :     if (it != aFTable.end())
    2192           0 :         return it->second;
    2193           0 :     return 0;
    2194             : }
    2195             : 
    2196           0 : const SvNumberformat* SvNumberFormatter::GetEntry( sal_uInt32 nKey ) const
    2197             : {
    2198           0 :     SvNumberFormatTable::const_iterator it = aFTable.find( nKey);
    2199           0 :     if (it != aFTable.end())
    2200           0 :         return it->second;
    2201           0 :     return 0;
    2202             : }
    2203             : 
    2204           0 : void SvNumberFormatter::ImpGenerateFormats( sal_uInt32 CLOffset, bool bNoAdditionalFormats )
    2205             : {
    2206             :     using namespace ::com::sun::star;
    2207             : 
    2208             :     {
    2209           0 :         osl::MutexGuard aGuard(&theIndexTable.maMtx);
    2210           0 :         if (!theIndexTable.mbInitialized)
    2211             :         {
    2212           0 :             for ( sal_uInt16 j=0; j<NF_INDEX_TABLE_ENTRIES; j++ )
    2213             :             {
    2214           0 :                 theIndexTable.maData[j] = NUMBERFORMAT_ENTRY_NOT_FOUND;
    2215             :             }
    2216           0 :         }
    2217             :     }
    2218             : 
    2219           0 :     bool bOldConvertMode = pFormatScanner->GetConvertMode();
    2220           0 :     if (bOldConvertMode)
    2221             :     {
    2222           0 :         pFormatScanner->SetConvertMode(false);      // switch off for this function
    2223             :     }
    2224             : 
    2225             :     NumberFormatCodeWrapper aNumberFormatCode( m_xContext,
    2226           0 :             GetLanguageTag().getLocale() );
    2227           0 :     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           0 :     sal_uInt16 nNewExtended = ZF_STANDARD_NEWEXTENDED;
    2236             : 
    2237             :     // Number
    2238             :     uno::Sequence< i18n::NumberFormatCode > aFormatSeq =
    2239           0 :         aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::FIXED_NUMBER );
    2240           0 :     ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() );
    2241             : 
    2242             :     // General
    2243           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_STANDARD );
    2244           0 :     SvNumberformat* pStdFormat = ImpInsertFormat( aFormatSeq[nIdx],
    2245           0 :             CLOffset + SetIndexTable( NF_NUMBER_STANDARD, ZF_STANDARD ));
    2246           0 :     if (pStdFormat)
    2247             :     {
    2248             :         // This is _the_ standard format.
    2249           0 :         if (LocaleDataWrapper::areChecksEnabled() && pStdFormat->GetType() != NUMBERFORMAT_NUMBER)
    2250             :         {
    2251             :             LocaleDataWrapper::outputCheckMessage( xLocaleData->
    2252           0 :                                                    appendLocaleInfo( "SvNumberFormatter::ImpGenerateFormats: General format not NUMBER"));
    2253             :         }
    2254           0 :         pStdFormat->SetType( NUMBERFORMAT_NUMBER );
    2255           0 :         pStdFormat->SetStandard();
    2256           0 :         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           0 :     OUString aFormatCode = pFormatScanner->GetBooleanString();
    2269           0 :     sal_Int32 nCheckPos = 0;
    2270             : 
    2271             :     pNewFormat = new SvNumberformat( aFormatCode, pFormatScanner,
    2272           0 :                                      pStringScanner, nCheckPos, ActLnge );
    2273           0 :     pNewFormat->SetType(NUMBERFORMAT_LOGICAL);
    2274           0 :     pNewFormat->SetStandard();
    2275           0 :     if ( !aFTable.insert(make_pair(
    2276           0 :                              CLOffset + SetIndexTable( NF_BOOLEAN, ZF_STANDARD_LOGICAL ),
    2277           0 :                              pNewFormat)).second)
    2278             :     {
    2279             :         SAL_WARN( "svl.numbers", "SvNumberFormatter::ImpGenerateFormats: dup position Boolean");
    2280           0 :         delete pNewFormat;
    2281             :     }
    2282             : 
    2283             :     // Text
    2284           0 :     aFormatCode = "@";
    2285             :     pNewFormat = new SvNumberformat( aFormatCode, pFormatScanner,
    2286           0 :                                      pStringScanner, nCheckPos, ActLnge );
    2287           0 :     pNewFormat->SetType(NUMBERFORMAT_TEXT);
    2288           0 :     pNewFormat->SetStandard();
    2289           0 :     if ( !aFTable.insert(make_pair(
    2290           0 :                              CLOffset + SetIndexTable( NF_TEXT, ZF_STANDARD_TEXT ),
    2291           0 :                              pNewFormat)).second)
    2292             :     {
    2293             :         SAL_WARN( "svl.numbers", "SvNumberFormatter::ImpGenerateFormats: dup position Text");
    2294           0 :         delete pNewFormat;
    2295             :     }
    2296             : 
    2297             : 
    2298             : 
    2299             :     // 0
    2300           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_INT );
    2301           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2302           0 :                      CLOffset + SetIndexTable( NF_NUMBER_INT, ZF_STANDARD+1 ));
    2303             : 
    2304             :     // 0.00
    2305           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_DEC2 );
    2306           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2307           0 :                      CLOffset + SetIndexTable( NF_NUMBER_DEC2, ZF_STANDARD+2 ));
    2308             : 
    2309             :     // #,##0
    2310           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_1000INT );
    2311           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2312           0 :                      CLOffset + SetIndexTable( NF_NUMBER_1000INT, ZF_STANDARD+3 ));
    2313             : 
    2314             :     // #,##0.00
    2315           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_1000DEC2 );
    2316           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2317           0 :                      CLOffset + SetIndexTable( NF_NUMBER_1000DEC2, ZF_STANDARD+4 ));
    2318             : 
    2319             :     // #.##0,00 System country/language dependent   since number formatter version 6
    2320           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_NUMBER_SYSTEM );
    2321           0 :     ImpInsertNewStandardFormat( aFormatSeq[nIdx],
    2322           0 :                                 CLOffset + SetIndexTable( NF_NUMBER_SYSTEM, ZF_STANDARD+5 ),
    2323           0 :                                 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD );
    2324             : 
    2325             : 
    2326             :     // Percent number
    2327           0 :     aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::PERCENT_NUMBER );
    2328           0 :     ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() );
    2329             : 
    2330             :     // 0%
    2331           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_PERCENT_INT );
    2332           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2333           0 :                      CLOffset + SetIndexTable( NF_PERCENT_INT, ZF_STANDARD_PERCENT ));
    2334             : 
    2335             :     // 0.00%
    2336           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_PERCENT_DEC2 );
    2337           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2338           0 :                      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           0 :     aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::CURRENCY );
    2345           0 :     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           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000INT );
    2353           0 :     bDefault = aFormatSeq[nIdx].Default;
    2354           0 :     aFormatSeq[nIdx].Default = false;
    2355           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2356           0 :                      CLOffset + SetIndexTable( NF_CURRENCY_1000INT, ZF_STANDARD_CURRENCY ));
    2357           0 :     aFormatSeq[nIdx].Default = bDefault;
    2358             : 
    2359             :     // #,##0.00
    2360           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000DEC2 );
    2361           0 :     bDefault = aFormatSeq[nIdx].Default;
    2362           0 :     aFormatSeq[nIdx].Default = false;
    2363           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2364           0 :                      CLOffset + SetIndexTable( NF_CURRENCY_1000DEC2, ZF_STANDARD_CURRENCY+1 ));
    2365           0 :     aFormatSeq[nIdx].Default = bDefault;
    2366             : 
    2367             :     // #,##0 negative red
    2368           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000INT_RED );
    2369           0 :     bDefault = aFormatSeq[nIdx].Default;
    2370           0 :     aFormatSeq[nIdx].Default = false;
    2371           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2372           0 :                      CLOffset + SetIndexTable( NF_CURRENCY_1000INT_RED, ZF_STANDARD_CURRENCY+2 ));
    2373           0 :     aFormatSeq[nIdx].Default = bDefault;
    2374             : 
    2375             :     // #,##0.00 negative red
    2376           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000DEC2_RED );
    2377           0 :     bDefault = aFormatSeq[nIdx].Default;
    2378           0 :     aFormatSeq[nIdx].Default = false;
    2379           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2380           0 :                      CLOffset + SetIndexTable( NF_CURRENCY_1000DEC2_RED, ZF_STANDARD_CURRENCY+3 ));
    2381           0 :     aFormatSeq[nIdx].Default = bDefault;
    2382             : 
    2383             :     // #,##0.00 USD   since number formatter version 3
    2384           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000DEC2_CCC );
    2385           0 :     bDefault = aFormatSeq[nIdx].Default;
    2386           0 :     aFormatSeq[nIdx].Default = false;
    2387           0 :     pNewFormat = ImpInsertFormat( aFormatSeq[nIdx],
    2388           0 :                                   CLOffset + SetIndexTable( NF_CURRENCY_1000DEC2_CCC, ZF_STANDARD_CURRENCY+4 ));
    2389           0 :     if ( pNewFormat )
    2390           0 :         pNewFormat->SetUsed(true);      // must be saved for older versions
    2391           0 :     aFormatSeq[nIdx].Default = bDefault;
    2392             : 
    2393             :     // #.##0,--   since number formatter version 6
    2394           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_CURRENCY_1000DEC2_DASHED );
    2395           0 :     bDefault = aFormatSeq[nIdx].Default;
    2396           0 :     aFormatSeq[nIdx].Default = false;
    2397           0 :     ImpInsertNewStandardFormat( aFormatSeq[nIdx],
    2398           0 :                                 CLOffset + SetIndexTable( NF_CURRENCY_1000DEC2_DASHED, ZF_STANDARD_CURRENCY+5 ),
    2399           0 :                                 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD );
    2400           0 :     aFormatSeq[nIdx].Default = bDefault;
    2401             : 
    2402             : 
    2403             : 
    2404             :     // Date
    2405           0 :     aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::DATE );
    2406           0 :     ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() );
    2407             : 
    2408             :     // DD.MM.YY   System
    2409           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYSTEM_SHORT );
    2410           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2411           0 :                      CLOffset + SetIndexTable( NF_DATE_SYSTEM_SHORT, ZF_STANDARD_DATE ));
    2412             : 
    2413             :     // NN DD.MMM YY
    2414           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DEF_NNDDMMMYY );
    2415           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2416           0 :                      CLOffset + SetIndexTable( NF_DATE_DEF_NNDDMMMYY, ZF_STANDARD_DATE+1 ));
    2417             : 
    2418             :     // DD.MM.YY   def/System
    2419           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_MMYY );
    2420           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2421           0 :                      CLOffset + SetIndexTable( NF_DATE_SYS_MMYY, ZF_STANDARD_DATE+2 ));
    2422             : 
    2423             :     // DD MMM
    2424           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DDMMM );
    2425           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2426           0 :                      CLOffset + SetIndexTable( NF_DATE_SYS_DDMMM, ZF_STANDARD_DATE+3 ));
    2427             : 
    2428             :     // MMMM
    2429           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_MMMM );
    2430           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2431           0 :                      CLOffset + SetIndexTable( NF_DATE_MMMM, ZF_STANDARD_DATE+4 ));
    2432             : 
    2433             :     // QQ YY
    2434           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_QQJJ );
    2435           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2436           0 :                      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           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DDMMYYYY );
    2440           0 :     pNewFormat = ImpInsertFormat( aFormatSeq[nIdx],
    2441           0 :                                   CLOffset + SetIndexTable( NF_DATE_SYS_DDMMYYYY, ZF_STANDARD_DATE+6 ));
    2442           0 :     if ( pNewFormat )
    2443             :     {
    2444           0 :         pNewFormat->SetUsed(true);      // must be saved for older versions
    2445             :     }
    2446             :     // DD.MM.YY   def/System, since number formatter version 6
    2447           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DDMMYY );
    2448           0 :     ImpInsertNewStandardFormat( aFormatSeq[nIdx],
    2449           0 :                                 CLOffset + SetIndexTable( NF_DATE_SYS_DDMMYY, ZF_STANDARD_DATE+7 ),
    2450           0 :                                 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD );
    2451             : 
    2452             :     // NNN, D. MMMM YYYY   System
    2453             :     // Long day of week: "NNNN" instead of "NNN," because of compatibility
    2454           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYSTEM_LONG );
    2455           0 :     ImpInsertNewStandardFormat( aFormatSeq[nIdx],
    2456           0 :                                 CLOffset + SetIndexTable( NF_DATE_SYSTEM_LONG, ZF_STANDARD_DATE+8 ),
    2457           0 :                                 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           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DMMMYY );
    2464           0 :     ImpInsertNewStandardFormat( aFormatSeq[nIdx],
    2465           0 :                                 CLOffset + SetIndexTable( NF_DATE_SYS_DMMMYY, ZF_STANDARD_DATE+9 ),
    2466           0 :                                 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           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DMMMYYYY );
    2474           0 :     ImpInsertNewStandardFormat( aFormatSeq[nIdx],
    2475           0 :                                 CLOffset + SetIndexTable( NF_DATE_SYS_DMMMYYYY, nNewExtended++ ),
    2476           0 :                                 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD );
    2477             : 
    2478             :     // D. MMMM YYYY   def/System
    2479           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_DMMMMYYYY );
    2480           0 :     ImpInsertNewStandardFormat( aFormatSeq[nIdx],
    2481           0 :                                 CLOffset + SetIndexTable( NF_DATE_SYS_DMMMMYYYY, nNewExtended++ ),
    2482           0 :                                 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD );
    2483             : 
    2484             :     // NN, D. MMM YY   def/System
    2485           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_NNDMMMYY );
    2486           0 :     ImpInsertNewStandardFormat( aFormatSeq[nIdx],
    2487           0 :                                 CLOffset + SetIndexTable( NF_DATE_SYS_NNDMMMYY, nNewExtended++ ),
    2488           0 :                                 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD );
    2489             : 
    2490             :     // NN, D. MMMM YYYY   def/System
    2491           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_NNDMMMMYYYY );
    2492           0 :     ImpInsertNewStandardFormat( aFormatSeq[nIdx],
    2493           0 :                                 CLOffset + SetIndexTable( NF_DATE_SYS_NNDMMMMYYYY, nNewExtended++ ),
    2494           0 :                                 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD );
    2495             : 
    2496             :     // NNN, D. MMMM YYYY   def/System
    2497           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_SYS_NNNNDMMMMYYYY );
    2498           0 :     ImpInsertNewStandardFormat( aFormatSeq[nIdx],
    2499           0 :                                 CLOffset + SetIndexTable( NF_DATE_SYS_NNNNDMMMMYYYY, nNewExtended++ ),
    2500           0 :                                 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           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_DMMMYYYY );
    2506           0 :     ImpInsertNewStandardFormat( aFormatSeq[nIdx],
    2507           0 :                                 CLOffset + SetIndexTable( NF_DATE_DIN_DMMMYYYY, nNewExtended++ ),
    2508           0 :                                 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD );
    2509             : 
    2510             :     // D. MMMM YYYY   DIN/EN
    2511           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_DMMMMYYYY );
    2512           0 :     ImpInsertNewStandardFormat( aFormatSeq[nIdx],
    2513           0 :                                 CLOffset + SetIndexTable( NF_DATE_DIN_DMMMMYYYY, nNewExtended++ ),
    2514           0 :                                 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD );
    2515             : 
    2516             :     // MM-DD   DIN/EN
    2517           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_MMDD );
    2518           0 :     ImpInsertNewStandardFormat( aFormatSeq[nIdx],
    2519           0 :                                 CLOffset + SetIndexTable( NF_DATE_DIN_MMDD, nNewExtended++ ),
    2520           0 :                                 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD );
    2521             : 
    2522             :     // YY-MM-DD   DIN/EN
    2523           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_YYMMDD );
    2524           0 :     ImpInsertNewStandardFormat( aFormatSeq[nIdx],
    2525           0 :                                 CLOffset + SetIndexTable( NF_DATE_DIN_YYMMDD, nNewExtended++ ),
    2526           0 :                                 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD );
    2527             : 
    2528             :     // YYYY-MM-DD   DIN/EN
    2529           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATE_DIN_YYYYMMDD );
    2530           0 :     ImpInsertNewStandardFormat( aFormatSeq[nIdx],
    2531           0 :                                 CLOffset + SetIndexTable( NF_DATE_DIN_YYYYMMDD, nNewExtended++ ),
    2532           0 :                                 SV_NUMBERFORMATTER_VERSION_NEWSTANDARD );
    2533             : 
    2534             : 
    2535             : 
    2536             :     // Time
    2537           0 :     aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::TIME );
    2538           0 :     ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() );
    2539             : 
    2540             :     // HH:MM
    2541           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HHMM );
    2542           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2543           0 :                      CLOffset + SetIndexTable( NF_TIME_HHMM, ZF_STANDARD_TIME ));
    2544             : 
    2545             :     // HH:MM:SS
    2546           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HHMMSS );
    2547           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2548           0 :                      CLOffset + SetIndexTable( NF_TIME_HHMMSS, ZF_STANDARD_TIME+1 ));
    2549             : 
    2550             :     // HH:MM AM/PM
    2551           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HHMMAMPM );
    2552           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2553           0 :                      CLOffset + SetIndexTable( NF_TIME_HHMMAMPM, ZF_STANDARD_TIME+2 ));
    2554             : 
    2555             :     // HH:MM:SS AM/PM
    2556           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HHMMSSAMPM );
    2557           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2558           0 :                      CLOffset + SetIndexTable( NF_TIME_HHMMSSAMPM, ZF_STANDARD_TIME+3 ));
    2559             : 
    2560             :     // [HH]:MM:SS
    2561           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HH_MMSS );
    2562           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2563           0 :                      CLOffset + SetIndexTable( NF_TIME_HH_MMSS, ZF_STANDARD_TIME+4 ));
    2564             : 
    2565             :     // MM:SS,00
    2566           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_MMSS00 );
    2567           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2568           0 :                      CLOffset + SetIndexTable( NF_TIME_MMSS00, ZF_STANDARD_TIME+5 ));
    2569             : 
    2570             :     // [HH]:MM:SS,00
    2571           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_TIME_HH_MMSS00 );
    2572           0 :     ImpInsertNewStandardFormat( aFormatSeq[nIdx],
    2573           0 :                                 CLOffset + SetIndexTable( NF_TIME_HH_MMSS00, ZF_STANDARD_TIME+6 ),
    2574           0 :                                 SV_NUMBERFORMATTER_VERSION_NF_TIME_HH_MMSS00 );
    2575             : 
    2576             : 
    2577             : 
    2578             :     // DateTime
    2579           0 :     aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::DATE_TIME );
    2580           0 :     ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() );
    2581             : 
    2582             :     // DD.MM.YY HH:MM   System
    2583           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATETIME_SYSTEM_SHORT_HHMM );
    2584           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2585           0 :                      CLOffset + SetIndexTable( NF_DATETIME_SYSTEM_SHORT_HHMM, ZF_STANDARD_DATETIME ));
    2586             : 
    2587             :     // DD.MM.YYYY HH:MM:SS   System
    2588           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_DATETIME_SYS_DDMMYYYY_HHMMSS );
    2589           0 :     ImpInsertNewStandardFormat( aFormatSeq[nIdx],
    2590           0 :                                 CLOffset + SetIndexTable( NF_DATETIME_SYS_DDMMYYYY_HHMMSS, ZF_STANDARD_DATETIME+1 ),
    2591           0 :                                 SV_NUMBERFORMATTER_VERSION_NF_DATETIME_SYS_DDMMYYYY_HHMMSS );
    2592             : 
    2593             : 
    2594             : 
    2595             :     // Scientific number
    2596           0 :     aFormatSeq = aNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::SCIENTIFIC_NUMBER );
    2597           0 :     ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), aFormatSeq.getLength() );
    2598             : 
    2599             :     // 0.00E+000
    2600           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_SCIENTIFIC_000E000 );
    2601           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2602           0 :                      CLOffset + SetIndexTable( NF_SCIENTIFIC_000E000, ZF_STANDARD_SCIENTIFIC ));
    2603             : 
    2604             :     // 0.00E+00
    2605           0 :     nIdx = ImpGetFormatCodeIndex( aFormatSeq, NF_SCIENTIFIC_000E00 );
    2606           0 :     ImpInsertFormat( aFormatSeq[nIdx],
    2607           0 :                      CLOffset + SetIndexTable( NF_SCIENTIFIC_000E00, ZF_STANDARD_SCIENTIFIC+1 ));
    2608             : 
    2609             : 
    2610             : 
    2611             :     // Fraction number (no default option)
    2612           0 :     i18n::NumberFormatCode aSingleFormatCode;
    2613           0 :     aSingleFormatCode.Usage = i18n::KNumberFormatUsage::FRACTION_NUMBER;
    2614             : 
    2615             :      // # ?/?
    2616           0 :     aSingleFormatCode.Code = "# ?/?";
    2617             :     ImpInsertFormat( aSingleFormatCode,
    2618           0 :                      CLOffset + SetIndexTable( NF_FRACTION_1, ZF_STANDARD_FRACTION ));
    2619             : 
    2620             :     // # ??/??
    2621             :     //! "??/" would be interpreted by the compiler as a trigraph for '\'
    2622           0 :     aSingleFormatCode.Code = "# ?\?/?\?";
    2623             :     ImpInsertFormat( aSingleFormatCode,
    2624           0 :                      CLOffset + SetIndexTable( NF_FRACTION_2, ZF_STANDARD_FRACTION+1 ));
    2625             : 
    2626             :     // # ?/4
    2627           0 :     aSingleFormatCode.Code = "# ?/4";
    2628             :     ImpInsertNewStandardFormat( aSingleFormatCode,
    2629           0 :                                 CLOffset + SetIndexTable( NF_FRACTION_3, ZF_STANDARD_FRACTION+2 ),
    2630           0 :                                 SV_NUMBERFORMATTER_VERSION_FIXED_FRACTION );
    2631             : 
    2632             :     // # ??/100
    2633           0 :     aSingleFormatCode.Code = "# ?\?/100";
    2634             :     ImpInsertNewStandardFormat( aSingleFormatCode,
    2635           0 :                                 CLOffset + SetIndexTable( NF_FRACTION_4, ZF_STANDARD_FRACTION+3 ),
    2636           0 :                                 SV_NUMBERFORMATTER_VERSION_FIXED_FRACTION );
    2637             : 
    2638             : 
    2639             : 
    2640             :     // Week of year   must be appended here because of nNewExtended
    2641           0 :     const NfKeywordTable & rKeyword = pFormatScanner->GetKeywords();
    2642           0 :     aSingleFormatCode.Code = rKeyword[NF_KEY_WW];
    2643             :     ImpInsertNewStandardFormat( aSingleFormatCode,
    2644           0 :                                 CLOffset + SetIndexTable( NF_DATE_WW, nNewExtended++ ),
    2645           0 :                                 SV_NUMBERFORMATTER_VERSION_NF_DATE_WW );
    2646             : 
    2647             :     {
    2648           0 :         osl::MutexGuard aGuard(&theIndexTable.maMtx);
    2649           0 :         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           0 :     if ( !bNoAdditionalFormats )
    2657             :     {
    2658           0 :         ImpGenerateAdditionalFormats( CLOffset, aNumberFormatCode, false );
    2659             :     }
    2660           0 :     if (bOldConvertMode)
    2661             :     {
    2662           0 :         pFormatScanner->SetConvertMode(true);
    2663           0 :     }
    2664           0 : }
    2665             : 
    2666             : 
    2667           0 : void SvNumberFormatter::ImpGenerateAdditionalFormats( sal_uInt32 CLOffset,
    2668             :             NumberFormatCodeWrapper& rNumberFormatCode, bool bAfterChangingSystemCL )
    2669             : {
    2670             :     using namespace ::com::sun::star;
    2671             : 
    2672           0 :     SvNumberformat* pStdFormat = GetFormatEntry( CLOffset + ZF_STANDARD );
    2673           0 :     if ( !pStdFormat )
    2674             :     {
    2675             :         SAL_WARN( "svl.numbers", "ImpGenerateAdditionalFormats: no GENERAL format" );
    2676           0 :         return ;
    2677             :     }
    2678           0 :     sal_uInt32 nPos = CLOffset + pStdFormat->GetLastInsertKey();
    2679           0 :     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           0 :         rNumberFormatCode.getAllFormatCode( i18n::KNumberFormatUsage::CURRENCY );
    2686           0 :     i18n::NumberFormatCode * pFormatArr = aFormatSeq.getArray();
    2687           0 :     sal_Int32 nCodes = aFormatSeq.getLength();
    2688           0 :     ImpAdjustFormatCodeDefault( aFormatSeq.getArray(), nCodes );
    2689           0 :     for ( j = 0; j < nCodes; j++ )
    2690             :     {
    2691           0 :         if ( nPos - CLOffset >= SV_COUNTRY_LANGUAGE_OFFSET )
    2692             :         {
    2693             :             SAL_WARN( "svl.numbers", "ImpGenerateAdditionalFormats: too many formats" );
    2694           0 :             break;  // for
    2695             :         }
    2696           0 :         if ( pFormatArr[j].Index < NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS &&
    2697           0 :                 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           0 :             sal_Int16 nOrgIndex = pFormatArr[j].Index;
    2701           0 :             pFormatArr[j].Index = sal::static_int_cast< sal_Int16 >(
    2702           0 :                 pFormatArr[j].Index + nCodes + NF_INDEX_TABLE_ENTRIES);
    2703             :             //! no default on currency
    2704           0 :             bool bDefault = aFormatSeq[j].Default;
    2705           0 :             aFormatSeq[j].Default = false;
    2706           0 :             if ( ImpInsertNewStandardFormat( pFormatArr[j], nPos+1,
    2707             :                     SV_NUMBERFORMATTER_VERSION_ADDITIONAL_I18N_FORMATS,
    2708           0 :                     bAfterChangingSystemCL, nOrgIndex ) )
    2709           0 :                 nPos++;
    2710           0 :             pFormatArr[j].Index = nOrgIndex;
    2711           0 :             aFormatSeq[j].Default = bDefault;
    2712             :         }
    2713             :     }
    2714             : 
    2715             :     // all additional format codes provided by I18N that are not old standard index
    2716           0 :     aFormatSeq = rNumberFormatCode.getAllFormatCodes();
    2717           0 :     nCodes = aFormatSeq.getLength();
    2718           0 :     if ( nCodes )
    2719             :     {
    2720           0 :         pFormatArr = aFormatSeq.getArray();
    2721             :         // don't check ALL
    2722           0 :         sal_Int32 nDef = ImpAdjustFormatCodeDefault( pFormatArr, nCodes, false);
    2723             :         // don't have any defaults here
    2724           0 :         pFormatArr[nDef].Default = false;
    2725           0 :         for ( j = 0; j < nCodes; j++ )
    2726             :         {
    2727           0 :             if ( nPos - CLOffset >= SV_COUNTRY_LANGUAGE_OFFSET )
    2728             :             {
    2729             :                 SAL_WARN( "svl.numbers", "ImpGenerateAdditionalFormats: too many formats" );
    2730           0 :                 break;  // for
    2731             :             }
    2732           0 :             if ( pFormatArr[j].Index >= NF_INDEX_TABLE_LOCALE_DATA_DEFAULTS )
    2733           0 :                 if ( ImpInsertNewStandardFormat( pFormatArr[j], nPos+1,
    2734             :                         SV_NUMBERFORMATTER_VERSION_ADDITIONAL_I18N_FORMATS,
    2735           0 :                         bAfterChangingSystemCL ) )
    2736           0 :                     nPos++;
    2737             :         }
    2738             :     }
    2739             : 
    2740           0 :     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           0 : 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           0 :     if (eLnge == LANGUAGE_DONTKNOW)
    2764             :     {
    2765           0 :         eLnge = IniLnge;
    2766             :     }
    2767           0 :     short eType = GetType(nIndex);
    2768             :     sal_uInt16 i;
    2769           0 :     ImpGenerateCL(eLnge);           // create new standard formats if necessary
    2770             : 
    2771           0 :     utl::DigitGroupingIterator aGrouping( xLocaleData->getDigitGrouping());
    2772           0 :     const sal_Int32 nDigitsInFirstGroup = aGrouping.get();
    2773           0 :     const OUString& rThSep = GetNumThousandSep();
    2774             : 
    2775           0 :     SvNumberformat* pFormat = GetFormatEntry( nIndex );
    2776             : 
    2777           0 :     OUStringBuffer sString;
    2778             :     using comphelper::string::padToLength;
    2779             : 
    2780           0 :     if (nAnzLeading == 0)
    2781             :     {
    2782           0 :         if (!bThousand)
    2783           0 :             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           0 :         for (i = 0; i < nAnzLeading; i++)
    2794             :         {
    2795           0 :             if (bThousand && i > 0 && i == aGrouping.getPos())
    2796             :             {
    2797           0 :                 sString.insert(0, rThSep);
    2798           0 :                 aGrouping.advance();
    2799             :             }
    2800           0 :             sString.insert(0, '0');
    2801             :         }
    2802           0 :         if (bThousand && nAnzLeading < nDigitsInFirstGroup + 1)
    2803             :         {
    2804           0 :             for (i = nAnzLeading; i < nDigitsInFirstGroup + 1; i++)
    2805             :             {
    2806           0 :                 if (bThousand && i % nDigitsInFirstGroup == 0)
    2807           0 :                     sString.insert(0, rThSep);
    2808           0 :                 sString.insert(0, '#');
    2809             :             }
    2810             :         }
    2811             :     }
    2812           0 :     if (nPrecision > 0)
    2813             :     {
    2814           0 :         sString.append(GetNumDecimalSep());
    2815           0 :         padToLength(sString, sString.getLength() + nPrecision, '0');
    2816             :     }
    2817           0 :     if (eType == NUMBERFORMAT_PERCENT)
    2818             :     {
    2819           0 :         sString.append('%');
    2820             :     }
    2821           0 :     else if (eType == NUMBERFORMAT_CURRENCY)
    2822             :     {
    2823           0 :         OUStringBuffer sNegStr(sString);
    2824           0 :         OUString aCurr;
    2825             :         const NfCurrencyEntry* pEntry;
    2826             :         bool bBank;
    2827           0 :         if ( GetNewCurrencySymbolString( nIndex, aCurr, &pEntry, &bBank ) )
    2828             :         {
    2829           0 :             if ( pEntry )
    2830             :             {
    2831             :                 sal_uInt16 nPosiForm = NfCurrencyEntry::GetEffectivePositiveFormat(
    2832           0 :                     xLocaleData->getCurrPositiveFormat(),
    2833           0 :                     pEntry->GetPositiveFormat(), bBank );
    2834             :                 sal_uInt16 nNegaForm = NfCurrencyEntry::GetEffectiveNegativeFormat(
    2835           0 :                     xLocaleData->getCurrNegativeFormat(),
    2836           0 :                     pEntry->GetNegativeFormat(), bBank );
    2837           0 :                 pEntry->CompletePositiveFormatString( sString, bBank, nPosiForm );
    2838           0 :                 pEntry->CompleteNegativeFormatString( sNegStr, bBank, nNegaForm );
    2839             :             }
    2840             :             else
    2841             :             {   // assume currency abbreviation (AKA banking symbol), not symbol
    2842             :                 sal_uInt16 nPosiForm = NfCurrencyEntry::GetEffectivePositiveFormat(
    2843           0 :                     xLocaleData->getCurrPositiveFormat(),
    2844           0 :                     xLocaleData->getCurrPositiveFormat(), true );
    2845             :                 sal_uInt16 nNegaForm = NfCurrencyEntry::GetEffectiveNegativeFormat(
    2846           0 :                     xLocaleData->getCurrNegativeFormat(),
    2847           0 :                     xLocaleData->getCurrNegativeFormat(), true );
    2848           0 :                 NfCurrencyEntry::CompletePositiveFormatString( sString, aCurr, nPosiForm );
    2849           0 :                 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           0 :         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           0 :             sString.append(';');
    2869             :         }
    2870           0 :         sString.append(sNegStr.makeStringAndClear());
    2871             :     }
    2872           0 :     if (eType != NUMBERFORMAT_CURRENCY)
    2873             :     {
    2874           0 :         bool insertBrackets = false;
    2875           0 :         if ( eType != NUMBERFORMAT_UNDEFINED)
    2876             :         {
    2877           0 :             insertBrackets = pFormat->IsNegativeInBracket();
    2878             :         }
    2879           0 :         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           0 :     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           0 : sal_uInt32 SvNumberFormatter::GetEntryKey(const OUString& sStr,
    2938             :                                           LanguageType eLnge)
    2939             : {
    2940           0 :     if (eLnge == LANGUAGE_DONTKNOW)
    2941             :     {
    2942           0 :         eLnge = IniLnge;
    2943             :     }
    2944           0 :     sal_uInt32 CLOffset = ImpGenerateCL(eLnge);     // create new standard formats if necessary
    2945           0 :     return ImpIsEntry(sStr, CLOffset, eLnge);
    2946             : }
    2947             : 
    2948           0 : sal_uInt32 SvNumberFormatter::GetStandardIndex(LanguageType eLnge)
    2949             : {
    2950           0 :     if (eLnge == LANGUAGE_DONTKNOW)
    2951             :     {
    2952           0 :         eLnge = IniLnge;
    2953             :     }
    2954           0 :     return GetStandardFormat(NUMBERFORMAT_NUMBER, eLnge);
    2955             : }
    2956             : 
    2957           0 : short SvNumberFormatter::GetType(sal_uInt32 nFIndex)
    2958             : {
    2959             :     short eType;
    2960           0 :     SvNumberformat* pFormat = GetFormatEntry( nFIndex );
    2961           0 :     if (!pFormat)
    2962             :     {
    2963           0 :         eType = NUMBERFORMAT_UNDEFINED;
    2964             :     }
    2965             :     else
    2966             :     {
    2967           0 :         eType = pFormat->GetType() &~NUMBERFORMAT_DEFINED;
    2968           0 :         if (eType == 0)
    2969             :         {
    2970           0 :             eType = NUMBERFORMAT_DEFINED;
    2971             :         }
    2972             :     }
    2973           0 :     return eType;
    2974             : }
    2975             : 
    2976           0 : void SvNumberFormatter::ClearMergeTable()
    2977             : {
    2978           0 :     if ( pMergeTable )
    2979             :     {
    2980           0 :         pMergeTable->clear();
    2981             :     }
    2982           0 : }
    2983             : 
    2984           0 : SvNumberFormatterIndexTable* SvNumberFormatter::MergeFormatter(SvNumberFormatter& rTable)
    2985             : {
    2986           0 :     if ( pMergeTable )
    2987             :     {
    2988           0 :         ClearMergeTable();
    2989             :     }
    2990             :     else
    2991             :     {
    2992           0 :         pMergeTable = new SvNumberFormatterIndexTable;
    2993             :     }
    2994             : 
    2995           0 :     sal_uInt32 nCLOffset = 0;
    2996             :     sal_uInt32 nOldKey, nOffset, nNewKey;
    2997             :     SvNumberformat* pNewEntry;
    2998             : 
    2999           0 :     SvNumberFormatTable::iterator it = rTable.aFTable.begin();
    3000           0 :     while (it != rTable.aFTable.end())
    3001             :     {
    3002           0 :         SvNumberformat* pFormat = it->second;
    3003           0 :         nOldKey = it->first;
    3004           0 :         nOffset = nOldKey % SV_COUNTRY_LANGUAGE_OFFSET;     // relative index
    3005           0 :         if (nOffset == 0)                                   // 1st format of CL
    3006             :         {
    3007           0 :             nCLOffset = ImpGenerateCL(pFormat->GetLanguage());
    3008             :         }
    3009           0 :         if (nOffset <= SV_MAX_ANZ_STANDARD_FORMATE)     // Std.form.
    3010             :         {
    3011           0 :             nNewKey = nCLOffset + nOffset;
    3012           0 :             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           0 :             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           0 :             pNewEntry = new SvNumberformat( *pFormat, *pFormatScanner );
    3031           0 :             nNewKey = ImpIsEntry(pNewEntry->GetFormatstring(),
    3032             :                                  nCLOffset,
    3033           0 :                                  pFormat->GetLanguage());
    3034           0 :             if (nNewKey != NUMBERFORMAT_ENTRY_NOT_FOUND) // already present
    3035             :             {
    3036           0 :                 delete pNewEntry;
    3037             :             }
    3038             :             else
    3039             :             {
    3040           0 :                 SvNumberformat* pStdFormat = GetFormatEntry(nCLOffset + ZF_STANDARD);
    3041           0 :                 sal_uInt32 nPos = nCLOffset + pStdFormat->GetLastInsertKey();
    3042           0 :                 nNewKey = nPos+1;
    3043           0 :                 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           0 :                 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           0 :                     pStdFormat->SetLastInsertKey((sal_uInt16) (nNewKey - nCLOffset));
    3056             :                 }
    3057             :             }
    3058           0 :             if (nNewKey != nOldKey)                     // new index
    3059             :             {
    3060           0 :                 (*pMergeTable)[nOldKey] = nNewKey;
    3061             :             }
    3062             :         }
    3063           0 :         ++it;
    3064             :     }
    3065           0 :     return pMergeTable;
    3066             : }
    3067             : 
    3068             : 
    3069           0 : SvNumberFormatterMergeMap SvNumberFormatter::ConvertMergeTableToMap()
    3070             : {
    3071           0 :     if (!HasMergeFmtTbl())
    3072             :     {
    3073           0 :         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           0 : sal_uInt32 SvNumberFormatter::GetFormatForLanguageIfBuiltIn( sal_uInt32 nFormat,
    3087             :                                                              LanguageType eLnge )
    3088             : {
    3089           0 :     if ( eLnge == LANGUAGE_DONTKNOW )
    3090             :     {
    3091           0 :         eLnge = IniLnge;
    3092             :     }
    3093           0 :     if ( nFormat < SV_COUNTRY_LANGUAGE_OFFSET && eLnge == IniLnge )
    3094             :     {
    3095           0 :         return nFormat;     // it stays as it is
    3096             :     }
    3097           0 :     sal_uInt32 nOffset = nFormat % SV_COUNTRY_LANGUAGE_OFFSET;  // relative index
    3098           0 :     if ( nOffset > SV_MAX_ANZ_STANDARD_FORMATE )
    3099             :     {
    3100           0 :         return nFormat;    // not a built-in format
    3101             :     }
    3102           0 :     sal_uInt32 nCLOffset = ImpGenerateCL(eLnge);    // create new standard formats if necessary
    3103           0 :     return nCLOffset + nOffset;
    3104             : }
    3105             : 
    3106             : 
    3107           0 : sal_uInt32 SvNumberFormatter::GetFormatIndex( NfIndexTableOffset nTabOff,
    3108             :                                               LanguageType eLnge )
    3109             : {
    3110           0 :     if (nTabOff >= NF_INDEX_TABLE_ENTRIES)
    3111           0 :         return NUMBERFORMAT_ENTRY_NOT_FOUND;
    3112             : 
    3113           0 :     if (eLnge == LANGUAGE_DONTKNOW)
    3114           0 :         eLnge = IniLnge;
    3115             : 
    3116             :     {
    3117           0 :         osl::MutexGuard aGuard(&theIndexTable.maMtx);
    3118           0 :         if (theIndexTable.maData[nTabOff] == NUMBERFORMAT_ENTRY_NOT_FOUND)
    3119           0 :             return NUMBERFORMAT_ENTRY_NOT_FOUND;
    3120             :     }
    3121             : 
    3122           0 :     sal_uInt32 nCLOffset = ImpGenerateCL(eLnge);    // create new standard formats if necessary
    3123             : 
    3124             :     {
    3125           0 :         osl::MutexGuard aGuard(&theIndexTable.maMtx);
    3126           0 :         return nCLOffset + theIndexTable.maData[nTabOff];
    3127             :     }
    3128             : }
    3129             : 
    3130             : 
    3131           0 : NfIndexTableOffset SvNumberFormatter::GetIndexTableOffset( sal_uInt32 nFormat ) const
    3132             : {
    3133           0 :     sal_uInt32 nOffset = nFormat % SV_COUNTRY_LANGUAGE_OFFSET;      // relative index
    3134           0 :     if ( nOffset > SV_MAX_ANZ_STANDARD_FORMATE )
    3135             :     {
    3136           0 :         return NF_INDEX_TABLE_ENTRIES;      // not a built-in format
    3137             :     }
    3138             : 
    3139             :     {
    3140           0 :         osl::MutexGuard aGuard(&theIndexTable.maMtx);
    3141           0 :         for ( sal_uInt16 j = 0; j < NF_INDEX_TABLE_ENTRIES; j++ )
    3142             :         {
    3143           0 :             if (theIndexTable.maData[j] == nOffset)
    3144           0 :                 return (NfIndexTableOffset) j;
    3145           0 :         }
    3146             :     }
    3147           0 :     return NF_INDEX_TABLE_ENTRIES;      // bad luck
    3148             : }
    3149             : 
    3150             : 
    3151           0 : void SvNumberFormatter::SetYear2000( sal_uInt16 nVal )
    3152             : {
    3153           0 :     pStringScanner->SetYear2000( nVal );
    3154           0 : }
    3155             : 
    3156             : 
    3157           0 : sal_uInt16 SvNumberFormatter::GetYear2000() const
    3158             : {
    3159           0 :     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           0 : sal_uInt16 SvNumberFormatter::GetYear2000Default()
    3174             : {
    3175           0 :     return (sal_uInt16) ::utl::MiscCfg().GetYear2000();
    3176             : }
    3177             : 
    3178             : 
    3179             : // static
    3180           0 : const NfCurrencyTable& SvNumberFormatter::GetTheCurrencyTable()
    3181             : {
    3182           0 :     ::osl::MutexGuard aGuard( GetMutex() );
    3183           0 :     while ( !bCurrencyTableInitialized )
    3184           0 :         ImpInitCurrencyTable();
    3185           0 :     return theCurrencyTable::get();
    3186             : }
    3187             : 
    3188             : 
    3189             : // static
    3190           0 : const NfCurrencyEntry* SvNumberFormatter::MatchSystemCurrency()
    3191             : {
    3192             :     // MUST call GetTheCurrencyTable() before accessing nSystemCurrencyPosition
    3193           0 :     const NfCurrencyTable& rTable = GetTheCurrencyTable();
    3194           0 :     return nSystemCurrencyPosition ? &rTable[nSystemCurrencyPosition] : NULL;
    3195             : }
    3196             : 
    3197             : 
    3198             : // static
    3199           0 : const NfCurrencyEntry& SvNumberFormatter::GetCurrencyEntry( LanguageType eLang )
    3200             : {
    3201           0 :     if ( eLang == LANGUAGE_SYSTEM )
    3202             :     {
    3203           0 :         const NfCurrencyEntry* pCurr = MatchSystemCurrency();
    3204           0 :         return pCurr ? *pCurr : GetTheCurrencyTable()[0];
    3205             :     }
    3206             :     else
    3207             :     {
    3208           0 :         eLang = MsLangId::getRealLanguage( eLang );
    3209           0 :         const NfCurrencyTable& rTable = GetTheCurrencyTable();
    3210           0 :         sal_uInt16 nCount = rTable.size();
    3211           0 :         for ( sal_uInt16 j = 0; j < nCount; j++ )
    3212             :         {
    3213           0 :             if ( rTable[j].GetLanguage() == eLang )
    3214           0 :                 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           0 : sal_uInt32 SvNumberFormatter::ImpGetDefaultSystemCurrencyFormat()
    3322             : {
    3323           0 :     if ( nDefaultSystemCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
    3324             :     {
    3325             :         sal_Int32 nCheck;
    3326             :         short nType;
    3327           0 :         NfWSStringsDtor aCurrList;
    3328             :         sal_uInt16 nDefault = GetCurrencyFormatStrings( aCurrList,
    3329           0 :             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           0 :         PutEntry( aCurrList[ nDefault ], nCheck, nType,
    3334           0 :             nDefaultSystemCurrencyFormat, LANGUAGE_SYSTEM );
    3335             :         DBG_ASSERT( nCheck == 0, "NewCurrency CheckError" );
    3336             :         DBG_ASSERT( nDefaultSystemCurrencyFormat != NUMBERFORMAT_ENTRY_NOT_FOUND,
    3337           0 :             "nDefaultSystemCurrencyFormat == NUMBERFORMAT_ENTRY_NOT_FOUND" );
    3338             :     }
    3339           0 :     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           0 :     bool SvNumberFormatter::ImpLookupCurrencyEntryLoopBody( const NfCurrencyEntry*& pFoundEntry, bool& bFoundBank,
    3407             :                                                             const NfCurrencyEntry* pData, sal_uInt16 nPos,
    3408             :                                                             const OUString& rSymbol )
    3409             : {
    3410             :     bool bFound;
    3411           0 :     if ( pData->GetSymbol() == rSymbol )
    3412             :     {
    3413           0 :         bFound = true;
    3414           0 :         bFoundBank = false;
    3415             :     }
    3416           0 :     else if ( pData->GetBankSymbol() == rSymbol )
    3417             :     {
    3418           0 :         bFound = true;
    3419           0 :         bFoundBank = true;
    3420             :     }
    3421             :     else
    3422           0 :         bFound = false;
    3423           0 :     if ( bFound )
    3424             :     {
    3425           0 :         if ( pFoundEntry && pFoundEntry != pData )
    3426             :         {
    3427           0 :             pFoundEntry = NULL;
    3428           0 :             return false;   // break loop, not unique
    3429             :         }
    3430           0 :         if ( nPos == 0 )
    3431             :         {   // first entry is SYSTEM
    3432           0 :             pFoundEntry = MatchSystemCurrency();
    3433           0 :             if ( pFoundEntry )
    3434             :             {
    3435           0 :                 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           0 :             pFoundEntry = pData;
    3447             :         }
    3448             :     }
    3449           0 :     return true;
    3450             : }
    3451             : 
    3452             : 
    3453           0 : bool SvNumberFormatter::GetNewCurrencySymbolString( sal_uInt32 nFormat, OUString& rStr,
    3454             :                                                     const NfCurrencyEntry** ppEntry /* = NULL */,
    3455             :                                                     bool* pBank /* = NULL */ ) const
    3456             : {
    3457           0 :     if ( ppEntry )
    3458           0 :         *ppEntry = NULL;
    3459           0 :     if ( pBank )
    3460           0 :         *pBank = false;
    3461             : 
    3462           0 :     const SvNumberformat* pFormat = GetFormatEntry(nFormat);
    3463           0 :     if ( pFormat )
    3464             :     {
    3465           0 :         OUStringBuffer sBuff(128); // guess-estimate of a value that will pretty much garantee no re-alloc
    3466           0 :         OUString aSymbol, aExtension;
    3467           0 :         if ( pFormat->GetNewCurrencySymbol( aSymbol, aExtension ) )
    3468             :         {
    3469           0 :             if ( ppEntry )
    3470             :             {
    3471           0 :                 bool bFoundBank = false;
    3472             :                 // we definiteley need an entry matching the format code string
    3473             :                 const NfCurrencyEntry* pFoundEntry = GetCurrencyEntry(
    3474           0 :                     bFoundBank, aSymbol, aExtension, pFormat->GetLanguage(),
    3475           0 :                     true );
    3476           0 :                 if ( pFoundEntry )
    3477             :                 {
    3478           0 :                     *ppEntry = pFoundEntry;
    3479           0 :                     if ( pBank )
    3480           0 :                         *pBank = bFoundBank;
    3481           0 :                     rStr = pFoundEntry->BuildSymbolString(bFoundBank);
    3482             :                 }
    3483             :             }
    3484           0 :             if ( rStr.isEmpty() )
    3485             :             {   // analog to BuildSymbolString
    3486           0 :                 sBuff.append("[$");
    3487           0 :                 if ( aSymbol.indexOf( '-' ) != -1 ||
    3488           0 :                         aSymbol.indexOf( ']' ) != -1 )
    3489             :                 {
    3490           0 :                     sBuff.append('"');
    3491           0 :                     sBuff.append( aSymbol);
    3492           0 :                     sBuff.append('"');
    3493             :                 }
    3494             :                 else
    3495             :                 {
    3496           0 :                     sBuff.append(aSymbol);
    3497             :                 }
    3498           0 :                 if ( !aExtension.isEmpty() )
    3499             :                 {
    3500           0 :                     sBuff.append(aExtension);
    3501             :                 }
    3502           0 :                 sBuff.append(']');
    3503             :             }
    3504           0 :             rStr = sBuff.toString();
    3505           0 :             return true;
    3506           0 :         }
    3507             :     }
    3508           0 :     rStr = "";
    3509           0 :     return false;
    3510             : }
    3511             : 
    3512             : 
    3513             : // static
    3514           0 : const NfCurrencyEntry* SvNumberFormatter::GetCurrencyEntry( bool & bFoundBank,
    3515             :                                                             const OUString& rSymbol,
    3516             :                                                             const OUString& rExtension,
    3517             :                                                             LanguageType eFormatLanguage,
    3518             :                                                             bool bOnlyStringLanguage )
    3519             : {
    3520           0 :     sal_Int32 nExtLen = rExtension.getLength();
    3521             :     LanguageType eExtLang;
    3522           0 :     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           0 :         sal_Int32 nExtLang = rExtension.toInt32( 16 );
    3528           0 :         if ( !nExtLang )
    3529             :         {
    3530           0 :             eExtLang = LANGUAGE_DONTKNOW;
    3531             :         }
    3532             :         else
    3533             :         {
    3534           0 :             eExtLang = (LanguageType) ((nExtLang < 0) ? -nExtLang : nExtLang);
    3535             :         }
    3536             :     }
    3537             :     else
    3538             :     {
    3539           0 :         eExtLang = LANGUAGE_DONTKNOW;
    3540             :     }
    3541           0 :     const NfCurrencyEntry* pFoundEntry = NULL;
    3542           0 :     const NfCurrencyTable& rTable = GetTheCurrencyTable();
    3543           0 :     sal_uInt16 nCount = rTable.size();
    3544           0 :     bool bCont = true;
    3545             : 
    3546             :     // first try with given extension language/country
    3547           0 :     if ( nExtLen )
    3548             :     {
    3549           0 :         for ( sal_uInt16 j = 0; j < nCount && bCont; j++ )
    3550             :         {
    3551           0 :             LanguageType eLang = rTable[j].GetLanguage();
    3552           0 :             if ( eLang == eExtLang ||
    3553           0 :                  ((eExtLang == LANGUAGE_DONTKNOW) &&
    3554             :                   (eLang == LANGUAGE_SYSTEM)))
    3555             :             {
    3556             :                 bCont = ImpLookupCurrencyEntryLoopBody( pFoundEntry, bFoundBank,
    3557           0 :                                                         &rTable[j], j, rSymbol );
    3558             :             }
    3559             :         }
    3560             :     }
    3561             : 
    3562             :     // ok?
    3563           0 :     if ( pFoundEntry || !bCont || (bOnlyStringLanguage && nExtLen) )
    3564             :     {
    3565           0 :         return pFoundEntry;
    3566             :     }
    3567           0 :     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           0 :     if ( !nExtLen )
    3591             :     {
    3592           0 :         for ( sal_uInt16 j = 0; j < nCount && bCont; j++ )
    3593             :         {
    3594             :             bCont = ImpLookupCurrencyEntryLoopBody( pFoundEntry, bFoundBank,
    3595           0 :                                                     &rTable[j], j, rSymbol );
    3596             :         }
    3597             :     }
    3598             : 
    3599           0 :     return pFoundEntry;
    3600             : }
    3601             : 
    3602             : 
    3603           0 : void SvNumberFormatter::GetCompatibilityCurrency( OUString& rSymbol, OUString& rAbbrev ) const
    3604             : {
    3605             :     ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Currency2 >
    3606           0 :         xCurrencies( xLocaleData->getAllCurrencies() );
    3607             : 
    3608           0 :     const ::com::sun::star::i18n::Currency2 *pCurrencies = xCurrencies.getConstArray();
    3609           0 :     sal_Int32 nCurrencies = xCurrencies.getLength();
    3610             : 
    3611             :     sal_Int32 j;
    3612           0 :     for ( j=0; j < nCurrencies; ++j )
    3613             :     {
    3614           0 :         if ( pCurrencies[j].UsedInCompatibleFormatCodes )
    3615             :         {
    3616           0 :             rSymbol = pCurrencies[j].Symbol;
    3617           0 :             rAbbrev = pCurrencies[j].BankSymbol;
    3618           0 :             break;
    3619             :         }
    3620             :     }
    3621           0 :     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           0 :     }
    3631           0 : }
    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           0 : 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           0 :     GetTheCurrencyTable();
    3679           0 :     const NfInstalledLocales &rInstalledLocales = theInstalledLocales::get();
    3680           0 :     return rInstalledLocales.find( eLang) != rInstalledLocales.end();
    3681             : }
    3682             : 
    3683             : // static
    3684           0 : void SvNumberFormatter::ImpInitCurrencyTable()
    3685             : {
    3686             :     // racing condition possible:
    3687             :     // ::osl::MutexGuard aGuard( GetMutex() );
    3688             :     // while ( !bCurrencyTableInitialized )
    3689             :     //      ImpInitCurrencyTable();
    3690             :     static bool bInitializing = false;
    3691           0 :     if ( bCurrencyTableInitialized || bInitializing )
    3692             :     {
    3693           0 :         return ;
    3694             :     }
    3695           0 :     bInitializing = true;
    3696             : 
    3697           0 :     LanguageType eSysLang = SvtSysLocale().GetLanguageTag().getLanguageType();
    3698             :     LocaleDataWrapper* pLocaleData = new LocaleDataWrapper(
    3699             :         ::comphelper::getProcessComponentContext(),
    3700           0 :         SvtSysLocale().GetLanguageTag() );
    3701             :     // get user configured currency
    3702           0 :     OUString aConfiguredCurrencyAbbrev;
    3703           0 :     LanguageType eConfiguredCurrencyLanguage = LANGUAGE_SYSTEM;
    3704             :     SvtSysLocaleOptions().GetCurrencyAbbrevAndLanguage(
    3705           0 :         aConfiguredCurrencyAbbrev, eConfiguredCurrencyLanguage );
    3706           0 :     sal_uInt16 nSecondarySystemCurrencyPosition = 0;
    3707           0 :     sal_uInt16 nMatchingSystemCurrencyPosition = 0;
    3708             :     NfCurrencyEntry* pEntry;
    3709             : 
    3710             :     // first entry is SYSTEM
    3711           0 :     pEntry = new NfCurrencyEntry( *pLocaleData, LANGUAGE_SYSTEM );
    3712           0 :     theCurrencyTable::get().insert( theCurrencyTable::get().begin(), pEntry );
    3713           0 :     sal_uInt16 nCurrencyPos = 1;
    3714             : 
    3715             :     ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > xLoc =
    3716           0 :         LocaleDataWrapper::getInstalledLocaleNames();
    3717           0 :     sal_Int32 nLocaleCount = xLoc.getLength();
    3718             :     SAL_INFO( "svl.numbers", "number of locales: \"" << nLocaleCount << "\"" );
    3719           0 :     Locale const * const pLocales = xLoc.getConstArray();
    3720           0 :     NfCurrencyTable &rCurrencyTable = theCurrencyTable::get();
    3721           0 :     NfCurrencyTable &rLegacyOnlyCurrencyTable = theLegacyOnlyCurrencyTable::get();
    3722           0 :     NfInstalledLocales &rInstalledLocales = theInstalledLocales::get();
    3723           0 :     sal_uInt16 nLegacyOnlyCurrencyPos = 0;
    3724           0 :     for ( sal_Int32 nLocale = 0; nLocale < nLocaleCount; nLocale++ )
    3725             :     {
    3726           0 :         LanguageType eLang = LanguageTag::convertToLanguageType( pLocales[nLocale], false);
    3727           0 :         rInstalledLocales.insert( eLang);
    3728           0 :         pLocaleData->setLanguageTag( LanguageTag( pLocales[nLocale]) );
    3729           0 :         Sequence< Currency2 > aCurrSeq = pLocaleData->getAllCurrencies();
    3730           0 :         sal_Int32 nCurrencyCount = aCurrSeq.getLength();
    3731           0 :         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           0 :         for ( nDefault = 0; nDefault < nCurrencyCount; nDefault++ )
    3736             :         {
    3737           0 :             if ( pCurrencies[nDefault].Default )
    3738           0 :                 break;
    3739             :         }
    3740           0 :         if ( nDefault < nCurrencyCount )
    3741             :         {
    3742           0 :             pEntry = new NfCurrencyEntry( pCurrencies[nDefault], *pLocaleData, eLang );
    3743             :         }
    3744             :         else
    3745             :         {
    3746           0 :             pEntry = new NfCurrencyEntry( *pLocaleData, eLang );    // first or ShellsAndPebbles
    3747             :         }
    3748           0 :         if (LocaleDataWrapper::areChecksEnabled())
    3749             :         {
    3750           0 :             lcl_CheckCurrencySymbolPosition( *pEntry );
    3751             :         }
    3752           0 :         rCurrencyTable.insert( rCurrencyTable.begin() + nCurrencyPos++, pEntry );
    3753           0 :         if ( !nSystemCurrencyPosition && (!aConfiguredCurrencyAbbrev.isEmpty() ?
    3754           0 :                                           pEntry->GetBankSymbol() == aConfiguredCurrencyAbbrev &&
    3755           0 :                                           pEntry->GetLanguage() == eConfiguredCurrencyLanguage : false) )
    3756             :         {
    3757           0 :             nSystemCurrencyPosition = nCurrencyPos-1;
    3758             :         }
    3759           0 :         if ( !nMatchingSystemCurrencyPosition &&
    3760           0 :              pEntry->GetLanguage() == eSysLang )
    3761             :         {
    3762           0 :             nMatchingSystemCurrencyPosition = nCurrencyPos-1;
    3763             :         }
    3764             :         // all remaining currencies for each locale
    3765           0 :         if ( nCurrencyCount > 1 )
    3766             :         {
    3767             :             sal_Int32 nCurrency;
    3768           0 :             for ( nCurrency = 0; nCurrency < nCurrencyCount; nCurrency++ )
    3769             :             {
    3770           0 :                 if (pCurrencies[nCurrency].LegacyOnly)
    3771             :                 {
    3772           0 :                     pEntry = new NfCurrencyEntry( pCurrencies[nCurrency], *pLocaleData, eLang );
    3773           0 :                     rLegacyOnlyCurrencyTable.insert( rLegacyOnlyCurrencyTable.begin() + nLegacyOnlyCurrencyPos++, pEntry );
    3774             :                 }
    3775           0 :                 else if ( nCurrency != nDefault )
    3776             :                 {
    3777           0 :                     pEntry = new NfCurrencyEntry( pCurrencies[nCurrency], *pLocaleData, eLang );
    3778             :                     // no dupes
    3779           0 :                     bool bInsert = true;
    3780           0 :                     sal_uInt16 n = rCurrencyTable.size();
    3781           0 :                     sal_uInt16 aCurrencyIndex = 1; // skip first SYSTEM entry
    3782           0 :                     for ( sal_uInt16 j=1; j<n; j++ )
    3783             :                     {
    3784           0 :                         if ( rCurrencyTable[aCurrencyIndex++] == *pEntry )
    3785             :                         {
    3786           0 :                             bInsert = false;
    3787           0 :                             break;  // for
    3788             :                         }
    3789             :                     }
    3790           0 :                     if ( !bInsert )
    3791             :                     {
    3792           0 :                         delete pEntry;
    3793             :                     }
    3794             :                     else
    3795             :                     {
    3796           0 :                         rCurrencyTable.insert( rCurrencyTable.begin() + nCurrencyPos++, pEntry );
    3797           0 :                         if ( !nSecondarySystemCurrencyPosition &&
    3798           0 :                              (!aConfiguredCurrencyAbbrev.isEmpty() ?
    3799           0 :                               pEntry->GetBankSymbol() == aConfiguredCurrencyAbbrev :
    3800           0 :                               pEntry->GetLanguage() == eConfiguredCurrencyLanguage) )
    3801             :                         {
    3802           0 :                             nSecondarySystemCurrencyPosition = nCurrencyPos-1;
    3803             :                         }
    3804           0 :                         if ( !nMatchingSystemCurrencyPosition &&
    3805           0 :                              pEntry->GetLanguage() ==  eSysLang )
    3806             :                         {
    3807           0 :                             nMatchingSystemCurrencyPosition = nCurrencyPos-1;
    3808             :                         }
    3809             :                     }
    3810             :                 }
    3811             :             }
    3812             :         }
    3813           0 :     }
    3814           0 :     if ( !nSystemCurrencyPosition )
    3815             :     {
    3816           0 :         nSystemCurrencyPosition = nSecondarySystemCurrencyPosition;
    3817             :     }
    3818           0 :     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           0 :     if ( !nSystemCurrencyPosition )
    3826             :     {
    3827           0 :         nSystemCurrencyPosition = nMatchingSystemCurrencyPosition;
    3828             :     }
    3829           0 :     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           0 :     delete pLocaleData;
    3836           0 :     SvtSysLocaleOptions::SetCurrencyChangeLink( STATIC_LINK( NULL, SvNumberFormatter, CurrencyChangeLink ) );
    3837           0 :     bInitializing = false;
    3838           0 :     bCurrencyTableInitialized = true;
    3839             : }
    3840             : 
    3841             : 
    3842           0 : sal_uInt16 SvNumberFormatter::GetCurrencyFormatStrings( NfWSStringsDtor& rStrArr,
    3843             :                                                         const NfCurrencyEntry& rCurr,
    3844             :                                                         bool bBank ) const
    3845             : {
    3846             :     OUString aRed = OUStringBuffer().
    3847           0 :         append('[').
    3848           0 :         append(pFormatScanner->GetRedString()).
    3849           0 :         append(']').makeStringAndClear();
    3850             : 
    3851           0 :     sal_uInt16 nDefault = 0;
    3852           0 :     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           0 :         OUString aPositive = rCurr.BuildPositiveFormatString(false, *xLocaleData, 1);
    3878           0 :         OUString aNegative = rCurr.BuildNegativeFormatString(false, *xLocaleData, 1 );
    3879           0 :         OUStringBuffer format1;
    3880           0 :         OUStringBuffer format2;
    3881           0 :         OUStringBuffer format3;
    3882           0 :         OUStringBuffer format4;
    3883           0 :         OUStringBuffer format5;
    3884           0 :         if (rCurr.GetDigits())
    3885             :         {
    3886           0 :             OUString aPositiveNoDec = rCurr.BuildPositiveFormatString(false, *xLocaleData, 0);
    3887           0 :             OUString aNegativeNoDec = rCurr.BuildNegativeFormatString(false, *xLocaleData, 0 );
    3888           0 :             OUString aPositiveDashed = rCurr.BuildPositiveFormatString(false, *xLocaleData, 2);
    3889           0 :             OUString aNegativeDashed = rCurr.BuildNegativeFormatString(false, *xLocaleData, 2);
    3890             : 
    3891           0 :             format1.append(aPositiveNoDec);
    3892           0 :             format1.append(';');
    3893           0 :             format1.append(aNegativeNoDec);
    3894             : 
    3895           0 :             format3.append(aPositiveNoDec);
    3896           0 :             format3.append(';');
    3897           0 :             format3.append(aRed);
    3898           0 :             format3.append(aNegativeNoDec);
    3899             : 
    3900           0 :             format5.append(aPositiveDashed);
    3901           0 :             format5.append(';');
    3902           0 :             format5.append(aRed);
    3903           0 :             format5.append(aNegativeDashed);
    3904             :         }
    3905             : 
    3906           0 :         format2.append(aPositive);
    3907           0 :         format2.append(';');
    3908           0 :         format2.append(aNegative);
    3909             : 
    3910           0 :         format4.append(aPositive);
    3911           0 :         format4.append(';');
    3912           0 :         format4.append(aRed);
    3913           0 :         format4.append(aNegative);
    3914             : 
    3915           0 :         if (rCurr.GetDigits())
    3916             :         {
    3917           0 :             rStrArr.push_back(format1.makeStringAndClear());
    3918             :         }
    3919           0 :         rStrArr.push_back(format2.makeStringAndClear());
    3920           0 :         if (rCurr.GetDigits())
    3921             :         {
    3922           0 :             rStrArr.push_back(format3.makeStringAndClear());
    3923             :         }
    3924           0 :         rStrArr.push_back(format4.makeStringAndClear());
    3925           0 :         nDefault = rStrArr.size() - 1;
    3926           0 :         if (rCurr.GetDigits())
    3927             :         {
    3928           0 :             rStrArr.push_back(format5.makeStringAndClear());
    3929           0 :         }
    3930             :     }
    3931           0 :     return nDefault;
    3932             : }
    3933             : 
    3934             : 
    3935             : //--- NfCurrencyEntry ----------------------------------------------------
    3936             : 
    3937             : 
    3938           0 : NfCurrencyEntry::NfCurrencyEntry( const LocaleDataWrapper& rLocaleData, LanguageType eLang )
    3939             : {
    3940           0 :     aSymbol         = rLocaleData.getCurrSymbol();
    3941           0 :     aBankSymbol     = rLocaleData.getCurrBankSymbol();
    3942           0 :     eLanguage       = eLang;
    3943           0 :     nPositiveFormat = rLocaleData.getCurrPositiveFormat();
    3944           0 :     nNegativeFormat = rLocaleData.getCurrNegativeFormat();
    3945           0 :     nDigits         = rLocaleData.getCurrDigits();
    3946           0 :     cZeroChar       = rLocaleData.getCurrZeroChar();
    3947           0 : }
    3948             : 
    3949             : 
    3950           0 : NfCurrencyEntry::NfCurrencyEntry( const ::com::sun::star::i18n::Currency & rCurr,
    3951           0 :                                   const LocaleDataWrapper& rLocaleData, LanguageType eLang )
    3952             : {
    3953           0 :     aSymbol         = rCurr.Symbol;
    3954           0 :     aBankSymbol     = rCurr.BankSymbol;
    3955           0 :     eLanguage       = eLang;
    3956           0 :     nPositiveFormat = rLocaleData.getCurrPositiveFormat();
    3957           0 :     nNegativeFormat = rLocaleData.getCurrNegativeFormat();
    3958           0 :     nDigits         = rCurr.DecimalPlaces;
    3959           0 :     cZeroChar       = rLocaleData.getCurrZeroChar();
    3960           0 : }
    3961             : 
    3962             : 
    3963           0 : bool NfCurrencyEntry::operator==( const NfCurrencyEntry& r ) const
    3964             : {
    3965           0 :     return aSymbol      == r.aSymbol
    3966           0 :         && aBankSymbol  == r.aBankSymbol
    3967           0 :         && eLanguage    == r.eLanguage
    3968             :         ;
    3969             : }
    3970             : 
    3971           0 : OUString NfCurrencyEntry::BuildSymbolString(bool bBank,
    3972             :                                             bool bWithoutExtension) const
    3973             : {
    3974           0 :     OUStringBuffer aBuf("[$");
    3975           0 :     if (bBank)
    3976             :     {
    3977           0 :         aBuf.append(aBankSymbol);
    3978             :     }
    3979             :     else
    3980             :     {
    3981           0 :         if ( aSymbol.indexOf( (sal_Unicode)'-' ) >= 0 ||
    3982           0 :              aSymbol.indexOf( (sal_Unicode)']' ) >= 0)
    3983             :         {
    3984           0 :             aBuf.append('"').append(aSymbol).append('"');
    3985             :         }
    3986             :         else
    3987             :         {
    3988           0 :             aBuf.append(aSymbol);
    3989             :         }
    3990           0 :         if ( !bWithoutExtension && eLanguage != LANGUAGE_DONTKNOW && eLanguage != LANGUAGE_SYSTEM )
    3991             :         {
    3992           0 :             sal_Int32 nLang = static_cast<sal_Int32>(eLanguage);
    3993           0 :             aBuf.append('-').append( OUString::number(nLang, 16).toAsciiUpperCase());
    3994             :         }
    3995             :     }
    3996           0 :     aBuf.append(']');
    3997           0 :     return aBuf.makeStringAndClear();
    3998             : }
    3999             : 
    4000           0 : OUString NfCurrencyEntry::Impl_BuildFormatStringNumChars( const LocaleDataWrapper& rLoc,
    4001             :                                                           sal_uInt16 nDecimalFormat) const
    4002             : {
    4003           0 :     OUStringBuffer aBuf;
    4004           0 :     aBuf.append('#').append(rLoc.getNumThousandSep()).append("##0");
    4005           0 :     if (nDecimalFormat && nDigits)
    4006             :     {
    4007           0 :         aBuf.append(rLoc.getNumDecimalSep());
    4008           0 :         sal_Unicode cDecimalChar = nDecimalFormat == 2 ? '-' : cZeroChar;
    4009           0 :         for (sal_uInt16 i = 0; i < nDigits; ++i)
    4010             :         {
    4011           0 :             aBuf.append(cDecimalChar);
    4012             :         }
    4013             :     }
    4014           0 :     return aBuf.makeStringAndClear();
    4015             : }
    4016             : 
    4017             : 
    4018           0 : OUString NfCurrencyEntry::BuildPositiveFormatString(bool bBank, const LocaleDataWrapper& rLoc,
    4019             :                                                     sal_uInt16 nDecimalFormat) const
    4020             : {
    4021           0 :     OUStringBuffer sBuf(Impl_BuildFormatStringNumChars(rLoc, nDecimalFormat));
    4022           0 :     sal_uInt16 nPosiForm = NfCurrencyEntry::GetEffectivePositiveFormat( rLoc.getCurrPositiveFormat(),
    4023           0 :                                                                         nPositiveFormat, bBank );
    4024           0 :     CompletePositiveFormatString(sBuf, bBank, nPosiForm);
    4025           0 :     return sBuf.makeStringAndClear();
    4026             : }
    4027             : 
    4028             : 
    4029           0 : OUString NfCurrencyEntry::BuildNegativeFormatString(bool bBank,
    4030             :             const LocaleDataWrapper& rLoc, sal_uInt16 nDecimalFormat ) const
    4031             : {
    4032           0 :     OUStringBuffer sBuf(Impl_BuildFormatStringNumChars(rLoc, nDecimalFormat));
    4033           0 :     sal_uInt16 nNegaForm = NfCurrencyEntry::GetEffectiveNegativeFormat( rLoc.getCurrNegativeFormat(),
    4034           0 :                                                                         nNegativeFormat, bBank );
    4035           0 :     CompleteNegativeFormatString(sBuf, bBank, nNegaForm);
    4036           0 :     return sBuf.makeStringAndClear();
    4037             : }
    4038             : 
    4039             : 
    4040           0 : void NfCurrencyEntry::CompletePositiveFormatString(OUStringBuffer& rStr, bool bBank,
    4041             :                                                    sal_uInt16 nPosiForm) const
    4042             : {
    4043           0 :     OUString aSymStr = BuildSymbolString(bBank);
    4044           0 :     NfCurrencyEntry::CompletePositiveFormatString( rStr, aSymStr, nPosiForm );
    4045           0 : }
    4046             : 
    4047             : 
    4048           0 : void NfCurrencyEntry::CompleteNegativeFormatString(OUStringBuffer& rStr, bool bBank,
    4049             :                                                    sal_uInt16 nNegaForm) const
    4050             : {
    4051           0 :     OUString aSymStr = BuildSymbolString(bBank);
    4052           0 :     NfCurrencyEntry::CompleteNegativeFormatString( rStr, aSymStr, nNegaForm );
    4053           0 : }
    4054             : 
    4055             : 
    4056             : // static
    4057           0 : void NfCurrencyEntry::CompletePositiveFormatString(OUStringBuffer& rStr, const OUString& rSymStr,
    4058             :                                                    sal_uInt16 nPositiveFormat)
    4059             : {
    4060           0 :     switch( nPositiveFormat )
    4061             :     {
    4062             :         case 0:                                         // $1
    4063           0 :             rStr.insert(0, rSymStr);
    4064           0 :         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           0 :             rStr.append(' ');
    4077           0 :             rStr.append(rSymStr);
    4078             :         }
    4079           0 :         break;
    4080             :         default:
    4081             :             SAL_WARN( "svl.numbers", "NfCurrencyEntry::CompletePositiveFormatString: unknown option");
    4082           0 :         break;
    4083             :     }
    4084           0 : }
    4085             : 
    4086             : 
    4087             : // static
    4088           0 : void NfCurrencyEntry::CompleteNegativeFormatString(OUStringBuffer& rStr,
    4089             :                                                    const OUString& rSymStr,
    4090             :                                                    sal_uInt16 nNegativeFormat)
    4091             : {
    4092           0 :     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           0 :             rStr.insert(0, rSymStr);
    4104           0 :             rStr.insert(0, '-');
    4105             :         }
    4106           0 :         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           0 :             rStr.append(' ');
    4147           0 :             rStr.append(rSymStr);
    4148           0 :             rStr.insert(0, '-');
    4149             :         }
    4150           0 :         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           0 : }
    4206             : 
    4207             : 
    4208             : // static
    4209           0 : sal_uInt16 NfCurrencyEntry::GetEffectivePositiveFormat( sal_uInt16 nIntlFormat,
    4210             :                                                         sal_uInt16 nCurrFormat, bool bBank )
    4211             : {
    4212           0 :     if ( bBank )
    4213             :     {
    4214             : #if NF_BANKSYMBOL_FIX_POSITION
    4215             :         (void) nIntlFormat; // avoid warnings
    4216           0 :         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           0 :         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           0 : sal_uInt16 NfCurrencyEntry::GetEffectiveNegativeFormat( sal_uInt16 nIntlFormat,
    4329             :             sal_uInt16 nCurrFormat, bool bBank )
    4330             : {
    4331           0 :     if ( bBank )
    4332             :     {
    4333             : #if NF_BANKSYMBOL_FIX_POSITION
    4334           0 :         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           0 :     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           0 :     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           3 : }
    4474             : 
    4475             : 
    4476             : 
    4477             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10