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