1 /* 2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "sun_util_locale_provider_HostLocaleProviderAdapterImpl.h" 27 #include <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 = 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 datePattern[BUFLEN]; 213 WCHAR timePattern[BUFLEN]; 214 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 215 216 datePattern[0] = L'\0'; 217 timePattern[0] = L'\0'; 218 219 if (dateStyle == 0 || dateStyle == 1) { 220 getLocaleInfoWrapper(langtag, LOCALE_SLONGDATE, datePattern, BUFLEN); 221 } else if (dateStyle == 2 || dateStyle == 3) { 222 getLocaleInfoWrapper(langtag, LOCALE_SSHORTDATE, datePattern, BUFLEN); 223 } 224 225 if (timeStyle == 0 || timeStyle == 1) { 226 getLocaleInfoWrapper(langtag, LOCALE_STIMEFORMAT, timePattern, BUFLEN); 227 } else if (timeStyle == 2 || timeStyle == 3) { 228 getLocaleInfoWrapper(langtag, LOCALE_SSHORTTIME, timePattern, BUFLEN); 229 } 230 231 wcscat(datePattern, L" "); 232 wcscat(datePattern, timePattern); 233 234 (*env)->ReleaseStringChars(env, jlangtag, langtag); 235 236 return (*env)->NewString(env, datePattern, wcslen(datePattern)); 237 } 238 239 /* 240 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 241 * Method: getCalendarID 242 * Signature: (Ljava/lang/String;)I 243 */ 244 JNIEXPORT jint JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCalendarID 245 (JNIEnv *env, jclass cls, jstring jlangtag) { 246 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 247 jint ret = getCalendarID(langtag); 248 (*env)->ReleaseStringChars(env, jlangtag, langtag); 249 return ret; 250 } 251 252 /* 253 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 254 * Method: getAmPmStrings 255 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 256 */ 257 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getAmPmStrings 258 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray ampms) { 259 WCHAR buf[BUFLEN]; 260 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 261 262 // AM 263 int got = getLocaleInfoWrapper(langtag, LOCALE_S1159, buf, BUFLEN); 264 if (got) { 265 (*env)->SetObjectArrayElement(env, ampms, 0, (*env)->NewString(env, buf, wcslen(buf))); 266 } 267 268 // PM 269 got = getLocaleInfoWrapper(langtag, LOCALE_S2359, buf, BUFLEN); 270 if (got) { 271 (*env)->SetObjectArrayElement(env, ampms, 1, (*env)->NewString(env, buf, wcslen(buf))); 272 } 273 274 (*env)->ReleaseStringChars(env, jlangtag, langtag); 275 276 return ampms; 277 } 278 279 /* 280 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 281 * Method: getEras 282 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 283 */ 284 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getEras 285 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray eras) { 286 WCHAR ad[BUFLEN]; 287 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 288 289 getCalendarInfoWrapper(langtag, getCalendarID(langtag), NULL, 290 CAL_SERASTRING, ad, BUFLEN, NULL); 291 292 // Windows does not provide B.C. era. 293 (*env)->SetObjectArrayElement(env, eras, 1, (*env)->NewString(env, ad, wcslen(ad))); 294 295 (*env)->ReleaseStringChars(env, jlangtag, langtag); 296 297 return eras; 298 } 299 300 /* 301 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 302 * Method: getMonths 303 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 304 */ 305 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMonths 306 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray months) { 307 replaceCalendarArrayElems(env, jlangtag, months, monthsType, 308 0, sizeof(monthsType)/sizeof(CALTYPE)); 309 return months; 310 } 311 312 /* 313 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 314 * Method: getShortMonths 315 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 316 */ 317 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getShortMonths 318 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray smonths) { 319 replaceCalendarArrayElems(env, jlangtag, smonths, sMonthsType, 320 0, sizeof(sMonthsType)/sizeof(CALTYPE)); 321 return smonths; 322 } 323 324 /* 325 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 326 * Method: getWeekdays 327 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 328 */ 329 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getWeekdays 330 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray wdays) { 331 replaceCalendarArrayElems(env, jlangtag, wdays, wDaysType, 332 1, sizeof(wDaysType)/sizeof(CALTYPE)); 333 return wdays; 334 } 335 336 /* 337 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 338 * Method: getShortWeekdays 339 * Signature: (Ljava/lang/String;[Ljava/lang/String;)[Ljava/lang/String; 340 */ 341 JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getShortWeekdays 342 (JNIEnv *env, jclass cls, jstring jlangtag, jobjectArray swdays) { 343 replaceCalendarArrayElems(env, jlangtag, swdays, sWDaysType, 344 1, sizeof(sWDaysType)/sizeof(CALTYPE)); 345 return swdays; 346 } 347 348 /* 349 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 350 * Method: getNumberPattern 351 * Signature: (ILjava/lang/String;)Ljava/lang/String; 352 */ 353 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getNumberPattern 354 (JNIEnv *env, jclass cls, jint numberStyle, jstring jlangtag) { 355 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 356 jstring ret; 357 358 WCHAR * pattern = getNumberPattern(langtag, numberStyle); 359 360 (*env)->ReleaseStringChars(env, jlangtag, langtag); 361 ret = (*env)->NewString(env, pattern, wcslen(pattern)); 362 free(pattern); 363 364 return ret; 365 } 366 367 /* 368 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 369 * Method: isNativeDigit 370 * Signature: (Ljava/lang/String;)Z 371 */ 372 JNIEXPORT jboolean JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_isNativeDigit 373 (JNIEnv *env, jclass cls, jstring jlangtag) { 374 WCHAR buf[BUFLEN]; 375 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 376 int got = getLocaleInfoWrapper(langtag, LOCALE_IDIGITSUBSTITUTION, buf, BUFLEN); 377 (*env)->ReleaseStringChars(env, jlangtag, langtag); 378 379 return got && buf[0] == L'2'; // 2: native digit substitution 380 } 381 382 /* 383 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 384 * Method: getCurrencySymbol 385 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 386 */ 387 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCurrencySymbol 388 (JNIEnv *env, jclass cls, jstring jlangtag, jstring currencySymbol) { 389 WCHAR buf[BUFLEN]; 390 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 391 int got = getLocaleInfoWrapper(langtag, LOCALE_SCURRENCY, buf, BUFLEN); 392 (*env)->ReleaseStringChars(env, jlangtag, langtag); 393 394 if (got) { 395 return (*env)->NewString(env, buf, wcslen(buf)); 396 } else { 397 return currencySymbol; 398 } 399 } 400 401 /* 402 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 403 * Method: getDecimalSeparator 404 * Signature: (Ljava/lang/String;C)C 405 */ 406 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDecimalSeparator 407 (JNIEnv *env, jclass cls, jstring jlangtag, jchar decimalSeparator) { 408 WCHAR buf[BUFLEN]; 409 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 410 int got = getLocaleInfoWrapper(langtag, LOCALE_SDECIMAL, buf, BUFLEN); 411 (*env)->ReleaseStringChars(env, jlangtag, langtag); 412 413 if (got) { 414 return buf[0]; 415 } else { 416 return decimalSeparator; 417 } 418 } 419 420 /* 421 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 422 * Method: getGroupingSeparator 423 * Signature: (Ljava/lang/String;C)C 424 */ 425 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getGroupingSeparator 426 (JNIEnv *env, jclass cls, jstring jlangtag, jchar groupingSeparator) { 427 WCHAR buf[BUFLEN]; 428 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 429 int got = getLocaleInfoWrapper(langtag, LOCALE_STHOUSAND, buf, BUFLEN); 430 (*env)->ReleaseStringChars(env, jlangtag, langtag); 431 432 if (got) { 433 return buf[0]; 434 } else { 435 return groupingSeparator; 436 } 437 } 438 439 /* 440 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 441 * Method: getInfinity 442 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 443 */ 444 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getInfinity 445 (JNIEnv *env, jclass cls, jstring jlangtag, jstring infinity) { 446 WCHAR buf[BUFLEN]; 447 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 448 int got = getLocaleInfoWrapper(langtag, LOCALE_SPOSINFINITY, buf, BUFLEN); 449 (*env)->ReleaseStringChars(env, jlangtag, langtag); 450 451 if (got) { 452 return (*env)->NewString(env, buf, wcslen(buf)); 453 } else { 454 return infinity; 455 } 456 } 457 458 /* 459 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 460 * Method: getInternationalCurrencySymbol 461 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 462 */ 463 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getInternationalCurrencySymbol 464 (JNIEnv *env, jclass cls, jstring jlangtag, jstring internationalCurrencySymbol) { 465 WCHAR buf[BUFLEN]; 466 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 467 int got = getLocaleInfoWrapper(langtag, LOCALE_SINTLSYMBOL, buf, BUFLEN); 468 (*env)->ReleaseStringChars(env, jlangtag, langtag); 469 470 if (got) { 471 return (*env)->NewString(env, buf, wcslen(buf)); 472 } else { 473 return internationalCurrencySymbol; 474 } 475 } 476 477 /* 478 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 479 * Method: getMinusSign 480 * Signature: (Ljava/lang/String;C)C 481 */ 482 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMinusSign 483 (JNIEnv *env, jclass cls, jstring jlangtag, jchar minusSign) { 484 WCHAR buf[BUFLEN]; 485 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 486 int got = getLocaleInfoWrapper(langtag, LOCALE_SNEGATIVESIGN, buf, BUFLEN); 487 (*env)->ReleaseStringChars(env, jlangtag, langtag); 488 489 if (got) { 490 return buf[0]; 491 } else { 492 return minusSign; 493 } 494 } 495 496 /* 497 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 498 * Method: getMonetaryDecimalSeparator 499 * Signature: (Ljava/lang/String;C)C 500 */ 501 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMonetaryDecimalSeparator 502 (JNIEnv *env, jclass cls, jstring jlangtag, jchar monetaryDecimalSeparator) { 503 WCHAR buf[BUFLEN]; 504 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 505 int got = getLocaleInfoWrapper(langtag, LOCALE_SMONDECIMALSEP, buf, BUFLEN); 506 (*env)->ReleaseStringChars(env, jlangtag, langtag); 507 508 if (got) { 509 return buf[0]; 510 } else { 511 return monetaryDecimalSeparator; 512 } 513 } 514 515 /* 516 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 517 * Method: getNaN 518 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 519 */ 520 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getNaN 521 (JNIEnv *env, jclass cls, jstring jlangtag, jstring nan) { 522 WCHAR buf[BUFLEN]; 523 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 524 int got = getLocaleInfoWrapper(langtag, LOCALE_SNAN, buf, BUFLEN); 525 (*env)->ReleaseStringChars(env, jlangtag, langtag); 526 527 if (got) { 528 return (*env)->NewString(env, buf, wcslen(buf)); 529 } else { 530 return nan; 531 } 532 } 533 534 /* 535 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 536 * Method: getPercent 537 * Signature: (Ljava/lang/String;C)C 538 */ 539 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPercent 540 (JNIEnv *env, jclass cls, jstring jlangtag, jchar percent) { 541 WCHAR buf[BUFLEN]; 542 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 543 int got = getLocaleInfoWrapper(langtag, LOCALE_SPERCENT, buf, BUFLEN); 544 (*env)->ReleaseStringChars(env, jlangtag, langtag); 545 546 if (got) { 547 return buf[0]; 548 } else { 549 return percent; 550 } 551 } 552 553 /* 554 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 555 * Method: getPerMill 556 * Signature: (Ljava/lang/String;C)C 557 */ 558 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPerMill 559 (JNIEnv *env, jclass cls, jstring jlangtag, jchar perMill) { 560 WCHAR buf[BUFLEN]; 561 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 562 int got = getLocaleInfoWrapper(langtag, LOCALE_SPERMILLE, buf, BUFLEN); 563 (*env)->ReleaseStringChars(env, jlangtag, langtag); 564 565 if (got) { 566 return buf[0]; 567 } else { 568 return perMill; 569 } 570 } 571 572 /* 573 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 574 * Method: getZeroDigit 575 * Signature: (Ljava/lang/String;C)C 576 */ 577 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getZeroDigit 578 (JNIEnv *env, jclass cls, jstring jlangtag, jchar zeroDigit) { 579 WCHAR buf[BUFLEN]; 580 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 581 int got = getLocaleInfoWrapper(langtag, LOCALE_SNATIVEDIGITS, buf, BUFLEN); 582 (*env)->ReleaseStringChars(env, jlangtag, langtag); 583 584 if (got) { 585 return buf[0]; 586 } else { 587 return zeroDigit; 588 } 589 } 590 591 /* 592 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 593 * Method: getCalendarDataValue 594 * Signature: (Ljava/lang/String;I)I 595 */ 596 JNIEXPORT jint JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCalendarDataValue 597 (JNIEnv *env, jclass cls, jstring jlangtag, jint type) { 598 WCHAR buf[BUFLEN]; 599 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 600 int got = 0; 601 602 switch (type) { 603 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CD_FIRSTDAYOFWEEK: 604 got = getLocaleInfoWrapper(langtag, LOCALE_IFIRSTDAYOFWEEK, buf, BUFLEN); 605 break; 606 } 607 608 (*env)->ReleaseStringChars(env, jlangtag, langtag); 609 610 if (got) { 611 return _wtoi(buf); 612 } else { 613 return -1; 614 } 615 } 616 617 int getLocaleInfoWrapper(const jchar *langtag, LCTYPE type, LPWSTR data, int buflen) { 618 if (pGetLocaleInfoEx) { 619 return pGetLocaleInfoEx((LPWSTR)langtag, type, data, buflen); 620 } else { 621 // If we ever wanted to support WinXP, we will need extra module from 622 // MS... 623 // return GetLocaleInfo(DownlevelLocaleNameToLCID(langtag, 0), type, data, buflen); 624 return 0; 625 } 626 } 627 628 int getCalendarInfoWrapper(const jchar *langtag, CALID id, LPCWSTR reserved, CALTYPE type, LPWSTR data, int buflen, LPDWORD val) { 629 if (pGetCalendarInfoEx) { 630 return pGetCalendarInfoEx((LPWSTR)langtag, id, reserved, type, data, buflen, val); 631 } else { 632 // If we ever wanted to support WinXP, we will need extra module from 633 // MS... 634 // return GetCalendarInfo(DownlevelLocaleNameToLCID(langtag, 0), ...); 635 return 0; 636 } 637 } 638 639 jint getCalendarID(const jchar *langtag) { 640 WCHAR type[BUFLEN]; 641 int got = getLocaleInfoWrapper(langtag, LOCALE_ICALENDARTYPE, type, BUFLEN); 642 643 if (got) { 644 return _wtoi(type); 645 } else { 646 return 0; 647 } 648 } 649 650 void replaceCalendarArrayElems(JNIEnv *env, jstring jlangtag, jobjectArray jarray, CALTYPE* pCalTypes, int offset, int length) { 651 WCHAR name[BUFLEN]; 652 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 653 int calid = getCalendarID(langtag); 654 655 if (calid != -1) { 656 int i; 657 for (i = 0; i < length; i++) { 658 getCalendarInfoWrapper(langtag, calid, NULL, 659 pCalTypes[i], name, BUFLEN, NULL); 660 (*env)->SetObjectArrayElement(env, jarray, i + offset, 661 (*env)->NewString(env, name, wcslen(name))); 662 } 663 } 664 665 (*env)->ReleaseStringChars(env, jlangtag, langtag); 666 } 667 668 WCHAR * getNumberPattern(const jchar * langtag, const jint numberStyle) { 669 WCHAR ret[BUFLEN]; 670 WCHAR number[BUFLEN]; 671 WCHAR fix[BUFLEN]; 672 673 getFixPart(langtag, numberStyle, TRUE, TRUE, ret); // "+" 674 getNumberPart(langtag, numberStyle, number); 675 wcscat_s(ret, BUFLEN-wcslen(ret), number); // "+12.34" 676 getFixPart(langtag, numberStyle, TRUE, FALSE, fix); 677 wcscat_s(ret, BUFLEN-wcslen(ret), fix); // "+12.34$" 678 wcscat_s(ret, BUFLEN-wcslen(ret), L";"); // "+12.34$;" 679 getFixPart(langtag, numberStyle, FALSE, TRUE, fix); 680 wcscat_s(ret, BUFLEN-wcslen(ret), fix); // "+12.34$;(" 681 wcscat_s(ret, BUFLEN-wcslen(ret), number); // "+12.34$;(12.34" 682 getFixPart(langtag, numberStyle, FALSE, FALSE, fix); 683 wcscat_s(ret, BUFLEN-wcslen(ret), fix); // "+12.34$;(12.34$)" 684 685 return _wcsdup(ret); 686 } 687 688 void getNumberPart(const jchar * langtag, const jint numberStyle, WCHAR * number) { 689 WCHAR buf[BUFLEN]; 690 WCHAR grouping[BUFLEN]; 691 WCHAR fractionPattern[BUFLEN]; 692 WCHAR * integerPattern = number; 693 int digits; 694 BOOL leadingZero; 695 WCHAR * pDest; 696 int groupingLen; 697 698 // Get info from Windows 699 if (numberStyle == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_CURRENCY) { 700 getLocaleInfoWrapper(langtag, LOCALE_ICURRDIGITS, buf, BUFLEN); 701 } else { 702 getLocaleInfoWrapper(langtag, LOCALE_IDIGITS, buf, BUFLEN); 703 } 704 if (numberStyle == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_INTEGER) { 705 digits = 0; 706 } else { 707 digits = _wtoi(buf); 708 } 709 getLocaleInfoWrapper(langtag, LOCALE_ILZERO, buf, BUFLEN); 710 leadingZero = _wtoi(buf) != 0; 711 groupingLen = getLocaleInfoWrapper(langtag, LOCALE_SGROUPING, grouping, BUFLEN); 712 713 // fraction pattern 714 if (digits > 0) { 715 int i; 716 for(i = digits; i > 0; i--) { 717 fractionPattern[i] = L'0'; 718 } 719 fractionPattern[0] = L'.'; 720 fractionPattern[digits+1] = L'\0'; 721 } else { 722 fractionPattern[0] = L'\0'; 723 } 724 725 // integer pattern 726 pDest = integerPattern; 727 if (groupingLen > 0) { 728 int cur = groupingLen - 1;// subtracting null terminator 729 while (--cur >= 0) { 730 int repnum; 731 732 if (grouping[cur] == L';') { 733 continue; 734 } 735 736 repnum = grouping[cur] - 0x30; 737 if (repnum > 0) { 738 *pDest++ = L'#'; 739 *pDest++ = L','; 740 while(--repnum > 0) { 741 *pDest++ = L'#'; 742 } 743 } 744 } 745 } 746 747 if (leadingZero) { 748 *pDest++ = L'0'; 749 } else { 750 *pDest++ = L'#'; 751 } 752 *pDest = L'\0'; 753 754 wcscat_s(integerPattern, BUFLEN, fractionPattern); 755 } 756 757 void getFixPart(const jchar * langtag, const jint numberStyle, BOOL positive, BOOL prefix, WCHAR * ret) { 758 WCHAR buf[BUFLEN]; 759 int pattern = 0; 760 int style = numberStyle; 761 int got = 0; 762 763 if (positive) { 764 if (style == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_CURRENCY) { 765 got = getLocaleInfoWrapper(langtag, LOCALE_ICURRENCY, buf, BUFLEN); 766 } else if (style == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_PERCENT) { 767 got = getLocaleInfoWrapper(langtag, LOCALE_IPOSITIVEPERCENT, buf, BUFLEN); 768 } 769 } else { 770 if (style == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_CURRENCY) { 771 got = getLocaleInfoWrapper(langtag, LOCALE_INEGCURR, buf, BUFLEN); 772 } else if (style == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_PERCENT) { 773 got = getLocaleInfoWrapper(langtag, LOCALE_INEGATIVEPERCENT, buf, BUFLEN); 774 } else { 775 got = getLocaleInfoWrapper(langtag, LOCALE_INEGNUMBER, buf, BUFLEN); 776 } 777 } 778 if (got) { 779 pattern = _wtoi(buf); 780 } 781 782 if (numberStyle == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_INTEGER) { 783 style = sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_NUMBER; 784 } 785 786 wcscpy(ret, fixes[!prefix][!positive][style][pattern]); 787 }