LCOV - code coverage report
Current view: top level - unotools/source/i18n - localedatawrapper.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 523 933 56.1 %
Date: 2012-08-25 Functions: 46 58 79.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 455 1318 34.5 %

           Branch data     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                 :            : 
      21                 :            : #include <string.h>      // memcpy()
      22                 :            : #include <stdio.h>       // fprintf(), stderr
      23                 :            : 
      24                 :            : #include <unotools/localedatawrapper.hxx>
      25                 :            : #include <unotools/numberformatcodewrapper.hxx>
      26                 :            : #include <unotools/calendarwrapper.hxx>
      27                 :            : #include <unotools/digitgroupingiterator.hxx>
      28                 :            : #include <tools/string.hxx>
      29                 :            : #include <tools/debug.hxx>
      30                 :            : #include <i18npool/mslangid.hxx>
      31                 :            : 
      32                 :            : #include "instance.hxx"
      33                 :            : #include <com/sun/star/i18n/KNumberFormatUsage.hpp>
      34                 :            : #include <com/sun/star/i18n/KNumberFormatType.hpp>
      35                 :            : #include <com/sun/star/i18n/CalendarFieldIndex.hpp>
      36                 :            : #include <com/sun/star/i18n/CalendarDisplayIndex.hpp>
      37                 :            : 
      38                 :            : #include <com/sun/star/i18n/NumberFormatIndex.hpp>
      39                 :            : #include <rtl/instance.hxx>
      40                 :            : #include <rtl/ustrbuf.hxx>
      41                 :            : #include <sal/macros.h>
      42                 :            : 
      43                 :            : static const int nDateFormatInvalid = -1;
      44                 :            : static const sal_uInt16 nCurrFormatInvalid = 0xffff;
      45                 :            : static const sal_uInt16 nCurrFormatDefault = 0;
      46                 :            : 
      47                 :            : using namespace ::com::sun::star;
      48                 :            : using namespace ::com::sun::star::i18n;
      49                 :            : using namespace ::com::sun::star::uno;
      50                 :            : 
      51                 :            : namespace
      52                 :            : {
      53                 :            :     struct InstalledLocales
      54                 :            :         : public rtl::Static<
      55                 :            :             uno::Sequence< lang::Locale >, InstalledLocales >
      56                 :            :     {};
      57                 :            : 
      58                 :            :     struct InstalledLanguageTypes
      59                 :            :         : public rtl::Static<
      60                 :            :             uno::Sequence< sal_uInt16 >, InstalledLanguageTypes >
      61                 :            :     {};
      62                 :            : }
      63                 :            : 
      64                 :            : sal_uInt8 LocaleDataWrapper::nLocaleDataChecking = 0;
      65                 :            : 
      66                 :      23318 : LocaleDataWrapper::LocaleDataWrapper(
      67                 :            :             const Reference< lang::XMultiServiceFactory > & xSF,
      68                 :            :             const lang::Locale& rLocale
      69                 :            :             )
      70                 :            :         :
      71                 :            :         xSMgr( xSF ),
      72                 :            :         bLocaleDataItemValid( sal_False ),
      73 [ +  - ][ +  - ]:     699540 :         bReservedWordValid( sal_False )
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
      74                 :            : {
      75         [ +  - ]:      23318 :     setLocale( rLocale );
      76                 :            :     xLD = Reference< XLocaleData4 > (
      77                 :            :         intl_createInstance( xSMgr, "com.sun.star.i18n.LocaleData",
      78 [ +  - ][ +  - ]:      23318 :                              "LocaleDataWrapper" ), uno::UNO_QUERY );
                 [ +  - ]
      79   [ #  #  #  #  :      23318 : }
             #  #  #  # ]
      80                 :            : 
      81                 :            : 
      82 [ +  - ][ +  - ]:     719355 : LocaleDataWrapper::~LocaleDataWrapper()
         [ +  - ][ +  - ]
      83                 :            : {
      84 [ +  + ][ +  - ]:     719355 : }
           [ +  +  #  #  
          #  #  #  #  #  
              # ][ +  - ]
      85                 :            : 
      86                 :            : 
      87                 :      30778 : void LocaleDataWrapper::setLocale( const ::com::sun::star::lang::Locale& rLocale )
      88                 :            : {
      89         [ +  - ]:      30778 :     ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nCriticalChange );
      90                 :      30778 :     aLocale = rLocale;
      91 [ +  - ][ +  - ]:      30778 :     invalidateData();
      92                 :      30778 : }
      93                 :            : 
      94                 :            : 
      95                 :     129105 : const ::com::sun::star::lang::Locale& LocaleDataWrapper::getLocale() const
      96                 :            : {
      97         [ +  - ]:     129105 :     ::utl::ReadWriteGuard aGuard( aMutex );
      98         [ +  - ]:     129105 :     return aLocale;
      99                 :            : }
     100                 :            : 
     101                 :            : 
     102                 :      30778 : void LocaleDataWrapper::invalidateData()
     103                 :            : {
     104                 :      30778 :     aCurrSymbol = rtl::OUString();
     105                 :      30778 :     aCurrBankSymbol = rtl::OUString();
     106                 :      30778 :     nDateFormat = nLongDateFormat = nDateFormatInvalid;
     107                 :      30778 :     nCurrPositiveFormat = nCurrNegativeFormat = nCurrDigits = nCurrFormatInvalid;
     108         [ +  + ]:      30778 :     if ( bLocaleDataItemValid )
     109                 :            :     {
     110         [ +  + ]:       6624 :         for (sal_Int32 j=0; j<LocaleItem::COUNT; ++j)
     111                 :       6256 :             aLocaleItem[j] = rtl::OUString();
     112                 :        368 :         bLocaleDataItemValid = sal_False;
     113                 :            :     }
     114         [ +  + ]:      30778 :     if ( bReservedWordValid )
     115                 :            :     {
     116         [ +  + ]:         78 :         for ( sal_Int16 j=0; j<reservedWords::COUNT; ++j )
     117                 :         72 :             aReservedWord[j] = rtl::OUString();
     118                 :          6 :         bReservedWordValid = sal_False;
     119                 :            :     }
     120                 :      30778 :     xDefaultCalendar.reset();
     121         [ +  + ]:      30778 :     if (aGrouping.getLength())
     122                 :          6 :         aGrouping[0] = 0;
     123                 :            :     // dummies
     124                 :      30778 :     cCurrZeroChar = '0';
     125                 :      30778 : }
     126                 :            : 
     127                 :            : 
     128                 :      75149 : ::com::sun::star::i18n::LanguageCountryInfo LocaleDataWrapper::getLanguageCountryInfo() const
     129                 :            : {
     130                 :            :     try
     131                 :            :     {
     132         [ +  - ]:      75149 :         if ( xLD.is() )
     133 [ +  - ][ +  - ]:      75149 :             return xLD->getLanguageCountryInfo( getLocale() );
                 [ +  - ]
     134                 :            :     }
     135                 :          0 :     catch (const Exception& e)
     136                 :            :     {
     137                 :            :         SAL_WARN( "unotools.i18n", "getLanguageCountryInfo: Exception caught " << e.Message );
     138                 :            :     }
     139         [ #  # ]:      75149 :     return ::com::sun::star::i18n::LanguageCountryInfo();
     140                 :            : }
     141                 :            : 
     142                 :            : 
     143                 :       3738 : ::com::sun::star::i18n::LocaleDataItem LocaleDataWrapper::getLocaleItem() const
     144                 :            : {
     145                 :            :     try
     146                 :            :     {
     147         [ +  - ]:       3738 :         if ( xLD.is() )
     148 [ +  - ][ +  - ]:       3738 :             return xLD->getLocaleItem( getLocale() );
                 [ +  - ]
     149                 :            :     }
     150                 :          0 :     catch (const Exception& e)
     151                 :            :     {
     152                 :            :         SAL_WARN( "unotools.i18n", "getLocaleItem: Exception caught " << e.Message );
     153                 :            :     }
     154         [ #  # ]:       3738 :     return ::com::sun::star::i18n::LocaleDataItem();
     155                 :            : }
     156                 :            : 
     157                 :            : 
     158                 :      21618 : ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Currency2 > LocaleDataWrapper::getAllCurrencies() const
     159                 :            : {
     160                 :            :     try
     161                 :            :     {
     162         [ +  - ]:      21618 :         if ( xLD.is() )
     163 [ +  - ][ +  - ]:      21618 :             return xLD->getAllCurrencies2( getLocale() );
                 [ +  - ]
     164                 :            :     }
     165                 :          0 :     catch (const Exception& e)
     166                 :            :     {
     167                 :            :         SAL_WARN( "unotools.i18n", "getAllCurrencies: Exception caught " << e.Message );
     168                 :            :     }
     169         [ #  # ]:      21618 :     return ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Currency2 >(0);
     170                 :            : }
     171                 :            : 
     172                 :            : 
     173                 :          0 : ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::FormatElement > LocaleDataWrapper::getAllFormats() const
     174                 :            : {
     175                 :            :     try
     176                 :            :     {
     177         [ #  # ]:          0 :         if ( xLD.is() )
     178 [ #  # ][ #  # ]:          0 :             return xLD->getAllFormats( getLocale() );
                 [ #  # ]
     179                 :            :     }
     180                 :          0 :     catch (const Exception& e)
     181                 :            :     {
     182                 :            :         SAL_WARN( "unotools.i18n", "getAllFormats: Exception caught " << e.Message );
     183                 :            :     }
     184         [ #  # ]:          0 :     return ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::FormatElement >(0);
     185                 :            : }
     186                 :            : 
     187                 :            : 
     188                 :      16729 : ::com::sun::star::i18n::ForbiddenCharacters LocaleDataWrapper::getForbiddenCharacters() const
     189                 :            : {
     190                 :            :     try
     191                 :            :     {
     192         [ +  - ]:      16729 :         if ( xLD.is() )
     193 [ +  - ][ +  - ]:      16729 :             return xLD->getForbiddenCharacters( getLocale() );
                 [ +  - ]
     194                 :            :     }
     195                 :          0 :     catch (const Exception& e)
     196                 :            :     {
     197                 :            :         SAL_WARN( "unotools.i18n", "getForbiddenCharacters: Exception caught " << e.Message );
     198                 :            :     }
     199         [ #  # ]:      16729 :     return ::com::sun::star::i18n::ForbiddenCharacters();
     200                 :            : }
     201                 :            : 
     202                 :            : 
     203                 :        684 : ::com::sun::star::uno::Sequence< ::rtl::OUString > LocaleDataWrapper::getReservedWord() const
     204                 :            : {
     205                 :            :     try
     206                 :            :     {
     207         [ +  - ]:        684 :         if ( xLD.is() )
     208 [ +  - ][ +  - ]:        684 :             return xLD->getReservedWord( getLocale() );
                 [ +  - ]
     209                 :            :     }
     210                 :          0 :     catch ( const Exception& e )
     211                 :            :     {
     212                 :            :         SAL_WARN( "unotools.i18n", "getReservedWord: Exception caught " << e.Message );
     213                 :            :     }
     214         [ #  # ]:        684 :     return ::com::sun::star::uno::Sequence< ::rtl::OUString >(0);
     215                 :            : }
     216                 :            : 
     217                 :            : 
     218                 :         36 : ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > LocaleDataWrapper::getAllInstalledLocaleNames() const
     219                 :            : {
     220                 :         36 :     uno::Sequence< lang::Locale > &rInstalledLocales = InstalledLocales::get();
     221                 :            : 
     222         [ -  + ]:         36 :     if ( rInstalledLocales.getLength() )
     223                 :          0 :         return rInstalledLocales;
     224                 :            : 
     225                 :            :     try
     226                 :            :     {
     227         [ +  - ]:         36 :         if ( xLD.is() )
     228 [ +  - ][ +  - ]:         36 :             rInstalledLocales = xLD->getAllInstalledLocaleNames();
         [ +  - ][ +  - ]
                 [ #  # ]
     229                 :            :     }
     230                 :          0 :     catch ( const Exception& e )
     231                 :            :     {
     232                 :            :         SAL_WARN( "unotools.i18n", "getAllInstalledLocaleNames: Exception caught " << e.Message );
     233                 :            :     }
     234                 :         36 :     return rInstalledLocales;
     235                 :            : }
     236                 :            : 
     237                 :            : 
     238                 :            : // --- Impl and helpers ----------------------------------------------------
     239                 :            : 
     240                 :            : // static
     241                 :         36 : ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > LocaleDataWrapper::getInstalledLocaleNames()
     242                 :            : {
     243                 :            :     const uno::Sequence< lang::Locale > &rInstalledLocales =
     244                 :         36 :         InstalledLocales::get();
     245                 :            : 
     246         [ +  - ]:         36 :     if ( !rInstalledLocales.getLength() )
     247                 :            :     {
     248 [ +  - ][ +  - ]:         36 :         LocaleDataWrapper aLDW( ::comphelper::getProcessServiceFactory(), lang::Locale() );
     249 [ +  - ][ +  - ]:         36 :         aLDW.getAllInstalledLocaleNames();
                 [ +  - ]
     250                 :            :     }
     251                 :         36 :     return rInstalledLocales;
     252                 :            : }
     253                 :            : 
     254                 :            : // static
     255                 :          0 : ::com::sun::star::uno::Sequence< sal_uInt16 > LocaleDataWrapper::getInstalledLanguageTypes()
     256                 :            : {
     257                 :            :     uno::Sequence< sal_uInt16 > &rInstalledLanguageTypes =
     258         [ #  # ]:          0 :         InstalledLanguageTypes::get();
     259                 :            : 
     260         [ #  # ]:          0 :     if ( rInstalledLanguageTypes.getLength() )
     261         [ #  # ]:          0 :         return rInstalledLanguageTypes;
     262                 :            : 
     263                 :            :     ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > xLoc =
     264         [ #  # ]:          0 :         getInstalledLocaleNames();
     265                 :          0 :     sal_Int32 nCount = xLoc.getLength();
     266         [ #  # ]:          0 :     ::com::sun::star::uno::Sequence< sal_uInt16 > xLang( nCount );
     267                 :          0 :     sal_Int32 nLanguages = 0;
     268         [ #  # ]:          0 :     for ( sal_Int32 i=0; i<nCount; i++ )
     269                 :            :     {
     270         [ #  # ]:          0 :         String aDebugLocale;
     271 [ #  # ][ #  # ]:          0 :         if (areChecksEnabled())
     272                 :            :         {
     273 [ #  # ][ #  # ]:          0 :             aDebugLocale = xLoc[i].Language;
     274 [ #  # ][ #  # ]:          0 :             if ( !xLoc[i].Country.isEmpty() )
     275                 :            :             {
     276         [ #  # ]:          0 :                 aDebugLocale += '_';
     277 [ #  # ][ #  # ]:          0 :                 aDebugLocale += String( xLoc[i].Country);
         [ #  # ][ #  # ]
     278 [ #  # ][ #  # ]:          0 :                 if ( !xLoc[i].Variant.isEmpty() )
     279                 :            :                 {
     280         [ #  # ]:          0 :                     aDebugLocale += '_';
     281 [ #  # ][ #  # ]:          0 :                     aDebugLocale += String( xLoc[i].Variant);
         [ #  # ][ #  # ]
     282                 :            :                 }
     283                 :            :             }
     284                 :            :         }
     285                 :            : 
     286 [ #  # ][ #  # ]:          0 :         if ( !xLoc[i].Variant.isEmpty() )
     287                 :            :         {
     288 [ #  # ][ #  # ]:          0 :             if (areChecksEnabled())
     289                 :            :             {
     290                 :          0 :                 rtl::OUStringBuffer aMsg("LocaleDataWrapper::getInstalledLanguageTypes: Variants not supported, locale\n");
     291 [ #  # ][ #  # ]:          0 :                 aMsg.append(aDebugLocale);
     292 [ #  # ][ #  # ]:          0 :                 outputCheckMessage(aMsg.makeStringAndClear());
     293                 :            :             }
     294                 :          0 :             continue;
     295                 :            :         }
     296 [ #  # ][ #  # ]:          0 :         LanguageType eLang = MsLangId::convertLocaleToLanguage( xLoc[i] );
     297                 :            : 
     298                 :            :         // In checks, exclude known problems because no MS-LCID defined.
     299 [ #  # ][ #  # ]:          0 :         if (areChecksEnabled() && eLang == LANGUAGE_DONTKNOW)
         [ #  # ][ #  # ]
     300                 :            :         {
     301                 :          0 :             rtl::OUStringBuffer aMsg("ConvertIsoNamesToLanguage: unknown MS-LCID for locale\n");
     302 [ #  # ][ #  # ]:          0 :             aMsg.append(aDebugLocale);
     303 [ #  # ][ #  # ]:          0 :             outputCheckMessage(aMsg.makeStringAndClear());
     304                 :            :         }
     305                 :            : 
     306         [ #  # ]:          0 :         switch ( eLang )
     307                 :            :         {
     308                 :            :             case LANGUAGE_NORWEGIAN :       // no_NO, not Bokmal (nb_NO), not Nynorsk (nn_NO)
     309                 :          0 :                 eLang = LANGUAGE_DONTKNOW;  // don't offer "Unknown" language
     310                 :          0 :                 break;
     311                 :            :         }
     312         [ #  # ]:          0 :         if ( eLang != LANGUAGE_DONTKNOW )
     313                 :            :         {
     314                 :          0 :             rtl::OUString aLanguage, aCountry;
     315         [ #  # ]:          0 :             MsLangId::convertLanguageToIsoNames( eLang, aLanguage, aCountry );
     316         [ #  # ]:          0 :             if ( xLoc[i].Language != aLanguage ||
           [ #  #  #  # ]
                 [ #  # ]
     317         [ #  # ]:          0 :                     xLoc[i].Country != aCountry )
     318                 :            :             {
     319                 :            :                 // In checks, exclude known problems because no MS-LCID defined
     320                 :            :                 // and default for Language found.
     321 [ #  # ][ #  # ]:          0 :                 if ( areChecksEnabled()
         [ #  # ][ #  # ]
                 [ #  # ]
     322         [ #  # ]:          0 :                         && !aDebugLocale.EqualsAscii( "ar_SD" ) // Sudan/ar
     323         [ #  # ]:          0 :                         && !aDebugLocale.EqualsAscii( "en_CB" ) // Carribean is not a country
     324                 :            : //                      && !aDebugLocale.EqualsAscii( "en_BG" ) // ?!? Bulgaria/en
     325                 :            : //                      && !aDebugLocale.EqualsAscii( "es_BR" ) // ?!? Brazil/es
     326                 :            :                     )
     327                 :            :                 {
     328                 :          0 :                     rtl::OUStringBuffer aMsg;
     329                 :            :                     aMsg.appendAscii(RTL_CONSTASCII_STRINGPARAM(
     330         [ #  # ]:          0 :                                 "ConvertIsoNamesToLanguage/ConvertLanguageToIsoNames: ambiguous locale (MS-LCID?)\n"));
     331 [ #  # ][ #  # ]:          0 :                     aMsg.append(aDebugLocale);
     332         [ #  # ]:          0 :                     aMsg.appendAscii(RTL_CONSTASCII_STRINGPARAM( "  ->  0x"));
     333         [ #  # ]:          0 :                     aMsg.append(static_cast<sal_Int32>(eLang), 16);
     334         [ #  # ]:          0 :                     aMsg.appendAscii(RTL_CONSTASCII_STRINGPARAM( "  ->  "));
     335         [ #  # ]:          0 :                     aMsg.append(aLanguage);
     336         [ #  # ]:          0 :                     if ( !aCountry.isEmpty() )
     337                 :            :                     {
     338         [ #  # ]:          0 :                         aMsg.append('_');
     339         [ #  # ]:          0 :                         aMsg.append(aCountry);
     340                 :            :                     }
     341 [ #  # ][ #  # ]:          0 :                     outputCheckMessage( aMsg.makeStringAndClear() );
     342                 :            :                 }
     343                 :          0 :                 eLang = LANGUAGE_DONTKNOW;
     344                 :          0 :             }
     345                 :            :         }
     346         [ #  # ]:          0 :         if ( eLang != LANGUAGE_DONTKNOW )
     347         [ #  # ]:          0 :             xLang[ nLanguages++ ] = eLang;
     348 [ #  # ][ #  # ]:          0 :     }
     349         [ #  # ]:          0 :     if ( nLanguages < nCount )
     350         [ #  # ]:          0 :         xLang.realloc( nLanguages );
     351         [ #  # ]:          0 :     rInstalledLanguageTypes = xLang;
     352                 :            : 
     353 [ #  # ][ #  # ]:          0 :     return rInstalledLanguageTypes;
                 [ #  # ]
     354                 :            : }
     355                 :            : 
     356                 :    2003439 : const rtl::OUString& LocaleDataWrapper::getOneLocaleItem( sal_Int16 nItem ) const
     357                 :            : {
     358         [ +  - ]:    2003439 :     ::utl::ReadWriteGuard aGuard( aMutex );
     359         [ -  + ]:    2003439 :     if ( nItem >= LocaleItem::COUNT )
     360                 :            :     {
     361                 :            :         SAL_WARN( "unotools", "getOneLocaleItem: bounds" );
     362                 :          0 :         return aLocaleItem[0];
     363                 :            :     }
     364         [ +  + ]:    2003439 :     if (aLocaleItem[nItem].isEmpty())
     365                 :            :     {   // no cached content
     366         [ +  - ]:       7158 :         aGuard.changeReadToWrite();
     367         [ +  - ]:       7158 :         ((LocaleDataWrapper*)this)->getOneLocaleItemImpl( nItem );
     368                 :            :     }
     369         [ +  - ]:    2003439 :     return aLocaleItem[nItem];
     370                 :            : }
     371                 :            : 
     372                 :            : 
     373                 :       7158 : void LocaleDataWrapper::getOneLocaleItemImpl( sal_Int16 nItem )
     374                 :            : {
     375         [ +  + ]:       7158 :     if ( !bLocaleDataItemValid )
     376                 :            :     {
     377                 :       2766 :         aLocaleDataItem = getLocaleItem();
     378                 :       2766 :         bLocaleDataItemValid = sal_True;
     379                 :            :     }
     380   [ +  +  +  +  :       7158 :     switch ( nItem )
          +  +  -  +  -  
          -  +  +  +  +  
             +  +  -  - ]
     381                 :            :     {
     382                 :            :         case LocaleItem::DATE_SEPARATOR :
     383                 :        738 :             aLocaleItem[nItem] = aLocaleDataItem.dateSeparator;
     384                 :        738 :         break;
     385                 :            :         case LocaleItem::THOUSAND_SEPARATOR :
     386                 :       2492 :             aLocaleItem[nItem] = aLocaleDataItem.thousandSeparator;
     387                 :       2492 :         break;
     388                 :            :         case LocaleItem::DECIMAL_SEPARATOR :
     389                 :       2175 :             aLocaleItem[nItem] = aLocaleDataItem.decimalSeparator;
     390                 :       2175 :         break;
     391                 :            :         case LocaleItem::TIME_SEPARATOR :
     392                 :        715 :             aLocaleItem[nItem] = aLocaleDataItem.timeSeparator;
     393                 :        715 :         break;
     394                 :            :         case LocaleItem::TIME_100SEC_SEPARATOR :
     395                 :        685 :             aLocaleItem[nItem] = aLocaleDataItem.time100SecSeparator;
     396                 :        685 :         break;
     397                 :            :         case LocaleItem::LIST_SEPARATOR :
     398                 :         51 :             aLocaleItem[nItem] = aLocaleDataItem.listSeparator;
     399                 :         51 :         break;
     400                 :            :         case LocaleItem::SINGLE_QUOTATION_START :
     401                 :          0 :             aLocaleItem[nItem] = aLocaleDataItem.quotationStart;
     402                 :          0 :         break;
     403                 :            :         case LocaleItem::SINGLE_QUOTATION_END :
     404                 :         40 :             aLocaleItem[nItem] = aLocaleDataItem.quotationEnd;
     405                 :         40 :         break;
     406                 :            :         case LocaleItem::DOUBLE_QUOTATION_START :
     407                 :          0 :             aLocaleItem[nItem] = aLocaleDataItem.doubleQuotationStart;
     408                 :          0 :         break;
     409                 :            :         case LocaleItem::DOUBLE_QUOTATION_END :
     410                 :          0 :             aLocaleItem[nItem] = aLocaleDataItem.doubleQuotationEnd;
     411                 :          0 :         break;
     412                 :            :         case LocaleItem::MEASUREMENT_SYSTEM :
     413                 :        135 :             aLocaleItem[nItem] = aLocaleDataItem.measurementSystem;
     414                 :        135 :         break;
     415                 :            :         case LocaleItem::TIME_AM :
     416                 :         35 :             aLocaleItem[nItem] = aLocaleDataItem.timeAM;
     417                 :         35 :         break;
     418                 :            :         case LocaleItem::TIME_PM :
     419                 :         35 :             aLocaleItem[nItem] = aLocaleDataItem.timePM;
     420                 :         35 :         break;
     421                 :            :         case LocaleItem::LONG_DATE_DAY_OF_WEEK_SEPARATOR :
     422                 :         19 :             aLocaleItem[nItem] = aLocaleDataItem.LongDateDayOfWeekSeparator;
     423                 :         19 :         break;
     424                 :            :         case LocaleItem::LONG_DATE_DAY_SEPARATOR :
     425                 :         19 :             aLocaleItem[nItem] = aLocaleDataItem.LongDateDaySeparator;
     426                 :         19 :         break;
     427                 :            :         case LocaleItem::LONG_DATE_MONTH_SEPARATOR :
     428                 :         19 :             aLocaleItem[nItem] = aLocaleDataItem.LongDateMonthSeparator;
     429                 :         19 :         break;
     430                 :            :         case LocaleItem::LONG_DATE_YEAR_SEPARATOR :
     431                 :          0 :             aLocaleItem[nItem] = aLocaleDataItem.LongDateYearSeparator;
     432                 :          0 :         break;
     433                 :            :         default:
     434                 :            :             SAL_WARN( "unotools", "getOneLocaleItemImpl: which one?" );
     435                 :            :     }
     436                 :       7158 : }
     437                 :            : 
     438                 :            : 
     439                 :       1377 : void LocaleDataWrapper::getOneReservedWordImpl( sal_Int16 nWord )
     440                 :            : {
     441         [ +  + ]:       1377 :     if ( !bReservedWordValid )
     442                 :            :     {
     443         [ +  - ]:        684 :         aReservedWordSeq = getReservedWord();
     444                 :        684 :         bReservedWordValid = sal_True;
     445                 :            :     }
     446                 :            :     DBG_ASSERT( nWord < aReservedWordSeq.getLength(), "getOneReservedWordImpl: which one?" );
     447         [ +  - ]:       1377 :     if ( nWord < aReservedWordSeq.getLength() )
     448                 :       1377 :         aReservedWord[nWord] = aReservedWordSeq[nWord];
     449                 :       1377 : }
     450                 :            : 
     451                 :            : 
     452                 :      14722 : const rtl::OUString& LocaleDataWrapper::getOneReservedWord( sal_Int16 nWord ) const
     453                 :            : {
     454         [ +  - ]:      14722 :     ::utl::ReadWriteGuard aGuard( aMutex );
     455 [ +  - ][ -  + ]:      14722 :     if ( nWord < 0 || nWord >= reservedWords::COUNT )
     456                 :            :     {
     457                 :            :         SAL_WARN( "unotools", "getOneReservedWord: bounds" );
     458                 :          0 :         nWord = reservedWords::FALSE_WORD;
     459                 :            :     }
     460         [ +  + ]:      14722 :     if (aReservedWord[nWord].isEmpty())
     461                 :            :     {   // no cached content
     462         [ +  - ]:       1377 :         aGuard.changeReadToWrite();
     463         [ +  - ]:       1377 :         ((LocaleDataWrapper*)this)->getOneReservedWordImpl( nWord );
     464                 :            :     }
     465         [ +  - ]:      14722 :     return aReservedWord[nWord];
     466                 :            : }
     467                 :            : 
     468                 :            : 
     469                 :       8422 : MeasurementSystem LocaleDataWrapper::mapMeasurementStringToEnum( const rtl::OUString& rMS ) const
     470                 :            : {
     471                 :            : //! TODO: could be cached too
     472         [ -  + ]:       8422 :     if ( rMS.equalsIgnoreAsciiCase( "metric" ) )
     473                 :          0 :         return MEASURE_METRIC;
     474                 :            : //! TODO: other measurement systems? => extend enum MeasurementSystem
     475                 :       8422 :     return MEASURE_US;
     476                 :            : }
     477                 :            : 
     478                 :            : 
     479                 :          0 : void LocaleDataWrapper::getDefaultCalendarImpl()
     480                 :            : {
     481         [ #  # ]:          0 :     if (!xDefaultCalendar)
     482                 :            :     {
     483         [ #  # ]:          0 :         Sequence< Calendar2 > xCals = getAllCalendars();
     484                 :          0 :         sal_Int32 nCount = xCals.getLength();
     485                 :          0 :         sal_Int32 nDef = 0;
     486         [ #  # ]:          0 :         if (nCount > 1)
     487                 :            :         {
     488         [ #  # ]:          0 :             const Calendar2* pArr = xCals.getArray();
     489         [ #  # ]:          0 :             for (sal_Int32 i=0; i<nCount; ++i)
     490                 :            :             {
     491         [ #  # ]:          0 :                 if (pArr[i].Default)
     492                 :            :                 {
     493                 :          0 :                     nDef = i;
     494                 :          0 :                     break;
     495                 :            :                 }
     496                 :            :             }
     497                 :            :         }
     498 [ #  # ][ #  # ]:          0 :         xDefaultCalendar.reset( new Calendar2( xCals[nDef]));
         [ #  # ][ #  # ]
                 [ #  # ]
     499                 :            :     }
     500                 :          0 : }
     501                 :            : 
     502                 :            : 
     503                 :          0 : const ::boost::shared_ptr< ::com::sun::star::i18n::Calendar2 > LocaleDataWrapper::getDefaultCalendar() const
     504                 :            : {
     505         [ #  # ]:          0 :     ::utl::ReadWriteGuard aGuard( aMutex );
     506         [ #  # ]:          0 :     if (!xDefaultCalendar)
     507                 :            :     {   // no cached content
     508         [ #  # ]:          0 :         aGuard.changeReadToWrite();
     509         [ #  # ]:          0 :         ((LocaleDataWrapper*)this)->getDefaultCalendarImpl();
     510                 :            :     }
     511 [ #  # ][ #  # ]:          0 :     return xDefaultCalendar;
     512                 :            : }
     513                 :            : 
     514                 :            : 
     515                 :          0 : const ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem2 > LocaleDataWrapper::getDefaultCalendarDays() const
     516                 :            : {
     517         [ #  # ]:          0 :     return getDefaultCalendar()->Days;
     518                 :            : }
     519                 :            : 
     520                 :            : 
     521                 :          0 : const ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem2 > LocaleDataWrapper::getDefaultCalendarMonths() const
     522                 :            : {
     523         [ #  # ]:          0 :     return getDefaultCalendar()->Months;
     524                 :            : }
     525                 :            : 
     526                 :            : 
     527                 :            : // --- currencies -----------------------------------------------------
     528                 :            : 
     529                 :       7335 : const rtl::OUString& LocaleDataWrapper::getCurrSymbol() const
     530                 :            : {
     531         [ +  - ]:       7335 :     ::utl::ReadWriteGuard aGuard( aMutex );
     532         [ +  + ]:       7335 :     if (aCurrSymbol.isEmpty())
     533                 :            :     {
     534         [ +  - ]:       7201 :         aGuard.changeReadToWrite();
     535         [ +  - ]:       7201 :         ((LocaleDataWrapper*)this)->getCurrSymbolsImpl();
     536                 :            :     }
     537         [ +  - ]:       7335 :     return aCurrSymbol;
     538                 :            : }
     539                 :            : 
     540                 :            : 
     541                 :         65 : const rtl::OUString& LocaleDataWrapper::getCurrBankSymbol() const
     542                 :            : {
     543         [ +  - ]:         65 :     ::utl::ReadWriteGuard aGuard( aMutex );
     544         [ +  + ]:         65 :     if (aCurrBankSymbol.isEmpty())
     545                 :            :     {
     546         [ +  - ]:         29 :         aGuard.changeReadToWrite();
     547         [ +  - ]:         29 :         ((LocaleDataWrapper*)this)->getCurrSymbolsImpl();
     548                 :            :     }
     549         [ +  - ]:         65 :     return aCurrBankSymbol;
     550                 :            : }
     551                 :            : 
     552                 :            : 
     553                 :      10854 : sal_uInt16 LocaleDataWrapper::getCurrPositiveFormat() const
     554                 :            : {
     555         [ +  - ]:      10854 :     ::utl::ReadWriteGuard aGuard( aMutex );
     556         [ +  + ]:      10854 :     if ( nCurrPositiveFormat == nCurrFormatInvalid )
     557                 :            :     {
     558         [ +  - ]:       7193 :         aGuard.changeReadToWrite();
     559         [ +  - ]:       7193 :         ((LocaleDataWrapper*)this)->getCurrFormatsImpl();
     560                 :            :     }
     561         [ +  - ]:      10854 :     return nCurrPositiveFormat;
     562                 :            : }
     563                 :            : 
     564                 :            : 
     565                 :      10835 : sal_uInt16 LocaleDataWrapper::getCurrNegativeFormat() const
     566                 :            : {
     567         [ +  - ]:      10835 :     ::utl::ReadWriteGuard aGuard( aMutex );
     568         [ -  + ]:      10835 :     if ( nCurrNegativeFormat == nCurrFormatInvalid )
     569                 :            :     {
     570         [ #  # ]:          0 :         aGuard.changeReadToWrite();
     571         [ #  # ]:          0 :         ((LocaleDataWrapper*)this)->getCurrFormatsImpl();
     572                 :            :     }
     573         [ +  - ]:      10835 :     return nCurrNegativeFormat;
     574                 :            : }
     575                 :            : 
     576                 :            : 
     577                 :         36 : sal_uInt16 LocaleDataWrapper::getCurrDigits() const
     578                 :            : {
     579         [ +  - ]:         36 :     ::utl::ReadWriteGuard aGuard( aMutex );
     580         [ -  + ]:         36 :     if ( nCurrDigits == nCurrFormatInvalid )
     581                 :            :     {
     582         [ #  # ]:          0 :         aGuard.changeReadToWrite();
     583         [ #  # ]:          0 :         ((LocaleDataWrapper*)this)->getCurrSymbolsImpl();
     584                 :            :     }
     585         [ +  - ]:         36 :     return nCurrDigits;
     586                 :            : }
     587                 :            : 
     588                 :            : 
     589                 :       7230 : void LocaleDataWrapper::getCurrSymbolsImpl()
     590                 :            : {
     591         [ +  - ]:       7230 :     Sequence< Currency2 > aCurrSeq = getAllCurrencies();
     592                 :       7230 :     sal_Int32 nCnt = aCurrSeq.getLength();
     593         [ +  - ]:       7230 :     Currency2 const * const pCurrArr = aCurrSeq.getArray();
     594                 :            :     sal_Int32 nElem;
     595         [ +  - ]:       7626 :     for ( nElem = 0; nElem < nCnt; nElem++ )
     596                 :            :     {
     597         [ +  + ]:       7626 :         if ( pCurrArr[nElem].Default )
     598                 :       7230 :             break;
     599                 :            :     }
     600         [ -  + ]:       7230 :     if ( nElem >= nCnt )
     601                 :            :     {
     602 [ #  # ][ #  # ]:          0 :         if (areChecksEnabled())
     603                 :            :         {
     604                 :            :             rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
     605         [ #  # ]:          0 :                         "LocaleDataWrapper::getCurrSymbolsImpl: no default currency"));
     606 [ #  # ][ #  # ]:          0 :             outputCheckMessage( appendLocaleInfo( aMsg ) );
     607                 :            :         }
     608                 :          0 :         nElem = 0;
     609         [ #  # ]:          0 :         if ( nElem >= nCnt )
     610                 :            :         {
     611 [ #  # ][ #  # ]:          0 :             if (areChecksEnabled())
     612         [ #  # ]:          0 :                 outputCheckMessage(rtl::OUString("LocaleDataWrapper::getCurrSymbolsImpl: no currency at all, using ShellsAndPebbles"));
     613                 :          0 :             aCurrSymbol = rtl::OUString("ShellsAndPebbles");
     614                 :          0 :             aCurrBankSymbol = aCurrSymbol;
     615                 :          0 :             nCurrPositiveFormat = nCurrNegativeFormat = nCurrFormatDefault;
     616                 :          0 :             nCurrDigits = 2;
     617                 :       7230 :             return ;
     618                 :            :         }
     619                 :            :     }
     620                 :       7230 :     aCurrSymbol = pCurrArr[nElem].Symbol;
     621                 :       7230 :     aCurrBankSymbol = pCurrArr[nElem].BankSymbol;
     622 [ +  - ][ +  - ]:       7230 :     nCurrDigits = pCurrArr[nElem].DecimalPlaces;
     623                 :            : }
     624                 :            : 
     625                 :            : 
     626                 :      14386 : void LocaleDataWrapper::scanCurrFormatImpl( const rtl::OUString& rCode,
     627                 :            :         sal_Int32 nStart, sal_Int32& nSign, sal_Int32& nPar,
     628                 :            :         sal_Int32& nNum, sal_Int32& nBlank, sal_Int32& nSym )
     629                 :            : {
     630                 :      14386 :     nSign = nPar = nNum = nBlank = nSym = -1;
     631                 :      14386 :     const sal_Unicode* const pStr = rCode.getStr();
     632                 :      14386 :     const sal_Unicode* const pStop = pStr + rCode.getLength();
     633                 :      14386 :     const sal_Unicode* p = pStr + nStart;
     634                 :      14386 :     int nInSection = 0;
     635                 :      14386 :     sal_Bool bQuote = sal_False;
     636         [ +  + ]:     315325 :     while ( p < pStop )
     637                 :            :     {
     638         [ -  + ]:     300939 :         if ( bQuote )
     639                 :            :         {
     640 [ #  # ][ #  # ]:          0 :             if ( *p == '"' && *(p-1) != '\\' )
     641                 :          0 :                 bQuote = sal_False;
     642                 :            :         }
     643                 :            :         else
     644                 :            :         {
     645   [ -  +  +  +  :     300939 :             switch ( *p )
             +  +  +  +  
                      + ]
     646                 :            :             {
     647                 :            :                 case '"' :
     648 [ #  # ][ #  # ]:          0 :                     if ( pStr == p || *(p-1) != '\\' )
     649                 :          0 :                         bQuote = sal_True;
     650                 :          0 :                 break;
     651                 :            :                 case '-' :
     652 [ +  + ][ +  - ]:      21111 :                     if (!nInSection && nSign == -1)
     653                 :       6725 :                         nSign = p - pStr;
     654                 :      21111 :                 break;
     655                 :            :                 case '(' :
     656 [ +  - ][ +  - ]:        468 :                     if (!nInSection && nPar == -1)
     657                 :        468 :                         nPar = p - pStr;
     658                 :        468 :                 break;
     659                 :            :                 case '0' :
     660                 :            :                 case '#' :
     661 [ +  + ][ +  + ]:      90406 :                     if (!nInSection && nNum == -1)
     662                 :      14386 :                         nNum = p - pStr;
     663                 :      90406 :                 break;
     664                 :            :                 case '[' :
     665                 :      21615 :                     nInSection++;
     666                 :      21615 :                 break;
     667                 :            :                 case ']' :
     668         [ +  - ]:      21615 :                     if ( nInSection )
     669                 :            :                     {
     670                 :      21615 :                         nInSection--;
     671 [ +  - ][ +  + ]:      21615 :                         if (!nInSection && nBlank == -1
         [ +  + ][ +  + ]
                 [ +  + ]
     672                 :      20456 :                           && nSym != -1 && p < pStop-1 && *(p+1) == ' ' )
     673                 :       3024 :                             nBlank = p - pStr + 1;
     674                 :            :                     }
     675                 :      21615 :                 break;
     676                 :            :                 case '$' :
     677 [ +  + ][ +  - ]:      16676 :                     if (nSym == -1 && nInSection && *(p-1) == '[')
                 [ +  - ]
     678                 :            :                     {
     679                 :      14386 :                         nSym = p - pStr + 1;
     680 [ +  + ][ +  + ]:      14386 :                         if (nNum != -1 && *(p-2) == ' ')
     681                 :       3852 :                             nBlank = p - pStr - 2;
     682                 :            :                     }
     683                 :      16676 :                 break;
     684                 :            :                 case ';' :
     685         [ +  - ]:       7193 :                     if ( !nInSection )
     686                 :       7193 :                         p = pStop;
     687                 :       7193 :                 break;
     688                 :            :                 default:
     689 [ +  + ][ +  + ]:     121855 :                     if (!nInSection && nSym == -1 && String(rCode).Equals( aCurrSymbol, (xub_StrLen)(p-pStr), aCurrSymbol.getLength()))
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  + ][ +  - ]
         [ +  + ][ -  +  
             #  #  #  # ]
     690                 :            :                     {   // currency symbol not surrounded by [$...]
     691                 :          0 :                         nSym = p - pStr;
     692 [ #  # ][ #  # ]:          0 :                         if (nBlank == -1 && pStr < p && *(p-1) == ' ')
                 [ #  # ]
     693                 :          0 :                             nBlank = p - pStr - 1;
     694                 :          0 :                         p += aCurrSymbol.getLength() - 1;
     695 [ #  # ][ #  # ]:          0 :                         if (nBlank == -1 && p < pStop-2 && *(p+2) == ' ')
                 [ #  # ]
     696                 :          0 :                             nBlank = p - pStr + 2;
     697                 :            :                     }
     698                 :            :             }
     699                 :            :         }
     700                 :     300939 :         p++;
     701                 :            :     }
     702                 :      14386 : }
     703                 :            : 
     704                 :       7193 : void LocaleDataWrapper::getCurrFormatsImpl()
     705                 :            : {
     706 [ +  - ][ +  - ]:       7193 :     NumberFormatCodeWrapper aNumberFormatCode( xSMgr, getLocale() );
     707                 :            :     uno::Sequence< NumberFormatCode > aFormatSeq
     708         [ +  - ]:       7193 :         = aNumberFormatCode.getAllFormatCode( KNumberFormatUsage::CURRENCY );
     709                 :       7193 :     sal_Int32 nCnt = aFormatSeq.getLength();
     710         [ -  + ]:       7193 :     if ( !nCnt )
     711                 :            :     {   // bad luck
     712 [ #  # ][ #  # ]:          0 :         if (areChecksEnabled())
     713                 :            :         {
     714                 :            :             rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
     715         [ #  # ]:          0 :                         "LocaleDataWrapper::getCurrFormatsImpl: no currency formats"));
     716 [ #  # ][ #  # ]:          0 :             outputCheckMessage( appendLocaleInfo( aMsg ) );
     717                 :            :         }
     718                 :          0 :         nCurrPositiveFormat = nCurrNegativeFormat = nCurrFormatDefault;
     719                 :       7193 :         return ;
     720                 :            :     }
     721                 :            :     // find a negative code (medium preferred) and a default (medium preferred) (not necessarily the same)
     722         [ +  - ]:       7193 :     NumberFormatCode const * const pFormatArr = aFormatSeq.getArray();
     723                 :            :     sal_Int32 nElem, nDef, nNeg, nMedium;
     724                 :       7193 :     nDef = nNeg = nMedium = -1;
     725         [ +  + ]:      51071 :     for ( nElem = 0; nElem < nCnt; nElem++ )
     726                 :            :     {
     727         [ +  + ]:      43878 :         if ( pFormatArr[nElem].Type == KNumberFormatType::MEDIUM )
     728                 :            :         {
     729         [ +  + ]:      36541 :             if ( pFormatArr[nElem].Default )
     730                 :            :             {
     731                 :       7193 :                 nDef = nElem;
     732                 :       7193 :                 nMedium = nElem;
     733         [ +  - ]:       7193 :                 if ( pFormatArr[nElem].Code.indexOf( ';' ) >= 0 )
     734                 :       7193 :                     nNeg = nElem;
     735                 :            :             }
     736                 :            :             else
     737                 :            :             {
     738 [ +  + ][ +  + ]:      29348 :                 if ( (nNeg == -1 || nMedium == -1) && pFormatArr[nElem].Code.indexOf( ';' ) >= 0 )
         [ +  - ][ +  + ]
     739                 :       7013 :                     nNeg = nElem;
     740         [ +  + ]:      29348 :                 if ( nMedium == -1 )
     741                 :       7013 :                     nMedium = nElem;
     742                 :            :             }
     743                 :            :         }
     744                 :            :         else
     745                 :            :         {
     746 [ +  + ][ +  - ]:       7337 :             if ( nDef == -1 && pFormatArr[nElem].Default )
     747                 :       6941 :                 nDef = nElem;
     748 [ +  + ][ +  - ]:       7337 :             if ( nNeg == -1 && pFormatArr[nElem].Code.indexOf( ';' ) >= 0 )
                 [ +  + ]
     749                 :       6941 :                 nNeg = nElem;
     750                 :            :         }
     751                 :            :     }
     752                 :            : 
     753                 :            :     // make sure it's loaded
     754         [ +  - ]:       7193 :     getCurrSymbol();
     755                 :            : 
     756                 :            :     sal_Int32 nSign, nPar, nNum, nBlank, nSym;
     757                 :            : 
     758                 :            :     // positive format
     759         [ -  + ]:       7193 :     nElem = (nDef >= 0 ? nDef : (nNeg >= 0 ? nNeg : 0));
     760         [ +  - ]:       7193 :     scanCurrFormatImpl( pFormatArr[nElem].Code, 0, nSign, nPar, nNum, nBlank, nSym );
     761 [ +  - ][ -  + ]:       7193 :     if (areChecksEnabled() && (nNum == -1 || nSym == -1))
         [ #  # ][ #  # ]
                 [ -  + ]
     762                 :            :     {
     763                 :            :         rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
     764         [ #  # ]:          0 :                     "LocaleDataWrapper::getCurrFormatsImpl: CurrPositiveFormat?"));
     765 [ #  # ][ #  # ]:          0 :         outputCheckMessage( appendLocaleInfo( aMsg ) );
     766                 :            :     }
     767         [ +  + ]:       7193 :     if (nBlank == -1)
     768                 :            :     {
     769         [ +  + ]:       3521 :         if ( nSym < nNum )
     770                 :       2909 :             nCurrPositiveFormat = 0;    // $1
     771                 :            :         else
     772                 :        612 :             nCurrPositiveFormat = 1;    // 1$
     773                 :            :     }
     774                 :            :     else
     775                 :            :     {
     776         [ +  + ]:       3672 :         if ( nSym < nNum )
     777                 :       1764 :             nCurrPositiveFormat = 2;    // $ 1
     778                 :            :         else
     779                 :       1908 :             nCurrPositiveFormat = 3;    // 1 $
     780                 :            :     }
     781                 :            : 
     782                 :            :     // negative format
     783         [ -  + ]:       7193 :     if ( nNeg < 0 )
     784                 :          0 :         nCurrNegativeFormat = nCurrFormatDefault;
     785                 :            :     else
     786                 :            :     {
     787                 :       7193 :         const ::rtl::OUString& rCode = pFormatArr[nNeg].Code;
     788                 :       7193 :         sal_Int32 nDelim = rCode.indexOf(';');
     789         [ +  - ]:       7193 :         scanCurrFormatImpl( rCode, nDelim+1, nSign, nPar, nNum, nBlank, nSym );
     790 [ +  - ][ -  + ]:       7193 :         if (areChecksEnabled() && (nNum == -1 || nSym == -1 || (nPar == -1 && nSign == -1)))
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ -  + ]
     791                 :            :         {
     792                 :            :             rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
     793         [ #  # ]:          0 :                         "LocaleDataWrapper::getCurrFormatsImpl: CurrNegativeFormat?"));
     794 [ #  # ][ #  # ]:          0 :             outputCheckMessage( appendLocaleInfo( aMsg ) );
     795                 :            :         }
     796                 :            :         // NOTE: one of nPar or nSign are allowed to be -1
     797         [ +  + ]:       7193 :         if (nBlank == -1)
     798                 :            :         {
     799         [ +  + ]:       3989 :             if ( nSym < nNum )
     800                 :            :             {
     801 [ +  + ][ +  - ]:       3377 :                 if ( -1 < nPar && nPar < nSym )
     802                 :        396 :                     nCurrNegativeFormat = 0;    // ($1)
     803 [ +  - ][ +  + ]:       2981 :                 else if ( -1 < nSign && nSign < nSym )
     804                 :       2261 :                     nCurrNegativeFormat = 1;    // -$1
     805         [ -  + ]:        720 :                 else if ( nNum < nSign )
     806                 :          0 :                     nCurrNegativeFormat = 3;    // $1-
     807                 :            :                 else
     808                 :       3377 :                     nCurrNegativeFormat = 2;    // $-1
     809                 :            :             }
     810                 :            :             else
     811                 :            :             {
     812 [ -  + ][ #  # ]:        612 :                 if ( -1 < nPar && nPar < nNum )
     813                 :          0 :                     nCurrNegativeFormat = 4;    // (1$)
     814 [ +  - ][ +  - ]:        612 :                 else if ( -1 < nSign && nSign < nNum )
     815                 :        612 :                     nCurrNegativeFormat = 5;    // -1$
     816         [ #  # ]:          0 :                 else if ( nSym < nSign )
     817                 :          0 :                     nCurrNegativeFormat = 7;    // 1$-
     818                 :            :                 else
     819                 :       3989 :                     nCurrNegativeFormat = 6;    // 1-$
     820                 :            :             }
     821                 :            :         }
     822                 :            :         else
     823                 :            :         {
     824         [ +  + ]:       3204 :             if ( nSym < nNum )
     825                 :            :             {
     826 [ +  + ][ +  - ]:       1260 :                 if ( -1 < nPar && nPar < nSym )
     827                 :         72 :                     nCurrNegativeFormat = 14;   // ($ 1)
     828 [ +  - ][ +  + ]:       1188 :                 else if ( -1 < nSign && nSign < nSym )
     829                 :        576 :                     nCurrNegativeFormat = 9;    // -$ 1
     830         [ +  + ]:        612 :                 else if ( nNum < nSign )
     831                 :        252 :                     nCurrNegativeFormat = 12;   // $ 1-
     832                 :            :                 else
     833                 :       1260 :                     nCurrNegativeFormat = 11;   // $ -1
     834                 :            :             }
     835                 :            :             else
     836                 :            :             {
     837 [ -  + ][ #  # ]:       1944 :                 if ( -1 < nPar && nPar < nNum )
     838                 :          0 :                     nCurrNegativeFormat = 15;   // (1 $)
     839 [ +  - ][ +  - ]:       1944 :                 else if ( -1 < nSign && nSign < nNum )
     840                 :       1944 :                     nCurrNegativeFormat = 8;    // -1 $
     841         [ #  # ]:          0 :                 else if ( nSym < nSign )
     842                 :          0 :                     nCurrNegativeFormat = 10;   // 1 $-
     843                 :            :                 else
     844                 :       7193 :                     nCurrNegativeFormat = 13;   // 1- $
     845                 :            :             }
     846                 :            :         }
     847 [ +  - ][ -  + ]:       7193 :     }
         [ +  - ][ +  - ]
     848                 :            : }
     849                 :            : 
     850                 :            : 
     851                 :            : // --- date -----------------------------------------------------------
     852                 :            : 
     853                 :       1283 : DateFormat LocaleDataWrapper::getDateFormat() const
     854                 :            : {
     855         [ +  - ]:       1283 :     ::utl::ReadWriteGuard aGuard( aMutex );
     856         [ +  + ]:       1283 :     if ( nDateFormat == nDateFormatInvalid )
     857                 :            :     {
     858         [ +  - ]:         74 :         aGuard.changeReadToWrite();
     859         [ +  - ]:         74 :         ((LocaleDataWrapper*)this)->getDateFormatsImpl();
     860                 :            :     }
     861         [ +  - ]:       1283 :     return (DateFormat) nDateFormat;
     862                 :            : }
     863                 :            : 
     864                 :            : 
     865                 :        299 : DateFormat LocaleDataWrapper::getLongDateFormat() const
     866                 :            : {
     867         [ +  - ]:        299 :     ::utl::ReadWriteGuard aGuard( aMutex );
     868         [ -  + ]:        299 :     if ( nLongDateFormat == nDateFormatInvalid )
     869                 :            :     {
     870         [ #  # ]:          0 :         aGuard.changeReadToWrite();
     871         [ #  # ]:          0 :         ((LocaleDataWrapper*)this)->getDateFormatsImpl();
     872                 :            :     }
     873         [ +  - ]:        299 :     return (DateFormat) nLongDateFormat;
     874                 :            : }
     875                 :            : 
     876                 :            : 
     877                 :        148 : DateFormat LocaleDataWrapper::scanDateFormatImpl( const rtl::OUString& rCode )
     878                 :            : {
     879                 :            :     // Only some european versions were translated, the ones with different
     880                 :            :     // keyword combinations are:
     881                 :            :     // English DMY, German TMJ, Spanish DMA, French JMA, Italian GMA,
     882                 :            :     // Dutch DMJ, Finnish PKV
     883                 :            : 
     884                 :            :     // default is English keywords for every other language
     885                 :        148 :     sal_Int32 nDay = rCode.indexOf('D');
     886                 :        148 :     sal_Int32 nMonth = rCode.indexOf('M');
     887                 :        148 :     sal_Int32 nYear = rCode.indexOf('Y');
     888 [ +  - ][ -  + ]:        148 :     if (nDay == -1 || nMonth == -1 || nYear == -1)
                 [ +  - ]
     889                 :            :     {   // This algorithm assumes that all three parts (DMY) are present
     890         [ #  # ]:          0 :         if (nMonth == -1)
     891                 :            :         {   // only Finnish has something else than 'M' for month
     892                 :          0 :             nMonth = rCode.indexOf('K');
     893         [ #  # ]:          0 :             if (nMonth != -1)
     894                 :            :             {
     895                 :          0 :                 nDay = rCode.indexOf('P');
     896                 :          0 :                 nYear = rCode.indexOf('V');
     897                 :            :             }
     898                 :            :         }
     899         [ #  # ]:          0 :         else if (nDay == -1)
     900                 :            :         {   // We have a month 'M' if we reach this branch.
     901                 :            :             // Possible languages containing 'M' but no 'D':
     902                 :            :             // German, French, Italian
     903                 :          0 :             nDay = rCode.indexOf('T');         // German
     904         [ #  # ]:          0 :             if (nDay != -1)
     905                 :          0 :                 nYear = rCode.indexOf('J');
     906                 :            :             else
     907                 :            :             {
     908                 :          0 :                 nYear = rCode.indexOf('A');    // French, Italian
     909         [ #  # ]:          0 :                 if (nYear != -1)
     910                 :            :                 {
     911                 :          0 :                     nDay = rCode.indexOf('J'); // French
     912         [ #  # ]:          0 :                     if (nDay == -1)
     913                 :          0 :                         nDay = rCode.indexOf('G'); // Italian
     914                 :            :                 }
     915                 :            :             }
     916                 :            :         }
     917                 :            :         else
     918                 :            :         {   // We have a month 'M' and a day 'D'.
     919                 :            :             // Possible languages containing 'D' and 'M' but not 'Y':
     920                 :            :             // Spanish, Dutch
     921                 :          0 :             nYear = rCode.indexOf('A');        // Spanish
     922         [ #  # ]:          0 :             if (nYear == -1)
     923                 :          0 :                 nYear = rCode.indexOf('J');    // Dutch
     924                 :            :         }
     925 [ #  # ][ #  # ]:          0 :         if (nDay == -1 || nMonth == -1 || nYear == -1)
                 [ #  # ]
     926                 :            :         {
     927         [ #  # ]:          0 :             if (areChecksEnabled())
     928                 :            :             {
     929                 :            :                 rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
     930         [ #  # ]:          0 :                             "LocaleDataWrapper::scanDateFormat: not all DMY present"));
     931 [ #  # ][ #  # ]:          0 :                 outputCheckMessage( appendLocaleInfo( aMsg ) );
     932                 :            :             }
     933         [ #  # ]:          0 :             if (nDay == -1)
     934                 :          0 :                 nDay = rCode.getLength();
     935         [ #  # ]:          0 :             if (nMonth == -1)
     936                 :          0 :                 nMonth = rCode.getLength();
     937         [ #  # ]:          0 :             if (nYear == -1)
     938                 :          0 :                 nYear = rCode.getLength();
     939                 :            :         }
     940                 :            :     }
     941                 :            :     // compare with <= because each position may equal rCode.getLength()
     942 [ -  + ][ #  # ]:        148 :     if ( nDay <= nMonth && nMonth <= nYear )
     943                 :          0 :         return DMY;     // also if every position equals rCode.getLength()
     944 [ +  - ][ +  - ]:        148 :     else if ( nMonth <= nDay && nDay <= nYear )
     945                 :        148 :         return MDY;
     946 [ #  # ][ #  # ]:          0 :     else if ( nYear <= nMonth && nMonth <= nDay )
     947                 :          0 :         return YMD;
     948                 :            :     else
     949                 :            :     {
     950         [ #  # ]:          0 :         if (areChecksEnabled())
     951                 :            :         {
     952                 :            :             rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
     953         [ #  # ]:          0 :                         "LocaleDataWrapper::scanDateFormat: no magic applyable"));
     954 [ #  # ][ #  # ]:          0 :             outputCheckMessage( appendLocaleInfo( aMsg ) );
     955                 :            :         }
     956                 :        148 :         return DMY;
     957                 :            :     }
     958                 :            : }
     959                 :            : 
     960                 :            : 
     961                 :         74 : void LocaleDataWrapper::getDateFormatsImpl()
     962                 :            : {
     963 [ +  - ][ +  - ]:         74 :     NumberFormatCodeWrapper aNumberFormatCode( xSMgr, getLocale() );
     964                 :            :     uno::Sequence< NumberFormatCode > aFormatSeq
     965         [ +  - ]:         74 :         = aNumberFormatCode.getAllFormatCode( KNumberFormatUsage::DATE );
     966                 :         74 :     sal_Int32 nCnt = aFormatSeq.getLength();
     967         [ -  + ]:         74 :     if ( !nCnt )
     968                 :            :     {   // bad luck
     969 [ #  # ][ #  # ]:          0 :         if (areChecksEnabled())
     970                 :            :         {
     971                 :            :             rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
     972         [ #  # ]:          0 :                         "LocaleDataWrapper::getDateFormatsImpl: no date formats"));
     973 [ #  # ][ #  # ]:          0 :             outputCheckMessage( appendLocaleInfo( aMsg ) );
     974                 :            :         }
     975                 :          0 :         nDateFormat = nLongDateFormat = DMY;
     976                 :         74 :         return ;
     977                 :            :     }
     978                 :            :     // find the edit (21), a default (medium preferred),
     979                 :            :     // a medium (default preferred), and a long (default preferred)
     980         [ +  - ]:         74 :     NumberFormatCode const * const pFormatArr = aFormatSeq.getArray();
     981                 :            :     sal_Int32 nElem, nEdit, nDef, nMedium, nLong;
     982                 :         74 :     nEdit = nDef = nMedium = nLong = -1;
     983         [ +  + ]:       2368 :     for ( nElem = 0; nElem < nCnt; nElem++ )
     984                 :            :     {
     985 [ +  + ][ +  + ]:       2294 :         if ( nEdit == -1 && pFormatArr[nElem].Index == NumberFormatIndex::DATE_SYS_DDMMYYYY )
     986                 :         74 :             nEdit = nElem;
     987 [ +  + ][ +  - ]:       2294 :         if ( nDef == -1 && pFormatArr[nElem].Default )
     988                 :         74 :             nDef = nElem;
     989      [ +  +  + ]:       2294 :         switch ( pFormatArr[nElem].Type )
     990                 :            :         {
     991                 :            :             case KNumberFormatType::MEDIUM :
     992                 :            :             {
     993         [ +  + ]:       1110 :                 if ( pFormatArr[nElem].Default )
     994                 :            :                 {
     995                 :         74 :                     nDef = nElem;
     996                 :         74 :                     nMedium = nElem;
     997                 :            :                 }
     998         [ -  + ]:       1036 :                 else if ( nMedium == -1 )
     999                 :          0 :                     nMedium = nElem;
    1000                 :            :             }
    1001                 :       1110 :             break;
    1002                 :            :             case KNumberFormatType::LONG :
    1003                 :            :             {
    1004         [ +  + ]:       1036 :                 if ( pFormatArr[nElem].Default )
    1005                 :         74 :                     nLong = nElem;
    1006         [ -  + ]:        962 :                 else if ( nLong == -1 )
    1007                 :          0 :                     nLong = nElem;
    1008                 :            :             }
    1009                 :       1036 :             break;
    1010                 :            :         }
    1011                 :            :     }
    1012         [ -  + ]:         74 :     if ( nEdit == -1 )
    1013                 :            :     {
    1014 [ #  # ][ #  # ]:          0 :         if (areChecksEnabled())
    1015                 :            :         {
    1016                 :            :             rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
    1017         [ #  # ]:          0 :                         "LocaleDataWrapper::getDateFormatsImpl: no edit"));
    1018 [ #  # ][ #  # ]:          0 :             outputCheckMessage( appendLocaleInfo( aMsg ) );
    1019                 :            :         }
    1020         [ #  # ]:          0 :         if ( nDef == -1 )
    1021                 :            :         {
    1022 [ #  # ][ #  # ]:          0 :             if (areChecksEnabled())
    1023                 :            :             {
    1024                 :            :                 rtl::OUString aMsg( RTL_CONSTASCII_USTRINGPARAM(
    1025         [ #  # ]:          0 :                             "LocaleDataWrapper::getDateFormatsImpl: no default"));
    1026 [ #  # ][ #  # ]:          0 :                 outputCheckMessage( appendLocaleInfo( aMsg ) );
    1027                 :            :             }
    1028         [ #  # ]:          0 :             if ( nMedium != -1 )
    1029                 :          0 :                 nDef = nMedium;
    1030         [ #  # ]:          0 :             else if ( nLong != -1 )
    1031                 :          0 :                 nDef = nLong;
    1032                 :            :             else
    1033                 :          0 :                 nDef = 0;
    1034                 :            :         }
    1035                 :          0 :         nEdit = nDef;
    1036                 :            :     }
    1037         [ +  - ]:         74 :     DateFormat nDF = scanDateFormatImpl( pFormatArr[nEdit].Code );
    1038         [ -  + ]:         74 :     if ( pFormatArr[nEdit].Type == KNumberFormatType::LONG )
    1039                 :            :     {   // normally this is not the case
    1040                 :          0 :         nLongDateFormat = nDateFormat = nDF;
    1041                 :            :     }
    1042                 :            :     else
    1043                 :            :     {
    1044                 :         74 :         nDateFormat = nDF;
    1045         [ -  + ]:         74 :         if ( nLong == -1 )
    1046                 :          0 :             nLongDateFormat = nDF;
    1047                 :            :         else
    1048         [ +  - ]:         74 :             nLongDateFormat = scanDateFormatImpl( pFormatArr[nLong].Code );
    1049 [ +  - ][ -  + ]:         74 :     }
         [ +  - ][ +  - ]
    1050                 :            : }
    1051                 :            : 
    1052                 :            : 
    1053                 :            : // --- digit grouping -------------------------------------------------
    1054                 :            : 
    1055                 :       1832 : void LocaleDataWrapper::getDigitGroupingImpl()
    1056                 :            : {
    1057                 :            :     /* TODO: This is a very simplified grouping setup that only serves its
    1058                 :            :      * current purpose for Indian locales. A free-form flexible one would
    1059                 :            :      * obtain grouping from locale data where it could be specified using, for
    1060                 :            :      * example, codes like #,### and #,##,### that would generate the integer
    1061                 :            :      * sequence. Needed additional API and a locale data element.
    1062                 :            :      */
    1063                 :            : 
    1064         [ +  - ]:       1832 :     if (!aGrouping.getLength())
    1065                 :            :     {
    1066                 :       1832 :         aGrouping.realloc(3);   // room for {3,2,0}
    1067                 :       1832 :         aGrouping[0] = 0;       // invalidate
    1068                 :            :     }
    1069         [ +  - ]:       1832 :     if (!aGrouping[0])
    1070                 :            :     {
    1071         [ +  - ]:       1832 :         i18n::LanguageCountryInfo aLCInfo( getLanguageCountryInfo());
    1072   [ +  -  -  + ]:       3664 :         if (aLCInfo.Country.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("IN")) || // India
                 [ -  + ]
    1073                 :       1832 :             aLCInfo.Country.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("BT")) )  // Bhutan
    1074                 :            :         {
    1075         [ #  # ]:          0 :             aGrouping[0] = 3;
    1076         [ #  # ]:          0 :             aGrouping[1] = 2;
    1077         [ #  # ]:          0 :             aGrouping[2] = 0;
    1078                 :            :         }
    1079                 :            :         else
    1080                 :            :         {
    1081         [ +  - ]:       1832 :             aGrouping[0] = 3;
    1082         [ +  - ]:       1832 :             aGrouping[1] = 0;
    1083                 :       1832 :         }
    1084                 :            :     }
    1085                 :       1832 : }
    1086                 :            : 
    1087                 :            : 
    1088                 :     110114 : const ::com::sun::star::uno::Sequence< sal_Int32 > LocaleDataWrapper::getDigitGrouping() const
    1089                 :            : {
    1090         [ +  - ]:     110114 :     ::utl::ReadWriteGuard aGuard( aMutex );
    1091 [ +  + ][ -  + ]:     110114 :     if (!aGrouping.getLength() || aGrouping[0] == 0)
                 [ +  + ]
    1092                 :            :     {   // no cached content
    1093         [ +  - ]:       1832 :         aGuard.changeReadToWrite();
    1094         [ +  - ]:       1832 :         ((LocaleDataWrapper*)this)->getDigitGroupingImpl();
    1095                 :            :     }
    1096 [ +  - ][ +  - ]:     110114 :     return aGrouping;
    1097                 :            : }
    1098                 :            : 
    1099                 :            : 
    1100                 :            : // --- simple number formatting helpers -------------------------------
    1101                 :            : 
    1102                 :            : // The ImplAdd... methods are taken from class International and modified to
    1103                 :            : // suit the needs.
    1104                 :            : 
    1105                 :      38440 : static sal_Unicode* ImplAddUNum( sal_Unicode* pBuf, sal_uInt64 nNumber )
    1106                 :            : {
    1107                 :            :     // fill temp buffer with digits
    1108                 :            :     sal_Unicode aTempBuf[64];
    1109                 :      38440 :     sal_Unicode* pTempBuf = aTempBuf;
    1110         [ +  + ]:      98934 :     do
    1111                 :            :     {
    1112                 :      98934 :         *pTempBuf = (sal_Unicode)(nNumber % 10) + '0';
    1113                 :      98934 :         pTempBuf++;
    1114                 :      98934 :         nNumber /= 10;
    1115                 :            :     }
    1116                 :            :     while ( nNumber );
    1117                 :            : 
    1118                 :            :     // copy temp buffer to buffer passed
    1119         [ +  + ]:      98934 :     do
    1120                 :            :     {
    1121                 :      98934 :         pTempBuf--;
    1122                 :      98934 :         *pBuf = *pTempBuf;
    1123                 :      98934 :         pBuf++;
    1124                 :            :     }
    1125                 :            :     while ( pTempBuf != aTempBuf );
    1126                 :            : 
    1127                 :      38440 :     return pBuf;
    1128                 :            : }
    1129                 :            : 
    1130                 :            : 
    1131                 :        119 : static sal_Unicode* ImplAddUNum( sal_Unicode* pBuf, sal_uInt64 nNumber, int nMinLen )
    1132                 :            : {
    1133                 :            :     // fill temp buffer with digits
    1134                 :            :     sal_Unicode aTempBuf[64];
    1135                 :        119 :     sal_Unicode* pTempBuf = aTempBuf;
    1136         [ +  + ]:        218 :     do
    1137                 :            :     {
    1138                 :        218 :         *pTempBuf = (sal_Unicode)(nNumber % 10) + '0';
    1139                 :        218 :         pTempBuf++;
    1140                 :        218 :         nNumber /= 10;
    1141                 :        218 :         nMinLen--;
    1142                 :            :     }
    1143                 :            :     while ( nNumber );
    1144                 :            : 
    1145                 :            :     // fill with zeros up to the minimal length
    1146         [ +  + ]:        353 :     while ( nMinLen > 0 )
    1147                 :            :     {
    1148                 :        234 :         *pBuf = '0';
    1149                 :        234 :         pBuf++;
    1150                 :        234 :         nMinLen--;
    1151                 :            :     }
    1152                 :            : 
    1153                 :            :     // copy temp buffer to real buffer
    1154         [ +  + ]:        218 :     do
    1155                 :            :     {
    1156                 :        218 :         pTempBuf--;
    1157                 :        218 :         *pBuf = *pTempBuf;
    1158                 :        218 :         pBuf++;
    1159                 :            :     }
    1160                 :            :     while ( pTempBuf != aTempBuf );
    1161                 :            : 
    1162                 :        119 :     return pBuf;
    1163                 :            : }
    1164                 :            : 
    1165                 :            : 
    1166                 :       1353 : static sal_Unicode* ImplAdd2UNum( sal_Unicode* pBuf, sal_uInt16 nNumber, int bLeading )
    1167                 :            : {
    1168                 :            :     DBG_ASSERT( nNumber < 100, "ImplAdd2UNum() - Number >= 100" );
    1169                 :            : 
    1170         [ +  + ]:       1353 :     if ( nNumber < 10 )
    1171                 :            :     {
    1172         [ +  - ]:       1192 :         if ( bLeading )
    1173                 :            :         {
    1174                 :       1192 :             *pBuf = '0';
    1175                 :       1192 :             pBuf++;
    1176                 :            :         }
    1177                 :       1192 :         *pBuf = nNumber + '0';
    1178                 :            :     }
    1179                 :            :     else
    1180                 :            :     {
    1181                 :        161 :         sal_uInt16 nTemp = nNumber % 10;
    1182                 :        161 :         nNumber /= 10;
    1183                 :        161 :         *pBuf = nNumber + '0';
    1184                 :        161 :         pBuf++;
    1185                 :        161 :         *pBuf = nTemp + '0';
    1186                 :            :     }
    1187                 :            : 
    1188                 :       1353 :     pBuf++;
    1189                 :       1353 :     return pBuf;
    1190                 :            : }
    1191                 :            : 
    1192                 :            : 
    1193                 :      35448 : inline sal_Unicode* ImplAddString( sal_Unicode* pBuf, const rtl::OUString& rStr )
    1194                 :            : {
    1195         [ +  - ]:      35448 :     if ( rStr.getLength() == 1 )
    1196                 :      35448 :         *pBuf++ = rStr[0];
    1197         [ #  # ]:          0 :     else if (rStr.isEmpty())
    1198                 :            :         ;
    1199                 :            :     else
    1200                 :            :     {
    1201                 :          0 :         memcpy( pBuf, rStr.getStr(), rStr.getLength() * sizeof(sal_Unicode) );
    1202                 :          0 :         pBuf += rStr.getLength();
    1203                 :            :     }
    1204                 :      35448 :     return pBuf;
    1205                 :            : }
    1206                 :            : 
    1207                 :            : 
    1208                 :          0 : inline sal_Unicode* ImplAddString( sal_Unicode* pBuf, sal_Unicode c )
    1209                 :            : {
    1210                 :          0 :     *pBuf = c;
    1211                 :          0 :     pBuf++;
    1212                 :          0 :     return pBuf;
    1213                 :            : }
    1214                 :            : 
    1215                 :            : 
    1216                 :          0 : inline sal_Unicode* ImplAddString( sal_Unicode* pBuf, const sal_Unicode* pCopyBuf, xub_StrLen nLen )
    1217                 :            : {
    1218                 :          0 :     memcpy( pBuf, pCopyBuf, nLen * sizeof(sal_Unicode) );
    1219                 :          0 :     return pBuf + nLen;
    1220                 :            : }
    1221                 :            : 
    1222                 :            : 
    1223                 :      38345 : sal_Unicode* LocaleDataWrapper::ImplAddFormatNum( sal_Unicode* pBuf,
    1224                 :            :         sal_Int64 nNumber, sal_uInt16 nDecimals, sal_Bool bUseThousandSep,
    1225                 :            :         sal_Bool bTrailingZeros ) const
    1226                 :            : {
    1227                 :            :     sal_Unicode aNumBuf[64];
    1228                 :            :     sal_Unicode* pNumBuf;
    1229                 :            :     sal_uInt16  nNumLen;
    1230                 :      38345 :     sal_uInt16  i = 0;
    1231                 :            : 
    1232                 :            :     // negative number
    1233         [ -  + ]:      38345 :     if ( nNumber < 0 )
    1234                 :            :     {
    1235                 :          0 :         nNumber *= -1;
    1236                 :          0 :         *pBuf = '-';
    1237                 :          0 :         pBuf++;
    1238                 :            :     }
    1239                 :            : 
    1240                 :            :     // convert number
    1241                 :      38345 :     pNumBuf = ImplAddUNum( aNumBuf, (sal_uInt64)nNumber );
    1242                 :      38345 :     nNumLen = (sal_uInt16)(sal_uLong)(pNumBuf-aNumBuf);
    1243                 :      38345 :     pNumBuf = aNumBuf;
    1244                 :            : 
    1245         [ +  + ]:      38345 :     if ( nNumLen <= nDecimals )
    1246                 :            :     {
    1247                 :            :         // strip .0 in decimals?
    1248 [ +  - ][ +  + ]:       2122 :         if ( !nNumber && !bTrailingZeros )
    1249                 :            :         {
    1250                 :        961 :             *pBuf = '0';
    1251                 :        961 :             pBuf++;
    1252                 :            :         }
    1253                 :            :         else
    1254                 :            :         {
    1255                 :            :             // LeadingZero, insert 0
    1256         [ +  - ]:       1161 :             if ( isNumLeadingZero() )
    1257                 :            :             {
    1258                 :       1161 :                 *pBuf = '0';
    1259                 :       1161 :                 pBuf++;
    1260                 :            :             }
    1261                 :            : 
    1262                 :            :             // append decimal separator
    1263         [ +  - ]:       1161 :             pBuf = ImplAddString( pBuf, getNumDecimalSep() );
    1264                 :            : 
    1265                 :            :             // fill with zeros
    1266         [ +  + ]:       2322 :             while ( i < (nDecimals-nNumLen) )
    1267                 :            :             {
    1268                 :       1161 :                 *pBuf = '0';
    1269                 :       1161 :                 pBuf++;
    1270                 :       1161 :                 i++;
    1271                 :            :             }
    1272                 :            : 
    1273                 :            :             // append decimals
    1274         [ +  + ]:       3283 :             while ( nNumLen )
    1275                 :            :             {
    1276                 :       1161 :                 *pBuf = *pNumBuf;
    1277                 :       1161 :                 pBuf++;
    1278                 :       1161 :                 pNumBuf++;
    1279                 :       1161 :                 nNumLen--;
    1280                 :            :             }
    1281                 :            :         }
    1282                 :            :     }
    1283                 :            :     else
    1284                 :            :     {
    1285         [ +  - ]:      36223 :         const rtl::OUString& rThoSep = getNumThousandSep();
    1286                 :            : 
    1287                 :            :         // copy number to buffer (excluding decimals)
    1288                 :      36223 :         sal_uInt16 nNumLen2 = nNumLen-nDecimals;
    1289         [ +  - ]:      36223 :         uno::Sequence< sal_Bool > aGroupPos;
    1290         [ +  - ]:      36223 :         if (bUseThousandSep)
    1291                 :            :             aGroupPos = utl::DigitGroupingIterator::createForwardSequence(
    1292 [ +  - ][ +  - ]:      36223 :                     nNumLen2, getDigitGrouping());
         [ +  - ][ +  - ]
                 [ +  - ]
    1293         [ +  + ]:      99284 :         for ( ; i < nNumLen2; ++i )
    1294                 :            :         {
    1295                 :      63061 :             *pBuf = *pNumBuf;
    1296                 :      63061 :             pBuf++;
    1297                 :      63061 :             pNumBuf++;
    1298                 :            : 
    1299                 :            :             // add thousand separator?
    1300 [ +  - ][ +  - ]:      63061 :             if ( bUseThousandSep && aGroupPos[i] )
         [ -  + ][ -  + ]
    1301                 :          0 :                 pBuf = ImplAddString( pBuf, rThoSep );
    1302                 :            :         }
    1303                 :            : 
    1304                 :            :         // append decimals
    1305         [ +  + ]:      36223 :         if ( nDecimals )
    1306                 :            :         {
    1307         [ +  - ]:      33479 :             pBuf = ImplAddString( pBuf, getNumDecimalSep() );
    1308                 :            : 
    1309                 :      33479 :             sal_Bool bNullEnd = sal_True;
    1310         [ +  + ]:      66958 :             while ( i < nNumLen )
    1311                 :            :             {
    1312         [ +  + ]:      33479 :                 if ( *pNumBuf != '0' )
    1313                 :        940 :                     bNullEnd = sal_False;
    1314                 :            : 
    1315                 :      33479 :                 *pBuf = *pNumBuf;
    1316                 :      33479 :                 pBuf++;
    1317                 :      33479 :                 pNumBuf++;
    1318                 :      33479 :                 i++;
    1319                 :            :             }
    1320                 :            : 
    1321                 :            :             // strip .0 in decimals?
    1322 [ +  + ][ +  - ]:      33479 :             if ( bNullEnd && !bTrailingZeros )
    1323                 :      32539 :                 pBuf -= nDecimals+1;
    1324         [ +  - ]:      36223 :         }
    1325                 :            :     }
    1326                 :            : 
    1327                 :      38345 :     return pBuf;
    1328                 :            : }
    1329                 :            : 
    1330                 :            : 
    1331                 :            : // --- simple date and time formatting --------------------------------
    1332                 :            : 
    1333                 :        107 : rtl::OUString LocaleDataWrapper::getDate( const Date& rDate ) const
    1334                 :            : {
    1335         [ +  - ]:        107 :     ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical );
    1336                 :            : //!TODO: leading zeros et al
    1337                 :            :     sal_Unicode aBuf[128];
    1338                 :        107 :     sal_Unicode* pBuf = aBuf;
    1339                 :        107 :     sal_uInt16  nDay    = rDate.GetDay();
    1340                 :        107 :     sal_uInt16  nMonth  = rDate.GetMonth();
    1341                 :        107 :     sal_uInt16  nYear   = rDate.GetYear();
    1342                 :            :     sal_uInt16  nYearLen;
    1343                 :            : 
    1344                 :            :     if ( sal_True /* IsDateCentury() */ )
    1345                 :        107 :         nYearLen = 4;
    1346                 :            :     else
    1347                 :            :     {
    1348                 :            :         nYearLen = 2;
    1349                 :            :         nYear %= 100;
    1350                 :            :     }
    1351                 :            : 
    1352      [ -  +  - ]:        107 :     switch ( getDateFormat() )
                 [ +  - ]
    1353                 :            :     {
    1354                 :            :         case DMY :
    1355                 :          0 :             pBuf = ImplAdd2UNum( pBuf, nDay, sal_True /* IsDateDayLeadingZero() */ );
    1356         [ #  # ]:          0 :             pBuf = ImplAddString( pBuf, getDateSep() );
    1357                 :          0 :             pBuf = ImplAdd2UNum( pBuf, nMonth, sal_True /* IsDateMonthLeadingZero() */ );
    1358         [ #  # ]:          0 :             pBuf = ImplAddString( pBuf, getDateSep() );
    1359                 :          0 :             pBuf = ImplAddUNum( pBuf, nYear, nYearLen );
    1360                 :          0 :         break;
    1361                 :            :         case MDY :
    1362                 :        107 :             pBuf = ImplAdd2UNum( pBuf, nMonth, sal_True /* IsDateMonthLeadingZero() */ );
    1363         [ +  - ]:        107 :             pBuf = ImplAddString( pBuf, getDateSep() );
    1364                 :        107 :             pBuf = ImplAdd2UNum( pBuf, nDay, sal_True /* IsDateDayLeadingZero() */ );
    1365         [ +  - ]:        107 :             pBuf = ImplAddString( pBuf, getDateSep() );
    1366                 :        107 :             pBuf = ImplAddUNum( pBuf, nYear, nYearLen );
    1367                 :        107 :         break;
    1368                 :            :         default:
    1369                 :          0 :             pBuf = ImplAddUNum( pBuf, nYear, nYearLen );
    1370         [ #  # ]:          0 :             pBuf = ImplAddString( pBuf, getDateSep() );
    1371                 :          0 :             pBuf = ImplAdd2UNum( pBuf, nMonth, sal_True /* IsDateMonthLeadingZero() */ );
    1372         [ #  # ]:          0 :             pBuf = ImplAddString( pBuf, getDateSep() );
    1373                 :          0 :             pBuf = ImplAdd2UNum( pBuf, nDay, sal_True /* IsDateDayLeadingZero() */ );
    1374                 :            :     }
    1375                 :            : 
    1376         [ +  - ]:        107 :     return rtl::OUString(aBuf, pBuf-aBuf);
    1377                 :            : }
    1378                 :            : 
    1379                 :            : 
    1380                 :        450 : rtl::OUString LocaleDataWrapper::getTime( const Time& rTime, sal_Bool bSec, sal_Bool b100Sec ) const
    1381                 :            : {
    1382         [ +  - ]:        450 :     ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical );
    1383                 :            : //!TODO: leading zeros et al
    1384                 :            :     sal_Unicode aBuf[128];
    1385                 :        450 :     sal_Unicode* pBuf = aBuf;
    1386                 :        450 :     sal_uInt16  nHour = rTime.GetHour();
    1387                 :        450 :     sal_Bool bHour12 = sal_False;   //!TODO: AM/PM from default time format code
    1388                 :            : 
    1389         [ -  + ]:        450 :     if ( bHour12 )
    1390                 :            :     {
    1391                 :          0 :         nHour %= 12;
    1392                 :            :         // 0:00 -> 12:00
    1393         [ #  # ]:          0 :         if ( !nHour )
    1394                 :          0 :             nHour = 12;
    1395                 :            :     }
    1396                 :            :     else
    1397                 :        450 :         nHour %= 24;
    1398                 :            : 
    1399                 :        450 :     pBuf = ImplAdd2UNum( pBuf, nHour, sal_True /* IsTimeLeadingZero() */ );
    1400         [ +  - ]:        450 :     pBuf = ImplAddString( pBuf, getTimeSep() );
    1401                 :        450 :     pBuf = ImplAdd2UNum( pBuf, rTime.GetMin(), sal_True );
    1402         [ +  + ]:        450 :     if ( bSec )
    1403                 :            :     {
    1404         [ +  - ]:        130 :         pBuf = ImplAddString( pBuf, getTimeSep() );
    1405                 :        130 :         pBuf = ImplAdd2UNum( pBuf, rTime.GetSec(), sal_True );
    1406                 :            : 
    1407         [ -  + ]:        130 :         if ( b100Sec )
    1408                 :            :         {
    1409         [ #  # ]:          0 :             pBuf = ImplAddString( pBuf, getTime100SecSep() );
    1410                 :          0 :             pBuf = ImplAdd2UNum( pBuf, rTime.Get100Sec(), sal_True );
    1411                 :            :         }
    1412                 :            :     }
    1413                 :            : 
    1414                 :        450 :     rtl::OUString aStr(aBuf, pBuf - aBuf);
    1415                 :            : 
    1416         [ -  + ]:        450 :     if ( bHour12 )
    1417                 :            :     {
    1418         [ #  # ]:          0 :         if ( (rTime.GetHour() % 24) >= 12 )
    1419         [ #  # ]:          0 :             aStr += getTimePM();
    1420                 :            :         else
    1421         [ #  # ]:          0 :             aStr += getTimeAM();
    1422                 :            :     }
    1423                 :            : 
    1424         [ +  - ]:        450 :     return aStr;
    1425                 :            : }
    1426                 :            : 
    1427                 :            : 
    1428                 :         95 : rtl::OUString LocaleDataWrapper::getLongDate( const Date& rDate, CalendarWrapper& rCal,
    1429                 :            :         sal_Int16 nDisplayDayOfWeek, sal_Bool bDayOfMonthWithLeadingZero,
    1430                 :            :         sal_Int16 nDisplayMonth, sal_Bool bTwoDigitYear ) const
    1431                 :            : {
    1432         [ +  - ]:         95 :     ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical );
    1433                 :            :     using namespace ::com::sun::star::i18n;
    1434                 :            :     sal_Unicode     aBuf[20];
    1435                 :            :     sal_Unicode*    pBuf;
    1436         [ +  - ]:         95 :     String aStr;
    1437                 :            :     sal_Int16 nVal;
    1438         [ +  - ]:         95 :     rCal.setGregorianDateTime( rDate );
    1439                 :            :     // day of week
    1440         [ +  - ]:         95 :     nVal = rCal.getValue( CalendarFieldIndex::DAY_OF_WEEK );
    1441 [ +  - ][ +  - ]:         95 :     aStr += rCal.getDisplayName( CalendarDisplayIndex::DAY, nVal, nDisplayDayOfWeek );
                 [ +  - ]
    1442 [ +  - ][ +  - ]:         95 :     aStr += getLongDateDayOfWeekSep();
    1443                 :            :     // day of month
    1444         [ +  - ]:         95 :     nVal = rCal.getValue( CalendarFieldIndex::DAY_OF_MONTH );
    1445                 :         95 :     pBuf = ImplAdd2UNum( aBuf, nVal, bDayOfMonthWithLeadingZero );
    1446                 :         95 :     rtl::OUString aDay(aBuf, pBuf-aBuf);
    1447                 :            :     // month of year
    1448         [ +  - ]:         95 :     nVal = rCal.getValue( CalendarFieldIndex::MONTH );
    1449 [ +  - ][ +  - ]:         95 :     rtl::OUString aMonth( rCal.getDisplayName( CalendarDisplayIndex::MONTH, nVal, nDisplayMonth ) );
                 [ +  - ]
    1450                 :            :     // year
    1451         [ +  - ]:         95 :     nVal = rCal.getValue( CalendarFieldIndex::YEAR );
    1452         [ -  + ]:         95 :     if ( bTwoDigitYear )
    1453                 :          0 :         pBuf = ImplAddUNum( aBuf, nVal % 100, 2 );
    1454                 :            :     else
    1455                 :         95 :         pBuf = ImplAddUNum( aBuf, nVal );
    1456                 :         95 :     rtl::OUString aYear(aBuf, pBuf-aBuf);
    1457                 :            :     // concatenate
    1458      [ -  +  - ]:         95 :     switch ( getLongDateFormat() )
                 [ +  - ]
    1459                 :            :     {
    1460                 :            :         case DMY :
    1461         [ #  # ]:          0 :             aStr += aDay;
    1462 [ #  # ][ #  # ]:          0 :             aStr += getLongDateDaySep();
    1463         [ #  # ]:          0 :             aStr += aMonth;
    1464 [ #  # ][ #  # ]:          0 :             aStr += getLongDateMonthSep();
    1465         [ #  # ]:          0 :             aStr += aYear;
    1466                 :          0 :         break;
    1467                 :            :         case MDY :
    1468         [ +  - ]:         95 :             aStr += aMonth;
    1469 [ +  - ][ +  - ]:         95 :             aStr += getLongDateMonthSep();
    1470         [ +  - ]:         95 :             aStr += aDay;
    1471 [ +  - ][ +  - ]:         95 :             aStr += getLongDateDaySep();
    1472         [ +  - ]:         95 :             aStr += aYear;
    1473                 :         95 :         break;
    1474                 :            :         default:    // YMD
    1475         [ #  # ]:          0 :             aStr += aYear;
    1476 [ #  # ][ #  # ]:          0 :             aStr += getLongDateYearSep();
    1477         [ #  # ]:          0 :             aStr += aMonth;
    1478 [ #  # ][ #  # ]:          0 :             aStr += getLongDateMonthSep();
    1479         [ #  # ]:          0 :             aStr += aDay;
    1480                 :            :     }
    1481 [ +  - ][ +  - ]:         95 :     return aStr;
                 [ +  - ]
    1482                 :            : }
    1483                 :            : 
    1484                 :            : 
    1485                 :         12 : rtl::OUString LocaleDataWrapper::getDuration( const Time& rTime, sal_Bool bSec, sal_Bool b100Sec ) const
    1486                 :            : {
    1487         [ +  - ]:         12 :     ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical );
    1488                 :            :     sal_Unicode aBuf[128];
    1489                 :         12 :     sal_Unicode* pBuf = aBuf;
    1490                 :            : 
    1491         [ -  + ]:         12 :     if ( rTime < Time( 0 ) )
    1492                 :          0 :         pBuf = ImplAddString( pBuf, ' ' );
    1493                 :            : 
    1494                 :            :     if ( sal_True /* IsTimeLeadingZero() */ )
    1495                 :         12 :         pBuf = ImplAddUNum( pBuf, rTime.GetHour(), 2 );
    1496                 :            :     else
    1497                 :            :         pBuf = ImplAddUNum( pBuf, rTime.GetHour() );
    1498         [ +  - ]:         12 :     pBuf = ImplAddString( pBuf, getTimeSep() );
    1499                 :         12 :     pBuf = ImplAdd2UNum( pBuf, rTime.GetMin(), sal_True );
    1500         [ +  + ]:         12 :     if ( bSec )
    1501                 :            :     {
    1502         [ +  - ]:          2 :         pBuf = ImplAddString( pBuf, getTimeSep() );
    1503                 :          2 :         pBuf = ImplAdd2UNum( pBuf, rTime.GetSec(), sal_True );
    1504                 :            : 
    1505         [ -  + ]:          2 :         if ( b100Sec )
    1506                 :            :         {
    1507         [ #  # ]:          0 :             pBuf = ImplAddString( pBuf, getTime100SecSep() );
    1508                 :          0 :             pBuf = ImplAdd2UNum( pBuf, rTime.Get100Sec(), sal_True );
    1509                 :            :         }
    1510                 :            :     }
    1511                 :            : 
    1512         [ +  - ]:         12 :     return rtl::OUString(aBuf, pBuf-aBuf);
    1513                 :            : }
    1514                 :            : 
    1515                 :            : 
    1516                 :            : // --- simple number formatting ---------------------------------------
    1517                 :            : 
    1518                 :      38345 : inline size_t ImplGetNumberStringLengthGuess( const LocaleDataWrapper& rLoc, sal_uInt16 nDecimals )
    1519                 :            : {
    1520                 :            :     // approximately 3.2 bits per digit
    1521                 :      38345 :     const size_t nDig = ((sizeof(sal_Int64) * 8) / 3) + 1;
    1522                 :            :     // digits, separators (pessimized for insane "every digit may be grouped"), leading zero, sign
    1523                 :            :     size_t nGuess = ((nDecimals < nDig) ?
    1524                 :      38345 :         (((nDig - nDecimals) * rLoc.getNumThousandSep().getLength()) + nDig) :
    1525         [ +  - ]:      76690 :         nDecimals) + rLoc.getNumDecimalSep().getLength() + 3;
    1526                 :      38345 :     return nGuess;
    1527                 :            : }
    1528                 :            : 
    1529                 :            : 
    1530                 :      38345 : rtl::OUString LocaleDataWrapper::getNum( sal_Int64 nNumber, sal_uInt16 nDecimals,
    1531                 :            :         sal_Bool bUseThousandSep, sal_Bool bTrailingZeros ) const
    1532                 :            : {
    1533         [ +  - ]:      38345 :     ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical );
    1534                 :            :     sal_Unicode aBuf[128];      // big enough for 64-bit long and crazy grouping
    1535                 :            :     // check if digits and separators will fit into fixed buffer or allocate
    1536         [ +  - ]:      38345 :     size_t nGuess = ImplGetNumberStringLengthGuess( *this, nDecimals );
    1537                 :            :     sal_Unicode* const pBuffer = (nGuess < 118 ? aBuf :
    1538 [ +  - ][ #  # ]:      38345 :         new sal_Unicode[nGuess + 16]);
    1539                 :            : 
    1540                 :            :     sal_Unicode* pBuf = ImplAddFormatNum( pBuffer, nNumber, nDecimals,
    1541         [ +  - ]:      38345 :         bUseThousandSep, bTrailingZeros );
    1542                 :      38345 :     rtl::OUString aStr(pBuffer, pBuf-pBuffer);
    1543                 :            : 
    1544         [ -  + ]:      38345 :     if ( pBuffer != aBuf )
    1545         [ #  # ]:          0 :         delete [] pBuffer;
    1546         [ +  - ]:      38345 :     return aStr;
    1547                 :            : }
    1548                 :            : 
    1549                 :          0 : rtl::OUString LocaleDataWrapper::getCurr( sal_Int64 nNumber, sal_uInt16 nDecimals,
    1550                 :            :         const rtl::OUString& rCurrencySymbol, sal_Bool bUseThousandSep ) const
    1551                 :            : {
    1552         [ #  # ]:          0 :     ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical );
    1553                 :            :     sal_Unicode aBuf[192];
    1554                 :            :     sal_Unicode aNumBuf[128];    // big enough for 64-bit long and crazy grouping
    1555                 :          0 :     sal_Unicode cZeroChar = getCurrZeroChar();
    1556                 :            : 
    1557                 :            :     // check if digits and separators will fit into fixed buffer or allocate
    1558         [ #  # ]:          0 :     size_t nGuess = ImplGetNumberStringLengthGuess( *this, nDecimals );
    1559                 :            :     sal_Unicode* const pNumBuffer = (nGuess < 118 ? aNumBuf :
    1560 [ #  # ][ #  # ]:          0 :         new sal_Unicode[nGuess + 16]);
    1561                 :            : 
    1562                 :            :     sal_Unicode* const pBuffer =
    1563                 :          0 :         ((size_t(rCurrencySymbol.getLength()) + nGuess + 20) < SAL_N_ELEMENTS(aBuf) ? aBuf :
    1564 [ #  # ][ #  # ]:          0 :         new sal_Unicode[ rCurrencySymbol.getLength() + nGuess + 20 ]);
    1565                 :          0 :     sal_Unicode* pBuf = pBuffer;
    1566                 :            : 
    1567                 :            :     sal_Bool bNeg;
    1568         [ #  # ]:          0 :     if ( nNumber < 0 )
    1569                 :            :     {
    1570                 :          0 :         bNeg = sal_True;
    1571                 :          0 :         nNumber *= -1;
    1572                 :            :     }
    1573                 :            :     else
    1574                 :          0 :         bNeg = sal_False;
    1575                 :            : 
    1576                 :            :     // convert number
    1577                 :            :     sal_Unicode* pEndNumBuf = ImplAddFormatNum( pNumBuffer, nNumber, nDecimals,
    1578         [ #  # ]:          0 :         bUseThousandSep, sal_True );
    1579                 :          0 :     xub_StrLen nNumLen = (xub_StrLen)(sal_uLong)(pEndNumBuf-pNumBuffer);
    1580                 :            : 
    1581                 :            :     // replace zeros with zero character
    1582 [ #  # ][ #  # ]:          0 :     if ( (cZeroChar != '0') && nDecimals /* && IsNumTrailingZeros() */ )
    1583                 :            :     {
    1584                 :            :         sal_Unicode* pTempBuf;
    1585                 :            :         sal_uInt16  i;
    1586                 :          0 :         sal_Bool    bZero = sal_True;
    1587                 :            : 
    1588                 :          0 :         pTempBuf = pNumBuffer+nNumLen-nDecimals;
    1589                 :          0 :         i = 0;
    1590         [ #  # ]:          0 :         do
    1591                 :            :         {
    1592         [ #  # ]:          0 :             if ( *pTempBuf != '0' )
    1593                 :            :             {
    1594                 :          0 :                 bZero = sal_False;
    1595                 :          0 :                 break;
    1596                 :            :             }
    1597                 :            : 
    1598                 :          0 :             pTempBuf++;
    1599                 :          0 :             i++;
    1600                 :            :         }
    1601                 :            :         while ( i < nDecimals );
    1602                 :            : 
    1603         [ #  # ]:          0 :         if ( bZero )
    1604                 :            :         {
    1605                 :          0 :             pTempBuf = pNumBuffer+nNumLen-nDecimals;
    1606                 :          0 :             i = 0;
    1607         [ #  # ]:          0 :             do
    1608                 :            :             {
    1609                 :          0 :                 *pTempBuf = cZeroChar;
    1610                 :          0 :                 pTempBuf++;
    1611                 :          0 :                 i++;
    1612                 :            :             }
    1613                 :            :             while ( i < nDecimals );
    1614                 :            :         }
    1615                 :            :     }
    1616                 :            : 
    1617         [ #  # ]:          0 :     if ( !bNeg )
    1618                 :            :     {
    1619 [ #  # ][ #  #  :          0 :         switch( getCurrPositiveFormat() )
                #  #  # ]
    1620                 :            :         {
    1621                 :            :             case 0:
    1622                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1623                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1624                 :          0 :                 break;
    1625                 :            :             case 1:
    1626                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1627                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1628                 :          0 :                 break;
    1629                 :            :             case 2:
    1630                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1631                 :          0 :                 pBuf = ImplAddString( pBuf, ' ' );
    1632                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1633                 :          0 :                 break;
    1634                 :            :             case 3:
    1635                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1636                 :          0 :                 pBuf = ImplAddString( pBuf, ' ' );
    1637                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1638                 :          0 :                 break;
    1639                 :            :         }
    1640                 :            :     }
    1641                 :            :     else
    1642                 :            :     {
    1643 [ #  # ][ #  #  :          0 :         switch( getCurrNegativeFormat() )
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1644                 :            :         {
    1645                 :            :             case 0:
    1646                 :          0 :                 pBuf = ImplAddString( pBuf, '(' );
    1647                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1648                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1649                 :          0 :                 pBuf = ImplAddString( pBuf, ')' );
    1650                 :          0 :                 break;
    1651                 :            :             case 1:
    1652                 :          0 :                 pBuf = ImplAddString( pBuf, '-' );
    1653                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1654                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1655                 :          0 :                 break;
    1656                 :            :             case 2:
    1657                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1658                 :          0 :                 pBuf = ImplAddString( pBuf, '-' );
    1659                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1660                 :          0 :                 break;
    1661                 :            :             case 3:
    1662                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1663                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1664                 :          0 :                 pBuf = ImplAddString( pBuf, '-' );
    1665                 :          0 :                 break;
    1666                 :            :             case 4:
    1667                 :          0 :                 pBuf = ImplAddString( pBuf, '(' );
    1668                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1669                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1670                 :          0 :                 pBuf = ImplAddString( pBuf, ')' );
    1671                 :          0 :                 break;
    1672                 :            :             case 5:
    1673                 :          0 :                 pBuf = ImplAddString( pBuf, '-' );
    1674                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1675                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1676                 :          0 :                 break;
    1677                 :            :             case 6:
    1678                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1679                 :          0 :                 pBuf = ImplAddString( pBuf, '-' );
    1680                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1681                 :          0 :                 break;
    1682                 :            :             case 7:
    1683                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1684                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1685                 :          0 :                 pBuf = ImplAddString( pBuf, '-' );
    1686                 :          0 :                 break;
    1687                 :            :             case 8:
    1688                 :          0 :                 pBuf = ImplAddString( pBuf, '-' );
    1689                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1690                 :          0 :                 pBuf = ImplAddString( pBuf, ' ' );
    1691                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1692                 :          0 :                 break;
    1693                 :            :             case 9:
    1694                 :          0 :                 pBuf = ImplAddString( pBuf, '-' );
    1695                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1696                 :          0 :                 pBuf = ImplAddString( pBuf, ' ' );
    1697                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1698                 :          0 :                 break;
    1699                 :            :             case 10:
    1700                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1701                 :          0 :                 pBuf = ImplAddString( pBuf, ' ' );
    1702                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1703                 :          0 :                 pBuf = ImplAddString( pBuf, '-' );
    1704                 :          0 :                 break;
    1705                 :            :             case 11:
    1706                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1707                 :          0 :                 pBuf = ImplAddString( pBuf, ' ' );
    1708                 :          0 :                 pBuf = ImplAddString( pBuf, '-' );
    1709                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1710                 :          0 :                 break;
    1711                 :            :             case 12:
    1712                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1713                 :          0 :                 pBuf = ImplAddString( pBuf, ' ' );
    1714                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1715                 :          0 :                 pBuf = ImplAddString( pBuf, '-' );
    1716                 :          0 :                 break;
    1717                 :            :             case 13:
    1718                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1719                 :          0 :                 pBuf = ImplAddString( pBuf, '-' );
    1720                 :          0 :                 pBuf = ImplAddString( pBuf, ' ' );
    1721                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1722                 :          0 :                 break;
    1723                 :            :             case 14:
    1724                 :          0 :                 pBuf = ImplAddString( pBuf, '(' );
    1725                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1726                 :          0 :                 pBuf = ImplAddString( pBuf, ' ' );
    1727                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1728                 :          0 :                 pBuf = ImplAddString( pBuf, ')' );
    1729                 :          0 :                 break;
    1730                 :            :             case 15:
    1731                 :          0 :                 pBuf = ImplAddString( pBuf, '(' );
    1732                 :          0 :                 pBuf = ImplAddString( pBuf, pNumBuffer, nNumLen );
    1733                 :          0 :                 pBuf = ImplAddString( pBuf, ' ' );
    1734                 :          0 :                 pBuf = ImplAddString( pBuf, rCurrencySymbol );
    1735                 :          0 :                 pBuf = ImplAddString( pBuf, ')' );
    1736                 :          0 :                 break;
    1737                 :            :         }
    1738                 :            :     }
    1739                 :            : 
    1740                 :          0 :     rtl::OUString aNumber(pBuffer, pBuf-pBuffer);
    1741                 :            : 
    1742         [ #  # ]:          0 :     if ( pBuffer != aBuf )
    1743         [ #  # ]:          0 :         delete [] pBuffer;
    1744         [ #  # ]:          0 :     if ( pNumBuffer != aNumBuf )
    1745         [ #  # ]:          0 :         delete [] pNumBuffer;
    1746                 :            : 
    1747         [ #  # ]:          0 :     return aNumber;
    1748                 :            : }
    1749                 :            : 
    1750                 :            : 
    1751                 :            : // --- mixed ----------------------------------------------------------
    1752                 :            : 
    1753                 :      73317 : ::com::sun::star::lang::Locale LocaleDataWrapper::getLoadedLocale() const
    1754                 :            : {
    1755         [ +  - ]:      73317 :     LanguageCountryInfo aLCInfo = getLanguageCountryInfo();
    1756                 :      73317 :     return lang::Locale( aLCInfo.Language, aLCInfo.Country, aLCInfo.Variant );
    1757                 :            : }
    1758                 :            : 
    1759                 :            : 
    1760                 :          0 : rtl::OUString LocaleDataWrapper::appendLocaleInfo(const rtl::OUString& rDebugMsg) const
    1761                 :            : {
    1762         [ #  # ]:          0 :     ::utl::ReadWriteGuard aGuard( aMutex, ::utl::ReadWriteGuardMode::nBlockCritical );
    1763         [ #  # ]:          0 :     rtl::OUStringBuffer aDebugMsg(rDebugMsg);
    1764         [ #  # ]:          0 :     aDebugMsg.append(static_cast<sal_Unicode>('\n'));
    1765         [ #  # ]:          0 :     aDebugMsg.append(aLocale.Language);
    1766         [ #  # ]:          0 :     aDebugMsg.append(static_cast<sal_Unicode>('_'));
    1767         [ #  # ]:          0 :     aDebugMsg.append(aLocale.Country);
    1768         [ #  # ]:          0 :     aDebugMsg.appendAscii(RTL_CONSTASCII_STRINGPARAM(" requested\n"));
    1769         [ #  # ]:          0 :     lang::Locale aLoaded = getLoadedLocale();
    1770         [ #  # ]:          0 :     aDebugMsg.append(aLoaded.Language);
    1771         [ #  # ]:          0 :     aDebugMsg.append(static_cast<sal_Unicode>('_'));
    1772         [ #  # ]:          0 :     aDebugMsg.append(aLoaded.Country);
    1773         [ #  # ]:          0 :     aDebugMsg.appendAscii(RTL_CONSTASCII_STRINGPARAM(" loaded"));
    1774 [ #  # ][ #  # ]:          0 :     return aDebugMsg.makeStringAndClear();
    1775                 :            : }
    1776                 :            : 
    1777                 :            : 
    1778                 :            : // static
    1779                 :          0 : void LocaleDataWrapper::outputCheckMessage( const rtl::OUString& rMsg )
    1780                 :            : {
    1781         [ #  # ]:          0 :     outputCheckMessage(rtl::OUStringToOString(rMsg, RTL_TEXTENCODING_UTF8).getStr());
    1782                 :          0 : }
    1783                 :            : 
    1784                 :            : 
    1785                 :            : // static
    1786                 :          0 : void LocaleDataWrapper::outputCheckMessage( const char* pStr )
    1787                 :            : {
    1788                 :          0 :     fprintf( stderr, "\n%s\n", pStr);
    1789                 :          0 :     fflush( stderr);
    1790                 :            :     OSL_TRACE("%s", pStr);
    1791                 :          0 : }
    1792                 :            : 
    1793                 :            : 
    1794                 :            : // static
    1795                 :        123 : void LocaleDataWrapper::evaluateLocaleDataChecking()
    1796                 :            : {
    1797                 :            :     // Using the rtl_Instance template here wouldn't solve all threaded write
    1798                 :            :     // accesses, since we want to assign the result to the static member
    1799                 :            :     // variable and would need to dereference the pointer returned and assign
    1800                 :            :     // the value unguarded. This is the same pattern manually coded.
    1801                 :        123 :     sal_uInt8 nCheck = nLocaleDataChecking;
    1802         [ +  - ]:        123 :     if (!nCheck)
    1803                 :            :     {
    1804 [ +  - ][ +  - ]:        123 :         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex());
    1805                 :        123 :         nCheck = nLocaleDataChecking;
    1806         [ +  - ]:        123 :         if (!nCheck)
    1807                 :            :         {
    1808                 :            : #ifdef DBG_UTIL
    1809                 :            :             nCheck = 1;
    1810                 :            : #else
    1811                 :        123 :             const char* pEnv = getenv( "OOO_ENABLE_LOCALE_DATA_CHECKS");
    1812 [ #  # ][ #  # ]:        123 :             if (pEnv && (pEnv[0] == 'Y' || pEnv[0] == 'y' || pEnv[0] == '1'))
         [ #  # ][ -  + ]
    1813                 :          0 :                 nCheck = 1;
    1814                 :            :             else
    1815                 :        123 :                 nCheck = 2;
    1816                 :            : #endif
    1817                 :            :             OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
    1818                 :        123 :             nLocaleDataChecking = nCheck;
    1819         [ +  - ]:        123 :         }
    1820                 :            :     }
    1821                 :            :     else {
    1822                 :            :         OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
    1823                 :            :     }
    1824                 :        123 : }
    1825                 :            : 
    1826                 :            : 
    1827                 :            : // --- XLocaleData3 ----------------------------------------------------------
    1828                 :            : 
    1829                 :         51 : ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Calendar2 > LocaleDataWrapper::getAllCalendars() const
    1830                 :            : {
    1831                 :            :     try
    1832                 :            :     {
    1833         [ +  - ]:         51 :         if ( xLD.is() )
    1834 [ +  - ][ +  - ]:         51 :             return xLD->getAllCalendars2( getLocale() );
                 [ +  - ]
    1835                 :            :     }
    1836                 :          0 :     catch (const Exception& e)
    1837                 :            :     {
    1838                 :            :         SAL_WARN( "unotools.i18n", "getAllCalendars: Exception caught " << e.Message );
    1839                 :            :     }
    1840         [ #  # ]:         51 :     return ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::Calendar2 >(0);
    1841                 :            : }
    1842                 :            : 
    1843                 :            : 
    1844                 :            : // --- XLocaleData4 ----------------------------------------------------------
    1845                 :            : 
    1846                 :         54 : ::com::sun::star::uno::Sequence< ::rtl::OUString > LocaleDataWrapper::getDateAcceptancePatterns() const
    1847                 :            : {
    1848                 :            :     try
    1849                 :            :     {
    1850         [ +  - ]:         54 :         if ( xLD.is() )
    1851 [ +  - ][ +  - ]:         54 :             return xLD->getDateAcceptancePatterns( getLocale() );
                 [ +  - ]
    1852                 :            :     }
    1853                 :          0 :     catch (const Exception& e)
    1854                 :            :     {
    1855                 :            :         SAL_WARN( "unotools.i18n", "getDateAcceptancePatterns: Exception caught " << e.Message );
    1856                 :            :     }
    1857         [ #  # ]:         54 :     return ::com::sun::star::uno::Sequence< ::rtl::OUString >(0);
    1858                 :            : }
    1859                 :            : 
    1860                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10