Commit f55192aa authored by Piotr Caban's avatar Piotr Caban Committed by Alexandre Julliard

msvcr120: Add ___lc_locale_name_func implementation.

parent 7a89251c
...@@ -893,7 +893,7 @@ ...@@ -893,7 +893,7 @@
@ stub __TypeMatch @ stub __TypeMatch
@ cdecl ___lc_codepage_func() @ cdecl ___lc_codepage_func()
@ cdecl ___lc_collate_cp_func() @ cdecl ___lc_collate_cp_func()
@ stub ___lc_locale_name_func @ cdecl ___lc_locale_name_func()
@ cdecl ___mb_cur_max_func() MSVCRT____mb_cur_max_func @ cdecl ___mb_cur_max_func() MSVCRT____mb_cur_max_func
@ cdecl ___mb_cur_max_l_func(ptr) @ cdecl ___mb_cur_max_l_func(ptr)
@ cdecl ___setlc_active_func() MSVCRT____setlc_active_func @ cdecl ___setlc_active_func() MSVCRT____setlc_active_func
......
...@@ -876,7 +876,7 @@ ...@@ -876,7 +876,7 @@
@ stub __TypeMatch @ stub __TypeMatch
@ cdecl ___lc_codepage_func() @ cdecl ___lc_codepage_func()
@ cdecl ___lc_collate_cp_func() @ cdecl ___lc_collate_cp_func()
@ stub ___lc_locale_name_func @ cdecl ___lc_locale_name_func()
@ cdecl ___mb_cur_max_func() MSVCRT____mb_cur_max_func @ cdecl ___mb_cur_max_func() MSVCRT____mb_cur_max_func
@ cdecl ___mb_cur_max_l_func(ptr) @ cdecl ___mb_cur_max_l_func(ptr)
@ cdecl ___setlc_active_func() MSVCRT____setlc_active_func @ cdecl ___setlc_active_func() MSVCRT____setlc_active_func
......
...@@ -63,6 +63,7 @@ static struct MSVCRT_lconv* (CDECL *p_localeconv)(void); ...@@ -63,6 +63,7 @@ static struct MSVCRT_lconv* (CDECL *p_localeconv)(void);
static size_t (CDECL *p_wcstombs_s)(size_t *ret, char* dest, size_t sz, const wchar_t* src, size_t max); static size_t (CDECL *p_wcstombs_s)(size_t *ret, char* dest, size_t sz, const wchar_t* src, size_t max);
static int (CDECL *p__dsign)(double); static int (CDECL *p__dsign)(double);
static int (CDECL *p__fdsign)(float); static int (CDECL *p__fdsign)(float);
static wchar_t** (CDECL *p____lc_locale_name_func)(void);
static BOOL init(void) static BOOL init(void)
{ {
...@@ -80,6 +81,7 @@ static BOOL init(void) ...@@ -80,6 +81,7 @@ static BOOL init(void)
p_wcstombs_s = (void*)GetProcAddress(module, "wcstombs_s"); p_wcstombs_s = (void*)GetProcAddress(module, "wcstombs_s");
p__dsign = (void*)GetProcAddress(module, "_dsign"); p__dsign = (void*)GetProcAddress(module, "_dsign");
p__fdsign = (void*)GetProcAddress(module, "_fdsign"); p__fdsign = (void*)GetProcAddress(module, "_fdsign");
p____lc_locale_name_func = (void*)GetProcAddress(module, "___lc_locale_name_func");
return TRUE; return TRUE;
} }
...@@ -171,9 +173,58 @@ static void test__dsign(void) ...@@ -171,9 +173,58 @@ static void test__dsign(void)
ok(ret == 0x8000, "p_fdsign(-1) = %x\n", ret); ok(ret == 0x8000, "p_fdsign(-1) = %x\n", ret);
} }
static void test____lc_locale_name_func(void)
{
struct {
const char *locale;
const WCHAR name[10];
const WCHAR broken_name[10];
BOOL todo;
} tests[] = {
{ "American", {'e','n',0}, {'e','n','-','U','S',0} },
{ "Belgian", {'n','l','-','B','E',0} },
{ "Chinese", {'z','h',0}, {'z','h','-','C','N',0}, TRUE },
{ "Dutch", {'n','l',0}, {'n','l','-','N','L',0} },
{ "English", {'e','n',0}, {'e','n','-','U','S',0} },
{ "French", {'f','r',0}, {'f','r','-','F','R',0} },
{ "German", {'d','e',0}, {'d','e','-','D','E',0} },
{ "Hungarian", {'h','u',0}, {'h','u','-','H','U',0} },
{ "Icelandic", {'i','s',0}, {'i','s','-','I','S',0} },
{ "Japanese", {'j','a',0}, {'j','a','-','J','P',0} },
{ "Korean", {'k','o',0}, {'k','o','-','K','R',0} }
};
int i, j;
wchar_t **lc_names;
for(i=0; i<sizeof(tests)/sizeof(*tests); i++) {
if(!p_setlocale(LC_ALL, tests[i].locale))
continue;
lc_names = p____lc_locale_name_func();
ok(lc_names[0] == NULL, "%d - lc_names[0] = %s\n", i, wine_dbgstr_w(lc_names[0]));
if(tests[i].todo) {
todo_wine ok(!lstrcmpW(lc_names[1], tests[i].name) || broken(!lstrcmpW(lc_names[1], tests[i].broken_name)),
"%d - lc_names[1] = %s\n", i, wine_dbgstr_w(lc_names[1]));
} else {
ok(!lstrcmpW(lc_names[1], tests[i].name) || broken(!lstrcmpW(lc_names[1], tests[i].broken_name)),
"%d - lc_names[1] = %s\n", i, wine_dbgstr_w(lc_names[1]));
}
for(j=LC_MIN+2; j<=LC_MAX; j++) {
ok(!lstrcmpW(lc_names[1], lc_names[j]), "%d - lc_names[%d] = %s, expected %s\n",
i, j, wine_dbgstr_w(lc_names[j]), wine_dbgstr_w(lc_names[1]));
}
}
p_setlocale(LC_ALL, "C");
lc_names = p____lc_locale_name_func();
ok(!lc_names[1], "___lc_locale_name_func()[1] = %s\n", wine_dbgstr_w(lc_names[1]));
}
START_TEST(msvcr120) START_TEST(msvcr120)
{ {
if (!init()) return; if (!init()) return;
test_lconv(); test_lconv();
test__dsign(); test__dsign();
test____lc_locale_name_func();
} }
...@@ -872,7 +872,7 @@ ...@@ -872,7 +872,7 @@
@ stub __TypeMatch @ stub __TypeMatch
@ cdecl ___lc_codepage_func() msvcr120.___lc_codepage_func @ cdecl ___lc_codepage_func() msvcr120.___lc_codepage_func
@ cdecl ___lc_collate_cp_func() msvcr120.___lc_collate_cp_func @ cdecl ___lc_collate_cp_func() msvcr120.___lc_collate_cp_func
@ stub ___lc_locale_name_func @ cdecl ___lc_locale_name_func() msvcr120.___lc_locale_name_func
@ cdecl ___mb_cur_max_func() msvcr120.___mb_cur_max_func @ cdecl ___mb_cur_max_func() msvcr120.___mb_cur_max_func
@ cdecl ___mb_cur_max_l_func(ptr) msvcr120.___mb_cur_max_l_func @ cdecl ___mb_cur_max_l_func(ptr) msvcr120.___mb_cur_max_l_func
@ cdecl ___setlc_active_func() msvcr120.___setlc_active_func @ cdecl ___setlc_active_func() msvcr120.___setlc_active_func
......
...@@ -684,6 +684,16 @@ LCID* CDECL ___lc_handle_func(void) ...@@ -684,6 +684,16 @@ LCID* CDECL ___lc_handle_func(void)
} }
/********************************************************************* /*********************************************************************
* ___lc_locale_name_func (MSVCR110.@)
*/
#if _MSVCR_VER >= 110
MSVCRT_wchar_t** CDECL ___lc_locale_name_func(void)
{
return get_locinfo()->lc_name;
}
#endif
/*********************************************************************
* ___lc_codepage_func (MSVCRT.@) * ___lc_codepage_func (MSVCRT.@)
*/ */
unsigned int CDECL ___lc_codepage_func(void) unsigned int CDECL ___lc_codepage_func(void)
...@@ -713,6 +723,9 @@ void free_locinfo(MSVCRT_pthreadlocinfo locinfo) ...@@ -713,6 +723,9 @@ void free_locinfo(MSVCRT_pthreadlocinfo locinfo)
for(i=MSVCRT_LC_MIN+1; i<=MSVCRT_LC_MAX; i++) { for(i=MSVCRT_LC_MIN+1; i<=MSVCRT_LC_MAX; i++) {
MSVCRT_free(locinfo->lc_category[i].locale); MSVCRT_free(locinfo->lc_category[i].locale);
MSVCRT_free(locinfo->lc_category[i].refcount); MSVCRT_free(locinfo->lc_category[i].refcount);
#if _MSVCR_VER >= 110
MSVCRT_free(locinfo->lc_name[i]);
#endif
} }
if(locinfo->lconv) { if(locinfo->lconv) {
...@@ -794,6 +807,33 @@ void CDECL MSVCRT__free_locale(MSVCRT__locale_t locale) ...@@ -794,6 +807,33 @@ void CDECL MSVCRT__free_locale(MSVCRT__locale_t locale)
MSVCRT_free(locale); MSVCRT_free(locale);
} }
#if _MSVCR_VER >= 110
static inline BOOL set_lc_locale_name(MSVCRT__locale_t loc, int cat)
{
LCID lcid = loc->locinfo->lc_handle[cat];
WCHAR buf[100];
int len;
len = GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME
|LOCALE_NOUSEROVERRIDE, buf, 100);
if(!len) return FALSE;
if(LocaleNameToLCID(buf, 0) != lcid)
len = LCIDToLocaleName(lcid, buf, 100, 0);
if(!len || !(loc->locinfo->lc_name[cat] = MSVCRT_malloc(len*sizeof(MSVCRT_wchar_t))))
return FALSE;
memcpy(loc->locinfo->lc_name[cat], buf, len*sizeof(MSVCRT_wchar_t));
return TRUE;
}
#else
static inline BOOL set_lc_locale_name(MSVCRT__locale_t loc, int cat)
{
return TRUE;
}
#endif
/********************************************************************* /*********************************************************************
* _create_locale (MSVCRT.@) * _create_locale (MSVCRT.@)
*/ */
...@@ -950,6 +990,11 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) ...@@ -950,6 +990,11 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale)
} }
loc->locinfo->lc_collate_cp = loc->locinfo->lc_id[MSVCRT_LC_COLLATE].wCodePage; loc->locinfo->lc_collate_cp = loc->locinfo->lc_id[MSVCRT_LC_COLLATE].wCodePage;
if(!set_lc_locale_name(loc, MSVCRT_LC_COLLATE)) {
MSVCRT__free_locale(loc);
return NULL;
}
} else } else
loc->locinfo->lc_category[MSVCRT_LC_COLLATE].locale = MSVCRT__strdup("C"); loc->locinfo->lc_category[MSVCRT_LC_COLLATE].locale = MSVCRT__strdup("C");
...@@ -995,6 +1040,11 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) ...@@ -995,6 +1040,11 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale)
for(i=0; cp_info.LeadByte[i+1]!=0; i+=2) for(i=0; cp_info.LeadByte[i+1]!=0; i+=2)
for(j=cp_info.LeadByte[i]; j<=cp_info.LeadByte[i+1]; j++) for(j=cp_info.LeadByte[i]; j<=cp_info.LeadByte[i+1]; j++)
loc->locinfo->ctype1[j+1] |= MSVCRT__LEADBYTE; loc->locinfo->ctype1[j+1] |= MSVCRT__LEADBYTE;
if(!set_lc_locale_name(loc, MSVCRT_LC_CTYPE)) {
MSVCRT__free_locale(loc);
return NULL;
}
} else { } else {
loc->locinfo->lc_clike = 1; loc->locinfo->lc_clike = 1;
loc->locinfo->mb_cur_max = 1; loc->locinfo->mb_cur_max = 1;
...@@ -1229,6 +1279,10 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) ...@@ -1229,6 +1279,10 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale)
} }
#endif #endif
if(!set_lc_locale_name(loc, MSVCRT_LC_MONETARY)) {
MSVCRT__free_locale(loc);
return NULL;
}
} else { } else {
loc->locinfo->lconv->int_curr_symbol = MSVCRT_malloc(sizeof(char)); loc->locinfo->lconv->int_curr_symbol = MSVCRT_malloc(sizeof(char));
loc->locinfo->lconv->currency_symbol = MSVCRT_malloc(sizeof(char)); loc->locinfo->lconv->currency_symbol = MSVCRT_malloc(sizeof(char));
...@@ -1358,6 +1412,10 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) ...@@ -1358,6 +1412,10 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale)
} }
#endif #endif
if(!set_lc_locale_name(loc, MSVCRT_LC_NUMERIC)) {
MSVCRT__free_locale(loc);
return NULL;
}
} else { } else {
loc->locinfo->lconv->decimal_point = MSVCRT_malloc(sizeof(char[2])); loc->locinfo->lconv->decimal_point = MSVCRT_malloc(sizeof(char[2]));
loc->locinfo->lconv->thousands_sep = MSVCRT_malloc(sizeof(char)); loc->locinfo->lconv->thousands_sep = MSVCRT_malloc(sizeof(char));
...@@ -1395,6 +1453,11 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) ...@@ -1395,6 +1453,11 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale)
MSVCRT__free_locale(loc); MSVCRT__free_locale(loc);
return NULL; return NULL;
} }
if(!set_lc_locale_name(loc, MSVCRT_LC_TIME)) {
MSVCRT__free_locale(loc);
return NULL;
}
} else } else
loc->locinfo->lc_category[MSVCRT_LC_TIME].locale = MSVCRT__strdup("C"); loc->locinfo->lc_category[MSVCRT_LC_TIME].locale = MSVCRT__strdup("C");
...@@ -1505,6 +1568,11 @@ char* CDECL MSVCRT_setlocale(int category, const char* locale) ...@@ -1505,6 +1568,11 @@ char* CDECL MSVCRT_setlocale(int category, const char* locale)
swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_COLLATE].refcount, swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_COLLATE].refcount,
(void**)&loc->locinfo->lc_category[MSVCRT_LC_COLLATE].refcount); (void**)&loc->locinfo->lc_category[MSVCRT_LC_COLLATE].refcount);
#if _MSVCR_VER >= 110
swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_COLLATE],
(void**)&loc->locinfo->lc_name[MSVCRT_LC_COLLATE]);
#endif
if(category != MSVCRT_LC_ALL) if(category != MSVCRT_LC_ALL)
break; break;
/* fall through */ /* fall through */
...@@ -1527,6 +1595,11 @@ char* CDECL MSVCRT_setlocale(int category, const char* locale) ...@@ -1527,6 +1595,11 @@ char* CDECL MSVCRT_setlocale(int category, const char* locale)
swap_pointers((void**)&locinfo->pclmap, (void**)&loc->locinfo->pclmap); swap_pointers((void**)&locinfo->pclmap, (void**)&loc->locinfo->pclmap);
swap_pointers((void**)&locinfo->pcumap, (void**)&loc->locinfo->pcumap); swap_pointers((void**)&locinfo->pcumap, (void**)&loc->locinfo->pcumap);
#if _MSVCR_VER >= 110
swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_CTYPE],
(void**)&loc->locinfo->lc_name[MSVCRT_LC_CTYPE]);
#endif
if(category != MSVCRT_LC_ALL) if(category != MSVCRT_LC_ALL)
break; break;
/* fall through */ /* fall through */
...@@ -1577,6 +1650,11 @@ char* CDECL MSVCRT_setlocale(int category, const char* locale) ...@@ -1577,6 +1650,11 @@ char* CDECL MSVCRT_setlocale(int category, const char* locale)
locinfo->lconv->p_sign_posn = loc->locinfo->lconv->p_sign_posn; locinfo->lconv->p_sign_posn = loc->locinfo->lconv->p_sign_posn;
locinfo->lconv->n_sign_posn = loc->locinfo->lconv->n_sign_posn; locinfo->lconv->n_sign_posn = loc->locinfo->lconv->n_sign_posn;
#if _MSVCR_VER >= 110
swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_MONETARY],
(void**)&loc->locinfo->lc_name[MSVCRT_LC_MONETARY]);
#endif
if(category != MSVCRT_LC_ALL) if(category != MSVCRT_LC_ALL)
break; break;
/* fall through */ /* fall through */
...@@ -1602,6 +1680,11 @@ char* CDECL MSVCRT_setlocale(int category, const char* locale) ...@@ -1602,6 +1680,11 @@ char* CDECL MSVCRT_setlocale(int category, const char* locale)
(void**)&loc->locinfo->lconv->_W_thousands_sep); (void**)&loc->locinfo->lconv->_W_thousands_sep);
#endif #endif
#if _MSVCR_VER >= 110
swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_NUMERIC],
(void**)&loc->locinfo->lc_name[MSVCRT_LC_NUMERIC]);
#endif
if(category != MSVCRT_LC_ALL) if(category != MSVCRT_LC_ALL)
break; break;
/* fall through */ /* fall through */
...@@ -1615,6 +1698,11 @@ char* CDECL MSVCRT_setlocale(int category, const char* locale) ...@@ -1615,6 +1698,11 @@ char* CDECL MSVCRT_setlocale(int category, const char* locale)
swap_pointers((void**)&locinfo->lc_time_curr, swap_pointers((void**)&locinfo->lc_time_curr,
(void**)&loc->locinfo->lc_time_curr); (void**)&loc->locinfo->lc_time_curr);
#if _MSVCR_VER >= 110
swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_TIME],
(void**)&loc->locinfo->lc_name[MSVCRT_LC_TIME]);
#endif
if(category != MSVCRT_LC_ALL) if(category != MSVCRT_LC_ALL)
break; break;
} }
......
...@@ -159,7 +159,7 @@ typedef struct MSVCRT_threadlocaleinfostruct { ...@@ -159,7 +159,7 @@ typedef struct MSVCRT_threadlocaleinfostruct {
MSVCRT_LC_ID lc_id[6]; MSVCRT_LC_ID lc_id[6];
struct { struct {
char *locale; char *locale;
wchar_t *wlocale; MSVCRT_wchar_t *wlocale;
int *refcount; int *refcount;
int *wrefcount; int *wrefcount;
} lc_category[6]; } lc_category[6];
...@@ -175,6 +175,9 @@ typedef struct MSVCRT_threadlocaleinfostruct { ...@@ -175,6 +175,9 @@ typedef struct MSVCRT_threadlocaleinfostruct {
unsigned char *pclmap; unsigned char *pclmap;
unsigned char *pcumap; unsigned char *pcumap;
MSVCRT___lc_time_data *lc_time_curr; MSVCRT___lc_time_data *lc_time_curr;
#if _MSVCR_VER >= 110
MSVCRT_wchar_t *lc_name[6];
#endif
} MSVCRT_threadlocinfo; } MSVCRT_threadlocinfo;
typedef struct MSVCRT_threadmbcinfostruct { typedef struct MSVCRT_threadmbcinfostruct {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment