1 /* 2 * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "sun_util_locale_provider_HostLocaleProviderAdapterImpl.h" 27 #include "jni_util.h" 28 #include <CoreFoundation/CoreFoundation.h> 29 #include <stdio.h> 30 31 #define BUFLEN 256 32 33 // java.util.Calendar constants 34 #define CALENDAR_FIELD_ERA 0 // Calendar.ERA 35 #define CALENDAR_FIELD_DAY_OF_WEEK 7 // Calendar.DAY_OF_WEEK 36 #define CALENDAR_FIELD_AM_PM 9 // Calendar.AM_PM 37 #define JAPANESE_MEIJI_INDEX 232 38 39 static CFDateFormatterStyle convertDateFormatterStyle(jint javaStyle); 40 static CFNumberFormatterStyle convertNumberFormatterStyle(jint javaStyle); 41 static void copyArrayElements(JNIEnv *env, CFArrayRef cfarray, jobjectArray jarray, CFIndex sindex, int dindex, int count); 42 static jstring getNumberSymbolString(JNIEnv *env, jstring jlangtag, jstring jdefault, CFStringRef type); 43 static jchar getNumberSymbolChar(JNIEnv *env, jstring jlangtag, jchar jdefault, CFStringRef type); 44 jobjectArray getErasImpl(JNIEnv *env, jstring jlangtag, jint style, jobjectArray eras); 45 jobjectArray getWeekdaysImpl(JNIEnv *env, jclass cls, jstring jlangtag, jint style, jobjectArray wdays); 46 jobjectArray getAmPmImpl(JNIEnv *env, jclass cls, jstring jlangtag, jint style, jobjectArray ampms); 47 48 // from java_props_macosx.c 49 extern char * getMacOSXLocale(int cat); 50 extern char * getPosixLocale(int cat); 51 52 /* 53 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 54 * Method: getDefaultLocale 55 * Signature: (I)Ljava/lang/String; 56 */ 57 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDefaultLocale 58 (JNIEnv *env, jclass cls, jint cat) { 59 char * localeString = NULL; 60 int posixCat; 61 jstring ret = NULL; 62 63 switch (cat) { 64 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CAT_DISPLAY: 65 posixCat = LC_MESSAGES; 66 break; 67 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CAT_FORMAT: 68 default: 69 posixCat = LC_CTYPE; 70 break; 71 } 72 73 localeString = getMacOSXLocale(posixCat); 74 if (localeString == NULL) { 75 localeString = getPosixLocale(posixCat); 76 if (localeString == NULL) { 77 JNU_ThrowOutOfMemoryError(env, NULL); 78 return NULL; 79 } 80 } 81 ret = (*env)->NewStringUTF(env, localeString); 82 free(localeString); 83 84 return ret; 85 } 86 87 /* 88 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 89 * Method: getDateTimePatternNative 90 * Signature: (IILjava/lang/String;)Ljava/lang/String; 91 */ 92 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDateTimePatternNative 93 (JNIEnv *env, jclass cls, jint dateStyle, jint timeStyle, jstring jlangtag) { 94 jstring ret = NULL; 95 CFLocaleRef cflocale = CFLocaleCopyCurrent(); 96 97 if (cflocale != NULL) { 98 CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault, 99 cflocale, 100 convertDateFormatterStyle(dateStyle), 101 convertDateFormatterStyle(timeStyle)); 102 if (df != NULL) { 103 char buf[BUFLEN]; 104 CFStringRef formatStr = CFDateFormatterGetFormat(df); 105 CFStringGetCString(formatStr, buf, BUFLEN, kCFStringEncodingUTF8); 106 ret = (*env)->NewStringUTF(env, buf); 107 CFRelease(df); 108 } 109 CFRelease(cflocale); 110 } 111 112 return ret; 113 } 114 115 /* 116 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 117 * Method: getCalendarID 118 * Signature: (Ljava/lang/String;)Ljava/lang/String; 119 */ 120 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCalendarID 121 (JNIEnv *env, jclass cls, jstring jlangtag) { 122 jstring ret = NULL; 123 CFLocaleRef cflocale = CFLocaleCopyCurrent(); 124 125 if (cflocale != NULL) { 126 char buf[BUFLEN]; 127 CFTypeRef calid = CFLocaleGetValue(cflocale, kCFLocaleCalendarIdentifier); 128 CFStringGetCString((CFStringRef)calid, buf, BUFLEN, kCFStringEncodingUTF8); 129 ret = (*env)->NewStringUTF(env, buf); 130 CFRelease(cflocale); 131 } 132 133 return ret; 134 } 135 136 /* 137 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 138 * Method: getAmPmStrings 139 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 140 */ 141 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getAmPmStrings 142 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray ampms) { 143 return getAmPmImpl(env, cls, jlangtag, 0, ampms); 144 } 145 146 /* 147 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 148 * Method: getEras 149 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 150 */ 151 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getEras 152 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray eras) { 153 return getErasImpl(env, jlangtag, 0, eras); 154 } 155 156 /* 157 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 158 * Method: getMonths 159 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 160 */ 161 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMonths 162 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray months) { 163 CFLocaleRef cflocale = CFLocaleCopyCurrent(); 164 if (cflocale != NULL) { 165 CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault, 166 cflocale, 167 kCFDateFormatterFullStyle, 168 kCFDateFormatterFullStyle); 169 if (df != NULL) { 170 CFArrayRef cfmonths = CFDateFormatterCopyProperty(df, kCFDateFormatterMonthSymbols); 171 if (cfmonths != NULL) { 172 copyArrayElements(env, cfmonths, months, 0, 0, CFArrayGetCount(cfmonths)); 173 CFRelease(cfmonths); 174 } 175 CFRelease(df); 176 } 177 CFRelease(cflocale); 178 } 179 180 return months; 181 } 182 183 /* 184 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 185 * Method: getShortMonths 186 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 187 */ 188 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getShortMonths 189 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray smonths) { 190 CFLocaleRef cflocale = CFLocaleCopyCurrent(); 191 if (cflocale != NULL) { 192 CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault, 193 cflocale, 194 kCFDateFormatterFullStyle, 195 kCFDateFormatterFullStyle); 196 if (df != NULL) { 197 CFArrayRef cfsmonths = CFDateFormatterCopyProperty(df, kCFDateFormatterShortMonthSymbols); 198 if (cfsmonths != NULL) { 199 copyArrayElements(env, cfsmonths, smonths, 0, 0, CFArrayGetCount(cfsmonths)); 200 CFRelease(cfsmonths); 201 } 202 CFRelease(df); 203 } 204 CFRelease(cflocale); 205 } 206 207 return smonths; 208 } 209 210 /* 211 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 212 * Method: getWeekdays 213 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 214 */ 215 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getWeekdays 216 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray wdays) { 217 return getWeekdaysImpl(env, cls, jlangtag, 0, wdays); 218 } 219 220 /* 221 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 222 * Method: getShortWeekdays 223 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 224 */ 225 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getShortWeekdays 226 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray swdays) { 227 CFLocaleRef cflocale = CFLocaleCopyCurrent(); 228 if (cflocale != NULL) { 229 CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault, 230 cflocale, 231 kCFDateFormatterFullStyle, 232 kCFDateFormatterFullStyle); 233 if (df != NULL) { 234 CFArrayRef cfswdays = CFDateFormatterCopyProperty(df, kCFDateFormatterShortWeekdaySymbols); 235 if (cfswdays != NULL) { 236 copyArrayElements(env, cfswdays, swdays, 0, 1, CFArrayGetCount(cfswdays)); 237 CFRelease(cfswdays); 238 } 239 CFRelease(df); 240 } 241 CFRelease(cflocale); 242 } 243 244 return swdays; 245 } 246 247 /* 248 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 249 * Method: getNumberPatternNative 250 * Signature: (ILjava/lang/String;)Ljava/lang/String; 251 */ 252 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getNumberPatternNative 253 (JNIEnv *env, jclass cls, jint numberStyle, jstring jlangtag) { 254 jstring ret = NULL; 255 CFLocaleRef cflocale = CFLocaleCopyCurrent(); 256 if (cflocale != NULL) { 257 CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorDefault, 258 cflocale, 259 convertNumberFormatterStyle(numberStyle)); 260 if (nf != NULL) { 261 char buf[BUFLEN]; 262 CFStringRef formatStr = CFNumberFormatterGetFormat(nf); 263 CFStringGetCString(formatStr, buf, BUFLEN, kCFStringEncodingUTF8); 264 ret = (*env)->NewStringUTF(env, buf); 265 CFRelease(nf); 266 } 267 CFRelease(cflocale); 268 } 269 270 return ret; 271 } 272 273 /* 274 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 275 * Method: getCurrencySymbol 276 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 277 */ 278 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCurrencySymbol 279 (JNIEnv *env, jclass cls, jstring jlangtag, jstring currencySymbol) { 280 return getNumberSymbolString(env, jlangtag, currencySymbol, kCFNumberFormatterCurrencySymbol); 281 } 282 283 /* 284 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 285 * Method: getDecimalSeparator 286 * Signature: (Ljava/lang/String;C)C 287 */ 288 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDecimalSeparator 289 (JNIEnv *env, jclass cls, jstring jlangtag, jchar decimalSeparator) { 290 return getNumberSymbolChar(env, jlangtag, decimalSeparator, kCFNumberFormatterDecimalSeparator); 291 } 292 293 /* 294 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 295 * Method: getGroupingSeparator 296 * Signature: (Ljava/lang/String;C)C 297 */ 298 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getGroupingSeparator 299 (JNIEnv *env, jclass cls, jstring jlangtag, jchar groupingSeparator) { 300 return getNumberSymbolChar(env, jlangtag, groupingSeparator, kCFNumberFormatterGroupingSeparator); 301 } 302 303 /* 304 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 305 * Method: getInfinity 306 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 307 */ 308 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getInfinity 309 (JNIEnv *env, jclass cls, jstring jlangtag, jstring infinity) { 310 return getNumberSymbolString(env, jlangtag, infinity, kCFNumberFormatterInfinitySymbol); 311 } 312 313 /* 314 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 315 * Method: getInternationalCurrencySymbol 316 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 317 */ 318 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getInternationalCurrencySymbol 319 (JNIEnv *env, jclass cls, jstring jlangtag, jstring internationalCurrencySymbol) { 320 return getNumberSymbolString(env, jlangtag, internationalCurrencySymbol, kCFNumberFormatterInternationalCurrencySymbol); 321 } 322 323 /* 324 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 325 * Method: getMinusSign 326 * Signature: (Ljava/lang/String;C)C 327 */ 328 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMinusSign 329 (JNIEnv *env, jclass cls, jstring jlangtag, jchar minusSign) { 330 return getNumberSymbolChar(env, jlangtag, minusSign, kCFNumberFormatterMinusSign); 331 } 332 333 /* 334 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 335 * Method: getMonetaryDecimalSeparator 336 * Signature: (Ljava/lang/String;C)C 337 */ 338 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMonetaryDecimalSeparator 339 (JNIEnv *env, jclass cls, jstring jlangtag, jchar monetaryDecimalSeparator) { 340 return getNumberSymbolChar(env, jlangtag, monetaryDecimalSeparator, kCFNumberFormatterCurrencyDecimalSeparator); 341 } 342 343 /* 344 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 345 * Method: getNaN 346 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 347 */ 348 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getNaN 349 (JNIEnv *env, jclass cls, jstring jlangtag, jstring nan) { 350 return getNumberSymbolString(env, jlangtag, nan, kCFNumberFormatterNaNSymbol); 351 } 352 353 /* 354 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 355 * Method: getPercent 356 * Signature: (Ljava/lang/String;C)C 357 */ 358 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPercent 359 (JNIEnv *env, jclass cls, jstring jlangtag, jchar percent) { 360 return getNumberSymbolChar(env, jlangtag, percent, kCFNumberFormatterPercentSymbol); 361 } 362 363 /* 364 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 365 * Method: getPerMill 366 * Signature: (Ljava/lang/String;C)C 367 */ 368 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPerMill 369 (JNIEnv *env, jclass cls, jstring jlangtag, jchar perMill) { 370 return getNumberSymbolChar(env, jlangtag, perMill, kCFNumberFormatterPerMillSymbol); 371 } 372 373 /* 374 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 375 * Method: getZeroDigit 376 * Signature: (Ljava/lang/String;C)C 377 */ 378 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getZeroDigit 379 (JNIEnv *env, jclass cls, jstring jlangtag, jchar zeroDigit) { 380 // The following code *should* work, but not for some reason :o 381 // 382 //return getNumberSymbolChar(env, jlangtag, zeroDigit, kCFNumberFormatterZeroSymbol); 383 // 384 // so here is a workaround. 385 jchar ret = zeroDigit; 386 CFLocaleRef cflocale = CFLocaleCopyCurrent(); 387 388 if (cflocale != NULL) { 389 CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorDefault, 390 cflocale, 391 kCFNumberFormatterNoStyle); 392 if (nf != NULL) { 393 int zero = 0; 394 CFStringRef str = CFNumberFormatterCreateStringWithValue(kCFAllocatorDefault, 395 nf, kCFNumberIntType, &zero); 396 if (str != NULL) { 397 if (CFStringGetLength(str) > 0) { 398 ret = CFStringGetCharacterAtIndex(str, 0); 399 } 400 CFRelease(str); 401 } 402 403 CFRelease(nf); 404 } 405 406 CFRelease(cflocale); 407 } 408 409 return ret; 410 } 411 412 /* 413 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 414 * Method: getExponentSeparator 415 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 416 */ 417 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getExponentSeparator 418 (JNIEnv *env, jclass cls, jstring jlangtag, jstring exponent) { 419 return getNumberSymbolString(env, jlangtag, exponent, kCFNumberFormatterExponentSymbol); 420 } 421 422 /* 423 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 424 * Method: getCalendarInt 425 * Signature: (Ljava/lang/String;I)I 426 */ 427 JNIEXPORT jint JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCalendarInt 428 (JNIEnv *env, jclass cls, jstring jlangtag, jint type) { 429 jint ret = 0; 430 CFCalendarRef cfcal = CFCalendarCopyCurrent(); 431 432 if (cfcal != NULL) { 433 switch (type) { 434 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CD_FIRSTDAYOFWEEK: 435 ret = CFCalendarGetFirstWeekday(cfcal); 436 break; 437 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CD_MINIMALDAYSINFIRSTWEEK: 438 ret = CFCalendarGetMinimumDaysInFirstWeek(cfcal); 439 break; 440 default: 441 ret = 0; 442 } 443 444 CFRelease(cfcal); 445 } 446 447 return ret; 448 } 449 450 /* 451 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 452 * Method: getCalendarDisplayStrings 453 * Signature: (Ljava/lang/String;III)[Ljava/lang/String; 454 */ 455 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCalendarDisplayStrings 456 (JNIEnv *env, jclass cls, jstring jlangtag, jint field, jint style) { 457 switch (field) { 458 case CALENDAR_FIELD_ERA: 459 return getErasImpl(env, jlangtag, style, NULL); 460 461 case CALENDAR_FIELD_DAY_OF_WEEK: 462 return getWeekdaysImpl(env, cls, jlangtag, style, NULL); 463 464 case CALENDAR_FIELD_AM_PM: 465 return getAmPmImpl(env, cls, jlangtag, style, NULL); 466 467 default: 468 // not supported 469 return NULL; 470 } 471 } 472 473 /* 474 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 475 * Method: getDisplayString 476 * Signature: (Ljava/lang/String;ILjava/lang/String;)Ljava/lang/String; 477 */ 478 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDisplayString 479 (JNIEnv *env, jclass cls, jstring jlangtag, jint type, jstring value) { 480 jstring ret = NULL; 481 482 const char *clangtag = (*env)->GetStringUTFChars(env, jlangtag, 0); 483 if (clangtag != NULL) { 484 const char *cvalue = (*env)->GetStringUTFChars(env, value, 0); 485 if (cvalue != NULL) { 486 CFStringRef cflangtag = 487 CFStringCreateWithCString(kCFAllocatorDefault, clangtag, kCFStringEncodingUTF8); 488 if (cflangtag != NULL) { 489 CFLocaleRef cflocale = CFLocaleCreate(kCFAllocatorDefault, cflangtag); 490 if (cflocale != NULL) { 491 CFStringRef cfvalue = 492 CFStringCreateWithCString(kCFAllocatorDefault, cvalue, kCFStringEncodingUTF8); 493 if (cfvalue != NULL) { 494 CFStringRef str = NULL; 495 switch (type) { 496 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_LANGUAGE: 497 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleLanguageCode, cfvalue); 498 break; 499 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_SCRIPT: 500 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleScriptCode, cfvalue); 501 break; 502 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_REGION: 503 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleCountryCode, cfvalue); 504 break; 505 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_VARIANT: 506 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleVariantCode, cfvalue); 507 break; 508 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_CURRENCY_CODE: 509 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleCurrencyCode, cfvalue); 510 break; 511 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_CURRENCY_SYMBOL: 512 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleCurrencySymbol, cfvalue); 513 break; 514 } 515 if (str != NULL) { 516 char buf[BUFLEN]; 517 CFStringGetCString(str, buf, BUFLEN, kCFStringEncodingUTF8); 518 CFRelease(str); 519 ret = (*env)->NewStringUTF(env, buf); 520 } 521 CFRelease(cfvalue); 522 } 523 CFRelease(cflocale); 524 } 525 CFRelease(cflangtag); 526 } 527 (*env)->ReleaseStringUTFChars(env, value, cvalue); 528 } 529 (*env)->ReleaseStringUTFChars(env, jlangtag, clangtag); 530 } 531 532 return ret; 533 } 534 535 /* 536 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 537 * Method: getTimeZoneDisplayString 538 * Signature: (Ljava/lang/String;ILjava/lang/String;)Ljava/lang/String; 539 */ 540 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getTimeZoneDisplayString 541 (JNIEnv *env, jclass cls, jstring jlangtag, jint type, jstring tzid) { 542 jstring ret = NULL; 543 544 const char *clangtag = (*env)->GetStringUTFChars(env, jlangtag, 0); 545 if (clangtag != NULL) { 546 const char *ctzid = (*env)->GetStringUTFChars(env, tzid, 0); 547 if (ctzid != NULL) { 548 CFStringRef cflangtag = 549 CFStringCreateWithCString(kCFAllocatorDefault, clangtag, kCFStringEncodingUTF8); 550 if (cflangtag != NULL) { 551 CFLocaleRef cflocale = CFLocaleCreate(kCFAllocatorDefault, cflangtag); 552 if (cflocale != NULL) { 553 CFStringRef cftzid = 554 CFStringCreateWithCString(kCFAllocatorDefault, ctzid, kCFStringEncodingUTF8); 555 if (cftzid != NULL) { 556 CFTimeZoneRef cftz = CFTimeZoneCreateWithName(kCFAllocatorDefault, cftzid, false); 557 if (cftz != NULL) { 558 CFStringRef str = NULL; 559 switch (type) { 560 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_TZ_SHORT_STANDARD: 561 str = CFTimeZoneCopyLocalizedName(cftz, kCFTimeZoneNameStyleShortStandard, cflocale); 562 break; 563 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_TZ_SHORT_DST: 564 str = CFTimeZoneCopyLocalizedName(cftz, kCFTimeZoneNameStyleShortDaylightSaving, cflocale); 565 break; 566 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_TZ_LONG_STANDARD: 567 str = CFTimeZoneCopyLocalizedName(cftz, kCFTimeZoneNameStyleStandard, cflocale); 568 break; 569 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_TZ_LONG_DST: 570 str = CFTimeZoneCopyLocalizedName(cftz, kCFTimeZoneNameStyleDaylightSaving, cflocale); 571 break; 572 } 573 if (str != NULL) { 574 char buf[BUFLEN]; 575 CFStringGetCString(str, buf, BUFLEN, kCFStringEncodingUTF8); 576 CFRelease(str); 577 ret = (*env)->NewStringUTF(env, buf); 578 } 579 CFRelease(cftz); 580 } 581 CFRelease(cftzid); 582 } 583 CFRelease(cflocale); 584 } 585 CFRelease(cflangtag); 586 } 587 (*env)->ReleaseStringUTFChars(env, tzid, ctzid); 588 } 589 (*env)->ReleaseStringUTFChars(env, jlangtag, clangtag); 590 } 591 592 return ret; 593 } 594 595 static CFDateFormatterStyle convertDateFormatterStyle(jint javaStyle) { 596 switch (javaStyle) { 597 case 0: // FULL 598 return kCFDateFormatterFullStyle; 599 case 1: // LONG 600 return kCFDateFormatterLongStyle; 601 case 2: // MEDIUM 602 return kCFDateFormatterMediumStyle; 603 case 3: // LONG 604 return kCFDateFormatterShortStyle; 605 case -1: // No style 606 default: 607 return kCFDateFormatterNoStyle; 608 } 609 } 610 611 static CFNumberFormatterStyle convertNumberFormatterStyle(jint javaStyle) { 612 switch (javaStyle) { 613 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_CURRENCY: 614 return kCFNumberFormatterCurrencyStyle; 615 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_INTEGER: 616 return kCFNumberFormatterDecimalStyle; 617 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_NUMBER: 618 return kCFNumberFormatterDecimalStyle; 619 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_PERCENT: 620 return kCFNumberFormatterPercentStyle; 621 default: 622 return kCFNumberFormatterNoStyle; 623 } 624 } 625 626 static void copyArrayElements(JNIEnv *env, CFArrayRef cfarray, jobjectArray jarray, CFIndex sindex, int dindex, int count) { 627 char buf[BUFLEN]; 628 jstring tmp_string; 629 630 for (; count > 0; sindex++, dindex++, count--) { 631 CFStringGetCString(CFArrayGetValueAtIndex(cfarray, sindex), buf, BUFLEN, kCFStringEncodingUTF8); 632 tmp_string = (*env)->NewStringUTF(env, buf); 633 if (tmp_string != NULL) { 634 (*env)->SetObjectArrayElement(env, jarray, dindex, tmp_string); 635 } else { 636 break; 637 } 638 } 639 } 640 641 static jstring getNumberSymbolString(JNIEnv *env, jstring jlangtag, jstring jdefault, CFStringRef type) { 642 char buf[BUFLEN]; 643 jstring ret = jdefault; 644 CFLocaleRef cflocale = CFLocaleCopyCurrent(); 645 646 if (cflocale != NULL) { 647 CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorDefault, 648 cflocale, 649 kCFNumberFormatterNoStyle); 650 if (nf != NULL) { 651 CFStringRef str = CFNumberFormatterCopyProperty(nf, type); 652 if (str != NULL) { 653 CFStringGetCString(str, buf, BUFLEN, kCFStringEncodingUTF8); 654 CFRelease(str); 655 ret = (*env)->NewStringUTF(env, buf); 656 } 657 658 CFRelease(nf); 659 } 660 661 CFRelease(cflocale); 662 } 663 664 return ret; 665 } 666 667 static jchar getNumberSymbolChar(JNIEnv *env, jstring jlangtag, jchar jdefault, CFStringRef type) { 668 jchar ret = jdefault; 669 CFLocaleRef cflocale = CFLocaleCopyCurrent(); 670 671 if (cflocale != NULL) { 672 CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorDefault, 673 cflocale, 674 kCFNumberFormatterNoStyle); 675 if (nf != NULL) { 676 CFStringRef str = CFNumberFormatterCopyProperty(nf, type); 677 if (str != NULL) { 678 if (CFStringGetLength(str) > 0) { 679 ret = CFStringGetCharacterAtIndex(str, 0); 680 } 681 CFRelease(str); 682 } 683 684 CFRelease(nf); 685 } 686 687 CFRelease(cflocale); 688 } 689 690 return ret; 691 } 692 693 jobjectArray getErasImpl(JNIEnv *env, jstring jlangtag, jint style, jobjectArray eras) { 694 jobjectArray ret = eras; 695 CFLocaleRef cflocale = CFLocaleCopyCurrent(); 696 if (cflocale != NULL) { 697 CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault, 698 cflocale, 699 convertDateFormatterStyle(style), 700 convertDateFormatterStyle(style)); 701 if (df != NULL) { 702 CFArrayRef cferas = CFDateFormatterCopyProperty(df, kCFDateFormatterEraSymbols); 703 if (cferas != NULL) { 704 int eraCount = CFArrayGetCount(cferas); 705 706 if (eras == NULL) { 707 ret = (*env)->NewObjectArray(env, (jsize)eraCount, 708 (*env)->FindClass(env, "java/lang/String"), NULL); 709 } 710 CFTypeRef cal = CFLocaleGetValue(cflocale, kCFLocaleCalendarIdentifier); 711 int sindex = cal == kCFJapaneseCalendar ? JAPANESE_MEIJI_INDEX : 0; 712 int dindex = cal == kCFJapaneseCalendar ? 1 : 0; // 0 is "BeforeMeiji" in JCal 713 copyArrayElements(env, cferas, ret, sindex, dindex, eraCount - sindex); 714 CFRelease(cferas); 715 } 716 CFRelease(df); 717 } 718 CFRelease(cflocale); 719 } 720 721 return ret; 722 } 723 724 jobjectArray getWeekdaysImpl(JNIEnv *env, jclass cls, jstring jlangtag, jint style, jobjectArray wdays) { 725 jobjectArray ret = wdays; 726 CFLocaleRef cflocale = CFLocaleCopyCurrent(); 727 if (cflocale != NULL) { 728 CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault, 729 cflocale, 730 convertDateFormatterStyle(style), 731 convertDateFormatterStyle(style)); 732 if (df != NULL) { 733 CFArrayRef cfwdays = CFDateFormatterCopyProperty(df, kCFDateFormatterWeekdaySymbols); 734 if (cfwdays != NULL) { 735 int dayCount = CFArrayGetCount(cfwdays); 736 737 if (wdays == NULL) { 738 ret = (*env)->NewObjectArray(env, dayCount + 1, 739 (*env)->FindClass(env, "java/lang/String"), NULL); 740 } 741 copyArrayElements(env, cfwdays, ret, 0, 1, dayCount); 742 CFRelease(cfwdays); 743 } 744 CFRelease(df); 745 } 746 CFRelease(cflocale); 747 } 748 749 return ret; 750 } 751 752 jobjectArray getAmPmImpl(JNIEnv *env, jclass cls, jstring jlangtag, jint style, jobjectArray ampms) { 753 CFLocaleRef cflocale = CFLocaleCopyCurrent(); 754 jstring tmp_string; 755 if (cflocale != NULL) { 756 CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault, 757 cflocale, 758 convertDateFormatterStyle(style), 759 convertDateFormatterStyle(style)); 760 if (df != NULL) { 761 char buf[BUFLEN]; 762 if (ampms == NULL) { 763 ampms = (*env)->NewObjectArray(env, 2, 764 (*env)->FindClass(env, "java/lang/String"), NULL); 765 } 766 CFStringRef amStr = CFDateFormatterCopyProperty(df, kCFDateFormatterAMSymbol); 767 if (amStr != NULL) { 768 CFStringGetCString(amStr, buf, BUFLEN, kCFStringEncodingUTF8); 769 CFRelease(amStr); 770 tmp_string = (*env)->NewStringUTF(env, buf); 771 if (tmp_string != NULL) { 772 (*env)->SetObjectArrayElement(env, ampms, 0, tmp_string); 773 } 774 } 775 if (!(*env)->ExceptionCheck(env)){ 776 CFStringRef pmStr = CFDateFormatterCopyProperty(df, kCFDateFormatterPMSymbol); 777 if (pmStr != NULL) { 778 CFStringGetCString(pmStr, buf, BUFLEN, kCFStringEncodingUTF8); 779 CFRelease(pmStr); 780 tmp_string = (*env)->NewStringUTF(env, buf); 781 if (tmp_string != NULL) { 782 (*env)->SetObjectArrayElement(env, ampms, 1, tmp_string); 783 } 784 } 785 } 786 CFRelease(df); 787 } 788 CFRelease(cflocale); 789 } 790 791 return ampms; 792 }