1 /* 2 ******************************************************************************* 3 * Copyright (C) 2010-2012, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ******************************************************************************* 6 */ 7 8 #include "unicode/utypes.h" 9 10 #if !UCONFIG_NO_FORMATTING 11 12 #include "unicode/locdspnm.h" 13 #include "unicode/msgfmt.h" 14 #include "unicode/ures.h" 15 #include "unicode/brkiter.h" 16 17 #include "cmemory.h" 18 #include "cstring.h" 19 #include "ulocimp.h" 20 #include "ureslocs.h" 21 #include "uresimp.h" 22 23 #include <stdarg.h> 24 25 /** 26 * Concatenate a number of null-terminated strings to buffer, leaving a 27 * null-terminated string. The last argument should be the null pointer. 28 * Return the length of the string in the buffer, not counting the trailing 29 * null. Return -1 if there is an error (buffer is null, or buflen < 1). 30 */ 31 static int32_t ncat(char *buffer, uint32_t buflen, ...) { 32 va_list args; 33 char *str; 34 char *p = buffer; 35 const char* e = buffer + buflen - 1; 36 37 if (buffer == NULL || buflen < 1) { 38 return -1; 39 } 40 41 va_start(args, buflen); 42 while ((str = va_arg(args, char *))) { 43 char c; 44 while (p != e && (c = *str++)) { 45 *p++ = c; 46 } 47 } 48 *p = 0; 49 va_end(args); 50 51 return p - buffer; 52 } 53 54 U_NAMESPACE_BEGIN 55 56 //////////////////////////////////////////////////////////////////////////////////////////////////// 57 58 // Access resource data for locale components. 59 // Wrap code in uloc.c for now. 60 class ICUDataTable { 61 const char* path; 62 Locale locale; 63 64 public: 65 ICUDataTable(const char* path, const Locale& locale); 66 ~ICUDataTable(); 67 68 const Locale& getLocale(); 69 70 UnicodeString& get(const char* tableKey, const char* itemKey, 71 UnicodeString& result) const; 72 UnicodeString& get(const char* tableKey, const char* subTableKey, const char* itemKey, 73 UnicodeString& result) const; 74 75 UnicodeString& getNoFallback(const char* tableKey, const char* itemKey, 76 UnicodeString &result) const; 77 UnicodeString& getNoFallback(const char* tableKey, const char* subTableKey, const char* itemKey, 78 UnicodeString &result) const; 79 }; 80 81 inline UnicodeString & 82 ICUDataTable::get(const char* tableKey, const char* itemKey, UnicodeString& result) const { 83 return get(tableKey, NULL, itemKey, result); 84 } 85 86 inline UnicodeString & 87 ICUDataTable::getNoFallback(const char* tableKey, const char* itemKey, UnicodeString& result) const { 88 return getNoFallback(tableKey, NULL, itemKey, result); 89 } 90 91 ICUDataTable::ICUDataTable(const char* path, const Locale& locale) 92 : path(NULL), locale(Locale::getRoot()) 93 { 94 if (path) { 95 int32_t len = uprv_strlen(path); 96 this->path = (const char*) uprv_malloc(len + 1); 97 if (this->path) { 98 uprv_strcpy((char *)this->path, path); 99 this->locale = locale; 100 } 101 } 102 } 103 104 ICUDataTable::~ICUDataTable() { 105 if (path) { 106 uprv_free((void*) path); 107 path = NULL; 108 } 109 } 110 111 const Locale& 112 ICUDataTable::getLocale() { 113 return locale; 114 } 115 116 UnicodeString & 117 ICUDataTable::get(const char* tableKey, const char* subTableKey, const char* itemKey, 118 UnicodeString &result) const { 119 UErrorCode status = U_ZERO_ERROR; 120 int32_t len = 0; 121 122 const UChar *s = uloc_getTableStringWithFallback(path, locale.getName(), 123 tableKey, subTableKey, itemKey, 124 &len, &status); 125 if (U_SUCCESS(status) && len > 0) { 126 return result.setTo(s, len); 127 } 128 return result.setTo(UnicodeString(itemKey, -1, US_INV)); 129 } 130 131 UnicodeString & 132 ICUDataTable::getNoFallback(const char* tableKey, const char* subTableKey, const char* itemKey, 133 UnicodeString& result) const { 134 UErrorCode status = U_ZERO_ERROR; 135 int32_t len = 0; 136 137 const UChar *s = uloc_getTableStringWithFallback(path, locale.getName(), 138 tableKey, subTableKey, itemKey, 139 &len, &status); 140 if (U_SUCCESS(status)) { 141 return result.setTo(s, len); 142 } 143 144 result.setToBogus(); 145 return result; 146 } 147 148 //////////////////////////////////////////////////////////////////////////////////////////////////// 149 150 LocaleDisplayNames::~LocaleDisplayNames() {} 151 152 UOBJECT_DEFINE_NO_RTTI_IMPLEMENTATION(LocaleDisplayNames) 153 154 //////////////////////////////////////////////////////////////////////////////////////////////////// 155 156 #if 0 // currently unused 157 158 class DefaultLocaleDisplayNames : public LocaleDisplayNames { 159 UDialectHandling dialectHandling; 160 161 public: 162 // constructor 163 DefaultLocaleDisplayNames(UDialectHandling dialectHandling); 164 165 virtual ~DefaultLocaleDisplayNames(); 166 167 virtual const Locale& getLocale() const; 168 virtual UDialectHandling getDialectHandling() const; 169 170 virtual UnicodeString& localeDisplayName(const Locale& locale, 171 UnicodeString& result) const; 172 virtual UnicodeString& localeDisplayName(const char* localeId, 173 UnicodeString& result) const; 174 virtual UnicodeString& languageDisplayName(const char* lang, 175 UnicodeString& result) const; 176 virtual UnicodeString& scriptDisplayName(const char* script, 177 UnicodeString& result) const; 178 virtual UnicodeString& scriptDisplayName(UScriptCode scriptCode, 179 UnicodeString& result) const; 180 virtual UnicodeString& regionDisplayName(const char* region, 181 UnicodeString& result) const; 182 virtual UnicodeString& variantDisplayName(const char* variant, 183 UnicodeString& result) const; 184 virtual UnicodeString& keyDisplayName(const char* key, 185 UnicodeString& result) const; 186 virtual UnicodeString& keyValueDisplayName(const char* key, 187 const char* value, 188 UnicodeString& result) const; 189 }; 190 191 DefaultLocaleDisplayNames::DefaultLocaleDisplayNames(UDialectHandling dialectHandling) 192 : dialectHandling(dialectHandling) { 193 } 194 195 DefaultLocaleDisplayNames::~DefaultLocaleDisplayNames() { 196 } 197 198 const Locale& 199 DefaultLocaleDisplayNames::getLocale() const { 200 return Locale::getRoot(); 201 } 202 203 UDialectHandling 204 DefaultLocaleDisplayNames::getDialectHandling() const { 205 return dialectHandling; 206 } 207 208 UnicodeString& 209 DefaultLocaleDisplayNames::localeDisplayName(const Locale& locale, 210 UnicodeString& result) const { 211 return result = UnicodeString(locale.getName(), -1, US_INV); 212 } 213 214 UnicodeString& 215 DefaultLocaleDisplayNames::localeDisplayName(const char* localeId, 216 UnicodeString& result) const { 217 return result = UnicodeString(localeId, -1, US_INV); 218 } 219 220 UnicodeString& 221 DefaultLocaleDisplayNames::languageDisplayName(const char* lang, 222 UnicodeString& result) const { 223 return result = UnicodeString(lang, -1, US_INV); 224 } 225 226 UnicodeString& 227 DefaultLocaleDisplayNames::scriptDisplayName(const char* script, 228 UnicodeString& result) const { 229 return result = UnicodeString(script, -1, US_INV); 230 } 231 232 UnicodeString& 233 DefaultLocaleDisplayNames::scriptDisplayName(UScriptCode scriptCode, 234 UnicodeString& result) const { 235 const char* name = uscript_getName(scriptCode); 236 if (name) { 237 return result = UnicodeString(name, -1, US_INV); 238 } 239 return result.remove(); 240 } 241 242 UnicodeString& 243 DefaultLocaleDisplayNames::regionDisplayName(const char* region, 244 UnicodeString& result) const { 245 return result = UnicodeString(region, -1, US_INV); 246 } 247 248 UnicodeString& 249 DefaultLocaleDisplayNames::variantDisplayName(const char* variant, 250 UnicodeString& result) const { 251 return result = UnicodeString(variant, -1, US_INV); 252 } 253 254 UnicodeString& 255 DefaultLocaleDisplayNames::keyDisplayName(const char* key, 256 UnicodeString& result) const { 257 return result = UnicodeString(key, -1, US_INV); 258 } 259 260 UnicodeString& 261 DefaultLocaleDisplayNames::keyValueDisplayName(const char* /* key */, 262 const char* value, 263 UnicodeString& result) const { 264 return result = UnicodeString(value, -1, US_INV); 265 } 266 267 #endif // currently unused class DefaultLocaleDisplayNames 268 269 //////////////////////////////////////////////////////////////////////////////////////////////////// 270 271 class LocaleDisplayNamesImpl : public LocaleDisplayNames { 272 Locale locale; 273 UDialectHandling dialectHandling; 274 ICUDataTable langData; 275 ICUDataTable regionData; 276 UnicodeString sep; 277 MessageFormat *format; 278 MessageFormat *keyTypeFormat; 279 UDisplayContext capitalizationContext; 280 281 // Constants for capitalization context usage types. 282 enum CapContextUsage { 283 kCapContextUsageLanguage, 284 kCapContextUsageScript, 285 kCapContextUsageTerritory, 286 kCapContextUsageVariant, 287 kCapContextUsageKey, 288 kCapContextUsageType, 289 kCapContextUsageCount 290 }; 291 // Capitalization transforms. For each usage type, the first array element indicates 292 // whether to titlecase for uiListOrMenu context, the second indicates whether to 293 // titlecase for stand-alone context. 294 UBool fCapitalization[kCapContextUsageCount][2]; 295 296 public: 297 // constructor 298 LocaleDisplayNamesImpl(const Locale& locale, UDialectHandling dialectHandling); 299 LocaleDisplayNamesImpl(const Locale& locale, UDisplayContext *contexts, int32_t length); 300 virtual ~LocaleDisplayNamesImpl(); 301 302 virtual const Locale& getLocale() const; 303 virtual UDialectHandling getDialectHandling() const; 304 virtual UDisplayContext getContext(UDisplayContextType type) const; 305 306 virtual UnicodeString& localeDisplayName(const Locale& locale, 307 UnicodeString& result) const; 308 virtual UnicodeString& localeDisplayName(const char* localeId, 309 UnicodeString& result) const; 310 virtual UnicodeString& languageDisplayName(const char* lang, 311 UnicodeString& result) const; 312 virtual UnicodeString& scriptDisplayName(const char* script, 313 UnicodeString& result) const; 314 virtual UnicodeString& scriptDisplayName(UScriptCode scriptCode, 315 UnicodeString& result) const; 316 virtual UnicodeString& regionDisplayName(const char* region, 317 UnicodeString& result) const; 318 virtual UnicodeString& variantDisplayName(const char* variant, 319 UnicodeString& result) const; 320 virtual UnicodeString& keyDisplayName(const char* key, 321 UnicodeString& result) const; 322 virtual UnicodeString& keyValueDisplayName(const char* key, 323 const char* value, 324 UnicodeString& result) const; 325 private: 326 UnicodeString& localeIdName(const char* localeId, 327 UnicodeString& result) const; 328 UnicodeString& appendWithSep(UnicodeString& buffer, const UnicodeString& src) const; 329 UnicodeString& adjustForUsageAndContext(CapContextUsage usage, UnicodeString& result) const; 330 void initialize(void); 331 }; 332 333 LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale, 334 UDialectHandling dialectHandling) 335 : dialectHandling(dialectHandling) 336 , langData(U_ICUDATA_LANG, locale) 337 , regionData(U_ICUDATA_REGION, locale) 338 , format(NULL) 339 , keyTypeFormat(NULL) 340 , capitalizationContext(UDISPCTX_CAPITALIZATION_NONE) 341 { 342 initialize(); 343 } 344 345 LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale, 346 UDisplayContext *contexts, int32_t length) 347 : dialectHandling(ULDN_STANDARD_NAMES) 348 , langData(U_ICUDATA_LANG, locale) 349 , regionData(U_ICUDATA_REGION, locale) 350 , format(NULL) 351 , keyTypeFormat(NULL) 352 , capitalizationContext(UDISPCTX_CAPITALIZATION_NONE) 353 { 354 while (length-- > 0) { 355 UDisplayContext value = *contexts++; 356 UDisplayContextType selector = (UDisplayContextType)((uint32_t)value >> 8); 357 switch (selector) { 358 case UDISPCTX_TYPE_DIALECT_HANDLING: 359 dialectHandling = (UDialectHandling)value; 360 break; 361 case UDISPCTX_TYPE_CAPITALIZATION: 362 capitalizationContext = value; 363 break; 364 default: 365 break; 366 } 367 } 368 initialize(); 369 } 370 371 void 372 LocaleDisplayNamesImpl::initialize(void) { 373 LocaleDisplayNamesImpl *nonConstThis = (LocaleDisplayNamesImpl *)this; 374 nonConstThis->locale = langData.getLocale() == Locale::getRoot() 375 ? regionData.getLocale() 376 : langData.getLocale(); 377 378 langData.getNoFallback("localeDisplayPattern", "separator", sep); 379 if (sep.isBogus()) { 380 sep = UnicodeString(", ", -1, US_INV); 381 } 382 383 UnicodeString pattern; 384 langData.getNoFallback("localeDisplayPattern", "pattern", pattern); 385 if (pattern.isBogus()) { 386 pattern = UnicodeString("{0} ({1})", -1, US_INV); 387 } 388 UErrorCode status = U_ZERO_ERROR; 389 format = new MessageFormat(pattern, status); 390 391 UnicodeString ktPattern; 392 langData.get("localeDisplayPattern", "keyTypePattern", ktPattern); 393 if (ktPattern.isBogus()) { 394 ktPattern = UnicodeString("{0}={1}", -1, US_INV); 395 } 396 keyTypeFormat = new MessageFormat(ktPattern, status); 397 398 uprv_memset(fCapitalization, 0, sizeof(fCapitalization)); 399 #if !UCONFIG_NO_BREAK_ITERATION 400 // The following is basically copied from DateFormatSymbols::initializeData 401 typedef struct { 402 const char * usageName; 403 LocaleDisplayNamesImpl::CapContextUsage usageEnum; 404 } ContextUsageNameToEnum; 405 const ContextUsageNameToEnum contextUsageTypeMap[] = { 406 // Entries must be sorted by usageTypeName; entry with NULL name terminates list. 407 { "key", kCapContextUsageKey }, 408 { "languages", kCapContextUsageLanguage }, 409 { "script", kCapContextUsageScript }, 410 { "territory", kCapContextUsageTerritory }, 411 { "type", kCapContextUsageType }, 412 { "variant", kCapContextUsageVariant }, 413 { NULL, (CapContextUsage)0 }, 414 }; 415 int32_t len = 0; 416 UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &status); 417 if (U_SUCCESS(status)) { 418 UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, "contextTransforms", NULL, &status); 419 if (U_SUCCESS(status)) { 420 UResourceBundle *contextTransformUsage; 421 while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &status)) != NULL ) { 422 const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status); 423 if (U_SUCCESS(status) && intVector != NULL && len >= 2) { 424 const char* usageKey = ures_getKey(contextTransformUsage); 425 if (usageKey != NULL) { 426 const ContextUsageNameToEnum * typeMapPtr = contextUsageTypeMap; 427 int32_t compResult = 0; 428 // linear search; list is short and we cannot be sure that bsearch is available 429 while ( typeMapPtr->usageName != NULL && (compResult = uprv_strcmp(usageKey, typeMapPtr->usageName)) > 0 ) { 430 ++typeMapPtr; 431 } 432 if (typeMapPtr->usageName != NULL && compResult == 0) { 433 fCapitalization[typeMapPtr->usageEnum][0] = intVector[0]; 434 fCapitalization[typeMapPtr->usageEnum][1] = intVector[1]; 435 } 436 } 437 } 438 status = U_ZERO_ERROR; 439 ures_close(contextTransformUsage); 440 } 441 ures_close(contextTransforms); 442 } 443 ures_close(localeBundle); 444 } 445 #endif 446 } 447 448 LocaleDisplayNamesImpl::~LocaleDisplayNamesImpl() { 449 delete format; 450 delete keyTypeFormat; 451 } 452 453 const Locale& 454 LocaleDisplayNamesImpl::getLocale() const { 455 return locale; 456 } 457 458 UDialectHandling 459 LocaleDisplayNamesImpl::getDialectHandling() const { 460 return dialectHandling; 461 } 462 463 UDisplayContext 464 LocaleDisplayNamesImpl::getContext(UDisplayContextType type) const { 465 switch (type) { 466 case UDISPCTX_TYPE_DIALECT_HANDLING: 467 return (UDisplayContext)dialectHandling; 468 case UDISPCTX_TYPE_CAPITALIZATION: 469 return capitalizationContext; 470 default: 471 break; 472 } 473 return (UDisplayContext)0; 474 } 475 476 UnicodeString& 477 LocaleDisplayNamesImpl::adjustForUsageAndContext(CapContextUsage usage, 478 UnicodeString& result) const { 479 #if !UCONFIG_NO_BREAK_ITERATION 480 // check to see whether we need to titlecase result 481 UBool titlecase = FALSE; 482 switch (capitalizationContext) { 483 case UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE: 484 titlecase = TRUE; 485 break; 486 case UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU: 487 titlecase = fCapitalization[usage][0]; 488 break; 489 case UDISPCTX_CAPITALIZATION_FOR_STANDALONE: 490 titlecase = fCapitalization[usage][1]; 491 break; 492 default: 493 // titlecase = FALSE; 494 break; 495 } 496 if (titlecase) { 497 // TODO: Fix this titlecase hack when we figure out something better to do. 498 // We don't want to titlecase the whole text, only something like the first word, 499 // of the first segment long enough to have a complete cluster, whichever is 500 // shorter. We could have keep a word break iterator around, but I am not sure 501 // that will do the ight thing for the purposes here. For now we assume that in 502 // languages for which titlecasing makes a difference, we can stop at non-letter 503 // characters in 0x0000-0x00FF and only titlecase up to the first occurrence of 504 // any of those, or to a small number of chars, whichever comes first. 505 int32_t stopPos, stopPosLimit = 8, len = result.length(); 506 if ( stopPosLimit > len ) { 507 stopPosLimit = len; 508 } 509 for ( stopPos = 0; stopPos < stopPosLimit; stopPos++ ) { 510 UChar32 ch = result.char32At(stopPos); 511 if ( (ch < 0x41) || (ch > 0x5A && ch < 0x61) || (ch > 0x7A && ch < 0xC0) ) { 512 break; 513 } 514 if (ch >= 0x10000) { 515 stopPos++; 516 } 517 } 518 if ( stopPos > 0 && stopPos < len ) { 519 UnicodeString firstWord(result, 0, stopPos); 520 firstWord.toTitle(NULL, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT); 521 result.replaceBetween(0, stopPos, firstWord); 522 } else { 523 // no stopPos, titlecase the whole text 524 result.toTitle(NULL, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT); 525 } 526 } 527 #endif 528 return result; 529 } 530 531 UnicodeString& 532 LocaleDisplayNamesImpl::localeDisplayName(const Locale& locale, 533 UnicodeString& result) const { 534 UnicodeString resultName; 535 536 const char* lang = locale.getLanguage(); 537 if (uprv_strlen(lang) == 0) { 538 lang = "root"; 539 } 540 const char* script = locale.getScript(); 541 const char* country = locale.getCountry(); 542 const char* variant = locale.getVariant(); 543 544 UBool hasScript = uprv_strlen(script) > 0; 545 UBool hasCountry = uprv_strlen(country) > 0; 546 UBool hasVariant = uprv_strlen(variant) > 0; 547 548 if (dialectHandling == ULDN_DIALECT_NAMES) { 549 char buffer[ULOC_FULLNAME_CAPACITY]; 550 do { // loop construct is so we can break early out of search 551 if (hasScript && hasCountry) { 552 ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, "_", country, (char *)0); 553 localeIdName(buffer, resultName); 554 if (!resultName.isBogus()) { 555 hasScript = FALSE; 556 hasCountry = FALSE; 557 break; 558 } 559 } 560 if (hasScript) { 561 ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, (char *)0); 562 localeIdName(buffer, resultName); 563 if (!resultName.isBogus()) { 564 hasScript = FALSE; 565 break; 566 } 567 } 568 if (hasCountry) { 569 ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", country, (char*)0); 570 localeIdName(buffer, resultName); 571 if (!resultName.isBogus()) { 572 hasCountry = FALSE; 573 break; 574 } 575 } 576 } while (FALSE); 577 } 578 if (resultName.isBogus() || resultName.isEmpty()) { 579 localeIdName(lang, resultName); 580 } 581 582 UnicodeString resultRemainder; 583 UnicodeString temp; 584 StringEnumeration *e = NULL; 585 UErrorCode status = U_ZERO_ERROR; 586 587 if (hasScript) { 588 resultRemainder.append(scriptDisplayName(script, temp)); 589 } 590 if (hasCountry) { 591 appendWithSep(resultRemainder, regionDisplayName(country, temp)); 592 } 593 if (hasVariant) { 594 appendWithSep(resultRemainder, variantDisplayName(variant, temp)); 595 } 596 597 e = locale.createKeywords(status); 598 if (e && U_SUCCESS(status)) { 599 UnicodeString temp2; 600 char value[ULOC_KEYWORD_AND_VALUES_CAPACITY]; // sigh, no ULOC_VALUE_CAPACITY 601 const char* key; 602 while ((key = e->next((int32_t *)0, status)) != NULL) { 603 locale.getKeywordValue(key, value, ULOC_KEYWORD_AND_VALUES_CAPACITY, status); 604 keyDisplayName(key, temp); 605 keyValueDisplayName(key, value, temp2); 606 if (temp2 != UnicodeString(value, -1, US_INV)) { 607 appendWithSep(resultRemainder, temp2); 608 } else if (temp != UnicodeString(key, -1, US_INV)) { 609 UnicodeString temp3; 610 Formattable data[] = { 611 temp, 612 temp2 613 }; 614 FieldPosition fpos; 615 status = U_ZERO_ERROR; 616 keyTypeFormat->format(data, 2, temp3, fpos, status); 617 appendWithSep(resultRemainder, temp3); 618 } else { 619 appendWithSep(resultRemainder, temp) 620 .append((UChar)0x3d /* = */) 621 .append(temp2); 622 } 623 } 624 delete e; 625 } 626 627 if (!resultRemainder.isEmpty()) { 628 Formattable data[] = { 629 resultName, 630 resultRemainder 631 }; 632 FieldPosition fpos; 633 status = U_ZERO_ERROR; 634 format->format(data, 2, result, fpos, status); 635 return adjustForUsageAndContext(kCapContextUsageLanguage, result); 636 } 637 638 result = resultName; 639 return adjustForUsageAndContext(kCapContextUsageLanguage, result); 640 } 641 642 UnicodeString& 643 LocaleDisplayNamesImpl::appendWithSep(UnicodeString& buffer, const UnicodeString& src) const { 644 if (!buffer.isEmpty()) { 645 buffer.append(sep); 646 } 647 buffer.append(src); 648 return buffer; 649 } 650 651 UnicodeString& 652 LocaleDisplayNamesImpl::localeDisplayName(const char* localeId, 653 UnicodeString& result) const { 654 return localeDisplayName(Locale(localeId), result); 655 } 656 657 // private 658 UnicodeString& 659 LocaleDisplayNamesImpl::localeIdName(const char* localeId, 660 UnicodeString& result) const { 661 return langData.getNoFallback("Languages", localeId, result); 662 } 663 664 UnicodeString& 665 LocaleDisplayNamesImpl::languageDisplayName(const char* lang, 666 UnicodeString& result) const { 667 if (uprv_strcmp("root", lang) == 0 || uprv_strchr(lang, '_') != NULL) { 668 return result = UnicodeString(lang, -1, US_INV); 669 } 670 langData.get("Languages", lang, result); 671 return adjustForUsageAndContext(kCapContextUsageLanguage, result); 672 } 673 674 UnicodeString& 675 LocaleDisplayNamesImpl::scriptDisplayName(const char* script, 676 UnicodeString& result) const { 677 langData.get("Scripts", script, result); 678 return adjustForUsageAndContext(kCapContextUsageScript, result); 679 } 680 681 UnicodeString& 682 LocaleDisplayNamesImpl::scriptDisplayName(UScriptCode scriptCode, 683 UnicodeString& result) const { 684 const char* name = uscript_getName(scriptCode); 685 langData.get("Scripts", name, result); 686 return adjustForUsageAndContext(kCapContextUsageScript, result); 687 } 688 689 UnicodeString& 690 LocaleDisplayNamesImpl::regionDisplayName(const char* region, 691 UnicodeString& result) const { 692 regionData.get("Countries", region, result); 693 return adjustForUsageAndContext(kCapContextUsageTerritory, result); 694 } 695 696 UnicodeString& 697 LocaleDisplayNamesImpl::variantDisplayName(const char* variant, 698 UnicodeString& result) const { 699 langData.get("Variants", variant, result); 700 return adjustForUsageAndContext(kCapContextUsageVariant, result); 701 } 702 703 UnicodeString& 704 LocaleDisplayNamesImpl::keyDisplayName(const char* key, 705 UnicodeString& result) const { 706 langData.get("Keys", key, result); 707 return adjustForUsageAndContext(kCapContextUsageKey, result); 708 } 709 710 UnicodeString& 711 LocaleDisplayNamesImpl::keyValueDisplayName(const char* key, 712 const char* value, 713 UnicodeString& result) const { 714 langData.get("Types", key, value, result); 715 return adjustForUsageAndContext(kCapContextUsageType, result); 716 } 717 718 //////////////////////////////////////////////////////////////////////////////////////////////////// 719 720 LocaleDisplayNames* 721 LocaleDisplayNames::createInstance(const Locale& locale, 722 UDialectHandling dialectHandling) { 723 return new LocaleDisplayNamesImpl(locale, dialectHandling); 724 } 725 726 LocaleDisplayNames* 727 LocaleDisplayNames::createInstance(const Locale& locale, 728 UDisplayContext *contexts, int32_t length) { 729 if (contexts == NULL) { 730 length = 0; 731 } 732 return new LocaleDisplayNamesImpl(locale, contexts, length); 733 } 734 735 U_NAMESPACE_END 736 737 //////////////////////////////////////////////////////////////////////////////////////////////////// 738 739 U_NAMESPACE_USE 740 741 U_CAPI ULocaleDisplayNames * U_EXPORT2 742 uldn_open(const char * locale, 743 UDialectHandling dialectHandling, 744 UErrorCode *pErrorCode) { 745 if (U_FAILURE(*pErrorCode)) { 746 return 0; 747 } 748 if (locale == NULL) { 749 locale = uloc_getDefault(); 750 } 751 return (ULocaleDisplayNames *)LocaleDisplayNames::createInstance(Locale(locale), dialectHandling); 752 } 753 754 U_CAPI ULocaleDisplayNames * U_EXPORT2 755 uldn_openForContext(const char * locale, 756 UDisplayContext *contexts, int32_t length, 757 UErrorCode *pErrorCode) { 758 if (U_FAILURE(*pErrorCode)) { 759 return 0; 760 } 761 if (locale == NULL) { 762 locale = uloc_getDefault(); 763 } 764 return (ULocaleDisplayNames *)LocaleDisplayNames::createInstance(Locale(locale), contexts, length); 765 } 766 767 768 U_CAPI void U_EXPORT2 769 uldn_close(ULocaleDisplayNames *ldn) { 770 delete (LocaleDisplayNames *)ldn; 771 } 772 773 U_CAPI const char * U_EXPORT2 774 uldn_getLocale(const ULocaleDisplayNames *ldn) { 775 if (ldn) { 776 return ((const LocaleDisplayNames *)ldn)->getLocale().getName(); 777 } 778 return NULL; 779 } 780 781 U_CAPI UDialectHandling U_EXPORT2 782 uldn_getDialectHandling(const ULocaleDisplayNames *ldn) { 783 if (ldn) { 784 return ((const LocaleDisplayNames *)ldn)->getDialectHandling(); 785 } 786 return ULDN_STANDARD_NAMES; 787 } 788 789 U_CAPI UDisplayContext U_EXPORT2 790 uldn_getContext(const ULocaleDisplayNames *ldn, 791 UDisplayContextType type, 792 UErrorCode *pErrorCode) { 793 if (U_FAILURE(*pErrorCode)) { 794 return (UDisplayContext)0; 795 } 796 return ((const LocaleDisplayNames *)ldn)->getContext(type); 797 } 798 799 U_CAPI int32_t U_EXPORT2 800 uldn_localeDisplayName(const ULocaleDisplayNames *ldn, 801 const char *locale, 802 UChar *result, 803 int32_t maxResultSize, 804 UErrorCode *pErrorCode) { 805 if (U_FAILURE(*pErrorCode)) { 806 return 0; 807 } 808 if (ldn == NULL || locale == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 809 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 810 return 0; 811 } 812 UnicodeString temp(result, 0, maxResultSize); 813 ((const LocaleDisplayNames *)ldn)->localeDisplayName(locale, temp); 814 return temp.extract(result, maxResultSize, *pErrorCode); 815 } 816 817 U_CAPI int32_t U_EXPORT2 818 uldn_languageDisplayName(const ULocaleDisplayNames *ldn, 819 const char *lang, 820 UChar *result, 821 int32_t maxResultSize, 822 UErrorCode *pErrorCode) { 823 if (U_FAILURE(*pErrorCode)) { 824 return 0; 825 } 826 if (ldn == NULL || lang == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 827 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 828 return 0; 829 } 830 UnicodeString temp(result, 0, maxResultSize); 831 ((const LocaleDisplayNames *)ldn)->languageDisplayName(lang, temp); 832 return temp.extract(result, maxResultSize, *pErrorCode); 833 } 834 835 U_CAPI int32_t U_EXPORT2 836 uldn_scriptDisplayName(const ULocaleDisplayNames *ldn, 837 const char *script, 838 UChar *result, 839 int32_t maxResultSize, 840 UErrorCode *pErrorCode) { 841 if (U_FAILURE(*pErrorCode)) { 842 return 0; 843 } 844 if (ldn == NULL || script == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 845 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 846 return 0; 847 } 848 UnicodeString temp(result, 0, maxResultSize); 849 ((const LocaleDisplayNames *)ldn)->scriptDisplayName(script, temp); 850 return temp.extract(result, maxResultSize, *pErrorCode); 851 } 852 853 U_CAPI int32_t U_EXPORT2 854 uldn_scriptCodeDisplayName(const ULocaleDisplayNames *ldn, 855 UScriptCode scriptCode, 856 UChar *result, 857 int32_t maxResultSize, 858 UErrorCode *pErrorCode) { 859 return uldn_scriptDisplayName(ldn, uscript_getName(scriptCode), result, maxResultSize, pErrorCode); 860 } 861 862 U_CAPI int32_t U_EXPORT2 863 uldn_regionDisplayName(const ULocaleDisplayNames *ldn, 864 const char *region, 865 UChar *result, 866 int32_t maxResultSize, 867 UErrorCode *pErrorCode) { 868 if (U_FAILURE(*pErrorCode)) { 869 return 0; 870 } 871 if (ldn == NULL || region == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 872 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 873 return 0; 874 } 875 UnicodeString temp(result, 0, maxResultSize); 876 ((const LocaleDisplayNames *)ldn)->regionDisplayName(region, temp); 877 return temp.extract(result, maxResultSize, *pErrorCode); 878 } 879 880 U_CAPI int32_t U_EXPORT2 881 uldn_variantDisplayName(const ULocaleDisplayNames *ldn, 882 const char *variant, 883 UChar *result, 884 int32_t maxResultSize, 885 UErrorCode *pErrorCode) { 886 if (U_FAILURE(*pErrorCode)) { 887 return 0; 888 } 889 if (ldn == NULL || variant == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 890 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 891 return 0; 892 } 893 UnicodeString temp(result, 0, maxResultSize); 894 ((const LocaleDisplayNames *)ldn)->variantDisplayName(variant, temp); 895 return temp.extract(result, maxResultSize, *pErrorCode); 896 } 897 898 U_CAPI int32_t U_EXPORT2 899 uldn_keyDisplayName(const ULocaleDisplayNames *ldn, 900 const char *key, 901 UChar *result, 902 int32_t maxResultSize, 903 UErrorCode *pErrorCode) { 904 if (U_FAILURE(*pErrorCode)) { 905 return 0; 906 } 907 if (ldn == NULL || key == NULL || (result == NULL && maxResultSize > 0) || maxResultSize < 0) { 908 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 909 return 0; 910 } 911 UnicodeString temp(result, 0, maxResultSize); 912 ((const LocaleDisplayNames *)ldn)->keyDisplayName(key, temp); 913 return temp.extract(result, maxResultSize, *pErrorCode); 914 } 915 916 U_CAPI int32_t U_EXPORT2 917 uldn_keyValueDisplayName(const ULocaleDisplayNames *ldn, 918 const char *key, 919 const char *value, 920 UChar *result, 921 int32_t maxResultSize, 922 UErrorCode *pErrorCode) { 923 if (U_FAILURE(*pErrorCode)) { 924 return 0; 925 } 926 if (ldn == NULL || key == NULL || value == NULL || (result == NULL && maxResultSize > 0) 927 || maxResultSize < 0) { 928 *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; 929 return 0; 930 } 931 UnicodeString temp(result, 0, maxResultSize); 932 ((const LocaleDisplayNames *)ldn)->keyValueDisplayName(key, value, temp); 933 return temp.extract(result, maxResultSize, *pErrorCode); 934 } 935 936 #endif 937