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 */
29 #define MAX_LOCALE_LENGTH 256
31 unsigned char MSVCRT_mbctype
[257];
32 static int g_mbcp_is_multibyte
= 0;
34 /* It seems that the data about valid trail bytes is not available from kernel32
35 * so we have to store is here. The format is the same as for lead bytes in CPINFO */
36 struct cp_extra_info_t
39 BYTE TrailBytes
[MAX_LEADBYTES
];
42 static struct cp_extra_info_t g_cpextrainfo
[] =
44 {932, {0x40, 0x7e, 0x80, 0xfc, 0, 0}},
45 {936, {0x40, 0xfe, 0, 0}},
46 {949, {0x41, 0xfe, 0, 0}},
47 {950, {0x40, 0x7e, 0xa1, 0xfe, 0, 0}},
48 {20932, {1, 255, 0, 0}}, /* seems to give different results on different systems */
49 {0, {1, 255, 0, 0}} /* match all with FIXME */
53 char MSVCRT_current_lc_all
[MAX_LOCALE_LENGTH
];
54 LCID MSVCRT_current_lc_all_lcid
;
55 int MSVCRT___lc_codepage
;
56 int MSVCRT___lc_collate_cp
;
57 HANDLE MSVCRT___lc_handle
[MSVCRT_LC_MAX
- MSVCRT_LC_MIN
+ 1];
60 #define LOCK_LOCALE _mlock(_SETLOCALE_LOCK);
61 #define UNLOCK_LOCALE _munlock(_SETLOCALE_LOCK);
63 #define MSVCRT_LEADBYTE 0x8000
66 char search_language
[MAX_ELEM_LEN
];
67 char search_country
[MAX_ELEM_LEN
];
68 char search_codepage
[MAX_ELEM_LEN
];
69 char found_language
[MAX_ELEM_LEN
];
70 char found_country
[MAX_ELEM_LEN
];
71 char found_codepage
[MAX_ELEM_LEN
];
72 unsigned int match_flags
;
76 unsigned int __setlc_active
;
77 unsigned int __unguarded_readlc_active
;
78 int _current_category
; /* used by setlocale */
79 const char *_current_locale
;
82 int parse_locale(const char *locale
, char *lang
, char *country
, char *code_page
);
92 WORD MSVCRT__ctype
[257] = {
93 0, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _S_
|_C_
, _S_
|_C_
,
94 _S_
|_C_
, _S_
|_C_
, _S_
|_C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
,
95 _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _S_
|_BLANK
,
96 _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
,
97 _P_
, _D_
|_H_
, _D_
|_H_
, _D_
|_H_
, _D_
|_H_
, _D_
|_H_
, _D_
|_H_
, _D_
|_H_
,
98 _D_
|_H_
, _D_
|_H_
, _D_
|_H_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _U_
|_H_
,
99 _U_
|_H_
, _U_
|_H_
, _U_
|_H_
, _U_
|_H_
, _U_
|_H_
, _U_
, _U_
, _U_
, _U_
, _U_
,
100 _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
,
101 _U_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _L_
|_H_
, _L_
|_H_
, _L_
|_H_
, _L_
|_H_
,
102 _L_
|_H_
, _L_
|_H_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
,
103 _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _P_
, _P_
, _P_
, _P_
,
104 _C_
, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
112 /* Internal: Current ctype table for locale */
113 WORD MSVCRT_current_ctype
[257];
115 /* pctype is used by macros in the Win32 headers. It must point
116 * To a table of flags exactly like ctype. To allow locale
117 * changes to affect ctypes (i.e. isleadbyte), we use a second table
118 * and update its flags whenever the current locale changes.
120 WORD
* MSVCRT__pctype
= MSVCRT_current_ctype
+ 1;
122 /* Friendly country strings & iso codes for synonym support.
123 * Based on MS documentation for setlocale().
125 static const char * const _country_synonyms
[] =
133 "United Kingdom","GB",
134 "United-Kingdom","GB",
137 "Great Britain","GB",
138 "United States","US",
139 "United-States","US",
143 /* Note: Flags are weighted in order of matching importance */
144 #define FOUND_LANGUAGE 0x4
145 #define FOUND_COUNTRY 0x2
146 #define FOUND_CODEPAGE 0x1
148 /* INTERNAL: Map a synonym to an ISO code */
149 static void remap_synonym(char *name
)
152 for (i
= 0; i
< sizeof(_country_synonyms
)/sizeof(char*); i
+= 2 )
154 if (!strcasecmp(_country_synonyms
[i
],name
))
156 TRACE(":Mapping synonym %s to %s\n",name
,_country_synonyms
[i
+1]);
157 name
[0] = _country_synonyms
[i
+1][0];
158 name
[1] = _country_synonyms
[i
+1][1];
165 #define CONTINUE_LOOKING TRUE
166 #define STOP_LOOKING FALSE
168 /* INTERNAL: Get and compare locale info with a given string */
169 static int compare_info(LCID lcid
, DWORD flags
, char* buff
, const char* cmp
)
172 GetLocaleInfoA(lcid
, flags
|LOCALE_NOUSEROVERRIDE
,buff
, MAX_ELEM_LEN
);
173 if (!buff
[0] || !cmp
[0])
175 /* Partial matches are allowed, e.g. "Germ" matches "Germany" */
176 return !strncasecmp(cmp
, buff
, strlen(cmp
));
181 find_best_locale_proc(HMODULE hModule
, LPCSTR type
, LPCSTR name
, WORD LangID
, LONG_PTR lParam
)
183 locale_search_t
*res
= (locale_search_t
*)lParam
;
184 const LCID lcid
= MAKELCID(LangID
, SORT_DEFAULT
);
185 char buff
[MAX_ELEM_LEN
];
186 unsigned int flags
= 0;
188 if(PRIMARYLANGID(LangID
) == LANG_NEUTRAL
)
189 return CONTINUE_LOOKING
;
192 if (compare_info(lcid
,LOCALE_SISO639LANGNAME
,buff
,res
->search_language
) ||
193 compare_info(lcid
,LOCALE_SABBREVLANGNAME
,buff
,res
->search_language
) ||
194 compare_info(lcid
,LOCALE_SENGLANGUAGE
,buff
,res
->search_language
))
196 TRACE(":Found language: %s->%s\n", res
->search_language
, buff
);
197 flags
|= FOUND_LANGUAGE
;
198 memcpy(res
->found_language
,res
->search_language
,MAX_ELEM_LEN
);
200 else if (res
->match_flags
& FOUND_LANGUAGE
)
202 return CONTINUE_LOOKING
;
206 if (compare_info(lcid
,LOCALE_SISO3166CTRYNAME
,buff
,res
->search_country
) ||
207 compare_info(lcid
,LOCALE_SABBREVCTRYNAME
,buff
,res
->search_country
) ||
208 compare_info(lcid
,LOCALE_SENGCOUNTRY
,buff
,res
->search_country
))
210 TRACE("Found country:%s->%s\n", res
->search_country
, buff
);
211 flags
|= FOUND_COUNTRY
;
212 memcpy(res
->found_country
,res
->search_country
,MAX_ELEM_LEN
);
214 else if (res
->match_flags
& FOUND_COUNTRY
)
216 return CONTINUE_LOOKING
;
220 if (compare_info(lcid
,LOCALE_IDEFAULTCODEPAGE
,buff
,res
->search_codepage
) ||
221 (compare_info(lcid
,LOCALE_IDEFAULTANSICODEPAGE
,buff
,res
->search_codepage
)))
223 TRACE("Found codepage:%s->%s\n", res
->search_codepage
, buff
);
224 flags
|= FOUND_CODEPAGE
;
225 memcpy(res
->found_codepage
,res
->search_codepage
,MAX_ELEM_LEN
);
227 else if (res
->match_flags
& FOUND_CODEPAGE
)
229 return CONTINUE_LOOKING
;
232 if (flags
> res
->match_flags
)
234 /* Found a better match than previously */
235 res
->match_flags
= flags
;
236 res
->found_lang_id
= LangID
;
238 if (flags
& (FOUND_LANGUAGE
& FOUND_COUNTRY
& FOUND_CODEPAGE
))
240 TRACE(":found exact locale match\n");
243 return CONTINUE_LOOKING
;
246 /* Internal: Find the LCID for a locale specification */
247 static LCID
MSVCRT_locale_to_LCID(locale_search_t
* locale
)
250 EnumResourceLanguagesA(GetModuleHandleA("KERNEL32"), (LPSTR
)RT_STRING
,
251 (LPCSTR
)LOCALE_ILANGUAGE
,find_best_locale_proc
,
254 if (!locale
->match_flags
)
257 /* If we were given something that didn't match, fail */
258 if (locale
->search_country
[0] && !(locale
->match_flags
& FOUND_COUNTRY
))
261 lcid
= MAKELCID(locale
->found_lang_id
, SORT_DEFAULT
);
263 /* Populate partial locale, translating LCID to locale string elements */
264 if (!locale
->found_codepage
[0])
266 /* Even if a codepage is not enumerated for a locale
267 * it can be set if valid */
268 if (locale
->search_codepage
[0])
270 if (IsValidCodePage(atoi(locale
->search_codepage
)))
271 memcpy(locale
->found_codepage
,locale
->search_codepage
,MAX_ELEM_LEN
);
274 /* Special codepage values: OEM & ANSI */
275 if (strcasecmp(locale
->search_codepage
,"OCP"))
277 GetLocaleInfoA(lcid
, LOCALE_IDEFAULTCODEPAGE
,
278 locale
->found_codepage
, MAX_ELEM_LEN
);
280 if (strcasecmp(locale
->search_codepage
,"ACP"))
282 GetLocaleInfoA(lcid
, LOCALE_IDEFAULTANSICODEPAGE
,
283 locale
->found_codepage
, MAX_ELEM_LEN
);
288 if (!atoi(locale
->found_codepage
))
294 /* Prefer ANSI codepages if present */
295 GetLocaleInfoA(lcid
, LOCALE_IDEFAULTANSICODEPAGE
,
296 locale
->found_codepage
, MAX_ELEM_LEN
);
297 if (!locale
->found_codepage
[0] || !atoi(locale
->found_codepage
))
298 GetLocaleInfoA(lcid
, LOCALE_IDEFAULTCODEPAGE
,
299 locale
->found_codepage
, MAX_ELEM_LEN
);
302 GetLocaleInfoA(lcid
, LOCALE_SENGLANGUAGE
|LOCALE_NOUSEROVERRIDE
,
303 locale
->found_language
, MAX_ELEM_LEN
);
304 GetLocaleInfoA(lcid
, LOCALE_SENGCOUNTRY
|LOCALE_NOUSEROVERRIDE
,
305 locale
->found_country
, MAX_ELEM_LEN
);
309 /* INTERNAL: Set ctype behaviour for a codepage */
310 static void msvcrt_set_ctype(unsigned int codepage
, LCID lcid
)
314 memset(&cp
, 0, sizeof(CPINFO
));
316 if (GetCPInfo(codepage
, &cp
))
320 unsigned char *traverse
= (unsigned char *)cp
.LeadByte
;
322 memset(MSVCRT_current_ctype
, 0, sizeof(MSVCRT__ctype
));
323 MSVCRT___lc_codepage
= codepage
;
324 MSVCRT___lc_collate_cp
= codepage
;
326 /* Switch ctype macros to MBCS if needed */
327 __mb_cur_max
= cp
.MaxCharSize
;
329 /* Set remaining ctype flags: FIXME: faster way to do this? */
331 for (i
= 0; i
< 256; i
++)
333 if (!(MSVCRT__pctype
[i
] & MSVCRT_LEADBYTE
))
336 GetStringTypeA(lcid
, CT_CTYPE1
, str
, 1, MSVCRT__pctype
+ i
);
340 /* Set leadbyte flags */
341 while (traverse
[0] || traverse
[1])
343 for( i
= traverse
[0]; i
<= traverse
[1]; i
++ )
344 MSVCRT_current_ctype
[i
+1] |= MSVCRT_LEADBYTE
;
354 char *setlocale(int category
, const char *locale
)
358 int haveLang
, haveCountry
, haveCP
;
362 TRACE("(%d %s)\n",category
,locale
);
364 if (category
< MSVCRT_LC_MIN
|| category
> MSVCRT_LC_MAX
)
369 /* Report the current Locale */
370 return MSVCRT_current_lc_all
;
375 if (locale
[0] == 'L' && locale
[1] == 'C' && locale
[2] == '_')
377 WARN(":restore previous locale not implemented!\n");
378 /* FIXME: Easiest way to do this is parse the string and
379 * call this function recursively with its elements,
380 * Where they differ for each lc_ type.
383 return MSVCRT_current_lc_all
;
386 /* Default Locale: Special case handling */
387 if (!strlen(locale
) || ((toupper(locale
[0]) == 'C') && !locale
[1]))
389 MSVCRT_current_lc_all
[0] = 'C';
390 MSVCRT_current_lc_all
[1] = '\0';
391 MSVCRT___lc_codepage
= GetACP();
392 MSVCRT___lc_collate_cp
= GetACP();
396 lc_all
= 1; /* Fall through all cases ... */
397 case MSVCRT_LC_COLLATE
:
399 case MSVCRT_LC_CTYPE
:
400 /* Restore C locale ctype info */
402 memcpy(MSVCRT_current_ctype
, MSVCRT__ctype
, sizeof(MSVCRT__ctype
));
404 case MSVCRT_LC_MONETARY
:
406 case MSVCRT_LC_NUMERIC
:
412 return MSVCRT_current_lc_all
;
415 /* Get locale elements */
416 haveLang
= haveCountry
= haveCP
= 0;
417 memset(&lc
,0,sizeof(lc
));
419 next
= strchr(locale
,'_');
420 if (next
&& next
!= locale
)
423 memcpy(lc
.search_language
,locale
,next
-locale
);
424 locale
+= next
-locale
+1;
427 next
= strchr(locale
,'.');
434 lstrcpynA(lc
.search_codepage
, locale
, MAX_ELEM_LEN
);
441 memcpy(lc
.search_country
,locale
,next
-locale
);
442 locale
+= next
-locale
+1;
447 memcpy(lc
.search_language
,locale
,next
-locale
);
448 locale
+= next
-locale
+1;
450 lstrcpynA(lc
.search_codepage
, locale
, MAX_ELEM_LEN
);
458 lstrcpynA(lc
.search_country
, locale
, MAX_ELEM_LEN
);
463 lstrcpynA(lc
.search_language
, locale
, MAX_ELEM_LEN
);
468 remap_synonym(lc
.search_country
);
470 if (haveCP
&& !haveCountry
&& !haveLang
)
472 ERR(":Codepage only locale not implemented\n");
473 /* FIXME: Use default lang/country and skip locale_to_LCID()
480 lcid
= MSVCRT_locale_to_LCID(&lc
);
482 TRACE(":found LCID %d\n",lcid
);
490 MSVCRT_current_lc_all_lcid
= lcid
;
492 _snprintf(MSVCRT_current_lc_all
,MAX_LOCALE_LENGTH
,"%s_%s.%s",
493 lc
.found_language
,lc
.found_country
,lc
.found_codepage
);
497 lc_all
= 1; /* Fall through all cases ... */
498 case MSVCRT_LC_COLLATE
:
500 case MSVCRT_LC_CTYPE
:
501 msvcrt_set_ctype(atoi(lc
.found_codepage
),lcid
);
503 case MSVCRT_LC_MONETARY
:
505 case MSVCRT_LC_NUMERIC
:
511 return MSVCRT_current_lc_all
;
517 wchar_t* _wsetlocale(int category
, const wchar_t* locale
)
519 static wchar_t fake
[] = {
520 'E','n','g','l','i','s','h','_','U','n','i','t','e','d',' ',
521 'S','t','a','t','e','s','.','1','2','5','2',0 };
523 TRACE("%d %S\n", category
, locale
);
530 locale "lang[_country[.code_page]]"
536 int parse_locale(const char *locale
, char *lang
, char *country
, char *code_page
)
538 while ( *locale
!= 0 && *locale
!= '.' && *locale
!= '_' )
545 if ( *locale
== '_' ) {
547 while ( *locale
!= 0 && *locale
!= '.' )
557 if ( *locale
== '.' ) {
559 while ( *locale
!= 0 && *locale
!= '.' )
561 *code_page
= *locale
;
571 const struct map_lcid2str
{
573 const char *langname
;
576 {0x0409,"English", "United States"},
577 {0x0809,"English", "United Kingdom"},
578 {0x0000,"Unknown", "Unknown"}
582 const struct map_cntr
{
586 {"britain", "united kingdom"},
587 {"england", "united kingdom"},
588 {"gbr", "united kingdom"},
589 {"great britain", "united kingdom"},
590 {"uk", "united kingdom"},
591 {"united kingdom", "united kingdom"},
592 {"united-kingdom", "united kingdom"},
593 {"america", "united states" },
594 {"united states", "united states"},
595 {"united-states", "united states"},
596 {"us", "united states"},
597 {"usa" "united states"}
601 struct lconv _lconv
= {
602 ".", // decimal_point
603 ",", // thousands_sep
605 "DOL", // int_curr_symbol
606 "$", // currency_symbol
607 ".", // mon_decimal_point
608 ",", // mon_thousands_sep
610 "+", // positive_sign
611 "-", // negative_sign
612 127, // int_frac_digits
614 127, // p_cs_precedes
615 127, // p_sep_by_space
616 127, // n_cs_precedes
617 127, // n_sep_by_space
625 struct lconv
*localeconv(void)
627 return (struct lconv
*) &_lconv
;
630 /*********************************************************************
631 * _setmbcp (MSVCRT.@)
634 int CDECL
_setmbcp(int cp
)
647 TRACE("_setmbcp %d\n",cp
);
657 newcp
= MSVCRT___lc_codepage
;
660 newcp
= 20127; /* ASCII */
667 if (!GetCPInfo(newcp
, &cpi
))
669 ERR("Codepage %d not found\n", newcp
);
674 /* setup the _mbctype */
675 memset(MSVCRT_mbctype
, 0, sizeof(MSVCRT_mbctype
));
677 bytes
= cpi
.LeadByte
;
678 while (bytes
[0] || bytes
[1])
680 for (i
= bytes
[0]; i
<= bytes
[1]; i
++)
681 MSVCRT_mbctype
[i
+ 1] |= _M1
;
685 if (cpi
.MaxCharSize
> 1)
687 /* trail bytes not available through kernel32 but stored in a structure in msvcrt */
688 struct cp_extra_info_t
*cpextra
= g_cpextrainfo
;
690 g_mbcp_is_multibyte
= 1;
693 if (cpextra
->cp
== 0 || cpextra
->cp
== newcp
)
695 if (cpextra
->cp
== 0)
696 ERR("trail bytes data not available for DBCS codepage %d - assuming all bytes\n", newcp
);
698 bytes
= cpextra
->TrailBytes
;
699 while (bytes
[0] || bytes
[1])
701 for (i
= bytes
[0]; i
<= bytes
[1]; i
++)
702 MSVCRT_mbctype
[i
+ 1] |= _M2
;
711 g_mbcp_is_multibyte
= 0;
713 /* we can't use GetStringTypeA directly because we don't have a locale - only a code page
716 for (i
= 0; i
< 256; i
++)
717 if (!(MSVCRT_mbctype
[i
+ 1] & _M1
))
718 bufA
[charcount
++] = i
;
720 ret
= MultiByteToWideChar(newcp
, 0, bufA
, charcount
, bufW
, charcount
);
721 if (ret
!= charcount
)
722 ERR("MultiByteToWideChar of chars failed for cp %d, ret=%d (exp %d), error=%d\n", newcp
, ret
, charcount
, GetLastError());
724 GetStringTypeW(CT_CTYPE1
, bufW
, charcount
, chartypes
);
726 curr_type
= chartypes
;
727 for (i
= 0; i
< 256; i
++)
728 if (!(MSVCRT_mbctype
[i
+ 1] & _M1
))
730 if ((*curr_type
) & C1_UPPER
)
731 MSVCRT_mbctype
[i
+ 1] |= _SBUP
;
732 if ((*curr_type
) & C1_LOWER
)
733 MSVCRT_mbctype
[i
+ 1] |= _SBLOW
;
737 if (newcp
== 932) /* CP932 only - set _MP and _MS */
739 /* On Windows it's possible to calculate the _MP and _MS from CT_CTYPE1
740 * and CT_CTYPE3. But as of Wine 0.9.43 we return wrong values what makes
741 * it hard. As this is set only for codepage 932 we hardcode it what gives
742 * also faster execution.
744 for (i
= 161; i
<= 165; i
++)
745 MSVCRT_mbctype
[i
+ 1] |= _MP
;
746 for (i
= 166; i
<= 223; i
++)
747 MSVCRT_mbctype
[i
+ 1] |= _MS
;
750 MSVCRT___lc_collate_cp
= MSVCRT___lc_codepage
= newcp
;
751 TRACE("(%d) -> %d\n", cp
, MSVCRT___lc_codepage
);
756 /*********************************************************************
757 * __lc_collate_cp (MSVCRT.@)
761 void __lc_collate_cp(int cp
)
763 FIXME("__lc_collate_cp - stub\n");
768 /*********************************************************************
769 * __lc_handle (MSVCRT.@)
773 void __lc_handle(void)
775 FIXME("__lc_handle - stub\n");
780 /*********************************************************************
781 * __lc_codepage (MSVCRT.@)
785 void __lc_codepage(void)
787 FIXME("__lc_codepage - stub\n");
792 /*********************************************************************
793 * _Gettnames (MSVCRT.@)
795 void *_Gettnames(void)
797 FIXME("(void), stub!\n");
801 /*********************************************************************
802 * __lconv_init (MSVCRT.@)
804 void __lconv_init(void)
810 /*********************************************************************
811 * _Strftime (MSVCRT.@)
813 const char* _Strftime(char *out
, unsigned int len
, const char *fmt
,
814 const void *tm
, void *foo
)
817 FIXME("(%p %d %s %p %p) stub\n", out
, len
, fmt
, tm
, foo
);
822 /*********************************************************************
823 * _Getdays (MSVCRT.@)
825 const char* _Getdays(void)
827 static const char *MSVCRT_days
= ":Sun:Sunday:Mon:Monday:Tue:Tuesday:Wed:"
828 "Wednesday:Thu:Thursday:Fri:Friday:Sat:Saturday";
829 /* FIXME: Use locale */
830 FIXME("(void) semi-stub\n");
834 /*********************************************************************
835 * _Getmonths (MSVCRT.@)
837 const char* _Getmonths(void)
839 static const char *MSVCRT_months
= ":Jan:January:Feb:February:Mar:March:Apr:"
840 "April:May:May:Jun:June:Jul:July:Aug:August:Sep:September:Oct:"
841 "October:Nov:November:Dec:December";
842 /* FIXME: Use locale */
843 FIXME("(void) semi-stub\n");
844 return MSVCRT_months
;
847 /*********************************************************************
848 * __crtLCMapStringA (MSVCRT.@)
850 int __crtLCMapStringA(
851 LCID lcid
, DWORD mapflags
, const char* src
, int srclen
, char* dst
,
852 int dstlen
, unsigned int codepage
, int xflag
854 TRACE("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n",
855 lcid
,mapflags
,src
,srclen
,dst
,dstlen
,codepage
,xflag
);
856 /* FIXME: A bit incorrect. But msvcrt itself just converts its
857 * arguments to wide strings and then calls LCMapStringW
859 return LCMapStringA(lcid
,mapflags
,src
,srclen
,dst
,dstlen
);
862 /*********************************************************************
863 * __crtLCMapStringW (MSVCRT.@)
865 int __crtLCMapStringW(
866 LCID lcid
, DWORD mapflags
, LPCWSTR src
, int srclen
, LPWSTR dst
,
867 int dstlen
, unsigned int codepage
, int xflag
869 TRACE("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n",
870 lcid
,mapflags
,src
,srclen
,dst
,dstlen
,codepage
,xflag
);
872 return LCMapStringW(lcid
,mapflags
,src
,srclen
,dst
,dstlen
);
875 int CDECL
_getmbcp(void)
877 return MSVCRT___lc_codepage
;