1 /* 2 ********************************************************************** 3 * Copyright (C) 1997-2014, International Business Machines 4 * Corporation and others. All Rights Reserved. 5 ********************************************************************** 6 * 7 * File USCRIPT.C 8 * 9 * Modification History: 10 * 11 * Date Name Description 12 * 07/06/2001 Ram Creation. 13 ****************************************************************************** 14 */ 15 16 #include "unicode/uchar.h" 17 #include "unicode/uscript.h" 18 #include "unicode/uloc.h" 19 #include "cmemory.h" 20 #include "cstring.h" 21 22 static const UScriptCode JAPANESE[3] = { USCRIPT_KATAKANA, USCRIPT_HIRAGANA, USCRIPT_HAN }; 23 static const UScriptCode KOREAN[2] = { USCRIPT_HANGUL, USCRIPT_HAN }; 24 static const UScriptCode HAN_BOPO[2] = { USCRIPT_HAN, USCRIPT_BOPOMOFO }; 25 26 static int32_t 27 setCodes(const UScriptCode *src, int32_t length, 28 UScriptCode *dest, int32_t capacity, UErrorCode *err) { 29 int32_t i; 30 if(U_FAILURE(*err)) { return 0; } 31 if(length > capacity) { 32 *err = U_BUFFER_OVERFLOW_ERROR; 33 return length; 34 } 35 for(i = 0; i < length; ++i) { 36 dest[i] = src[i]; 37 } 38 return length; 39 } 40 41 static int32_t 42 setOneCode(UScriptCode script, UScriptCode *scripts, int32_t capacity, UErrorCode *err) { 43 if(U_FAILURE(*err)) { return 0; } 44 if(1 > capacity) { 45 *err = U_BUFFER_OVERFLOW_ERROR; 46 return 1; 47 } 48 scripts[0] = script; 49 return 1; 50 } 51 52 static int32_t 53 getCodesFromLocale(const char *locale, 54 UScriptCode *scripts, int32_t capacity, UErrorCode *err) { 55 UErrorCode internalErrorCode = U_ZERO_ERROR; 56 char lang[8]; 57 char script[8]; 58 int32_t scriptLength; 59 if(U_FAILURE(*err)) { return 0; } 60 // Multi-script languages, equivalent to the LocaleScript data 61 // that we used to load from locale resource bundles. 62 /*length = */ uloc_getLanguage(locale, lang, UPRV_LENGTHOF(lang), &internalErrorCode); 63 if(U_FAILURE(internalErrorCode) || internalErrorCode == U_STRING_NOT_TERMINATED_WARNING) { 64 return 0; 65 } 66 if(0 == uprv_strcmp(lang, "ja")) { 67 return setCodes(JAPANESE, UPRV_LENGTHOF(JAPANESE), scripts, capacity, err); 68 } 69 if(0 == uprv_strcmp(lang, "ko")) { 70 return setCodes(KOREAN, UPRV_LENGTHOF(KOREAN), scripts, capacity, err); 71 } 72 scriptLength = uloc_getScript(locale, script, UPRV_LENGTHOF(script), &internalErrorCode); 73 if(U_FAILURE(internalErrorCode) || internalErrorCode == U_STRING_NOT_TERMINATED_WARNING) { 74 return 0; 75 } 76 if(0 == uprv_strcmp(lang, "zh") && 0 == uprv_strcmp(script, "Hant")) { 77 return setCodes(HAN_BOPO, UPRV_LENGTHOF(HAN_BOPO), scripts, capacity, err); 78 } 79 // Explicit script code. 80 if(scriptLength != 0) { 81 UScriptCode scriptCode = (UScriptCode)u_getPropertyValueEnum(UCHAR_SCRIPT, script); 82 if(scriptCode != USCRIPT_INVALID_CODE) { 83 if(scriptCode == USCRIPT_SIMPLIFIED_HAN || scriptCode == USCRIPT_TRADITIONAL_HAN) { 84 scriptCode = USCRIPT_HAN; 85 } 86 return setOneCode(scriptCode, scripts, capacity, err); 87 } 88 } 89 return 0; 90 } 91 92 /* TODO: this is a bad API and should be deprecated, ticket #11141 */ 93 U_CAPI int32_t U_EXPORT2 94 uscript_getCode(const char* nameOrAbbrOrLocale, 95 UScriptCode* fillIn, 96 int32_t capacity, 97 UErrorCode* err){ 98 UBool triedCode; 99 char likely[ULOC_FULLNAME_CAPACITY]; 100 UErrorCode internalErrorCode; 101 int32_t length; 102 103 if(U_FAILURE(*err)) { 104 return 0; 105 } 106 if(nameOrAbbrOrLocale==NULL || 107 (fillIn == NULL ? capacity != 0 : capacity < 0)) { 108 *err = U_ILLEGAL_ARGUMENT_ERROR; 109 return 0; 110 } 111 112 triedCode = FALSE; 113 if(uprv_strchr(nameOrAbbrOrLocale, '-')==NULL && uprv_strchr(nameOrAbbrOrLocale, '_')==NULL ){ 114 /* try long and abbreviated script names first */ 115 UScriptCode code = (UScriptCode) u_getPropertyValueEnum(UCHAR_SCRIPT, nameOrAbbrOrLocale); 116 if(code!=USCRIPT_INVALID_CODE) { 117 return setOneCode(code, fillIn, capacity, err); 118 } 119 triedCode = TRUE; 120 } 121 internalErrorCode = U_ZERO_ERROR; 122 length = getCodesFromLocale(nameOrAbbrOrLocale, fillIn, capacity, err); 123 if(U_FAILURE(*err) || length != 0) { 124 return length; 125 } 126 (void)uloc_addLikelySubtags(nameOrAbbrOrLocale, 127 likely, UPRV_LENGTHOF(likely), &internalErrorCode); 128 if(U_SUCCESS(internalErrorCode) && internalErrorCode != U_STRING_NOT_TERMINATED_WARNING) { 129 length = getCodesFromLocale(likely, fillIn, capacity, err); 130 if(U_FAILURE(*err) || length != 0) { 131 return length; 132 } 133 } 134 if(!triedCode) { 135 /* still not found .. try long and abbreviated script names again */ 136 UScriptCode code = (UScriptCode) u_getPropertyValueEnum(UCHAR_SCRIPT, nameOrAbbrOrLocale); 137 if(code!=USCRIPT_INVALID_CODE) { 138 return setOneCode(code, fillIn, capacity, err); 139 } 140 } 141 return 0; 142 } 143