Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenlocale.c
Go to the documentation of this file.
00001 /* 00002 * Some stuff takem from wine msvcrt\locale.c 00003 * 00004 * Copyright 2000 Jon Griffiths 00005 */ 00006 00007 #include <precomp.h> 00008 #include <locale.h> 00009 00010 #include "mbctype.h" 00011 00012 // mtdll.h 00013 #define _SETLOCALE_LOCK 19 00014 00015 // msvcrt.h 00016 #define MSVCRT_LC_ALL 0 00017 #define MSVCRT_LC_COLLATE 1 00018 #define MSVCRT_LC_CTYPE 2 00019 #define MSVCRT_LC_MONETARY 3 00020 #define MSVCRT_LC_NUMERIC 4 00021 #define MSVCRT_LC_TIME 5 00022 #define MSVCRT_LC_MIN MSVCRT_LC_ALL 00023 #define MSVCRT_LC_MAX MSVCRT_LC_TIME 00024 00025 /* FIXME: Need to hold locale for each LC_* type and aggregate 00026 * string to produce lc_all. 00027 */ 00028 #define MAX_ELEM_LEN 64 /* Max length of country/language/CP string */ 00029 00030 unsigned char _mbctype[257] = { 0 }; 00031 int g_mbcp_is_multibyte = 0; 00032 00033 /* It seems that the data about valid trail bytes is not available from kernel32 00034 * so we have to store is here. The format is the same as for lead bytes in CPINFO */ 00035 struct cp_extra_info_t 00036 { 00037 int cp; 00038 BYTE TrailBytes[MAX_LEADBYTES]; 00039 }; 00040 00041 static struct cp_extra_info_t g_cpextrainfo[] = 00042 { 00043 {932, {0x40, 0x7e, 0x80, 0xfc, 0, 0}}, 00044 {936, {0x40, 0xfe, 0, 0}}, 00045 {949, {0x41, 0xfe, 0, 0}}, 00046 {950, {0x40, 0x7e, 0xa1, 0xfe, 0, 0}}, 00047 {1361, {0x31, 0x7e, 0x81, 0xfe, 0, 0}}, 00048 {20932, {1, 255, 0, 0}}, /* seems to give different results on different systems */ 00049 {0, {1, 255, 0, 0}} /* match all with FIXME */ 00050 }; 00051 00052 00053 char MSVCRT_current_lc_all[MAX_LOCALE_LENGTH] = { 0 }; 00054 LCID MSVCRT_current_lc_all_lcid = 0; 00055 int MSVCRT___lc_codepage = 0; 00056 int MSVCRT___lc_collate_cp = 0; 00057 HANDLE MSVCRT___lc_handle[MSVCRT_LC_MAX - MSVCRT_LC_MIN + 1] = { 0 }; 00058 int __mb_cur_max = 1; 00059 00060 /* MT */ 00061 #define LOCK_LOCALE _mlock(_SETLOCALE_LOCK); 00062 #define UNLOCK_LOCALE _munlock(_SETLOCALE_LOCK); 00063 00064 #define MSVCRT_LEADBYTE 0x8000 00065 00066 typedef struct { 00067 char search_language[MAX_ELEM_LEN]; 00068 char search_country[MAX_ELEM_LEN]; 00069 char search_codepage[MAX_ELEM_LEN]; 00070 char found_language[MAX_ELEM_LEN]; 00071 char found_country[MAX_ELEM_LEN]; 00072 char found_codepage[MAX_ELEM_LEN]; 00073 unsigned int match_flags; 00074 LANGID found_lang_id; 00075 } locale_search_t; 00076 00077 unsigned int __setlc_active; 00078 unsigned int __unguarded_readlc_active; 00079 int _current_category; /* used by setlocale */ 00080 const char *_current_locale; 00081 00082 00083 int parse_locale(const char *locale, char *lang, char *country, char *code_page); 00084 00085 #define _C_ _CONTROL 00086 #define _S_ _SPACE 00087 #define _P_ _PUNCT 00088 #define _D_ _DIGIT 00089 #define _H_ _HEX 00090 #define _U_ _UPPER 00091 #define _L_ _LOWER 00092 00093 WORD MSVCRT__ctype [257] = { 00094 0, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|_C_, _S_|_C_, 00095 _S_|_C_, _S_|_C_, _S_|_C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, 00096 _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|_BLANK, 00097 _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, 00098 _P_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, 00099 _D_|_H_, _D_|_H_, _D_|_H_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _U_|_H_, 00100 _U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_, _U_, _U_, _U_, _U_, 00101 _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, 00102 _U_, _P_, _P_, _P_, _P_, _P_, _P_, _L_|_H_, _L_|_H_, _L_|_H_, _L_|_H_, 00103 _L_|_H_, _L_|_H_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, 00104 _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _P_, _P_, _P_, _P_, 00105 _C_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00106 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00108 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 00111 }; 00112 00113 /* Internal: Current ctype table for locale */ 00114 WORD MSVCRT_current_ctype[257]; 00115 00116 /* pctype is used by macros in the Win32 headers. It must point 00117 * To a table of flags exactly like ctype. To allow locale 00118 * changes to affect ctypes (i.e. isleadbyte), we use a second table 00119 * and update its flags whenever the current locale changes. 00120 */ 00121 WORD* MSVCRT__pctype = MSVCRT_current_ctype + 1; 00122 00123 /* Friendly country strings & iso codes for synonym support. 00124 * Based on MS documentation for setlocale(). 00125 */ 00126 static const char * const _country_synonyms[] = 00127 { 00128 "Hong Kong","HK", 00129 "Hong-Kong","HK", 00130 "New Zealand","NZ", 00131 "New-Zealand","NZ", 00132 "PR China","CN", 00133 "PR-China","CN", 00134 "United Kingdom","GB", 00135 "United-Kingdom","GB", 00136 "Britain","GB", 00137 "England","GB", 00138 "Great Britain","GB", 00139 "United States","US", 00140 "United-States","US", 00141 "America","US" 00142 }; 00143 00144 /* Note: Flags are weighted in order of matching importance */ 00145 #define FOUND_LANGUAGE 0x4 00146 #define FOUND_COUNTRY 0x2 00147 #define FOUND_CODEPAGE 0x1 00148 00149 /* INTERNAL: Map a synonym to an ISO code */ 00150 static void remap_synonym(char *name) 00151 { 00152 size_t i; 00153 for (i = 0; i < sizeof(_country_synonyms)/sizeof(char*); i += 2 ) 00154 { 00155 if (!_stricmp(_country_synonyms[i],name)) 00156 { 00157 TRACE(":Mapping synonym %s to %s\n",name,_country_synonyms[i+1]); 00158 name[0] = _country_synonyms[i+1][0]; 00159 name[1] = _country_synonyms[i+1][1]; 00160 name[2] = '\0'; 00161 return; 00162 } 00163 } 00164 } 00165 00166 #define CONTINUE_LOOKING TRUE 00167 #define STOP_LOOKING FALSE 00168 00169 /* INTERNAL: Get and compare locale info with a given string */ 00170 static int compare_info(LCID lcid, DWORD flags, char* buff, const char* cmp) 00171 { 00172 buff[0] = 0; 00173 GetLocaleInfoA(lcid, flags|LOCALE_NOUSEROVERRIDE,buff, MAX_ELEM_LEN); 00174 if (!buff[0] || !cmp[0]) 00175 return 0; 00176 /* Partial matches are allowed, e.g. "Germ" matches "Germany" */ 00177 return !_strnicmp(cmp, buff, strlen(cmp)); 00178 } 00179 00180 00181 static BOOL CALLBACK 00182 find_best_locale_proc(HMODULE hModule, LPCSTR type, LPCSTR name, WORD LangID, LONG_PTR lParam) 00183 { 00184 locale_search_t *res = (locale_search_t *)lParam; 00185 const LCID lcid = MAKELCID(LangID, SORT_DEFAULT); 00186 char buff[MAX_ELEM_LEN]; 00187 unsigned int flags = 0; 00188 00189 if(PRIMARYLANGID(LangID) == LANG_NEUTRAL) 00190 return CONTINUE_LOOKING; 00191 00192 /* Check Language */ 00193 if (compare_info(lcid,LOCALE_SISO639LANGNAME,buff,res->search_language) || 00194 compare_info(lcid,LOCALE_SABBREVLANGNAME,buff,res->search_language) || 00195 compare_info(lcid,LOCALE_SENGLANGUAGE,buff,res->search_language)) 00196 { 00197 TRACE(":Found language: %s->%s\n", res->search_language, buff); 00198 flags |= FOUND_LANGUAGE; 00199 memcpy(res->found_language,res->search_language,MAX_ELEM_LEN); 00200 } 00201 else if (res->match_flags & FOUND_LANGUAGE) 00202 { 00203 return CONTINUE_LOOKING; 00204 } 00205 00206 /* Check Country */ 00207 if (compare_info(lcid,LOCALE_SISO3166CTRYNAME,buff,res->search_country) || 00208 compare_info(lcid,LOCALE_SABBREVCTRYNAME,buff,res->search_country) || 00209 compare_info(lcid,LOCALE_SENGCOUNTRY,buff,res->search_country)) 00210 { 00211 TRACE("Found country:%s->%s\n", res->search_country, buff); 00212 flags |= FOUND_COUNTRY; 00213 memcpy(res->found_country,res->search_country,MAX_ELEM_LEN); 00214 } 00215 else if (res->match_flags & FOUND_COUNTRY) 00216 { 00217 return CONTINUE_LOOKING; 00218 } 00219 00220 /* Check codepage */ 00221 if (compare_info(lcid,LOCALE_IDEFAULTCODEPAGE,buff,res->search_codepage) || 00222 (compare_info(lcid,LOCALE_IDEFAULTANSICODEPAGE,buff,res->search_codepage))) 00223 { 00224 TRACE("Found codepage:%s->%s\n", res->search_codepage, buff); 00225 flags |= FOUND_CODEPAGE; 00226 memcpy(res->found_codepage,res->search_codepage,MAX_ELEM_LEN); 00227 } 00228 else if (res->match_flags & FOUND_CODEPAGE) 00229 { 00230 return CONTINUE_LOOKING; 00231 } 00232 00233 if (flags > res->match_flags) 00234 { 00235 /* Found a better match than previously */ 00236 res->match_flags = flags; 00237 res->found_lang_id = LangID; 00238 } 00239 if ((flags & (FOUND_LANGUAGE | FOUND_COUNTRY | FOUND_CODEPAGE)) == 00240 (FOUND_LANGUAGE | FOUND_COUNTRY | FOUND_CODEPAGE)) 00241 { 00242 TRACE(":found exact locale match\n"); 00243 return STOP_LOOKING; 00244 } 00245 return CONTINUE_LOOKING; 00246 } 00247 00248 /* Internal: Find the LCID for a locale specification */ 00249 static LCID MSVCRT_locale_to_LCID(locale_search_t* locale) 00250 { 00251 LCID lcid; 00252 EnumResourceLanguagesA(GetModuleHandleA("KERNEL32"), (LPSTR)RT_STRING, 00253 (LPCSTR)LOCALE_ILANGUAGE,find_best_locale_proc, 00254 (LONG_PTR)locale); 00255 00256 if (!locale->match_flags) 00257 return 0; 00258 00259 /* If we were given something that didn't match, fail */ 00260 if (locale->search_country[0] && !(locale->match_flags & FOUND_COUNTRY)) 00261 return 0; 00262 00263 lcid = MAKELCID(locale->found_lang_id, SORT_DEFAULT); 00264 00265 /* Populate partial locale, translating LCID to locale string elements */ 00266 if (!locale->found_codepage[0]) 00267 { 00268 /* Even if a codepage is not enumerated for a locale 00269 * it can be set if valid */ 00270 if (locale->search_codepage[0]) 00271 { 00272 if (IsValidCodePage(atoi(locale->search_codepage))) 00273 memcpy(locale->found_codepage,locale->search_codepage,MAX_ELEM_LEN); 00274 else 00275 { 00276 /* Special codepage values: OEM & ANSI */ 00277 if (_stricmp(locale->search_codepage,"OCP")) 00278 { 00279 GetLocaleInfoA(lcid, LOCALE_IDEFAULTCODEPAGE, 00280 locale->found_codepage, MAX_ELEM_LEN); 00281 } 00282 if (_stricmp(locale->search_codepage,"ACP")) 00283 { 00284 GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE, 00285 locale->found_codepage, MAX_ELEM_LEN); 00286 } 00287 else 00288 return 0; 00289 00290 if (!atoi(locale->found_codepage)) 00291 return 0; 00292 } 00293 } 00294 else 00295 { 00296 /* Prefer ANSI codepages if present */ 00297 GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE, 00298 locale->found_codepage, MAX_ELEM_LEN); 00299 if (!locale->found_codepage[0] || !atoi(locale->found_codepage)) 00300 GetLocaleInfoA(lcid, LOCALE_IDEFAULTCODEPAGE, 00301 locale->found_codepage, MAX_ELEM_LEN); 00302 } 00303 } 00304 GetLocaleInfoA(lcid, LOCALE_SENGLANGUAGE|LOCALE_NOUSEROVERRIDE, 00305 locale->found_language, MAX_ELEM_LEN); 00306 GetLocaleInfoA(lcid, LOCALE_SENGCOUNTRY|LOCALE_NOUSEROVERRIDE, 00307 locale->found_country, MAX_ELEM_LEN); 00308 return lcid; 00309 } 00310 00311 /* INTERNAL: Set ctype behaviour for a codepage */ 00312 static void msvcrt_set_ctype(unsigned int codepage, LCID lcid) 00313 { 00314 CPINFO cp; 00315 00316 memset(&cp, 0, sizeof(CPINFO)); 00317 00318 if (GetCPInfo(codepage, &cp)) 00319 { 00320 int i; 00321 char str[3]; 00322 unsigned char *traverse = cp.LeadByte; 00323 00324 memset(MSVCRT_current_ctype, 0, sizeof(MSVCRT__ctype)); 00325 MSVCRT___lc_codepage = codepage; 00326 MSVCRT___lc_collate_cp = codepage; 00327 00328 /* Switch ctype macros to MBCS if needed */ 00329 __mb_cur_max = cp.MaxCharSize; 00330 00331 /* Set remaining ctype flags: FIXME: faster way to do this? */ 00332 str[1] = str[2] = 0; 00333 for (i = 0; i < 256; i++) 00334 { 00335 if (!(MSVCRT__pctype[i] & MSVCRT_LEADBYTE)) 00336 { 00337 str[0] = i; 00338 GetStringTypeA(lcid, CT_CTYPE1, str, 1, MSVCRT__pctype + i); 00339 } 00340 } 00341 00342 /* Set leadbyte flags */ 00343 while (traverse[0] || traverse[1]) 00344 { 00345 for( i = traverse[0]; i <= traverse[1]; i++ ) 00346 MSVCRT_current_ctype[i+1] |= MSVCRT_LEADBYTE; 00347 traverse += 2; 00348 }; 00349 } 00350 } 00351 00352 00353 /* 00354 * @implemented 00355 */ 00356 char *setlocale(int category, const char *locale) 00357 { 00358 LCID lcid = 0; 00359 locale_search_t lc; 00360 int haveLang, haveCountry, haveCP; 00361 char* next; 00362 int lc_all = 0; 00363 00364 TRACE("(%d %s)\n",category,locale); 00365 00366 if (category < MSVCRT_LC_MIN || category > MSVCRT_LC_MAX) 00367 return NULL; 00368 00369 if (locale == NULL) 00370 { 00371 /* Report the current Locale */ 00372 return MSVCRT_current_lc_all; 00373 } 00374 00375 LOCK_LOCALE; 00376 00377 if (locale[0] == 'L' && locale[1] == 'C' && locale[2] == '_') 00378 { 00379 WARN(":restore previous locale not implemented!\n"); 00380 /* FIXME: Easiest way to do this is parse the string and 00381 * call this function recursively with its elements, 00382 * Where they differ for each lc_ type. 00383 */ 00384 UNLOCK_LOCALE; 00385 return MSVCRT_current_lc_all; 00386 } 00387 00388 /* Default Locale: Special case handling */ 00389 if (!strlen(locale) || ((toupper(locale[0]) == 'C') && !locale[1])) 00390 { 00391 MSVCRT_current_lc_all[0] = 'C'; 00392 MSVCRT_current_lc_all[1] = '\0'; 00393 MSVCRT___lc_codepage = GetACP(); 00394 MSVCRT___lc_collate_cp = GetACP(); 00395 00396 switch (category) { 00397 case MSVCRT_LC_ALL: 00398 lc_all = 1; /* Fall through all cases ... */ 00399 case MSVCRT_LC_COLLATE: 00400 if (!lc_all) break; 00401 case MSVCRT_LC_CTYPE: 00402 /* Restore C locale ctype info */ 00403 __mb_cur_max = 1; 00404 memcpy(MSVCRT_current_ctype, MSVCRT__ctype, sizeof(MSVCRT__ctype)); 00405 if (!lc_all) break; 00406 case MSVCRT_LC_MONETARY: 00407 if (!lc_all) break; 00408 case MSVCRT_LC_NUMERIC: 00409 if (!lc_all) break; 00410 case MSVCRT_LC_TIME: 00411 break; 00412 } 00413 UNLOCK_LOCALE; 00414 return MSVCRT_current_lc_all; 00415 } 00416 00417 /* Get locale elements */ 00418 haveLang = haveCountry = haveCP = 0; 00419 memset(&lc,0,sizeof(lc)); 00420 00421 next = strchr(locale,'_'); 00422 if (next && next != locale) 00423 { 00424 haveLang = 1; 00425 memcpy(lc.search_language,locale,next-locale); 00426 locale += next-locale+1; 00427 } 00428 00429 next = strchr(locale,'.'); 00430 if (next) 00431 { 00432 haveCP = 1; 00433 if (next == locale) 00434 { 00435 locale++; 00436 lstrcpynA(lc.search_codepage, locale, MAX_ELEM_LEN); 00437 } 00438 else 00439 { 00440 if (haveLang) 00441 { 00442 haveCountry = 1; 00443 memcpy(lc.search_country,locale,next-locale); 00444 locale += next-locale+1; 00445 } 00446 else 00447 { 00448 haveLang = 1; 00449 memcpy(lc.search_language,locale,next-locale); 00450 locale += next-locale+1; 00451 } 00452 lstrcpynA(lc.search_codepage, locale, MAX_ELEM_LEN); 00453 } 00454 } 00455 else 00456 { 00457 if (haveLang) 00458 { 00459 haveCountry = 1; 00460 lstrcpynA(lc.search_country, locale, MAX_ELEM_LEN); 00461 } 00462 else 00463 { 00464 haveLang = 1; 00465 lstrcpynA(lc.search_language, locale, MAX_ELEM_LEN); 00466 } 00467 } 00468 00469 if (haveCountry) 00470 remap_synonym(lc.search_country); 00471 00472 if (haveCP && !haveCountry && !haveLang) 00473 { 00474 ERR(":Codepage only locale not implemented\n"); 00475 /* FIXME: Use default lang/country and skip locale_to_LCID() 00476 * call below... 00477 */ 00478 UNLOCK_LOCALE; 00479 return NULL; 00480 } 00481 00482 lcid = MSVCRT_locale_to_LCID(&lc); 00483 00484 TRACE(":found LCID %d\n",lcid); 00485 00486 if (lcid == 0) 00487 { 00488 UNLOCK_LOCALE; 00489 return NULL; 00490 } 00491 00492 MSVCRT_current_lc_all_lcid = lcid; 00493 00494 _snprintf(MSVCRT_current_lc_all,MAX_LOCALE_LENGTH,"%s_%s.%s", 00495 lc.found_language,lc.found_country,lc.found_codepage); 00496 00497 switch (category) { 00498 case MSVCRT_LC_ALL: 00499 lc_all = 1; /* Fall through all cases ... */ 00500 case MSVCRT_LC_COLLATE: 00501 if (!lc_all) break; 00502 case MSVCRT_LC_CTYPE: 00503 msvcrt_set_ctype(atoi(lc.found_codepage),lcid); 00504 if (!lc_all) break; 00505 case MSVCRT_LC_MONETARY: 00506 if (!lc_all) break; 00507 case MSVCRT_LC_NUMERIC: 00508 if (!lc_all) break; 00509 case MSVCRT_LC_TIME: 00510 break; 00511 } 00512 UNLOCK_LOCALE; 00513 return MSVCRT_current_lc_all; 00514 } 00515 00516 /* 00517 * @unimplemented 00518 */ 00519 wchar_t* _wsetlocale(int category, const wchar_t* locale) 00520 { 00521 static wchar_t fake[] = { 00522 'E','n','g','l','i','s','h','_','U','n','i','t','e','d',' ', 00523 'S','t','a','t','e','s','.','1','2','5','2',0 }; 00524 00525 TRACE("%d %S\n", category, locale); 00526 00527 return fake; 00528 } 00529 00530 /* 00531 00532 locale "lang[_country[.code_page]]" 00533 | ".code_page" 00534 | "" 00535 | NULL 00536 00537 */ 00538 int parse_locale(const char *locale, char *lang, char *country, char *code_page) 00539 { 00540 while ( *locale != 0 && *locale != '.' && *locale != '_' ) 00541 { 00542 *lang = *locale; 00543 lang++; 00544 locale++; 00545 } 00546 *lang = 0; 00547 if ( *locale == '_' ) { 00548 locale++; 00549 while ( *locale != 0 && *locale != '.' ) 00550 { 00551 *country = *locale; 00552 country++; 00553 locale++; 00554 } 00555 } 00556 *country = 0; 00557 00558 00559 if ( *locale == '.' ) { 00560 locale++; 00561 while ( *locale != 0 && *locale != '.' ) 00562 { 00563 *code_page = *locale; 00564 code_page++; 00565 locale++; 00566 } 00567 } 00568 00569 *code_page = 0; 00570 return 0; 00571 } 00572 00573 const struct map_lcid2str { 00574 short langid; 00575 const char *langname; 00576 const char *country; 00577 } languages[]={ 00578 {0x0409,"English", "United States"}, 00579 {0x0809,"English", "United Kingdom"}, 00580 {0x0000,"Unknown", "Unknown"} 00581 00582 }; 00583 00584 const struct map_cntr { 00585 const char *abrev; 00586 const char *country; 00587 } abrev[] = { 00588 {"britain", "united kingdom"}, 00589 {"england", "united kingdom"}, 00590 {"gbr", "united kingdom"}, 00591 {"great britain", "united kingdom"}, 00592 {"uk", "united kingdom"}, 00593 {"united kingdom", "united kingdom"}, 00594 {"united-kingdom", "united kingdom"}, 00595 {"america", "united states" }, 00596 {"united states", "united states"}, 00597 {"united-states", "united states"}, 00598 {"us", "united states"}, 00599 {"usa", "united states"} 00600 }; 00601 00602 00603 struct lconv _lconv = { 00604 ".", // decimal_point 00605 ",", // thousands_sep 00606 "", // grouping; 00607 "DOL", // int_curr_symbol 00608 "$", // currency_symbol 00609 ".", // mon_decimal_point 00610 ",", // mon_thousands_sep 00611 "", // mon_grouping; 00612 "+", // positive_sign 00613 "-", // negative_sign 00614 127, // int_frac_digits 00615 127, // frac_digits 00616 127, // p_cs_precedes 00617 127, // p_sep_by_space 00618 127, // n_cs_precedes 00619 127, // n_sep_by_space 00620 127, // p_sign_posn; 00621 127 // n_sign_posn; 00622 }; 00623 00624 /* 00625 * @implemented 00626 */ 00627 struct lconv *localeconv(void) 00628 { 00629 return (struct lconv *) &_lconv; 00630 } 00631 00632 /********************************************************************* 00633 * _setmbcp (MSVCRT.@) 00634 * @implemented 00635 */ 00636 int CDECL _setmbcp(int cp) 00637 { 00638 int newcp; 00639 CPINFO cpi; 00640 BYTE *bytes; 00641 WORD chartypes[256]; 00642 WORD *curr_type; 00643 char bufA[256]; 00644 WCHAR bufW[256]; 00645 int charcount; 00646 int ret; 00647 int i; 00648 00649 TRACE("_setmbcp %d\n",cp); 00650 switch (cp) 00651 { 00652 case _MB_CP_ANSI: 00653 newcp = GetACP(); 00654 break; 00655 case _MB_CP_OEM: 00656 newcp = GetOEMCP(); 00657 break; 00658 case _MB_CP_LOCALE: 00659 newcp = MSVCRT___lc_codepage; 00660 break; 00661 case _MB_CP_SBCS: 00662 newcp = 20127; /* ASCII */ 00663 break; 00664 default: 00665 newcp = cp; 00666 break; 00667 } 00668 00669 if (!GetCPInfo(newcp, &cpi)) 00670 { 00671 ERR("Codepage %d not found\n", newcp); 00672 _set_errno(EINVAL); 00673 return -1; 00674 } 00675 00676 /* setup the _mbctype */ 00677 memset(_mbctype, 0, sizeof(_mbctype)); 00678 00679 bytes = cpi.LeadByte; 00680 while (bytes[0] || bytes[1]) 00681 { 00682 for (i = bytes[0]; i <= bytes[1]; i++) 00683 _mbctype[i + 1] |= _M1; 00684 bytes += 2; 00685 } 00686 00687 if (cpi.MaxCharSize > 1) 00688 { 00689 /* trail bytes not available through kernel32 but stored in a structure in msvcrt */ 00690 struct cp_extra_info_t *cpextra = g_cpextrainfo; 00691 00692 g_mbcp_is_multibyte = 1; 00693 while (TRUE) 00694 { 00695 if (cpextra->cp == 0 || cpextra->cp == newcp) 00696 { 00697 if (cpextra->cp == 0) 00698 ERR("trail bytes data not available for DBCS codepage %d - assuming all bytes\n", newcp); 00699 00700 bytes = cpextra->TrailBytes; 00701 while (bytes[0] || bytes[1]) 00702 { 00703 for (i = bytes[0]; i <= bytes[1]; i++) 00704 _mbctype[i + 1] |= _M2; 00705 bytes += 2; 00706 } 00707 break; 00708 } 00709 cpextra++; 00710 } 00711 } 00712 else 00713 g_mbcp_is_multibyte = 0; 00714 00715 /* we can't use GetStringTypeA directly because we don't have a locale - only a code page 00716 */ 00717 charcount = 0; 00718 for (i = 0; i < 256; i++) 00719 if (!(_mbctype[i + 1] & _M1)) 00720 bufA[charcount++] = i; 00721 00722 ret = MultiByteToWideChar(newcp, 0, bufA, charcount, bufW, charcount); 00723 if (ret != charcount) 00724 ERR("MultiByteToWideChar of chars failed for cp %d, ret=%d (exp %d), error=%d\n", newcp, ret, charcount, GetLastError()); 00725 00726 GetStringTypeW(CT_CTYPE1, bufW, charcount, chartypes); 00727 00728 curr_type = chartypes; 00729 for (i = 0; i < 256; i++) 00730 if (!(_mbctype[i + 1] & _M1)) 00731 { 00732 if ((*curr_type) & C1_UPPER) 00733 _mbctype[i + 1] |= _SBUP; 00734 if ((*curr_type) & C1_LOWER) 00735 _mbctype[i + 1] |= _SBLOW; 00736 curr_type++; 00737 } 00738 00739 if (newcp == 932) /* CP932 only - set _MP and _MS */ 00740 { 00741 /* On Windows it's possible to calculate the _MP and _MS from CT_CTYPE1 00742 * and CT_CTYPE3. But as of Wine 0.9.43 we return wrong values what makes 00743 * it hard. As this is set only for codepage 932 we hardcode it what gives 00744 * also faster execution. 00745 */ 00746 for (i = 161; i <= 165; i++) 00747 _mbctype[i + 1] |= _MP; 00748 for (i = 166; i <= 223; i++) 00749 _mbctype[i + 1] |= _MS; 00750 } 00751 00752 MSVCRT___lc_collate_cp = MSVCRT___lc_codepage = newcp; 00753 TRACE("(%d) -> %d\n", cp, MSVCRT___lc_codepage); 00754 return 0; 00755 } 00756 00757 00758 /********************************************************************* 00759 * ___lc_handle_func (MSVCRT.@) 00760 */ 00761 HANDLE * CDECL ___lc_handle_func(void) 00762 { 00763 return MSVCRT___lc_handle; 00764 } 00765 00766 00767 /********************************************************************* 00768 * ___lc_codepage_func (MSVCRT.@) 00769 */ 00770 int CDECL ___lc_codepage_func(void) 00771 { 00772 return MSVCRT___lc_codepage; 00773 } 00774 00775 00776 /********************************************************************* 00777 * _Gettnames (MSVCRT.@) 00778 */ 00779 void *_Gettnames(void) 00780 { 00781 FIXME("(void), stub!\n"); 00782 return NULL; 00783 } 00784 00785 /********************************************************************* 00786 * __lconv_init (MSVCRT.@) 00787 */ 00788 void __lconv_init(void) 00789 { 00790 char Char = (char) UCHAR_MAX; 00791 00792 TRACE("__lconv_init()\n"); 00793 00794 _lconv.int_frac_digits = Char; 00795 _lconv.frac_digits = Char; 00796 _lconv.p_sep_by_space = _lconv.n_sep_by_space = Char; 00797 _lconv.p_cs_precedes = _lconv.n_cs_precedes = Char; 00798 _lconv.p_sign_posn = _lconv.n_sign_posn = Char; 00799 } 00800 00801 00802 /********************************************************************* 00803 * _Strftime (MSVCRT.@) 00804 */ 00805 const char* _Strftime(char *out, unsigned int len, const char *fmt, 00806 const void *tm, void *foo) 00807 { 00808 /* FIXME: */ 00809 FIXME("(%p %d %s %p %p) stub\n", out, len, fmt, tm, foo); 00810 return ""; 00811 } 00812 00813 00814 /********************************************************************* 00815 * _Getdays (MSVCRT.@) 00816 */ 00817 const char* _Getdays(void) 00818 { 00819 static const char *MSVCRT_days = ":Sun:Sunday:Mon:Monday:Tue:Tuesday:Wed:" 00820 "Wednesday:Thu:Thursday:Fri:Friday:Sat:Saturday"; 00821 /* FIXME: Use locale */ 00822 FIXME("(void) semi-stub\n"); 00823 return MSVCRT_days; 00824 } 00825 00826 /********************************************************************* 00827 * _Getmonths (MSVCRT.@) 00828 */ 00829 const char* _Getmonths(void) 00830 { 00831 static const char *MSVCRT_months = ":Jan:January:Feb:February:Mar:March:Apr:" 00832 "April:May:May:Jun:June:Jul:July:Aug:August:Sep:September:Oct:" 00833 "October:Nov:November:Dec:December"; 00834 /* FIXME: Use locale */ 00835 FIXME("(void) semi-stub\n"); 00836 return MSVCRT_months; 00837 } 00838 00839 /********************************************************************* 00840 * __crtLCMapStringA (MSVCRT.@) 00841 */ 00842 int __crtLCMapStringA( 00843 LCID lcid, DWORD mapflags, const char* src, int srclen, char* dst, 00844 int dstlen, unsigned int codepage, int xflag 00845 ) { 00846 TRACE("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n", 00847 lcid,mapflags,src,srclen,dst,dstlen,codepage,xflag); 00848 /* FIXME: A bit incorrect. But msvcrt itself just converts its 00849 * arguments to wide strings and then calls LCMapStringW 00850 */ 00851 return LCMapStringA(lcid,mapflags,src,srclen,dst,dstlen); 00852 } 00853 00854 /********************************************************************* 00855 * __crtLCMapStringW (MSVCRT.@) 00856 */ 00857 int __crtLCMapStringW( 00858 LCID lcid, DWORD mapflags, LPCWSTR src, int srclen, LPWSTR dst, 00859 int dstlen, unsigned int codepage, int xflag 00860 ) { 00861 TRACE("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n", 00862 lcid,mapflags,src,srclen,dst,dstlen,codepage,xflag); 00863 00864 return LCMapStringW(lcid,mapflags,src,srclen,dst,dstlen); 00865 } 00866 00867 int CDECL _getmbcp(void) 00868 { 00869 return MSVCRT___lc_codepage; 00870 } 00871 00872 /********************************************************************* 00873 * ___unguarded_readlc_active_add_func (MSVCRT.@) 00874 */ 00875 unsigned int * CDECL ___unguarded_readlc_active_add_func(void) 00876 { 00877 return &__unguarded_readlc_active; 00878 } 00879 00880 /********************************************************************* 00881 * ___setlc_active_func (MSVCRT.@) 00882 */ 00883 unsigned int CDECL ___setlc_active_func(void) 00884 { 00885 return __setlc_active; 00886 } 00887 00888 /********************************************************************* 00889 * __crtGetStringTypeW(MSVCRT.@) 00890 * 00891 * This function was accepting different number of arguments in older 00892 * versions of msvcrt. 00893 */ 00894 BOOL CDECL __crtGetStringTypeW(DWORD unk, DWORD type, 00895 wchar_t *buffer, int len, WORD *out) 00896 { 00897 FIXME("(unk %x, type %x, wstr %p(%d), %p) partial stub\n", 00898 unk, type, buffer, len, out); 00899 00900 return GetStringTypeW(type, buffer, len, out); 00901 } Generated on Sun May 27 2012 04:18:12 for ReactOS by
1.7.6.1
|