| /* | |
| * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle in the LICENSE file that accompanied this code. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| #include "sun_util_locale_provider_HostLocaleProviderAdapterImpl.h" | |
| #include "jni_util.h" | |
| #include <CoreFoundation/CoreFoundation.h> | |
| #include <stdio.h> | |
| #define BUFLEN 256 | |
| // java.util.Calendar constants | |
| #define CALENDAR_FIELD_ERA 0 // Calendar.ERA | |
| #define CALENDAR_FIELD_DAY_OF_WEEK 7 // Calendar.DAY_OF_WEEK | |
| #define CALENDAR_FIELD_AM_PM 9 // Calendar.AM_PM | |
| #define JAPANESE_MEIJI_INDEX 232 | |
| static CFDateFormatterStyle convertDateFormatterStyle(jint javaStyle); | |
| static CFNumberFormatterStyle convertNumberFormatterStyle(jint javaStyle); | |
| static void copyArrayElements(JNIEnv *env, CFArrayRef cfarray, jobjectArray jarray, CFIndex sindex, int dindex, int count); | |
| static jstring getNumberSymbolString(JNIEnv *env, jstring jlangtag, jstring jdefault, CFStringRef type); | |
| static jchar getNumberSymbolChar(JNIEnv *env, jstring jlangtag, jchar jdefault, CFStringRef type); | |
| jobjectArray getErasImpl(JNIEnv *env, jstring jlangtag, jint style, jobjectArray eras); | |
| jobjectArray getWeekdaysImpl(JNIEnv *env, jclass cls, jstring jlangtag, jint style, jobjectArray wdays); | |
| jobjectArray getAmPmImpl(JNIEnv *env, jclass cls, jstring jlangtag, jint style, jobjectArray ampms); | |
| // from java_props_macosx.c | |
| extern char * getMacOSXLocale(int cat); | |
| extern char * getPosixLocale(int cat); | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getDefaultLocale | |
| * Signature: (I)Ljava/lang/String; | |
| */ | |
| JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDefaultLocale | |
| (JNIEnv *env, jclass cls, jint cat) { | |
| char * localeString = NULL; | |
| int posixCat; | |
| jstring ret = NULL; | |
| switch (cat) { | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CAT_DISPLAY: | |
| posixCat = LC_MESSAGES; | |
| break; | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CAT_FORMAT: | |
| default: | |
| posixCat = LC_CTYPE; | |
| break; | |
| } | |
| localeString = getMacOSXLocale(posixCat); | |
| if (localeString == NULL) { | |
| localeString = getPosixLocale(posixCat); | |
| if (localeString == NULL) { | |
| JNU_ThrowOutOfMemoryError(env, NULL); | |
| return NULL; | |
| } | |
| } | |
| ret = (*env)->NewStringUTF(env, localeString); | |
| free(localeString); | |
| return ret; | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getDateTimePatternNative | |
| * Signature: (IILjava/lang/String;)Ljava/lang/String; | |
| */ | |
| JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDateTimePatternNative | |
| (JNIEnv *env, jclass cls, jint dateStyle, jint timeStyle, jstring jlangtag) { | |
| jstring ret = NULL; | |
| CFLocaleRef cflocale = CFLocaleCopyCurrent(); | |
| if (cflocale != NULL) { | |
| CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault, | |
| cflocale, | |
| convertDateFormatterStyle(dateStyle), | |
| convertDateFormatterStyle(timeStyle)); | |
| if (df != NULL) { | |
| char buf[BUFLEN]; | |
| CFStringRef formatStr = CFDateFormatterGetFormat(df); | |
| CFStringGetCString(formatStr, buf, BUFLEN, kCFStringEncodingUTF8); | |
| ret = (*env)->NewStringUTF(env, buf); | |
| CFRelease(df); | |
| } | |
| CFRelease(cflocale); | |
| } | |
| return ret; | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getCalendarID | |
| * Signature: (Ljava/lang/String;)Ljava/lang/String; | |
| */ | |
| JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCalendarID | |
| (JNIEnv *env, jclass cls, jstring jlangtag) { | |
| jstring ret = NULL; | |
| CFLocaleRef cflocale = CFLocaleCopyCurrent(); | |
| if (cflocale != NULL) { | |
| char buf[BUFLEN]; | |
| CFTypeRef calid = CFLocaleGetValue(cflocale, kCFLocaleCalendarIdentifier); | |
| CFStringGetCString((CFStringRef)calid, buf, BUFLEN, kCFStringEncodingUTF8); | |
| ret = (*env)->NewStringUTF(env, buf); | |
| CFRelease(cflocale); | |
| } | |
| return ret; | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getAmPmStrings | |
| * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; | |
| */ | |
| JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getAmPmStrings | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray ampms) { | |
| return getAmPmImpl(env, cls, jlangtag, 0, ampms); | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getEras | |
| * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; | |
| */ | |
| JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getEras | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray eras) { | |
| return getErasImpl(env, jlangtag, 0, eras); | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getMonths | |
| * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; | |
| */ | |
| JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMonths | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray months) { | |
| CFLocaleRef cflocale = CFLocaleCopyCurrent(); | |
| if (cflocale != NULL) { | |
| CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault, | |
| cflocale, | |
| kCFDateFormatterFullStyle, | |
| kCFDateFormatterFullStyle); | |
| if (df != NULL) { | |
| CFArrayRef cfmonths = CFDateFormatterCopyProperty(df, kCFDateFormatterMonthSymbols); | |
| if (cfmonths != NULL) { | |
| copyArrayElements(env, cfmonths, months, 0, 0, CFArrayGetCount(cfmonths)); | |
| CFRelease(cfmonths); | |
| } | |
| CFRelease(df); | |
| } | |
| CFRelease(cflocale); | |
| } | |
| return months; | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getShortMonths | |
| * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; | |
| */ | |
| JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getShortMonths | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray smonths) { | |
| CFLocaleRef cflocale = CFLocaleCopyCurrent(); | |
| if (cflocale != NULL) { | |
| CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault, | |
| cflocale, | |
| kCFDateFormatterFullStyle, | |
| kCFDateFormatterFullStyle); | |
| if (df != NULL) { | |
| CFArrayRef cfsmonths = CFDateFormatterCopyProperty(df, kCFDateFormatterShortMonthSymbols); | |
| if (cfsmonths != NULL) { | |
| copyArrayElements(env, cfsmonths, smonths, 0, 0, CFArrayGetCount(cfsmonths)); | |
| CFRelease(cfsmonths); | |
| } | |
| CFRelease(df); | |
| } | |
| CFRelease(cflocale); | |
| } | |
| return smonths; | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getWeekdays | |
| * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; | |
| */ | |
| JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getWeekdays | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray wdays) { | |
| return getWeekdaysImpl(env, cls, jlangtag, 0, wdays); | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getShortWeekdays | |
| * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; | |
| */ | |
| JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getShortWeekdays | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray swdays) { | |
| CFLocaleRef cflocale = CFLocaleCopyCurrent(); | |
| if (cflocale != NULL) { | |
| CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault, | |
| cflocale, | |
| kCFDateFormatterFullStyle, | |
| kCFDateFormatterFullStyle); | |
| if (df != NULL) { | |
| CFArrayRef cfswdays = CFDateFormatterCopyProperty(df, kCFDateFormatterShortWeekdaySymbols); | |
| if (cfswdays != NULL) { | |
| copyArrayElements(env, cfswdays, swdays, 0, 1, CFArrayGetCount(cfswdays)); | |
| CFRelease(cfswdays); | |
| } | |
| CFRelease(df); | |
| } | |
| CFRelease(cflocale); | |
| } | |
| return swdays; | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getNumberPatternNative | |
| * Signature: (ILjava/lang/String;)Ljava/lang/String; | |
| */ | |
| JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getNumberPatternNative | |
| (JNIEnv *env, jclass cls, jint numberStyle, jstring jlangtag) { | |
| jstring ret = NULL; | |
| CFLocaleRef cflocale = CFLocaleCopyCurrent(); | |
| if (cflocale != NULL) { | |
| CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorDefault, | |
| cflocale, | |
| convertNumberFormatterStyle(numberStyle)); | |
| if (nf != NULL) { | |
| char buf[BUFLEN]; | |
| CFStringRef formatStr = CFNumberFormatterGetFormat(nf); | |
| CFStringGetCString(formatStr, buf, BUFLEN, kCFStringEncodingUTF8); | |
| ret = (*env)->NewStringUTF(env, buf); | |
| CFRelease(nf); | |
| } | |
| CFRelease(cflocale); | |
| } | |
| return ret; | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getCurrencySymbol | |
| * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; | |
| */ | |
| JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCurrencySymbol | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jstring currencySymbol) { | |
| return getNumberSymbolString(env, jlangtag, currencySymbol, kCFNumberFormatterCurrencySymbol); | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getDecimalSeparator | |
| * Signature: (Ljava/lang/String;C)C | |
| */ | |
| JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDecimalSeparator | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jchar decimalSeparator) { | |
| return getNumberSymbolChar(env, jlangtag, decimalSeparator, kCFNumberFormatterDecimalSeparator); | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getGroupingSeparator | |
| * Signature: (Ljava/lang/String;C)C | |
| */ | |
| JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getGroupingSeparator | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jchar groupingSeparator) { | |
| return getNumberSymbolChar(env, jlangtag, groupingSeparator, kCFNumberFormatterGroupingSeparator); | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getInfinity | |
| * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; | |
| */ | |
| JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getInfinity | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jstring infinity) { | |
| return getNumberSymbolString(env, jlangtag, infinity, kCFNumberFormatterInfinitySymbol); | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getInternationalCurrencySymbol | |
| * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; | |
| */ | |
| JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getInternationalCurrencySymbol | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jstring internationalCurrencySymbol) { | |
| return getNumberSymbolString(env, jlangtag, internationalCurrencySymbol, kCFNumberFormatterInternationalCurrencySymbol); | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getMinusSign | |
| * Signature: (Ljava/lang/String;C)C | |
| */ | |
| JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMinusSign | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jchar minusSign) { | |
| return getNumberSymbolChar(env, jlangtag, minusSign, kCFNumberFormatterMinusSign); | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getMonetaryDecimalSeparator | |
| * Signature: (Ljava/lang/String;C)C | |
| */ | |
| JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMonetaryDecimalSeparator | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jchar monetaryDecimalSeparator) { | |
| return getNumberSymbolChar(env, jlangtag, monetaryDecimalSeparator, kCFNumberFormatterCurrencyDecimalSeparator); | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getNaN | |
| * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; | |
| */ | |
| JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getNaN | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jstring nan) { | |
| return getNumberSymbolString(env, jlangtag, nan, kCFNumberFormatterNaNSymbol); | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getPercent | |
| * Signature: (Ljava/lang/String;C)C | |
| */ | |
| JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPercent | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jchar percent) { | |
| return getNumberSymbolChar(env, jlangtag, percent, kCFNumberFormatterPercentSymbol); | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getPerMill | |
| * Signature: (Ljava/lang/String;C)C | |
| */ | |
| JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPerMill | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jchar perMill) { | |
| return getNumberSymbolChar(env, jlangtag, perMill, kCFNumberFormatterPerMillSymbol); | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getZeroDigit | |
| * Signature: (Ljava/lang/String;C)C | |
| */ | |
| JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getZeroDigit | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jchar zeroDigit) { | |
| // The following code *should* work, but not for some reason :o | |
| // | |
| //return getNumberSymbolChar(env, jlangtag, zeroDigit, kCFNumberFormatterZeroSymbol); | |
| // | |
| // so here is a workaround. | |
| jchar ret = zeroDigit; | |
| CFLocaleRef cflocale = CFLocaleCopyCurrent(); | |
| if (cflocale != NULL) { | |
| CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorDefault, | |
| cflocale, | |
| kCFNumberFormatterNoStyle); | |
| if (nf != NULL) { | |
| int zero = 0; | |
| CFStringRef str = CFNumberFormatterCreateStringWithValue(kCFAllocatorDefault, | |
| nf, kCFNumberIntType, &zero); | |
| if (str != NULL) { | |
| if (CFStringGetLength(str) > 0) { | |
| ret = CFStringGetCharacterAtIndex(str, 0); | |
| } | |
| CFRelease(str); | |
| } | |
| CFRelease(nf); | |
| } | |
| CFRelease(cflocale); | |
| } | |
| return ret; | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getExponentSeparator | |
| * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; | |
| */ | |
| JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getExponentSeparator | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jstring exponent) { | |
| return getNumberSymbolString(env, jlangtag, exponent, kCFNumberFormatterExponentSymbol); | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getCalendarInt | |
| * Signature: (Ljava/lang/String;I)I | |
| */ | |
| JNIEXPORT jint JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCalendarInt | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jint type) { | |
| jint ret = 0; | |
| // Majority of MacOSX fixed locales return Gregorian cal identifier | |
| // Using CFCalendarCopyCurrent() provides a cal that is based off OS settings | |
| // which is more accurate than one created with a Gregorian identifier | |
| CFCalendarRef cfcal = CFCalendarCopyCurrent(); | |
| if (cfcal != NULL) { | |
| switch (type) { | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CD_FIRSTDAYOFWEEK: | |
| ret = CFCalendarGetFirstWeekday(cfcal); | |
| break; | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CD_MINIMALDAYSINFIRSTWEEK: | |
| ret = CFCalendarGetMinimumDaysInFirstWeek(cfcal); | |
| break; | |
| default: | |
| ret = 0; | |
| } | |
| CFRelease(cfcal); | |
| } | |
| return ret; | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getCalendarDisplayStrings | |
| * Signature: (Ljava/lang/String;III)[Ljava/lang/String; | |
| */ | |
| JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCalendarDisplayStrings | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jint field, jint style) { | |
| switch (field) { | |
| case CALENDAR_FIELD_ERA: | |
| return getErasImpl(env, jlangtag, style, NULL); | |
| case CALENDAR_FIELD_DAY_OF_WEEK: | |
| return getWeekdaysImpl(env, cls, jlangtag, style, NULL); | |
| case CALENDAR_FIELD_AM_PM: | |
| return getAmPmImpl(env, cls, jlangtag, style, NULL); | |
| default: | |
| // not supported | |
| return NULL; | |
| } | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getDisplayString | |
| * Signature: (Ljava/lang/String;ILjava/lang/String;)Ljava/lang/String; | |
| */ | |
| JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDisplayString | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jint type, jstring value) { | |
| jstring ret = NULL; | |
| const char *clangtag = (*env)->GetStringUTFChars(env, jlangtag, 0); | |
| if (clangtag != NULL) { | |
| const char *cvalue = (*env)->GetStringUTFChars(env, value, 0); | |
| if (cvalue != NULL) { | |
| CFStringRef cflangtag = | |
| CFStringCreateWithCString(kCFAllocatorDefault, clangtag, kCFStringEncodingUTF8); | |
| if (cflangtag != NULL) { | |
| CFLocaleRef cflocale = CFLocaleCreate(kCFAllocatorDefault, cflangtag); | |
| if (cflocale != NULL) { | |
| CFStringRef cfvalue = | |
| CFStringCreateWithCString(kCFAllocatorDefault, cvalue, kCFStringEncodingUTF8); | |
| if (cfvalue != NULL) { | |
| CFStringRef str = NULL; | |
| switch (type) { | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_LANGUAGE: | |
| str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleLanguageCode, cfvalue); | |
| break; | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_SCRIPT: | |
| str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleScriptCode, cfvalue); | |
| break; | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_REGION: | |
| str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleCountryCode, cfvalue); | |
| break; | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_VARIANT: | |
| str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleVariantCode, cfvalue); | |
| break; | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_CURRENCY_CODE: | |
| str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleCurrencyCode, cfvalue); | |
| break; | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_CURRENCY_SYMBOL: | |
| str = CFLocaleCopyDisplayNameForPropertyValue(cflocale, kCFLocaleCurrencySymbol, cfvalue); | |
| break; | |
| } | |
| if (str != NULL) { | |
| char buf[BUFLEN]; | |
| CFStringGetCString(str, buf, BUFLEN, kCFStringEncodingUTF8); | |
| CFRelease(str); | |
| ret = (*env)->NewStringUTF(env, buf); | |
| } | |
| CFRelease(cfvalue); | |
| } | |
| CFRelease(cflocale); | |
| } | |
| CFRelease(cflangtag); | |
| } | |
| (*env)->ReleaseStringUTFChars(env, value, cvalue); | |
| } | |
| (*env)->ReleaseStringUTFChars(env, jlangtag, clangtag); | |
| } | |
| return ret; | |
| } | |
| /* | |
| * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl | |
| * Method: getTimeZoneDisplayString | |
| * Signature: (Ljava/lang/String;ILjava/lang/String;)Ljava/lang/String; | |
| */ | |
| JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getTimeZoneDisplayString | |
| (JNIEnv *env, jclass cls, jstring jlangtag, jint type, jstring tzid) { | |
| jstring ret = NULL; | |
| const char *clangtag = (*env)->GetStringUTFChars(env, jlangtag, 0); | |
| if (clangtag != NULL) { | |
| const char *ctzid = (*env)->GetStringUTFChars(env, tzid, 0); | |
| if (ctzid != NULL) { | |
| CFStringRef cflangtag = | |
| CFStringCreateWithCString(kCFAllocatorDefault, clangtag, kCFStringEncodingUTF8); | |
| if (cflangtag != NULL) { | |
| CFLocaleRef cflocale = CFLocaleCreate(kCFAllocatorDefault, cflangtag); | |
| if (cflocale != NULL) { | |
| CFStringRef cftzid = | |
| CFStringCreateWithCString(kCFAllocatorDefault, ctzid, kCFStringEncodingUTF8); | |
| if (cftzid != NULL) { | |
| CFTimeZoneRef cftz = CFTimeZoneCreateWithName(kCFAllocatorDefault, cftzid, false); | |
| if (cftz != NULL) { | |
| CFStringRef str = NULL; | |
| switch (type) { | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_TZ_SHORT_STANDARD: | |
| str = CFTimeZoneCopyLocalizedName(cftz, kCFTimeZoneNameStyleShortStandard, cflocale); | |
| break; | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_TZ_SHORT_DST: | |
| str = CFTimeZoneCopyLocalizedName(cftz, kCFTimeZoneNameStyleShortDaylightSaving, cflocale); | |
| break; | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_TZ_LONG_STANDARD: | |
| str = CFTimeZoneCopyLocalizedName(cftz, kCFTimeZoneNameStyleStandard, cflocale); | |
| break; | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_TZ_LONG_DST: | |
| str = CFTimeZoneCopyLocalizedName(cftz, kCFTimeZoneNameStyleDaylightSaving, cflocale); | |
| break; | |
| } | |
| if (str != NULL) { | |
| char buf[BUFLEN]; | |
| CFStringGetCString(str, buf, BUFLEN, kCFStringEncodingUTF8); | |
| CFRelease(str); | |
| ret = (*env)->NewStringUTF(env, buf); | |
| } | |
| CFRelease(cftz); | |
| } | |
| CFRelease(cftzid); | |
| } | |
| CFRelease(cflocale); | |
| } | |
| CFRelease(cflangtag); | |
| } | |
| (*env)->ReleaseStringUTFChars(env, tzid, ctzid); | |
| } | |
| (*env)->ReleaseStringUTFChars(env, jlangtag, clangtag); | |
| } | |
| return ret; | |
| } | |
| static CFDateFormatterStyle convertDateFormatterStyle(jint javaStyle) { | |
| switch (javaStyle) { | |
| case 0: // FULL | |
| return kCFDateFormatterFullStyle; | |
| case 1: // LONG | |
| return kCFDateFormatterLongStyle; | |
| case 2: // MEDIUM | |
| return kCFDateFormatterMediumStyle; | |
| case 3: // LONG | |
| return kCFDateFormatterShortStyle; | |
| case -1: // No style | |
| default: | |
| return kCFDateFormatterNoStyle; | |
| } | |
| } | |
| static CFNumberFormatterStyle convertNumberFormatterStyle(jint javaStyle) { | |
| switch (javaStyle) { | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_CURRENCY: | |
| return kCFNumberFormatterCurrencyStyle; | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_INTEGER: | |
| return kCFNumberFormatterDecimalStyle; | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_NUMBER: | |
| return kCFNumberFormatterDecimalStyle; | |
| case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_PERCENT: | |
| return kCFNumberFormatterPercentStyle; | |
| default: | |
| return kCFNumberFormatterNoStyle; | |
| } | |
| } | |
| static void copyArrayElements(JNIEnv *env, CFArrayRef cfarray, jobjectArray jarray, CFIndex sindex, int dindex, int count) { | |
| char buf[BUFLEN]; | |
| jstring tmp_string; | |
| for (; count > 0; sindex++, dindex++, count--) { | |
| CFStringGetCString(CFArrayGetValueAtIndex(cfarray, sindex), buf, BUFLEN, kCFStringEncodingUTF8); | |
| tmp_string = (*env)->NewStringUTF(env, buf); | |
| if (tmp_string != NULL) { | |
| (*env)->SetObjectArrayElement(env, jarray, dindex, tmp_string); | |
| } else { | |
| break; | |
| } | |
| } | |
| } | |
| static jstring getNumberSymbolString(JNIEnv *env, jstring jlangtag, jstring jdefault, CFStringRef type) { | |
| char buf[BUFLEN]; | |
| jstring ret = jdefault; | |
| CFLocaleRef cflocale = CFLocaleCopyCurrent(); | |
| if (cflocale != NULL) { | |
| CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorDefault, | |
| cflocale, | |
| kCFNumberFormatterNoStyle); | |
| if (nf != NULL) { | |
| CFStringRef str = CFNumberFormatterCopyProperty(nf, type); | |
| if (str != NULL) { | |
| CFStringGetCString(str, buf, BUFLEN, kCFStringEncodingUTF8); | |
| CFRelease(str); | |
| ret = (*env)->NewStringUTF(env, buf); | |
| } | |
| CFRelease(nf); | |
| } | |
| CFRelease(cflocale); | |
| } | |
| return ret; | |
| } | |
| static jchar getNumberSymbolChar(JNIEnv *env, jstring jlangtag, jchar jdefault, CFStringRef type) { | |
| jchar ret = jdefault; | |
| CFLocaleRef cflocale = CFLocaleCopyCurrent(); | |
| if (cflocale != NULL) { | |
| CFNumberFormatterRef nf = CFNumberFormatterCreate(kCFAllocatorDefault, | |
| cflocale, | |
| kCFNumberFormatterNoStyle); | |
| if (nf != NULL) { | |
| CFStringRef str = CFNumberFormatterCopyProperty(nf, type); | |
| if (str != NULL) { | |
| if (CFStringGetLength(str) > 0) { | |
| ret = CFStringGetCharacterAtIndex(str, 0); | |
| } | |
| CFRelease(str); | |
| } | |
| CFRelease(nf); | |
| } | |
| CFRelease(cflocale); | |
| } | |
| return ret; | |
| } | |
| jobjectArray getErasImpl(JNIEnv *env, jstring jlangtag, jint style, jobjectArray eras) { | |
| jobjectArray ret = eras; | |
| CFLocaleRef cflocale = CFLocaleCopyCurrent(); | |
| if (cflocale != NULL) { | |
| CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault, | |
| cflocale, | |
| convertDateFormatterStyle(style), | |
| convertDateFormatterStyle(style)); | |
| if (df != NULL) { | |
| CFArrayRef cferas = CFDateFormatterCopyProperty(df, kCFDateFormatterEraSymbols); | |
| if (cferas != NULL) { | |
| int eraCount = CFArrayGetCount(cferas); | |
| if (eras == NULL) { | |
| ret = (*env)->NewObjectArray(env, (jsize)eraCount, | |
| (*env)->FindClass(env, "java/lang/String"), NULL); | |
| } | |
| CFTypeRef cal = CFLocaleGetValue(cflocale, kCFLocaleCalendarIdentifier); | |
| int sindex = cal == kCFJapaneseCalendar ? JAPANESE_MEIJI_INDEX : 0; | |
| int dindex = cal == kCFJapaneseCalendar ? 1 : 0; // 0 is "BeforeMeiji" in JCal | |
| copyArrayElements(env, cferas, ret, sindex, dindex, eraCount - sindex); | |
| CFRelease(cferas); | |
| } | |
| CFRelease(df); | |
| } | |
| CFRelease(cflocale); | |
| } | |
| return ret; | |
| } | |
| jobjectArray getWeekdaysImpl(JNIEnv *env, jclass cls, jstring jlangtag, jint style, jobjectArray wdays) { | |
| jobjectArray ret = wdays; | |
| CFLocaleRef cflocale = CFLocaleCopyCurrent(); | |
| if (cflocale != NULL) { | |
| CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault, | |
| cflocale, | |
| convertDateFormatterStyle(style), | |
| convertDateFormatterStyle(style)); | |
| if (df != NULL) { | |
| CFArrayRef cfwdays = CFDateFormatterCopyProperty(df, kCFDateFormatterWeekdaySymbols); | |
| if (cfwdays != NULL) { | |
| int dayCount = CFArrayGetCount(cfwdays); | |
| if (wdays == NULL) { | |
| ret = (*env)->NewObjectArray(env, dayCount + 1, | |
| (*env)->FindClass(env, "java/lang/String"), NULL); | |
| } | |
| copyArrayElements(env, cfwdays, ret, 0, 1, dayCount); | |
| CFRelease(cfwdays); | |
| } | |
| CFRelease(df); | |
| } | |
| CFRelease(cflocale); | |
| } | |
| return ret; | |
| } | |
| jobjectArray getAmPmImpl(JNIEnv *env, jclass cls, jstring jlangtag, jint style, jobjectArray ampms) { | |
| CFLocaleRef cflocale = CFLocaleCopyCurrent(); | |
| jstring tmp_string; | |
| if (cflocale != NULL) { | |
| CFDateFormatterRef df = CFDateFormatterCreate(kCFAllocatorDefault, | |
| cflocale, | |
| convertDateFormatterStyle(style), | |
| convertDateFormatterStyle(style)); | |
| if (df != NULL) { | |
| char buf[BUFLEN]; | |
| if (ampms == NULL) { | |
| ampms = (*env)->NewObjectArray(env, 2, | |
| (*env)->FindClass(env, "java/lang/String"), NULL); | |
| } | |
| CFStringRef amStr = CFDateFormatterCopyProperty(df, kCFDateFormatterAMSymbol); | |
| if (amStr != NULL) { | |
| CFStringGetCString(amStr, buf, BUFLEN, kCFStringEncodingUTF8); | |
| CFRelease(amStr); | |
| tmp_string = (*env)->NewStringUTF(env, buf); | |
| if (tmp_string != NULL) { | |
| (*env)->SetObjectArrayElement(env, ampms, 0, tmp_string); | |
| } | |
| } | |
| if (!(*env)->ExceptionCheck(env)){ | |
| CFStringRef pmStr = CFDateFormatterCopyProperty(df, kCFDateFormatterPMSymbol); | |
| if (pmStr != NULL) { | |
| CFStringGetCString(pmStr, buf, BUFLEN, kCFStringEncodingUTF8); | |
| CFRelease(pmStr); | |
| tmp_string = (*env)->NewStringUTF(env, buf); | |
| if (tmp_string != NULL) { | |
| (*env)->SetObjectArrayElement(env, ampms, 1, tmp_string); | |
| } | |
| } | |
| } | |
| CFRelease(df); | |
| } | |
| CFRelease(cflocale); | |
| } | |
| return ampms; | |
| } |