Module: wine Branch: master Commit: cd44979ce1794a092a4c2b99c74d49ed88d4098d URL: https://source.winehq.org/git/wine.git/?a=commit;h=cd44979ce1794a092a4c2b99c...
Author: Alexandre Julliard julliard@winehq.org Date: Thu Jun 2 09:56:19 2022 +0200
kernelbase: Add a helper function to map an entire buffer to full width.
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/kernel32/tests/locale.c | 6 +++ dlls/kernelbase/locale.c | 111 ++++++++++++++++++++++--------------------- 2 files changed, 64 insertions(+), 53 deletions(-)
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c index 125d0c1f2ca..87c12430dac 100644 --- a/dlls/kernel32/tests/locale.c +++ b/dlls/kernel32/tests/locale.c @@ -2490,6 +2490,12 @@ static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *f ret2 = func_ptr(LCMAP_FULLWIDTH | LCMAP_HIRAGANA, halfwidth_text, -1, NULL, 0); ok(ret == ret2, "%s ret %d, expected value %d\n", func_name, ret, ret2);
+ /* LCMAP_FULLWIDTH | LCMAP_KATAKANA maps to full-width first */ + ret = func_ptr(LCMAP_FULLWIDTH | LCMAP_KATAKANA, halfwidth_text, -1, buf, ARRAY_SIZE(buf)); + ok(ret == lstrlenW(katakana_text) + 1, "%s ret %d, error %ld, expected value %d\n", func_name, + ret, GetLastError(), lstrlenW(katakana_text) + 1); + ok(!lstrcmpW(buf, katakana_text), "%s string compare mismatch\n", func_name); + /* test LCMAP_HALFWIDTH */ ret = func_ptr(LCMAP_HALFWIDTH, japanese_text, -1, buf, ARRAY_SIZE(buf)); ok(ret == lstrlenW(halfwidth_text) + 1, "%s ret %d, error %ld, expected value %d\n", func_name, diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c index 0fccc29bc6f..a0e4a74658f 100644 --- a/dlls/kernelbase/locale.c +++ b/dlls/kernelbase/locale.c @@ -3901,40 +3901,53 @@ static int find_substring( const struct sortguid *sortid, DWORD flags, const WCH }
-/* compose a full-width katakana. return consumed source characters. */ -static int map_to_fullwidth( const WCHAR *src, int srclen, WCHAR *dst ) -{ - *dst = casemap( charmaps[CHARMAP_FULLWIDTH], *src ); - if (srclen <= 1) return 1; - - switch (src[1]) - { - case 0xff9e: /* datakuten (voiced sound) */ - if ((*src >= 0xff76 && *src <= 0xff84) || (*src >= 0xff8a && *src <= 0xff8e) || *src == 0x30fd) - *dst += 1; - else if (*src == 0xff73) - *dst = 0x30f4; /* KATAKANA LETTER VU */ - else if (*src == 0xff9c) - *dst = 0x30f7; /* KATAKANA LETTER VA */ - else if (*src == 0x30f0) - *dst = 0x30f8; /* KATAKANA LETTER VI */ - else if (*src == 0x30f1) - *dst = 0x30f9; /* KATAKANA LETTER VE */ - else if (*src == 0xff66) - *dst = 0x30fa; /* KATAKANA LETTER VO */ - else - return 1; - break; - case 0xff9f: /* handakuten (semi-voiced sound) */ - if (*src >= 0xff8a && *src <= 0xff8e) - *dst += 2; - else - return 1; - break; - default: - return 1; +/* map buffer to full-width katakana */ +static int map_to_fullwidth( const WCHAR *src, int srclen, WCHAR *dst, int dstlen ) +{ + int pos; + + for (pos = 0; srclen; pos++, src++, srclen--) + { + WCHAR wch = casemap( charmaps[CHARMAP_FULLWIDTH], *src ); + if (srclen > 1) + { + switch (src[1]) + { + case 0xff9e: /* dakuten (voiced sound) */ + if ((*src >= 0xff76 && *src <= 0xff84) || + (*src >= 0xff8a && *src <= 0xff8e) || + *src == 0x30fd) + wch++; + else if (*src == 0xff73) + wch = 0x30f4; /* KATAKANA LETTER VU */ + else if (*src == 0xff9c) + wch = 0x30f7; /* KATAKANA LETTER VA */ + else if (*src == 0x30f0) + wch = 0x30f8; /* KATAKANA LETTER VI */ + else if (*src == 0x30f1) + wch = 0x30f9; /* KATAKANA LETTER VE */ + else if (*src == 0xff66) + wch = 0x30fa; /* KATAKANA LETTER VO */ + else + break; + src++; + srclen--; + break; + case 0xff9f: /* handakuten (semi-voiced sound) */ + if (*src >= 0xff8a && *src <= 0xff8e) + { + wch += 2; + src++; + srclen--; + } + break; + default: + break; + } + } + if (pos < dstlen) dst[pos] = wch; } - return 2; + return pos; }
/* map single full-width character to single or double half-width characters. */ @@ -6373,15 +6386,7 @@ INT WINAPI DECLSPEC_HOTPATCH LCMapStringEx( const WCHAR *locale, DWORD flags, co } else if (flags & LCMAP_FULLWIDTH) { - WCHAR wch; - for (len = 0; srclen; src++, srclen--, len++) - { - if (map_to_fullwidth( src, srclen, &wch ) == 2) - { - src++; - srclen--; - } - } + len = map_to_fullwidth( src, srclen, NULL, 0 ); } else if (flags & LCMAP_HALFWIDTH) { @@ -6429,20 +6434,20 @@ INT WINAPI DECLSPEC_HOTPATCH LCMapStringEx( const WCHAR *locale, DWORD flags, co
if (flags & (LCMAP_FULLWIDTH | LCMAP_HALFWIDTH | LCMAP_HIRAGANA | LCMAP_KATAKANA)) { - for (len = dstlen, dst_ptr = dst; len && srclen; src++, srclen--, len--, dst_ptr++) + if (flags & LCMAP_FULLWIDTH) { - WCHAR wch; - if (flags & LCMAP_FULLWIDTH) + len = map_to_fullwidth( src, srclen, dst, dstlen ); + if (dstlen && dstlen < len) { - /* map half-width character to full-width one, - e.g. U+FF71 -> U+30A2, U+FF8C U+FF9F -> U+30D7. */ - if (map_to_fullwidth( src, srclen, &wch ) == 2) - { - src++; - srclen--; - } + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return 0; } - else wch = *src; + srclen = len; + src = dst; + } + for (len = dstlen, dst_ptr = dst; len && srclen; src++, srclen--, len--, dst_ptr++) + { + WCHAR wch = *src;
if (flags & LCMAP_KATAKANA) wch = casemap( charmaps[CHARMAP_KATAKANA], wch ); else if (flags & LCMAP_HIRAGANA) wch = casemap( charmaps[CHARMAP_HIRAGANA], wch );