home *** CD-ROM | disk | FTP | other *** search
- /*
- *******************************************************************************
- * *
- * COPYRIGHT: *
- * (C) Copyright Taligent, Inc., 1997 *
- * (C) Copyright International Business Machines Corporation, 1997-1998 *
- * Licensed Material - Program-Property of IBM - All Rights Reserved. *
- * US Government Users Restricted Rights - Use, duplication, or disclosure *
- * restricted by GSA ADP Schedule Contract with IBM Corp. *
- * *
- *******************************************************************************
- *
- * File ULOC.CPP
- *
- * Modification History:
- *
- * Date Name Description
- * 04/01/97 aliu Creation.
- * 08/21/98 stephen JDK 1.2 sync
- * 12/08/98 rtg New Locale implementation and C API
- * 03/15/99 damiba overhaul.
- * 04/06/99 stephen changed setDefault() to realloc and copy
- * 06/14/99 stephen Changed calls to ures_open for new params
- * 07/21/99 stephen Modified setDefault() to propagate to C++
- ******************************************************************************/
-
-
- #include "uloc.h"
-
- #include "utypes.h"
- #include "ures.h"
- #include "uchar.h"
- #include "umutex.h"
- #include "cstring.h"
- #include "ustring.h"
- #include "cmemory.h"
-
- /****************************************************************************
- Global variable and type definitions
- ******************************************************************************/
-
- /* UnicodeString stuff */
- typedef struct UnicodeString UnicodeString;
-
- U_CAPI const UChar* T_UnicodeString_getUChars(const UnicodeString *s);
- /* Locale stuff */
- U_CAPI void locale_set_default(const char *id);
-
- /* These strings describe the resources we attempt to load from
- the locale ResourceBundle data file.*/
- static const char* _kLocaleString = "LocaleString";
- static const char* _kShortLanguage = "ShortLanguage";
- static const char* _kShortCountry = "ShortCountry";
- static const char* _kLocaleID = "LocaleID";
- static const char* _kLanguages = "Languages";
- static const char* _kCountries = "Countries";
-
-
- #define TEMPBUFSIZE 8
-
- /*Some static strings needed in the getDisplay* functions*/
- static const UChar openParen[] = { (UChar)0x0020 /* space */, (UChar)0x0028 /* ( */, (UChar)0x0000};
- static const UChar comma[] = { (UChar)0x002C /* space */, (UChar)0x0020 /* , */, (UChar)0x0000};
- static const UChar closeParen[] = { (UChar)0x0029 /* ( */, (UChar)0x0000};
-
-
- static char* _defaultLocale = NULL;
- static char* _dataDirectory = NULL;
-
- static char** _installedLocales = NULL;
- static int32_t _installedLocalesCount = 0;
-
-
- static const char _languages[] =
- "aa\0ab\0af\0am\0ar\0as\0ay\0az\0"
- "ba\0be\0bg\0bh\0bi\0bn\0bo\0br\0"
- "ca\0co\0cs\0cy\0da\0de\0dz\0"
- "el\0en\0eo\0es\0et\0eu\0fa\0fi\0fj\0fo\0fr\0fy\0"
- "ga\0gd\0gl\0gn\0gu\0ha\0he\0hi\0hr\0hu\0hy\0"
- "ia\0id\0ie\0ik\0in\0is\0it\0iu\0iw\0"
- "ja\0ji\0jw\0ka\0kk\0kl\0km\0kn\0ko\0ks\0ku\0ky\0"
- "la\0ln\0lo\0lt\0lv\0"
- "mg\0mi\0mk\0ml\0mn\0mo\0mr\0ms\0mt\0my\0"
- "na\0ne\0nl\0no\0oc\0om\0or\0"
- "pa\0pl\0ps\0pt\0qu\0rm\0rn\0ro\0ru\0rw\0"
- "sa\0sd\0sg\0sh\0si\0sk\0sl\0sm\0sn\0so\0sq\0sr\0ss\0st\0su\0sv\0sw\0"
- "ta\0te\0tg\0th\0ti\0tk\0tl\0tn\0to\0tr\0ts\0tt\0tw\0"
- "ug\0uk\0ur\0uz\0vi\0vo\0wo\0xh\0yi\0yo\0za\0zh\0zu";
- /* This list MUST be in sorted order, and MUST contain only two-letter codes! */
-
- static const char _languages3[] =
- "aar\0abk\0afr\0amh\0ara\0asm\0aym\0aze\0"
- "bak\0bel\0bul\0bih\0bis\0ben\0bod\0bre\0"
- "cat\0cos\0ces\0cym\0dan\0deu\0dzo\0"
- "ell\0eng\0epo\0spa\0est\0eus\0fas\0fin\0fij\0fao\0fra\0fry\0"
- "gai\0gdh\0glg\0grn\0guj\0hau\0heb\0hin\0hrv\0hun\0hye\0"
- "ina\0ind\0ile\0ipk\0ind\0isl\0ita\0iku\0heb\0"
- "jpn\0yid\0jaw\0kat\0kaz\0kal\0khm\0kan\0kor\0kas\0kur\0kir\0"
- "lat\0lin\0lao\0lit\0lav\0"
- "mlg\0mri\0mkd\0mal\0mon\0mol\0mar\0msa\0mlt\0mya\0"
- "nau\0nep\0nld\0nor\0oci\0orm\0ori\0"
- "pan\0pol\0pus\0por\0que\0roh\0run\0ron\0rus\0kin\0"
- "san\0snd\0sag\0srp\0sin\0slk\0slv\0smo\0sna\0som\0sqi\0srp\0ssw\0sot\0sun\0swe\0swa\0"
- "tat\0tel\0tgk\0tha\0tir\0tuk\0tgl\0tsn\0ton\0tur\0tsn\0tat\0twi\0"
- "uig\0ukr\0urd\0uzb\0vie\0vol\0wol\0xho\0yid\0yor\0zha\0zho\0zul";
- /* This list MUST contain a three-letter code for every two-letter code in the
- list above, and they MUST ne in the same order (i.e., the same language must
- be in the same place in both lists)! */
-
- static const char _countries[] =
- "AD\0AE\0AF\0AG\0AI\0AL\0AM\0AN\0AO\0AQ\0AR\0AS\0AT\0AU\0AW\0AZ\0"
- "BA\0BB\0BD\0BE\0BF\0BG\0BH\0BI\0BJ\0BM\0BN\0BO\0BR\0BS\0BT\0BV\0BW\0BY\0BZ\0"
- "CA\0CC\0CF\0CG\0CH\0CI\0CK\0CL\0CM\0CN\0CO\0CR\0CU\0CV\0CX\0CY\0CZ\0"
- "DE\0DJ\0DK\0DM\0DO\0DZ\0EC\0EE\0EG\0EH\0ER\0ES\0ET\0"
- "FI\0FJ\0FK\0FM\0FO\0FR\0FX\0"
- "GA\0GB\0GD\0GE\0GF\0GH\0GI\0GL\0GM\0GN\0GP\0GQ\0GR\0GS\0GT\0GU\0GW\0GY\0"
- "HK\0HM\0HN\0HR\0HT\0HU\0ID\0IE\0IL\0IN\0IO\0IQ\0IR\0IS\0IT\0"
- "JM\0JO\0JP\0KE\0KG\0KH\0KI\0KM\0KN\0KP\0KR\0KW\0KY\0KZ\0"
- "LA\0LB\0LC\0LI\0LK\0LR\0LS\0LT\0LU\0LV\0LY\0"
- "MA\0MC\0MD\0MG\0MH\0MK\0ML\0MM\0MN\0MO\0MP\0MQ\0MR\0MS\0MT\0MU\0MV\0MW\0MX\0MY\0MZ\0"
- "NA\0NC\0NE\0NF\0NG\0NI\0NL\0NO\0NP\0NR\0NU\0NZ\0OM\0"
- "PA\0PE\0PF\0PG\0PH\0PK\0PL\0PM\0PN\0PR\0PT\0PW\0PY\0QA\0RE\0RO\0RU\0RW\0"
- "SA\0SB\0SC\0SD\0SE\0SG\0SH\0SI\0SJ\0SK\0SL\0SM\0SN\0SO\0SR\0ST\0SV\0SY\0SZ\0"
- "TC\0TD\0TF\0TG\0TH\0TJ\0TK\0TM\0TN\0TO\0TP\0TR\0TT\0TV\0TW\0TZ\0"
- "UA\0UG\0UM\0US\0UY\0UZ\0VA\0VC\0VE\0VG\0VI\0VN\0VU\0"
- "WF\0WS\0YE\0YT\0YU\0ZA\0ZM\0ZR\0ZW";
- /* This list MUST be in sorted order, and MUST contain only two-letter codes! */
-
- static const char _countries3[] =
- "AND\0ARE\0AFG\0ATG\0AIA\0ALB\0ARM\0ANT\0AGO\0ATA\0ARG\0ASM\0AUT\0AUS\0ABW\0AZE\0"
- "BIH\0BRB\0BGD\0BEL\0BFA\0BGR\0BHR\0BDI\0BEN\0BMU\0BRN\0BOL\0BRA\0BHS\0BTN\0BVT\0BWA"
- "\0BLR\0BLZ\0"
- "CAN\0CCK\0CAF\0COG\0CHE\0CIV\0COK\0CHL\0CMR\0CHN\0COL\0CRI\0CUB\0CPV\0CXR\0CYP\0CZE\0"
- "DEU\0DJI\0DNK\0DMA\0DOM\0DZA\0ECU\0EST\0EGY\0ESH\0ERI\0ESP\0ETH\0"
- "FIN\0FJI\0FLK\0FSM\0FRO\0FRA\0FXX\0"
- "GAB\0GBR\0GRD\0GEO\0GUF\0GHA\0GIB\0GRL\0GMB\0GIN\0GLP\0GNQ\0GRC\0SGS\0GTM\0GUM"
- "\0GNB\0GUY\0"
- "HKG\0HMD\0HND\0HRV\0HTI\0HUN\0IDN\0IRL\0ISR\0IND\0IOT\0IRQ\0IRN\0ISL\0ITA\0"
- "JAM\0JOR\0JPN\0KEN\0KGZ\0KHM\0KIR\0COM\0KNA\0PRK\0KOR\0KWT\0CYM\0KAZ\0"
- "LAO\0LBN\0LCA\0LIE\0LKA\0LBR\0LSO\0LTU\0LUX\0LVA\0LBY\0"
- "MAR\0MCO\0MDA\0MDG\0MHL\0MKD\0MLI\0MMR\0MNG\0MAC\0MNP\0MTQ\0MRT\0MSR\0MLT\0MUS\0"
- "MDV\0MWI\0MEX\0MYS\0MOZ\0"
- "NAM\0NCL\0NER\0NFK\0NGA\0NIC\0NLD\0NOR\0NPL\0NRU\0NIU\0NZL\0OMN\0"
- "PAN\0PER\0PYF\0PNG\0PHL\0PAK\0POL\0SPM\0PCN\0PRI\0PRT\0PLW\0PRY\0QAT\0REU\0ROM"
- "\0RUS\0RWA\0"
- "SAU\0SLB\0SYC\0SDN\0SWE\0SGP\0SHN\0SVN\0SJM\0SVK\0SLE\0SMR\0SEN\0SOM\0SUR\0STP"
- "\0SLV\0SYR\0SWZ\0"
- "TCA\0TCD\0ATF\0TGO\0THA\0TJK\0TKL\0TKM\0TUN\0TON\0TMP\0TUR\0TTO\0TUV\0TWN\0TZA\0"
- "UKR\0UGA\0UMI\0USA\0URY\0UZB\0VAT\0VCT\0VEN\0VGB\0VIR\0VNM\0VUT\0"
- "WLF\0WSM\0YEM\0MYT\0YUG\0ZAF\0ZMB\0ZAR\0ZWE";
- /* This list MUST contain a three-letter code for every two-letter code in
- the above list, and they MUST be listed in the same order! */
-
- static char** _isoLanguages = NULL;
- static char** _isoCountries = NULL;
-
- /*******************************************************************************
- Implementation function definitions
- *******************************************************************************/
-
- static int16_t _findIndex(const char* list, int32_t listLength, const char* key);
-
- /*Works like strchr with '_' pr '-'*/
- static const char* _findCharSeparator(const char* string);
-
- /*Lazy evaluated the list of installed locales*/
- static void _lazyEvaluate_installedLocales();
-
- /*returns TRUE if a is an ID separator FALSE otherwise*/
- #define _isIDSeparator(a) (a == '_' || a == '-')
-
-
- /*******************************************************************************
- API function definitions
- *******************************************************************************/
-
-
- const char* _findCharSeparator(const char* string)
- {
- if (string == NULL) return NULL;
- /*Keeps iterating until an ID separator is found*/
- while (*string && !_isIDSeparator(*string)) string++;
- if (*string) return string;
- else return NULL;
- }
-
-
- int16_t _findIndex(const char* list, int32_t listLength, const char* key)
- {
- const char* anchor = list;
- const char* listEnd = anchor + listLength;
- bool_t found = FALSE;
- int index = 0;
- int tokenSize = icu_strlen(list)+1; /*gets the size of the tokens*/
-
- while (!found && list<listEnd)
- {
- if (icu_strcmp(key, list) == 0)
- {
- found = TRUE;
- break;
- }
- list += tokenSize;
- }
- if (found == TRUE) return ((list - anchor)/tokenSize);
- else return -1;
- }
-
- const char* uloc_getDefault()
- {
- const char* result = _defaultLocale;
- UErrorCode err = U_ZERO_ERROR;
-
- /*lazy evaluates _defaultLocale*/
- if (result == NULL)
- {
- uloc_setDefault(NULL, &err);
- result = _defaultLocale;
- }
-
- return result;
- }
-
- void uloc_setDefault(const char* newDefaultLocale,
- UErrorCode* err)
- {
-
- if (U_FAILURE(*err)) return;
- /* the error code isn't currently used for anything by this function*/
-
- if (newDefaultLocale == NULL)
- {
- newDefaultLocale = icu_getDefaultLocaleID();
- }
-
- umtx_lock(NULL);
- if(_defaultLocale == NULL)
- _defaultLocale = (char*)icu_malloc(sizeof(char) * (icu_strlen(newDefaultLocale) + 1));
- else
- _defaultLocale = (char*)icu_realloc(_defaultLocale,
- sizeof(char) * (icu_strlen(newDefaultLocale) + 1));
- icu_strcpy(_defaultLocale, newDefaultLocale);
- umtx_unlock(NULL);
-
- /* propagate change to C++ */
- locale_set_default(newDefaultLocale);
- }
-
-
- int32_t uloc_getParent(const char* localeID,
- char* parent,
- int32_t parentCapacity,
- UErrorCode* err)
- {
- int i=0;
- int offset = 0;
- int count = 0;
-
- if (U_FAILURE(*err)) return 0;
-
- if (localeID == NULL) localeID = uloc_getDefault();
-
-
- while (localeID[offset]&&(count < 2))
- {
- if (_isIDSeparator(localeID[offset++])) count++;
- }
-
- /*finds the second IDSeparator*/
- while (offset && !_isIDSeparator(localeID[offset])) offset--;
-
-
- /*Loop updates i to the size of the parent
- but only copies into the buffer as much as the buffer can bare*/
- while (i < offset)
- {
- if (parentCapacity > i) parent[i] = localeID[i];
- i++;
- }
-
- /*Sets the error code on case of need*/
- if (i >= parentCapacity )
- {
- *err = U_BUFFER_OVERFLOW_ERROR;
- }
-
- if (parentCapacity>0) parent[icu_min(i,parentCapacity-1)] = '\0';
-
-
- return i+1;
- }
-
- int32_t
- uloc_getLanguage(const char* localeID,
- char* language,
- int32_t languageCapacity,
- UErrorCode* err)
- {
- int i=0;
-
-
- if (U_FAILURE(*err)) return 0;
-
- if (localeID == NULL) localeID = uloc_getDefault();
-
- /*Loop updates i to the size of the language
- but only copies into the buffer as much as the buffer can bare*/
- while ((*localeID != '\0') && !_isIDSeparator(*localeID))
- {
- if (languageCapacity > i) language[i] = tolower(*localeID);
- i++;
- localeID++;
- }
-
- if (i >= languageCapacity )
- {
- *err = U_BUFFER_OVERFLOW_ERROR;
- }
-
- if (languageCapacity > 0)
- {
- language[icu_min(i,languageCapacity-1)] = '\0';
- /*We need to normalize for changes in ISO language names,
- We special case out the recent ISO changes, translating them
- internally to the old iso codes.*/
- if (U_SUCCESS(*err))
- {
- if (icu_strcmp("he", language) == 0) icu_strcpy(language, "iw");
- else if (icu_strcmp("yi", language) == 0) icu_strcpy(language, "ji");
- else if (icu_strcmp("id", language) == 0) icu_strcpy(language, "in");
- }
- }
-
- return i+1;
- }
-
-
- int32_t uloc_getCountry(const char* localeID,
- char* country,
- int32_t countryCapacity,
- UErrorCode* err)
- {
- int i=0;
-
- if (U_FAILURE(*err)) return 0;
- if (localeID == NULL) localeID = uloc_getDefault();
-
- localeID = _findCharSeparator(localeID);
-
- /*Loop updates i to the size of the language
- but only copies into the buffer as much as the buffer can bare*/
- if (localeID)
- {
- ++localeID;
- while ((*localeID != '\0') && !_isIDSeparator(*localeID))
- {
- if (countryCapacity > i) country[i] = toupper(*localeID);
- i++;
- localeID++;
- }
- }
-
- if (i >= countryCapacity )
- {
- *err = U_BUFFER_OVERFLOW_ERROR;
- }
-
- if (countryCapacity > 0) {country[icu_min(i,countryCapacity-1)] = '\0';}
- return i+1;
- }
-
- int32_t uloc_getVariant(const char* localeID,
- char* variant,
- int32_t variantCapacity,
- UErrorCode* err)
- {
- int i=0;
-
- if (U_FAILURE(*err)) return 0;
- if (localeID == NULL) localeID = uloc_getDefault();
-
- localeID = _findCharSeparator(localeID);
- if (localeID) localeID = _findCharSeparator(++localeID);
-
- if (localeID)
- {
- ++localeID;
- /*Loop updates i to the size of the language
- but only copies into the buffer as much as the buffer can bare*/
- while (*localeID != '\0')
- {
- if (variantCapacity > i) variant[i] = toupper(*localeID);
- i++;
- localeID++;
- }
-
- }
-
- if (i >= variantCapacity )
- {
- *err = U_BUFFER_OVERFLOW_ERROR;
- }
-
-
- if (variantCapacity>0) {variant[icu_min(i,variantCapacity-1)] = '\0';}
- return i+1;
- }
-
- int32_t uloc_getName(const char* localeID,
- char* name,
- int32_t nameCapacity,
- UErrorCode* err)
- {
- int i= 0;
- int varSze = 0;
- int cntSze = 0;
- UErrorCode int_err = U_ZERO_ERROR;
-
- if (U_FAILURE(*err)) return 0;
- /*First we preflight the components in order to ensure a valid return value*/
- if (localeID == NULL) localeID = uloc_getDefault();
-
- cntSze = uloc_getCountry(localeID,
- NULL ,
- 0,
- &int_err);
- int_err = U_ZERO_ERROR;
- varSze = uloc_getVariant(localeID,
- NULL ,
- 0,
- &int_err);
-
- int_err = U_ZERO_ERROR;
- i = uloc_getLanguage(localeID,
- NULL,
- 0,
- &int_err);
- /*Adjust for the zero terminators*/
- --varSze;
- --cntSze;
-
- if (cntSze) i++;
- if (varSze) i++;
- i += cntSze + varSze;
-
- int_err = U_ZERO_ERROR;
-
- uloc_getLanguage(localeID,
- name,
- nameCapacity,
- &int_err);
-
- /*We fill in the users buffer*/
- if ((nameCapacity>0) && cntSze)
- {
- if (U_SUCCESS(int_err)) icu_strcat(name, "_");
-
- uloc_getCountry(localeID,
- name + icu_strlen(name),
- nameCapacity - icu_strlen(name),
- &int_err);
-
- if (varSze)
- {
- if (U_SUCCESS(int_err)) icu_strcat(name, "_");
-
- uloc_getVariant(localeID,
- name + icu_strlen(name),
- nameCapacity - icu_strlen(name),
- &int_err);
- }
-
- }
- *err = int_err;
-
- return i;
- }
-
- const char* uloc_getISO3Language(const char* localeID)
- {
- int16_t index;
- char lang[TEMPBUFSIZE];
- UErrorCode err = U_ZERO_ERROR;
-
- if (localeID == NULL) localeID = uloc_getDefault();
- uloc_getLanguage(localeID, lang, TEMPBUFSIZE, &err);
- if (U_FAILURE(err)) return "";
- index = _findIndex(_languages, sizeof(_languages),lang);
- if (index < 0) return "";
- return &(_languages3[index * 4]);
- }
-
- const char* uloc_getISO3Country(const char* localeID)
- {
- int16_t index;
- char cntry[TEMPBUFSIZE];
- UErrorCode err = U_ZERO_ERROR;
-
- if (localeID == NULL) localeID = uloc_getDefault();
- uloc_getCountry(localeID, cntry, TEMPBUFSIZE, &err);
- if (U_FAILURE(err)) return "";
- index = _findIndex(_countries, sizeof(_countries), cntry);
- if (index < 0) return "";
-
- return &(_countries3[index * 4]);
- }
-
- uint32_t uloc_getLCID(const char* localeID)
- {
- UErrorCode err = U_ZERO_ERROR;
- char temp[30];
- const UChar* lcid = NULL;
- uint32_t result = 0;
- UResourceBundle* bundle = ures_open(uloc_getDataDirectory(), localeID, &err);
-
- if (U_SUCCESS(err))
- {
- lcid = ures_get(bundle, _kLocaleID, &err);
- ures_close(bundle);
- if (U_FAILURE(err) || !lcid || u_strlen(lcid) == 0)
- {
- return 0;
- }
- u_austrcpy(temp, lcid);
- result = (uint32_t)T_CString_stringToInteger(temp, 16);
- }
-
- return result;
- }
-
- int32_t uloc_getDisplayLanguage(const char* locale,
- const char* inLocale,
- UChar* language,
- int32_t languageCapacity,
- UErrorCode* status)
- {
- const UChar* result = NULL;
- int32_t i = 0;
- int langBufSize;
- bool_t doneDefaultLocale = FALSE;
- char inLanguageBuffer[TEMPBUFSIZE];
- char inLocaleBuffer[TEMPBUFSIZE];
- UErrorCode err = U_ZERO_ERROR;
- UResourceBundle* bundle;
- const UChar* temp = NULL;
- bool_t isDefaultLocale = FALSE;
- const char* dataDir = uloc_getDataDirectory();
- bool_t done = FALSE;
-
- if (U_FAILURE(*status)) return 0;
-
- if (inLocale == NULL)
- {
- inLocale = uloc_getDefault();
- isDefaultLocale = TRUE;
- }
- else if (icu_strcmp(inLocale, uloc_getDefault()) == 0) isDefaultLocale = TRUE;
- /*truncates the fallback mechanism if we start out with a defaultLocale*/
-
- if (locale == NULL) locale = uloc_getDefault();
-
- /*extracts the language*/
- langBufSize = uloc_getLanguage(locale,
- inLanguageBuffer,
- TEMPBUFSIZE,
- &err);
-
-
-
- /*We need to implement a fallback mechanism here because we are getting keys out of a
- tagged array, there is no capability of doing this with fallback through the resource
- bundle API*/
-
- if (langBufSize > 1)
- {
- do
- {
- /*
- If we are at the root locale ("")
- The first time we fall back to the full default locale
- As we iterate down the latter, if we hit the root locale ("")
- we pass it to the resource bundle api so it checks default.txt
- */
-
- if (inLocale[0] == '\0')
- {
- if (!isDefaultLocale)
- {
- isDefaultLocale = TRUE;
- inLocale = uloc_getDefault();
- }
- else done = TRUE;
- }
-
-
- bundle = ures_open(dataDir, inLocale, &err);
-
- if (U_SUCCESS(err))
- {
- UErrorCode err = U_ZERO_ERROR;
- temp = ures_getTaggedArrayItem(bundle,
- _kLanguages,
- inLanguageBuffer,
- &err);
- if (U_SUCCESS(err)) result = temp;
- ures_close(bundle);
- }
-
-
- err = U_ZERO_ERROR;
-
- /*Iterates down the Locale ID*/
-
- uloc_getParent(inLocale, inLocaleBuffer, TEMPBUFSIZE, &err);
- inLocale = inLocaleBuffer;
-
- } while ((result == NULL) && !done);
- }
-
-
- if (result)
- {
- i = u_strlen(result)+1;
- if (i > languageCapacity)
- {
- *status = U_BUFFER_OVERFLOW_ERROR;
-
- if (languageCapacity >= 1)
- {
- u_strncpy(language, result, languageCapacity-1);
- language[languageCapacity-1] = (UChar)0x0000;
- }
- }
- else u_strcpy(language, result);
- }
- else
- {
- /*Falls back to ISO Name*/
- i = langBufSize;
- if (i > languageCapacity)
- {
- *status = U_BUFFER_OVERFLOW_ERROR;
-
- if (languageCapacity >= 1)
- {
-
- language[languageCapacity-1] = (UChar)0x0000;
- u_uastrncpy(language, inLanguageBuffer, languageCapacity-1);
- }
- }
- else u_uastrcpy(language, inLanguageBuffer);
- }
- return i;
- }
-
- int32_t uloc_getDisplayCountry(const char* locale,
- const char* inLocale,
- UChar* country,
- int32_t countryCapacity,
- UErrorCode* status)
- {
- /* NULL may be used to specify the default */
- const UChar* result = NULL;
- int32_t i = 0;
- int cntryBufSize;
- bool_t doneDefaultLocale = FALSE;
- char inCountryBuffer[TEMPBUFSIZE];
- UErrorCode err = U_ZERO_ERROR;
- UResourceBundle* bundle = NULL;
- char inLocaleBuffer[TEMPBUFSIZE];
- bool_t isDefaultLocale = FALSE;
- const char* dataDir = uloc_getDataDirectory();
- bool_t done = FALSE;
-
- if (U_FAILURE(*status)) return 0;
-
-
-
- if (inLocale == NULL)
- {
- inLocale = uloc_getDefault();
- isDefaultLocale = TRUE;
- }
- else if (icu_strcmp(inLocale, uloc_getDefault()) == 0) isDefaultLocale = TRUE;
- /*truncates the fallback mechanism if we start out with a defaultLocale*/
-
- if (locale == NULL) locale = uloc_getDefault();
-
- /*extracts the country*/
- cntryBufSize = uloc_getCountry(locale, inCountryBuffer, TEMPBUFSIZE, &err);
-
-
-
- if (cntryBufSize > 1)
- {
- /*
- We need to implement a fallback mechanism here because we are getting keys out of a
- tagged array, there is no capability of doing this with fallback through the resource
- bundle API
- */
- do
- {
- /*
- If we are at the root locale ("")
- The first time we fall back to the full default locale
- As we iterate down the latter, if we hit the root locale ("")
- we pass it to the resource bundle api so it checks default.txt
- */
-
- if (inLocale[0] == '\0')
- {
- if (!isDefaultLocale)
- {
- isDefaultLocale = TRUE;
- inLocale = uloc_getDefault();
- }
- else done = TRUE;
- }
-
-
- bundle = ures_open(dataDir, inLocale, &err);
-
- if (U_SUCCESS(err))
- {
- const UChar* temp;
-
- temp = ures_getTaggedArrayItem(bundle,
- _kCountries,
- inCountryBuffer,
- &err);
- if (U_SUCCESS(err))
- result = temp;
- ures_close(bundle);
- }
-
- err = U_ZERO_ERROR;
- uloc_getParent(inLocale, inLocaleBuffer, TEMPBUFSIZE, &err);
-
- inLocale = inLocaleBuffer;
- } while ((result == NULL) && !done);
- }
-
- if (result)
- {
- i = u_strlen(result)+1;
- if (i > countryCapacity)
- {
- *status = U_BUFFER_OVERFLOW_ERROR;
-
- if (countryCapacity >= 1)
- {
- country[countryCapacity-1] = (UChar)0x0000;
- u_strncpy(country, result, countryCapacity-1);
- }
- }
- else u_strcpy(country, result);
- }
- else
- {
- /*Falls back to ISO Name*/
- i = cntryBufSize;
- if (i > countryCapacity)
- {
- *status = U_BUFFER_OVERFLOW_ERROR;
-
- if (countryCapacity >= 1)
- {
- u_uastrncpy(country, inCountryBuffer, countryCapacity-1);
- country[countryCapacity-1] = (UChar)0x0000;
- }
- }
- else u_uastrcpy(country, inCountryBuffer);
- }
-
- return i;
- }
-
- int32_t uloc_getDisplayVariant(const char* locale,
- const char* inLocale,
- UChar* variant,
- int32_t variantCapacity,
- UErrorCode* status)
- {
- const UChar* result = NULL;
- int32_t i = 0;
- int varBufSize;
- bool_t doneDefaultLocale = FALSE;
- char inVariantBuffer[TEMPBUFSIZE];
- char* inVariant = inVariantBuffer;
- UErrorCode err = U_ZERO_ERROR;
- UResourceBundle* bundle;
- char inLocaleBuffer[TEMPBUFSIZE];
- bool_t isDefaultLocale = FALSE;
- char inVariantTagBuffer[TEMPBUFSIZE+2];
- char* inVariantTag = inVariantTagBuffer;
- const char* dataDir = uloc_getDataDirectory();
- bool_t done = FALSE;
-
- if (U_FAILURE(*status)) return 0;
-
- inVariantTagBuffer[0] = '\0';
-
- if (inLocale == NULL)
- {
- inLocale = uloc_getDefault();
- isDefaultLocale = TRUE;
- }
- else if (icu_strcmp(inLocale, uloc_getDefault()) == 0) isDefaultLocale = TRUE;
- /*truncates the fallback mechanism if we start out with a defaultLocale*/
-
- if (locale == NULL) locale = uloc_getDefault();
-
- /*extracts the variant*/
- varBufSize = uloc_getVariant(locale, inVariant, TEMPBUFSIZE, &err);
-
- if (varBufSize > 1)
- {
- /*In case the variant is longer than our stack buffers*/
- if (err == U_BUFFER_OVERFLOW_ERROR)
- {
- inVariant = (char*)icu_malloc(varBufSize*sizeof(char)+1);
- if (inVariant == NULL) goto NO_MEMORY;
- inVariantTag = (char*)icu_malloc(varBufSize*sizeof(char)+icu_strlen("%%")+1);
- if (inVariantTag == NULL)
- {
- icu_free(inVariant);
- goto NO_MEMORY;
- }
- err = U_ZERO_ERROR;
- uloc_getVariant(locale, inVariant, varBufSize, &err);
- }
-
- icu_strcpy(inVariantTag,"%%");
- icu_strcat(inVariantTag, inVariant);
-
- /*We need to implement a fallback mechanism here because we are getting keys out of a
- tagged array, there is no capability of doing this with fallback through the resource
- bundle API*/
- do {
- /*
- If we are at the root locale ("")
- The first time we fall back to the full default locale
- As we iterate down the latter, if we hit the root locale ("")
- we pass it to the resource bundle api so it checks default.txt
- */
-
- if (inLocale[0] == '\0')
- {
- if (!isDefaultLocale)
- {
- isDefaultLocale = TRUE;
- inLocale = uloc_getDefault();
- }
- else done = TRUE;
- }
-
-
- bundle = ures_open(dataDir, inLocale, &err);
-
- if (U_SUCCESS(err))
- {
- const UChar* temp;
-
- temp = ures_get(bundle,
- inVariantTag,
- &err);
- if (U_SUCCESS(err)) result = temp;
- ures_close(bundle);
- }
-
- err = U_ZERO_ERROR;
- uloc_getParent(inLocale, inLocaleBuffer, TEMPBUFSIZE, &err);
-
- inLocale = inLocaleBuffer;
- } while ((result == NULL) && !done);
-
-
-
- }
-
-
- if (result)
- {
- i = u_strlen(result)+1;
- if (i > variantCapacity)
- {
- *status = U_BUFFER_OVERFLOW_ERROR;
-
- if (variantCapacity >= 1)
- {
- variant[variantCapacity-1] = (UChar)0x0000;
- u_strncpy(variant, result, variantCapacity-1);
- }
- }
- else u_strcpy(variant, result);
- }
- else
- {
- /*Falls back to user's Name*/
- i = varBufSize;
- if (i > variantCapacity)
- {
- *status = U_BUFFER_OVERFLOW_ERROR;
-
- if (variantCapacity >= 1)
- {
- u_uastrncpy(variant, inVariant, variantCapacity-1);
- variant[variantCapacity-1] = (UChar)0x0000;
- }
- }
- else u_uastrcpy(variant, inVariant);
- }
-
- /*Clean up memory*/
- if (inVariant != inVariantBuffer)
- {
- icu_free(inVariant);
- icu_free(inVariantTag);
- }
- return i;
-
- NO_MEMORY:
- *status = U_MEMORY_ALLOCATION_ERROR;
- return 0;
- }
-
- int32_t uloc_getDisplayName(const char* locale,
- const char* inLocale,
- UChar* result,
- int32_t nameCapacity,
- UErrorCode* err)
- {
- UErrorCode int_err = U_ZERO_ERROR;
- int i = 0;
- int cntSze, varSze;
- bool_t has_lang = TRUE;
- int result_size;
-
- int_err = U_ZERO_ERROR;
-
- /*Preflights all the components*/
- cntSze = uloc_getDisplayCountry(locale,
- inLocale,
- NULL ,
- 0,
- &int_err);
- int_err = U_ZERO_ERROR;
- varSze = uloc_getDisplayVariant(locale,
- inLocale,
- NULL ,
- 0,
- &int_err);
-
- int_err = U_ZERO_ERROR;
- i = uloc_getDisplayLanguage(locale,
- inLocale,
- NULL,
- 0,
- &int_err);
- /*Decrement duplicative zero-terminators*/
- --varSze;
- --cntSze;
-
- /*Logic below adjusts pre-flight information with additional characters "(", ",", " ", ")"
- when neeed be*/
- if ((i-1 == 0) && (varSze == 0)) /*No language field*/
- {
- has_lang = FALSE;
- i = cntSze+1;
- }
- else if (cntSze)
- {
- if (varSze) i += cntSze + varSze + 5;
- else i += cntSze + 3;
- }
-
- int_err = U_ZERO_ERROR;
-
- result_size = uloc_getDisplayLanguage(locale,
- inLocale,
- result,
- nameCapacity,
- &int_err) - 1;
-
- if (U_SUCCESS(int_err)&&cntSze)
- {
- if (U_SUCCESS(int_err))
- {
- if (has_lang)
- {
- u_strcat(result, openParen);
- result_size += 2;
- }
-
- result_size += uloc_getDisplayCountry(locale,
- inLocale,
- result + result_size,
- nameCapacity - result_size,
- &int_err) - 1;
- }
-
- if (varSze)
- {
- if (U_SUCCESS(int_err))
- {
- u_strcat(result, comma);
- result_size += 2;
-
- result_size += uloc_getDisplayVariant(locale,
- inLocale,
- result + result_size,
- nameCapacity - result_size,
- &int_err) - 1;
- }
- }
-
- if (U_SUCCESS(int_err)&&has_lang) u_strcat(result, closeParen);
- }
-
- *err = int_err;
-
- return i;
- }
-
-
- /**
- * Returns a list of all available locales. The return value is a pointer to
- * an array of pointers to ULocale objects. Both this array and the pointers
- * it contains are owned by ICU and should not be deleted or written through
- * by the caller. The array is terminated by a null pointer. RTG
- */
- U_CAPI UnicodeString** T_ResourceBundle_listInstalledLocales(const char* path, int32_t* numInstalledLocales);
-
- const char*
- uloc_getAvailable(int32_t index)
- {
-
- if (_installedLocales == NULL) _lazyEvaluate_installedLocales();
-
- if (index > _installedLocalesCount) return NULL;
- else return _installedLocales[index];
-
- }
-
- int32_t uloc_countAvailable()
- {
- if (_installedLocales == NULL) _lazyEvaluate_installedLocales();
-
- return _installedLocalesCount;
- }
-
- void _lazyEvaluate_installedLocales()
- {
- UnicodeString** temp;
- char ** temp2;
- int i;
- if (_installedLocales == NULL)
- {
- temp = T_ResourceBundle_listInstalledLocales(uloc_getDataDirectory(),
- &_installedLocalesCount);
- temp2 = (char **) icu_malloc(sizeof(char*) * (_installedLocalesCount+1));
-
- for (i = 0; i < _installedLocalesCount; i++)
- {
- temp2[i] = (char*) icu_malloc(sizeof(char) *
- (u_strlen(T_UnicodeString_getUChars(temp[i])) + 1));
- temp2[i] = u_austrcpy(temp2[i], T_UnicodeString_getUChars(temp[i]));
- }
- {
- umtx_lock(NULL);
- if (_installedLocales == NULL)
- {
- _installedLocales = temp2;
- temp2 = NULL;
- }
- else {
- for (i = 0; i < _installedLocalesCount; i++) icu_free(temp2[i]);
- icu_free(temp2);
- }
- umtx_unlock(NULL);
-
- }
- }
- }
-
- /**
- * Returns a list of all language codes defined in ISO 639. This is a pointer
- * to an array of pointers to arrays of char. All of these pointers are owned
- * by ICU-- do not delete them, and do not write through them. The array is
- * terminated with a null pointer.
- */
- const char* const* uloc_getISOLanguages()
- {
- const char *from, *end;
- char **to;
-
- if (_isoLanguages == NULL)
- {
-
- {
- umtx_lock(NULL);
-
- if (_isoLanguages == NULL)
- {
- _isoLanguages = (char**) icu_malloc(sizeof(char*)*(1+(sizeof(_languages) / 3)));
-
- end = _languages + (sizeof(_languages));
- from = _languages;
- to = _isoLanguages;
-
- while (from < end)
- {
- *to = (char*)from;
- ++to;
- from += 3;
- }
- *to = NULL;
- }
- umtx_unlock(NULL);
- }
- }
- return (const char* const*)_isoLanguages;
- }
-
- /**
- * Returns a list of all 2-letter country codes defined in ISO 639. This is a
- * pointer to an array of pointers to arrays of char. All of these pointers are
- * owned by ICU-- do not delete them, and do not write through them. The array is
- * terminated with a null pointer.
- */
- const char* const* uloc_getISOCountries()
- {
- if (_isoCountries == NULL)
- {
- const char *from, *end;
- char **to;
- {
- umtx_lock(NULL);
-
- if (_isoCountries == NULL)
- {
- _isoCountries = (char**) icu_malloc(sizeof(char*)*(1+(sizeof(_countries) / 3)));
-
- end = _countries + (sizeof(_countries));
- from = _countries;
- to = _isoCountries;
-
- while (from < end)
- {
- *to = (char*)from;
- ++to;
- from += 3;
- }
- *to = NULL;
- }
- umtx_unlock(NULL);
- }
- }
- return (const char* const*)_isoCountries;
- }
-
- /**
- * Functions to get and set the directory containing the locale data files.
- */
-
- const char*
- uloc_getDataDirectory()
- {
- if (_dataDirectory == NULL)
- {
- uloc_setDataDirectory(icu_getDefaultDataDirectory());
- }
- return _dataDirectory;
- }
-
- void
- uloc_setDataDirectory(const char* newDirectory)
- {
- char* newDataDirectory = (char*) icu_malloc(sizeof(char)*(icu_strlen(newDirectory) + 1));
- icu_strcpy(newDataDirectory, newDirectory);
-
- {
- umtx_lock(NULL);
-
- if(_dataDirectory != NULL)
- icu_free(_dataDirectory);
- _dataDirectory = newDataDirectory;
- if(_installedLocales != NULL)
- icu_free(_installedLocales);
- _installedLocales = NULL;
- umtx_unlock(NULL);
- }
- }
-