OLD | NEW |
(Empty) | |
| 1 /* |
| 2 ******************************************************************************* |
| 3 * |
| 4 * Copyright (C) 1997-2010, International Business Machines |
| 5 * Corporation and others. All Rights Reserved. |
| 6 * |
| 7 ******************************************************************************* |
| 8 * file name: locdispnames.cpp |
| 9 * encoding: US-ASCII |
| 10 * tab size: 8 (not used) |
| 11 * indentation:4 |
| 12 * |
| 13 * created on: 2010feb25 |
| 14 * created by: Markus W. Scherer |
| 15 * |
| 16 * Code for locale display names, separated out from other .cpp files |
| 17 * that then do not depend on resource bundle code and display name data. |
| 18 */ |
| 19 |
| 20 #include "unicode/utypes.h" |
| 21 #include "unicode/brkiter.h" |
| 22 #include "unicode/locid.h" |
| 23 #include "unicode/uloc.h" |
| 24 #include "unicode/ures.h" |
| 25 #include "unicode/ustring.h" |
| 26 #include "cmemory.h" |
| 27 #include "cstring.h" |
| 28 #include "putilimp.h" |
| 29 #include "ulocimp.h" |
| 30 #include "uresimp.h" |
| 31 #include "ureslocs.h" |
| 32 #include "ustr_imp.h" |
| 33 |
| 34 // C++ API ----------------------------------------------------------------- *** |
| 35 |
| 36 U_NAMESPACE_BEGIN |
| 37 |
| 38 UnicodeString& |
| 39 Locale::getDisplayLanguage(UnicodeString& dispLang) const |
| 40 { |
| 41 return this->getDisplayLanguage(getDefault(), dispLang); |
| 42 } |
| 43 |
| 44 /*We cannot make any assumptions on the size of the output display strings |
| 45 * Yet, since we are calling through to a C API, we need to set limits on |
| 46 * buffer size. For all the following getDisplay functions we first attempt |
| 47 * to fill up a stack allocated buffer. If it is to small we heap allocated |
| 48 * the exact buffer we need copy it to the UnicodeString and delete it*/ |
| 49 |
| 50 UnicodeString& |
| 51 Locale::getDisplayLanguage(const Locale &displayLocale, |
| 52 UnicodeString &result) const { |
| 53 UChar *buffer; |
| 54 UErrorCode errorCode=U_ZERO_ERROR; |
| 55 int32_t length; |
| 56 |
| 57 buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); |
| 58 if(buffer==0) { |
| 59 result.truncate(0); |
| 60 return result; |
| 61 } |
| 62 |
| 63 length=uloc_getDisplayLanguage(fullName, displayLocale.fullName, |
| 64 buffer, result.getCapacity(), |
| 65 &errorCode); |
| 66 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
| 67 |
| 68 if(errorCode==U_BUFFER_OVERFLOW_ERROR) { |
| 69 buffer=result.getBuffer(length); |
| 70 if(buffer==0) { |
| 71 result.truncate(0); |
| 72 return result; |
| 73 } |
| 74 errorCode=U_ZERO_ERROR; |
| 75 length=uloc_getDisplayLanguage(fullName, displayLocale.fullName, |
| 76 buffer, result.getCapacity(), |
| 77 &errorCode); |
| 78 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
| 79 } |
| 80 |
| 81 return result; |
| 82 } |
| 83 |
| 84 UnicodeString& |
| 85 Locale::getDisplayScript(UnicodeString& dispScript) const |
| 86 { |
| 87 return this->getDisplayScript(getDefault(), dispScript); |
| 88 } |
| 89 |
| 90 UnicodeString& |
| 91 Locale::getDisplayScript(const Locale &displayLocale, |
| 92 UnicodeString &result) const { |
| 93 UChar *buffer; |
| 94 UErrorCode errorCode=U_ZERO_ERROR; |
| 95 int32_t length; |
| 96 |
| 97 buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); |
| 98 if(buffer==0) { |
| 99 result.truncate(0); |
| 100 return result; |
| 101 } |
| 102 |
| 103 length=uloc_getDisplayScript(fullName, displayLocale.fullName, |
| 104 buffer, result.getCapacity(), |
| 105 &errorCode); |
| 106 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
| 107 |
| 108 if(errorCode==U_BUFFER_OVERFLOW_ERROR) { |
| 109 buffer=result.getBuffer(length); |
| 110 if(buffer==0) { |
| 111 result.truncate(0); |
| 112 return result; |
| 113 } |
| 114 errorCode=U_ZERO_ERROR; |
| 115 length=uloc_getDisplayScript(fullName, displayLocale.fullName, |
| 116 buffer, result.getCapacity(), |
| 117 &errorCode); |
| 118 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
| 119 } |
| 120 |
| 121 return result; |
| 122 } |
| 123 |
| 124 UnicodeString& |
| 125 Locale::getDisplayCountry(UnicodeString& dispCntry) const |
| 126 { |
| 127 return this->getDisplayCountry(getDefault(), dispCntry); |
| 128 } |
| 129 |
| 130 UnicodeString& |
| 131 Locale::getDisplayCountry(const Locale &displayLocale, |
| 132 UnicodeString &result) const { |
| 133 UChar *buffer; |
| 134 UErrorCode errorCode=U_ZERO_ERROR; |
| 135 int32_t length; |
| 136 |
| 137 buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); |
| 138 if(buffer==0) { |
| 139 result.truncate(0); |
| 140 return result; |
| 141 } |
| 142 |
| 143 length=uloc_getDisplayCountry(fullName, displayLocale.fullName, |
| 144 buffer, result.getCapacity(), |
| 145 &errorCode); |
| 146 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
| 147 |
| 148 if(errorCode==U_BUFFER_OVERFLOW_ERROR) { |
| 149 buffer=result.getBuffer(length); |
| 150 if(buffer==0) { |
| 151 result.truncate(0); |
| 152 return result; |
| 153 } |
| 154 errorCode=U_ZERO_ERROR; |
| 155 length=uloc_getDisplayCountry(fullName, displayLocale.fullName, |
| 156 buffer, result.getCapacity(), |
| 157 &errorCode); |
| 158 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
| 159 } |
| 160 |
| 161 return result; |
| 162 } |
| 163 |
| 164 UnicodeString& |
| 165 Locale::getDisplayVariant(UnicodeString& dispVar) const |
| 166 { |
| 167 return this->getDisplayVariant(getDefault(), dispVar); |
| 168 } |
| 169 |
| 170 UnicodeString& |
| 171 Locale::getDisplayVariant(const Locale &displayLocale, |
| 172 UnicodeString &result) const { |
| 173 UChar *buffer; |
| 174 UErrorCode errorCode=U_ZERO_ERROR; |
| 175 int32_t length; |
| 176 |
| 177 buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); |
| 178 if(buffer==0) { |
| 179 result.truncate(0); |
| 180 return result; |
| 181 } |
| 182 |
| 183 length=uloc_getDisplayVariant(fullName, displayLocale.fullName, |
| 184 buffer, result.getCapacity(), |
| 185 &errorCode); |
| 186 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
| 187 |
| 188 if(errorCode==U_BUFFER_OVERFLOW_ERROR) { |
| 189 buffer=result.getBuffer(length); |
| 190 if(buffer==0) { |
| 191 result.truncate(0); |
| 192 return result; |
| 193 } |
| 194 errorCode=U_ZERO_ERROR; |
| 195 length=uloc_getDisplayVariant(fullName, displayLocale.fullName, |
| 196 buffer, result.getCapacity(), |
| 197 &errorCode); |
| 198 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
| 199 } |
| 200 |
| 201 return result; |
| 202 } |
| 203 |
| 204 UnicodeString& |
| 205 Locale::getDisplayName( UnicodeString& name ) const |
| 206 { |
| 207 return this->getDisplayName(getDefault(), name); |
| 208 } |
| 209 |
| 210 UnicodeString& |
| 211 Locale::getDisplayName(const Locale &displayLocale, |
| 212 UnicodeString &result) const { |
| 213 UChar *buffer; |
| 214 UErrorCode errorCode=U_ZERO_ERROR; |
| 215 int32_t length; |
| 216 |
| 217 buffer=result.getBuffer(ULOC_FULLNAME_CAPACITY); |
| 218 if(buffer==0) { |
| 219 result.truncate(0); |
| 220 return result; |
| 221 } |
| 222 |
| 223 length=uloc_getDisplayName(fullName, displayLocale.fullName, |
| 224 buffer, result.getCapacity(), |
| 225 &errorCode); |
| 226 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
| 227 |
| 228 if(errorCode==U_BUFFER_OVERFLOW_ERROR) { |
| 229 buffer=result.getBuffer(length); |
| 230 if(buffer==0) { |
| 231 result.truncate(0); |
| 232 return result; |
| 233 } |
| 234 errorCode=U_ZERO_ERROR; |
| 235 length=uloc_getDisplayName(fullName, displayLocale.fullName, |
| 236 buffer, result.getCapacity(), |
| 237 &errorCode); |
| 238 result.releaseBuffer(U_SUCCESS(errorCode) ? length : 0); |
| 239 } |
| 240 |
| 241 return result; |
| 242 } |
| 243 |
| 244 #if ! UCONFIG_NO_BREAK_ITERATION |
| 245 |
| 246 // ------------------------------------- |
| 247 // Gets the objectLocale display name in the default locale language. |
| 248 UnicodeString& U_EXPORT2 |
| 249 BreakIterator::getDisplayName(const Locale& objectLocale, |
| 250 UnicodeString& name) |
| 251 { |
| 252 return objectLocale.getDisplayName(name); |
| 253 } |
| 254 |
| 255 // ------------------------------------- |
| 256 // Gets the objectLocale display name in the displayLocale language. |
| 257 UnicodeString& U_EXPORT2 |
| 258 BreakIterator::getDisplayName(const Locale& objectLocale, |
| 259 const Locale& displayLocale, |
| 260 UnicodeString& name) |
| 261 { |
| 262 return objectLocale.getDisplayName(displayLocale, name); |
| 263 } |
| 264 |
| 265 #endif |
| 266 |
| 267 |
| 268 U_NAMESPACE_END |
| 269 |
| 270 // C API ------------------------------------------------------------------- *** |
| 271 |
| 272 U_NAMESPACE_USE |
| 273 |
| 274 /* ### Constants **************************************************/ |
| 275 |
| 276 /* These strings describe the resources we attempt to load from |
| 277 the locale ResourceBundle data file.*/ |
| 278 static const char _kLanguages[] = "Languages"; |
| 279 static const char _kScripts[] = "Scripts"; |
| 280 static const char _kCountries[] = "Countries"; |
| 281 static const char _kVariants[] = "Variants"; |
| 282 static const char _kKeys[] = "Keys"; |
| 283 static const char _kTypes[] = "Types"; |
| 284 static const char _kRootName[] = "root"; |
| 285 static const char _kCurrency[] = "currency"; |
| 286 static const char _kCurrencies[] = "Currencies"; |
| 287 static const char _kLocaleDisplayPattern[] = "localeDisplayPattern"; |
| 288 static const char _kPattern[] = "pattern"; |
| 289 static const char _kSeparator[] = "separator"; |
| 290 |
| 291 /* ### Display name **************************************************/ |
| 292 |
| 293 static int32_t |
| 294 _getStringOrCopyKey(const char *path, const char *locale, |
| 295 const char *tableKey, |
| 296 const char* subTableKey, |
| 297 const char *itemKey, |
| 298 const char *substitute, |
| 299 UChar *dest, int32_t destCapacity, |
| 300 UErrorCode *pErrorCode) { |
| 301 const UChar *s = NULL; |
| 302 int32_t length = 0; |
| 303 |
| 304 if(itemKey==NULL) { |
| 305 /* top-level item: normal resource bundle access */ |
| 306 UResourceBundle *rb; |
| 307 |
| 308 rb=ures_open(path, locale, pErrorCode); |
| 309 |
| 310 if(U_SUCCESS(*pErrorCode)) { |
| 311 s=ures_getStringByKey(rb, tableKey, &length, pErrorCode); |
| 312 /* see comment about closing rb near "return item;" in _res_getTable
StringWithFallback() */ |
| 313 ures_close(rb); |
| 314 } |
| 315 } else { |
| 316 /* Language code should not be a number. If it is, set the error code. *
/ |
| 317 if (!uprv_strncmp(tableKey, "Languages", 9) && uprv_strtol(itemKey, NULL
, 10)) { |
| 318 *pErrorCode = U_MISSING_RESOURCE_ERROR; |
| 319 } else { |
| 320 /* second-level item, use special fallback */ |
| 321 s=uloc_getTableStringWithFallback(path, locale, |
| 322 tableKey, |
| 323 subTableKey, |
| 324 itemKey, |
| 325 &length, |
| 326 pErrorCode); |
| 327 } |
| 328 } |
| 329 |
| 330 if(U_SUCCESS(*pErrorCode)) { |
| 331 int32_t copyLength=uprv_min(length, destCapacity); |
| 332 if(copyLength>0 && s != NULL) { |
| 333 u_memcpy(dest, s, copyLength); |
| 334 } |
| 335 } else { |
| 336 /* no string from a resource bundle: convert the substitute */ |
| 337 length=(int32_t)uprv_strlen(substitute); |
| 338 u_charsToUChars(substitute, dest, uprv_min(length, destCapacity)); |
| 339 *pErrorCode=U_USING_DEFAULT_WARNING; |
| 340 } |
| 341 |
| 342 return u_terminateUChars(dest, destCapacity, length, pErrorCode); |
| 343 } |
| 344 |
| 345 typedef int32_t U_CALLCONV UDisplayNameGetter(const char *, char *, int32_t, UE
rrorCode *); |
| 346 |
| 347 static int32_t |
| 348 _getDisplayNameForComponent(const char *locale, |
| 349 const char *displayLocale, |
| 350 UChar *dest, int32_t destCapacity, |
| 351 UDisplayNameGetter *getter, |
| 352 const char *tag, |
| 353 UErrorCode *pErrorCode) { |
| 354 char localeBuffer[ULOC_FULLNAME_CAPACITY*4]; |
| 355 int32_t length; |
| 356 UErrorCode localStatus; |
| 357 const char* root = NULL; |
| 358 |
| 359 /* argument checking */ |
| 360 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { |
| 361 return 0; |
| 362 } |
| 363 |
| 364 if(destCapacity<0 || (destCapacity>0 && dest==NULL)) { |
| 365 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; |
| 366 return 0; |
| 367 } |
| 368 |
| 369 localStatus = U_ZERO_ERROR; |
| 370 length=(*getter)(locale, localeBuffer, sizeof(localeBuffer), &localStatus); |
| 371 if(U_FAILURE(localStatus) || localStatus==U_STRING_NOT_TERMINATED_WARNING) { |
| 372 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; |
| 373 return 0; |
| 374 } |
| 375 if(length==0) { |
| 376 return u_terminateUChars(dest, destCapacity, 0, pErrorCode); |
| 377 } |
| 378 |
| 379 root = tag == _kCountries ? U_ICUDATA_REGION : U_ICUDATA_LANG; |
| 380 |
| 381 return _getStringOrCopyKey(root, displayLocale, |
| 382 tag, NULL, localeBuffer, |
| 383 localeBuffer, |
| 384 dest, destCapacity, |
| 385 pErrorCode); |
| 386 } |
| 387 |
| 388 U_CAPI int32_t U_EXPORT2 |
| 389 uloc_getDisplayLanguage(const char *locale, |
| 390 const char *displayLocale, |
| 391 UChar *dest, int32_t destCapacity, |
| 392 UErrorCode *pErrorCode) { |
| 393 return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity
, |
| 394 uloc_getLanguage, _kLanguages, pErrorCode); |
| 395 } |
| 396 |
| 397 U_CAPI int32_t U_EXPORT2 |
| 398 uloc_getDisplayScript(const char* locale, |
| 399 const char* displayLocale, |
| 400 UChar *dest, int32_t destCapacity, |
| 401 UErrorCode *pErrorCode) |
| 402 { |
| 403 return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity
, |
| 404 uloc_getScript, _kScripts, pErrorCode); |
| 405 } |
| 406 |
| 407 U_CAPI int32_t U_EXPORT2 |
| 408 uloc_getDisplayCountry(const char *locale, |
| 409 const char *displayLocale, |
| 410 UChar *dest, int32_t destCapacity, |
| 411 UErrorCode *pErrorCode) { |
| 412 return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity
, |
| 413 uloc_getCountry, _kCountries, pErrorCode); |
| 414 } |
| 415 |
| 416 /* |
| 417 * TODO separate variant1_variant2_variant3... |
| 418 * by getting each tag's display string and concatenating them with ", " |
| 419 * in between - similar to uloc_getDisplayName() |
| 420 */ |
| 421 U_CAPI int32_t U_EXPORT2 |
| 422 uloc_getDisplayVariant(const char *locale, |
| 423 const char *displayLocale, |
| 424 UChar *dest, int32_t destCapacity, |
| 425 UErrorCode *pErrorCode) { |
| 426 return _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity
, |
| 427 uloc_getVariant, _kVariants, pErrorCode); |
| 428 } |
| 429 |
| 430 U_CAPI int32_t U_EXPORT2 |
| 431 uloc_getDisplayName(const char *locale, |
| 432 const char *displayLocale, |
| 433 UChar *dest, int32_t destCapacity, |
| 434 UErrorCode *pErrorCode) |
| 435 { |
| 436 int32_t length, length2, length3 = 0; |
| 437 UBool hasLanguage, hasScript, hasCountry, hasVariant, hasKeywords; |
| 438 UEnumeration* keywordEnum = NULL; |
| 439 int32_t keywordCount = 0; |
| 440 const char *keyword = NULL; |
| 441 int32_t keywordLen = 0; |
| 442 char keywordValue[256]; |
| 443 int32_t keywordValueLen = 0; |
| 444 |
| 445 int32_t locSepLen = 0; |
| 446 int32_t locPatLen = 0; |
| 447 int32_t p0Len = 0; |
| 448 int32_t defaultPatternLen = 9; |
| 449 const UChar *dispLocSeparator; |
| 450 const UChar *dispLocPattern; |
| 451 static const UChar defaultSeparator[3] = { 0x002c, 0x0020 , 0x0000 }; /* com
ma + space */ |
| 452 static const UChar defaultPattern[10] = { 0x007b, 0x0030, 0x007d, 0x0020, 0x
0028, 0x007b, 0x0031, 0x007d, 0x0029, 0x0000 }; /* {0} ({1}) */ |
| 453 static const UChar pat0[4] = { 0x007b, 0x0030, 0x007d , 0x0000 } ; /* {0} */ |
| 454 static const UChar pat1[4] = { 0x007b, 0x0031, 0x007d , 0x0000 } ; /* {1} */ |
| 455 |
| 456 UResourceBundle *bundle = NULL; |
| 457 UResourceBundle *locdsppat = NULL; |
| 458 |
| 459 UErrorCode status = U_ZERO_ERROR; |
| 460 |
| 461 /* argument checking */ |
| 462 if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { |
| 463 return 0; |
| 464 } |
| 465 |
| 466 if(destCapacity<0 || (destCapacity>0 && dest==NULL)) { |
| 467 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; |
| 468 return 0; |
| 469 } |
| 470 |
| 471 bundle = ures_open(U_ICUDATA_LANG, displayLocale, &status); |
| 472 |
| 473 locdsppat = ures_getByKeyWithFallback(bundle, _kLocaleDisplayPattern, NULL,
&status); |
| 474 dispLocSeparator = ures_getStringByKeyWithFallback(locdsppat, _kSeparator, &
locSepLen, &status); |
| 475 dispLocPattern = ures_getStringByKeyWithFallback(locdsppat, _kPattern, &locP
atLen, &status); |
| 476 |
| 477 /*close the bundles */ |
| 478 ures_close(locdsppat); |
| 479 ures_close(bundle); |
| 480 |
| 481 /* If we couldn't find any data, then use the defaults */ |
| 482 if ( locSepLen == 0) { |
| 483 dispLocSeparator = defaultSeparator; |
| 484 locSepLen = 2; |
| 485 } |
| 486 |
| 487 if ( locPatLen == 0) { |
| 488 dispLocPattern = defaultPattern; |
| 489 locPatLen = 9; |
| 490 } |
| 491 |
| 492 /* |
| 493 * if there is a language, then write "language (country, variant)" |
| 494 * otherwise write "country, variant" |
| 495 */ |
| 496 |
| 497 /* write the language */ |
| 498 length=uloc_getDisplayLanguage(locale, displayLocale, |
| 499 dest, destCapacity, |
| 500 pErrorCode); |
| 501 hasLanguage= length>0; |
| 502 |
| 503 if(hasLanguage) { |
| 504 p0Len = length; |
| 505 |
| 506 /* append " (" */ |
| 507 if(length<destCapacity) { |
| 508 dest[length]=0x20; |
| 509 } |
| 510 ++length; |
| 511 if(length<destCapacity) { |
| 512 dest[length]=0x28; |
| 513 } |
| 514 ++length; |
| 515 } |
| 516 |
| 517 if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) { |
| 518 /* keep preflighting */ |
| 519 *pErrorCode=U_ZERO_ERROR; |
| 520 } |
| 521 |
| 522 /* append the script */ |
| 523 if(length<destCapacity) { |
| 524 length2=uloc_getDisplayScript(locale, displayLocale, |
| 525 dest+length, destCapacity-length, |
| 526 pErrorCode); |
| 527 } else { |
| 528 length2=uloc_getDisplayScript(locale, displayLocale, |
| 529 NULL, 0, |
| 530 pErrorCode); |
| 531 } |
| 532 hasScript= length2>0; |
| 533 length+=length2; |
| 534 |
| 535 if(hasScript) { |
| 536 /* append separator */ |
| 537 if(length+locSepLen<=destCapacity) { |
| 538 u_memcpy(dest+length,dispLocSeparator,locSepLen); |
| 539 } |
| 540 length+=locSepLen; |
| 541 } |
| 542 |
| 543 if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) { |
| 544 /* keep preflighting */ |
| 545 *pErrorCode=U_ZERO_ERROR; |
| 546 } |
| 547 |
| 548 /* append the country */ |
| 549 if(length<destCapacity) { |
| 550 length2=uloc_getDisplayCountry(locale, displayLocale, |
| 551 dest+length, destCapacity-length, |
| 552 pErrorCode); |
| 553 } else { |
| 554 length2=uloc_getDisplayCountry(locale, displayLocale, |
| 555 NULL, 0, |
| 556 pErrorCode); |
| 557 } |
| 558 hasCountry= length2>0; |
| 559 length+=length2; |
| 560 |
| 561 if(hasCountry) { |
| 562 /* append separator */ |
| 563 if(length+locSepLen<=destCapacity) { |
| 564 u_memcpy(dest+length,dispLocSeparator,locSepLen); |
| 565 } |
| 566 length+=locSepLen; |
| 567 } |
| 568 |
| 569 if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) { |
| 570 /* keep preflighting */ |
| 571 *pErrorCode=U_ZERO_ERROR; |
| 572 } |
| 573 |
| 574 /* append the variant */ |
| 575 if(length<destCapacity) { |
| 576 length2=uloc_getDisplayVariant(locale, displayLocale, |
| 577 dest+length, destCapacity-length, |
| 578 pErrorCode); |
| 579 } else { |
| 580 length2=uloc_getDisplayVariant(locale, displayLocale, |
| 581 NULL, 0, |
| 582 pErrorCode); |
| 583 } |
| 584 hasVariant= length2>0; |
| 585 length+=length2; |
| 586 |
| 587 if(hasVariant) { |
| 588 /* append separator */ |
| 589 if(length+locSepLen<=destCapacity) { |
| 590 u_memcpy(dest+length,dispLocSeparator,locSepLen); |
| 591 } |
| 592 length+=locSepLen; |
| 593 } |
| 594 |
| 595 keywordEnum = uloc_openKeywords(locale, pErrorCode); |
| 596 |
| 597 for(keywordCount = uenum_count(keywordEnum, pErrorCode); keywordCount > 0 ;
keywordCount--){ |
| 598 if(U_FAILURE(*pErrorCode)){ |
| 599 break; |
| 600 } |
| 601 /* the uenum_next returns NUL terminated string */ |
| 602 keyword = uenum_next(keywordEnum, &keywordLen, pErrorCode); |
| 603 if(length + length3 < destCapacity) { |
| 604 length3 += uloc_getDisplayKeyword(keyword, displayLocale, dest+lengt
h+length3, destCapacity-length-length3, pErrorCode); |
| 605 } else { |
| 606 length3 += uloc_getDisplayKeyword(keyword, displayLocale, NULL, 0, p
ErrorCode); |
| 607 } |
| 608 if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) { |
| 609 /* keep preflighting */ |
| 610 *pErrorCode=U_ZERO_ERROR; |
| 611 } |
| 612 keywordValueLen = uloc_getKeywordValue(locale, keyword, keywordValue,
256, pErrorCode); |
| 613 if(keywordValueLen) { |
| 614 if(length + length3 < destCapacity) { |
| 615 dest[length + length3] = 0x3D; |
| 616 } |
| 617 length3++; |
| 618 if(length + length3 < destCapacity) { |
| 619 length3 += uloc_getDisplayKeywordValue(locale, keyword, displayLoc
ale, dest+length+length3, destCapacity-length-length3, pErrorCode); |
| 620 } else { |
| 621 length3 += uloc_getDisplayKeywordValue(locale, keyword, displayLoc
ale, NULL, 0, pErrorCode); |
| 622 } |
| 623 if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) { |
| 624 /* keep preflighting */ |
| 625 *pErrorCode=U_ZERO_ERROR; |
| 626 } |
| 627 } |
| 628 if(keywordCount > 1) { |
| 629 if(length + length3 + locSepLen <= destCapacity && keywordCount) { |
| 630 u_memcpy(dest+length+length3,dispLocSeparator,locSepLen); |
| 631 length3+=locSepLen; |
| 632 } |
| 633 } |
| 634 } |
| 635 uenum_close(keywordEnum); |
| 636 |
| 637 hasKeywords = length3 > 0; |
| 638 length += length3; |
| 639 |
| 640 |
| 641 if ((hasScript && !hasCountry) |
| 642 || ((hasScript || hasCountry) && !hasVariant && !hasKeywords) |
| 643 || ((hasScript || hasCountry || hasVariant) && !hasKeywords)) { |
| 644 /* Remove separator */ |
| 645 length -= locSepLen; |
| 646 } else if (hasLanguage && !hasScript && !hasCountry && !hasVariant && !hasKe
ywords) { |
| 647 /* Remove " (" */ |
| 648 length-=2; |
| 649 } |
| 650 |
| 651 if (hasLanguage && (hasScript || hasCountry || hasVariant || hasKeywords)) { |
| 652 /* append ")" */ |
| 653 if(length<destCapacity) { |
| 654 dest[length]=0x29; |
| 655 } |
| 656 ++length; |
| 657 |
| 658 /* If the localized display pattern is something other than the default
pattern of "{0} ({1})", then |
| 659 * then we need to do the formatting here. It would be easier to use a
messageFormat to do this, but we |
| 660 * can't since we don't have the APIs in the i18n library available to u
s at this point. |
| 661 */ |
| 662 if (locPatLen != defaultPatternLen || u_strcmp(dispLocPattern,defaultPat
tern)) { /* Something other than the default pattern */ |
| 663 UChar *p0 = u_strstr(dispLocPattern,pat0); |
| 664 UChar *p1 = u_strstr(dispLocPattern,pat1); |
| 665 u_terminateUChars(dest, destCapacity, length, pErrorCode); |
| 666 |
| 667 if ( p0 != NULL && p1 != NULL ) { /* The pattern is well formed */ |
| 668 if ( dest ) { |
| 669 int32_t destLen = 0; |
| 670 UChar *result = (UChar *)uprv_malloc((length+1)*sizeof(UChar))
; |
| 671 UChar *upos = (UChar *)dispLocPattern; |
| 672 u_strcpy(result,dest); |
| 673 dest[0] = 0; |
| 674 while ( *upos ) { |
| 675 if ( upos == p0 ) { /* Handle {0} substitution */ |
| 676 u_strncat(dest,result,p0Len); |
| 677 destLen += p0Len; |
| 678 dest[destLen] = 0; /* Null terminate */ |
| 679 upos += 3; |
| 680 } else if ( upos == p1 ) { /* Handle {1} substitution */ |
| 681 UChar *p1Start = &result[p0Len+2]; |
| 682 u_strncat(dest,p1Start,length-p0Len-3); |
| 683 destLen += (length-p0Len-3); |
| 684 dest[destLen] = 0; /* Null terminate */ |
| 685 upos += 3; |
| 686 } else { /* Something from the pattern not {0} or {1} */ |
| 687 u_strncat(dest,upos,1); |
| 688 upos++; |
| 689 destLen++; |
| 690 dest[destLen] = 0; /* Null terminate */ |
| 691 } |
| 692 } |
| 693 length = destLen; |
| 694 uprv_free(result); |
| 695 } |
| 696 } |
| 697 } |
| 698 } |
| 699 if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) { |
| 700 /* keep preflighting */ |
| 701 *pErrorCode=U_ZERO_ERROR; |
| 702 } |
| 703 |
| 704 return u_terminateUChars(dest, destCapacity, length, pErrorCode); |
| 705 } |
| 706 |
| 707 U_CAPI int32_t U_EXPORT2 |
| 708 uloc_getDisplayKeyword(const char* keyword, |
| 709 const char* displayLocale, |
| 710 UChar* dest, |
| 711 int32_t destCapacity, |
| 712 UErrorCode* status){ |
| 713 |
| 714 /* argument checking */ |
| 715 if(status==NULL || U_FAILURE(*status)) { |
| 716 return 0; |
| 717 } |
| 718 |
| 719 if(destCapacity<0 || (destCapacity>0 && dest==NULL)) { |
| 720 *status=U_ILLEGAL_ARGUMENT_ERROR; |
| 721 return 0; |
| 722 } |
| 723 |
| 724 |
| 725 /* pass itemKey=NULL to look for a top-level item */ |
| 726 return _getStringOrCopyKey(U_ICUDATA_LANG, displayLocale, |
| 727 _kKeys, NULL, |
| 728 keyword, |
| 729 keyword, |
| 730 dest, destCapacity, |
| 731 status); |
| 732 |
| 733 } |
| 734 |
| 735 |
| 736 #define UCURRENCY_DISPLAY_NAME_INDEX 1 |
| 737 |
| 738 U_CAPI int32_t U_EXPORT2 |
| 739 uloc_getDisplayKeywordValue( const char* locale, |
| 740 const char* keyword, |
| 741 const char* displayLocale, |
| 742 UChar* dest, |
| 743 int32_t destCapacity, |
| 744 UErrorCode* status){ |
| 745 |
| 746 |
| 747 char keywordValue[ULOC_FULLNAME_CAPACITY*4]; |
| 748 int32_t capacity = ULOC_FULLNAME_CAPACITY*4; |
| 749 int32_t keywordValueLen =0; |
| 750 |
| 751 /* argument checking */ |
| 752 if(status==NULL || U_FAILURE(*status)) { |
| 753 return 0; |
| 754 } |
| 755 |
| 756 if(destCapacity<0 || (destCapacity>0 && dest==NULL)) { |
| 757 *status=U_ILLEGAL_ARGUMENT_ERROR; |
| 758 return 0; |
| 759 } |
| 760 |
| 761 /* get the keyword value */ |
| 762 keywordValue[0]=0; |
| 763 keywordValueLen = uloc_getKeywordValue(locale, keyword, keywordValue, capaci
ty, status); |
| 764 |
| 765 /* |
| 766 * if the keyword is equal to currency .. then to get the display name |
| 767 * we need to do the fallback ourselves |
| 768 */ |
| 769 if(uprv_stricmp(keyword, _kCurrency)==0){ |
| 770 |
| 771 int32_t dispNameLen = 0; |
| 772 const UChar *dispName = NULL; |
| 773 |
| 774 UResourceBundle *bundle = ures_open(U_ICUDATA_CURR, displayLocale, s
tatus); |
| 775 UResourceBundle *currencies = ures_getByKey(bundle, _kCurrencies, NULL,
status); |
| 776 UResourceBundle *currency = ures_getByKeyWithFallback(currencies, keyw
ordValue, NULL, status); |
| 777 |
| 778 dispName = ures_getStringByIndex(currency, UCURRENCY_DISPLAY_NAME_INDEX,
&dispNameLen, status); |
| 779 |
| 780 /*close the bundles */ |
| 781 ures_close(currency); |
| 782 ures_close(currencies); |
| 783 ures_close(bundle); |
| 784 |
| 785 if(U_FAILURE(*status)){ |
| 786 if(*status == U_MISSING_RESOURCE_ERROR){ |
| 787 /* we just want to write the value over if nothing is available
*/ |
| 788 *status = U_USING_DEFAULT_WARNING; |
| 789 }else{ |
| 790 return 0; |
| 791 } |
| 792 } |
| 793 |
| 794 /* now copy the dispName over if not NULL */ |
| 795 if(dispName != NULL){ |
| 796 if(dispNameLen <= destCapacity){ |
| 797 uprv_memcpy(dest, dispName, dispNameLen * U_SIZEOF_UCHAR); |
| 798 return u_terminateUChars(dest, destCapacity, dispNameLen, status
); |
| 799 }else{ |
| 800 *status = U_BUFFER_OVERFLOW_ERROR; |
| 801 return dispNameLen; |
| 802 } |
| 803 }else{ |
| 804 /* we have not found the display name for the value .. just copy ove
r */ |
| 805 if(keywordValueLen <= destCapacity){ |
| 806 u_charsToUChars(keywordValue, dest, keywordValueLen); |
| 807 return u_terminateUChars(dest, destCapacity, keywordValueLen, st
atus); |
| 808 }else{ |
| 809 *status = U_BUFFER_OVERFLOW_ERROR; |
| 810 return keywordValueLen; |
| 811 } |
| 812 } |
| 813 |
| 814 |
| 815 }else{ |
| 816 |
| 817 return _getStringOrCopyKey(U_ICUDATA_LANG, displayLocale, |
| 818 _kTypes, keyword, |
| 819 keywordValue, |
| 820 keywordValue, |
| 821 dest, destCapacity, |
| 822 status); |
| 823 } |
| 824 } |
OLD | NEW |