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