Back to index

lightning-sunbird  0.9+nobinonly
nsOS2Locale.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Mozilla OS/2 libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * John Fairhurst, <john_fairhurst@iname.com>.
00018  * Portions created by the Initial Developer are Copyright (C) 1999
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either of the GNU General Public License Version 2 or later (the "GPL"),
00025  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK *****
00036  * This Original Code has been modified by IBM Corporation.
00037  * Modifications made by IBM described herein are
00038  * Copyright (c) International Business Machines
00039  * Corporation, 2000
00040  *
00041  * Modifications to Mozilla code or documentation
00042  * identified per MPL Section 3.3
00043  *
00044  * Date             Modified by     Description of modification
00045  *
00046  * 07/05/2000       IBM Corp.      renamed file to nsOS2Locale.cpp from ns LocaleOS2.cpp
00047  *                                 added implementation for GetPlatformLocale, and GetXPlatformLocale using Unix model
00048  *                                 created ParseLocaleString method
00049  */
00050 
00051 #include "nsISupports.h"
00052 #include "nscore.h"
00053 #include "nsString.h"
00054 #include "nsILocale.h"
00055 #include "nsOS2Locale.h"
00056 #include "nsLocaleCID.h"
00057 #include "prprf.h"
00058 #include "nsReadableUtils.h"
00059 #include <unidef.h>
00060 
00061 extern "C" {
00062 #include <callconv.h>
00063 int APIENTRY UniQueryLocaleValue ( const LocaleObject locale_object,
00064                                    LocaleItem item,
00065                                   int *info_item);
00066 }
00067 
00068 /* nsOS2Locale ISupports */
00069 NS_IMPL_ISUPPORTS1(nsOS2Locale,nsIOS2Locale)
00070 
00071 nsOS2Locale::nsOS2Locale(void)
00072 {
00073 }
00074 
00075 nsOS2Locale::~nsOS2Locale(void)
00076 {
00077 
00078 }
00079 
00080 /* Workaround for GCC problem */
00081 #ifndef LOCI_sName
00082 #define LOCI_sName ((LocaleItem)100)
00083 #endif
00084 
00085 NS_IMETHODIMP 
00086 nsOS2Locale::GetPlatformLocale(const nsAString& locale, PULONG os2Codepage)
00087 {
00088   LocaleObject locObj = NULL;
00089   int codePage;
00090   nsAutoString tempLocale(locale);
00091   tempLocale.ReplaceChar('-', '_');
00092 
00093  
00094   int  ret = UniCreateLocaleObject(UNI_UCS_STRING_POINTER, (UniChar *)PromiseFlatString(tempLocale).get(), &locObj);
00095   if (ret != ULS_SUCCESS)
00096     UniCreateLocaleObject(UNI_UCS_STRING_POINTER, (UniChar *)L"C", &locObj);
00097 
00098   ret = UniQueryLocaleValue(locObj, LOCI_iCodepage, &codePage);
00099   if (ret != ULS_SUCCESS)
00100     return NS_ERROR_FAILURE;
00101 
00102   if (codePage == 437) {
00103     *os2Codepage = 850;
00104   } else {
00105     *os2Codepage = codePage;
00106   }
00107   UniFreeLocaleObject(locObj);
00108 
00109   return NS_OK;
00110 }
00111 
00112 NS_IMETHODIMP
00113 nsOS2Locale::GetXPLocale(const char* os2Locale, nsAString& locale)
00114 {
00115   char  country_code[MAX_COUNTRY_CODE_LEN];
00116   char  lang_code[MAX_LANGUAGE_CODE_LEN];
00117   char  extra[MAX_EXTRA_LEN];
00118   char  os2_locale[MAX_LOCALE_LEN];
00119 
00120   if (os2Locale!=nsnull) {
00121     if (strcmp(os2Locale,"C")==0 || strcmp(os2Locale,"OS2")==0) {
00122       locale.AssignLiteral("en-US");
00123       return NS_OK;
00124     }
00125     if (!ParseLocaleString(os2Locale,lang_code,country_code,extra,'_')) {
00126 //      * locale = "x-user-defined";
00127       // use os2 if parse failed
00128       CopyASCIItoUTF16(nsDependentCString(os2Locale), locale);  
00129       return NS_OK;
00130     }
00131 
00132     if (*country_code) {
00133       if (*extra) {
00134         PR_snprintf(os2_locale,MAX_LOCALE_LEN,"%s-%s.%s",lang_code,country_code,extra);
00135       }
00136       else {
00137         PR_snprintf(os2_locale,MAX_LOCALE_LEN,"%s-%s",lang_code,country_code);
00138       }
00139     } 
00140     else {
00141       if (*extra) {
00142         PR_snprintf(os2_locale,MAX_LOCALE_LEN,"%s.%s",lang_code,extra);
00143       }
00144       else {
00145         PR_snprintf(os2_locale,MAX_LOCALE_LEN,"%s",lang_code);
00146       }
00147     }
00148 
00149     CopyASCIItoUTF16(nsDependentCString(os2_locale), locale);  
00150     return NS_OK;
00151 
00152   }
00153 
00154   return NS_ERROR_FAILURE;
00155 }
00156 
00157 // copied from nsPosixLocale::ParseLocaleString:
00158 // returns PR_FALSE/PR_TRUE depending on if it was of the form LL-CC.Extra
00159 // or possibly ll_CC_Extra (depending on the separator, which happens on OS/2
00160 PRBool
00161 nsOS2Locale::ParseLocaleString(const char* locale_string, char* language, char* country, char* extra, char separator)
00162 {
00163   const char *src = locale_string;
00164   char modifier[MAX_EXTRA_LEN+1];
00165   char *dest;
00166   int dest_space, len;
00167 
00168   *language = '\0';
00169   *country = '\0';
00170   *extra = '\0';
00171   if (strlen(locale_string) < 2) {
00172     return(PR_FALSE);
00173   }
00174 
00175   //
00176   // parse the language part
00177   //
00178   dest = language;
00179   dest_space = MAX_LANGUAGE_CODE_LEN;
00180   while ((*src) && (isalpha(*src)) && (dest_space--)) {
00181     *dest++ = tolower(*src++);
00182   }
00183   *dest = '\0';
00184   len = dest - language;
00185   if ((len != 2) && (len != 3)) {
00186     NS_ASSERTION((len == 2) || (len == 3), "language code too short");
00187     NS_ASSERTION(len < 3, "reminder: verify we can handle 3+ character language code in all parts of the system; eg: language packs");
00188     *language = '\0';
00189     return(PR_FALSE);
00190   }
00191 
00192   // check if all done
00193   if (*src == '\0') {
00194     return(PR_TRUE);
00195   }
00196 
00197   if ((*src != '_') && (*src != '-') && (*src != '.') && (*src != '@')) {
00198     NS_ASSERTION(isalpha(*src), "language code too long");
00199     NS_ASSERTION(!isalpha(*src), "unexpected language/country separator");
00200     *language = '\0';
00201     return(PR_FALSE);
00202   }
00203 
00204   //
00205   // parse the country part
00206   //
00207   if ((*src == '_') || (*src == '-')) { 
00208     src++;
00209     dest = country;
00210     dest_space = MAX_COUNTRY_CODE_LEN;
00211     while ((*src) && (isalpha(*src)) && (dest_space--)) {
00212       *dest++ = toupper(*src++);
00213     }
00214     *dest = '\0';
00215     len = dest - country;
00216     if (len != 2) {
00217       NS_ASSERTION(len == 2, "unexpected country code length");
00218       *language = '\0';
00219       *country = '\0';
00220       return(PR_FALSE);
00221     }
00222   }
00223 
00224   // check if all done
00225   if (*src == '\0') {
00226     return(PR_TRUE);
00227   }
00228 
00229   if ((*src != '.') && (*src != '@') && (*src != separator)) {
00230     NS_ASSERTION(isalpha(*src), "country code too long");
00231     NS_ASSERTION(!isalpha(*src), "unexpected country/extra separator");
00232     *language = '\0';
00233     *country = '\0';
00234     return(PR_FALSE);
00235   }
00236 
00237   //
00238   // handle the extra part
00239   //
00240   if (*src == '.') { 
00241     src++;  // move past the extra part separator
00242     dest = extra;
00243     dest_space = MAX_EXTRA_LEN;
00244     while ((*src) && (*src != '@') && (dest_space--)) {
00245       *dest++ = *src++;
00246     }
00247     *dest = '\0';
00248     len = dest - extra;
00249     if (len < 1) {
00250       NS_ASSERTION(len > 0, "found country/extra separator but no extra code");
00251       *language = '\0';
00252       *country = '\0';
00253       *extra = '\0';
00254       return(PR_FALSE);
00255     }
00256   }
00257 
00258   // check if all done
00259   if (*src == '\0') {
00260     return(PR_TRUE);
00261   }
00262 
00263   //
00264   // handle the modifier part
00265   //
00266   if ((*src == '@') || (*src == separator)) { 
00267     src++;  // move past the modifier separator
00268     NS_ASSERTION(stricmp("euro",src) == 0, "found non euro modifier");
00269     dest = modifier;
00270     dest_space = MAX_EXTRA_LEN;
00271     while ((*src) && (dest_space--)) {
00272       *dest++ = *src++;
00273     }
00274     *dest = '\0';
00275     len = dest - modifier;
00276     if (len < 1) {
00277       NS_ASSERTION(len > 0, "found modifier separator but no modifier code");
00278       *language = '\0';
00279       *country = '\0';
00280       *extra = '\0';
00281       *modifier = '\0';
00282       return(PR_FALSE);
00283     }
00284   }
00285 
00286   // check if all done
00287   if (*src == '\0') {
00288     return(PR_TRUE);
00289   }
00290 
00291   NS_ASSERTION(*src == '\0', "extra/modifier code too long");
00292   *language = '\0';
00293   *country = '\0';
00294   *extra = '\0';
00295 
00296   return(PR_FALSE);
00297 }