kernel32: Implement LCMAP_FULLWIDTH.
Signed-off-by: Akihiro Sagawa <sagawa.aki@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
410a9832d1
commit
85cff1717d
|
@ -3111,6 +3111,122 @@ BOOL WINAPI GetStringTypeExA( LCID locale, DWORD type, LPCSTR src, INT count, LP
|
|||
return GetStringTypeA(locale, type, src, count, chartype);
|
||||
}
|
||||
|
||||
/* compose a full-width katakana. return consumed source characters. */
|
||||
static INT compose_katakana( LPCWSTR src, INT srclen, LPWSTR dst )
|
||||
{
|
||||
const static BYTE katakana_map[] = {
|
||||
/* */ 0x02, 0x0c, 0x0d, 0x01, 0xfb, 0xf2, 0xa1, /* U+FF61- */
|
||||
0xa3, 0xa5, 0xa7, 0xa9, 0xe3, 0xe5, 0xe7, 0xc3, /* U+FF68- */
|
||||
0xfc, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xab, 0xad, /* U+FF70- */
|
||||
0xaf, 0xb1, 0xb3, 0xb5, 0xb7, 0xb9, 0xbb, 0xbd, /* U+FF78- */
|
||||
0xbf, 0xc1, 0xc4, 0xc6, 0xc8, 0xca, 0xcb, 0xcc, /* U+FF80- */
|
||||
0xcd, 0xce, 0xcf, 0xd2, 0xd5, 0xd8, 0xdb, 0xde, /* U+FF88- */
|
||||
0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe6, 0xe8, 0xe9, /* U+FF90- */
|
||||
0xea, 0xeb, 0xec, 0xed, 0xef, 0xf3, 0x99, 0x9a, /* U+FF98- */
|
||||
};
|
||||
WCHAR before, dummy;
|
||||
|
||||
if (!dst)
|
||||
dst = &dummy;
|
||||
|
||||
switch (*src)
|
||||
{
|
||||
case 0x309b: case 0x309c:
|
||||
*dst = *src - 2;
|
||||
return 1;
|
||||
case 0x30f0: case 0x30f1: case 0x30fd:
|
||||
*dst = *src;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
int shift = *src - 0xff61;
|
||||
if (shift < 0 || shift >= sizeof(katakana_map)/sizeof(katakana_map[0]) )
|
||||
return 0;
|
||||
else
|
||||
*dst = katakana_map[shift] | 0x3000;
|
||||
}
|
||||
}
|
||||
|
||||
if (srclen <= 1)
|
||||
return 1;
|
||||
|
||||
before = *dst;
|
||||
|
||||
/* datakuten (voiced sound) */
|
||||
if (*(src + 1) == 0xff9e)
|
||||
{
|
||||
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 */
|
||||
}
|
||||
|
||||
/* handakuten (semi-voiced sound) */
|
||||
if (*(src + 1) == 0xff9f)
|
||||
if (*src >= 0xff8a && *src <= 0xff8e)
|
||||
*dst += 2;
|
||||
|
||||
return (*dst != before) ? 2 : 1;
|
||||
}
|
||||
|
||||
/* map one or two half-width characters to one full-width character */
|
||||
static INT map_to_fullwidth( LPCWSTR src, INT srclen, LPWSTR dst )
|
||||
{
|
||||
INT n;
|
||||
|
||||
if (*src <= '~' && *src > ' ' && *src != '\\')
|
||||
*dst = *src - 0x20 + 0xff00;
|
||||
else if (*src == ' ')
|
||||
*dst = 0x3000;
|
||||
else if (*src <= 0x00af && *src >= 0x00a2)
|
||||
{
|
||||
const static BYTE misc_symbols_table[] = {
|
||||
0xe0, 0xe1, 0x00, 0xe5, 0xe4, 0x00, 0x00, /* U+00A2- */
|
||||
0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0xe3 /* U+00A9- */
|
||||
};
|
||||
if (misc_symbols_table[*src - 0x00a2])
|
||||
*dst = misc_symbols_table[*src - 0x00a2] | 0xff00;
|
||||
else
|
||||
*dst = *src;
|
||||
}
|
||||
else if (*src == 0x20a9) /* WON SIGN */
|
||||
*dst = 0xffe6;
|
||||
else if ((n = compose_katakana(src, srclen, dst)) > 0)
|
||||
return n;
|
||||
else if (*src >= 0xffa0 && *src <= 0xffdc)
|
||||
{
|
||||
const static BYTE hangul_mapping_table[] = {
|
||||
0x64, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* U+FFA0- */
|
||||
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* U+FFA8- */
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* U+FFB0- */
|
||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x00, /* U+FFB8- */
|
||||
0x00, 0x00, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, /* U+FFC0- */
|
||||
0x00, 0x00, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, /* U+FFC8- */
|
||||
0x00, 0x00, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, /* U+FFD0- */
|
||||
0x00, 0x00, 0x61, 0x62, 0x63 /* U+FFD8- */
|
||||
};
|
||||
|
||||
if (hangul_mapping_table[*src - 0xffa0])
|
||||
*dst = hangul_mapping_table[*src - 0xffa0] | 0x3100;
|
||||
else
|
||||
*dst = *src;
|
||||
}
|
||||
else
|
||||
*dst = *src;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* LCMapStringEx (KERNEL32.@)
|
||||
*
|
||||
|
@ -3194,7 +3310,7 @@ INT WINAPI LCMapStringEx(LPCWSTR name, DWORD flags, LPCWSTR src, INT srclen, LPW
|
|||
}
|
||||
if (((flags & (NORM_IGNORENONSPACE | NORM_IGNORESYMBOLS)) &&
|
||||
(flags & ~(NORM_IGNORENONSPACE | NORM_IGNORESYMBOLS))) ||
|
||||
((flags & (LCMAP_HIRAGANA | LCMAP_KATAKANA)) &&
|
||||
((flags & (LCMAP_HIRAGANA | LCMAP_KATAKANA | LCMAP_FULLWIDTH)) &&
|
||||
(flags & (LCMAP_SIMPLIFIED_CHINESE | LCMAP_TRADITIONAL_CHINESE))))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_FLAGS);
|
||||
|
@ -3222,6 +3338,17 @@ INT WINAPI LCMapStringEx(LPCWSTR name, DWORD flags, LPCWSTR src, INT srclen, LPW
|
|||
len++;
|
||||
}
|
||||
}
|
||||
else if (flags & LCMAP_FULLWIDTH)
|
||||
{
|
||||
for (len = 0; srclen; src++, srclen--, len++)
|
||||
{
|
||||
if (compose_katakana(src, srclen, NULL) == 2)
|
||||
{
|
||||
src++;
|
||||
srclen--;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
len = srclen;
|
||||
return len;
|
||||
|
@ -3246,6 +3373,49 @@ INT WINAPI LCMapStringEx(LPCWSTR name, DWORD flags, LPCWSTR src, INT srclen, LPW
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (flags & (LCMAP_FULLWIDTH | LCMAP_HALFWIDTH | LCMAP_HIRAGANA | LCMAP_KATAKANA))
|
||||
{
|
||||
for (len = dstlen, dst_ptr = dst; len && srclen; src++, srclen--, len--, dst_ptr++)
|
||||
{
|
||||
WCHAR wch;
|
||||
if (flags & LCMAP_FULLWIDTH)
|
||||
{
|
||||
/* 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--;
|
||||
}
|
||||
}
|
||||
else
|
||||
wch = *src;
|
||||
|
||||
if (flags & LCMAP_KATAKANA)
|
||||
{
|
||||
/* map hiragana to katakana, e.g. U+3041 -> U+30A1.
|
||||
we can't use C3_HIRAGANA as some characters can't map to katakana */
|
||||
if ((wch >= 0x3041 && wch <= 0x3096) ||
|
||||
wch == 0x309D || wch == 0x309E)
|
||||
wch += 0x60;
|
||||
}
|
||||
else if (flags & LCMAP_HIRAGANA)
|
||||
{
|
||||
/* map katakana to hiragana, e.g. U+30A1 -> U+3041.
|
||||
we can't use C3_KATAKANA as some characters can't map to hiragana */
|
||||
if ((wch >= 0x30A1 && wch <= 0x30F6) ||
|
||||
wch == 0x30FD || wch == 0x30FE)
|
||||
wch -= 0x60;
|
||||
}
|
||||
*dst_ptr = wch;
|
||||
}
|
||||
if (!(flags & (LCMAP_UPPERCASE | LCMAP_LOWERCASE)))
|
||||
goto done;
|
||||
|
||||
srclen = dst_ptr - dst;
|
||||
src = dst;
|
||||
}
|
||||
|
||||
if (flags & LCMAP_UPPERCASE)
|
||||
{
|
||||
for (len = dstlen, dst_ptr = dst; srclen && len; src++, srclen--)
|
||||
|
@ -3270,29 +3440,6 @@ INT WINAPI LCMapStringEx(LPCWSTR name, DWORD flags, LPCWSTR src, INT srclen, LPW
|
|||
srclen -= len;
|
||||
}
|
||||
|
||||
if (flags & LCMAP_HIRAGANA)
|
||||
{
|
||||
/* map katakana to hiragana, e.g. U+30A1 -> U+3041.
|
||||
we can't use C3_KATAKANA as some characters can't map to hiragana */
|
||||
for (len = dst_ptr - dst, dst_ptr = dst; len; len--, dst_ptr++)
|
||||
{
|
||||
if ((*dst_ptr >= 0x30A1 && *dst_ptr <= 0x30F6) ||
|
||||
*dst_ptr == 0x30FD || *dst_ptr == 0x30FE)
|
||||
*dst_ptr -= 0x60;
|
||||
}
|
||||
}
|
||||
else if (flags & LCMAP_KATAKANA)
|
||||
{
|
||||
/* map hiragana to katakana, e.g. U+3041 -> U+30A1.
|
||||
we can't use C3_HIRAGANA as some characters can't map to katakana */
|
||||
for (len = dst_ptr - dst, dst_ptr = dst; len; len--, dst_ptr++)
|
||||
{
|
||||
if ((*dst_ptr >= 0x3041 && *dst_ptr <= 0x3096) ||
|
||||
*dst_ptr == 0x309D || *dst_ptr == 0x309E)
|
||||
*dst_ptr += 0x60;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (srclen)
|
||||
{
|
||||
|
|
|
@ -2214,6 +2214,10 @@ static const DWORD lcmap_invalid_flags[] = {
|
|||
LCMAP_KATAKANA | NORM_IGNORESYMBOLS,
|
||||
LCMAP_KATAKANA | LCMAP_SIMPLIFIED_CHINESE,
|
||||
LCMAP_KATAKANA | LCMAP_TRADITIONAL_CHINESE,
|
||||
LCMAP_FULLWIDTH | NORM_IGNORENONSPACE,
|
||||
LCMAP_FULLWIDTH | NORM_IGNORESYMBOLS,
|
||||
LCMAP_FULLWIDTH | LCMAP_SIMPLIFIED_CHINESE,
|
||||
LCMAP_FULLWIDTH | LCMAP_TRADITIONAL_CHINESE,
|
||||
};
|
||||
|
||||
static void test_LCMapStringA(void)
|
||||
|
@ -2461,9 +2465,9 @@ static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *f
|
|||
/* test LCMAP_FULLWIDTH */
|
||||
ret = func_ptr(LCMAP_FULLWIDTH,
|
||||
halfwidth_text, -1, buf, sizeof(buf)/sizeof(WCHAR));
|
||||
todo_wine ok(ret == lstrlenW(japanese_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
|
||||
ok(ret == lstrlenW(japanese_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
|
||||
ret, GetLastError(), lstrlenW(japanese_text) + 1);
|
||||
todo_wine ok(!lstrcmpW(buf, japanese_text), "%s string compare mismatch\n", func_name);
|
||||
ok(!lstrcmpW(buf, japanese_text), "%s string compare mismatch\n", func_name);
|
||||
|
||||
ret2 = func_ptr(LCMAP_FULLWIDTH, halfwidth_text, -1, NULL, 0);
|
||||
ok(ret == ret2, "%s ret %d, expected value %d\n", func_name, ret2, ret);
|
||||
|
@ -2472,9 +2476,9 @@ static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *f
|
|||
(half-width katakana is converted into full-wdith hiragana) */
|
||||
ret = func_ptr(LCMAP_FULLWIDTH | LCMAP_HIRAGANA,
|
||||
halfwidth_text, -1, buf, sizeof(buf)/sizeof(WCHAR));
|
||||
todo_wine ok(ret == lstrlenW(hiragana_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
|
||||
ok(ret == lstrlenW(hiragana_text) + 1, "%s ret %d, error %d, expected value %d\n", func_name,
|
||||
ret, GetLastError(), lstrlenW(hiragana_text) + 1);
|
||||
todo_wine ok(!lstrcmpW(buf, hiragana_text), "%s string compare mismatch\n", func_name);
|
||||
ok(!lstrcmpW(buf, hiragana_text), "%s string compare mismatch\n", func_name);
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue