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