LCOV - code coverage report
Current view: directory - intl/locale/src - nsLocaleService.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 120 44 36.7 %
Date: 2012-06-02 Functions: 12 10 83.3 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : #ifdef MOZ_WIDGET_QT
      39                 : #include <QString>
      40                 : #include <QtCore/QLocale>
      41                 : #endif
      42                 : 
      43                 : #include "nsCOMPtr.h"
      44                 : #include "nsAutoPtr.h"
      45                 : #include "nsILocale.h"
      46                 : #include "nsILocaleService.h"
      47                 : #include "nsLocale.h"
      48                 : #include "nsLocaleCID.h"
      49                 : #include "nsServiceManagerUtils.h"
      50                 : #include "nsReadableUtils.h"
      51                 : #include "nsCRT.h"
      52                 : #include "prprf.h"
      53                 : #include "nsTArray.h"
      54                 : 
      55                 : #include <ctype.h>
      56                 : 
      57                 : #if defined(XP_WIN)
      58                 : #  include "nsWin32Locale.h"
      59                 : #elif defined(XP_OS2)
      60                 : #  include "unidef.h"
      61                 : #  include "nsIOS2Locale.h"
      62                 : #elif defined(XP_MACOSX)
      63                 : #  include <Carbon/Carbon.h>
      64                 : #elif defined(XP_UNIX)
      65                 : #  include <locale.h>
      66                 : #  include <stdlib.h>
      67                 : #  include "nsPosixLocale.h"
      68                 : #endif
      69                 : 
      70                 : //
      71                 : // implementation constants
      72                 : const int LocaleListLength = 6;
      73                 : const char* LocaleList[LocaleListLength] = 
      74                 : {
      75                 :         NSILOCALE_COLLATE,
      76                 :         NSILOCALE_CTYPE,
      77                 :         NSILOCALE_MONETARY,
      78                 :         NSILOCALE_NUMERIC,
      79                 :         NSILOCALE_TIME,
      80                 :         NSILOCALE_MESSAGE
      81                 : };
      82                 : 
      83                 : #define NSILOCALE_MAX_ACCEPT_LANGUAGE   16
      84                 : #define NSILOCALE_MAX_ACCEPT_LENGTH             18
      85                 : 
      86                 : #if (defined(XP_UNIX) && !defined(XP_MACOSX)) || defined(XP_OS2)
      87                 : static int posix_locale_category[LocaleListLength] =
      88                 : {
      89                 :   LC_COLLATE,
      90                 :   LC_CTYPE,
      91                 :   LC_MONETARY,
      92                 :   LC_NUMERIC,
      93                 :   LC_TIME,
      94                 : #ifdef HAVE_I18N_LC_MESSAGES
      95                 :   LC_MESSAGES
      96                 : #else
      97                 :   LC_CTYPE
      98                 : #endif
      99                 : };
     100                 : #endif
     101                 : 
     102                 : //
     103                 : // nsILocaleService implementation
     104                 : //
     105                 : class nsLocaleService: public nsILocaleService {
     106                 : 
     107                 : public:
     108                 :         
     109                 :         //
     110                 :         // nsISupports
     111                 :         //
     112                 :         NS_DECL_ISUPPORTS
     113                 : 
     114                 :         //
     115                 :         // nsILocaleService
     116                 :         //
     117                 :     NS_DECL_NSILOCALESERVICE
     118                 : 
     119                 : 
     120                 :         nsLocaleService(void);
     121                 :         virtual ~nsLocaleService(void);
     122                 : 
     123                 : protected:
     124                 : 
     125                 :         nsresult SetSystemLocale(void);
     126                 :         nsresult SetApplicationLocale(void);
     127                 : 
     128                 :         nsCOMPtr<nsILocale>                               mSystemLocale;
     129                 :         nsCOMPtr<nsILocale>                               mApplicationLocale;
     130                 : 
     131                 : };
     132                 : 
     133                 : //
     134                 : // nsLocaleService methods
     135                 : //
     136              83 : nsLocaleService::nsLocaleService(void) 
     137              83 :     : mSystemLocale(0), mApplicationLocale(0)
     138                 : {
     139                 : #ifdef XP_WIN
     140                 :     nsAutoString        xpLocale;
     141                 :     //
     142                 :     // get the system LCID
     143                 :     //
     144                 :     LCID win_lcid = GetSystemDefaultLCID();
     145                 :     NS_ENSURE_TRUE(win_lcid, );
     146                 :     nsWin32Locale::GetXPLocale(win_lcid, xpLocale);
     147                 :     nsresult rv = NewLocale(xpLocale, getter_AddRefs(mSystemLocale));
     148                 :     NS_ENSURE_SUCCESS(rv, );
     149                 : 
     150                 :     //
     151                 :     // get the application LCID
     152                 :     //
     153                 :     win_lcid = GetUserDefaultLCID();
     154                 :     NS_ENSURE_TRUE(win_lcid, );
     155                 :     nsWin32Locale::GetXPLocale(win_lcid, xpLocale);
     156                 :     rv = NewLocale(xpLocale, getter_AddRefs(mApplicationLocale));
     157                 :     NS_ENSURE_SUCCESS(rv, );
     158                 : #endif
     159                 : #if defined(XP_UNIX) && !defined(XP_MACOSX)
     160             166 :     nsRefPtr<nsLocale> resultLocale(new nsLocale());
     161              83 :     NS_ENSURE_TRUE(resultLocale, );
     162                 : 
     163                 : #ifdef MOZ_WIDGET_QT
     164                 :     const char* lang = QLocale::system().name().toAscii();
     165                 : #else
     166                 :     // Get system configuration
     167              83 :     const char* lang = getenv("LANG");
     168                 : #endif
     169                 : 
     170             166 :     nsAutoString xpLocale, platformLocale;
     171             249 :     nsAutoString category, category_platform;
     172                 :     int i;
     173                 : 
     174             581 :     for( i = 0; i < LocaleListLength; i++ ) {
     175                 :         nsresult result;
     176                 :         // setlocale( , "") evaluates LC_* and LANG
     177             498 :         char* lc_temp = setlocale(posix_locale_category[i], "");
     178             498 :         CopyASCIItoUTF16(LocaleList[i], category);
     179             498 :         category_platform = category;
     180             498 :         category_platform.AppendLiteral("##PLATFORM");
     181             498 :         if (lc_temp != nsnull) {
     182             498 :             result = nsPosixLocale::GetXPLocale(lc_temp, xpLocale);
     183             498 :             CopyASCIItoUTF16(lc_temp, platformLocale);
     184                 :         } else {
     185               0 :             if ( lang == nsnull ) {
     186               0 :                 platformLocale.AssignLiteral("en_US");
     187               0 :                 result = nsPosixLocale::GetXPLocale("en-US", xpLocale);
     188                 :             } else {
     189               0 :                 CopyASCIItoUTF16(lang, platformLocale);
     190               0 :                 result = nsPosixLocale::GetXPLocale(lang, xpLocale);
     191                 :             }
     192                 :         }
     193             498 :         if (NS_FAILED(result)) {
     194                 :             return;
     195                 :         }
     196             498 :         resultLocale->AddCategory(category, xpLocale);
     197             498 :         resultLocale->AddCategory(category_platform, platformLocale);
     198                 :     }
     199              83 :     mSystemLocale = do_QueryInterface(resultLocale);
     200             166 :     mApplicationLocale = do_QueryInterface(resultLocale);
     201                 :        
     202                 : #endif // XP_UNIX
     203                 : #ifdef XP_OS2
     204                 :     nsCOMPtr<nsIOS2Locale> os2Converter = do_GetService(NS_OS2LOCALE_CONTRACTID);
     205                 :     nsAutoString xpLocale;
     206                 :     if (os2Converter) {
     207                 :         nsAutoString category;
     208                 :         int i;
     209                 : 
     210                 :         nsRefPtr<nsLocale> resultLocale(new nsLocale());
     211                 :         if ( resultLocale == NULL ) { 
     212                 :             return; 
     213                 :         }
     214                 : 
     215                 :         LocaleObject locale_object = NULL;
     216                 :         int result = UniCreateLocaleObject(UNI_UCS_STRING_POINTER,
     217                 :                                            (UniChar *)L"", &locale_object);
     218                 :         if (result != ULS_SUCCESS) {
     219                 :             int result = UniCreateLocaleObject(UNI_UCS_STRING_POINTER,
     220                 :                                                (UniChar *)L"en_US", &locale_object);
     221                 :         }
     222                 :         char* lc_temp;
     223                 :         for( i = 0; i < LocaleListLength; i++ ) {
     224                 :             lc_temp = nsnull;
     225                 :             UniQueryLocaleObject(locale_object,
     226                 :                                  posix_locale_category[i],
     227                 :                                  UNI_MBS_STRING_POINTER,
     228                 :                                  (void **)&lc_temp);
     229                 :             category.AssignASCII(LocaleList[i]);
     230                 :             nsresult result;
     231                 :             if (lc_temp != nsnull)
     232                 :                 result = os2Converter->GetXPLocale(lc_temp, xpLocale);
     233                 :             else {
     234                 :                 char* lang = getenv("LANG");
     235                 :                 if ( lang == nsnull ) {
     236                 :                     result = os2Converter->GetXPLocale("en-US", xpLocale);
     237                 :                 }
     238                 :                 else
     239                 :                     result = os2Converter->GetXPLocale(lang, xpLocale); 
     240                 :             }
     241                 :             if (NS_FAILED(result)) {
     242                 :                 UniFreeMem(lc_temp);
     243                 :                 UniFreeLocaleObject(locale_object);
     244                 :                 return;
     245                 :             }
     246                 :             resultLocale->AddCategory(category, xpLocale);
     247                 :             UniFreeMem(lc_temp);
     248                 :         }
     249                 :         UniFreeLocaleObject(locale_object);
     250                 :         mSystemLocale = do_QueryInterface(resultLocale);
     251                 :         mApplicationLocale = do_QueryInterface(resultLocale);
     252                 :     }  // if ( NS_SUCCEEDED )...
     253                 : #endif  // XP_OS2
     254                 : 
     255                 : #ifdef XP_MACOSX
     256                 :     // Get string representation of user's current locale
     257                 :     CFLocaleRef userLocaleRef = ::CFLocaleCopyCurrent();
     258                 :     CFStringRef userLocaleStr = ::CFLocaleGetIdentifier(userLocaleRef);
     259                 :     ::CFRetain(userLocaleStr);
     260                 : 
     261                 :     nsAutoTArray<UniChar, 32> buffer;
     262                 :     int size = ::CFStringGetLength(userLocaleStr);
     263                 :     if (buffer.SetLength(size + 1))
     264                 :     {
     265                 :         CFRange range = ::CFRangeMake(0, size);
     266                 :         ::CFStringGetCharacters(userLocaleStr, range, buffer.Elements());
     267                 :         buffer[size] = 0;
     268                 : 
     269                 :         // Convert the locale string to the format that Mozilla expects
     270                 :         nsAutoString xpLocale(buffer.Elements());
     271                 :         xpLocale.ReplaceChar('_', '-');
     272                 : 
     273                 :         nsresult rv = NewLocale(xpLocale, getter_AddRefs(mSystemLocale));
     274                 :         if (NS_SUCCEEDED(rv)) {
     275                 :             mApplicationLocale = mSystemLocale;
     276                 :         }
     277                 :     }
     278                 : 
     279                 :     ::CFRelease(userLocaleStr);
     280                 :     ::CFRelease(userLocaleRef);
     281                 : 
     282                 :     NS_ASSERTION(mApplicationLocale, "Failed to create locale objects");
     283                 : #endif // XP_MACOSX
     284                 : }
     285                 : 
     286             166 : nsLocaleService::~nsLocaleService(void)
     287                 : {
     288             332 : }
     289                 : 
     290            2335 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsLocaleService, nsILocaleService)
     291                 : 
     292                 : NS_IMETHODIMP
     293               0 : nsLocaleService::NewLocale(const nsAString &aLocale, nsILocale **_retval)
     294                 : {
     295                 :     nsresult result;
     296                 : 
     297               0 :     *_retval = nsnull;
     298                 : 
     299               0 :     nsRefPtr<nsLocale> resultLocale(new nsLocale());
     300               0 :     if (!resultLocale) return NS_ERROR_OUT_OF_MEMORY;
     301                 : 
     302               0 :     for (PRInt32 i = 0; i < LocaleListLength; i++) {
     303               0 :       NS_ConvertASCIItoUTF16 category(LocaleList[i]);
     304               0 :       result = resultLocale->AddCategory(category, aLocale);
     305               0 :       if (NS_FAILED(result)) return result;
     306                 : #if defined(XP_UNIX) && !defined(XP_MACOSX)
     307               0 :       category.AppendLiteral("##PLATFORM");
     308               0 :       result = resultLocale->AddCategory(category, aLocale);
     309               0 :       if (NS_FAILED(result)) return result;
     310                 : #endif
     311                 :     }
     312                 : 
     313               0 :     NS_ADDREF(*_retval = resultLocale);
     314               0 :     return NS_OK;
     315                 : }
     316                 : 
     317                 : 
     318                 : NS_IMETHODIMP
     319              12 : nsLocaleService::GetSystemLocale(nsILocale **_retval)
     320                 : {
     321              12 :         if (mSystemLocale) {
     322              12 :                 NS_ADDREF(*_retval = mSystemLocale);
     323              12 :                 return NS_OK;
     324                 :         }
     325                 : 
     326               0 :         *_retval = (nsILocale*)nsnull;
     327               0 :         return NS_ERROR_FAILURE;
     328                 : }
     329                 : 
     330                 : NS_IMETHODIMP
     331             195 : nsLocaleService::GetApplicationLocale(nsILocale **_retval)
     332                 : {
     333             195 :         if (mApplicationLocale) {
     334             195 :                 NS_ADDREF(*_retval = mApplicationLocale);
     335             195 :                 return NS_OK;
     336                 :         }
     337                 : 
     338               0 :         *_retval=(nsILocale*)nsnull;
     339               0 :         return NS_ERROR_FAILURE;
     340                 : }
     341                 : 
     342                 : NS_IMETHODIMP
     343               0 : nsLocaleService::GetLocaleFromAcceptLanguage(const char *acceptLanguage, nsILocale **_retval)
     344                 : {
     345                 :   char* input;
     346                 :   char* cPtr;
     347                 :   char* cPtr1;
     348                 :   char* cPtr2;
     349                 :   int i;
     350                 :   int j;
     351               0 :   int countLang = 0;
     352                 :   char  acceptLanguageList[NSILOCALE_MAX_ACCEPT_LANGUAGE][NSILOCALE_MAX_ACCEPT_LENGTH];
     353                 :   nsresult      result;
     354                 : 
     355               0 :   input = new char[strlen(acceptLanguage)+1];
     356               0 :   NS_ASSERTION(input!=nsnull,"nsLocaleFactory::GetLocaleFromAcceptLanguage: memory allocation failed.");
     357               0 :   if (input == (char*)NULL){ return NS_ERROR_OUT_OF_MEMORY; }
     358                 : 
     359               0 :   strcpy(input, acceptLanguage);
     360               0 :   cPtr1 = input-1;
     361               0 :   cPtr2 = input;
     362                 : 
     363                 :   /* put in standard form */
     364               0 :   while (*(++cPtr1)) {
     365               0 :     if      (isalpha(*cPtr1))  *cPtr2++ = tolower(*cPtr1); /* force lower case */
     366               0 :     else if (isspace(*cPtr1))  ;                           /* ignore any space */
     367               0 :     else if (*cPtr1=='-')      *cPtr2++ = '_';             /* "-" -> "_"       */
     368               0 :     else if (*cPtr1=='*')      ;                           /* ignore "*"       */
     369               0 :     else                       *cPtr2++ = *cPtr1;          /* else unchanged   */
     370                 :   }
     371               0 :   *cPtr2 = '\0';
     372                 : 
     373               0 :   countLang = 0;
     374                 : 
     375               0 :   if (strchr(input,';')) {
     376                 :     /* deal with the quality values */
     377                 : 
     378                 :     float qvalue[NSILOCALE_MAX_ACCEPT_LANGUAGE];
     379                 :     float qSwap;
     380               0 :     float bias = 0.0f;
     381                 :     char* ptrLanguage[NSILOCALE_MAX_ACCEPT_LANGUAGE];
     382                 :     char* ptrSwap;
     383                 : 
     384               0 :     cPtr = nsCRT::strtok(input,",",&cPtr2);
     385               0 :     while (cPtr) {
     386               0 :       qvalue[countLang] = 1.0f;
     387                 :       /* add extra parens to get rid of warning */
     388               0 :       if ((cPtr1 = strchr(cPtr,';')) != nsnull) {
     389               0 :         PR_sscanf(cPtr1,";q=%f",&qvalue[countLang]);
     390               0 :         *cPtr1 = '\0';
     391                 :       }
     392               0 :       if (strlen(cPtr)<NSILOCALE_MAX_ACCEPT_LANGUAGE) {     /* ignore if too long */
     393               0 :         qvalue[countLang] -= (bias += 0.0001f); /* to insure original order */
     394               0 :         ptrLanguage[countLang++] = cPtr;
     395               0 :         if (countLang>=NSILOCALE_MAX_ACCEPT_LANGUAGE) break; /* quit if too many */
     396                 :       }
     397               0 :       cPtr = nsCRT::strtok(cPtr2,",",&cPtr2);
     398                 :     }
     399                 : 
     400                 :     /* sort according to decending qvalue */
     401                 :     /* not a very good algorithm, but count is not likely large */
     402               0 :     for ( i=0 ; i<countLang-1 ; i++ ) {
     403               0 :       for ( j=i+1 ; j<countLang ; j++ ) {
     404               0 :         if (qvalue[i]<qvalue[j]) {
     405               0 :           qSwap     = qvalue[i];
     406               0 :           qvalue[i] = qvalue[j];
     407               0 :           qvalue[j] = qSwap;
     408               0 :           ptrSwap        = ptrLanguage[i];
     409               0 :           ptrLanguage[i] = ptrLanguage[j];
     410               0 :           ptrLanguage[j] = ptrSwap;
     411                 :         }
     412                 :       }
     413                 :     }
     414               0 :     for ( i=0 ; i<countLang ; i++ ) {
     415               0 :       PL_strncpyz(acceptLanguageList[i],ptrLanguage[i],NSILOCALE_MAX_ACCEPT_LENGTH);
     416                 :     }
     417                 : 
     418                 :   } else {
     419                 :     /* simple case: no quality values */
     420                 : 
     421               0 :     cPtr = nsCRT::strtok(input,",",&cPtr2);
     422               0 :     while (cPtr) {
     423               0 :       if (strlen(cPtr)<NSILOCALE_MAX_ACCEPT_LENGTH) {        /* ignore if too long */
     424               0 :         PL_strncpyz(acceptLanguageList[countLang++],cPtr,NSILOCALE_MAX_ACCEPT_LENGTH);
     425               0 :         if (countLang>=NSILOCALE_MAX_ACCEPT_LENGTH) break; /* quit if too many */
     426                 :       }
     427               0 :       cPtr = nsCRT::strtok(cPtr2,",",&cPtr2);
     428                 :     }
     429                 :   }
     430                 : 
     431                 :   //
     432                 :   // now create the locale 
     433                 :   //
     434               0 :   result = NS_ERROR_FAILURE;
     435               0 :   if (countLang>0) {
     436               0 :           result = NewLocale(NS_ConvertASCIItoUTF16(acceptLanguageList[0]), _retval);
     437                 :   }
     438                 : 
     439                 :   //
     440                 :   // clean up
     441                 :   //
     442               0 :   delete[] input;
     443               0 :   return result;
     444                 : }
     445                 : 
     446                 : 
     447                 : nsresult
     448              12 : nsLocaleService::GetLocaleComponentForUserAgent(nsAString& retval)
     449                 : {
     450              24 :     nsCOMPtr<nsILocale>     system_locale;
     451                 :     nsresult                result;
     452                 : 
     453              12 :     result = GetSystemLocale(getter_AddRefs(system_locale));
     454              12 :     if (NS_SUCCEEDED(result))
     455                 :     {
     456              12 :         result = system_locale->
     457              12 :                  GetCategory(NS_LITERAL_STRING(NSILOCALE_MESSAGE), retval);
     458              12 :         return result;
     459                 :     }
     460                 : 
     461               0 :     return result;
     462                 : }
     463                 : 
     464                 : 
     465                 : 
     466                 : nsresult
     467              83 : NS_NewLocaleService(nsILocaleService** result)
     468                 : {
     469              83 :   if(!result)
     470               0 :     return NS_ERROR_NULL_POINTER;
     471              83 :   *result = new nsLocaleService();
     472              83 :   if (! *result)
     473               0 :     return NS_ERROR_OUT_OF_MEMORY;
     474              83 :   NS_ADDREF(*result);
     475              83 :   return NS_OK;
     476                 : }

Generated by: LCOV version 1.7