00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00035
00036
00037
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
00046 U_CAPI void locale_set_default(const char *id);
00047
00048
00049
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
00061 static const UChar openParen[] = { (UChar)0x0020 , (UChar)0x0028 , (UChar)0x0000};
00062 static const UChar comma[] = { (UChar)0x002C , (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
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
00106
00107
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
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
00151
00152
00153 static char** _isoLanguages = NULL;
00154 static char** _isoCountries = NULL;
00155
00156
00157
00158
00159
00160 static int16_t _findIndex(const char* list, int32_t listLength, const char* key);
00161
00162
00163 static const char* _findCharSeparator(const char* string);
00164
00165
00166 static void _lazyEvaluate_installedLocales(void);
00167
00168
00169 #define _isIDSeparator(a) (a == '_' || a == '-')
00170
00171
00172
00173
00174
00175
00176
00177 static const char* _findCharSeparator(const char* string)
00178 {
00179 if (string == NULL) return NULL;
00180
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;
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
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
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
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
00264 while (offset && !_isIDSeparator(localeID[offset])) offset--;
00265
00266
00267
00268
00269 while (i < offset)
00270 {
00271 if (parentCapacity > i) parent[i] = localeID[i];
00272 i++;
00273 }
00274
00275
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
00301
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
00336
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
00374
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
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
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
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
00543
00544 if (locale == NULL) locale = uloc_getDefault();
00545
00546
00547 langBufSize = uloc_getLanguage(locale,
00548 inLanguageBuffer,
00549 TEMPBUFSIZE,
00550 &err);
00551
00552
00553
00554
00555
00556
00557
00558 if (langBufSize > 1)
00559 {
00560 do
00561 {
00562
00563
00564
00565
00566
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
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
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
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
00668
00669 if (locale == NULL) locale = uloc_getDefault();
00670
00671
00672 cntryBufSize = uloc_getCountry(locale, inCountryBuffer, TEMPBUFSIZE, &err);
00673
00674
00675
00676 if (cntryBufSize > 1)
00677 {
00678
00679
00680
00681
00682
00683 do
00684 {
00685
00686
00687
00688
00689
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
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
00790
00791 if (locale == NULL) locale = uloc_getDefault();
00792
00793
00794 varBufSize = uloc_getVariant(locale, inVariant, TEMPBUFSIZE, &err);
00795
00796 if (varBufSize > 1)
00797 {
00798
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
00817
00818
00819 do {
00820
00821
00822
00823
00824
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
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
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
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
00941 --varSze;
00942 --cntSze;
00943
00944
00945
00946 if ((i-1 == 0) && (varSze == 0))
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;
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 }