Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

uloc.c

00001 /*
00002 **********************************************************************
00003 *   Copyright (C) 1997-2000, International Business Machines
00004 *   Corporation and others.  All Rights Reserved.
00005 **********************************************************************
00006 *
00007 * File ULOC.CPP
00008 *
00009 * Modification History:
00010 *
00011 *   Date        Name        Description
00012 *   04/01/97    aliu        Creation.
00013 *   08/21/98    stephen     JDK 1.2 sync
00014 *   12/08/98    rtg         New Locale implementation and C API
00015 *   03/15/99    damiba      overhaul.
00016 *   04/06/99    stephen     changed setDefault() to realloc and copy
00017 *   06/14/99    stephen     Changed calls to ures_open for new params
00018 *   07/21/99    stephen     Modified setDefault() to propagate to C++
00019 ******************************************************************************/
00020 
00021 
00022 #include "unicode/uloc.h"
00023 #include "unicode/locid.h"
00024 
00025 #include "unicode/utypes.h"
00026 #include "uresimp.h"
00027 #include "unicode/uchar.h"
00028 #include "umutex.h"
00029 #include "cstring.h"
00030 #include "unicode/ustring.h"
00031 #include "cmemory.h"
00032 
00033 /****************************************************************************
00034   Global variable and type definitions
00035 ******************************************************************************/
00036 
00037 /* UnicodeString stuff */
00038 typedef struct UnicodeString UnicodeString;
00039 
00040 U_CFUNC int32_t T_UnicodeString_length(const UnicodeString *s);
00041 
00042 U_CAPI int32_t
00043 T_UnicodeString_extract(const UnicodeString *s, char *dst);
00044 
00045 /* Locale stuff from locid.cpp */
00046 U_CAPI void locale_set_default(const char *id);
00047 
00048 /* These strings describe the resources we attempt to load from
00049  the locale ResourceBundle data file.*/
00050 static const char* _kLocaleString   = "LocaleString";
00051 static const char* _kShortLanguage  = "ShortLanguage";
00052 static const char* _kShortCountry   = "ShortCountry";
00053 static const char* _kLocaleID       = "LocaleID";
00054 static const char* _kLanguages      = "Languages";
00055 static const char* _kCountries      = "Countries";
00056 
00057 
00058 #define TEMPBUFSIZE 8
00059 
00060 /*Some static strings needed in the getDisplay* functions*/
00061 static const UChar openParen[] = { (UChar)0x0020 /* space */, (UChar)0x0028 /* ( */, (UChar)0x0000};
00062 static const UChar comma[] = { (UChar)0x002C /* space */, (UChar)0x0020 /* , */, (UChar)0x0000};
00063 static const UChar closeParen[] = { (UChar)0x0029 /* ( */, (UChar)0x0000};
00064 
00065 
00066 static char _defaultLocale[ULOC_FULLNAME_CAPACITY] = "en_US";
00067 static UBool _emptyDefaultLocale = TRUE;
00068 
00069 static char** _installedLocales = NULL;
00070 static int32_t _installedLocalesCount = 0;
00071 
00072 
00073 static const char _languages[] =
00074 "aa\0ab\0af\0am\0ar\0as\0ay\0az\0"
00075 "ba\0be\0bg\0bh\0bi\0bn\0bo\0br\0"
00076 "ca\0co\0cs\0cy\0da\0de\0dz\0"
00077 "el\0en\0eo\0es\0et\0eu\0fa\0fi\0fj\0fo\0fr\0fy\0"
00078 "ga\0gd\0gl\0gn\0gu\0ha\0he\0hi\0hr\0hu\0hy\0"
00079 "ia\0id\0ie\0ik\0in\0is\0it\0iu\0iw\0"
00080 "ja\0ji\0jw\0ka\0kk\0kl\0km\0kn\0ko\0ks\0ku\0ky\0"
00081 "la\0ln\0lo\0lt\0lv\0"
00082 "mg\0mi\0mk\0ml\0mn\0mo\0mr\0ms\0mt\0my\0"
00083 "na\0ne\0nl\0no\0oc\0om\0or\0"
00084 "pa\0pl\0ps\0pt\0qu\0rm\0rn\0ro\0ru\0rw\0"
00085 "sa\0sd\0sg\0sh\0si\0sk\0sl\0sm\0sn\0so\0sq\0sr\0ss\0st\0su\0sv\0sw\0"
00086 "ta\0te\0tg\0th\0ti\0tk\0tl\0tn\0to\0tr\0ts\0tt\0tw\0"
00087 "ug\0uk\0ur\0uz\0vi\0vo\0wo\0xh\0yi\0yo\0za\0zh\0zu";
00088 /* This list MUST be in sorted order, and MUST contain only two-letter codes! */
00089 
00090 static const char _languages3[] =
00091 "aar\0abk\0afr\0amh\0ara\0asm\0aym\0aze\0"
00092 "bak\0bel\0bul\0bih\0bis\0ben\0bod\0bre\0"
00093 "cat\0cos\0ces\0cym\0dan\0deu\0dzo\0"
00094 "ell\0eng\0epo\0spa\0est\0eus\0fas\0fin\0fij\0fao\0fra\0fry\0"
00095 "gai\0gdh\0glg\0grn\0guj\0hau\0heb\0hin\0hrv\0hun\0hye\0"
00096 "ina\0ind\0ile\0ipk\0ind\0isl\0ita\0iku\0heb\0"
00097 "jpn\0yid\0jaw\0kat\0kaz\0kal\0khm\0kan\0kor\0kas\0kur\0kir\0"
00098 "lat\0lin\0lao\0lit\0lav\0"
00099     "mlg\0mri\0mkd\0mal\0mon\0mol\0mar\0msa\0mlt\0mya\0"
00100 "nau\0nep\0nld\0nor\0oci\0orm\0ori\0"
00101 "pan\0pol\0pus\0por\0que\0roh\0run\0ron\0rus\0kin\0"
00102 "san\0snd\0sag\0srp\0sin\0slk\0slv\0smo\0sna\0som\0sqi\0srp\0ssw\0sot\0sun\0swe\0swa\0"
00103 "tat\0tel\0tgk\0tha\0tir\0tuk\0tgl\0tsn\0ton\0tur\0tsn\0tat\0twi\0"
00104 "uig\0ukr\0urd\0uzb\0vie\0vol\0wol\0xho\0yid\0yor\0zha\0zho\0zul";
00105 /* This list MUST contain a three-letter code for every two-letter code in the
00106    list above, and they MUST ne in the same order (i.e., the same language must
00107    be in the same place in both lists)! */
00108 
00109 static const char _countries[] =
00110 "AD\0AE\0AF\0AG\0AI\0AL\0AM\0AN\0AO\0AQ\0AR\0AS\0AT\0AU\0AW\0AZ\0"
00111 "BA\0BB\0BD\0BE\0BF\0BG\0BH\0BI\0BJ\0BM\0BN\0BO\0BR\0BS\0BT\0BV\0BW\0BY\0BZ\0"
00112 "CA\0CC\0CF\0CG\0CH\0CI\0CK\0CL\0CM\0CN\0CO\0CR\0CU\0CV\0CX\0CY\0CZ\0"
00113 "DE\0DJ\0DK\0DM\0DO\0DZ\0EC\0EE\0EG\0EH\0ER\0ES\0ET\0"
00114 "FI\0FJ\0FK\0FM\0FO\0FR\0FX\0"
00115 "GA\0GB\0GD\0GE\0GF\0GH\0GI\0GL\0GM\0GN\0GP\0GQ\0GR\0GS\0GT\0GU\0GW\0GY\0"
00116 "HK\0HM\0HN\0HR\0HT\0HU\0ID\0IE\0IL\0IN\0IO\0IQ\0IR\0IS\0IT\0"
00117 "JM\0JO\0JP\0KE\0KG\0KH\0KI\0KM\0KN\0KP\0KR\0KW\0KY\0KZ\0"
00118 "LA\0LB\0LC\0LI\0LK\0LR\0LS\0LT\0LU\0LV\0LY\0"
00119 "MA\0MC\0MD\0MG\0MH\0MK\0ML\0MM\0MN\0MO\0MP\0MQ\0MR\0MS\0MT\0MU\0MV\0MW\0MX\0MY\0MZ\0"
00120 "NA\0NC\0NE\0NF\0NG\0NI\0NL\0NO\0NP\0NR\0NU\0NZ\0OM\0"
00121 "PA\0PE\0PF\0PG\0PH\0PK\0PL\0PM\0PN\0PR\0PT\0PW\0PY\0QA\0RE\0RO\0RU\0RW\0"
00122 "SA\0SB\0SC\0SD\0SE\0SG\0SH\0SI\0SJ\0SK\0SL\0SM\0SN\0SO\0SR\0ST\0SV\0SY\0SZ\0"
00123 "TC\0TD\0TF\0TG\0TH\0TJ\0TK\0TM\0TN\0TO\0TP\0TR\0TT\0TV\0TW\0TZ\0"
00124 "UA\0UG\0UM\0US\0UY\0UZ\0VA\0VC\0VE\0VG\0VI\0VN\0VU\0"
00125 "WF\0WS\0YE\0YT\0YU\0ZA\0ZM\0ZR\0ZW";
00126 /* This list MUST be in sorted order, and MUST contain only two-letter codes! */
00127 
00128 static const char _countries3[] =
00129 "AND\0ARE\0AFG\0ATG\0AIA\0ALB\0ARM\0ANT\0AGO\0ATA\0ARG\0ASM\0AUT\0AUS\0ABW\0AZE\0"
00130 "BIH\0BRB\0BGD\0BEL\0BFA\0BGR\0BHR\0BDI\0BEN\0BMU\0BRN\0BOL\0BRA\0BHS\0BTN\0BVT\0BWA"
00131 "\0BLR\0BLZ\0"
00132 "CAN\0CCK\0CAF\0COG\0CHE\0CIV\0COK\0CHL\0CMR\0CHN\0COL\0CRI\0CUB\0CPV\0CXR\0CYP\0CZE\0"
00133 "DEU\0DJI\0DNK\0DMA\0DOM\0DZA\0ECU\0EST\0EGY\0ESH\0ERI\0ESP\0ETH\0"
00134 "FIN\0FJI\0FLK\0FSM\0FRO\0FRA\0FXX\0"
00135 "GAB\0GBR\0GRD\0GEO\0GUF\0GHA\0GIB\0GRL\0GMB\0GIN\0GLP\0GNQ\0GRC\0SGS\0GTM\0GUM"
00136 "\0GNB\0GUY\0"
00137 "HKG\0HMD\0HND\0HRV\0HTI\0HUN\0IDN\0IRL\0ISR\0IND\0IOT\0IRQ\0IRN\0ISL\0ITA\0"
00138 "JAM\0JOR\0JPN\0KEN\0KGZ\0KHM\0KIR\0COM\0KNA\0PRK\0KOR\0KWT\0CYM\0KAZ\0"
00139 "LAO\0LBN\0LCA\0LIE\0LKA\0LBR\0LSO\0LTU\0LUX\0LVA\0LBY\0"
00140 "MAR\0MCO\0MDA\0MDG\0MHL\0MKD\0MLI\0MMR\0MNG\0MAC\0MNP\0MTQ\0MRT\0MSR\0MLT\0MUS\0"
00141 "MDV\0MWI\0MEX\0MYS\0MOZ\0"
00142 "NAM\0NCL\0NER\0NFK\0NGA\0NIC\0NLD\0NOR\0NPL\0NRU\0NIU\0NZL\0OMN\0"
00143 "PAN\0PER\0PYF\0PNG\0PHL\0PAK\0POL\0SPM\0PCN\0PRI\0PRT\0PLW\0PRY\0QAT\0REU\0ROM"
00144 "\0RUS\0RWA\0"
00145 "SAU\0SLB\0SYC\0SDN\0SWE\0SGP\0SHN\0SVN\0SJM\0SVK\0SLE\0SMR\0SEN\0SOM\0SUR\0STP"
00146 "\0SLV\0SYR\0SWZ\0"
00147 "TCA\0TCD\0ATF\0TGO\0THA\0TJK\0TKL\0TKM\0TUN\0TON\0TMP\0TUR\0TTO\0TUV\0TWN\0TZA\0"
00148 "UKR\0UGA\0UMI\0USA\0URY\0UZB\0VAT\0VCT\0VEN\0VGB\0VIR\0VNM\0VUT\0"
00149 "WLF\0WSM\0YEM\0MYT\0YUG\0ZAF\0ZMB\0ZAR\0ZWE";
00150 /* This list MUST contain a three-letter code for every two-letter code in
00151    the above list, and they MUST be listed in the same order! */
00152 
00153 static char** _isoLanguages = NULL;
00154 static char** _isoCountries = NULL;
00155 
00156 /*******************************************************************************
00157   Implementation function definitions
00158 *******************************************************************************/
00159 
00160 static int16_t _findIndex(const char* list, int32_t listLength, const char* key);
00161 
00162 /*Works like strchr with '_' pr '-'*/
00163 static const char* _findCharSeparator(const char* string);
00164 
00165 /*Lazy evaluated the list of installed locales*/
00166 static void _lazyEvaluate_installedLocales(void);
00167 
00168 /*returns TRUE if a is an ID separator FALSE otherwise*/
00169 #define _isIDSeparator(a) (a == '_' || a == '-')
00170 
00171 
00172 /*******************************************************************************
00173   API function definitions
00174 *******************************************************************************/
00175 
00176 
00177 static const char* _findCharSeparator(const char* string)
00178 {
00179   if (string == NULL) return NULL;
00180   /*Keeps iterating until an ID separator is found*/
00181   while (*string && !_isIDSeparator(*string)) string++;
00182   if (*string) return string;
00183   else return NULL;
00184 }
00185 
00186 
00187 static int16_t _findIndex(const char* list, int32_t listLength, const char* key)
00188 {
00189   const char* anchor = list;
00190   const char* listEnd = anchor + listLength;
00191   UBool found = FALSE;
00192   int tokenSize = uprv_strlen(list)+1; /*gets the size of the tokens*/
00193   
00194   while (!found && list<listEnd)
00195     {
00196       if (uprv_strcmp(key, list) == 0) 
00197     {
00198       found = TRUE;
00199       break;
00200     }
00201       list += tokenSize;
00202     }
00203   if (found == TRUE) return (int16_t)((list - anchor)/tokenSize);
00204   else return -1;
00205 }
00206 
00207 const char* uloc_getDefault()
00208 {
00209   UErrorCode err = U_ZERO_ERROR;
00210   
00211   /*lazy evaluates _defaultLocale*/
00212   if (_emptyDefaultLocale) 
00213     {
00214       uloc_setDefault(NULL, &err);
00215     }
00216   
00217   return _defaultLocale;
00218 }
00219 
00220 void uloc_setDefault(const char*   newDefaultLocale,
00221              UErrorCode* err) 
00222 {
00223 
00224   if (U_FAILURE(*err))
00225       return;
00226   /* the error code isn't currently used for anything by this function*/
00227   
00228   if (newDefaultLocale == NULL) 
00229     {
00230       newDefaultLocale = uprv_getDefaultLocaleID();
00231     }
00232   
00233   umtx_lock(NULL);
00234   uprv_strncpy(_defaultLocale, newDefaultLocale, ULOC_FULLNAME_CAPACITY - 1);
00235   _defaultLocale[ULOC_FULLNAME_CAPACITY - 1] = 0;
00236   _emptyDefaultLocale = FALSE;
00237   umtx_unlock(NULL);
00238 
00239   /* propagate change to C++ */
00240   locale_set_default(newDefaultLocale);
00241 }
00242 
00243 
00244 int32_t uloc_getParent(const char*    localeID,
00245                char* parent,
00246                int32_t parentCapacity,
00247                UErrorCode* err)
00248 {
00249   int i=0;
00250   int offset = 0;
00251   int count = 0;
00252 
00253   if (U_FAILURE(*err)) return 0;
00254 
00255   if (localeID == NULL)    localeID = uloc_getDefault();
00256   
00257  
00258  while (localeID[offset]&&(count < 2))
00259     {
00260       if (_isIDSeparator(localeID[offset++])) count++;
00261     }
00262 
00263   /*finds the second IDSeparator*/
00264   while (offset && !_isIDSeparator(localeID[offset])) offset--;
00265 
00266   
00267   /*Loop updates i to the size of the parent
00268     but only copies into the buffer as much as the buffer can bare*/
00269   while (i < offset)
00270     {
00271       if (parentCapacity > i) parent[i] = localeID[i];
00272       i++;
00273     }
00274 
00275   /*Sets the error code on case of need*/
00276   if (i >= parentCapacity )
00277     {
00278       *err = U_BUFFER_OVERFLOW_ERROR;
00279     }
00280 
00281   if (parentCapacity>0)   parent[uprv_min(i,parentCapacity-1)] = '\0';
00282 
00283 
00284   return i+1;
00285 }
00286 
00287 int32_t
00288 uloc_getLanguage(const char*    localeID,
00289          char* language,
00290          int32_t languageCapacity,
00291          UErrorCode* err)
00292 {
00293   int i=0;
00294 
00295 
00296   if (U_FAILURE(*err)) return 0;
00297 
00298   if (localeID == NULL)    localeID = uloc_getDefault();
00299 
00300   /*Loop updates i to the size of the language
00301     but only copies into the buffer as much as the buffer can bare*/
00302   while ((*localeID != '\0') && !_isIDSeparator(*localeID))
00303     {
00304       if (languageCapacity > i) language[i] = (char)tolower(*localeID);
00305       i++;
00306       localeID++;
00307     }
00308 
00309   if (i >= languageCapacity )
00310     {
00311       *err = U_BUFFER_OVERFLOW_ERROR;
00312     }
00313 
00314   if (languageCapacity > 0) 
00315     {
00316       language[uprv_min(i,languageCapacity-1)] = '\0';
00317     }
00318 
00319   return i+1;
00320 }
00321 
00322 
00323 int32_t uloc_getCountry(const char* localeID,
00324             char* country,
00325             int32_t countryCapacity,
00326             UErrorCode* err) 
00327 {
00328   int i=0;
00329 
00330   if (U_FAILURE(*err)) return 0;
00331   if (localeID == NULL)    localeID = uloc_getDefault();
00332   
00333   localeID = _findCharSeparator(localeID);
00334   
00335   /*Loop updates i to the size of the language
00336     but only copies into the buffer as much as the buffer can bare*/
00337   if (localeID)
00338     {
00339       ++localeID;
00340       while ((*localeID != '\0') && !_isIDSeparator(*localeID))
00341       {
00342         if (countryCapacity > i) country[i] = (char)toupper(*localeID);
00343         i++;
00344         localeID++;
00345       }
00346     }
00347 
00348   if (i >= countryCapacity )
00349     {
00350       *err = U_BUFFER_OVERFLOW_ERROR;
00351     }
00352 
00353   if (countryCapacity > 0) {country[uprv_min(i,countryCapacity-1)] = '\0';}
00354   return i+1;
00355 }
00356 
00357 int32_t uloc_getVariant(const char* localeID,
00358                         char* variant,
00359                         int32_t variantCapacity,
00360                         UErrorCode* err) 
00361 {
00362   int i=0;
00363 
00364   if (U_FAILURE(*err)) return 0;
00365   if (localeID == NULL)    localeID = uloc_getDefault();
00366 
00367   localeID = _findCharSeparator(localeID);
00368   if (localeID)    localeID = _findCharSeparator(++localeID);
00369 
00370   if (localeID)
00371     {
00372       ++localeID;
00373       /*Loop updates i to the size of the language
00374     but only copies into the buffer as much as the buffer can bare*/
00375       while (*localeID != '\0')
00376     {
00377       if (variantCapacity > i) variant[i] = (char)toupper(*localeID);
00378       i++;
00379       localeID++;
00380     }
00381 
00382     }
00383 
00384   if (i >= variantCapacity )
00385     {
00386       *err = U_BUFFER_OVERFLOW_ERROR;
00387     }
00388 
00389 
00390   if (variantCapacity>0) {variant[uprv_min(i,variantCapacity-1)] = '\0';}
00391   return i+1;
00392 }
00393 
00394 int32_t uloc_getName(const char* localeID,
00395              char* name,
00396              int32_t nameCapacity,
00397              UErrorCode* err)  
00398 {
00399   int i= 0;
00400   int varSze = 0;
00401   int cntSze = 0;
00402   UErrorCode int_err = U_ZERO_ERROR;
00403 
00404   if (U_FAILURE(*err)) return 0;
00405   /*First we preflight the components in order to ensure a valid return value*/
00406   if (localeID == NULL)    localeID = uloc_getDefault();
00407 
00408   cntSze = uloc_getCountry(localeID, 
00409                NULL , 
00410                0,
00411                &int_err);
00412   int_err = U_ZERO_ERROR;
00413   varSze = uloc_getVariant(localeID, 
00414                NULL , 
00415                0,
00416                &int_err);
00417 
00418   int_err = U_ZERO_ERROR;
00419   i = uloc_getLanguage(localeID, 
00420                NULL,
00421                0, 
00422                &int_err);
00423   /*Adjust for the zero terminators*/
00424   --varSze; 
00425   --cntSze;
00426 
00427   if (cntSze) i++;
00428   if (varSze) i++;
00429   i += cntSze + varSze;
00430 
00431   int_err = U_ZERO_ERROR;
00432 
00433   uloc_getLanguage(localeID, 
00434            name,
00435            nameCapacity, 
00436            &int_err);
00437 
00438   /*We fill in the users buffer*/
00439   if ((nameCapacity>0) && cntSze)
00440     {
00441       if (U_SUCCESS(int_err)) uprv_strcat(name, "_");
00442 
00443       uloc_getCountry(localeID,
00444           name + uprv_strlen(name),
00445               nameCapacity - uprv_strlen(name),
00446               &int_err);
00447 
00448       if (varSze)
00449     {
00450       if (U_SUCCESS(int_err)) uprv_strcat(name, "_");
00451 
00452       uloc_getVariant(localeID,
00453                    name + uprv_strlen(name),
00454                    nameCapacity - uprv_strlen(name), 
00455                    &int_err);
00456     }
00457 
00458     }
00459   *err  = int_err;
00460 
00461   return i;
00462 }
00463 
00464 const char* uloc_getISO3Language(const char* localeID) 
00465 {
00466   int16_t offset;
00467   char lang[TEMPBUFSIZE];
00468   UErrorCode err = U_ZERO_ERROR;
00469 
00470   if (localeID == NULL)    localeID = uloc_getDefault();
00471   uloc_getLanguage(localeID, lang, TEMPBUFSIZE, &err);
00472   if (U_FAILURE(err)) return "";
00473   offset = _findIndex(_languages, sizeof(_languages),lang);
00474   if (offset < 0) return "";
00475   return &(_languages3[offset * 4]);
00476 }
00477 
00478 const char* uloc_getISO3Country(const char* localeID) 
00479 {
00480   int16_t offset;
00481   char cntry[TEMPBUFSIZE];
00482   UErrorCode err = U_ZERO_ERROR;
00483 
00484   if (localeID == NULL)    localeID = uloc_getDefault();
00485   uloc_getCountry(localeID, cntry, TEMPBUFSIZE, &err);
00486   if (U_FAILURE(err)) return "";
00487   offset = _findIndex(_countries, sizeof(_countries), cntry);
00488   if (offset < 0) return "";
00489 
00490   return &(_countries3[offset * 4]);
00491 }
00492 
00493 uint32_t uloc_getLCID(const char* localeID) 
00494 {
00495   UErrorCode err = U_ZERO_ERROR;
00496   char temp[30];
00497   const UChar* lcid = NULL;
00498   int32_t lcidLen = 0;
00499   uint32_t result = 0;
00500   UResourceBundle* bundle = ures_open(NULL, localeID, &err);
00501 
00502   if (U_SUCCESS(err))
00503     {
00504       lcid = ures_getStringByKey(bundle, _kLocaleID, &lcidLen, &err);
00505       ures_close(bundle);
00506       if (U_FAILURE(err) || !lcid || lcidLen == 0)
00507     {
00508       return 0;
00509     }
00510       u_austrcpy(temp, lcid);
00511       result = (uint32_t)T_CString_stringToInteger(temp, 16);
00512     }
00513 
00514   return result;
00515 }
00516 
00517 int32_t uloc_getDisplayLanguage(const char* locale,
00518                 const char* inLocale,
00519                 UChar* language,
00520                 int32_t languageCapacity,
00521                 UErrorCode* status) 
00522 {
00523   const UChar* result = NULL;
00524   int32_t i = 0;
00525   int langBufSize;
00526   char inLanguageBuffer[TEMPBUFSIZE];
00527   char inLocaleBuffer[TEMPBUFSIZE];
00528   UErrorCode err = U_ZERO_ERROR;
00529   UResourceBundle* bundle;
00530   const UChar* temp = NULL;  
00531   UBool isDefaultLocale = FALSE;
00532   UBool done = FALSE;
00533 
00534   if (U_FAILURE(*status)) return 0;
00535 
00536   if (inLocale == NULL) 
00537     {
00538       inLocale = uloc_getDefault();
00539       isDefaultLocale = TRUE;
00540     }
00541   else if (uprv_strcmp(inLocale, uloc_getDefault()) == 0) isDefaultLocale = TRUE;
00542   /*truncates the fallback mechanism if we start out with a defaultLocale*/
00543 
00544   if (locale == NULL) locale = uloc_getDefault();
00545 
00546   /*extracts the language*/
00547   langBufSize = uloc_getLanguage(locale,
00548                  inLanguageBuffer,
00549                  TEMPBUFSIZE,
00550                  &err);  
00551 
00552 
00553 
00554   /*We need to implement a fallback mechanism here because we are getting keys out of a
00555     tagged array, there is no capability of doing this with fallback through the resource
00556     bundle API*/
00557 
00558   if (langBufSize > 1)
00559     {
00560       do 
00561     {    
00562       /*
00563         If we are at the root locale ("")
00564         The first time we fall back to the full default locale
00565         As we iterate down the latter, if we hit the root locale ("")
00566         we pass it to the resource bundle api so it checks default.txt
00567       */
00568       
00569       if (inLocale[0] == '\0')
00570         {
00571           if (!isDefaultLocale)
00572         {
00573           isDefaultLocale = TRUE;
00574           inLocale = uloc_getDefault();
00575         }
00576           else   done = TRUE;
00577         }
00578 
00579 
00580       bundle = ures_open(NULL, inLocale, &err);
00581 
00582       if (U_SUCCESS(err))
00583         {
00584           err = U_ZERO_ERROR;
00585           temp = ures_getTaggedArrayItem(bundle,
00586                          _kLanguages,
00587                          inLanguageBuffer, 
00588                          &err);
00589           if (U_SUCCESS(err))        result = temp;
00590           ures_close(bundle);
00591         }
00592 
00593 
00594       err = U_ZERO_ERROR;
00595 
00596       /*Iterates down the Locale ID*/
00597 
00598       uloc_getParent(inLocale, inLocaleBuffer, TEMPBUFSIZE, &err);
00599       inLocale = inLocaleBuffer;
00600 
00601     } while ((result == NULL) && !done);
00602     }
00603 
00604 
00605   if (result)
00606     {
00607       i = u_strlen(result)+1;
00608       if (i > languageCapacity)
00609     {
00610       *status = U_BUFFER_OVERFLOW_ERROR;
00611       
00612       if (languageCapacity >= 1) 
00613         {
00614           u_strncpy(language, result, languageCapacity-1);
00615           language[languageCapacity-1] = (UChar)0x0000;
00616         }
00617     }
00618       else u_strcpy(language, result);
00619     }
00620   else 
00621     {
00622       /*Falls back to ISO Name*/
00623       i = langBufSize;
00624       if (i > languageCapacity)
00625     {
00626       *status = U_BUFFER_OVERFLOW_ERROR;
00627       
00628       if (languageCapacity >= 1) 
00629         {
00630          
00631           language[languageCapacity-1] = (UChar)0x0000;
00632            u_uastrncpy(language, inLanguageBuffer, languageCapacity-1);
00633         }
00634     }
00635       else u_uastrcpy(language, inLanguageBuffer);
00636     }
00637   return i;
00638 }
00639 
00640 int32_t uloc_getDisplayCountry(const char* locale,
00641                    const char* inLocale,
00642                    UChar* country,
00643                    int32_t countryCapacity,
00644                    UErrorCode* status)
00645 {
00646   /* NULL may be used to specify the default */
00647   const UChar* result = NULL;
00648   int32_t i = 0;
00649   int cntryBufSize;
00650   char inCountryBuffer[TEMPBUFSIZE];
00651   UErrorCode err = U_ZERO_ERROR;
00652   UResourceBundle* bundle = NULL;
00653   char inLocaleBuffer[TEMPBUFSIZE];
00654   UBool isDefaultLocale = FALSE;
00655   UBool done = FALSE;
00656 
00657   if (U_FAILURE(*status)) return 0;
00658 
00659 
00660 
00661   if (inLocale == NULL)    
00662     {
00663       inLocale = uloc_getDefault();
00664       isDefaultLocale = TRUE;
00665     }
00666   else if (uprv_strcmp(inLocale, uloc_getDefault()) == 0) isDefaultLocale = TRUE;
00667     /*truncates the fallback mechanism if we start out with a defaultLocale*/
00668 
00669   if (locale == NULL) locale = uloc_getDefault();
00670   
00671     /*extracts the country*/
00672   cntryBufSize = uloc_getCountry(locale, inCountryBuffer, TEMPBUFSIZE, &err);
00673 
00674 
00675 
00676   if (cntryBufSize > 1)
00677     {
00678       /*
00679     We need to implement a fallback mechanism here because we are getting keys out of a
00680     tagged array, there is no capability of doing this with fallback through the resource
00681     bundle API
00682       */
00683   do 
00684     {
00685       /*
00686     If we are at the root locale ("")
00687     The first time we fall back to the full default locale
00688     As we iterate down the latter, if we hit the root locale ("")
00689     we pass it to the resource bundle api so it checks default.txt
00690       */
00691       
00692       if (inLocale[0] == '\0')
00693     {
00694       if (!isDefaultLocale)
00695         {
00696           isDefaultLocale = TRUE;
00697           inLocale = uloc_getDefault();
00698         }
00699       else   done = TRUE;
00700     }
00701 
00702 
00703       bundle = ures_open(NULL, inLocale, &err);      
00704       
00705       if (U_SUCCESS(err))
00706     {
00707       const UChar* temp;
00708 
00709       temp = ures_getTaggedArrayItem(bundle,
00710                      _kCountries,
00711                      inCountryBuffer, 
00712                      &err);
00713       if (U_SUCCESS(err))  
00714         result = temp;
00715       ures_close(bundle);
00716     }
00717 
00718       err = U_ZERO_ERROR;
00719       uloc_getParent(inLocale, inLocaleBuffer, TEMPBUFSIZE, &err);
00720 
00721       inLocale = inLocaleBuffer;
00722     } while ((result == NULL) && !done);
00723     }
00724 
00725   if (result)
00726     {
00727       i = u_strlen(result)+1;
00728       if (i > countryCapacity)
00729     {
00730       *status = U_BUFFER_OVERFLOW_ERROR;
00731 
00732       if (countryCapacity >= 1)
00733         {
00734           country[countryCapacity-1] = (UChar)0x0000;
00735           u_strncpy(country, result, countryCapacity-1);
00736         }
00737     }
00738       else u_strcpy(country, result);
00739     }
00740   else 
00741     {
00742       /*Falls back to ISO Name*/
00743       i = cntryBufSize;
00744       if (i > countryCapacity)
00745     {
00746       *status = U_BUFFER_OVERFLOW_ERROR;
00747       
00748       if (countryCapacity >= 1) 
00749         {
00750           u_uastrncpy(country, inCountryBuffer, countryCapacity-1);
00751           country[countryCapacity-1] = (UChar)0x0000;
00752         }
00753     }
00754       else u_uastrcpy(country, inCountryBuffer);
00755     }
00756 
00757   return i;
00758 }
00759 
00760 int32_t uloc_getDisplayVariant(const char* locale,
00761                    const char* inLocale,
00762                    UChar* variant,
00763                    int32_t variantCapacity,
00764                    UErrorCode* status)
00765 {
00766   const UChar* result = NULL;
00767   int32_t i = 0;
00768   int varBufSize;
00769   char inVariantBuffer[TEMPBUFSIZE];
00770   char* inVariant = inVariantBuffer;
00771   UErrorCode err = U_ZERO_ERROR;
00772   UResourceBundle* bundle;
00773   char inLocaleBuffer[TEMPBUFSIZE];
00774   UBool isDefaultLocale = FALSE;
00775   char inVariantTagBuffer[TEMPBUFSIZE+2];
00776   char* inVariantTag = inVariantTagBuffer;
00777   UBool done = FALSE;
00778 
00779   if (U_FAILURE(*status)) return 0;
00780   
00781   inVariantTagBuffer[0] = '\0';
00782   
00783   if (inLocale == NULL)    
00784     {
00785       inLocale = uloc_getDefault();
00786       isDefaultLocale = TRUE;
00787     }
00788   else if (uprv_strcmp(inLocale, uloc_getDefault()) == 0) isDefaultLocale = TRUE;
00789     /*truncates the fallback mechanism if we start out with a defaultLocale*/
00790 
00791   if (locale == NULL) locale = uloc_getDefault();
00792     
00793   /*extracts the variant*/
00794   varBufSize = uloc_getVariant(locale, inVariant, TEMPBUFSIZE, &err);
00795   
00796   if (varBufSize > 1)
00797     {
00798       /*In case the variant is longer than our stack buffers*/
00799       if (err == U_BUFFER_OVERFLOW_ERROR)
00800     {
00801       inVariant = (char*)uprv_malloc(varBufSize*sizeof(char)+1);
00802       if (inVariant == NULL) goto NO_MEMORY;
00803       inVariantTag = (char*)uprv_malloc(varBufSize*sizeof(char)+uprv_strlen("%%")+1);
00804       if (inVariantTag == NULL) 
00805         {
00806           uprv_free(inVariant);
00807           goto NO_MEMORY;
00808         }
00809       err = U_ZERO_ERROR;
00810       uloc_getVariant(locale, inVariant, varBufSize, &err);
00811     }
00812 
00813       uprv_strcpy(inVariantTag,"%%");  
00814       uprv_strcat(inVariantTag, inVariant);
00815 
00816       /*We need to implement a fallback mechanism here because we are getting keys out of a
00817     tagged array, there is no capability of doing this with fallback through the resource
00818     bundle API*/
00819       do {
00820       /*
00821     If we are at the root locale ("")
00822     The first time we fall back to the full default locale
00823     As we iterate down the latter, if we hit the root locale ("")
00824     we pass it to the resource bundle api so it checks default.txt
00825       */
00826 
00827       if (inLocale[0] == '\0')
00828     {
00829       if (!isDefaultLocale)
00830         {
00831           isDefaultLocale = TRUE;
00832           inLocale = uloc_getDefault();
00833         }
00834       else   done = TRUE;
00835     }
00836 
00837       
00838       bundle = ures_open(NULL, inLocale, &err);      
00839       
00840       if (U_SUCCESS(err))
00841     {
00842       const UChar* temp;
00843       
00844       temp = ures_get(bundle,
00845               inVariantTag, 
00846               &err);
00847       if (U_SUCCESS(err))  result = temp;
00848       ures_close(bundle);
00849     }
00850 
00851       err = U_ZERO_ERROR;
00852       uloc_getParent(inLocale, inLocaleBuffer, TEMPBUFSIZE, &err);
00853       
00854       inLocale = inLocaleBuffer;
00855     } while ((result == NULL) && !done);
00856 
00857 
00858 
00859     }
00860 
00861 
00862       if (result)
00863     {
00864       i = u_strlen(result)+1;
00865       if (i > variantCapacity)
00866     {
00867       *status = U_BUFFER_OVERFLOW_ERROR;
00868 
00869       if (variantCapacity >= 1) 
00870         {
00871           variant[variantCapacity-1] = (UChar)0x0000;
00872           u_strncpy(variant, result, variantCapacity-1);
00873         }
00874     }
00875       else u_strcpy(variant, result);
00876     }
00877   else 
00878     {
00879       /*Falls back to user's Name*/
00880       i = varBufSize;
00881       if (i > variantCapacity)
00882     {
00883       *status = U_BUFFER_OVERFLOW_ERROR;
00884       
00885       if (variantCapacity >= 1) 
00886         {
00887           u_uastrncpy(variant, inVariant, variantCapacity-1);
00888           variant[variantCapacity-1] = (UChar)0x0000;
00889         }
00890     }
00891       else u_uastrcpy(variant, inVariant);
00892     }
00893  
00894   /*Clean up memory*/
00895   if (inVariant != inVariantBuffer)
00896     {
00897       uprv_free(inVariant);
00898       uprv_free(inVariantTag);
00899     } 
00900   return i;
00901 
00902 NO_MEMORY:
00903   *status = U_MEMORY_ALLOCATION_ERROR;
00904   return 0;
00905 }
00906 
00907 int32_t uloc_getDisplayName(const char* locale,
00908                 const char* inLocale, 
00909                 UChar* result,
00910                 int32_t nameCapacity,
00911                 UErrorCode* err) 
00912 {
00913   UErrorCode int_err = U_ZERO_ERROR;
00914   int i = 0;
00915   int cntSze, varSze;
00916   UBool has_lang = TRUE;
00917   int result_size;
00918 
00919   int_err = U_ZERO_ERROR;
00920 
00921   /*Preflights all the components*/
00922   cntSze = uloc_getDisplayCountry(locale, 
00923                   inLocale,
00924                   NULL , 
00925                   0,
00926                   &int_err);
00927   int_err = U_ZERO_ERROR;
00928   varSze = uloc_getDisplayVariant(locale, 
00929                   inLocale,
00930                   NULL , 
00931                   0,
00932                   &int_err);
00933   
00934   int_err = U_ZERO_ERROR;
00935   i = uloc_getDisplayLanguage(locale, 
00936                   inLocale,
00937                   NULL,
00938                   0, 
00939                   &int_err);
00940   /*Decrement duplicative zero-terminators*/
00941   --varSze;
00942   --cntSze;
00943   
00944   /*Logic below adjusts pre-flight information with additional characters "(", ",", " ", ")"
00945   when neeed be*/
00946   if ((i-1 == 0) && (varSze == 0)) /*No language field*/
00947     {
00948       has_lang = FALSE;
00949       i = cntSze+1;
00950     }
00951   else if (cntSze)
00952     {
00953       if (varSze) i += cntSze + varSze + 5;
00954       else i += cntSze + 3;
00955     }
00956 
00957   int_err = U_ZERO_ERROR;
00958 
00959   result_size = uloc_getDisplayLanguage(locale, 
00960                     inLocale,
00961                     result,
00962                     nameCapacity, 
00963                     &int_err) - 1;
00964 
00965   if (U_SUCCESS(int_err)&&cntSze)
00966     {
00967       if (U_SUCCESS(int_err))
00968     {
00969       if (has_lang) 
00970         {
00971           u_strcat(result, openParen);
00972           result_size += 2;
00973         }
00974       
00975       result_size += uloc_getDisplayCountry(locale,
00976                         inLocale,
00977                         result + result_size,
00978                         nameCapacity - result_size,
00979                         &int_err) - 1;
00980     }
00981       
00982       if (varSze)
00983     {
00984       if (U_SUCCESS(int_err))      
00985         {
00986           u_strcat(result, comma);
00987           result_size += 2;
00988           
00989           result_size += uloc_getDisplayVariant(locale,
00990                             inLocale,
00991                             result + result_size,
00992                             nameCapacity - result_size, 
00993                             &int_err) - 1;
00994         }
00995     }
00996       
00997       if (U_SUCCESS(int_err)&&has_lang) u_strcat(result, closeParen);
00998     }
00999   
01000   *err  = int_err;
01001   
01002   return i;
01003 }
01004 
01005 const char*
01006 uloc_getAvailable(int32_t offset) 
01007 {
01008 
01009   if (_installedLocales == NULL) _lazyEvaluate_installedLocales();
01010 
01011   if (offset > _installedLocalesCount) return NULL;
01012   else  return _installedLocales[offset];
01013 
01014 }
01015 
01016 int32_t uloc_countAvailable()
01017 {
01018   if (_installedLocales == NULL) _lazyEvaluate_installedLocales();
01019 
01020     return _installedLocalesCount;
01021 }
01022 
01023 static void _lazyEvaluate_installedLocales()
01024 {
01025 
01026     UResourceBundle *index = NULL;
01027     UResourceBundle installed;
01028     UErrorCode status = U_ZERO_ERROR;
01029     const UChar *lname;
01030     char ** temp;
01031     int32_t i = 0;
01032     int32_t len = 0;
01033 
01034     index = ures_open(NULL, kIndexLocaleName, &status);
01035     ures_getByKey(index, kIndexTag, &installed, &status);
01036 
01037     if(U_SUCCESS(status)) {
01038       _installedLocalesCount = ures_getSize(&installed);
01039       temp = (char **) uprv_malloc(sizeof(char*) * (_installedLocalesCount+1));
01040 
01041       ures_resetIterator(&installed);
01042       while(ures_hasNext(&installed)) {
01043         lname = ures_getNextString(&installed, &len, NULL, &status);
01044         temp[i] = (char*) uprv_malloc(sizeof(char) * (len + 1));
01045 
01046         u_UCharsToChars(lname, temp[i], len);
01047         temp[i][len] = 0; /* Terminate the string */
01048         i++;
01049       }
01050       {
01051         umtx_lock(NULL);
01052         if (_installedLocales == NULL)
01053         {
01054           _installedLocales = temp;
01055           temp = NULL;
01056         } else {
01057           for (i = 0; i < _installedLocalesCount; i++) uprv_free(temp[i]);
01058           uprv_free(temp);
01059         }
01060         umtx_unlock(NULL);
01061     
01062       }
01063       ures_close(&installed);
01064     }
01065     ures_close(index);
01066 }
01067 
01074 const char* const* uloc_getISOLanguages() 
01075 {
01076   const char *from, *end;
01077   char **to;
01078 
01079   if (_isoLanguages == NULL) 
01080     {
01081 
01082       {
01083     umtx_lock(NULL);
01084 
01085     if (_isoLanguages == NULL) 
01086       {
01087         _isoLanguages = (char**) uprv_malloc(sizeof(char*)*(1+(sizeof(_languages) / 3)));
01088 
01089         end = _languages + (sizeof(_languages));
01090         from = _languages; 
01091         to = _isoLanguages;
01092         
01093         while (from < end) 
01094           {
01095         *to = (char*)from;
01096         ++to;
01097         from += 3;
01098           }
01099         *to = NULL;
01100       }
01101     umtx_unlock(NULL);
01102       }
01103     }
01104   return (const char* const*)_isoLanguages;
01105 }
01106 
01113 const char* const* uloc_getISOCountries() 
01114 {
01115   if (_isoCountries == NULL) 
01116     {
01117       const char *from, *end;
01118       char **to;
01119       {
01120     umtx_lock(NULL);
01121     
01122     if (_isoCountries == NULL) 
01123       {
01124         _isoCountries = (char**) uprv_malloc(sizeof(char*)*(1+(sizeof(_countries) / 3)));
01125         
01126         end = _countries + (sizeof(_countries));
01127         from = _countries;
01128         to = _isoCountries;
01129         
01130         while (from < end) 
01131           {
01132         *to = (char*)from;
01133         ++to;
01134         from += 3;
01135           }
01136         *to = NULL;
01137       }
01138     umtx_unlock(NULL);
01139       }
01140     }
01141   return (const char* const*)_isoCountries;
01142 }

Generated at Tue Dec 5 10:48:06 2000 for ICU by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000