1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/i18n/locdspnm.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,971 @@ 1.4 +/* 1.5 +******************************************************************************* 1.6 +* Copyright (C) 2010-2013, International Business Machines Corporation and 1.7 +* others. All Rights Reserved. 1.8 +******************************************************************************* 1.9 +*/ 1.10 + 1.11 +#include "unicode/utypes.h" 1.12 + 1.13 +#if !UCONFIG_NO_FORMATTING 1.14 + 1.15 +#include "unicode/locdspnm.h" 1.16 +#include "unicode/msgfmt.h" 1.17 +#include "unicode/ures.h" 1.18 +#include "unicode/brkiter.h" 1.19 + 1.20 +#include "cmemory.h" 1.21 +#include "cstring.h" 1.22 +#include "ulocimp.h" 1.23 +#include "ureslocs.h" 1.24 +#include "uresimp.h" 1.25 + 1.26 +#include <stdarg.h> 1.27 + 1.28 +/** 1.29 + * Concatenate a number of null-terminated strings to buffer, leaving a 1.30 + * null-terminated string. The last argument should be the null pointer. 1.31 + * Return the length of the string in the buffer, not counting the trailing 1.32 + * null. Return -1 if there is an error (buffer is null, or buflen < 1). 1.33 + */ 1.34 +static int32_t ncat(char *buffer, uint32_t buflen, ...) { 1.35 + va_list args; 1.36 + char *str; 1.37 + char *p = buffer; 1.38 + const char* e = buffer + buflen - 1; 1.39 + 1.40 + if (buffer == NULL || buflen < 1) { 1.41 + return -1; 1.42 + } 1.43 + 1.44 + va_start(args, buflen); 1.45 + while ((str = va_arg(args, char *))) { 1.46 + char c; 1.47 + while (p != e && (c = *str++)) { 1.48 + *p++ = c; 1.49 + } 1.50 + } 1.51 + *p = 0; 1.52 + va_end(args); 1.53 + 1.54 + return p - buffer; 1.55 +} 1.56 + 1.57 +U_NAMESPACE_BEGIN 1.58 + 1.59 +//////////////////////////////////////////////////////////////////////////////////////////////////// 1.60 + 1.61 +// Access resource data for locale components. 1.62 +// Wrap code in uloc.c for now. 1.63 +class ICUDataTable { 1.64 + const char* path; 1.65 + Locale locale; 1.66 + 1.67 +public: 1.68 + ICUDataTable(const char* path, const Locale& locale); 1.69 + ~ICUDataTable(); 1.70 + 1.71 + const Locale& getLocale(); 1.72 + 1.73 + UnicodeString& get(const char* tableKey, const char* itemKey, 1.74 + UnicodeString& result) const; 1.75 + UnicodeString& get(const char* tableKey, const char* subTableKey, const char* itemKey, 1.76 + UnicodeString& result) const; 1.77 + 1.78 + UnicodeString& getNoFallback(const char* tableKey, const char* itemKey, 1.79 + UnicodeString &result) const; 1.80 + UnicodeString& getNoFallback(const char* tableKey, const char* subTableKey, const char* itemKey, 1.81 + UnicodeString &result) const; 1.82 +}; 1.83 + 1.84 +inline UnicodeString & 1.85 +ICUDataTable::get(const char* tableKey, const char* itemKey, UnicodeString& result) const { 1.86 + return get(tableKey, NULL, itemKey, result); 1.87 +} 1.88 + 1.89 +inline UnicodeString & 1.90 +ICUDataTable::getNoFallback(const char* tableKey, const char* itemKey, UnicodeString& result) const { 1.91 + return getNoFallback(tableKey, NULL, itemKey, result); 1.92 +} 1.93 + 1.94 +ICUDataTable::ICUDataTable(const char* path, const Locale& locale) 1.95 + : path(NULL), locale(Locale::getRoot()) 1.96 +{ 1.97 + if (path) { 1.98 + int32_t len = uprv_strlen(path); 1.99 + this->path = (const char*) uprv_malloc(len + 1); 1.100 + if (this->path) { 1.101 + uprv_strcpy((char *)this->path, path); 1.102 + this->locale = locale; 1.103 + } 1.104 + } 1.105 +} 1.106 + 1.107 +ICUDataTable::~ICUDataTable() { 1.108 + if (path) { 1.109 + uprv_free((void*) path); 1.110 + path = NULL; 1.111 + } 1.112 +} 1.113 + 1.114 +const Locale& 1.115 +ICUDataTable::getLocale() { 1.116 + return locale; 1.117 +} 1.118 + 1.119 +UnicodeString & 1.120 +ICUDataTable::get(const char* tableKey, const char* subTableKey, const char* itemKey, 1.121 + UnicodeString &result) const { 1.122 + UErrorCode status = U_ZERO_ERROR; 1.123 + int32_t len = 0; 1.124 + 1.125 + const UChar *s = uloc_getTableStringWithFallback(path, locale.getName(), 1.126 + tableKey, subTableKey, itemKey, 1.127 + &len, &status); 1.128 + if (U_SUCCESS(status) && len > 0) { 1.129 + return result.setTo(s, len); 1.130 + } 1.131 + return result.setTo(UnicodeString(itemKey, -1, US_INV)); 1.132 +} 1.133 + 1.134 +UnicodeString & 1.135 +ICUDataTable::getNoFallback(const char* tableKey, const char* subTableKey, const char* itemKey, 1.136 + UnicodeString& result) const { 1.137 + UErrorCode status = U_ZERO_ERROR; 1.138 + int32_t len = 0; 1.139 + 1.140 + const UChar *s = uloc_getTableStringWithFallback(path, locale.getName(), 1.141 + tableKey, subTableKey, itemKey, 1.142 + &len, &status); 1.143 + if (U_SUCCESS(status)) { 1.144 + return result.setTo(s, len); 1.145 + } 1.146 + 1.147 + result.setToBogus(); 1.148 + return result; 1.149 +} 1.150 + 1.151 +//////////////////////////////////////////////////////////////////////////////////////////////////// 1.152 + 1.153 +LocaleDisplayNames::~LocaleDisplayNames() {} 1.154 + 1.155 +//////////////////////////////////////////////////////////////////////////////////////////////////// 1.156 + 1.157 +#if 0 // currently unused 1.158 + 1.159 +class DefaultLocaleDisplayNames : public LocaleDisplayNames { 1.160 + UDialectHandling dialectHandling; 1.161 + 1.162 +public: 1.163 + // constructor 1.164 + DefaultLocaleDisplayNames(UDialectHandling dialectHandling); 1.165 + 1.166 + virtual ~DefaultLocaleDisplayNames(); 1.167 + 1.168 + virtual const Locale& getLocale() const; 1.169 + virtual UDialectHandling getDialectHandling() const; 1.170 + 1.171 + virtual UnicodeString& localeDisplayName(const Locale& locale, 1.172 + UnicodeString& result) const; 1.173 + virtual UnicodeString& localeDisplayName(const char* localeId, 1.174 + UnicodeString& result) const; 1.175 + virtual UnicodeString& languageDisplayName(const char* lang, 1.176 + UnicodeString& result) const; 1.177 + virtual UnicodeString& scriptDisplayName(const char* script, 1.178 + UnicodeString& result) const; 1.179 + virtual UnicodeString& scriptDisplayName(UScriptCode scriptCode, 1.180 + UnicodeString& result) const; 1.181 + virtual UnicodeString& regionDisplayName(const char* region, 1.182 + UnicodeString& result) const; 1.183 + virtual UnicodeString& variantDisplayName(const char* variant, 1.184 + UnicodeString& result) const; 1.185 + virtual UnicodeString& keyDisplayName(const char* key, 1.186 + UnicodeString& result) const; 1.187 + virtual UnicodeString& keyValueDisplayName(const char* key, 1.188 + const char* value, 1.189 + UnicodeString& result) const; 1.190 +}; 1.191 + 1.192 +DefaultLocaleDisplayNames::DefaultLocaleDisplayNames(UDialectHandling dialectHandling) 1.193 + : dialectHandling(dialectHandling) { 1.194 +} 1.195 + 1.196 +DefaultLocaleDisplayNames::~DefaultLocaleDisplayNames() { 1.197 +} 1.198 + 1.199 +const Locale& 1.200 +DefaultLocaleDisplayNames::getLocale() const { 1.201 + return Locale::getRoot(); 1.202 +} 1.203 + 1.204 +UDialectHandling 1.205 +DefaultLocaleDisplayNames::getDialectHandling() const { 1.206 + return dialectHandling; 1.207 +} 1.208 + 1.209 +UnicodeString& 1.210 +DefaultLocaleDisplayNames::localeDisplayName(const Locale& locale, 1.211 + UnicodeString& result) const { 1.212 + return result = UnicodeString(locale.getName(), -1, US_INV); 1.213 +} 1.214 + 1.215 +UnicodeString& 1.216 +DefaultLocaleDisplayNames::localeDisplayName(const char* localeId, 1.217 + UnicodeString& result) const { 1.218 + return result = UnicodeString(localeId, -1, US_INV); 1.219 +} 1.220 + 1.221 +UnicodeString& 1.222 +DefaultLocaleDisplayNames::languageDisplayName(const char* lang, 1.223 + UnicodeString& result) const { 1.224 + return result = UnicodeString(lang, -1, US_INV); 1.225 +} 1.226 + 1.227 +UnicodeString& 1.228 +DefaultLocaleDisplayNames::scriptDisplayName(const char* script, 1.229 + UnicodeString& result) const { 1.230 + return result = UnicodeString(script, -1, US_INV); 1.231 +} 1.232 + 1.233 +UnicodeString& 1.234 +DefaultLocaleDisplayNames::scriptDisplayName(UScriptCode scriptCode, 1.235 + UnicodeString& result) const { 1.236 + const char* name = uscript_getName(scriptCode); 1.237 + if (name) { 1.238 + return result = UnicodeString(name, -1, US_INV); 1.239 + } 1.240 + return result.remove(); 1.241 +} 1.242 + 1.243 +UnicodeString& 1.244 +DefaultLocaleDisplayNames::regionDisplayName(const char* region, 1.245 + UnicodeString& result) const { 1.246 + return result = UnicodeString(region, -1, US_INV); 1.247 +} 1.248 + 1.249 +UnicodeString& 1.250 +DefaultLocaleDisplayNames::variantDisplayName(const char* variant, 1.251 + UnicodeString& result) const { 1.252 + return result = UnicodeString(variant, -1, US_INV); 1.253 +} 1.254 + 1.255 +UnicodeString& 1.256 +DefaultLocaleDisplayNames::keyDisplayName(const char* key, 1.257 + UnicodeString& result) const { 1.258 + return result = UnicodeString(key, -1, US_INV); 1.259 +} 1.260 + 1.261 +UnicodeString& 1.262 +DefaultLocaleDisplayNames::keyValueDisplayName(const char* /* key */, 1.263 + const char* value, 1.264 + UnicodeString& result) const { 1.265 + return result = UnicodeString(value, -1, US_INV); 1.266 +} 1.267 + 1.268 +#endif // currently unused class DefaultLocaleDisplayNames 1.269 + 1.270 +//////////////////////////////////////////////////////////////////////////////////////////////////// 1.271 + 1.272 +class LocaleDisplayNamesImpl : public LocaleDisplayNames { 1.273 + Locale locale; 1.274 + UDialectHandling dialectHandling; 1.275 + ICUDataTable langData; 1.276 + ICUDataTable regionData; 1.277 + MessageFormat *separatorFormat; 1.278 + MessageFormat *format; 1.279 + MessageFormat *keyTypeFormat; 1.280 + UDisplayContext capitalizationContext; 1.281 + UnicodeString formatOpenParen; 1.282 + UnicodeString formatReplaceOpenParen; 1.283 + UnicodeString formatCloseParen; 1.284 + UnicodeString formatReplaceCloseParen; 1.285 + 1.286 + // Constants for capitalization context usage types. 1.287 + enum CapContextUsage { 1.288 + kCapContextUsageLanguage, 1.289 + kCapContextUsageScript, 1.290 + kCapContextUsageTerritory, 1.291 + kCapContextUsageVariant, 1.292 + kCapContextUsageKey, 1.293 + kCapContextUsageType, 1.294 + kCapContextUsageCount 1.295 + }; 1.296 + // Capitalization transforms. For each usage type, the first array element indicates 1.297 + // whether to titlecase for uiListOrMenu context, the second indicates whether to 1.298 + // titlecase for stand-alone context. 1.299 + UBool fCapitalization[kCapContextUsageCount][2]; 1.300 + 1.301 +public: 1.302 + // constructor 1.303 + LocaleDisplayNamesImpl(const Locale& locale, UDialectHandling dialectHandling); 1.304 + LocaleDisplayNamesImpl(const Locale& locale, UDisplayContext *contexts, int32_t length); 1.305 + virtual ~LocaleDisplayNamesImpl(); 1.306 + 1.307 + virtual const Locale& getLocale() const; 1.308 + virtual UDialectHandling getDialectHandling() const; 1.309 + virtual UDisplayContext getContext(UDisplayContextType type) const; 1.310 + 1.311 + virtual UnicodeString& localeDisplayName(const Locale& locale, 1.312 + UnicodeString& result) const; 1.313 + virtual UnicodeString& localeDisplayName(const char* localeId, 1.314 + UnicodeString& result) const; 1.315 + virtual UnicodeString& languageDisplayName(const char* lang, 1.316 + UnicodeString& result) const; 1.317 + virtual UnicodeString& scriptDisplayName(const char* script, 1.318 + UnicodeString& result) const; 1.319 + virtual UnicodeString& scriptDisplayName(UScriptCode scriptCode, 1.320 + UnicodeString& result) const; 1.321 + virtual UnicodeString& regionDisplayName(const char* region, 1.322 + UnicodeString& result) const; 1.323 + virtual UnicodeString& variantDisplayName(const char* variant, 1.324 + UnicodeString& result) const; 1.325 + virtual UnicodeString& keyDisplayName(const char* key, 1.326 + UnicodeString& result) const; 1.327 + virtual UnicodeString& keyValueDisplayName(const char* key, 1.328 + const char* value, 1.329 + UnicodeString& result) const; 1.330 +private: 1.331 + UnicodeString& localeIdName(const char* localeId, 1.332 + UnicodeString& result) const; 1.333 + UnicodeString& appendWithSep(UnicodeString& buffer, const UnicodeString& src) const; 1.334 + UnicodeString& adjustForUsageAndContext(CapContextUsage usage, UnicodeString& result) const; 1.335 + void initialize(void); 1.336 +}; 1.337 + 1.338 +LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale, 1.339 + UDialectHandling dialectHandling) 1.340 + : dialectHandling(dialectHandling) 1.341 + , langData(U_ICUDATA_LANG, locale) 1.342 + , regionData(U_ICUDATA_REGION, locale) 1.343 + , separatorFormat(NULL) 1.344 + , format(NULL) 1.345 + , keyTypeFormat(NULL) 1.346 + , capitalizationContext(UDISPCTX_CAPITALIZATION_NONE) 1.347 +{ 1.348 + initialize(); 1.349 +} 1.350 + 1.351 +LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale, 1.352 + UDisplayContext *contexts, int32_t length) 1.353 + : dialectHandling(ULDN_STANDARD_NAMES) 1.354 + , langData(U_ICUDATA_LANG, locale) 1.355 + , regionData(U_ICUDATA_REGION, locale) 1.356 + , separatorFormat(NULL) 1.357 + , format(NULL) 1.358 + , keyTypeFormat(NULL) 1.359 + , capitalizationContext(UDISPCTX_CAPITALIZATION_NONE) 1.360 +{ 1.361 + while (length-- > 0) { 1.362 + UDisplayContext value = *contexts++; 1.363 + UDisplayContextType selector = (UDisplayContextType)((uint32_t)value >> 8); 1.364 + switch (selector) { 1.365 + case UDISPCTX_TYPE_DIALECT_HANDLING: 1.366 + dialectHandling = (UDialectHandling)value; 1.367 + break; 1.368 + case UDISPCTX_TYPE_CAPITALIZATION: 1.369 + capitalizationContext = value; 1.370 + break; 1.371 + default: 1.372 + break; 1.373 + } 1.374 + } 1.375 + initialize(); 1.376 +} 1.377 + 1.378 +void 1.379 +LocaleDisplayNamesImpl::initialize(void) { 1.380 + LocaleDisplayNamesImpl *nonConstThis = (LocaleDisplayNamesImpl *)this; 1.381 + nonConstThis->locale = langData.getLocale() == Locale::getRoot() 1.382 + ? regionData.getLocale() 1.383 + : langData.getLocale(); 1.384 + 1.385 + UnicodeString sep; 1.386 + langData.getNoFallback("localeDisplayPattern", "separator", sep); 1.387 + if (sep.isBogus()) { 1.388 + sep = UnicodeString("{0}, {1}", -1, US_INV); 1.389 + } 1.390 + UErrorCode status = U_ZERO_ERROR; 1.391 + separatorFormat = new MessageFormat(sep, status); 1.392 + 1.393 + UnicodeString pattern; 1.394 + langData.getNoFallback("localeDisplayPattern", "pattern", pattern); 1.395 + if (pattern.isBogus()) { 1.396 + pattern = UnicodeString("{0} ({1})", -1, US_INV); 1.397 + } 1.398 + format = new MessageFormat(pattern, status); 1.399 + if (pattern.indexOf((UChar)0xFF08) >= 0) { 1.400 + formatOpenParen.setTo((UChar)0xFF08); // fullwidth ( 1.401 + formatReplaceOpenParen.setTo((UChar)0xFF3B); // fullwidth [ 1.402 + formatCloseParen.setTo((UChar)0xFF09); // fullwidth ) 1.403 + formatReplaceCloseParen.setTo((UChar)0xFF3D); // fullwidth ] 1.404 + } else { 1.405 + formatOpenParen.setTo((UChar)0x0028); // ( 1.406 + formatReplaceOpenParen.setTo((UChar)0x005B); // [ 1.407 + formatCloseParen.setTo((UChar)0x0029); // ) 1.408 + formatReplaceCloseParen.setTo((UChar)0x005D); // ] 1.409 + } 1.410 + 1.411 + UnicodeString ktPattern; 1.412 + langData.get("localeDisplayPattern", "keyTypePattern", ktPattern); 1.413 + if (ktPattern.isBogus()) { 1.414 + ktPattern = UnicodeString("{0}={1}", -1, US_INV); 1.415 + } 1.416 + keyTypeFormat = new MessageFormat(ktPattern, status); 1.417 + 1.418 + uprv_memset(fCapitalization, 0, sizeof(fCapitalization)); 1.419 +#if !UCONFIG_NO_BREAK_ITERATION 1.420 + // The following is basically copied from DateFormatSymbols::initializeData 1.421 + typedef struct { 1.422 + const char * usageName; 1.423 + LocaleDisplayNamesImpl::CapContextUsage usageEnum; 1.424 + } ContextUsageNameToEnum; 1.425 + const ContextUsageNameToEnum contextUsageTypeMap[] = { 1.426 + // Entries must be sorted by usageTypeName; entry with NULL name terminates list. 1.427 + { "key", kCapContextUsageKey }, 1.428 + { "languages", kCapContextUsageLanguage }, 1.429 + { "script", kCapContextUsageScript }, 1.430 + { "territory", kCapContextUsageTerritory }, 1.431 + { "type", kCapContextUsageType }, 1.432 + { "variant", kCapContextUsageVariant }, 1.433 + { NULL, (CapContextUsage)0 }, 1.434 + }; 1.435 + int32_t len = 0; 1.436 + UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &status); 1.437 + if (U_SUCCESS(status)) { 1.438 + UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, "contextTransforms", NULL, &status); 1.439 + if (U_SUCCESS(status)) { 1.440 + UResourceBundle *contextTransformUsage; 1.441 + while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &status)) != NULL ) { 1.442 + const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status); 1.443 + if (U_SUCCESS(status) && intVector != NULL && len >= 2) { 1.444 + const char* usageKey = ures_getKey(contextTransformUsage); 1.445 + if (usageKey != NULL) { 1.446 + const ContextUsageNameToEnum * typeMapPtr = contextUsageTypeMap; 1.447 + int32_t compResult = 0; 1.448 + // linear search; list is short and we cannot be sure that bsearch is available 1.449 + while ( typeMapPtr->usageName != NULL && (compResult = uprv_strcmp(usageKey, typeMapPtr->usageName)) > 0 ) { 1.450 + ++typeMapPtr; 1.451 + } 1.452 + if (typeMapPtr->usageName != NULL && compResult == 0) { 1.453 + fCapitalization[typeMapPtr->usageEnum][0] = intVector[0]; 1.454 + fCapitalization[typeMapPtr->usageEnum][1] = intVector[1]; 1.455 + } 1.456 + } 1.457 + } 1.458 + status = U_ZERO_ERROR; 1.459 + ures_close(contextTransformUsage); 1.460 + } 1.461 + ures_close(contextTransforms); 1.462 + } 1.463 + ures_close(localeBundle); 1.464 + } 1.465 +#endif 1.466 +} 1.467 + 1.468 +LocaleDisplayNamesImpl::~LocaleDisplayNamesImpl() { 1.469 + delete separatorFormat; 1.470 + delete format; 1.471 + delete keyTypeFormat; 1.472 + } 1.473 + 1.474 +const Locale& 1.475 +LocaleDisplayNamesImpl::getLocale() const { 1.476 + return locale; 1.477 +} 1.478 + 1.479 +UDialectHandling 1.480 +LocaleDisplayNamesImpl::getDialectHandling() const { 1.481 + return dialectHandling; 1.482 +} 1.483 + 1.484 +UDisplayContext 1.485 +LocaleDisplayNamesImpl::getContext(UDisplayContextType type) const { 1.486 + switch (type) { 1.487 + case UDISPCTX_TYPE_DIALECT_HANDLING: 1.488 + return (UDisplayContext)dialectHandling; 1.489 + case UDISPCTX_TYPE_CAPITALIZATION: 1.490 + return capitalizationContext; 1.491 + default: 1.492 + break; 1.493 + } 1.494 + return (UDisplayContext)0; 1.495 +} 1.496 + 1.497 +UnicodeString& 1.498 +LocaleDisplayNamesImpl::adjustForUsageAndContext(CapContextUsage usage, 1.499 + UnicodeString& result) const { 1.500 +#if !UCONFIG_NO_BREAK_ITERATION 1.501 + // check to see whether we need to titlecase result 1.502 + UBool titlecase = FALSE; 1.503 + switch (capitalizationContext) { 1.504 + case UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE: 1.505 + titlecase = TRUE; 1.506 + break; 1.507 + case UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU: 1.508 + titlecase = fCapitalization[usage][0]; 1.509 + break; 1.510 + case UDISPCTX_CAPITALIZATION_FOR_STANDALONE: 1.511 + titlecase = fCapitalization[usage][1]; 1.512 + break; 1.513 + default: 1.514 + // titlecase = FALSE; 1.515 + break; 1.516 + } 1.517 + if (titlecase) { 1.518 + // TODO: Fix this titlecase hack when we figure out something better to do. 1.519 + // We don't want to titlecase the whole text, only something like the first word, 1.520 + // of the first segment long enough to have a complete cluster, whichever is 1.521 + // shorter. We could have keep a word break iterator around, but I am not sure 1.522 + // that will do the ight thing for the purposes here. For now we assume that in 1.523 + // languages for which titlecasing makes a difference, we can stop at non-letter 1.524 + // characters in 0x0000-0x00FF and only titlecase up to the first occurrence of 1.525 + // any of those, or to a small number of chars, whichever comes first. 1.526 + int32_t stopPos, stopPosLimit = 8, len = result.length(); 1.527 + if ( stopPosLimit > len ) { 1.528 + stopPosLimit = len; 1.529 + } 1.530 + for ( stopPos = 0; stopPos < stopPosLimit; stopPos++ ) { 1.531 + UChar32 ch = result.char32At(stopPos); 1.532 + if ( (ch < 0x41) || (ch > 0x5A && ch < 0x61) || (ch > 0x7A && ch < 0xC0) ) { 1.533 + break; 1.534 + } 1.535 + if (ch >= 0x10000) { 1.536 + stopPos++; 1.537 + } 1.538 + } 1.539 + if ( stopPos > 0 && stopPos < len ) { 1.540 + UnicodeString firstWord(result, 0, stopPos); 1.541 + firstWord.toTitle(NULL, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT); 1.542 + result.replaceBetween(0, stopPos, firstWord); 1.543 + } else { 1.544 + // no stopPos, titlecase the whole text 1.545 + result.toTitle(NULL, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT); 1.546 + } 1.547 + } 1.548 +#endif 1.549 + return result; 1.550 +} 1.551 + 1.552 +UnicodeString& 1.553 +LocaleDisplayNamesImpl::localeDisplayName(const Locale& locale, 1.554 + UnicodeString& result) const { 1.555 + UnicodeString resultName; 1.556 + 1.557 + const char* lang = locale.getLanguage(); 1.558 + if (uprv_strlen(lang) == 0) { 1.559 + lang = "root"; 1.560 + } 1.561 + const char* script = locale.getScript(); 1.562 + const char* country = locale.getCountry(); 1.563 + const char* variant = locale.getVariant(); 1.564 + 1.565 + UBool hasScript = uprv_strlen(script) > 0; 1.566 + UBool hasCountry = uprv_strlen(country) > 0; 1.567 + UBool hasVariant = uprv_strlen(variant) > 0; 1.568 + 1.569 + if (dialectHandling == ULDN_DIALECT_NAMES) { 1.570 + char buffer[ULOC_FULLNAME_CAPACITY]; 1.571 + do { // loop construct is so we can break early out of search 1.572 + if (hasScript && hasCountry) { 1.573 + ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, "_", country, (char *)0); 1.574 + localeIdName(buffer, resultName); 1.575 + if (!resultName.isBogus()) { 1.576 + hasScript = FALSE; 1.577 + hasCountry = FALSE; 1.578 + break; 1.579 + } 1.580 + } 1.581 + if (hasScript) { 1.582 + ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, (char *)0); 1.583 + localeIdName(buffer, resultName); 1.584 + if (!resultName.isBogus()) { 1.585 + hasScript = FALSE; 1.586 + break; 1.587 + } 1.588 + } 1.589 + if (hasCountry) { 1.590 + ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", country, (char*)0); 1.591 + localeIdName(buffer, resultName); 1.592 + if (!resultName.isBogus()) { 1.593 + hasCountry = FALSE; 1.594 + break; 1.595 + } 1.596 + } 1.597 + } while (FALSE); 1.598 + } 1.599 + if (resultName.isBogus() || resultName.isEmpty()) { 1.600 + localeIdName(lang, resultName); 1.601 + } 1.602 + 1.603 + UnicodeString resultRemainder; 1.604 + UnicodeString temp; 1.605 + StringEnumeration *e = NULL; 1.606 + UErrorCode status = U_ZERO_ERROR; 1.607 + 1.608 + if (hasScript) { 1.609 + resultRemainder.append(scriptDisplayName(script, temp)); 1.610 + } 1.611 + if (hasCountry) { 1.612 + appendWithSep(resultRemainder, regionDisplayName(country, temp)); 1.613 + } 1.614 + if (hasVariant) { 1.615 + appendWithSep(resultRemainder, variantDisplayName(variant, temp)); 1.616 + } 1.617 + resultRemainder.findAndReplace(formatOpenParen, formatReplaceOpenParen); 1.618 + resultRemainder.findAndReplace(formatCloseParen, formatReplaceCloseParen); 1.619 + 1.620 + e = locale.createKeywords(status); 1.621 + if (e && U_SUCCESS(status)) { 1.622 + UnicodeString temp2; 1.623 + char value[ULOC_KEYWORD_AND_VALUES_CAPACITY]; // sigh, no ULOC_VALUE_CAPACITY 1.624 + const char* key; 1.625 + while ((key = e->next((int32_t *)0, status)) != NULL) { 1.626 + locale.getKeywordValue(key, value, ULOC_KEYWORD_AND_VALUES_CAPACITY, status); 1.627 + keyDisplayName(key, temp); 1.628 + temp.findAndReplace(formatOpenParen, formatReplaceOpenParen); 1.629 + temp.findAndReplace(formatCloseParen, formatReplaceCloseParen); 1.630 + keyValueDisplayName(key, value, temp2); 1.631 + temp2.findAndReplace(formatOpenParen, formatReplaceOpenParen); 1.632 + temp2.findAndReplace(formatCloseParen, formatReplaceCloseParen); 1.633 + if (temp2 != UnicodeString(value, -1, US_INV)) { 1.634 + appendWithSep(resultRemainder, temp2); 1.635 + } else if (temp != UnicodeString(key, -1, US_INV)) { 1.636 + UnicodeString temp3; 1.637 + Formattable data[] = { 1.638 + temp, 1.639 + temp2 1.640 + }; 1.641 + FieldPosition fpos; 1.642 + status = U_ZERO_ERROR; 1.643 + keyTypeFormat->format(data, 2, temp3, fpos, status); 1.644 + appendWithSep(resultRemainder, temp3); 1.645 + } else { 1.646 + appendWithSep(resultRemainder, temp) 1.647 + .append((UChar)0x3d /* = */) 1.648 + .append(temp2); 1.649 + } 1.650 + } 1.651 + delete e; 1.652 + } 1.653 + 1.654 + if (!resultRemainder.isEmpty()) { 1.655 + Formattable data[] = { 1.656 + resultName, 1.657 + resultRemainder 1.658 + }; 1.659 + FieldPosition fpos; 1.660 + status = U_ZERO_ERROR; 1.661 + format->format(data, 2, result, fpos, status); 1.662 + return adjustForUsageAndContext(kCapContextUsageLanguage, result); 1.663 + } 1.664 + 1.665 + result = resultName; 1.666 + return adjustForUsageAndContext(kCapContextUsageLanguage, result); 1.667 +} 1.668 + 1.669 +UnicodeString& 1.670 +LocaleDisplayNamesImpl::appendWithSep(UnicodeString& buffer, const UnicodeString& src) const { 1.671 + if (buffer.isEmpty()) { 1.672 + buffer.setTo(src); 1.673 + } else { 1.674 + UnicodeString combined; 1.675 + Formattable data[] = { 1.676 + buffer, 1.677 + src 1.678 + }; 1.679 + FieldPosition fpos; 1.680 + UErrorCode status = U_ZERO_ERROR; 1.681 + separatorFormat->format(data, 2, combined, fpos, status); 1.682 + if (U_SUCCESS(status)) { 1.683 + buffer.setTo(combined); 1.684 + } 1.685 + } 1.686 + return buffer; 1.687 +} 1.688 + 1.689 +UnicodeString& 1.690 +LocaleDisplayNamesImpl::localeDisplayName(const char* localeId, 1.691 + UnicodeString& result) const { 1.692 + return localeDisplayName(Locale(localeId), result); 1.693 +} 1.694 + 1.695 +// private 1.696 +UnicodeString& 1.697 +LocaleDisplayNamesImpl::localeIdName(const char* localeId, 1.698 + UnicodeString& result) const { 1.699 + return langData.getNoFallback("Languages", localeId, result); 1.700 +} 1.701 + 1.702 +UnicodeString& 1.703 +LocaleDisplayNamesImpl::languageDisplayName(const char* lang, 1.704 + UnicodeString& result) const { 1.705 + if (uprv_strcmp("root", lang) == 0 || uprv_strchr(lang, '_') != NULL) { 1.706 + return result = UnicodeString(lang, -1, US_INV); 1.707 + } 1.708 + langData.get("Languages", lang, result); 1.709 + return adjustForUsageAndContext(kCapContextUsageLanguage, result); 1.710 +} 1.711 + 1.712 +UnicodeString& 1.713 +LocaleDisplayNamesImpl::scriptDisplayName(const char* script, 1.714 + UnicodeString& result) const { 1.715 + langData.get("Scripts", script, result); 1.716 + return adjustForUsageAndContext(kCapContextUsageScript, result); 1.717 +} 1.718 + 1.719 +UnicodeString& 1.720 +LocaleDisplayNamesImpl::scriptDisplayName(UScriptCode scriptCode, 1.721 + UnicodeString& result) const { 1.722 + const char* name = uscript_getName(scriptCode); 1.723 + langData.get("Scripts", name, result); 1.724 + return adjustForUsageAndContext(kCapContextUsageScript, result); 1.725 +} 1.726 + 1.727 +UnicodeString& 1.728 +LocaleDisplayNamesImpl::regionDisplayName(const char* region, 1.729 + UnicodeString& result) const { 1.730 + regionData.get("Countries", region, result); 1.731 + return adjustForUsageAndContext(kCapContextUsageTerritory, result); 1.732 +} 1.733 + 1.734 +UnicodeString& 1.735 +LocaleDisplayNamesImpl::variantDisplayName(const char* variant, 1.736 + UnicodeString& result) const { 1.737 + langData.get("Variants", variant, result); 1.738 + return adjustForUsageAndContext(kCapContextUsageVariant, result); 1.739 +} 1.740 + 1.741 +UnicodeString& 1.742 +LocaleDisplayNamesImpl::keyDisplayName(const char* key, 1.743 + UnicodeString& result) const { 1.744 + langData.get("Keys", key, result); 1.745 + return adjustForUsageAndContext(kCapContextUsageKey, result); 1.746 +} 1.747 + 1.748 +UnicodeString& 1.749 +LocaleDisplayNamesImpl::keyValueDisplayName(const char* key, 1.750 + const char* value, 1.751 + UnicodeString& result) const { 1.752 + langData.get("Types", key, value, result); 1.753 + return adjustForUsageAndContext(kCapContextUsageType, result); 1.754 +} 1.755 + 1.756 +//////////////////////////////////////////////////////////////////////////////////////////////////// 1.757 + 1.758 +LocaleDisplayNames* 1.759 +LocaleDisplayNames::createInstance(const Locale& locale, 1.760 + UDialectHandling dialectHandling) { 1.761 + return new LocaleDisplayNamesImpl(locale, dialectHandling); 1.762 +} 1.763 + 1.764 +LocaleDisplayNames* 1.765 +LocaleDisplayNames::createInstance(const Locale& locale, 1.766 + UDisplayContext *contexts, int32_t length) { 1.767 + if (contexts == NULL) { 1.768 + length = 0; 1.769 + } 1.770 + return new LocaleDisplayNamesImpl(locale, contexts, length); 1.771 +} 1.772 + 1.773 +U_NAMESPACE_END 1.774 + 1.775 +//////////////////////////////////////////////////////////////////////////////////////////////////// 1.776 + 1.777 +U_NAMESPACE_USE 1.778 + 1.779 +U_CAPI ULocaleDisplayNames * U_EXPORT2 1.780 +uldn_open(const char * locale, 1.781 + UDialectHandling dialectHandling, 1.782 + UErrorCode *pErrorCode) { 1.783 + if (U_FAILURE(*pErrorCode)) { 1.784 + return 0; 1.785 + } 1.786 + if (locale == NULL) { 1.787 + locale = uloc_getDefault(); 1.788 + } 1.789 + return (ULocaleDisplayNames *)LocaleDisplayNames::createInstance(Locale(locale), dialectHandling); 1.790 +} 1.791 + 1.792 +U_CAPI ULocaleDisplayNames * U_EXPORT2 1.793 +uldn_openForContext(const char * locale, 1.794 + UDisplayContext *contexts, int32_t length, 1.795 + UErrorCode *pErrorCode) { 1.796 + if (U_FAILURE(*pErrorCode)) { 1.797 + return 0; 1.798 + } 1.799 + if (locale == NULL) { 1.800 + locale = uloc_getDefault(); 1.801 + } 1.802 + return (ULocaleDisplayNames *)LocaleDisplayNames::createInstance(Locale(locale), contexts, length); 1.803 +} 1.804 + 1.805 + 1.806 +U_CAPI void U_EXPORT2 1.807 +uldn_close(ULocaleDisplayNames *ldn) { 1.808 + delete (LocaleDisplayNames *)ldn; 1.809 +} 1.810 + 1.811 +U_CAPI const char * U_EXPORT2 1.812 +uldn_getLocale(const ULocaleDisplayNames *ldn) { 1.813 + if (ldn) { 1.814 + return ((const LocaleDisplayNames *)ldn)->getLocale().getName(); 1.815 + } 1.816 + return NULL; 1.817 +} 1.818 + 1.819 +U_CAPI UDialectHandling U_EXPORT2 1.820 +uldn_getDialectHandling(const ULocaleDisplayNames *ldn) { 1.821 + if (ldn) { 1.822 + return ((const LocaleDisplayNames *)ldn)->getDialectHandling(); 1.823 + } 1.824 + return ULDN_STANDARD_NAMES; 1.825 +} 1.826 + 1.827 +U_CAPI UDisplayContext U_EXPORT2 1.828 +uldn_getContext(const ULocaleDisplayNames *ldn, 1.829 + UDisplayContextType type, 1.830 + UErrorCode *pErrorCode) { 1.831 + if (U_FAILURE(*pErrorCode)) { 1.832 + return (UDisplayContext)0; 1.833 + } 1.834 + return ((const LocaleDisplayNames *)ldn)->getContext(type); 1.835 +} 1.836 + 1.837 +U_CAPI int32_t U_EXPORT2 1.838 +uldn_localeDisplayName(const ULocaleDisplayNames *ldn, 1.839 + const char *locale, 1.840 + UChar *result, 1.841 + int32_t maxResultSize, 1.842 + UErrorCode *pErrorCode) { 1.843 + if (U_FAILURE(*pErrorCode)) { 1.844 + return 0; 1.845 + } 1.846 + if (ldn == NULL || locale == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 1.847 + *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 1.848 + return 0; 1.849 + } 1.850 + UnicodeString temp(result, 0, maxResultSize); 1.851 + ((const LocaleDisplayNames *)ldn)->localeDisplayName(locale, temp); 1.852 + return temp.extract(result, maxResultSize, *pErrorCode); 1.853 +} 1.854 + 1.855 +U_CAPI int32_t U_EXPORT2 1.856 +uldn_languageDisplayName(const ULocaleDisplayNames *ldn, 1.857 + const char *lang, 1.858 + UChar *result, 1.859 + int32_t maxResultSize, 1.860 + UErrorCode *pErrorCode) { 1.861 + if (U_FAILURE(*pErrorCode)) { 1.862 + return 0; 1.863 + } 1.864 + if (ldn == NULL || lang == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 1.865 + *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 1.866 + return 0; 1.867 + } 1.868 + UnicodeString temp(result, 0, maxResultSize); 1.869 + ((const LocaleDisplayNames *)ldn)->languageDisplayName(lang, temp); 1.870 + return temp.extract(result, maxResultSize, *pErrorCode); 1.871 +} 1.872 + 1.873 +U_CAPI int32_t U_EXPORT2 1.874 +uldn_scriptDisplayName(const ULocaleDisplayNames *ldn, 1.875 + const char *script, 1.876 + UChar *result, 1.877 + int32_t maxResultSize, 1.878 + UErrorCode *pErrorCode) { 1.879 + if (U_FAILURE(*pErrorCode)) { 1.880 + return 0; 1.881 + } 1.882 + if (ldn == NULL || script == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 1.883 + *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 1.884 + return 0; 1.885 + } 1.886 + UnicodeString temp(result, 0, maxResultSize); 1.887 + ((const LocaleDisplayNames *)ldn)->scriptDisplayName(script, temp); 1.888 + return temp.extract(result, maxResultSize, *pErrorCode); 1.889 +} 1.890 + 1.891 +U_CAPI int32_t U_EXPORT2 1.892 +uldn_scriptCodeDisplayName(const ULocaleDisplayNames *ldn, 1.893 + UScriptCode scriptCode, 1.894 + UChar *result, 1.895 + int32_t maxResultSize, 1.896 + UErrorCode *pErrorCode) { 1.897 + return uldn_scriptDisplayName(ldn, uscript_getName(scriptCode), result, maxResultSize, pErrorCode); 1.898 +} 1.899 + 1.900 +U_CAPI int32_t U_EXPORT2 1.901 +uldn_regionDisplayName(const ULocaleDisplayNames *ldn, 1.902 + const char *region, 1.903 + UChar *result, 1.904 + int32_t maxResultSize, 1.905 + UErrorCode *pErrorCode) { 1.906 + if (U_FAILURE(*pErrorCode)) { 1.907 + return 0; 1.908 + } 1.909 + if (ldn == NULL || region == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 1.910 + *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 1.911 + return 0; 1.912 + } 1.913 + UnicodeString temp(result, 0, maxResultSize); 1.914 + ((const LocaleDisplayNames *)ldn)->regionDisplayName(region, temp); 1.915 + return temp.extract(result, maxResultSize, *pErrorCode); 1.916 +} 1.917 + 1.918 +U_CAPI int32_t U_EXPORT2 1.919 +uldn_variantDisplayName(const ULocaleDisplayNames *ldn, 1.920 + const char *variant, 1.921 + UChar *result, 1.922 + int32_t maxResultSize, 1.923 + UErrorCode *pErrorCode) { 1.924 + if (U_FAILURE(*pErrorCode)) { 1.925 + return 0; 1.926 + } 1.927 + if (ldn == NULL || variant == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 1.928 + *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 1.929 + return 0; 1.930 + } 1.931 + UnicodeString temp(result, 0, maxResultSize); 1.932 + ((const LocaleDisplayNames *)ldn)->variantDisplayName(variant, temp); 1.933 + return temp.extract(result, maxResultSize, *pErrorCode); 1.934 +} 1.935 + 1.936 +U_CAPI int32_t U_EXPORT2 1.937 +uldn_keyDisplayName(const ULocaleDisplayNames *ldn, 1.938 + const char *key, 1.939 + UChar *result, 1.940 + int32_t maxResultSize, 1.941 + UErrorCode *pErrorCode) { 1.942 + if (U_FAILURE(*pErrorCode)) { 1.943 + return 0; 1.944 + } 1.945 + if (ldn == NULL || key == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 1.946 + *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 1.947 + return 0; 1.948 + } 1.949 + UnicodeString temp(result, 0, maxResultSize); 1.950 + ((const LocaleDisplayNames *)ldn)->keyDisplayName(key, temp); 1.951 + return temp.extract(result, maxResultSize, *pErrorCode); 1.952 +} 1.953 + 1.954 +U_CAPI int32_t U_EXPORT2 1.955 +uldn_keyValueDisplayName(const ULocaleDisplayNames *ldn, 1.956 + const char *key, 1.957 + const char *value, 1.958 + UChar *result, 1.959 + int32_t maxResultSize, 1.960 + UErrorCode *pErrorCode) { 1.961 + if (U_FAILURE(*pErrorCode)) { 1.962 + return 0; 1.963 + } 1.964 + if (ldn == NULL || key == NULL || value == NULL || (result == NULL && maxResultSize > 0) 1.965 + || maxResultSize < 0) { 1.966 + *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 1.967 + return 0; 1.968 + } 1.969 + UnicodeString temp(result, 0, maxResultSize); 1.970 + ((const LocaleDisplayNames *)ldn)->keyValueDisplayName(key, value, temp); 1.971 + return temp.extract(result, maxResultSize, *pErrorCode); 1.972 +} 1.973 + 1.974 +#endif