1 /*
   2  * Copyright (c) 2012, 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 <CoreFoundation/CoreFoundation.h>
  28 #include <stdio.h>
  29 
  30 #define BUFLEN 256
  31 
  32 static CFDateFormatterStyle convertDateFormatterStyle(jint javaStyle);
  33 static CFNumberFormatterStyle convertNumberFormatterStyle(jint javaStyle);
  34 static void copyArrayElements(JNIEnv *env, CFArrayRef cfarray, jobjectArray jarray, CFIndex sindex, int dindex, int count);
  35 static jstring getNumberSymbolString(JNIEnv *env, jstring jlangtag, jstring jdefault, CFStringRef type);
  36 static jchar getNumberSymbolChar(JNIEnv *env, jstring jlangtag, jchar jdefault, CFStringRef type);
  37 
  38 // from java_props_macosx.c
  39 extern char * getMacOSXLocale(int cat);
  40 extern char * getPosixLocale(int cat);
  41 
  42 /*
  43  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
  44  * Method:    getDefaultLocale
  45  * Signature: (I)Ljava/lang/String;
  46  */
  47 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDefaultLocale
  48   (JNIEnv *env, jclass cls, jint cat) {
  49     char * localeString = NULL;
  50     int posixCat;
  51     jstring ret = NULL;
  52 
  53     switch (cat) {
  54         case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CAT_DISPLAY:
  55             posixCat = LC_MESSAGES;
  56             break;
  57         case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CAT_FORMAT:
  58         default:
  59             posixCat = LC_CTYPE;
  60             break;
  61     }
  62 
  63     localeString = getMacOSXLocale(posixCat);
  64     if (localeString == NULL) {
  65         localeString = getPosixLocale(posixCat);
  66     }
  67     ret = (*env)->NewStringUTF(env, localeString);
  68     free(localeString);
  69 
  70     return ret;
  71 }
  72 
  73 /*
  74  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
  75  * Method:    getDateTimePatternNative
  76  * Signature: (IILjava/lang/String;)Ljava/lang/String;
  77  */
  78 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDateTimePatternNative
  79   (JNIEnv *env, jclass cls, jint dateStyle, jint timeStyle, jstring jlangtag) {
  80     jstring ret = NULL;
  81     CFLocaleRef cflocale = CFLocaleCopyCurrent();
  82 
  83     if (cflocale != NULL) {
  84         CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault,
  85                                                   cflocale,
  86                                                   convertDateFormatterStyle(dateStyle),
  87                                                   convertDateFormatterStyle(timeStyle));
  88         if (df != NULL) {
  89             char buf[BUFLEN];
  90             CFStringRef formatStr = CFDateFormatterGetFormat(df);
  91             CFStringGetCString(formatStr, buf, BUFLEN, kCFStringEncodingUTF8);
  92             ret = (*env)->NewStringUTF(env, buf);
  93             CFRelease(df);
  94         }
  95         CFRelease(cflocale);
  96     }
  97 
  98     return ret;
  99 }
 100 
 101 /*
 102  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 103  * Method:    getCalendarID
 104  * Signature: (Ljava/lang/String;)Ljava/lang/String;
 105  */
 106 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCalendarID
 107   (JNIEnv *env, jclass cls, jstring jlangtag) {
 108     jstring ret = NULL;
 109     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 110 
 111     if (cflocale != NULL) {
 112         char buf[BUFLEN];
 113         CFTypeRef calid = CFLocaleGetValue(cflocale, kCFLocaleCalendarIdentifier);
 114         CFStringGetCString((CFStringRef)calid, buf, BUFLEN, kCFStringEncodingUTF8);
 115         ret = (*env)->NewStringUTF(env, buf);
 116         CFRelease(cflocale);
 117     }
 118 
 119     return ret;
 120 }
 121 
 122 /*
 123  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 124  * Method:    getAmPmStrings
 125  * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String;
 126  */
 127 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getAmPmStrings
 128   (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray ampms) {
 129     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 130     if (cflocale != NULL) {
 131         CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault,
 132                                                   cflocale,
 133                                                   kCFDateFormatterFullStyle,
 134                                                   kCFDateFormatterFullStyle);
 135         if (df != NULL) {
 136             char buf[BUFLEN];
 137             CFStringRef amStr = CFDateFormatterCopyProperty(df, kCFDateFormatterAMSymbol);
 138             if (amStr != NULL) {
 139                 CFStringGetCString(amStr, buf, BUFLEN, kCFStringEncodingUTF8);
 140                 CFRelease(amStr);
 141                 (*env)->SetObjectArrayElement(env, ampms, 0, (*env)->NewStringUTF(env, buf));
 142             }
 143             CFStringRef pmStr = CFDateFormatterCopyProperty(df, kCFDateFormatterPMSymbol);
 144             if (pmStr != NULL) {
 145                 CFStringGetCString(pmStr, buf, BUFLEN, kCFStringEncodingUTF8);
 146                 CFRelease(pmStr);
 147                 (*env)->SetObjectArrayElement(env, ampms, 1, (*env)->NewStringUTF(env, buf));
 148             }
 149             CFRelease(df);
 150         }
 151         CFRelease(cflocale);
 152     }
 153 
 154     return ampms;
 155 }
 156 
 157 /*
 158  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 159  * Method:    getEras
 160  * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String;
 161  */
 162 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getEras
 163   (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray eras) {
 164     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 165     if (cflocale != NULL) {
 166         CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault,
 167                                                   cflocale,
 168                                                   kCFDateFormatterFullStyle,
 169                                                   kCFDateFormatterFullStyle);
 170         if (df != NULL) {
 171             CFArrayRef cferas = CFDateFormatterCopyProperty(df, kCFDateFormatterEraSymbols);
 172             if (cferas != NULL) {
 173                 copyArrayElements(env, cferas, eras, 0, 0, CFArrayGetCount(cferas));
 174                 CFRelease(cferas);
 175             }
 176             CFRelease(df);
 177         }
 178         CFRelease(cflocale);
 179     }
 180 
 181     return eras;
 182 }
 183 
 184 /*
 185  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 186  * Method:    getMonths
 187  * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String;
 188  */
 189 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMonths
 190   (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray months) {
 191     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 192     if (cflocale != NULL) {
 193         CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault,
 194                                                   cflocale,
 195                                                   kCFDateFormatterFullStyle,
 196                                                   kCFDateFormatterFullStyle);
 197         if (df != NULL) {
 198             CFArrayRef cfmonths = CFDateFormatterCopyProperty(df, kCFDateFormatterMonthSymbols);
 199             if (cfmonths != NULL) {
 200                 copyArrayElements(env, cfmonths, months, 0, 0, CFArrayGetCount(cfmonths));
 201                 CFRelease(cfmonths);
 202             }
 203             CFRelease(df);
 204         }
 205         CFRelease(cflocale);
 206     }
 207 
 208     return months;
 209 }
 210 
 211 /*
 212  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 213  * Method:    getShortMonths
 214  * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String;
 215  */
 216 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getShortMonths
 217   (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray smonths) {
 218     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 219     if (cflocale != NULL) {
 220         CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault,
 221                                                   cflocale,
 222                                                   kCFDateFormatterFullStyle,
 223                                                   kCFDateFormatterFullStyle);
 224         if (df != NULL) {
 225             CFArrayRef cfsmonths = CFDateFormatterCopyProperty(df, kCFDateFormatterShortMonthSymbols);
 226             if (cfsmonths != NULL) {
 227                 copyArrayElements(env, cfsmonths, smonths, 0, 0, CFArrayGetCount(cfsmonths));
 228                 CFRelease(cfsmonths);
 229             }
 230             CFRelease(df);
 231         }
 232         CFRelease(cflocale);
 233     }
 234 
 235     return smonths;
 236 }
 237 
 238 /*
 239  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 240  * Method:    getWeekdays
 241  * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String;
 242  */
 243 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getWeekdays
 244   (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray wdays) {
 245     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 246     if (cflocale != NULL) {
 247         CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault,
 248                                                   cflocale,
 249                                                   kCFDateFormatterFullStyle,
 250                                                   kCFDateFormatterFullStyle);
 251         if (df != NULL) {
 252             CFArrayRef cfwdays = CFDateFormatterCopyProperty(df, kCFDateFormatterWeekdaySymbols);
 253             if (cfwdays != NULL) {
 254                 copyArrayElements(env, cfwdays, wdays, 0, 1, CFArrayGetCount(cfwdays));
 255                 CFRelease(cfwdays);
 256             }
 257             CFRelease(df);
 258         }
 259         CFRelease(cflocale);
 260     }
 261 
 262     return wdays;
 263 }
 264 
 265 /*
 266  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 267  * Method:    getShortWeekdays
 268  * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String;
 269  */
 270 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getShortWeekdays
 271   (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray swdays) {
 272     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 273     if (cflocale != NULL) {
 274         CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault,
 275                                                   cflocale,
 276                                                   kCFDateFormatterFullStyle,
 277                                                   kCFDateFormatterFullStyle);
 278         if (df != NULL) {
 279             CFArrayRef cfswdays = CFDateFormatterCopyProperty(df, kCFDateFormatterShortWeekdaySymbols);
 280             if (cfswdays != NULL) {
 281                 copyArrayElements(env, cfswdays, swdays, 0, 1, CFArrayGetCount(cfswdays));
 282                 CFRelease(cfswdays);
 283             }
 284             CFRelease(df);
 285         }
 286         CFRelease(cflocale);
 287     }
 288 
 289     return swdays;
 290 }
 291 
 292 /*
 293  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 294  * Method:    getNumberPatternNative
 295  * Signature: (ILjava/lang/String;)Ljava/lang/String;
 296  */
 297 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getNumberPatternNative
 298   (JNIEnv *env, jclass cls, jint numberStyle, jstring jlangtag) {
 299     jstring ret = NULL;
 300     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 301     if (cflocale != NULL) {
 302         CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorDefault,
 303                                                   cflocale,
 304                                                   convertNumberFormatterStyle(numberStyle));
 305         if (nf != NULL) {
 306             char buf[BUFLEN];
 307             CFStringRef formatStr = CFNumberFormatterGetFormat(nf);
 308             CFStringGetCString(formatStr, buf, BUFLEN, kCFStringEncodingUTF8);
 309             ret = (*env)->NewStringUTF(env, buf);
 310             CFRelease(nf);
 311         }
 312         CFRelease(cflocale);
 313     }
 314 
 315     return ret;
 316 }
 317 
 318 /*
 319  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 320  * Method:    getCurrencySymbol
 321  * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 322  */
 323 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCurrencySymbol
 324   (JNIEnv *env, jclass cls, jstring jlangtag, jstring currencySymbol) {
 325     return getNumberSymbolString(env, jlangtag, currencySymbol, kCFNumberFormatterCurrencySymbol);
 326 }
 327 
 328 /*
 329  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 330  * Method:    getDecimalSeparator
 331  * Signature: (Ljava/lang/String;C)C
 332  */
 333 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDecimalSeparator
 334   (JNIEnv *env, jclass cls, jstring jlangtag, jchar decimalSeparator) {
 335     return getNumberSymbolChar(env, jlangtag, decimalSeparator, kCFNumberFormatterDecimalSeparator);
 336 }
 337 
 338 /*
 339  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 340  * Method:    getGroupingSeparator
 341  * Signature: (Ljava/lang/String;C)C
 342  */
 343 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getGroupingSeparator
 344   (JNIEnv *env, jclass cls, jstring jlangtag, jchar groupingSeparator) {
 345     return getNumberSymbolChar(env, jlangtag, groupingSeparator, kCFNumberFormatterGroupingSeparator);
 346 }
 347 
 348 /*
 349  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 350  * Method:    getInfinity
 351  * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 352  */
 353 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getInfinity
 354   (JNIEnv *env, jclass cls, jstring jlangtag, jstring infinity) {
 355     return getNumberSymbolString(env, jlangtag, infinity, kCFNumberFormatterInfinitySymbol);
 356 }
 357 
 358 /*
 359  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 360  * Method:    getInternationalCurrencySymbol
 361  * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 362  */
 363 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getInternationalCurrencySymbol
 364   (JNIEnv *env, jclass cls, jstring jlangtag, jstring internationalCurrencySymbol) {
 365     return getNumberSymbolString(env, jlangtag, internationalCurrencySymbol, kCFNumberFormatterInternationalCurrencySymbol);
 366 }
 367 
 368 /*
 369  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 370  * Method:    getMinusSign
 371  * Signature: (Ljava/lang/String;C)C
 372  */
 373 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMinusSign
 374   (JNIEnv *env, jclass cls, jstring jlangtag, jchar minusSign) {
 375     return getNumberSymbolChar(env, jlangtag, minusSign, kCFNumberFormatterMinusSign);
 376 }
 377 
 378 /*
 379  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 380  * Method:    getMonetaryDecimalSeparator
 381  * Signature: (Ljava/lang/String;C)C
 382  */
 383 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMonetaryDecimalSeparator
 384   (JNIEnv *env, jclass cls, jstring jlangtag, jchar monetaryDecimalSeparator) {
 385     return getNumberSymbolChar(env, jlangtag, monetaryDecimalSeparator, kCFNumberFormatterCurrencyDecimalSeparator);
 386 }
 387 
 388 /*
 389  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 390  * Method:    getNaN
 391  * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 392  */
 393 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getNaN
 394   (JNIEnv *env, jclass cls, jstring jlangtag, jstring nan) {
 395     return getNumberSymbolString(env, jlangtag, nan, kCFNumberFormatterNaNSymbol);
 396 }
 397 
 398 /*
 399  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 400  * Method:    getPercent
 401  * Signature: (Ljava/lang/String;C)C
 402  */
 403 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPercent
 404   (JNIEnv *env, jclass cls, jstring jlangtag, jchar percent) {
 405     return getNumberSymbolChar(env, jlangtag, percent, kCFNumberFormatterPercentSymbol);
 406 }
 407 
 408 /*
 409  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 410  * Method:    getPerMill
 411  * Signature: (Ljava/lang/String;C)C
 412  */
 413 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPerMill
 414   (JNIEnv *env, jclass cls, jstring jlangtag, jchar perMill) {
 415     return getNumberSymbolChar(env, jlangtag, perMill, kCFNumberFormatterPerMillSymbol);
 416 }
 417 
 418 /*
 419  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 420  * Method:    getZeroDigit
 421  * Signature: (Ljava/lang/String;C)C
 422  */
 423 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getZeroDigit
 424   (JNIEnv *env, jclass cls, jstring jlangtag, jchar zeroDigit) {
 425     // The following code *should* work, but not for some reason :o
 426     //
 427     //return getNumberSymbolChar(env, jlangtag, zeroDigit, kCFNumberFormatterZeroSymbol);
 428     //
 429     // so here is a workaround.
 430     jchar ret = zeroDigit;
 431     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 432 
 433     if (cflocale != NULL) {
 434         CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorDefault,
 435                                                   cflocale,
 436                                                   kCFNumberFormatterNoStyle);
 437         if (nf != NULL) {
 438             int zero = 0;
 439             CFStringRef str = CFNumberFormatterCreateStringWithValue(kCFAllocatorDefault,
 440                               nf, kCFNumberIntType, &zero);
 441             if (str != NULL) {
 442                 if (CFStringGetLength(str) > 0) {
 443                     ret = CFStringGetCharacterAtIndex(str, 0);
 444                 }
 445                 CFRelease(str);
 446             }
 447 
 448             CFRelease(nf);
 449         }
 450 
 451         CFRelease(cflocale);
 452     }
 453 
 454     return ret;
 455 }
 456 
 457 /*
 458  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 459  * Method:    getExponentSeparator
 460  * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 461  */
 462 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getExponentSeparator
 463   (JNIEnv *env, jclass cls, jstring jlangtag, jstring exponent) {
 464     return getNumberSymbolString(env, jlangtag, exponent, kCFNumberFormatterExponentSymbol);
 465 }
 466 
 467 /*
 468  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 469  * Method:    getCalendarInt
 470  * Signature: (Ljava/lang/String;I)I
 471  */
 472 JNIEXPORT jint JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCalendarInt
 473   (JNIEnv *env, jclass cls, jstring jlangtag, jint type) {
 474     jint ret = 0;
 475     CFCalendarRef cfcal = CFCalendarCopyCurrent();
 476 
 477     if (cfcal != NULL) {
 478         switch (type) {
 479             case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CD_FIRSTDAYOFWEEK:
 480                 ret = CFCalendarGetFirstWeekday(cfcal);
 481                 break;
 482             case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CD_MINIMALDAYSINFIRSTWEEK:
 483                 ret = CFCalendarGetMinimumDaysInFirstWeek(cfcal);
 484                 break;
 485             default:
 486                 ret = 0;
 487         }
 488 
 489         CFRelease(cfcal);
 490     }
 491 
 492     return ret;
 493 }
 494 
 495 /*
 496  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 497  * Method:    getDisplayString
 498  * Signature: (Ljava/lang/String;ILjava/lang/String;)Ljava/lang/String;
 499  */
 500 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDisplayString
 501   (JNIEnv *env, jclass cls, jstring jlangtag, jint type, jstring value) {
 502     jstring ret = NULL;
 503 
 504     const char *clangtag = (*env)->GetStringUTFChars(env, jlangtag, 0);
 505     if (clangtag != NULL) {
 506         const char *cvalue = (*env)->GetStringUTFChars(env, value, 0);
 507         if (cvalue != NULL) {
 508             CFStringRef cflangtag =
 509                 CFStringCreateWithCString(kCFAllocatorDefault, clangtag, kCFStringEncodingUTF8);
 510             if (cflangtag != NULL) {
 511                 CFLocaleRef cflocale = CFLocaleCreate(kCFAllocatorDefault, cflangtag);
 512                 if (cflocale != NULL) {
 513                     CFStringRef cfvalue =
 514                         CFStringCreateWithCString(kCFAllocatorDefault, cvalue, kCFStringEncodingUTF8);
 515                     if (cfvalue != NULL) {
 516                         CFStringRef str = NULL;
 517                         switch (type) {
 518                             case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_LANGUAGE:
 519                                 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleLanguageCode, cfvalue);
 520                                 break;
 521                             case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_SCRIPT:
 522                                 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleScriptCode, cfvalue);
 523                                 break;
 524                             case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_REGION:
 525                                 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleCountryCode, cfvalue);
 526                                 break;
 527                             case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_VARIANT:
 528                                 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleVariantCode, cfvalue);
 529                                 break;
 530                             case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_CURRENCY_CODE:
 531                                 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleCurrencyCode, cfvalue);
 532                                 break;
 533                             case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_CURRENCY_SYMBOL:
 534                                 str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleCurrencySymbol, cfvalue);
 535                                 break;
 536                         }
 537                         if (str != NULL) {
 538                             char buf[BUFLEN];
 539                             CFStringGetCString(str, buf, BUFLEN, kCFStringEncodingUTF8);
 540                             CFRelease(str);
 541                             ret = (*env)->NewStringUTF(env, buf);
 542                         }
 543                         CFRelease(cfvalue);
 544                     }
 545                     CFRelease(cflocale);
 546                 }
 547                 CFRelease(cflangtag);
 548             }
 549             (*env)->ReleaseStringUTFChars(env, value, cvalue);
 550         }
 551         (*env)->ReleaseStringUTFChars(env, jlangtag, clangtag);
 552     }
 553 
 554     return ret;
 555 }
 556 
 557 /*
 558  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
 559  * Method:    getTimeZoneDisplayString
 560  * Signature: (Ljava/lang/String;ILjava/lang/String;)Ljava/lang/String;
 561  */
 562 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getTimeZoneDisplayString
 563   (JNIEnv *env, jclass cls, jstring jlangtag, jint type, jstring tzid) {
 564     jstring ret = NULL;
 565 
 566     const char *clangtag = (*env)->GetStringUTFChars(env, jlangtag, 0);
 567     if (clangtag != NULL) {
 568         const char *ctzid = (*env)->GetStringUTFChars(env, tzid, 0);
 569         if (ctzid != NULL) {
 570             CFStringRef cflangtag =
 571                 CFStringCreateWithCString(kCFAllocatorDefault, clangtag, kCFStringEncodingUTF8);
 572             if (cflangtag != NULL) {
 573                 CFLocaleRef cflocale = CFLocaleCreate(kCFAllocatorDefault, cflangtag);
 574                 if (cflocale != NULL) {
 575                     CFStringRef cftzid =
 576                         CFStringCreateWithCString(kCFAllocatorDefault, ctzid, kCFStringEncodingUTF8);
 577                     if (cftzid != NULL) {
 578                         CFTimeZoneRef cftz = CFTimeZoneCreateWithName(kCFAllocatorDefault, cftzid, false);
 579                         if (cftz != NULL) {
 580                             CFStringRef str = NULL;
 581                             switch (type) {
 582                                 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_TZ_SHORT_STANDARD:
 583                                     str = CFTimeZoneCopyLocalizedName(cftz, kCFTimeZoneNameStyleShortStandard, cflocale);
 584                                     break;
 585                                 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_TZ_SHORT_DST:
 586                                     str = CFTimeZoneCopyLocalizedName(cftz, kCFTimeZoneNameStyleShortDaylightSaving, cflocale);
 587                                     break;
 588                                 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_TZ_LONG_STANDARD:
 589                                     str = CFTimeZoneCopyLocalizedName(cftz, kCFTimeZoneNameStyleStandard, cflocale);
 590                                     break;
 591                                 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_TZ_LONG_DST:
 592                                     str = CFTimeZoneCopyLocalizedName(cftz, kCFTimeZoneNameStyleDaylightSaving, cflocale);
 593                                     break;
 594                             }
 595                             if (str != NULL) {
 596                                 char buf[BUFLEN];
 597                                 CFStringGetCString(str, buf, BUFLEN, kCFStringEncodingUTF8);
 598                                 CFRelease(str);
 599                                 ret = (*env)->NewStringUTF(env, buf);
 600                             }
 601                             CFRelease(cftz);
 602                         }
 603                         CFRelease(cftzid);
 604                     }
 605                     CFRelease(cflocale);
 606                 }
 607                 CFRelease(cflangtag);
 608             }
 609             (*env)->ReleaseStringUTFChars(env, tzid, ctzid);
 610         }
 611         (*env)->ReleaseStringUTFChars(env, jlangtag, clangtag);
 612     }
 613 
 614     return ret;
 615 }
 616 
 617 static CFDateFormatterStyle convertDateFormatterStyle(jint javaStyle) {
 618     switch (javaStyle) {
 619         case 0: // FULL
 620             return kCFDateFormatterFullStyle;
 621         case 1: // LONG
 622             return kCFDateFormatterLongStyle;
 623         case 2: // MEDIUM
 624             return kCFDateFormatterMediumStyle;
 625         case 3: // LONG
 626             return kCFDateFormatterShortStyle;
 627         case -1: // No style
 628         default:
 629             return kCFDateFormatterNoStyle;
 630     }
 631 }
 632 
 633 static CFNumberFormatterStyle convertNumberFormatterStyle(jint javaStyle) {
 634     switch (javaStyle) {
 635         case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_CURRENCY:
 636             return kCFNumberFormatterCurrencyStyle;
 637         case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_INTEGER:
 638             return kCFNumberFormatterDecimalStyle;
 639         case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_NUMBER:
 640             return kCFNumberFormatterDecimalStyle;
 641         case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_PERCENT:
 642             return kCFNumberFormatterPercentStyle;
 643         default:
 644             return kCFNumberFormatterNoStyle;
 645     }
 646 }
 647 
 648 static void copyArrayElements(JNIEnv *env, CFArrayRef cfarray, jobjectArray jarray, CFIndex sindex, int dindex, int count) {
 649     char buf[BUFLEN];
 650 
 651     for (; count > 0; sindex++, dindex++, count--) {
 652         CFStringGetCString(CFArrayGetValueAtIndex(cfarray, sindex), buf, BUFLEN, kCFStringEncodingUTF8);
 653         (*env)->SetObjectArrayElement(env, jarray, dindex, (*env)->NewStringUTF(env, buf));
 654     }
 655 }
 656 
 657 static jstring getNumberSymbolString(JNIEnv *env, jstring jlangtag, jstring jdefault, CFStringRef type) {
 658     char buf[BUFLEN];
 659     jstring ret = jdefault;
 660     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 661 
 662     if (cflocale != NULL) {
 663         CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorDefault,
 664                                                   cflocale,
 665                                                   kCFNumberFormatterNoStyle);
 666         if (nf != NULL) {
 667             CFStringRef str = CFNumberFormatterCopyProperty(nf, type);
 668             if (str != NULL) {
 669                 CFStringGetCString(str, buf, BUFLEN, kCFStringEncodingUTF8);
 670                 CFRelease(str);
 671                 ret = (*env)->NewStringUTF(env, buf);
 672             }
 673 
 674             CFRelease(nf);
 675         }
 676 
 677         CFRelease(cflocale);
 678     }
 679 
 680     return ret;
 681 }
 682 
 683 static jchar getNumberSymbolChar(JNIEnv *env, jstring jlangtag, jchar jdefault, CFStringRef type) {
 684     jchar ret = jdefault;
 685     CFLocaleRef cflocale = CFLocaleCopyCurrent();
 686 
 687     if (cflocale != NULL) {
 688         CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorDefault,
 689                                                   cflocale,
 690                                                   kCFNumberFormatterNoStyle);
 691         if (nf != NULL) {
 692             CFStringRef str = CFNumberFormatterCopyProperty(nf, type);
 693             if (str != NULL) {
 694                 if (CFStringGetLength(str) > 0) {
 695                     ret = CFStringGetCharacterAtIndex(str, 0);
 696                 }
 697                 CFRelease(str);
 698             }
 699 
 700             CFRelease(nf);
 701         }
 702 
 703         CFRelease(cflocale);
 704     }
 705 
 706     return ret;
 707 }