Alexandre Julliard : kernelbase: Add a helper function to map an entire buffer to full width.

Alexandre Julliard julliard at winehq.org
Thu Jun 2 16:26:08 CDT 2022


Module: wine
Branch: master
Commit: cd44979ce1794a092a4c2b99c74d49ed88d4098d
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=cd44979ce1794a092a4c2b99c74d49ed88d4098d

Author: Alexandre Julliard <julliard at 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 at 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 );




More information about the wine-cvs mailing list