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 <windows.h> 28 #include <gdefs.h> 29 #include <stdlib.h> 30 31 #define BUFLEN 256 32 33 // global variables 34 typedef int (WINAPI *PGLIE)(const jchar *, LCTYPE, LPWSTR, int); 35 typedef int (WINAPI *PGCIE)(const jchar *, CALID, LPCWSTR, CALTYPE, LPWSTR, int, LPDWORD); 36 PGLIE pGetLocaleInfoEx; 37 PGCIE pGetCalendarInfoEx; 38 BOOL initialized = FALSE; 39 40 // prototypes 41 int getLocaleInfoWrapper(const jchar *langtag, LCTYPE type, LPWSTR data, int buflen); 42 int getCalendarInfoWrapper(const jchar *langtag, CALID id, LPCWSTR reserved, CALTYPE type, LPWSTR data, int buflen, LPDWORD val); 43 jint getCalendarID(const jchar *langtag); 44 void replaceCalendarArrayElems(JNIEnv *env, jstring jlangtag, jobjectArray jarray, 45 CALTYPE* pCalTypes, int offset, int length); 46 WCHAR * getNumberPattern(const jchar * langtag, const jint numberStyle); 47 void getNumberPart(const jchar * langtag, const jint numberStyle, WCHAR * number); 48 void getFixPart(const jchar * langtag, const jint numberStyle, BOOL positive, BOOL prefix, WCHAR * ret); 49 50 // from java_props_md.c 51 extern __declspec(dllexport) const char * getJavaIDFromLangID(LANGID langID); 52 53 CALTYPE monthsType[] = { 54 CAL_SMONTHNAME1, 55 CAL_SMONTHNAME2, 56 CAL_SMONTHNAME3, 57 CAL_SMONTHNAME4, 58 CAL_SMONTHNAME5, 59 CAL_SMONTHNAME6, 60 CAL_SMONTHNAME7, 61 CAL_SMONTHNAME8, 62 CAL_SMONTHNAME9, 63 CAL_SMONTHNAME10, 64 CAL_SMONTHNAME11, 65 CAL_SMONTHNAME12, 66 CAL_SMONTHNAME13, 67 }; 68 69 CALTYPE sMonthsType[] = { 70 CAL_SABBREVMONTHNAME1, 71 CAL_SABBREVMONTHNAME2, 72 CAL_SABBREVMONTHNAME3, 73 CAL_SABBREVMONTHNAME4, 74 CAL_SABBREVMONTHNAME5, 75 CAL_SABBREVMONTHNAME6, 76 CAL_SABBREVMONTHNAME7, 77 CAL_SABBREVMONTHNAME8, 78 CAL_SABBREVMONTHNAME9, 79 CAL_SABBREVMONTHNAME10, 80 CAL_SABBREVMONTHNAME11, 81 CAL_SABBREVMONTHNAME12, 82 CAL_SABBREVMONTHNAME13, 83 }; 84 85 CALTYPE wDaysType[] = { 86 CAL_SDAYNAME7, 87 CAL_SDAYNAME1, 88 CAL_SDAYNAME2, 89 CAL_SDAYNAME3, 90 CAL_SDAYNAME4, 91 CAL_SDAYNAME5, 92 CAL_SDAYNAME6, 93 }; 94 95 CALTYPE sWDaysType[] = { 96 CAL_SABBREVDAYNAME7, 97 CAL_SABBREVDAYNAME1, 98 CAL_SABBREVDAYNAME2, 99 CAL_SABBREVDAYNAME3, 100 CAL_SABBREVDAYNAME4, 101 CAL_SABBREVDAYNAME5, 102 CAL_SABBREVDAYNAME6, 103 }; 104 105 WCHAR * fixes[2][2][3][16] = 106 { 107 { //prefix 108 { //positive 109 { // number 110 L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", 111 }, 112 { // currency 113 L"\xA4", L"", L"\xA4 ", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", 114 }, 115 { // percent 116 L"", L"", L"%", L"% ", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", 117 } 118 }, 119 { // negative 120 { // number 121 L"(", L"-", L"- ", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", 122 }, 123 { //currency 124 L"(\xA4", L"-\xA4", L"\xA4-", L"\xA4", L"(", L"-", L"", L"", L"-", L"-\xA4 ", L"", L"\xA4 ", L"\xA4 -", L"", L"(\xA4 ", L"(" 125 }, 126 { // percent 127 L"-", L"-", L"-%", L"%-", L"%", L"", L"", L"-% ", L"", L"% ", L"% -", L"", L"", L"", L"", L"", 128 } 129 } 130 }, 131 { // suffix 132 { //positive 133 { // number 134 L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"" 135 }, 136 { // currency 137 L"", L"\xA4 ", L"", L" \xA4", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", 138 }, 139 { // percent 140 L" %", L"%", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", 141 } 142 }, 143 { // negative 144 { // number 145 L")", L"", L" ", L"-", L" -", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", L"", 146 }, 147 { //currency 148 L")", L"", L"", L"-", L"\xA4)", L"\xA4", L"-\xA4", L"\xA4-", L" \xA4", L"", L" \xA4-", L"-", L"", L"- \xA4", L")", L" \xA4)" 149 }, 150 { // percent 151 L" %", L"%", L"", L"", L"-", L"-%", L"%-", L"", L" %-", L"-", L"", L"- %", L"", L"", L"", L"", 152 } 153 } 154 } 155 }; 156 157 /* 158 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 159 * Method: initialize 160 * Signature: ()Z 161 */ 162 JNIEXPORT jboolean JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_initialize 163 (JNIEnv *env, jclass cls) { 164 if (!initialized) { 165 pGetLocaleInfoEx = (PGLIE)GetProcAddress( 166 GetModuleHandle("kernel32.dll"), 167 "GetLocaleInfoEx"); 168 pGetCalendarInfoEx = (PGCIE)GetProcAddress( 169 GetModuleHandle("kernel32.dll"), 170 "GetCalendarInfoEx"); 171 initialized =TRUE; 172 } 173 174 return pGetLocaleInfoEx != NULL && 175 pGetCalendarInfoEx != NULL; 176 } 177 178 /* 179 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 180 * Method: getDefaultLocale 181 * Signature: (I)Ljava/lang/String; 182 */ 183 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDefaultLocale 184 (JNIEnv *env, jclass cls, jint cat) { 185 char * localeString = NULL; 186 LANGID langid; 187 jstring ret; 188 189 switch (cat) { 190 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CAT_DISPLAY: 191 langid = LANGIDFROMLCID(GetUserDefaultUILanguage()); 192 break; 193 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CAT_FORMAT: 194 default: 195 langid = LANGIDFROMLCID(GetUserDefaultLCID()); 196 break; 197 } 198 199 localeString = (char *)getJavaIDFromLangID(langid); 200 ret = (*env)->NewStringUTF(env, localeString); 201 free(localeString); 202 return ret; 203 } 204 205 /* 206 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 207 * Method: getDateTimePattern 208 * Signature: (IILjava/lang/String;)Ljava/lang/String; 209 */ 210 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDateTimePattern 211 (JNIEnv *env, jclass cls, jint dateStyle, jint timeStyle, jstring jlangtag) { 212 WCHAR pattern[BUFLEN]; 213 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 214 215 pattern[0] = L'\0'; 216 217 if (dateStyle == 0 || dateStyle == 1) { 218 getLocaleInfoWrapper(langtag, LOCALE_SLONGDATE, pattern, BUFLEN); 219 } else if (dateStyle == 2 || dateStyle == 3) { 220 getLocaleInfoWrapper(langtag, LOCALE_SSHORTDATE, pattern, BUFLEN); 221 } 222 223 if (timeStyle == 0 || timeStyle == 1) { 224 getLocaleInfoWrapper(langtag, LOCALE_STIMEFORMAT, pattern, BUFLEN); 225 } else if (timeStyle == 2 || timeStyle == 3) { 226 getLocaleInfoWrapper(langtag, LOCALE_SSHORTTIME, pattern, BUFLEN); 227 } 228 229 (*env)->ReleaseStringChars(env, jlangtag, langtag); 230 231 return (*env)->NewString(env, pattern, wcslen(pattern)); 232 } 233 234 /* 235 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 236 * Method: getCalendarID 237 * Signature: (Ljava/lang/String;)I 238 */ 239 JNIEXPORT jint JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCalendarID 240 (JNIEnv *env, jclass cls, jstring jlangtag) { 241 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 242 jint ret = getCalendarID(langtag); 243 (*env)->ReleaseStringChars(env, jlangtag, langtag); 244 return ret; 245 } 246 247 /* 248 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 249 * Method: getAmPmStrings 250 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 251 */ 252 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getAmPmStrings 253 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray ampms) { 254 WCHAR buf[BUFLEN]; 255 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 256 257 // AM 258 int got = getLocaleInfoWrapper(langtag, LOCALE_S1159, buf, BUFLEN); 259 if (got) { 260 (*env)->SetObjectArrayElement(env, ampms, 0, (*env)->NewString(env, buf, wcslen(buf))); 261 } 262 263 // PM 264 got = getLocaleInfoWrapper(langtag, LOCALE_S2359, buf, BUFLEN); 265 if (got) { 266 (*env)->SetObjectArrayElement(env, ampms, 1, (*env)->NewString(env, buf, wcslen(buf))); 267 } 268 269 (*env)->ReleaseStringChars(env, jlangtag, langtag); 270 271 return ampms; 272 } 273 274 /* 275 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 276 * Method: getEras 277 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 278 */ 279 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getEras 280 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray eras) { 281 WCHAR ad[BUFLEN]; 282 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 283 284 getCalendarInfoWrapper(langtag, getCalendarID(langtag), NULL, 285 CAL_SERASTRING, ad, BUFLEN, NULL); 286 287 // Windows does not provide B.C. era. 288 (*env)->SetObjectArrayElement(env, eras, 1, (*env)->NewString(env, ad, wcslen(ad))); 289 290 (*env)->ReleaseStringChars(env, jlangtag, langtag); 291 292 return eras; 293 } 294 295 /* 296 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 297 * Method: getMonths 298 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 299 */ 300 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMonths 301 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray months) { 302 replaceCalendarArrayElems(env, jlangtag, months, monthsType, 303 0, sizeof(monthsType)/sizeof(CALTYPE)); 304 return months; 305 } 306 307 /* 308 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 309 * Method: getShortMonths 310 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 311 */ 312 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getShortMonths 313 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray smonths) { 314 replaceCalendarArrayElems(env, jlangtag, smonths, sMonthsType, 315 0, sizeof(sMonthsType)/sizeof(CALTYPE)); 316 return smonths; 317 } 318 319 /* 320 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 321 * Method: getWeekdays 322 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 323 */ 324 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getWeekdays 325 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray wdays) { 326 replaceCalendarArrayElems(env, jlangtag, wdays, wDaysType, 327 1, sizeof(wDaysType)/sizeof(CALTYPE)); 328 return wdays; 329 } 330 331 /* 332 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 333 * Method: getShortWeekdays 334 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 335 */ 336 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getShortWeekdays 337 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray swdays) { 338 replaceCalendarArrayElems(env, jlangtag, swdays, sWDaysType, 339 1, sizeof(sWDaysType)/sizeof(CALTYPE)); 340 return swdays; 341 } 342 343 /* 344 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 345 * Method: getNumberPattern 346 * Signature: (ILjava/lang/String;)Ljava/lang/String; 347 */ 348 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getNumberPattern 349 (JNIEnv *env, jclass cls, jint numberStyle, jstring jlangtag) { 350 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 351 jstring ret; 352 353 WCHAR * pattern = getNumberPattern(langtag, numberStyle); 354 355 (*env)->ReleaseStringChars(env, jlangtag, langtag); 356 ret = (*env)->NewString(env, pattern, wcslen(pattern)); 357 free(pattern); 358 359 return ret; 360 } 361 362 /* 363 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 364 * Method: isNativeDigit 365 * Signature: (Ljava/lang/String;)Z 366 */ 367 JNIEXPORT jboolean JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_isNativeDigit 368 (JNIEnv *env, jclass cls, jstring jlangtag) { 369 DWORD num; 370 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 371 int got = getLocaleInfoWrapper(langtag, 372 LOCALE_IDIGITSUBSTITUTION | LOCALE_RETURN_NUMBER, 373 (LPWSTR)&num, sizeof(num)); 374 (*env)->ReleaseStringChars(env, jlangtag, langtag); 375 376 return got && num == 2; // 2: native digit substitution 377 } 378 379 /* 380 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 381 * Method: getCurrencySymbol 382 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 383 */ 384 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCurrencySymbol 385 (JNIEnv *env, jclass cls, jstring jlangtag, jstring currencySymbol) { 386 WCHAR buf[BUFLEN]; 387 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 388 int got = getLocaleInfoWrapper(langtag, LOCALE_SCURRENCY, buf, BUFLEN); 389 (*env)->ReleaseStringChars(env, jlangtag, langtag); 390 391 if (got) { 392 return (*env)->NewString(env, buf, wcslen(buf)); 393 } else { 394 return currencySymbol; 395 } 396 } 397 398 /* 399 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 400 * Method: getDecimalSeparator 401 * Signature: (Ljava/lang/String;C)C 402 */ 403 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDecimalSeparator 404 (JNIEnv *env, jclass cls, jstring jlangtag, jchar decimalSeparator) { 405 WCHAR buf[BUFLEN]; 406 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 407 int got = getLocaleInfoWrapper(langtag, LOCALE_SDECIMAL, buf, BUFLEN); 408 (*env)->ReleaseStringChars(env, jlangtag, langtag); 409 410 if (got) { 411 return buf[0]; 412 } else { 413 return decimalSeparator; 414 } 415 } 416 417 /* 418 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 419 * Method: getGroupingSeparator 420 * Signature: (Ljava/lang/String;C)C 421 */ 422 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getGroupingSeparator 423 (JNIEnv *env, jclass cls, jstring jlangtag, jchar groupingSeparator) { 424 WCHAR buf[BUFLEN]; 425 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 426 int got = getLocaleInfoWrapper(langtag, LOCALE_STHOUSAND, buf, BUFLEN); 427 (*env)->ReleaseStringChars(env, jlangtag, langtag); 428 429 if (got) { 430 return buf[0]; 431 } else { 432 return groupingSeparator; 433 } 434 } 435 436 /* 437 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 438 * Method: getInfinity 439 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 440 */ 441 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getInfinity 442 (JNIEnv *env, jclass cls, jstring jlangtag, jstring infinity) { 443 WCHAR buf[BUFLEN]; 444 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 445 int got = getLocaleInfoWrapper(langtag, LOCALE_SPOSINFINITY, buf, BUFLEN); 446 (*env)->ReleaseStringChars(env, jlangtag, langtag); 447 448 if (got) { 449 return (*env)->NewString(env, buf, wcslen(buf)); 450 } else { 451 return infinity; 452 } 453 } 454 455 /* 456 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 457 * Method: getInternationalCurrencySymbol 458 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 459 */ 460 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getInternationalCurrencySymbol 461 (JNIEnv *env, jclass cls, jstring jlangtag, jstring internationalCurrencySymbol) { 462 WCHAR buf[BUFLEN]; 463 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 464 int got = getLocaleInfoWrapper(langtag, LOCALE_SINTLSYMBOL, buf, BUFLEN); 465 (*env)->ReleaseStringChars(env, jlangtag, langtag); 466 467 if (got) { 468 return (*env)->NewString(env, buf, wcslen(buf)); 469 } else { 470 return internationalCurrencySymbol; 471 } 472 } 473 474 /* 475 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 476 * Method: getMinusSign 477 * Signature: (Ljava/lang/String;C)C 478 */ 479 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMinusSign 480 (JNIEnv *env, jclass cls, jstring jlangtag, jchar minusSign) { 481 WCHAR buf[BUFLEN]; 482 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 483 int got = getLocaleInfoWrapper(langtag, LOCALE_SNEGATIVESIGN, buf, BUFLEN); 484 (*env)->ReleaseStringChars(env, jlangtag, langtag); 485 486 if (got) { 487 return buf[0]; 488 } else { 489 return minusSign; 490 } 491 } 492 493 /* 494 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 495 * Method: getMonetaryDecimalSeparator 496 * Signature: (Ljava/lang/String;C)C 497 */ 498 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMonetaryDecimalSeparator 499 (JNIEnv *env, jclass cls, jstring jlangtag, jchar monetaryDecimalSeparator) { 500 WCHAR buf[BUFLEN]; 501 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 502 int got = getLocaleInfoWrapper(langtag, LOCALE_SMONDECIMALSEP, buf, BUFLEN); 503 (*env)->ReleaseStringChars(env, jlangtag, langtag); 504 505 if (got) { 506 return buf[0]; 507 } else { 508 return monetaryDecimalSeparator; 509 } 510 } 511 512 /* 513 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 514 * Method: getNaN 515 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 516 */ 517 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getNaN 518 (JNIEnv *env, jclass cls, jstring jlangtag, jstring nan) { 519 WCHAR buf[BUFLEN]; 520 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 521 int got = getLocaleInfoWrapper(langtag, LOCALE_SNAN, buf, BUFLEN); 522 (*env)->ReleaseStringChars(env, jlangtag, langtag); 523 524 if (got) { 525 return (*env)->NewString(env, buf, wcslen(buf)); 526 } else { 527 return nan; 528 } 529 } 530 531 /* 532 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 533 * Method: getPercent 534 * Signature: (Ljava/lang/String;C)C 535 */ 536 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPercent 537 (JNIEnv *env, jclass cls, jstring jlangtag, jchar percent) { 538 WCHAR buf[BUFLEN]; 539 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 540 int got = getLocaleInfoWrapper(langtag, LOCALE_SPERCENT, buf, BUFLEN); 541 (*env)->ReleaseStringChars(env, jlangtag, langtag); 542 543 if (got) { 544 return buf[0]; 545 } else { 546 return percent; 547 } 548 } 549 550 /* 551 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 552 * Method: getPerMill 553 * Signature: (Ljava/lang/String;C)C 554 */ 555 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPerMill 556 (JNIEnv *env, jclass cls, jstring jlangtag, jchar perMill) { 557 WCHAR buf[BUFLEN]; 558 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 559 int got = getLocaleInfoWrapper(langtag, LOCALE_SPERMILLE, buf, BUFLEN); 560 (*env)->ReleaseStringChars(env, jlangtag, langtag); 561 562 if (got) { 563 return buf[0]; 564 } else { 565 return perMill; 566 } 567 } 568 569 /* 570 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 571 * Method: getZeroDigit 572 * Signature: (Ljava/lang/String;C)C 573 */ 574 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getZeroDigit 575 (JNIEnv *env, jclass cls, jstring jlangtag, jchar zeroDigit) { 576 WCHAR buf[BUFLEN]; 577 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 578 int got = getLocaleInfoWrapper(langtag, LOCALE_SNATIVEDIGITS, buf, BUFLEN); 579 (*env)->ReleaseStringChars(env, jlangtag, langtag); 580 581 if (got) { 582 return buf[0]; 583 } else { 584 return zeroDigit; 585 } 586 } 587 588 /* 589 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 590 * Method: getCalendarDataValue 591 * Signature: (Ljava/lang/String;I)I 592 */ 593 JNIEXPORT jint JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCalendarDataValue 594 (JNIEnv *env, jclass cls, jstring jlangtag, jint type) { 595 DWORD num; 596 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 597 int got = 0; 598 599 switch (type) { 600 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CD_FIRSTDAYOFWEEK: 601 got = getLocaleInfoWrapper(langtag, 602 LOCALE_IFIRSTDAYOFWEEK | LOCALE_RETURN_NUMBER, 603 (LPWSTR)&num, sizeof(num)); 604 break; 605 } 606 607 (*env)->ReleaseStringChars(env, jlangtag, langtag); 608 609 if (got) { 610 return num; 611 } else { 612 return -1; 613 } 614 } 615 616 /* 617 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 618 * Method: getDisplayString 619 * Signature: (Ljava/lang/String;ILjava/lang/String;)Ljava/lang/String; 620 */ 621 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDisplayString 622 (JNIEnv *env, jclass cls, jstring jlangtag, jint type, jstring jvalue) { 623 LCTYPE lcType; 624 jstring jStr; 625 const jchar * pjChar; 626 WCHAR buf[BUFLEN]; 627 int got = 0; 628 629 switch (type) { 630 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_CURRENCY_NAME: 631 lcType = LOCALE_SNATIVECURRNAME; 632 jStr = jlangtag; 633 break; 634 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_CURRENCY_SYMBOL: 635 lcType = LOCALE_SCURRENCY; 636 jStr = jlangtag; 637 break; 638 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_LANGUAGE: 639 lcType = LOCALE_SLOCALIZEDLANGUAGENAME; 640 jStr = jvalue; 641 break; 642 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_REGION: 643 lcType = LOCALE_SLOCALIZEDCOUNTRYNAME; 644 jStr = jvalue; 645 break; 646 default: 647 return NULL; 648 } 649 650 pjChar = (*env)->GetStringChars(env, jStr, JNI_FALSE); 651 got = getLocaleInfoWrapper(pjChar, lcType, buf, BUFLEN); 652 (*env)->ReleaseStringChars(env, jStr, pjChar); 653 654 if (got) { 655 return (*env)->NewString(env, buf, wcslen(buf)); 656 } else { 657 return NULL; 658 } 659 } 660 661 int getLocaleInfoWrapper(const jchar *langtag, LCTYPE type, LPWSTR data, int buflen) { 662 if (pGetLocaleInfoEx) { 663 if (wcscmp(L"und", (LPWSTR)langtag) == 0) { 664 // defaults to "en" 665 return pGetLocaleInfoEx(L"en", type, data, buflen); 666 } else { 667 return pGetLocaleInfoEx((LPWSTR)langtag, type, data, buflen); 668 } 669 } else { 670 // If we ever wanted to support WinXP, we will need extra module from 671 // MS... 672 // return GetLocaleInfo(DownlevelLocaleNameToLCID(langtag, 0), type, data, buflen); 673 return 0; 674 } 675 } 676 677 int getCalendarInfoWrapper(const jchar *langtag, CALID id, LPCWSTR reserved, CALTYPE type, LPWSTR data, int buflen, LPDWORD val) { 678 if (pGetCalendarInfoEx) { 679 if (wcscmp(L"und", (LPWSTR)langtag) == 0) { 680 // defaults to "en" 681 return pGetCalendarInfoEx(L"en", id, reserved, type, data, buflen, val); 682 } else { 683 return pGetCalendarInfoEx((LPWSTR)langtag, id, reserved, type, data, buflen, val); 684 } 685 } else { 686 // If we ever wanted to support WinXP, we will need extra module from 687 // MS... 688 // return GetCalendarInfo(DownlevelLocaleNameToLCID(langtag, 0), ...); 689 return 0; 690 } 691 } 692 693 jint getCalendarID(const jchar *langtag) { 694 DWORD type; 695 int got = getLocaleInfoWrapper(langtag, 696 LOCALE_ICALENDARTYPE | LOCALE_RETURN_NUMBER, 697 (LPWSTR)&type, sizeof(type)); 698 699 if (got) { 700 return type; 701 } else { 702 return 0; 703 } 704 } 705 706 void replaceCalendarArrayElems(JNIEnv *env, jstring jlangtag, jobjectArray jarray, CALTYPE* pCalTypes, int offset, int length) { 707 WCHAR name[BUFLEN]; 708 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 709 int calid = getCalendarID(langtag); 710 711 if (calid != -1) { 712 int i; 713 for (i = 0; i < length; i++) { 714 getCalendarInfoWrapper(langtag, calid, NULL, 715 pCalTypes[i], name, BUFLEN, NULL); 716 (*env)->SetObjectArrayElement(env, jarray, i + offset, 717 (*env)->NewString(env, name, wcslen(name))); 718 } 719 } 720 721 (*env)->ReleaseStringChars(env, jlangtag, langtag); 722 } 723 724 WCHAR * getNumberPattern(const jchar * langtag, const jint numberStyle) { 725 WCHAR ret[BUFLEN]; 726 WCHAR number[BUFLEN]; 727 WCHAR fix[BUFLEN]; 728 729 getFixPart(langtag, numberStyle, TRUE, TRUE, ret); // "+" 730 getNumberPart(langtag, numberStyle, number); 731 wcscat_s(ret, BUFLEN-wcslen(ret), number); // "+12.34" 732 getFixPart(langtag, numberStyle, TRUE, FALSE, fix); 733 wcscat_s(ret, BUFLEN-wcslen(ret), fix); // "+12.34$" 734 wcscat_s(ret, BUFLEN-wcslen(ret), L";"); // "+12.34$;" 735 getFixPart(langtag, numberStyle, FALSE, TRUE, fix); 736 wcscat_s(ret, BUFLEN-wcslen(ret), fix); // "+12.34$;(" 737 wcscat_s(ret, BUFLEN-wcslen(ret), number); // "+12.34$;(12.34" 738 getFixPart(langtag, numberStyle, FALSE, FALSE, fix); 739 wcscat_s(ret, BUFLEN-wcslen(ret), fix); // "+12.34$;(12.34$)" 740 741 return _wcsdup(ret); 742 } 743 744 void getNumberPart(const jchar * langtag, const jint numberStyle, WCHAR * number) { 745 DWORD digits = 0; 746 DWORD leadingZero = 0; 747 WCHAR grouping[BUFLEN]; 748 int groupingLen; 749 WCHAR fractionPattern[BUFLEN]; 750 WCHAR * integerPattern = number; 751 WCHAR * pDest; 752 753 // Get info from Windows 754 switch (numberStyle) { 755 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_CURRENCY: 756 getLocaleInfoWrapper(langtag, 757 LOCALE_ICURRDIGITS | LOCALE_RETURN_NUMBER, 758 (LPWSTR)&digits, sizeof(digits)); 759 break; 760 761 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_INTEGER: 762 break; 763 764 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_NUMBER: 765 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_PERCENT: 766 default: 767 getLocaleInfoWrapper(langtag, 768 LOCALE_IDIGITS | LOCALE_RETURN_NUMBER, 769 (LPWSTR)&digits, sizeof(digits)); 770 break; 771 } 772 773 getLocaleInfoWrapper(langtag, 774 LOCALE_ILZERO | LOCALE_RETURN_NUMBER, 775 (LPWSTR)&leadingZero, sizeof(leadingZero)); 776 groupingLen = getLocaleInfoWrapper(langtag, LOCALE_SGROUPING, grouping, BUFLEN); 777 778 // fraction pattern 779 if (digits > 0) { 780 int i; 781 for(i = digits; i > 0; i--) { 782 fractionPattern[i] = L'0'; 783 } 784 fractionPattern[0] = L'.'; 785 fractionPattern[digits+1] = L'\0'; 786 } else { 787 fractionPattern[0] = L'\0'; 788 } 789 790 // integer pattern 791 pDest = integerPattern; 792 if (groupingLen > 0) { 793 int cur = groupingLen - 1;// subtracting null terminator 794 while (--cur >= 0) { 795 int repnum; 796 797 if (grouping[cur] == L';') { 798 continue; 799 } 800 801 repnum = grouping[cur] - 0x30; 802 if (repnum > 0) { 803 *pDest++ = L'#'; 804 *pDest++ = L','; 805 while(--repnum > 0) { 806 *pDest++ = L'#'; 807 } 808 } 809 } 810 } 811 812 if (leadingZero != 0) { 813 *pDest++ = L'0'; 814 } else { 815 *pDest++ = L'#'; 816 } 817 *pDest = L'\0'; 818 819 wcscat_s(integerPattern, BUFLEN, fractionPattern); 820 } 821 822 void getFixPart(const jchar * langtag, const jint numberStyle, BOOL positive, BOOL prefix, WCHAR * ret) { 823 DWORD pattern = 0; 824 int style = numberStyle; 825 int got = 0; 826 827 if (positive) { 828 if (style == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_CURRENCY) { 829 got = getLocaleInfoWrapper(langtag, 830 LOCALE_ICURRENCY | LOCALE_RETURN_NUMBER, 831 (LPWSTR)&pattern, sizeof(pattern)); 832 } else if (style == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_PERCENT) { 833 got = getLocaleInfoWrapper(langtag, 834 LOCALE_IPOSITIVEPERCENT | LOCALE_RETURN_NUMBER, 835 (LPWSTR)&pattern, sizeof(pattern)); 836 } 837 } else { 838 if (style == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_CURRENCY) { 839 got = getLocaleInfoWrapper(langtag, 840 LOCALE_INEGCURR | LOCALE_RETURN_NUMBER, 841 (LPWSTR)&pattern, sizeof(pattern)); 842 } else if (style == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_PERCENT) { 843 got = getLocaleInfoWrapper(langtag, 844 LOCALE_INEGATIVEPERCENT | LOCALE_RETURN_NUMBER, 845 (LPWSTR)&pattern, sizeof(pattern)); 846 } else { 847 got = getLocaleInfoWrapper(langtag, 848 LOCALE_INEGNUMBER | LOCALE_RETURN_NUMBER, 849 (LPWSTR)&pattern, sizeof(pattern)); 850 } 851 } 852 853 if (numberStyle == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_INTEGER) { 854 style = sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_NUMBER; 855 } 856 857 wcscpy(ret, fixes[!prefix][!positive][style][pattern]); 858 }