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 };
61 #define LOCK_LOCALE _mlock(_SETLOCALE_LOCK);
62 #define UNLOCK_LOCALE _munlock(_SETLOCALE_LOCK);
64 #define MSVCRT_LEADBYTE 0x8000
67 char search_language
[MAX_ELEM_LEN
];
68 char search_country
[MAX_ELEM_LEN
];
69 char search_codepage
[MAX_ELEM_LEN
];
70 char found_language
[MAX_ELEM_LEN
];
71 char found_country
[MAX_ELEM_LEN
];
72 char found_codepage
[MAX_ELEM_LEN
];
73 unsigned int match_flags
;
77 extern unsigned int __setlc_active
;
78 extern unsigned int __unguarded_readlc_active
;
79 int _current_category
; /* used by setlocale */
80 const char *_current_locale
;
83 int parse_locale(const char *locale
, char *lang
, char *country
, char *code_page
);
93 WORD MSVCRT__ctype
[257] = {
94 0, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _S_
|_C_
, _S_
|_C_
,
95 _S_
|_C_
, _S_
|_C_
, _S_
|_C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
,
96 _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _C_
, _S_
|_BLANK
,
97 _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
,
98 _P_
, _D_
|_H_
, _D_
|_H_
, _D_
|_H_
, _D_
|_H_
, _D_
|_H_
, _D_
|_H_
, _D_
|_H_
,
99 _D_
|_H_
, _D_
|_H_
, _D_
|_H_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _U_
|_H_
,
100 _U_
|_H_
, _U_
|_H_
, _U_
|_H_
, _U_
|_H_
, _U_
|_H_
, _U_
, _U_
, _U_
, _U_
, _U_
,
101 _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
, _U_
,
102 _U_
, _P_
, _P_
, _P_
, _P_
, _P_
, _P_
, _L_
|_H_
, _L_
|_H_
, _L_
|_H_
, _L_
|_H_
,
103 _L_
|_H_
, _L_
|_H_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
,
104 _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _L_
, _P_
, _P_
, _P_
, _P_
,
105 _C_
, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
113 /* Internal: Current ctype table for locale */
114 WORD MSVCRT_current_ctype
[257];
116 /* pctype is used by macros in the Win32 headers. It must point
117 * To a table of flags exactly like ctype. To allow locale
118 * changes to affect ctypes (i.e. isleadbyte), we use a second table
119 * and update its flags whenever the current locale changes.
121 WORD
* MSVCRT__pctype
= MSVCRT_current_ctype
+ 1;
123 /* Friendly country strings & iso codes for synonym support.
124 * Based on MS documentation for setlocale().
126 static const char * const _country_synonyms
[] =
134 "United Kingdom","GB",
135 "United-Kingdom","GB",
138 "Great Britain","GB",
139 "United States","US",
140 "United-States","US",
144 /* Note: Flags are weighted in order of matching importance */
145 #define FOUND_LANGUAGE 0x4
146 #define FOUND_COUNTRY 0x2
147 #define FOUND_CODEPAGE 0x1
149 /* INTERNAL: Map a synonym to an ISO code */
150 static void remap_synonym(char *name
)
153 for (i
= 0; i
< sizeof(_country_synonyms
)/sizeof(char*); i
+= 2 )
155 if (!_stricmp(_country_synonyms
[i
],name
))
157 TRACE(":Mapping synonym %s to %s\n",name
,_country_synonyms
[i
+1]);
158 name
[0] = _country_synonyms
[i
+1][0];
159 name
[1] = _country_synonyms
[i
+1][1];
166 #define CONTINUE_LOOKING TRUE
167 #define STOP_LOOKING FALSE
169 /* INTERNAL: Get and compare locale info with a given string */
170 static int compare_info(LCID lcid
, DWORD flags
, char* buff
, const char* cmp
)
173 GetLocaleInfoA(lcid
, flags
|LOCALE_NOUSEROVERRIDE
,buff
, MAX_ELEM_LEN
);
174 if (!buff
[0] || !cmp
[0])
176 /* Partial matches are allowed, e.g. "Germ" matches "Germany" */
177 return !_strnicmp(cmp
, buff
, strlen(cmp
));
182 find_best_locale_proc(HMODULE hModule
, LPCSTR type
, LPCSTR name
, WORD LangID
, LONG_PTR lParam
)
184 locale_search_t
*res
= (locale_search_t
*)lParam
;
185 const LCID lcid
= MAKELCID(LangID
, SORT_DEFAULT
);
186 char buff
[MAX_ELEM_LEN
];
187 unsigned int flags
= 0;
189 if(PRIMARYLANGID(LangID
) == LANG_NEUTRAL
)
190 return CONTINUE_LOOKING
;
193 if (compare_info(lcid
,LOCALE_SISO639LANGNAME
,buff
,res
->search_language
) ||
194 compare_info(lcid
,LOCALE_SABBREVLANGNAME
,buff
,res
->search_language
) ||
195 compare_info(lcid
,LOCALE_SENGLANGUAGE
,buff
,res
->search_language
))
197 TRACE(":Found language: %s->%s\n", res
->search_language
, buff
);
198 flags
|= FOUND_LANGUAGE
;
199 memcpy(res
->found_language
,res
->search_language
,MAX_ELEM_LEN
);
201 else if (res
->match_flags
& FOUND_LANGUAGE
)
203 return CONTINUE_LOOKING
;
207 if (compare_info(lcid
,LOCALE_SISO3166CTRYNAME
,buff
,res
->search_country
) ||
208 compare_info(lcid
,LOCALE_SABBREVCTRYNAME
,buff
,res
->search_country
) ||
209 compare_info(lcid
,LOCALE_SENGCOUNTRY
,buff
,res
->search_country
))
211 TRACE("Found country:%s->%s\n", res
->search_country
, buff
);
212 flags
|= FOUND_COUNTRY
;
213 memcpy(res
->found_country
,res
->search_country
,MAX_ELEM_LEN
);
215 else if (res
->match_flags
& FOUND_COUNTRY
)
217 return CONTINUE_LOOKING
;
221 if (compare_info(lcid
,LOCALE_IDEFAULTCODEPAGE
,buff
,res
->search_codepage
) ||
222 (compare_info(lcid
,LOCALE_IDEFAULTANSICODEPAGE
,buff
,res
->search_codepage
)))
224 TRACE("Found codepage:%s->%s\n", res
->search_codepage
, buff
);
225 flags
|= FOUND_CODEPAGE
;
226 memcpy(res
->found_codepage
,res
->search_codepage
,MAX_ELEM_LEN
);
228 else if (res
->match_flags
& FOUND_CODEPAGE
)
230 return CONTINUE_LOOKING
;
233 if (flags
> res
->match_flags
)
235 /* Found a better match than previously */
236 res
->match_flags
= flags
;
237 res
->found_lang_id
= LangID
;
239 if ((flags
& (FOUND_LANGUAGE
| FOUND_COUNTRY
| FOUND_CODEPAGE
)) ==
240 (FOUND_LANGUAGE
| FOUND_COUNTRY
| FOUND_CODEPAGE
))
242 TRACE(":found exact locale match\n");
245 return CONTINUE_LOOKING
;
248 /* Internal: Find the LCID for a locale specification */
249 static LCID
MSVCRT_locale_to_LCID(locale_search_t
* locale
)
252 EnumResourceLanguagesA(GetModuleHandleA("KERNEL32"), (LPSTR
)RT_STRING
,
253 (LPCSTR
)LOCALE_ILANGUAGE
,find_best_locale_proc
,
256 if (!locale
->match_flags
)
259 /* If we were given something that didn't match, fail */
260 if (locale
->search_country
[0] && !(locale
->match_flags
& FOUND_COUNTRY
))
263 lcid
= MAKELCID(locale
->found_lang_id
, SORT_DEFAULT
);
265 /* Populate partial locale, translating LCID to locale string elements */
266 if (!locale
->found_codepage
[0])
268 /* Even if a codepage is not enumerated for a locale
269 * it can be set if valid */
270 if (locale
->search_codepage
[0])
272 if (IsValidCodePage(atoi(locale
->search_codepage
)))
273 memcpy(locale
->found_codepage
,locale
->search_codepage
,MAX_ELEM_LEN
);
276 /* Special codepage values: OEM & ANSI */
277 if (_stricmp(locale
->search_codepage
,"OCP"))
279 GetLocaleInfoA(lcid
, LOCALE_IDEFAULTCODEPAGE
,
280 locale
->found_codepage
, MAX_ELEM_LEN
);
282 if (_stricmp(locale
->search_codepage
,"ACP"))
284 GetLocaleInfoA(lcid
, LOCALE_IDEFAULTANSICODEPAGE
,
285 locale
->found_codepage
, MAX_ELEM_LEN
);
290 if (!atoi(locale
->found_codepage
))
296 /* Prefer ANSI codepages if present */
297 GetLocaleInfoA(lcid
, LOCALE_IDEFAULTANSICODEPAGE
,
298 locale
->found_codepage
, MAX_ELEM_LEN
);
299 if (!locale
->found_codepage
[0] || !atoi(locale
->found_codepage
))
300 GetLocaleInfoA(lcid
, LOCALE_IDEFAULTCODEPAGE
,
301 locale
->found_codepage
, MAX_ELEM_LEN
);
304 GetLocaleInfoA(lcid
, LOCALE_SENGLANGUAGE
|LOCALE_NOUSEROVERRIDE
,
305 locale
->found_language
, MAX_ELEM_LEN
);
306 GetLocaleInfoA(lcid
, LOCALE_SENGCOUNTRY
|LOCALE_NOUSEROVERRIDE
,
307 locale
->found_country
, MAX_ELEM_LEN
);
311 /* INTERNAL: Set ctype behaviour for a codepage */
312 static void msvcrt_set_ctype(unsigned int codepage
, LCID lcid
)
316 memset(&cp
, 0, sizeof(CPINFO
));
318 if (GetCPInfo(codepage
, &cp
))
322 unsigned char *traverse
= cp
.LeadByte
;
324 memset(MSVCRT_current_ctype
, 0, sizeof(MSVCRT__ctype
));
325 MSVCRT___lc_codepage
= codepage
;
326 MSVCRT___lc_collate_cp
= codepage
;
328 /* Switch ctype macros to MBCS if needed */
329 __mb_cur_max
= cp
.MaxCharSize
;
331 /* Set remaining ctype flags: FIXME: faster way to do this? */
333 for (i
= 0; i
< 256; i
++)
335 if (!(MSVCRT__pctype
[i
] & MSVCRT_LEADBYTE
))
338 GetStringTypeA(lcid
, CT_CTYPE1
, str
, 1, MSVCRT__pctype
+ i
);
342 /* Set leadbyte flags */
343 while (traverse
[0] || traverse
[1])
345 for( i
= traverse
[0]; i
<= traverse
[1]; i
++ )
346 MSVCRT_current_ctype
[i
+1] |= MSVCRT_LEADBYTE
;
356 char *setlocale(int category
, const char *locale
)
360 int haveLang
, haveCountry
, haveCP
;
364 TRACE("(%d %s)\n",category
,locale
);
366 if (category
< MSVCRT_LC_MIN
|| category
> MSVCRT_LC_MAX
)
371 /* Report the current Locale */
372 return MSVCRT_current_lc_all
;
377 if (locale
[0] == 'L' && locale
[1] == 'C' && locale
[2] == '_')
379 WARN(":restore previous locale not implemented!\n");
380 /* FIXME: Easiest way to do this is parse the string and
381 * call this function recursively with its elements,
382 * Where they differ for each lc_ type.
385 return MSVCRT_current_lc_all
;
388 /* Default Locale: Special case handling */
389 if (!strlen(locale
) || ((toupper(locale
[0]) == 'C') && !locale
[1]))
391 MSVCRT_current_lc_all
[0] = 'C';
392 MSVCRT_current_lc_all
[1] = '\0';
393 MSVCRT___lc_codepage
= GetACP();
394 MSVCRT___lc_collate_cp
= GetACP();
398 lc_all
= 1; /* Fall through all cases ... */
399 case MSVCRT_LC_COLLATE
:
401 case MSVCRT_LC_CTYPE
:
402 /* Restore C locale ctype info */
404 memcpy(MSVCRT_current_ctype
, MSVCRT__ctype
, sizeof(MSVCRT__ctype
));
406 case MSVCRT_LC_MONETARY
:
408 case MSVCRT_LC_NUMERIC
:
414 return MSVCRT_current_lc_all
;
417 /* Get locale elements */
418 haveLang
= haveCountry
= haveCP
= 0;
419 memset(&lc
,0,sizeof(lc
));
421 next
= strchr(locale
,'_');
422 if (next
&& next
!= locale
)
425 memcpy(lc
.search_language
,locale
,next
-locale
);
426 locale
+= next
-locale
+1;
429 next
= strchr(locale
,'.');
436 lstrcpynA(lc
.search_codepage
, locale
, MAX_ELEM_LEN
);
443 memcpy(lc
.search_country
,locale
,next
-locale
);
444 locale
+= next
-locale
+1;
449 memcpy(lc
.search_language
,locale
,next
-locale
);
450 locale
+= next
-locale
+1;
452 lstrcpynA(lc
.search_codepage
, locale
, MAX_ELEM_LEN
);
460 lstrcpynA(lc
.search_country
, locale
, MAX_ELEM_LEN
);
465 lstrcpynA(lc
.search_language
, locale
, MAX_ELEM_LEN
);
470 remap_synonym(lc
.search_country
);
472 if (haveCP
&& !haveCountry
&& !haveLang
)
474 ERR(":Codepage only locale not implemented\n");
475 /* FIXME: Use default lang/country and skip locale_to_LCID()
482 lcid
= MSVCRT_locale_to_LCID(&lc
);
484 TRACE(":found LCID %d\n",lcid
);
492 MSVCRT_current_lc_all_lcid
= lcid
;
494 _snprintf(MSVCRT_current_lc_all
,MAX_LOCALE_LENGTH
,"%s_%s.%s",
495 lc
.found_language
,lc
.found_country
,lc
.found_codepage
);
499 lc_all
= 1; /* Fall through all cases ... */
500 case MSVCRT_LC_COLLATE
:
502 case MSVCRT_LC_CTYPE
:
503 msvcrt_set_ctype(atoi(lc
.found_codepage
),lcid
);
505 case MSVCRT_LC_MONETARY
:
507 case MSVCRT_LC_NUMERIC
:
513 return MSVCRT_current_lc_all
;
519 wchar_t* _wsetlocale(int category
, const wchar_t* locale
)
521 static wchar_t fake
[] = {
522 'E','n','g','l','i','s','h','_','U','n','i','t','e','d',' ',
523 'S','t','a','t','e','s','.','1','2','5','2',0 };
525 TRACE("%d %S\n", category
, locale
);
532 locale "lang[_country[.code_page]]"
538 int parse_locale(const char *locale
, char *lang
, char *country
, char *code_page
)
540 while ( *locale
!= 0 && *locale
!= '.' && *locale
!= '_' )
547 if ( *locale
== '_' ) {
549 while ( *locale
!= 0 && *locale
!= '.' )
559 if ( *locale
== '.' ) {
561 while ( *locale
!= 0 && *locale
!= '.' )
563 *code_page
= *locale
;
573 const struct map_lcid2str
{
575 const char *langname
;
578 {0x0409,"English", "United States"},
579 {0x0809,"English", "United Kingdom"},
580 {0x0000,"Unknown", "Unknown"}
584 const struct map_cntr
{
588 {"britain", "united kingdom"},
589 {"england", "united kingdom"},
590 {"gbr", "united kingdom"},
591 {"great britain", "united kingdom"},
592 {"uk", "united kingdom"},
593 {"united kingdom", "united kingdom"},
594 {"united-kingdom", "united kingdom"},
595 {"america", "united states" },
596 {"united states", "united states"},
597 {"united-states", "united states"},
598 {"us", "united states"},
599 {"usa", "united states"}
603 struct lconv _lconv
= {
604 ".", // decimal_point
605 ",", // thousands_sep
607 "DOL", // int_curr_symbol
608 "$", // currency_symbol
609 ".", // mon_decimal_point
610 ",", // mon_thousands_sep
612 "+", // positive_sign
613 "-", // negative_sign
614 127, // int_frac_digits
616 127, // p_cs_precedes
617 127, // p_sep_by_space
618 127, // n_cs_precedes
619 127, // n_sep_by_space
627 struct lconv
*localeconv(void)
629 return (struct lconv
*) &_lconv
;
632 /*********************************************************************
633 * _setmbcp (MSVCRT.@)
636 int CDECL
_setmbcp(int cp
)
649 TRACE("_setmbcp %d\n",cp
);
659 newcp
= MSVCRT___lc_codepage
;
662 newcp
= 20127; /* ASCII */
669 if (!GetCPInfo(newcp
, &cpi
))
671 ERR("Codepage %d not found\n", newcp
);
676 /* setup the _mbctype */
677 memset(_mbctype
, 0, sizeof(_mbctype
));
679 bytes
= cpi
.LeadByte
;
680 while (bytes
[0] || bytes
[1])
682 for (i
= bytes
[0]; i
<= bytes
[1]; i
++)
683 _mbctype
[i
+ 1] |= _M1
;
687 if (cpi
.MaxCharSize
> 1)
689 /* trail bytes not available through kernel32 but stored in a structure in msvcrt */
690 struct cp_extra_info_t
*cpextra
= g_cpextrainfo
;
692 g_mbcp_is_multibyte
= 1;
695 if (cpextra
->cp
== 0 || cpextra
->cp
== newcp
)
697 if (cpextra
->cp
== 0)
698 ERR("trail bytes data not available for DBCS codepage %d - assuming all bytes\n", newcp
);
700 bytes
= cpextra
->TrailBytes
;
701 while (bytes
[0] || bytes
[1])
703 for (i
= bytes
[0]; i
<= bytes
[1]; i
++)
704 _mbctype
[i
+ 1] |= _M2
;
713 g_mbcp_is_multibyte
= 0;
715 /* we can't use GetStringTypeA directly because we don't have a locale - only a code page
718 for (i
= 0; i
< 256; i
++)
719 if (!(_mbctype
[i
+ 1] & _M1
))
720 bufA
[charcount
++] = i
;
722 ret
= MultiByteToWideChar(newcp
, 0, bufA
, charcount
, bufW
, charcount
);
723 if (ret
!= charcount
)
724 ERR("MultiByteToWideChar of chars failed for cp %d, ret=%d (exp %d), error=%d\n", newcp
, ret
, charcount
, GetLastError());
726 GetStringTypeW(CT_CTYPE1
, bufW
, charcount
, chartypes
);
728 curr_type
= chartypes
;
729 for (i
= 0; i
< 256; i
++)
730 if (!(_mbctype
[i
+ 1] & _M1
))
732 if ((*curr_type
) & C1_UPPER
)
733 _mbctype
[i
+ 1] |= _SBUP
;
734 if ((*curr_type
) & C1_LOWER
)
735 _mbctype
[i
+ 1] |= _SBLOW
;
739 if (newcp
== 932) /* CP932 only - set _MP and _MS */
741 /* On Windows it's possible to calculate the _MP and _MS from CT_CTYPE1
742 * and CT_CTYPE3. But as of Wine 0.9.43 we return wrong values what makes
743 * it hard. As this is set only for codepage 932 we hardcode it what gives
744 * also faster execution.
746 for (i
= 161; i
<= 165; i
++)
747 _mbctype
[i
+ 1] |= _MP
;
748 for (i
= 166; i
<= 223; i
++)
749 _mbctype
[i
+ 1] |= _MS
;
752 MSVCRT___lc_collate_cp
= MSVCRT___lc_codepage
= newcp
;
753 TRACE("(%d) -> %d\n", cp
, MSVCRT___lc_codepage
);
758 /*********************************************************************
759 * ___lc_handle_func (MSVCRT.@)
761 HANDLE
* CDECL
___lc_handle_func(void)
763 return MSVCRT___lc_handle
;
767 /*********************************************************************
768 * ___lc_codepage_func (MSVCRT.@)
770 int CDECL
___lc_codepage_func(void)
772 return MSVCRT___lc_codepage
;
776 /*********************************************************************
777 * _Gettnames (MSVCRT.@)
779 void *_Gettnames(void)
781 FIXME("(void), stub!\n");
785 /*********************************************************************
786 * __lconv_init (MSVCRT.@)
788 void __lconv_init(void)
790 char Char
= (char) UCHAR_MAX
;
792 TRACE("__lconv_init()\n");
794 _lconv
.int_frac_digits
= Char
;
795 _lconv
.frac_digits
= Char
;
796 _lconv
.p_sep_by_space
= _lconv
.n_sep_by_space
= Char
;
797 _lconv
.p_cs_precedes
= _lconv
.n_cs_precedes
= Char
;
798 _lconv
.p_sign_posn
= _lconv
.n_sign_posn
= Char
;
802 /*********************************************************************
803 * _Strftime (MSVCRT.@)
805 const char* _Strftime(char *out
, unsigned int len
, const char *fmt
,
806 const void *tm
, void *foo
)
809 FIXME("(%p %d %s %p %p) stub\n", out
, len
, fmt
, tm
, foo
);
814 /*********************************************************************
815 * _Getdays (MSVCRT.@)
817 const char* _Getdays(void)
819 static const char *MSVCRT_days
= ":Sun:Sunday:Mon:Monday:Tue:Tuesday:Wed:"
820 "Wednesday:Thu:Thursday:Fri:Friday:Sat:Saturday";
821 /* FIXME: Use locale */
822 FIXME("(void) semi-stub\n");
826 /*********************************************************************
827 * _Getmonths (MSVCRT.@)
829 const char* _Getmonths(void)
831 static const char *MSVCRT_months
= ":Jan:January:Feb:February:Mar:March:Apr:"
832 "April:May:May:Jun:June:Jul:July:Aug:August:Sep:September:Oct:"
833 "October:Nov:November:Dec:December";
834 /* FIXME: Use locale */
835 FIXME("(void) semi-stub\n");
836 return MSVCRT_months
;
839 /*********************************************************************
840 * __crtLCMapStringA (MSVCRT.@)
842 int __crtLCMapStringA(
843 LCID lcid
, DWORD mapflags
, const char* src
, int srclen
, char* dst
,
844 int dstlen
, unsigned int codepage
, int xflag
846 TRACE("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n",
847 lcid
,mapflags
,src
,srclen
,dst
,dstlen
,codepage
,xflag
);
848 /* FIXME: A bit incorrect. But msvcrt itself just converts its
849 * arguments to wide strings and then calls LCMapStringW
851 return LCMapStringA(lcid
,mapflags
,src
,srclen
,dst
,dstlen
);
854 /*********************************************************************
855 * __crtLCMapStringW (MSVCRT.@)
857 int __crtLCMapStringW(
858 LCID lcid
, DWORD mapflags
, LPCWSTR src
, int srclen
, LPWSTR dst
,
859 int dstlen
, unsigned int codepage
, int xflag
861 TRACE("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n",
862 lcid
,mapflags
,src
,srclen
,dst
,dstlen
,codepage
,xflag
);
864 return LCMapStringW(lcid
,mapflags
,src
,srclen
,dst
,dstlen
);
867 int CDECL
_getmbcp(void)
869 return MSVCRT___lc_codepage
;
872 /*********************************************************************
873 * ___unguarded_readlc_active_add_func (MSVCRT.@)
875 unsigned int * CDECL
___unguarded_readlc_active_add_func(void)
877 return &__unguarded_readlc_active
;
880 /*********************************************************************
881 * ___setlc_active_func (MSVCRT.@)
883 unsigned int CDECL
___setlc_active_func(void)
885 return __setlc_active
;
888 /*********************************************************************
889 * __crtGetStringTypeW(MSVCRT.@)
891 * This function was accepting different number of arguments in older
892 * versions of msvcrt.
894 BOOL CDECL
__crtGetStringTypeW(DWORD unk
, DWORD type
,
895 wchar_t *buffer
, int len
, WORD
*out
)
897 FIXME("(unk %x, type %x, wstr %p(%d), %p) partial stub\n",
898 unk
, type
, buffer
, len
, out
);
900 return GetStringTypeW(type
, buffer
, len
, out
);