X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/51004dcb01e06fef634b61be77ed73dd61cb6db9..a01113dcd0f39d5da295ef82785beff9ed86fe38:/icuSources/common/locdispnames.cpp?ds=sidebyside diff --git a/icuSources/common/locdispnames.cpp b/icuSources/common/locdispnames.cpp index dd444524..7024bc46 100644 --- a/icuSources/common/locdispnames.cpp +++ b/icuSources/common/locdispnames.cpp @@ -1,12 +1,14 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html /* ******************************************************************************* * -* Copyright (C) 1997-2012, International Business Machines +* Copyright (C) 1997-2016, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************* * file name: locdispnames.cpp -* encoding: US-ASCII +* encoding: UTF-8 * tab size: 8 (not used) * indentation:4 * @@ -20,9 +22,12 @@ #include "unicode/utypes.h" #include "unicode/brkiter.h" #include "unicode/locid.h" +#include "unicode/uenum.h" #include "unicode/uloc.h" #include "unicode/ures.h" #include "unicode/ustring.h" +#include "unicode/uldnames.h" +#include "charstr.h" #include "cmemory.h" #include "cstring.h" #include "putilimp.h" @@ -304,14 +309,11 @@ _getStringOrCopyKey(const char *path, const char *locale, if(itemKey==NULL) { /* top-level item: normal resource bundle access */ - UResourceBundle *rb; - - rb=ures_open(path, locale, pErrorCode); + icu::LocalUResourceBundlePointer rb(ures_open(path, locale, pErrorCode)); if(U_SUCCESS(*pErrorCode)) { - s=ures_getStringByKey(rb, tableKey, &length, pErrorCode); + s=ures_getStringByKey(rb.getAlias(), tableKey, &length, pErrorCode); /* see comment about closing rb near "return item;" in _res_getTableStringWithFallback() */ - ures_close(rb); } } else { /* Language code should not be a number. If it is, set the error code. */ @@ -465,8 +467,7 @@ uloc_getDisplayName(const char *locale, UChar *dest, int32_t destCapacity, UErrorCode *pErrorCode) { - static const UChar defaultSeparator[3] = { 0x002c, 0x0020, 0x0000 }; /* comma + space */ - static const int32_t defaultSepLen = 2; + static const UChar defaultSeparator[9] = { 0x007b, 0x0030, 0x007d, 0x002c, 0x0020, 0x007b, 0x0031, 0x007d, 0x0000 }; /* "{0}, {1}" */ static const UChar sub0[4] = { 0x007b, 0x0030, 0x007d , 0x0000 } ; /* {0} */ static const UChar sub1[4] = { 0x007b, 0x0031, 0x007d , 0x0000 } ; /* {1} */ static const int32_t subLen = 3; @@ -484,6 +485,11 @@ uloc_getDisplayName(const char *locale, const UChar *pattern; int32_t patLen = 0; int32_t sub0Pos, sub1Pos; + + UChar formatOpenParen = 0x0028; // ( + UChar formatReplaceOpenParen = 0x005B; // [ + UChar formatCloseParen = 0x0029; // ) + UChar formatReplaceCloseParen = 0x005D; // ] UBool haveLang = TRUE; /* assume true, set false if we find we don't have a lang component in the locale */ @@ -502,23 +508,57 @@ uloc_getDisplayName(const char *locale, return 0; } + { // For select languages + script, route to uldn_localeDisplayName + char lang[ULOC_LANG_CAPACITY]; + char script[ULOC_SCRIPT_CAPACITY ]; + UErrorCode status = U_ZERO_ERROR; + int32_t langlen = uloc_getLanguage(locale, lang, ULOC_LANG_CAPACITY, &status); + int32_t scriptlen = uloc_getScript(locale, script, ULOC_SCRIPT_CAPACITY, &status); + if ( U_SUCCESS(status) && scriptlen>0 && (uprv_strcmp(lang, "zh") == 0 || uprv_strcmp(lang, "yue") == 0 || + uprv_strcmp(lang, "ks") == 0 || uprv_strcmp(lang, "pa") == 0 || uprv_strcmp(lang, "ur") == 0) ) { + ULocaleDisplayNames* uldn = uldn_open(displayLocale, ULDN_STANDARD_NAMES, &status); + if ( U_SUCCESS(status) ) { + int32_t namelen = uldn_localeDisplayName(uldn, locale, dest, destCapacity, pErrorCode); + uldn_close(uldn); + return namelen; + } + } + } + { UErrorCode status = U_ZERO_ERROR; - UResourceBundle* locbundle=ures_open(U_ICUDATA_LANG, displayLocale, &status); - UResourceBundle* dspbundle=ures_getByKeyWithFallback(locbundle, _kLocaleDisplayPattern, - NULL, &status); - separator=ures_getStringByKeyWithFallback(dspbundle, _kSeparator, &sepLen, &status); - pattern=ures_getStringByKeyWithFallback(dspbundle, _kPattern, &patLen, &status); + icu::LocalUResourceBundlePointer locbundle( + ures_open(U_ICUDATA_LANG, displayLocale, &status)); + icu::LocalUResourceBundlePointer dspbundle( + ures_getByKeyWithFallback(locbundle.getAlias(), _kLocaleDisplayPattern, NULL, &status)); - ures_close(dspbundle); - ures_close(locbundle); + separator=ures_getStringByKeyWithFallback(dspbundle.getAlias(), _kSeparator, &sepLen, &status); + pattern=ures_getStringByKeyWithFallback(dspbundle.getAlias(), _kPattern, &patLen, &status); } /* If we couldn't find any data, then use the defaults */ if(sepLen == 0) { separator = defaultSeparator; - sepLen = defaultSepLen; + } + /* #10244: Even though separator is now a pattern, it is awkward to handle it as such + * here since we are trying to build the display string in place in the dest buffer, + * and to handle it as a pattern would entail having separate storage for the + * substrings that need to be combined (the first of which may be the result of + * previous such combinations). So for now we continue to treat the portion between + * {0} and {1} as a string to be appended when joining substrings, ignoring anything + * that is before {0} or after {1} (no existing separator pattern has any such thing). + * This is similar to how pattern is handled below. + */ + { + UChar *p0=u_strstr(separator, sub0); + UChar *p1=u_strstr(separator, sub1); + if (p0==NULL || p1==NULL || p1(p1 - separator); } if(patLen==0 || (patLen==defaultPatLen && !u_strncmp(pattern, defaultPattern, patLen))) { @@ -526,6 +566,7 @@ uloc_getDisplayName(const char *locale, patLen=defaultPatLen; sub0Pos=defaultSub0Pos; sub1Pos=defaultSub1Pos; + // use default formatOpenParen etc. set above } else { /* non-default pattern */ UChar *p0=u_strstr(pattern, sub0); UChar *p1=u_strstr(pattern, sub1); @@ -533,12 +574,18 @@ uloc_getDisplayName(const char *locale, *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return 0; } - sub0Pos=p0-pattern; - sub1Pos=p1-pattern; + sub0Pos = static_cast(p0-pattern); + sub1Pos = static_cast(p1-pattern); if (sub1Pos < sub0Pos) { /* a very odd pattern */ int32_t t=sub0Pos; sub0Pos=sub1Pos; sub1Pos=t; langi=1; } + if (u_strchr(pattern, 0xFF08) != NULL) { + formatOpenParen = 0xFF08; // fullwidth ( + formatReplaceOpenParen = 0xFF3B; // fullwidth [ + formatCloseParen = 0xFF09; // fullwidth ) + formatReplaceCloseParen = 0xFF3D; // fullwidth ] + } } /* We loop here because there is one case in which after the first pass we could need to @@ -555,7 +602,7 @@ uloc_getDisplayName(const char *locale, int32_t langPos=0; /* position in output of language substitution */ int32_t restLen=0; /* length of 'everything else' substitution */ int32_t restPos=0; /* position in output of 'everything else' substitution */ - UEnumeration* kenum = NULL; /* keyword enumeration */ + icu::LocalUEnumerationPointer kenum; /* keyword enumeration */ /* prefix of pattern, extremely likely to be empty */ if(sub0Pos) { @@ -608,12 +655,11 @@ uloc_getDisplayName(const char *locale, len=uloc_getDisplayVariant(locale, displayLocale, p, cap, pErrorCode); break; case 3: - kenum = uloc_openKeywords(locale, pErrorCode); - /* fall through */ + kenum.adoptInstead(uloc_openKeywords(locale, pErrorCode)); + U_FALLTHROUGH; default: { - const char* kw=uenum_next(kenum, &len, pErrorCode); + const char* kw=uenum_next(kenum.getAlias(), &len, pErrorCode); if (kw == NULL) { - uenum_close(kenum); len=0; /* mark that we didn't add a component */ subdone=TRUE; } else { @@ -660,7 +706,14 @@ uloc_getDisplayName(const char *locale, if (len>0) { /* we addeed a component, so add separator and write it if there's room. */ if(len+sepLen<=cap) { - p+=len; + const UChar * plimit = p + len; + for (; p < plimit; p++) { + if (*p == formatOpenParen) { + *p = formatReplaceOpenParen; + } else if (*p == formatCloseParen) { + *p = formatReplaceCloseParen; + } + } for(int32_t i=0;i