Back to index

lightning-sunbird  0.9+nobinonly
nsPosixLocale.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nsISupports.h"
00039 #include "nscore.h"
00040 #include "nsString.h"
00041 #include "nsILocale.h"
00042 #include "nsPosixLocale.h"
00043 #include "nsLocaleCID.h"
00044 #include "prprf.h"
00045 #include "plstr.h"
00046 #include "nsReadableUtils.h"
00047 
00048 /* nsPosixLocale ISupports */
00049 NS_IMPL_ISUPPORTS1(nsPosixLocale, nsIPosixLocale)
00050 
00051 nsPosixLocale::nsPosixLocale(void)
00052 {
00053 }
00054 
00055 nsPosixLocale::~nsPosixLocale(void)
00056 {
00057 
00058 }
00059 
00060 NS_IMETHODIMP 
00061 nsPosixLocale::GetPlatformLocale(const nsAString& locale, nsACString& posixLocale)
00062 {
00063   char  country_code[MAX_COUNTRY_CODE_LEN+1];
00064   char  lang_code[MAX_LANGUAGE_CODE_LEN+1];
00065   char  extra[MAX_EXTRA_LEN+1];
00066   char  posix_locale[MAX_LOCALE_LEN+1];
00067   NS_LossyConvertUTF16toASCII xp_locale(locale);
00068 
00069   if (!xp_locale.IsEmpty()) {
00070     if (!ParseLocaleString(xp_locale.get(),lang_code,country_code,extra,'-')) {
00071 //      strncpy(posixLocale,"C",length);
00072       posixLocale = xp_locale;  // use xp locale if parse failed
00073       return NS_OK;
00074     }
00075 
00076     if (*country_code) {
00077       if (*extra) {
00078         PR_snprintf(posix_locale,sizeof(posix_locale),"%s_%s.%s",lang_code,country_code,extra);
00079       }
00080       else {
00081         PR_snprintf(posix_locale,sizeof(posix_locale),"%s_%s",lang_code,country_code);
00082       }
00083     }
00084     else {
00085       if (*extra) {
00086         PR_snprintf(posix_locale,sizeof(posix_locale),"%s.%s",lang_code,extra);
00087       }
00088       else {
00089         PR_snprintf(posix_locale,sizeof(posix_locale),"%s",lang_code);
00090       }
00091     }
00092 
00093     posixLocale = posix_locale;
00094     return NS_OK;
00095   }
00096 
00097   return NS_ERROR_FAILURE;
00098 }
00099 
00100 NS_IMETHODIMP
00101 nsPosixLocale::GetXPLocale(const char* posixLocale, nsAString& locale)
00102 {
00103   char  country_code[MAX_COUNTRY_CODE_LEN+1];
00104   char  lang_code[MAX_LANGUAGE_CODE_LEN+1];
00105   char  extra[MAX_EXTRA_LEN+1];
00106   char  posix_locale[MAX_LOCALE_LEN+1];
00107 
00108   if (posixLocale!=nsnull) {
00109     if (strcmp(posixLocale,"C")==0 || strcmp(posixLocale,"POSIX")==0) {
00110       locale.AssignLiteral("en-US");
00111       return NS_OK;
00112     }
00113     if (!ParseLocaleString(posixLocale,lang_code,country_code,extra,'_')) {
00114 //      * locale = "x-user-defined";
00115       // use posix if parse failed
00116       CopyASCIItoUTF16(nsDependentCString(posixLocale), locale);
00117       return NS_OK;
00118     }
00119 
00120     if (*country_code) {
00121       PR_snprintf(posix_locale,sizeof(posix_locale),"%s-%s",lang_code,country_code);
00122     } 
00123     else {
00124       PR_snprintf(posix_locale,sizeof(posix_locale),"%s",lang_code);
00125     }
00126 
00127     CopyASCIItoUTF16(nsDependentCString(posix_locale), locale);
00128     return NS_OK;
00129 
00130   }
00131 
00132     return NS_ERROR_FAILURE;
00133 
00134 }
00135 
00136 //
00137 // returns PR_FALSE/PR_TRUE depending on if it was of the form LL-CC.Extra
00138 PRBool
00139 nsPosixLocale::ParseLocaleString(const char* locale_string, char* language, char* country, char* extra, char separator)
00140 {
00141   const char *src = locale_string;
00142   char modifier[MAX_EXTRA_LEN+1];
00143   char *dest;
00144   int dest_space, len;
00145 
00146   *language = '\0';
00147   *country = '\0';
00148   *extra = '\0';
00149   if (strlen(locale_string) < 2) {
00150     return(PR_FALSE);
00151   }
00152 
00153   //
00154   // parse the language part
00155   //
00156   dest = language;
00157   dest_space = MAX_LANGUAGE_CODE_LEN;
00158   while ((*src) && (isalpha(*src)) && (dest_space--)) {
00159     *dest++ = tolower(*src++);
00160   }
00161   *dest = '\0';
00162   len = dest - language;
00163   if ((len != 2) && (len != 3)) {
00164     NS_ASSERTION((len == 2) || (len == 3), "language code too short");
00165     NS_ASSERTION(len < 3, "reminder: verify we can handle 3+ character language code in all parts of the system; eg: language packs");
00166     *language = '\0';
00167     return(PR_FALSE);
00168   }
00169 
00170   // check if all done
00171   if (*src == '\0') {
00172     return(PR_TRUE);
00173   }
00174 
00175   if ((*src != '_') && (*src != '-') && (*src != '.') && (*src != '@')) {
00176     NS_ASSERTION(isalpha(*src), "language code too long");
00177     NS_ASSERTION(!isalpha(*src), "unexpected language/country separator");
00178     *language = '\0';
00179     return(PR_FALSE);
00180   }
00181 
00182   //
00183   // parse the country part
00184   //
00185   if ((*src == '_') || (*src == '-')) { 
00186     src++;
00187     dest = country;
00188     dest_space = MAX_COUNTRY_CODE_LEN;
00189     while ((*src) && (isalpha(*src)) && (dest_space--)) {
00190       *dest++ = toupper(*src++);
00191     }
00192     *dest = '\0';
00193     len = dest - country;
00194     if (len != 2) {
00195       NS_ASSERTION(len == 2, "unexpected country code length");
00196       *language = '\0';
00197       *country = '\0';
00198       return(PR_FALSE);
00199     }
00200   }
00201 
00202   // check if all done
00203   if (*src == '\0') {
00204     return(PR_TRUE);
00205   }
00206 
00207   if ((*src != '.') && (*src != '@')) {
00208     NS_ASSERTION(isalpha(*src), "country code too long");
00209     NS_ASSERTION(!isalpha(*src), "unexpected country/extra separator");
00210     *language = '\0';
00211     *country = '\0';
00212     return(PR_FALSE);
00213   }
00214 
00215   //
00216   // handle the extra part
00217   //
00218   if (*src == '.') { 
00219     src++;  // move past the extra part separator
00220     dest = extra;
00221     dest_space = MAX_EXTRA_LEN;
00222     while ((*src) && (*src != '@') && (dest_space--)) {
00223       *dest++ = *src++;
00224     }
00225     *dest = '\0';
00226     len = dest - extra;
00227     if (len < 1) {
00228       NS_ASSERTION(len > 0, "found country/extra separator but no extra code");
00229       *language = '\0';
00230       *country = '\0';
00231       *extra = '\0';
00232       return(PR_FALSE);
00233     }
00234   }
00235 
00236   // check if all done
00237   if (*src == '\0') {
00238     return(PR_TRUE);
00239   }
00240 
00241   //
00242   // handle the modifier part
00243   //
00244   
00245   if (*src == '@') { 
00246     src++;  // move past the modifier separator
00247     NS_ASSERTION(strcmp("euro",src) == 0, "found non euro modifier");
00248     dest = modifier;
00249     dest_space = MAX_EXTRA_LEN;
00250     while ((*src) && (dest_space--)) {
00251       *dest++ = *src++;
00252     }
00253     *dest = '\0';
00254     len = dest - modifier;
00255     if (len < 1) {
00256       NS_ASSERTION(len > 0, "found modifier separator but no modifier code");
00257       *language = '\0';
00258       *country = '\0';
00259       *extra = '\0';
00260       *modifier = '\0';
00261       return(PR_FALSE);
00262     }
00263   }
00264 
00265   // check if all done
00266   if (*src == '\0') {
00267     return(PR_TRUE);
00268   }
00269 
00270   NS_ASSERTION(*src == '\0', "extra/modifier code too long");
00271   *language = '\0';
00272   *country = '\0';
00273   *extra = '\0';
00274 
00275   return(PR_FALSE);
00276 }
00277