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 _mbctype
[257] = { 0 };
31 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 {1361, {0x31, 0x7e, 0x81, 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
] = { 0 };
54 LCID MSVCRT_current_lc_all_lcid
= 0;
55 int MSVCRT___lc_codepage
= 0;
56 int MSVCRT___lc_collate_cp
= 0;
57 HANDLE MSVCRT___lc_handle
[MSVCRT_LC_MAX
- MSVCRT_LC_MIN
+ 1] = { 0 };
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 (!_stricmp(_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 !_strnicmp(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
)) ==
239 (FOUND_LANGUAGE
| FOUND_COUNTRY
| FOUND_CODEPAGE
))
241 TRACE(":found exact locale match\n");
244 return CONTINUE_LOOKING
;
247 /* Internal: Find the LCID for a locale specification */
248 static LCID
MSVCRT_locale_to_LCID(locale_search_t
* locale
)
251 EnumResourceLanguagesA(GetModuleHandleA("KERNEL32"), (LPSTR
)RT_STRING
,
252 (LPCSTR
)LOCALE_ILANGUAGE
,find_best_locale_proc
,
255 if (!locale
->match_flags
)
258 /* If we were given something that didn't match, fail */
259 if (locale
->search_country
[0] && !(locale
->match_flags
& FOUND_COUNTRY
))
262 lcid
= MAKELCID(locale
->found_lang_id
, SORT_DEFAULT
);
264 /* Populate partial locale, translating LCID to locale string elements */
265 if (!locale
->found_codepage
[0])
267 /* Even if a codepage is not enumerated for a locale
268 * it can be set if valid */
269 if (locale
->search_codepage
[0])
271 if (IsValidCodePage(atoi(locale
->search_codepage
)))
272 memcpy(locale
->found_codepage
,locale
->search_codepage
,MAX_ELEM_LEN
);
275 /* Special codepage values: OEM & ANSI */
276 if (_stricmp(locale
->search_codepage
,"OCP"))
278 GetLocaleInfoA(lcid
, LOCALE_IDEFAULTCODEPAGE
,
279 locale
->found_codepage
, MAX_ELEM_LEN
);
281 if (_stricmp(locale
->search_codepage
,"ACP"))
283 GetLocaleInfoA(lcid
, LOCALE_IDEFAULTANSICODEPAGE
,
284 locale
->found_codepage
, MAX_ELEM_LEN
);
289 if (!atoi(locale
->found_codepage
))
295 /* Prefer ANSI codepages if present */
296 GetLocaleInfoA(lcid
, LOCALE_IDEFAULTANSICODEPAGE
,
297 locale
->found_codepage
, MAX_ELEM_LEN
);
298 if (!locale
->found_codepage
[0] || !atoi(locale
->found_codepage
))
299 GetLocaleInfoA(lcid
, LOCALE_IDEFAULTCODEPAGE
,
300 locale
->found_codepage
, MAX_ELEM_LEN
);
303 GetLocaleInfoA(lcid
, LOCALE_SENGLANGUAGE
|LOCALE_NOUSEROVERRIDE
,
304 locale
->found_language
, MAX_ELEM_LEN
);
305 GetLocaleInfoA(lcid
, LOCALE_SENGCOUNTRY
|LOCALE_NOUSEROVERRIDE
,
306 locale
->found_country
, MAX_ELEM_LEN
);
310 /* INTERNAL: Set ctype behaviour for a codepage */
311 static void msvcrt_set_ctype(unsigned int codepage
, LCID lcid
)
315 memset(&cp
, 0, sizeof(CPINFO
));
317 if (GetCPInfo(codepage
, &cp
))
321 unsigned char *traverse
= cp
.LeadByte
;
323 memset(MSVCRT_current_ctype
, 0, sizeof(MSVCRT__ctype
));
324 MSVCRT___lc_codepage
= codepage
;
325 MSVCRT___lc_collate_cp
= codepage
;
327 /* Switch ctype macros to MBCS if needed */
328 __mb_cur_max
= cp
.MaxCharSize
;
330 /* Set remaining ctype flags: FIXME: faster way to do this? */
332 for (i
= 0; i
< 256; i
++)
334 if (!(MSVCRT__pctype
[i
] & MSVCRT_LEADBYTE
))
337 GetStringTypeA(lcid
, CT_CTYPE1
, str
, 1, MSVCRT__pctype
+ i
);
341 /* Set leadbyte flags */
342 while (traverse
[0] || traverse
[1])
344 for( i
= traverse
[0]; i
<= traverse
[1]; i
++ )
345 MSVCRT_current_ctype
[i
+1] |= MSVCRT_LEADBYTE
;
355 char *setlocale(int category
, const char *locale
)
359 int haveLang
, haveCountry
, haveCP
;
363 TRACE("(%d %s)\n",category
,locale
);
365 if (category
< MSVCRT_LC_MIN
|| category
> MSVCRT_LC_MAX
)
370 /* Report the current Locale */
371 return MSVCRT_current_lc_all
;
376 if (locale
[0] == 'L' && locale
[1] == 'C' && locale
[2] == '_')
378 WARN(":restore previous locale not implemented!\n");
379 /* FIXME: Easiest way to do this is parse the string and
380 * call this function recursively with its elements,
381 * Where they differ for each lc_ type.
384 return MSVCRT_current_lc_all
;
387 /* Default Locale: Special case handling */
388 if (!strlen(locale
) || ((toupper(locale
[0]) == 'C') && !locale
[1]))
390 MSVCRT_current_lc_all
[0] = 'C';
391 MSVCRT_current_lc_all
[1] = '\0';
392 MSVCRT___lc_codepage
= GetACP();
393 MSVCRT___lc_collate_cp
= GetACP();
397 lc_all
= 1; /* Fall through all cases ... */
398 case MSVCRT_LC_COLLATE
:
400 case MSVCRT_LC_CTYPE
:
401 /* Restore C locale ctype info */
403 memcpy(MSVCRT_current_ctype
, MSVCRT__ctype
, sizeof(MSVCRT__ctype
));
405 case MSVCRT_LC_MONETARY
:
407 case MSVCRT_LC_NUMERIC
:
413 return MSVCRT_current_lc_all
;
416 /* Get locale elements */
417 haveLang
= haveCountry
= haveCP
= 0;
418 memset(&lc
,0,sizeof(lc
));
420 next
= strchr(locale
,'_');
421 if (next
&& next
!= locale
)
424 memcpy(lc
.search_language
,locale
,next
-locale
);
425 locale
+= next
-locale
+1;
428 next
= strchr(locale
,'.');
435 lstrcpynA(lc
.search_codepage
, locale
, MAX_ELEM_LEN
);
442 memcpy(lc
.search_country
,locale
,next
-locale
);
443 locale
+= next
-locale
+1;
448 memcpy(lc
.search_language
,locale
,next
-locale
);
449 locale
+= next
-locale
+1;
451 lstrcpynA(lc
.search_codepage
, locale
, MAX_ELEM_LEN
);
459 lstrcpynA(lc
.search_country
, locale
, MAX_ELEM_LEN
);
464 lstrcpynA(lc
.search_language
, locale
, MAX_ELEM_LEN
);
469 remap_synonym(lc
.search_country
);
471 if (haveCP
&& !haveCountry
&& !haveLang
)
473 ERR(":Codepage only locale not implemented\n");
474 /* FIXME: Use default lang/country and skip locale_to_LCID()
481 lcid
= MSVCRT_locale_to_LCID(&lc
);
483 TRACE(":found LCID %d\n",lcid
);
491 MSVCRT_current_lc_all_lcid
= lcid
;
493 _snprintf(MSVCRT_current_lc_all
,MAX_LOCALE_LENGTH
,"%s_%s.%s",
494 lc
.found_language
,lc
.found_country
,lc
.found_codepage
);
498 lc_all
= 1; /* Fall through all cases ... */
499 case MSVCRT_LC_COLLATE
:
501 case MSVCRT_LC_CTYPE
:
502 msvcrt_set_ctype(atoi(lc
.found_codepage
),lcid
);
504 case MSVCRT_LC_MONETARY
:
506 case MSVCRT_LC_NUMERIC
:
512 return MSVCRT_current_lc_all
;
518 wchar_t* _wsetlocale(int category
, const wchar_t* locale
)
520 static wchar_t fake
[] = {
521 'E','n','g','l','i','s','h','_','U','n','i','t','e','d',' ',
522 'S','t','a','t','e','s','.','1','2','5','2',0 };
524 TRACE("%d %S\n", category
, locale
);
531 locale "lang[_country[.code_page]]"
537 int parse_locale(const char *locale
, char *lang
, char *country
, char *code_page
)
539 while ( *locale
!= 0 && *locale
!= '.' && *locale
!= '_' )
546 if ( *locale
== '_' ) {
548 while ( *locale
!= 0 && *locale
!= '.' )
558 if ( *locale
== '.' ) {
560 while ( *locale
!= 0 && *locale
!= '.' )
562 *code_page
= *locale
;
572 const struct map_lcid2str
{
574 const char *langname
;
577 {0x0409,"English", "United States"},
578 {0x0809,"English", "United Kingdom"},
579 {0x0000,"Unknown", "Unknown"}
583 const struct map_cntr
{
587 {"britain", "united kingdom"},
588 {"england", "united kingdom"},
589 {"gbr", "united kingdom"},
590 {"great britain", "united kingdom"},
591 {"uk", "united kingdom"},
592 {"united kingdom", "united kingdom"},
593 {"united-kingdom", "united kingdom"},
594 {"america", "united states" },
595 {"united states", "united states"},
596 {"united-states", "united states"},
597 {"us", "united states"},
598 {"usa", "united states"}
602 struct lconv _lconv
= {
603 ".", // decimal_point
604 ",", // thousands_sep
606 "DOL", // int_curr_symbol
607 "$", // currency_symbol
608 ".", // mon_decimal_point
609 ",", // mon_thousands_sep
611 "+", // positive_sign
612 "-", // negative_sign
613 127, // int_frac_digits
615 127, // p_cs_precedes
616 127, // p_sep_by_space
617 127, // n_cs_precedes
618 127, // n_sep_by_space
626 struct lconv
*localeconv(void)
628 return (struct lconv
*) &_lconv
;
631 /*********************************************************************
632 * _setmbcp (MSVCRT.@)
635 int CDECL
_setmbcp(int cp
)
648 TRACE("_setmbcp %d\n",cp
);
658 newcp
= MSVCRT___lc_codepage
;
661 newcp
= 20127; /* ASCII */
668 if (!GetCPInfo(newcp
, &cpi
))
670 ERR("Codepage %d not found\n", newcp
);
675 /* setup the _mbctype */
676 memset(_mbctype
, 0, sizeof(_mbctype
));
678 bytes
= cpi
.LeadByte
;
679 while (bytes
[0] || bytes
[1])
681 for (i
= bytes
[0]; i
<= bytes
[1]; i
++)
682 _mbctype
[i
+ 1] |= _M1
;
686 if (cpi
.MaxCharSize
> 1)
688 /* trail bytes not available through kernel32 but stored in a structure in msvcrt */
689 struct cp_extra_info_t
*cpextra
= g_cpextrainfo
;
691 g_mbcp_is_multibyte
= 1;
694 if (cpextra
->cp
== 0 || cpextra
->cp
== newcp
)
696 if (cpextra
->cp
== 0)
697 ERR("trail bytes data not available for DBCS codepage %d - assuming all bytes\n", newcp
);
699 bytes
= cpextra
->TrailBytes
;
700 while (bytes
[0] || bytes
[1])
702 for (i
= bytes
[0]; i
<= bytes
[1]; i
++)
703 _mbctype
[i
+ 1] |= _M2
;
712 g_mbcp_is_multibyte
= 0;
714 /* we can't use GetStringTypeA directly because we don't have a locale - only a code page
717 for (i
= 0; i
< 256; i
++)
718 if (!(_mbctype
[i
+ 1] & _M1
))
719 bufA
[charcount
++] = i
;
721 ret
= MultiByteToWideChar(newcp
, 0, bufA
, charcount
, bufW
, charcount
);
722 if (ret
!= charcount
)
723 ERR("MultiByteToWideChar of chars failed for cp %d, ret=%d (exp %d), error=%d\n", newcp
, ret
, charcount
, GetLastError());
725 GetStringTypeW(CT_CTYPE1
, bufW
, charcount
, chartypes
);
727 curr_type
= chartypes
;
728 for (i
= 0; i
< 256; i
++)
729 if (!(_mbctype
[i
+ 1] & _M1
))
731 if ((*curr_type
) & C1_UPPER
)
732 _mbctype
[i
+ 1] |= _SBUP
;
733 if ((*curr_type
) & C1_LOWER
)
734 _mbctype
[i
+ 1] |= _SBLOW
;
738 if (newcp
== 932) /* CP932 only - set _MP and _MS */
740 /* On Windows it's possible to calculate the _MP and _MS from CT_CTYPE1
741 * and CT_CTYPE3. But as of Wine 0.9.43 we return wrong values what makes
742 * it hard. As this is set only for codepage 932 we hardcode it what gives
743 * also faster execution.
745 for (i
= 161; i
<= 165; i
++)
746 _mbctype
[i
+ 1] |= _MP
;
747 for (i
= 166; i
<= 223; i
++)
748 _mbctype
[i
+ 1] |= _MS
;
751 MSVCRT___lc_collate_cp
= MSVCRT___lc_codepage
= newcp
;
752 TRACE("(%d) -> %d\n", cp
, MSVCRT___lc_codepage
);
757 /*********************************************************************
758 * __lc_collate_cp (MSVCRT.@)
762 void __lc_collate_cp(int cp
)
764 FIXME("__lc_collate_cp - stub\n");
769 /*********************************************************************
770 * __lc_handle (MSVCRT.@)
774 void __lc_handle(void)
776 FIXME("__lc_handle - stub\n");
781 /*********************************************************************
782 * __lc_codepage (MSVCRT.@)
786 void __lc_codepage(void)
788 FIXME("__lc_codepage - stub\n");
793 /*********************************************************************
794 * _Gettnames (MSVCRT.@)
796 void *_Gettnames(void)
798 FIXME("(void), stub!\n");
802 /*********************************************************************
803 * __lconv_init (MSVCRT.@)
805 void __lconv_init(void)
807 char Char
= (char) UCHAR_MAX
;
809 TRACE("__lconv_init()\n");
811 _lconv
.int_frac_digits
= Char
;
812 _lconv
.frac_digits
= Char
;
813 _lconv
.p_sep_by_space
= _lconv
.n_sep_by_space
= Char
;
814 _lconv
.p_cs_precedes
= _lconv
.n_cs_precedes
= Char
;
815 _lconv
.p_sign_posn
= _lconv
.n_sign_posn
= Char
;
819 /*********************************************************************
820 * _Strftime (MSVCRT.@)
822 const char* _Strftime(char *out
, unsigned int len
, const char *fmt
,
823 const void *tm
, void *foo
)
826 FIXME("(%p %d %s %p %p) stub\n", out
, len
, fmt
, tm
, foo
);
831 /*********************************************************************
832 * _Getdays (MSVCRT.@)
834 const char* _Getdays(void)
836 static const char *MSVCRT_days
= ":Sun:Sunday:Mon:Monday:Tue:Tuesday:Wed:"
837 "Wednesday:Thu:Thursday:Fri:Friday:Sat:Saturday";
838 /* FIXME: Use locale */
839 FIXME("(void) semi-stub\n");
843 /*********************************************************************
844 * _Getmonths (MSVCRT.@)
846 const char* _Getmonths(void)
848 static const char *MSVCRT_months
= ":Jan:January:Feb:February:Mar:March:Apr:"
849 "April:May:May:Jun:June:Jul:July:Aug:August:Sep:September:Oct:"
850 "October:Nov:November:Dec:December";
851 /* FIXME: Use locale */
852 FIXME("(void) semi-stub\n");
853 return MSVCRT_months
;
856 /*********************************************************************
857 * __crtLCMapStringA (MSVCRT.@)
859 int __crtLCMapStringA(
860 LCID lcid
, DWORD mapflags
, const char* src
, int srclen
, char* dst
,
861 int dstlen
, unsigned int codepage
, int xflag
863 TRACE("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n",
864 lcid
,mapflags
,src
,srclen
,dst
,dstlen
,codepage
,xflag
);
865 /* FIXME: A bit incorrect. But msvcrt itself just converts its
866 * arguments to wide strings and then calls LCMapStringW
868 return LCMapStringA(lcid
,mapflags
,src
,srclen
,dst
,dstlen
);
871 /*********************************************************************
872 * __crtLCMapStringW (MSVCRT.@)
874 int __crtLCMapStringW(
875 LCID lcid
, DWORD mapflags
, LPCWSTR src
, int srclen
, LPWSTR dst
,
876 int dstlen
, unsigned int codepage
, int xflag
878 TRACE("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n",
879 lcid
,mapflags
,src
,srclen
,dst
,dstlen
,codepage
,xflag
);
881 return LCMapStringW(lcid
,mapflags
,src
,srclen
,dst
,dstlen
);
884 int CDECL
_getmbcp(void)
886 return MSVCRT___lc_codepage
;
889 /*********************************************************************
890 * ___unguarded_readlc_active_add_func (MSVCRT.@)
892 unsigned int * CDECL
___unguarded_readlc_active_add_func(void)
894 return &__unguarded_readlc_active
;
897 /*********************************************************************
898 * ___setlc_active_func (MSVCRT.@)
900 unsigned int CDECL
___setlc_active_func(void)
902 return __setlc_active
;