2 * Some stuff takem from wine msvcrt\locale.c
4 * Copyright 2000 Jon Griffiths
13 #define _SETLOCALE_LOCK 19
16 #define MSVCRT_LC_ALL 0
17 #define MSVCRT_LC_COLLATE 1
18 #define MSVCRT_LC_CTYPE 2
19 #define MSVCRT_LC_MONETARY 3
20 #define MSVCRT_LC_NUMERIC 4
21 #define MSVCRT_LC_TIME 5
22 #define MSVCRT_LC_MIN MSVCRT_LC_ALL
23 #define MSVCRT_LC_MAX MSVCRT_LC_TIME
25 /* FIXME: Need to hold locale for each LC_* type and aggregate
26 * string to produce lc_all.
28 #define MAX_ELEM_LEN 64 /* Max length of country/language/CP string */
30 unsigned char MSVCRT_mbctype
[257] = { 0 };
31 static int g_mbcp_is_multibyte
= 0;
33 /* It seems that the data about valid trail bytes is not available from kernel32
34 * so we have to store is here. The format is the same as for lead bytes in CPINFO */
35 struct cp_extra_info_t
38 BYTE TrailBytes
[MAX_LEADBYTES
];
41 static struct cp_extra_info_t g_cpextrainfo
[] =
43 {932, {0x40, 0x7e, 0x80, 0xfc, 0, 0}},
44 {936, {0x40, 0xfe, 0, 0}},
45 {949, {0x41, 0xfe, 0, 0}},
46 {950, {0x40, 0x7e, 0xa1, 0xfe, 0, 0}},
47 {20932, {1, 255, 0, 0}}, /* seems to give different results on different systems */
48 {0, {1, 255, 0, 0}} /* match all with FIXME */
52 char MSVCRT_current_lc_all
[MAX_LOCALE_LENGTH
] = { 0 };
53 LCID MSVCRT_current_lc_all_lcid
= 0;
54 int MSVCRT___lc_codepage
= 0;
55 int MSVCRT___lc_collate_cp
= 0;
56 HANDLE MSVCRT___lc_handle
[MSVCRT_LC_MAX
- MSVCRT_LC_MIN
+ 1] = { 0 };
59 #define LOCK_LOCALE _mlock(_SETLOCALE_LOCK);
60 #define UNLOCK_LOCALE _munlock(_SETLOCALE_LOCK);
62 #define MSVCRT_LEADBYTE 0x8000
65 char search_language
[MAX_ELEM_LEN
];
66 char search_country
[MAX_ELEM_LEN
];
67 char search_codepage
[MAX_ELEM_LEN
];
68 char found_language
[MAX_ELEM_LEN
];
69 char found_country
[MAX_ELEM_LEN
];
70 char found_codepage
[MAX_ELEM_LEN
];
71 unsigned int match_flags
;
75 unsigned int __setlc_active
;
76 unsigned int __unguarded_readlc_active
;
77 int _current_category
; /* used by setlocale */
78 const char *_current_locale
;
81 int parse_locale(const char *locale
, char *lang
, char *country
, char *code_page
);
91 WORD MSVCRT__ctype
[257] = {
92 0, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _S_
|_C_
, _S_
|_C_
,
93 _S_
|_C_
, _S_
|_C_
, _S_
|_C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
,
94 _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _S_
|_BLANK
,
95 _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
,
96 _P_
, _D_
|_H_
, _D_
|_H_
, _D_
|_H_
, _D_
|_H_
, _D_
|_H_
, _D_
|_H_
, _D_
|_H_
,
97 _D_
|_H_
, _D_
|_H_
, _D_
|_H_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _U_
|_H_
,
98 _U_
|_H_
, _U_
|_H_
, _U_
|_H_
, _U_
|_H_
, _U_
|_H_
, _U_
, _U_
, _U_
, _U_
, _U_
,
99 _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
,
100 _U_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _L_
|_H_
, _L_
|_H_
, _L_
|_H_
, _L_
|_H_
,
101 _L_
|_H_
, _L_
|_H_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
,
102 _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _P_
, _P_
, _P_
, _P_
,
103 _C_
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
104 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
106 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
107 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
111 /* Internal: Current ctype table for locale */
112 WORD MSVCRT_current_ctype
[257];
114 /* pctype is used by macros in the Win32 headers. It must point
115 * To a table of flags exactly like ctype. To allow locale
116 * changes to affect ctypes (i.e. isleadbyte), we use a second table
117 * and update its flags whenever the current locale changes.
119 WORD
* MSVCRT__pctype
= MSVCRT_current_ctype
+ 1;
121 /* Friendly country strings & iso codes for synonym support.
122 * Based on MS documentation for setlocale().
124 static const char * const _country_synonyms
[] =
132 "United Kingdom","GB",
133 "United-Kingdom","GB",
136 "Great Britain","GB",
137 "United States","US",
138 "United-States","US",
142 /* Note: Flags are weighted in order of matching importance */
143 #define FOUND_LANGUAGE 0x4
144 #define FOUND_COUNTRY 0x2
145 #define FOUND_CODEPAGE 0x1
147 /* INTERNAL: Map a synonym to an ISO code */
148 static void remap_synonym(char *name
)
151 for (i
= 0; i
< sizeof(_country_synonyms
)/sizeof(char*); i
+= 2 )
153 if (!strcasecmp(_country_synonyms
[i
],name
))
155 TRACE(":Mapping synonym %s to %s\n",name
,_country_synonyms
[i
+1]);
156 name
[0] = _country_synonyms
[i
+1][0];
157 name
[1] = _country_synonyms
[i
+1][1];
164 #define CONTINUE_LOOKING TRUE
165 #define STOP_LOOKING FALSE
167 /* INTERNAL: Get and compare locale info with a given string */
168 static int compare_info(LCID lcid
, DWORD flags
, char* buff
, const char* cmp
)
171 GetLocaleInfoA(lcid
, flags
|LOCALE_NOUSEROVERRIDE
,buff
, MAX_ELEM_LEN
);
172 if (!buff
[0] || !cmp
[0])
174 /* Partial matches are allowed, e.g. "Germ" matches "Germany" */
175 return !strncasecmp(cmp
, buff
, strlen(cmp
));
180 find_best_locale_proc(HMODULE hModule
, LPCSTR type
, LPCSTR name
, WORD LangID
, LONG_PTR lParam
)
182 locale_search_t
*res
= (locale_search_t
*)lParam
;
183 const LCID lcid
= MAKELCID(LangID
, SORT_DEFAULT
);
184 char buff
[MAX_ELEM_LEN
];
185 unsigned int flags
= 0;
187 if(PRIMARYLANGID(LangID
) == LANG_NEUTRAL
)
188 return CONTINUE_LOOKING
;
191 if (compare_info(lcid
,LOCALE_SISO639LANGNAME
,buff
,res
->search_language
) ||
192 compare_info(lcid
,LOCALE_SABBREVLANGNAME
,buff
,res
->search_language
) ||
193 compare_info(lcid
,LOCALE_SENGLANGUAGE
,buff
,res
->search_language
))
195 TRACE(":Found language: %s->%s\n", res
->search_language
, buff
);
196 flags
|= FOUND_LANGUAGE
;
197 memcpy(res
->found_language
,res
->search_language
,MAX_ELEM_LEN
);
199 else if (res
->match_flags
& FOUND_LANGUAGE
)
201 return CONTINUE_LOOKING
;
205 if (compare_info(lcid
,LOCALE_SISO3166CTRYNAME
,buff
,res
->search_country
) ||
206 compare_info(lcid
,LOCALE_SABBREVCTRYNAME
,buff
,res
->search_country
) ||
207 compare_info(lcid
,LOCALE_SENGCOUNTRY
,buff
,res
->search_country
))
209 TRACE("Found country:%s->%s\n", res
->search_country
, buff
);
210 flags
|= FOUND_COUNTRY
;
211 memcpy(res
->found_country
,res
->search_country
,MAX_ELEM_LEN
);
213 else if (res
->match_flags
& FOUND_COUNTRY
)
215 return CONTINUE_LOOKING
;
219 if (compare_info(lcid
,LOCALE_IDEFAULTCODEPAGE
,buff
,res
->search_codepage
) ||
220 (compare_info(lcid
,LOCALE_IDEFAULTANSICODEPAGE
,buff
,res
->search_codepage
)))
222 TRACE("Found codepage:%s->%s\n", res
->search_codepage
, buff
);
223 flags
|= FOUND_CODEPAGE
;
224 memcpy(res
->found_codepage
,res
->search_codepage
,MAX_ELEM_LEN
);
226 else if (res
->match_flags
& FOUND_CODEPAGE
)
228 return CONTINUE_LOOKING
;
231 if (flags
> res
->match_flags
)
233 /* Found a better match than previously */
234 res
->match_flags
= flags
;
235 res
->found_lang_id
= LangID
;
237 if (flags
& (FOUND_LANGUAGE
& FOUND_COUNTRY
& FOUND_CODEPAGE
))
239 TRACE(":found exact locale match\n");
242 return CONTINUE_LOOKING
;
245 /* Internal: Find the LCID for a locale specification */
246 static LCID
MSVCRT_locale_to_LCID(locale_search_t
* locale
)
249 EnumResourceLanguagesA(GetModuleHandleA("KERNEL32"), (LPSTR
)RT_STRING
,
250 (LPCSTR
)LOCALE_ILANGUAGE
,find_best_locale_proc
,
253 if (!locale
->match_flags
)
256 /* If we were given something that didn't match, fail */
257 if (locale
->search_country
[0] && !(locale
->match_flags
& FOUND_COUNTRY
))
260 lcid
= MAKELCID(locale
->found_lang_id
, SORT_DEFAULT
);
262 /* Populate partial locale, translating LCID to locale string elements */
263 if (!locale
->found_codepage
[0])
265 /* Even if a codepage is not enumerated for a locale
266 * it can be set if valid */
267 if (locale
->search_codepage
[0])
269 if (IsValidCodePage(atoi(locale
->search_codepage
)))
270 memcpy(locale
->found_codepage
,locale
->search_codepage
,MAX_ELEM_LEN
);
273 /* Special codepage values: OEM & ANSI */
274 if (strcasecmp(locale
->search_codepage
,"OCP"))
276 GetLocaleInfoA(lcid
, LOCALE_IDEFAULTCODEPAGE
,
277 locale
->found_codepage
, MAX_ELEM_LEN
);
279 if (strcasecmp(locale
->search_codepage
,"ACP"))
281 GetLocaleInfoA(lcid
, LOCALE_IDEFAULTANSICODEPAGE
,
282 locale
->found_codepage
, MAX_ELEM_LEN
);
287 if (!atoi(locale
->found_codepage
))
293 /* Prefer ANSI codepages if present */
294 GetLocaleInfoA(lcid
, LOCALE_IDEFAULTANSICODEPAGE
,
295 locale
->found_codepage
, MAX_ELEM_LEN
);
296 if (!locale
->found_codepage
[0] || !atoi(locale
->found_codepage
))
297 GetLocaleInfoA(lcid
, LOCALE_IDEFAULTCODEPAGE
,
298 locale
->found_codepage
, MAX_ELEM_LEN
);
301 GetLocaleInfoA(lcid
, LOCALE_SENGLANGUAGE
|LOCALE_NOUSEROVERRIDE
,
302 locale
->found_language
, MAX_ELEM_LEN
);
303 GetLocaleInfoA(lcid
, LOCALE_SENGCOUNTRY
|LOCALE_NOUSEROVERRIDE
,
304 locale
->found_country
, MAX_ELEM_LEN
);
308 /* INTERNAL: Set ctype behaviour for a codepage */
309 static void msvcrt_set_ctype(unsigned int codepage
, LCID lcid
)
313 memset(&cp
, 0, sizeof(CPINFO
));
315 if (GetCPInfo(codepage
, &cp
))
319 unsigned char *traverse
= (unsigned char *)cp
.LeadByte
;
321 memset(MSVCRT_current_ctype
, 0, sizeof(MSVCRT__ctype
));
322 MSVCRT___lc_codepage
= codepage
;
323 MSVCRT___lc_collate_cp
= codepage
;
325 /* Switch ctype macros to MBCS if needed */
326 __mb_cur_max
= cp
.MaxCharSize
;
328 /* Set remaining ctype flags: FIXME: faster way to do this? */
330 for (i
= 0; i
< 256; i
++)
332 if (!(MSVCRT__pctype
[i
] & MSVCRT_LEADBYTE
))
335 GetStringTypeA(lcid
, CT_CTYPE1
, str
, 1, MSVCRT__pctype
+ i
);
339 /* Set leadbyte flags */
340 while (traverse
[0] || traverse
[1])
342 for( i
= traverse
[0]; i
<= traverse
[1]; i
++ )
343 MSVCRT_current_ctype
[i
+1] |= MSVCRT_LEADBYTE
;
353 char *setlocale(int category
, const char *locale
)
357 int haveLang
, haveCountry
, haveCP
;
361 TRACE("(%d %s)\n",category
,locale
);
363 if (category
< MSVCRT_LC_MIN
|| category
> MSVCRT_LC_MAX
)
368 /* Report the current Locale */
369 return MSVCRT_current_lc_all
;
374 if (locale
[0] == 'L' && locale
[1] == 'C' && locale
[2] == '_')
376 WARN(":restore previous locale not implemented!\n");
377 /* FIXME: Easiest way to do this is parse the string and
378 * call this function recursively with its elements,
379 * Where they differ for each lc_ type.
382 return MSVCRT_current_lc_all
;
385 /* Default Locale: Special case handling */
386 if (!strlen(locale
) || ((toupper(locale
[0]) == 'C') && !locale
[1]))
388 MSVCRT_current_lc_all
[0] = 'C';
389 MSVCRT_current_lc_all
[1] = '\0';
390 MSVCRT___lc_codepage
= 1252;
391 MSVCRT___lc_collate_cp
= 1252;
395 lc_all
= 1; /* Fall through all cases ... */
396 case MSVCRT_LC_COLLATE
:
398 case MSVCRT_LC_CTYPE
:
399 /* Restore C locale ctype info */
401 memcpy(MSVCRT_current_ctype
, MSVCRT__ctype
, sizeof(MSVCRT__ctype
));
403 case MSVCRT_LC_MONETARY
:
405 case MSVCRT_LC_NUMERIC
:
411 return MSVCRT_current_lc_all
;
414 /* Get locale elements */
415 haveLang
= haveCountry
= haveCP
= 0;
416 memset(&lc
,0,sizeof(lc
));
418 next
= strchr(locale
,'_');
419 if (next
&& next
!= locale
)
422 memcpy(lc
.search_language
,locale
,next
-locale
);
423 locale
+= next
-locale
+1;
426 next
= strchr(locale
,'.');
433 lstrcpynA(lc
.search_codepage
, locale
, MAX_ELEM_LEN
);
440 memcpy(lc
.search_country
,locale
,next
-locale
);
441 locale
+= next
-locale
+1;
446 memcpy(lc
.search_language
,locale
,next
-locale
);
447 locale
+= next
-locale
+1;
449 lstrcpynA(lc
.search_codepage
, locale
, MAX_ELEM_LEN
);
457 lstrcpynA(lc
.search_country
, locale
, MAX_ELEM_LEN
);
462 lstrcpynA(lc
.search_language
, locale
, MAX_ELEM_LEN
);
467 remap_synonym(lc
.search_country
);
469 if (haveCP
&& !haveCountry
&& !haveLang
)
471 ERR(":Codepage only locale not implemented\n");
472 /* FIXME: Use default lang/country and skip locale_to_LCID()
479 lcid
= MSVCRT_locale_to_LCID(&lc
);
481 TRACE(":found LCID %d\n",lcid
);
489 MSVCRT_current_lc_all_lcid
= lcid
;
491 _snprintf(MSVCRT_current_lc_all
,MAX_LOCALE_LENGTH
,"%s_%s.%s",
492 lc
.found_language
,lc
.found_country
,lc
.found_codepage
);
496 lc_all
= 1; /* Fall through all cases ... */
497 case MSVCRT_LC_COLLATE
:
499 case MSVCRT_LC_CTYPE
:
500 msvcrt_set_ctype(atoi(lc
.found_codepage
),lcid
);
502 case MSVCRT_LC_MONETARY
:
504 case MSVCRT_LC_NUMERIC
:
510 return MSVCRT_current_lc_all
;
516 wchar_t* _wsetlocale(int category
, const wchar_t* locale
)
518 static wchar_t fake
[] = {
519 'E','n','g','l','i','s','h','_','U','n','i','t','e','d',' ',
520 'S','t','a','t','e','s','.','1','2','5','2',0 };
522 TRACE("%d %S\n", category
, locale
);
529 locale "lang[_country[.code_page]]"
535 int parse_locale(const char *locale
, char *lang
, char *country
, char *code_page
)
537 while ( *locale
!= 0 && *locale
!= '.' && *locale
!= '_' )
544 if ( *locale
== '_' ) {
546 while ( *locale
!= 0 && *locale
!= '.' )
556 if ( *locale
== '.' ) {
558 while ( *locale
!= 0 && *locale
!= '.' )
560 *code_page
= *locale
;
570 const struct map_lcid2str
{
572 const char *langname
;
575 {0x0409,"English", "United States"},
576 {0x0809,"English", "United Kingdom"},
577 {0x0000,"Unknown", "Unknown"}
581 const struct map_cntr
{
585 {"britain", "united kingdom"},
586 {"england", "united kingdom"},
587 {"gbr", "united kingdom"},
588 {"great britain", "united kingdom"},
589 {"uk", "united kingdom"},
590 {"united kingdom", "united kingdom"},
591 {"united-kingdom", "united kingdom"},
592 {"america", "united states" },
593 {"united states", "united states"},
594 {"united-states", "united states"},
595 {"us", "united states"},
596 {"usa" "united states"}
600 struct lconv _lconv
= {
601 ".", // decimal_point
602 ",", // thousands_sep
604 "DOL", // int_curr_symbol
605 "$", // currency_symbol
606 ".", // mon_decimal_point
607 ",", // mon_thousands_sep
609 "+", // positive_sign
610 "-", // negative_sign
611 127, // int_frac_digits
613 127, // p_cs_precedes
614 127, // p_sep_by_space
615 127, // n_cs_precedes
616 127, // n_sep_by_space
624 struct lconv
*localeconv(void)
626 return (struct lconv
*) &_lconv
;
629 /*********************************************************************
630 * _setmbcp (MSVCRT.@)
633 int CDECL
_setmbcp(int cp
)
646 TRACE("_setmbcp %d\n",cp
);
656 newcp
= MSVCRT___lc_codepage
;
659 newcp
= 20127; /* ASCII */
666 if (!GetCPInfo(newcp
, &cpi
))
668 ERR("Codepage %d not found\n", newcp
);
673 /* setup the _mbctype */
674 memset(MSVCRT_mbctype
, 0, sizeof(MSVCRT_mbctype
));
676 bytes
= cpi
.LeadByte
;
677 while (bytes
[0] || bytes
[1])
679 for (i
= bytes
[0]; i
<= bytes
[1]; i
++)
680 MSVCRT_mbctype
[i
+ 1] |= _M1
;
684 if (cpi
.MaxCharSize
> 1)
686 /* trail bytes not available through kernel32 but stored in a structure in msvcrt */
687 struct cp_extra_info_t
*cpextra
= g_cpextrainfo
;
689 g_mbcp_is_multibyte
= 1;
692 if (cpextra
->cp
== 0 || cpextra
->cp
== newcp
)
694 if (cpextra
->cp
== 0)
695 ERR("trail bytes data not available for DBCS codepage %d - assuming all bytes\n", newcp
);
697 bytes
= cpextra
->TrailBytes
;
698 while (bytes
[0] || bytes
[1])
700 for (i
= bytes
[0]; i
<= bytes
[1]; i
++)
701 MSVCRT_mbctype
[i
+ 1] |= _M2
;
710 g_mbcp_is_multibyte
= 0;
712 /* we can't use GetStringTypeA directly because we don't have a locale - only a code page
715 for (i
= 0; i
< 256; i
++)
716 if (!(MSVCRT_mbctype
[i
+ 1] & _M1
))
717 bufA
[charcount
++] = i
;
719 ret
= MultiByteToWideChar(newcp
, 0, bufA
, charcount
, bufW
, charcount
);
720 if (ret
!= charcount
)
721 ERR("MultiByteToWideChar of chars failed for cp %d, ret=%d (exp %d), error=%d\n", newcp
, ret
, charcount
, GetLastError());
723 GetStringTypeW(CT_CTYPE1
, bufW
, charcount
, chartypes
);
725 curr_type
= chartypes
;
726 for (i
= 0; i
< 256; i
++)
727 if (!(MSVCRT_mbctype
[i
+ 1] & _M1
))
729 if ((*curr_type
) & C1_UPPER
)
730 MSVCRT_mbctype
[i
+ 1] |= _SBUP
;
731 if ((*curr_type
) & C1_LOWER
)
732 MSVCRT_mbctype
[i
+ 1] |= _SBLOW
;
736 if (newcp
== 932) /* CP932 only - set _MP and _MS */
738 /* On Windows it's possible to calculate the _MP and _MS from CT_CTYPE1
739 * and CT_CTYPE3. But as of Wine 0.9.43 we return wrong values what makes
740 * it hard. As this is set only for codepage 932 we hardcode it what gives
741 * also faster execution.
743 for (i
= 161; i
<= 165; i
++)
744 MSVCRT_mbctype
[i
+ 1] |= _MP
;
745 for (i
= 166; i
<= 223; i
++)
746 MSVCRT_mbctype
[i
+ 1] |= _MS
;
749 MSVCRT___lc_collate_cp
= MSVCRT___lc_codepage
= newcp
;
750 TRACE("(%d) -> %d\n", cp
, MSVCRT___lc_codepage
);
755 /*********************************************************************
756 * __lc_collate_cp (MSVCRT.@)
760 void __lc_collate_cp(int cp
)
762 FIXME("__lc_collate_cp - stub\n");
767 /*********************************************************************
768 * __lc_handle (MSVCRT.@)
772 void __lc_handle(void)
774 FIXME("__lc_handle - stub\n");
779 /*********************************************************************
780 * __lc_codepage (MSVCRT.@)
784 void __lc_codepage(void)
786 FIXME("__lc_codepage - stub\n");
791 /*********************************************************************
792 * _Gettnames (MSVCRT.@)
794 void *_Gettnames(void)
796 FIXME("(void), stub!\n");
800 /*********************************************************************
801 * __lconv_init (MSVCRT.@)
803 void __lconv_init(void)
809 /*********************************************************************
810 * _Strftime (MSVCRT.@)
812 const char* _Strftime(char *out
, unsigned int len
, const char *fmt
,
813 const void *tm
, void *foo
)
816 FIXME("(%p %d %s %p %p) stub\n", out
, len
, fmt
, tm
, foo
);
821 /*********************************************************************
822 * _Getdays (MSVCRT.@)
824 const char* _Getdays(void)
826 static const char *MSVCRT_days
= ":Sun:Sunday:Mon:Monday:Tue:Tuesday:Wed:"
827 "Wednesday:Thu:Thursday:Fri:Friday:Sat:Saturday";
828 /* FIXME: Use locale */
829 FIXME("(void) semi-stub\n");
833 /*********************************************************************
834 * _Getmonths (MSVCRT.@)
836 const char* _Getmonths(void)
838 static const char *MSVCRT_months
= ":Jan:January:Feb:February:Mar:March:Apr:"
839 "April:May:May:Jun:June:Jul:July:Aug:August:Sep:September:Oct:"
840 "October:Nov:November:Dec:December";
841 /* FIXME: Use locale */
842 FIXME("(void) semi-stub\n");
843 return MSVCRT_months
;
846 /*********************************************************************
847 * __crtLCMapStringA (MSVCRT.@)
849 int __crtLCMapStringA(
850 LCID lcid
, DWORD mapflags
, const char* src
, int srclen
, char* dst
,
851 int dstlen
, unsigned int codepage
, int xflag
853 TRACE("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n",
854 lcid
,mapflags
,src
,srclen
,dst
,dstlen
,codepage
,xflag
);
855 /* FIXME: A bit incorrect. But msvcrt itself just converts its
856 * arguments to wide strings and then calls LCMapStringW
858 return LCMapStringA(lcid
,mapflags
,src
,srclen
,dst
,dstlen
);
861 /*********************************************************************
862 * __crtLCMapStringW (MSVCRT.@)
864 int __crtLCMapStringW(
865 LCID lcid
, DWORD mapflags
, LPCWSTR src
, int srclen
, LPWSTR dst
,
866 int dstlen
, unsigned int codepage
, int xflag
868 TRACE("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n",
869 lcid
,mapflags
,src
,srclen
,dst
,dstlen
,codepage
,xflag
);
871 return LCMapStringW(lcid
,mapflags
,src
,srclen
,dst
,dstlen
);
874 int CDECL
_getmbcp(void)
876 return MSVCRT___lc_codepage
;
879 /*********************************************************************
880 * ___unguarded_readlc_active_add_func (MSVCRT.@)
882 unsigned int * CDECL
___unguarded_readlc_active_add_func(void)
884 return &__unguarded_readlc_active
;
887 /*********************************************************************
888 * ___setlc_active_func (MSVCRT.@)
890 unsigned int CDECL
___setlc_active_func(void)
892 return __setlc_active
;