[PATCH v2 0/4] MR8198: ucrtbase: Fix case mapping and ctype1 info for UTF8 locale.
-- v2: ucrtbase: Fix case mapping and ctype1 tables for utf8 locale. ucrtbase: Fix CP_UTF8 handling in _tolower_l. ucrtbase: Fix CP_UTF8 handling in _toupper_l. msvcrt: Print FIXME when WideCharToMultiByte() fails in create_locinfo(). https://gitlab.winehq.org/wine/wine/-/merge_requests/8198
From: Paul Gofman <pgofman(a)codeweavers.com> --- dlls/msvcrt/locale.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index 5fdede174a0..6fc45b3bdbe 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -1292,7 +1292,7 @@ static pthreadlocinfo create_locinfo(int category, char buf[256]; BOOL sname_match; wchar_t wbuf[256], map_buf[256]; - int i; + int i, ret; TRACE("(%d %s)\n", category, locale); @@ -1514,9 +1514,13 @@ static pthreadlocinfo create_locinfo(int category, MultiByteToWideChar(locinfo->lc_codepage, 0, buf, 256, wbuf, 256); LCMapStringW(LOCALE_INVARIANT, LCMAP_LOWERCASE, wbuf, 256, map_buf, 256); - WideCharToMultiByte(locinfo->lc_codepage, 0, map_buf, 256, (char *)locinfo->pclmap, 256, NULL, NULL); + if ((ret = WideCharToMultiByte(locinfo->lc_codepage, 0, map_buf, 256, + (char *)locinfo->pclmap, 256, NULL, NULL)) != 256) + FIXME("WideCharToMultiByte failed, ret %d, error %lu.\n", ret, GetLastError()); LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, wbuf, 256, map_buf, 256); - WideCharToMultiByte(locinfo->lc_codepage, 0, map_buf, 256, (char *)locinfo->pcumap, 256, NULL, NULL); + if ((ret = WideCharToMultiByte(locinfo->lc_codepage, 0, map_buf, 256, + (char *)locinfo->pcumap, 256, NULL, NULL)) != 256) + FIXME("WideCharToMultiByte failed, ret %d, error %lu.\n", ret, GetLastError()); } else { locinfo->lc_clike = 1; locinfo->mb_cur_max = 1; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/8198
From: Piotr Caban <piotr(a)codeweavers.com> --- dlls/msvcrt/ctype.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dlls/msvcrt/ctype.c b/dlls/msvcrt/ctype.c index 1297bc56046..89d25e5e5e5 100644 --- a/dlls/msvcrt/ctype.c +++ b/dlls/msvcrt/ctype.c @@ -483,9 +483,9 @@ int CDECL _toupper_l(int c, _locale_t locale) if((unsigned)c < 256) { - if(locinfo->pctype[c] & _LEADBYTE) - return c; - return locinfo->pcumap[c]; + if(locinfo->pctype[c] & _LOWER) + return locinfo->pcumap[c]; + return c; } if(locinfo->pctype[(c>>8)&255] & _LEADBYTE) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/8198
From: Piotr Caban <piotr(a)codeweavers.com> --- dlls/msvcrt/ctype.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dlls/msvcrt/ctype.c b/dlls/msvcrt/ctype.c index 89d25e5e5e5..ddb7e7ab9cc 100644 --- a/dlls/msvcrt/ctype.c +++ b/dlls/msvcrt/ctype.c @@ -541,9 +541,9 @@ int CDECL _tolower_l(int c, _locale_t locale) if((unsigned)c < 256) { - if(locinfo->pctype[c] & _LEADBYTE) - return c; - return locinfo->pclmap[c]; + if(locinfo->pctype[c] & _UPPER) + return locinfo->pclmap[c]; + return c; } if(locinfo->pctype[(c>>8)&255] & _LEADBYTE) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/8198
From: Piotr Caban <piotr(a)codeweavers.com> --- dlls/msvcrt/locale.c | 7 ++++++- dlls/ucrtbase/tests/file.c | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index 6fc45b3bdbe..380571b72fc 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -1506,7 +1506,12 @@ static pthreadlocinfo create_locinfo(int category, locinfo->ctype1[j+1] |= _LEADBYTE; for(i=0; i<256; i++) { - if(locinfo->pctype[i] & _LEADBYTE) + if (locinfo->lc_codepage == CP_UTF8) + { + buf[i] = (i >= 0x80) ? ' ' : i; + if (i >= 0x80) locinfo->ctype1[i+1] = (i >= 0xc2 && i <= 0xf4) ? _LEADBYTE : 0; + } + else if(locinfo->pctype[i] & _LEADBYTE) buf[i] = ' '; else buf[i] = i; diff --git a/dlls/ucrtbase/tests/file.c b/dlls/ucrtbase/tests/file.c index d5303a6020c..47971c76f95 100644 --- a/dlls/ucrtbase/tests/file.c +++ b/dlls/ucrtbase/tests/file.c @@ -232,6 +232,7 @@ static void test_utf8(const char *argv0) intptr_t hfind, hproc; WCHAR bufW[256], *pW; struct _stat64 stat; + unsigned int i; FILE *f; int ret; @@ -241,6 +242,24 @@ static void test_utf8(const char *argv0) return; } + for (i = 128; i < 256; ++i) + { + unsigned int v; + + winetest_push_context("%#x", i); + v = tolower(i); + ok(i == v, "got %#x.\n", v); + v = toupper(i); + ok(i == v, "got %#x.\n", v); + + v = _isctype(i, ~0u); + if (i >= 0xc2 && i <= 0xf4) + ok(v == _LEADBYTE, "got %#x.\n", v); + else + ok(!v, "got %#x.\n", v); + winetest_pop_context(); + } + ret = _mkdir(dir); if (ret == -1 && errno == ENOENT) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/8198
On Wed Jun 4 21:06:34 2025 +0000, Piotr Caban wrote:
Can you push these patches to the MR? I prefer this solution since it makes create_locinfo simpler (and the function is already a hard to review mess). Also depending on character case makes more sense in tolower/toupper functions. Done.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/8198#note_105410
Unrelated here, but we are probably also missing proper character length detection for UTF8 locale across the board. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/8198#note_105412
This merge request was approved by Paul Gofman. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/8198
This merge request was approved by Piotr Caban. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/8198
participants (4)
-
Paul Gofman -
Paul Gofman (@gofman) -
Piotr Caban -
Piotr Caban (@piotr)