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 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 WCHAR buf[BUFLEN]; 370 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 371 int got = getLocaleInfoWrapper(langtag, LOCALE_IDIGITSUBSTITUTION, buf, BUFLEN); 372 (*env)->ReleaseStringChars(env, jlangtag, langtag); 373 374 return got && buf[0] == L'2'; // 2: native digit substitution 375 } 376 377 /* 378 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 379 * Method: getCurrencySymbol 380 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 381 */ 382 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCurrencySymbol 383 (JNIEnv *env, jclass cls, jstring jlangtag, jstring currencySymbol) { 384 WCHAR buf[BUFLEN]; 385 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 386 int got = getLocaleInfoWrapper(langtag, LOCALE_SCURRENCY, buf, BUFLEN); 387 (*env)->ReleaseStringChars(env, jlangtag, langtag); 388 389 if (got) { 390 return (*env)->NewString(env, buf, wcslen(buf)); 391 } else { 392 return currencySymbol; 393 } 394 } 395 396 /* 397 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 398 * Method: getDecimalSeparator 399 * Signature: (Ljava/lang/String;C)C 400 */ 401 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDecimalSeparator 402 (JNIEnv *env, jclass cls, jstring jlangtag, jchar decimalSeparator) { 403 WCHAR buf[BUFLEN]; 404 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 405 int got = getLocaleInfoWrapper(langtag, LOCALE_SDECIMAL, buf, BUFLEN); 406 (*env)->ReleaseStringChars(env, jlangtag, langtag); 407 408 if (got) { 409 return buf[0]; 410 } else { 411 return decimalSeparator; 412 } 413 } 414 415 /* 416 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 417 * Method: getGroupingSeparator 418 * Signature: (Ljava/lang/String;C)C 419 */ 420 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getGroupingSeparator 421 (JNIEnv *env, jclass cls, jstring jlangtag, jchar groupingSeparator) { 422 WCHAR buf[BUFLEN]; 423 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 424 int got = getLocaleInfoWrapper(langtag, LOCALE_STHOUSAND, buf, BUFLEN); 425 (*env)->ReleaseStringChars(env, jlangtag, langtag); 426 427 if (got) { 428 return buf[0]; 429 } else { 430 return groupingSeparator; 431 } 432 } 433 434 /* 435 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 436 * Method: getInfinity 437 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 438 */ 439 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getInfinity 440 (JNIEnv *env, jclass cls, jstring jlangtag, jstring infinity) { 441 WCHAR buf[BUFLEN]; 442 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 443 int got = getLocaleInfoWrapper(langtag, LOCALE_SPOSINFINITY, buf, BUFLEN); 444 (*env)->ReleaseStringChars(env, jlangtag, langtag); 445 446 if (got) { 447 return (*env)->NewString(env, buf, wcslen(buf)); 448 } else { 449 return infinity; 450 } 451 } 452 453 /* 454 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 455 * Method: getInternationalCurrencySymbol 456 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 457 */ 458 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getInternationalCurrencySymbol 459 (JNIEnv *env, jclass cls, jstring jlangtag, jstring internationalCurrencySymbol) { 460 WCHAR buf[BUFLEN]; 461 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 462 int got = getLocaleInfoWrapper(langtag, LOCALE_SINTLSYMBOL, buf, BUFLEN); 463 (*env)->ReleaseStringChars(env, jlangtag, langtag); 464 465 if (got) { 466 return (*env)->NewString(env, buf, wcslen(buf)); 467 } else { 468 return internationalCurrencySymbol; 469 } 470 } 471 472 /* 473 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 474 * Method: getMinusSign 475 * Signature: (Ljava/lang/String;C)C 476 */ 477 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMinusSign 478 (JNIEnv *env, jclass cls, jstring jlangtag, jchar minusSign) { 479 WCHAR buf[BUFLEN]; 480 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 481 int got = getLocaleInfoWrapper(langtag, LOCALE_SNEGATIVESIGN, buf, BUFLEN); 482 (*env)->ReleaseStringChars(env, jlangtag, langtag); 483 484 if (got) { 485 return buf[0]; 486 } else { 487 return minusSign; 488 } 489 } 490 491 /* 492 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 493 * Method: getMonetaryDecimalSeparator 494 * Signature: (Ljava/lang/String;C)C 495 */ 496 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getMonetaryDecimalSeparator 497 (JNIEnv *env, jclass cls, jstring jlangtag, jchar monetaryDecimalSeparator) { 498 WCHAR buf[BUFLEN]; 499 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 500 int got = getLocaleInfoWrapper(langtag, LOCALE_SMONDECIMALSEP, buf, BUFLEN); 501 (*env)->ReleaseStringChars(env, jlangtag, langtag); 502 503 if (got) { 504 return buf[0]; 505 } else { 506 return monetaryDecimalSeparator; 507 } 508 } 509 510 /* 511 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 512 * Method: getNaN 513 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 514 */ 515 JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getNaN 516 (JNIEnv *env, jclass cls, jstring jlangtag, jstring nan) { 517 WCHAR buf[BUFLEN]; 518 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 519 int got = getLocaleInfoWrapper(langtag, LOCALE_SNAN, buf, BUFLEN); 520 (*env)->ReleaseStringChars(env, jlangtag, langtag); 521 522 if (got) { 523 return (*env)->NewString(env, buf, wcslen(buf)); 524 } else { 525 return nan; 526 } 527 } 528 529 /* 530 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 531 * Method: getPercent 532 * Signature: (Ljava/lang/String;C)C 533 */ 534 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPercent 535 (JNIEnv *env, jclass cls, jstring jlangtag, jchar percent) { 536 WCHAR buf[BUFLEN]; 537 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 538 int got = getLocaleInfoWrapper(langtag, LOCALE_SPERCENT, buf, BUFLEN); 539 (*env)->ReleaseStringChars(env, jlangtag, langtag); 540 541 if (got) { 542 return buf[0]; 543 } else { 544 return percent; 545 } 546 } 547 548 /* 549 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 550 * Method: getPerMill 551 * Signature: (Ljava/lang/String;C)C 552 */ 553 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getPerMill 554 (JNIEnv *env, jclass cls, jstring jlangtag, jchar perMill) { 555 WCHAR buf[BUFLEN]; 556 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 557 int got = getLocaleInfoWrapper(langtag, LOCALE_SPERMILLE, buf, BUFLEN); 558 (*env)->ReleaseStringChars(env, jlangtag, langtag); 559 560 if (got) { 561 return buf[0]; 562 } else { 563 return perMill; 564 } 565 } 566 567 /* 568 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 569 * Method: getZeroDigit 570 * Signature: (Ljava/lang/String;C)C 571 */ 572 JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getZeroDigit 573 (JNIEnv *env, jclass cls, jstring jlangtag, jchar zeroDigit) { 574 WCHAR buf[BUFLEN]; 575 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 576 int got = getLocaleInfoWrapper(langtag, LOCALE_SNATIVEDIGITS, buf, BUFLEN); 577 (*env)->ReleaseStringChars(env, jlangtag, langtag); 578 579 if (got) { 580 return buf[0]; 581 } else { 582 return zeroDigit; 583 } 584 } 585 586 /* 587 * Class: sun_util_locale_provider_HostLocaleProviderAdapterImpl 588 * Method: getCalendarDataValue 589 * Signature: (Ljava/lang/String;I)I 590 */ 591 JNIEXPORT jint JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getCalendarDataValue 592 (JNIEnv *env, jclass cls, jstring jlangtag, jint type) { 593 WCHAR buf[BUFLEN]; 594 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 595 int got = 0; 596 597 switch (type) { 598 case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CD_FIRSTDAYOFWEEK: 599 got = getLocaleInfoWrapper(langtag, LOCALE_IFIRSTDAYOFWEEK, buf, BUFLEN); 600 break; 601 } 602 603 (*env)->ReleaseStringChars(env, jlangtag, langtag); 604 605 if (got) { 606 return _wtoi(buf); 607 } else { 608 return -1; 609 } 610 } 611 612 int getLocaleInfoWrapper(const jchar *langtag, LCTYPE type, LPWSTR data, int buflen) { 613 if (pGetLocaleInfoEx) { 614 return pGetLocaleInfoEx((LPWSTR)langtag, type, data, buflen); 615 } else { 616 // If we ever wanted to support WinXP, we will need extra module from 617 // MS... 618 // return GetLocaleInfo(DownlevelLocaleNameToLCID(langtag, 0), type, data, buflen); 619 return 0; 620 } 621 } 622 623 int getCalendarInfoWrapper(const jchar *langtag, CALID id, LPCWSTR reserved, CALTYPE type, LPWSTR data, int buflen, LPDWORD val) { 624 if (pGetCalendarInfoEx) { 625 return pGetCalendarInfoEx((LPWSTR)langtag, id, reserved, type, data, buflen, val); 626 } else { 627 // If we ever wanted to support WinXP, we will need extra module from 628 // MS... 629 // return GetCalendarInfo(DownlevelLocaleNameToLCID(langtag, 0), ...); 630 return 0; 631 } 632 } 633 634 jint getCalendarID(const jchar *langtag) { 635 WCHAR type[BUFLEN]; 636 int got = getLocaleInfoWrapper(langtag, LOCALE_ICALENDARTYPE, type, BUFLEN); 637 638 if (got) { 639 return _wtoi(type); 640 } else { 641 return 0; 642 } 643 } 644 645 void replaceCalendarArrayElems(JNIEnv *env, jstring jlangtag, jobjectArray jarray, CALTYPE* pCalTypes, int offset, int length) { 646 WCHAR name[BUFLEN]; 647 const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); 648 int calid = getCalendarID(langtag); 649 650 if (calid != -1) { 651 int i; 652 for (i = 0; i < length; i++) { 653 getCalendarInfoWrapper(langtag, calid, NULL, 654 pCalTypes[i], name, BUFLEN, NULL); 655 (*env)->SetObjectArrayElement(env, jarray, i + offset, 656 (*env)->NewString(env, name, wcslen(name))); 657 } 658 } 659 660 (*env)->ReleaseStringChars(env, jlangtag, langtag); 661 } 662 663 WCHAR * getNumberPattern(const jchar * langtag, const jint numberStyle) { 664 WCHAR ret[BUFLEN]; 665 WCHAR number[BUFLEN]; 666 WCHAR fix[BUFLEN]; 667 668 getFixPart(langtag, numberStyle, TRUE, TRUE, ret); // "+" 669 getNumberPart(langtag, numberStyle, number); 670 wcscat_s(ret, BUFLEN-wcslen(ret), number); // "+12.34" 671 getFixPart(langtag, numberStyle, TRUE, FALSE, fix); 672 wcscat_s(ret, BUFLEN-wcslen(ret), fix); // "+12.34$" 673 wcscat_s(ret, BUFLEN-wcslen(ret), L";"); // "+12.34$;" 674 getFixPart(langtag, numberStyle, FALSE, TRUE, fix); 675 wcscat_s(ret, BUFLEN-wcslen(ret), fix); // "+12.34$;(" 676 wcscat_s(ret, BUFLEN-wcslen(ret), number); // "+12.34$;(12.34" 677 getFixPart(langtag, numberStyle, FALSE, FALSE, fix); 678 wcscat_s(ret, BUFLEN-wcslen(ret), fix); // "+12.34$;(12.34$)" 679 680 return _wcsdup(ret); 681 } 682 683 void getNumberPart(const jchar * langtag, const jint numberStyle, WCHAR * number) { 684 WCHAR buf[BUFLEN]; 685 WCHAR grouping[BUFLEN]; 686 WCHAR fractionPattern[BUFLEN]; 687 WCHAR * integerPattern = number; 688 int digits; 689 BOOL leadingZero; 690 WCHAR * pDest; 691 int groupingLen; 692 693 // Get info from Windows 694 if (numberStyle == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_CURRENCY) { 695 getLocaleInfoWrapper(langtag, LOCALE_ICURRDIGITS, buf, BUFLEN); 696 } else { 697 getLocaleInfoWrapper(langtag, LOCALE_IDIGITS, buf, BUFLEN); 698 } 699 if (numberStyle == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_INTEGER) { 700 digits = 0; 701 } else { 702 digits = _wtoi(buf); 703 } 704 getLocaleInfoWrapper(langtag, LOCALE_ILZERO, buf, BUFLEN); 705 leadingZero = _wtoi(buf) != 0; 706 groupingLen = getLocaleInfoWrapper(langtag, LOCALE_SGROUPING, grouping, BUFLEN); 707 708 // fraction pattern 709 if (digits > 0) { 710 int i; 711 for(i = digits; i > 0; i--) { 712 fractionPattern[i] = L'0'; 713 } 714 fractionPattern[0] = L'.'; 715 fractionPattern[digits+1] = L'\0'; 716 } else { 717 fractionPattern[0] = L'\0'; 718 } 719 720 // integer pattern 721 pDest = integerPattern; 722 if (groupingLen > 0) { 723 int cur = groupingLen - 1;// subtracting null terminator 724 while (--cur >= 0) { 725 int repnum; 726 727 if (grouping[cur] == L';') { 728 continue; 729 } 730 731 repnum = grouping[cur] - 0x30; 732 if (repnum > 0) { 733 *pDest++ = L'#'; 734 *pDest++ = L','; 735 while(--repnum > 0) { 736 *pDest++ = L'#'; 737 } 738 } 739 } 740 } 741 742 if (leadingZero) { 743 *pDest++ = L'0'; 744 } else { 745 *pDest++ = L'#'; 746 } 747 *pDest = L'\0'; 748 749 wcscat_s(integerPattern, BUFLEN, fractionPattern); 750 } 751 752 void getFixPart(const jchar * langtag, const jint numberStyle, BOOL positive, BOOL prefix, WCHAR * ret) { 753 WCHAR buf[BUFLEN]; 754 int pattern = 0; 755 int style = numberStyle; 756 int got = 0; 757 758 if (positive) { 759 if (style == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_CURRENCY) { 760 got = getLocaleInfoWrapper(langtag, LOCALE_ICURRENCY, buf, BUFLEN); 761 } else if (style == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_PERCENT) { 762 got = getLocaleInfoWrapper(langtag, LOCALE_IPOSITIVEPERCENT, buf, BUFLEN); 763 } 764 } else { 765 if (style == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_CURRENCY) { 766 got = getLocaleInfoWrapper(langtag, LOCALE_INEGCURR, buf, BUFLEN); 767 } else if (style == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_PERCENT) { 768 got = getLocaleInfoWrapper(langtag, LOCALE_INEGATIVEPERCENT, buf, BUFLEN); 769 } else { 770 got = getLocaleInfoWrapper(langtag, LOCALE_INEGNUMBER, buf, BUFLEN); 771 } 772 } 773 if (got) { 774 pattern = _wtoi(buf); 775 } 776 777 if (numberStyle == sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_INTEGER) { 778 style = sun_util_locale_provider_HostLocaleProviderAdapterImpl_NF_NUMBER; 779 } 780 781 wcscpy(ret, fixes[!prefix][!positive][style][pattern]); 782 }