mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
ba516ff0f5
This test shows how a console program's thread's language ID changes, or not, when changing the console output code page (or indirectly when starting on/connecting to a new console), depending on whether or not the console is running on a CJK/on a non-CJK system, and the selected code page is a CJK/a non-CJK one. By that, the test indirectly tests the (non-exposed) consoles GetLangId + SetThreadLocale() calls being made under the hood.
1566 lines
49 KiB
C
1566 lines
49 KiB
C
/*
|
|
* PROJECT: ReactOS api tests
|
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
|
* PURPOSE: Tests for i18n console.
|
|
* COPYRIGHT: Copyright 2017-2020 Katayama Hirofumi MZ
|
|
* Copyright 2020-2022 Hermès Bélusca-Maïto
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#define okCURSOR(hCon, c) \
|
|
do { \
|
|
CONSOLE_SCREEN_BUFFER_INFO __sbi; \
|
|
BOOL expect = GetConsoleScreenBufferInfo((hCon), &__sbi) && \
|
|
__sbi.dwCursorPosition.X == (c).X && __sbi.dwCursorPosition.Y == (c).Y; \
|
|
ok(expect, "Expected cursor at (%d,%d), got (%d,%d)\n", \
|
|
(c).X, (c).Y, __sbi.dwCursorPosition.X, __sbi.dwCursorPosition.Y); \
|
|
} while (0)
|
|
|
|
#define ATTR (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
|
|
|
|
static const WCHAR u0414[] = {0x0414, 0}; /* Д */
|
|
static const WCHAR u9580[] = {0x9580, 0}; /* 門 */
|
|
static const WCHAR space[] = {L' ', 0};
|
|
static const WCHAR ideograph_space = (WCHAR)0x3000; /* fullwidth space */
|
|
static const WCHAR s_str[] = {L'A', 0x9580, 'B', 0};
|
|
static const LCID lcidJapanese = MAKELCID(MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT), SORT_DEFAULT);
|
|
static const LCID lcidRussian = MAKELCID(MAKELANGID(LANG_RUSSIAN , SUBLANG_DEFAULT), SORT_DEFAULT);
|
|
|
|
static UINT s_uOEMCP;
|
|
static BOOL s_bIs8Plus;
|
|
|
|
static BOOL IsCJKCodePage(_In_ UINT CodePage)
|
|
{
|
|
switch (CodePage)
|
|
{
|
|
case 932: // Japanese
|
|
case 949: // Korean
|
|
case 1361: // Korean (Johab)
|
|
case 936: // Chinese PRC
|
|
case 950: // Taiwan
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static __inline
|
|
LANGID MapCJKCPToLangId(_In_ UINT CodePage)
|
|
{
|
|
switch (CodePage)
|
|
{
|
|
case 932: // Japanese (Shift-JIS)
|
|
return MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT);
|
|
case 949: // Korean (Hangul/Wansung)
|
|
// case 1361: // Korean (Johab)
|
|
return MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN);
|
|
case 936: // Chinese PRC (Chinese Simplified)
|
|
return MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED);
|
|
case 950: // Taiwan (Chinese Traditional)
|
|
return MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL);
|
|
default:
|
|
return MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
|
|
}
|
|
}
|
|
|
|
static BOOL ChangeOutputCP_(
|
|
_In_ const char* file,
|
|
_In_ int line,
|
|
_In_ UINT CodePage)
|
|
{
|
|
BOOL bSuccess;
|
|
|
|
/* Validate the code page */
|
|
bSuccess = IsValidCodePage(CodePage);
|
|
if (!bSuccess)
|
|
{
|
|
skip_(file, line)("Code page %d not available\n", CodePage);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Set the new code page */
|
|
SetLastError(0xdeadbeef);
|
|
bSuccess = SetConsoleOutputCP(CodePage);
|
|
if (!bSuccess)
|
|
skip_(file, line)("SetConsoleOutputCP(%d) failed with last error %lu\n", CodePage, GetLastError());
|
|
return bSuccess;
|
|
}
|
|
|
|
#define ChangeOutputCP(CodePage) \
|
|
ChangeOutputCP_(__FILE__, __LINE__, CodePage)
|
|
|
|
|
|
#define cmpThreadLangId(file, line, ExpectedLangId) \
|
|
do { \
|
|
LANGID ThreadLangId; \
|
|
ThreadLangId = LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale); \
|
|
trace_((file), (line))("Thread LangId %d, expecting %d...\n", \
|
|
ThreadLangId, (ExpectedLangId)); \
|
|
ok_((file), (line))(ThreadLangId == (ExpectedLangId), \
|
|
"Thread LangId %d, expected %d\n", \
|
|
ThreadLangId, (ExpectedLangId)); \
|
|
} while (0)
|
|
|
|
static BOOL
|
|
doTest_CP_ThreadLang_(
|
|
_In_ const char* file,
|
|
_In_ int line,
|
|
_In_ UINT CodePage,
|
|
_In_ LANGID ExpectedLangId)
|
|
{
|
|
UINT newcp;
|
|
|
|
/* Verify and set the new code page */
|
|
if (!ChangeOutputCP_(file, line, CodePage))
|
|
{
|
|
skip_(file, line)("Code page %d expected to be valid!\n", CodePage);
|
|
return FALSE;
|
|
}
|
|
|
|
newcp = GetConsoleOutputCP();
|
|
ok_(file, line)(newcp == CodePage, "Console output CP is %d, expected %d\n", newcp, CodePage);
|
|
|
|
/* Verify that the thread lang ID is the expected one */
|
|
cmpThreadLangId(file, line, ExpectedLangId);
|
|
return TRUE;
|
|
}
|
|
|
|
#define doTest_CP_ThreadLang(...) \
|
|
doTest_CP_ThreadLang_(__FILE__, __LINE__, ##__VA_ARGS__)
|
|
|
|
static VOID test_CP_ThreadLang(VOID)
|
|
{
|
|
/* Save the initial current thread locale. It is (re)initialized after
|
|
* attaching to a console. Don't use GetThreadLocale() as the latter
|
|
* can return a replacement value in case CurrentLocale is 0. */
|
|
LANGID ThreadLangId = LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale);
|
|
UINT oldcp = GetConsoleOutputCP();
|
|
|
|
if (IsCJKCodePage(s_uOEMCP))
|
|
{
|
|
/* We are on a CJK system */
|
|
|
|
/* Is the console in CJK? If so, current thread should be in CJK language */
|
|
if (!IsCJKCodePage(oldcp))
|
|
{
|
|
skip("CJK system but console CP not in CJK\n");
|
|
}
|
|
else
|
|
{
|
|
/* Check that the thread lang ID matches what the console set */
|
|
LANGID LangId = MapCJKCPToLangId(oldcp);
|
|
cmpThreadLangId(__FILE__, __LINE__, LangId);
|
|
}
|
|
|
|
/* Set the code page to OEM USA (non-CJK codepage that is supported).
|
|
* Verify that the thread lang ID has changed to non-CJK language. */
|
|
doTest_CP_ThreadLang(437, MapCJKCPToLangId(437));
|
|
|
|
/* Set the code page to the default system CJK codepage.
|
|
* Check that the thread lang ID matches what the console set. */
|
|
doTest_CP_ThreadLang(s_uOEMCP, MapCJKCPToLangId(s_uOEMCP));
|
|
}
|
|
else
|
|
{
|
|
/* We are on a non-CJK system */
|
|
|
|
/* Code pages: Japanese, Korean, Chinese Simplified/Traditional */
|
|
UINT CJKCodePages[] = {932, 949, 936, 950};
|
|
UINT newcp;
|
|
USHORT i;
|
|
|
|
/* Switch to a different code page (OEM USA) than the current one.
|
|
* In such setup, the current thread lang ID should not change. */
|
|
newcp = (s_uOEMCP == 437 ? 850 : 437);
|
|
doTest_CP_ThreadLang(newcp, ThreadLangId);
|
|
|
|
/* Try switching to a CJK codepage, if possible, but
|
|
* the thread lang ID should not change either... */
|
|
|
|
/* Retry as long as no valid CJK codepage has been found */
|
|
for (i = 0; i < ARRAYSIZE(CJKCodePages); ++i)
|
|
{
|
|
newcp = CJKCodePages[i];
|
|
if (IsValidCodePage(newcp))
|
|
break; // Found a valid one.
|
|
}
|
|
if (i >= ARRAYSIZE(CJKCodePages))
|
|
{
|
|
/* No valid CJK code pages on the system */
|
|
skip("CJK system but console CP not in CJK\n");
|
|
}
|
|
else
|
|
{
|
|
/* Verify that the thread lang ID remains the same */
|
|
doTest_CP_ThreadLang(newcp, ThreadLangId);
|
|
}
|
|
}
|
|
|
|
/* Restore code page */
|
|
SetConsoleOutputCP(oldcp);
|
|
}
|
|
|
|
|
|
/* Russian Code Page 855 */
|
|
// NOTE that CP 866 can also be used
|
|
static void test_cp855(HANDLE hConOut)
|
|
{
|
|
BOOL ret;
|
|
UINT oldcp;
|
|
int n;
|
|
DWORD len;
|
|
COORD c;
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
int count;
|
|
WCHAR str[32];
|
|
WORD attrs[16];
|
|
|
|
/* Set code page */
|
|
oldcp = GetConsoleOutputCP();
|
|
if (!ChangeOutputCP(855))
|
|
{
|
|
skip("Codepage 855 not available\n");
|
|
return;
|
|
}
|
|
|
|
/* Get info */
|
|
ret = GetConsoleScreenBufferInfo(hConOut, &csbi);
|
|
ok(ret, "GetConsoleScreenBufferInfo failed\n");
|
|
trace("csbi.dwSize.X:%d, csbi.dwSize.Y:%d\n", csbi.dwSize.X, csbi.dwSize.Y);
|
|
count = 200;
|
|
|
|
/* "\u0414" */
|
|
{
|
|
/* Output u0414 "count" times at (0,0) */
|
|
c.X = c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
for (n = 0; n < count; ++n)
|
|
{
|
|
ret = WriteConsoleW(hConOut, u0414, lstrlenW(u0414), &len, NULL);
|
|
ok(ret && len == lstrlenW(u0414), "WriteConsoleW failed\n");
|
|
}
|
|
|
|
/* Check cursor */
|
|
len = count; /* u0414 is normal width in Russian */
|
|
c.X = (SHORT)(len % csbi.dwSize.X);
|
|
c.Y = (SHORT)(len / csbi.dwSize.X);
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* Read characters at (0,0) */
|
|
c.X = c.Y = 0;
|
|
ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
|
|
ok(ret, "ReadConsoleOutputCharacterW failed\n");
|
|
ok_long(len, 6);
|
|
ok_int(str[0], 0x414);
|
|
ok_int(str[1], 0x414);
|
|
ok_int(str[2], 0x414);
|
|
|
|
/* Read attributes at (0,0) */
|
|
c.X = c.Y = 0;
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 6, c, &len);
|
|
ok(ret, "ReadConsoleOutputAttribute failed\n");
|
|
ok_long(len, 6);
|
|
ok_int(attrs[0], ATTR);
|
|
|
|
/* Check cursor */
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
ret = SetConsoleCursorPosition(hConOut, c);
|
|
ok(ret, "SetConsoleCursorPosition failed\n");
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* Fill by space */
|
|
c.X = c.Y = 0;
|
|
FillConsoleOutputCharacterW(hConOut, L' ', csbi.dwSize.X * csbi.dwSize.Y, c, &len);
|
|
|
|
/* Output u0414 "count" times at (1,0) */
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
for (n = 0; n < count; ++n)
|
|
{
|
|
ret = WriteConsoleW(hConOut, u0414, lstrlenW(u0414), &len, NULL);
|
|
ok(ret && len == lstrlenW(u0414), "WriteConsoleW failed\n");
|
|
}
|
|
|
|
/* Check cursor */
|
|
len = 1 + count;
|
|
c.X = (SHORT)(len % csbi.dwSize.X);
|
|
c.Y = (SHORT)(len / csbi.dwSize.X);
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* Read characters at (0,0) */
|
|
c.X = c.Y = 0;
|
|
ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
|
|
ok(ret, "ReadConsoleOutputCharacterW failed\n");
|
|
ok_long(len, 6);
|
|
ok_int(str[0], L' ');
|
|
ok_int(str[1], 0x414);
|
|
ok_int(str[2], 0x414);
|
|
}
|
|
|
|
/* "\u9580" */
|
|
{
|
|
/* Output u9580 "count" times at (0,0) */
|
|
c.X = c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
for (n = 0; n < count; ++n)
|
|
{
|
|
ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
|
|
ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
|
|
}
|
|
|
|
/* Check cursor */
|
|
len = count; /* u9580 is normal width in Russian */
|
|
c.X = (SHORT)(len % csbi.dwSize.X);
|
|
c.Y = (SHORT)(len / csbi.dwSize.X);
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* Check cursor */
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
ret = SetConsoleCursorPosition(hConOut, c);
|
|
ok(ret, "SetConsoleCursorPosition failed\n");
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* Fill by space */
|
|
c.X = c.Y = 0;
|
|
ret = FillConsoleOutputCharacterW(hConOut, L' ', csbi.dwSize.X * csbi.dwSize.Y, c, &len);
|
|
ok(ret, "FillConsoleOutputCharacterW failed\n");
|
|
ok_long(len, csbi.dwSize.X * csbi.dwSize.Y);
|
|
|
|
/* Output u9580 "count" times at (1,0) */
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
for (n = 0; n < count; ++n)
|
|
{
|
|
ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
|
|
ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
|
|
}
|
|
|
|
/* Check cursor */
|
|
len = 1 + count;
|
|
c.X = (SHORT)(len % csbi.dwSize.X);
|
|
c.Y = (SHORT)(len / csbi.dwSize.X);
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* Fill by ideograph space */
|
|
c.X = c.Y = 0;
|
|
ret = FillConsoleOutputCharacterW(hConOut, ideograph_space, csbi.dwSize.X * csbi.dwSize.Y, c, &len);
|
|
ok(ret, "FillConsoleOutputCharacterW failed\n");
|
|
ok_long(len, csbi.dwSize.X * csbi.dwSize.Y);
|
|
|
|
/* Read characters at (0,0) */
|
|
c.X = c.Y = 0;
|
|
ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
|
|
ok(ret, "ReadConsoleOutputCharacterW failed\n");
|
|
ok_long(len, 6);
|
|
ok(str[0] == ideograph_space || str[0] == L'?', "str[0] was: 0x%04X\n", str[0]);
|
|
ok(str[1] == ideograph_space || str[1] == L'?', "str[1] was: 0x%04X\n", str[1]);
|
|
ok(str[2] == ideograph_space || str[2] == L'?', "str[2] was: 0x%04X\n", str[2]);
|
|
|
|
/* Read attributes at (0,0) */
|
|
c.X = c.Y = 0;
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 6, c, &len);
|
|
ok(ret, "ReadConsoleOutputAttribute failed\n");
|
|
ok_long(len, 6);
|
|
ok_int(attrs[0], ATTR);
|
|
|
|
/* Read characters at (1,0) */
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
|
|
ok(ret, "ReadConsoleOutputCharacterW failed\n");
|
|
ok_long(len, 6);
|
|
ok(str[0] == ideograph_space || str[0] == L'?', "str[0] was: 0x%04X\n", str[0]);
|
|
ok(str[1] == ideograph_space || str[1] == L'?', "str[1] was: 0x%04X\n", str[1]);
|
|
ok(str[2] == ideograph_space || str[2] == L'?', "str[2] was: 0x%04X\n", str[2]);
|
|
|
|
/* Output u9580 "count" once at (1,0) */
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
|
|
ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
|
|
|
|
/* Read attributes at (1,0) */
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 1, c, &len);
|
|
ok(ret, "ReadConsoleOutputAttribute failed\n");
|
|
ok_long(len, 1);
|
|
ok_int(attrs[0], ATTR);
|
|
|
|
/* Check cursor */
|
|
c.X = 2;
|
|
c.Y = 0;
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* Read characters at (0,0) */
|
|
c.X = c.Y = 0;
|
|
ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
|
|
ok(ret, "ReadConsoleOutputCharacterW failed\n");
|
|
ok_long(len, 6);
|
|
ok(str[0] == ideograph_space || str[0] == L'?', "str[0] was: 0x%04X\n", str[0]);
|
|
ok(str[1] == u9580[0] || str[1] == L'?', "str[1] was: 0x%04X\n", str[1]);
|
|
ok(str[2] == ideograph_space || str[2] == L'?', "str[2] was: 0x%04X\n", str[2]);
|
|
}
|
|
|
|
/* Restore code page */
|
|
SetConsoleOutputCP(oldcp);
|
|
}
|
|
|
|
/* Japanese Code Page 932 */
|
|
static void test_cp932(HANDLE hConOut)
|
|
{
|
|
BOOL ret;
|
|
UINT oldcp;
|
|
int n;
|
|
DWORD len;
|
|
COORD c, buffSize;
|
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
|
int count;
|
|
WCHAR str[32];
|
|
WORD attrs[16];
|
|
CHAR_INFO buff[16];
|
|
SMALL_RECT sr;
|
|
|
|
/* Set code page */
|
|
oldcp = GetConsoleOutputCP();
|
|
if (!ChangeOutputCP(932))
|
|
{
|
|
skip("Codepage 932 not available\n");
|
|
return;
|
|
}
|
|
|
|
/* Get info */
|
|
ret = GetConsoleScreenBufferInfo(hConOut, &csbi);
|
|
ok(ret, "GetConsoleScreenBufferInfo failed\n");
|
|
trace("csbi.dwSize.X:%d, csbi.dwSize.Y:%d\n", csbi.dwSize.X, csbi.dwSize.Y);
|
|
count = 200;
|
|
|
|
/* "\u0414" */
|
|
{
|
|
/* Output u0414 "count" times at (0,0) */
|
|
c.X = c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
for (n = 0; n < count; ++n)
|
|
{
|
|
ret = WriteConsoleW(hConOut, u0414, lstrlenW(u0414), &len, NULL);
|
|
ok(ret && len == lstrlenW(u0414), "WriteConsoleW failed\n");
|
|
}
|
|
|
|
/* Check cursor */
|
|
GetConsoleScreenBufferInfo(hConOut, &csbi);
|
|
len = count * 2; /* u0414 is fullwidth in Japanese */
|
|
c.X = (SHORT)(len % csbi.dwSize.X);
|
|
c.Y = (SHORT)(len / csbi.dwSize.X);
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* Read characters at (0,0) */
|
|
c.X = c.Y = 0;
|
|
ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
|
|
ok(ret, "ReadConsoleOutputCharacterW failed\n");
|
|
ok_long(len, 3);
|
|
ok_int(str[0], 0x414);
|
|
ok_int(str[1], 0x414);
|
|
ok_int(str[2], 0x414);
|
|
|
|
/* Read attributes at (0,0) */
|
|
c.X = c.Y = 0;
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 6, c, &len);
|
|
ok(ret, "ReadConsoleOutputAttribute failed\n");
|
|
ok_long(len, 6);
|
|
ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(attrs[1], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
|
|
/* Check cursor */
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
ret = SetConsoleCursorPosition(hConOut, c);
|
|
ok(ret, "SetConsoleCursorPosition failed\n");
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* Fill by space */
|
|
c.X = c.Y = 0;
|
|
FillConsoleOutputCharacterW(hConOut, L' ', csbi.dwSize.X * csbi.dwSize.Y, c, &len);
|
|
|
|
/* Output u0414 "count" times at (1,0) */
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
for (n = 0; n < count; ++n)
|
|
{
|
|
ret = WriteConsoleW(hConOut, u0414, lstrlenW(u0414), &len, NULL);
|
|
ok(ret && len == lstrlenW(u0414), "WriteConsoleW failed\n");
|
|
}
|
|
|
|
/* Check cursor */
|
|
len = csbi.dwSize.X + (count - (csbi.dwSize.X - 1) / 2) * 2;
|
|
c.X = (SHORT)(len % csbi.dwSize.X);
|
|
c.Y = (SHORT)(len / csbi.dwSize.X);
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* Read characters at (0,0) */
|
|
c.X = 0;
|
|
c.Y = 0;
|
|
ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
|
|
ok(ret, "ReadConsoleOutputCharacterW failed\n");
|
|
ok_long(len, 4);
|
|
ok_int(str[0], L' ');
|
|
ok_int(str[1], 0x414);
|
|
ok_int(str[2], 0x414);
|
|
}
|
|
|
|
/* "\u9580" */
|
|
{
|
|
/* Output u9580 "count" times at (0,0) */
|
|
c.X = c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
for (n = 0; n < count; ++n)
|
|
{
|
|
ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
|
|
ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
|
|
}
|
|
|
|
/* Check cursor */
|
|
len = count * 2; /* u9580 is fullwidth in Japanese */
|
|
c.X = (SHORT)(len % csbi.dwSize.X);
|
|
c.Y = (SHORT)(len / csbi.dwSize.X);
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* Check cursor */
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
ret = SetConsoleCursorPosition(hConOut, c);
|
|
ok(ret, "SetConsoleCursorPosition failed\n");
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* Fill by space */
|
|
c.X = c.Y = 0;
|
|
ret = FillConsoleOutputCharacterW(hConOut, L' ', csbi.dwSize.X * csbi.dwSize.Y, c, &len);
|
|
ok(ret, "FillConsoleOutputCharacterW failed\n");
|
|
ok_long(len, csbi.dwSize.X * csbi.dwSize.Y);
|
|
|
|
/* Output u9580 "count" times at (1,0) */
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
for (n = 0; n < count; ++n)
|
|
{
|
|
ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
|
|
ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
|
|
}
|
|
|
|
/* Check cursor */
|
|
len = csbi.dwSize.X + (count - (csbi.dwSize.X - 1) / 2) * 2;
|
|
c.X = (SHORT)(len % csbi.dwSize.X);
|
|
c.Y = (SHORT)(len / csbi.dwSize.X);
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* Fill by ideograph space */
|
|
c.X = c.Y = 0;
|
|
ret = FillConsoleOutputCharacterW(hConOut, ideograph_space, csbi.dwSize.X * csbi.dwSize.Y, c, &len);
|
|
ok(ret, "FillConsoleOutputCharacterW failed\n");
|
|
if (s_bIs8Plus)
|
|
ok_long(len, csbi.dwSize.X * csbi.dwSize.Y / 2);
|
|
else
|
|
ok_long(len, csbi.dwSize.X * csbi.dwSize.Y);
|
|
|
|
/* Read characters at (0,0) */
|
|
c.X = c.Y = 0;
|
|
ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
|
|
ok(ret, "ReadConsoleOutputCharacterW failed\n");
|
|
ok_long(len, 3);
|
|
ok_int(str[0], ideograph_space);
|
|
ok_int(str[1], ideograph_space);
|
|
ok_int(str[2], ideograph_space);
|
|
|
|
/* Read attributes at (0,0) */
|
|
c.X = c.Y = 0;
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 6, c, &len);
|
|
ok(ret, "ReadConsoleOutputAttribute failed\n");
|
|
ok_long(len, 6);
|
|
ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(attrs[1], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
ok_int(attrs[2], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(attrs[3], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
ok_int(attrs[4], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(attrs[5], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
|
|
/* Output u9580 "count" once at (1,0) */
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
ret = WriteConsoleW(hConOut, u9580, lstrlenW(u9580), &len, NULL);
|
|
ok(ret && len == lstrlenW(u9580), "WriteConsoleW failed\n");
|
|
|
|
/*
|
|
* Read attributes at (1,0) -
|
|
* Note that if only one attribute of a fullwidth character
|
|
* is retrieved, no leading/trailing byte flag is set!
|
|
*/
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 1, c, &len);
|
|
ok(ret, "ReadConsoleOutputAttribute failed\n");
|
|
ok_long(len, 1);
|
|
ok_int(attrs[0], ATTR);
|
|
|
|
/* Check that the same problem happens for the trailing byte */
|
|
c.X = 2;
|
|
c.Y = 0;
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 1, c, &len);
|
|
ok(ret, "ReadConsoleOutputAttribute failed\n");
|
|
ok_long(len, 1);
|
|
ok_int(attrs[0], ATTR);
|
|
|
|
/* Read attributes at (1,0) */
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 2, c, &len);
|
|
ok(ret, "ReadConsoleOutputAttribute failed\n");
|
|
ok_long(len, 2);
|
|
ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(attrs[1], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
|
|
/* Read attributes at (1,0) */
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 3, c, &len);
|
|
ok(ret, "ReadConsoleOutputAttribute failed\n");
|
|
ok_long(len, 3);
|
|
ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(attrs[1], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
if (s_bIs8Plus)
|
|
ok_int(attrs[2], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
else
|
|
ok_int(attrs[2], ATTR);
|
|
|
|
/* Read attributes at (0,0) */
|
|
c.X = c.Y = 0;
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
|
|
ok(ret, "ReadConsoleOutputAttribute failed\n");
|
|
ok_long(len, 4);
|
|
if (s_bIs8Plus)
|
|
ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
else
|
|
ok_int(attrs[0], ATTR);
|
|
ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(attrs[2], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
if (s_bIs8Plus)
|
|
ok_int(attrs[3], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
else
|
|
ok_int(attrs[3], ATTR);
|
|
|
|
/* Check cursor */
|
|
c.X = 3;
|
|
c.Y = 0;
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* Read characters */
|
|
c.X = c.Y = 0;
|
|
ret = ReadConsoleOutputCharacterW(hConOut, str, 3 * sizeof(WCHAR), c, &len);
|
|
ok(ret, "ReadConsoleOutputCharacterW failed\n");
|
|
if (s_bIs8Plus)
|
|
{
|
|
ok_long(len, 3);
|
|
ok_int(str[0], ideograph_space);
|
|
ok_int(str[1], u9580[0]);
|
|
ok_int(str[2], ideograph_space);
|
|
}
|
|
else
|
|
{
|
|
ok_long(len, 4);
|
|
ok_int(str[0], L' ');
|
|
ok_int(str[1], u9580[0]);
|
|
ok_int(str[2], L' ');
|
|
}
|
|
}
|
|
|
|
/* COMMON_LVB_LEADING_BYTE and COMMON_LVB_TRAILING_BYTE for u0414 */
|
|
{
|
|
/* set cursor */
|
|
c.X = c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* fill by 'A' */
|
|
ret = FillConsoleOutputCharacterW(hConOut, L'A', csbi.dwSize.X * 2, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, csbi.dwSize.X * 2);
|
|
|
|
/* reset buff */
|
|
buffSize.X = ARRAYSIZE(buff);
|
|
buffSize.Y = 1;
|
|
memset(buff, 0x7F, sizeof(buff));
|
|
|
|
/* read output */
|
|
c.X = c.Y = 0;
|
|
ZeroMemory(&sr, sizeof(sr));
|
|
sr.Right = buffSize.X - 1;
|
|
ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
|
|
ok_int(ret, 1);
|
|
ok_int(sr.Left, 0);
|
|
ok_int(sr.Top, 0);
|
|
ok_int(sr.Right, buffSize.X - 1);
|
|
ok_int(sr.Bottom, 0);
|
|
|
|
/* check buff */
|
|
ok_int(buff[0].Char.UnicodeChar, L'A');
|
|
ok_int(buff[0].Attributes, ATTR);
|
|
|
|
/* read attr */
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 1, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 1);
|
|
ok_int(attrs[0], ATTR);
|
|
|
|
/* read char */
|
|
c.X = c.Y = 0;
|
|
memset(str, 0x7F, sizeof(str));
|
|
ret = ReadConsoleOutputCharacterW(hConOut, str, 4, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 4);
|
|
ok_int(str[0], L'A');
|
|
ok_int(str[1], L'A');
|
|
ok_int(str[2], L'A');
|
|
ok_int(str[3], L'A');
|
|
|
|
/* set cursor */
|
|
c.X = c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* write u0414 */
|
|
ret = WriteConsoleW(hConOut, u0414, 1, &len, NULL);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 1);
|
|
|
|
/* reset buff */
|
|
buffSize.X = ARRAYSIZE(buff);
|
|
buffSize.Y = 1;
|
|
memset(buff, 0x7F, sizeof(buff));
|
|
|
|
/* read output */
|
|
c.X = c.Y = 0;
|
|
ZeroMemory(&sr, sizeof(sr));
|
|
sr.Right = buffSize.X - 1;
|
|
ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
|
|
ok_int(ret, 1);
|
|
ok_int(sr.Left, 0);
|
|
ok_int(sr.Top, 0);
|
|
ok_int(sr.Right, buffSize.X - 1);
|
|
ok_int(sr.Bottom, 0);
|
|
|
|
/* check buff */
|
|
if (s_bIs8Plus)
|
|
{
|
|
ok_int(buff[0].Char.UnicodeChar, 0x0414);
|
|
ok_int(buff[0].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(buff[1].Char.UnicodeChar, 0x0414);
|
|
ok_int(buff[1].Attributes, ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
}
|
|
else
|
|
{
|
|
ok_int(buff[0].Char.UnicodeChar, 0x0414);
|
|
ok_int(buff[0].Attributes, ATTR);
|
|
ok_int(buff[1].Char.UnicodeChar, L'A');
|
|
ok_int(buff[1].Attributes, ATTR);
|
|
}
|
|
ok_int(buff[2].Char.UnicodeChar, L'A');
|
|
ok_int(buff[2].Attributes, ATTR);
|
|
ok_int(buff[3].Char.UnicodeChar, L'A');
|
|
ok_int(buff[3].Attributes, ATTR);
|
|
|
|
/* read attr */
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, ARRAYSIZE(attrs));
|
|
ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(attrs[1], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
ok_int(attrs[2], ATTR);
|
|
ok_int(attrs[3], ATTR);
|
|
|
|
/* read char */
|
|
c.X = c.Y = 0;
|
|
memset(str, 0x7F, sizeof(str));
|
|
ret = ReadConsoleOutputCharacterW(hConOut, str, 4, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 3);
|
|
ok_int(str[0], 0x0414);
|
|
ok_int(str[1], L'A');
|
|
ok_int(str[2], L'A');
|
|
if (s_bIs8Plus)
|
|
ok_int(str[3], 0);
|
|
else
|
|
ok_int(str[3], 0x7F7F);
|
|
|
|
/* set cursor */
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* write u0414 */
|
|
ret = WriteConsoleW(hConOut, u0414, 1, &len, NULL);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 1);
|
|
|
|
/* read output */
|
|
c.X = c.Y = 0;
|
|
ZeroMemory(&sr, sizeof(sr));
|
|
sr.Right = buffSize.X - 1;
|
|
ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
|
|
ok_int(ret, 1);
|
|
ok_int(sr.Left, 0);
|
|
ok_int(sr.Top, 0);
|
|
ok_int(sr.Right, buffSize.X - 1);
|
|
ok_int(sr.Bottom, 0);
|
|
|
|
/* check buff */
|
|
if (s_bIs8Plus)
|
|
{
|
|
ok_int(buff[0].Char.UnicodeChar, 0x0414);
|
|
ok_int(buff[0].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(buff[1].Char.UnicodeChar, 0x0414);
|
|
ok_int(buff[1].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(buff[2].Char.UnicodeChar, 0x0414);
|
|
ok_int(buff[2].Attributes, ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
}
|
|
else
|
|
{
|
|
ok_int(buff[0].Char.UnicodeChar, L' ');
|
|
ok_int(buff[0].Attributes, ATTR);
|
|
ok_int(buff[1].Char.UnicodeChar, 0x0414);
|
|
ok_int(buff[1].Attributes, ATTR);
|
|
ok_int(buff[2].Char.UnicodeChar, L'A');
|
|
ok_int(buff[2].Attributes, ATTR);
|
|
}
|
|
ok_int(buff[3].Char.UnicodeChar, L'A');
|
|
ok_int(buff[3].Attributes, ATTR);
|
|
|
|
/* read attr */
|
|
c.X = c.Y = 0;
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, ARRAYSIZE(attrs));
|
|
if (s_bIs8Plus)
|
|
ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
else
|
|
ok_int(attrs[0], ATTR);
|
|
ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(attrs[2], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
ok_int(attrs[3], ATTR);
|
|
|
|
/* read char */
|
|
c.X = c.Y = 0;
|
|
memset(str, 0x7F, sizeof(str));
|
|
ret = ReadConsoleOutputCharacterW(hConOut, str, 4, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 3);
|
|
if (s_bIs8Plus)
|
|
{
|
|
ok_int(str[0], 0x0414);
|
|
ok_int(str[1], 0x0414);
|
|
ok_int(str[2], L'A');
|
|
ok_int(str[3], 0);
|
|
}
|
|
else
|
|
{
|
|
ok_int(str[0], L' ');
|
|
ok_int(str[1], 0x0414);
|
|
ok_int(str[2], L'A');
|
|
ok_int(str[3], 0x7F7F);
|
|
}
|
|
|
|
/* set cursor */
|
|
c.X = csbi.dwSize.X - 1;
|
|
c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* write u0414 */
|
|
WriteConsoleW(hConOut, u0414, 1, &len, NULL);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 1);
|
|
|
|
/* reset buff */
|
|
buffSize.X = ARRAYSIZE(buff);
|
|
buffSize.Y = 1;
|
|
memset(buff, 0x7F, sizeof(buff));
|
|
|
|
/* read output */
|
|
c.X = c.Y = 0;
|
|
sr.Left = csbi.dwSize.X - 2;
|
|
sr.Top = 0;
|
|
sr.Right = csbi.dwSize.X - 1;
|
|
sr.Bottom = 0;
|
|
ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
|
|
ok_int(ret, 1);
|
|
ok_int(sr.Left, csbi.dwSize.X - 2);
|
|
ok_int(sr.Top, 0);
|
|
ok_int(sr.Right, csbi.dwSize.X - 1);
|
|
ok_int(sr.Bottom, 0);
|
|
|
|
/* check buff */
|
|
ok_int(buff[0].Char.UnicodeChar, L'A');
|
|
ok_int(buff[0].Attributes, ATTR);
|
|
ok_int(buff[1].Char.UnicodeChar, L'A');
|
|
ok_int(buff[1].Attributes, ATTR);
|
|
|
|
/* read attrs */
|
|
c.X = csbi.dwSize.X - 2;
|
|
c.Y = 0;
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, ARRAYSIZE(attrs));
|
|
ok_int(attrs[0], ATTR);
|
|
ok_int(attrs[1], ATTR);
|
|
|
|
/* read char */
|
|
ret = ReadConsoleOutputCharacterW(hConOut, str, 2, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 2);
|
|
ok_int(str[0], L'A');
|
|
ok_int(str[1], L'A');
|
|
|
|
/* fill by 'A' */
|
|
c.X = c.Y = 0;
|
|
ret = FillConsoleOutputCharacterW(hConOut, L'A', 10, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 10);
|
|
|
|
/* fill by u0414 */
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
ret = FillConsoleOutputCharacterW(hConOut, 0x0414, 1, c, &len);
|
|
c.X = c.Y = 0;
|
|
ok_int(ret, 1);
|
|
ok_long(len, 1);
|
|
|
|
/* reset buff */
|
|
buffSize.X = ARRAYSIZE(buff);
|
|
buffSize.Y = 1;
|
|
memset(buff, 0x7F, sizeof(buff));
|
|
|
|
/* read output */
|
|
c.X = c.Y = 0;
|
|
sr.Left = 0;
|
|
sr.Top = 0;
|
|
sr.Right = 4;
|
|
sr.Bottom = 0;
|
|
ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
|
|
ok_int(ret, 1);
|
|
ok_int(sr.Left, 0);
|
|
ok_int(sr.Top, 0);
|
|
ok_int(sr.Right, 4);
|
|
ok_int(sr.Bottom, 0);
|
|
|
|
/* check buff */
|
|
ok_int(buff[0].Char.UnicodeChar, L'A');
|
|
ok_int(buff[0].Attributes, ATTR);
|
|
if (s_bIs8Plus)
|
|
{
|
|
ok_int(buff[1].Char.UnicodeChar, 0x0414);
|
|
ok_int(buff[1].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(buff[2].Char.UnicodeChar, 0x0414);
|
|
ok_int(buff[2].Attributes, ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
}
|
|
else
|
|
{
|
|
ok_int(buff[1].Char.UnicodeChar, L' ');
|
|
ok_int(buff[1].Attributes, ATTR);
|
|
ok_int(buff[2].Char.UnicodeChar, L'A');
|
|
ok_int(buff[2].Attributes, ATTR);
|
|
}
|
|
ok_int(buff[3].Char.UnicodeChar, L'A');
|
|
ok_int(buff[3].Attributes, ATTR);
|
|
ok_int(buff[4].Char.UnicodeChar, L'A');
|
|
ok_int(buff[4].Attributes, ATTR);
|
|
|
|
/* read attrs */
|
|
c.X = 0;
|
|
c.Y = 0;
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 4);
|
|
ok_int(attrs[0], ATTR);
|
|
if (s_bIs8Plus)
|
|
{
|
|
ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(attrs[2], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
}
|
|
else
|
|
{
|
|
ok_int(attrs[1], ATTR);
|
|
ok_int(attrs[2], ATTR);
|
|
}
|
|
ok_int(attrs[3], ATTR);
|
|
}
|
|
|
|
/* COMMON_LVB_LEADING_BYTE and COMMON_LVB_TRAILING_BYTE for u9580 */
|
|
{
|
|
/* set cursor */
|
|
c.X = c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* fill by 'A' */
|
|
ret = FillConsoleOutputCharacterW(hConOut, L'A', csbi.dwSize.X * 2, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, csbi.dwSize.X * 2);
|
|
|
|
/* reset buff */
|
|
buffSize.X = ARRAYSIZE(buff);
|
|
buffSize.Y = 1;
|
|
memset(buff, 0x7F, sizeof(buff));
|
|
|
|
/* read output */
|
|
c.X = c.Y = 0;
|
|
ZeroMemory(&sr, sizeof(sr));
|
|
sr.Right = buffSize.X - 1;
|
|
ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
|
|
ok_int(ret, 1);
|
|
ok_int(sr.Left, 0);
|
|
ok_int(sr.Top, 0);
|
|
ok_int(sr.Right, buffSize.X - 1);
|
|
ok_int(sr.Bottom, 0);
|
|
|
|
/* check buff */
|
|
ok_int(buff[0].Char.UnicodeChar, L'A');
|
|
ok_int(buff[0].Attributes, ATTR);
|
|
|
|
/* read attr */
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 1, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 1);
|
|
ok_int(attrs[0], ATTR);
|
|
|
|
/* read char */
|
|
memset(str, 0x7F, sizeof(str));
|
|
ret = ReadConsoleOutputCharacterW(hConOut, str, 2, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 2);
|
|
ok_int(str[0], L'A');
|
|
ok_int(str[1], L'A');
|
|
|
|
/* set cursor */
|
|
c.X = 0;
|
|
c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* write u9580 */
|
|
ret = WriteConsoleW(hConOut, u9580, 1, &len, NULL);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 1);
|
|
|
|
/* reset buff */
|
|
buffSize.X = ARRAYSIZE(buff);
|
|
buffSize.Y = 1;
|
|
memset(buff, 0x7F, sizeof(buff));
|
|
|
|
/* read output */
|
|
c.X = c.Y = 0;
|
|
ZeroMemory(&sr, sizeof(sr));
|
|
sr.Right = buffSize.X - 1;
|
|
ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
|
|
ok_int(ret, 1);
|
|
ok_int(sr.Left, 0);
|
|
ok_int(sr.Top, 0);
|
|
ok_int(sr.Right, buffSize.X - 1);
|
|
ok_int(sr.Bottom, 0);
|
|
|
|
/* check buff */
|
|
if (s_bIs8Plus)
|
|
{
|
|
ok_int(buff[0].Char.UnicodeChar, u9580[0]);
|
|
ok_int(buff[0].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(buff[1].Char.UnicodeChar, u9580[0]);
|
|
ok_int(buff[1].Attributes, ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
}
|
|
else
|
|
{
|
|
ok_int(buff[0].Char.UnicodeChar, u9580[0]);
|
|
ok_int(buff[0].Attributes, ATTR);
|
|
ok_int(buff[1].Char.UnicodeChar, L'A');
|
|
ok_int(buff[1].Attributes, ATTR);
|
|
}
|
|
ok_int(buff[2].Char.UnicodeChar, L'A');
|
|
ok_int(buff[2].Attributes, ATTR);
|
|
ok_int(buff[3].Char.UnicodeChar, L'A');
|
|
ok_int(buff[3].Attributes, ATTR);
|
|
|
|
/* read attr */
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, ARRAYSIZE(attrs));
|
|
|
|
ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(attrs[1], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
ok_int(attrs[2], ATTR);
|
|
ok_int(attrs[3], ATTR);
|
|
|
|
/* read char */
|
|
c.X = c.Y = 0;
|
|
memset(str, 0x7F, sizeof(str));
|
|
ret = ReadConsoleOutputCharacterW(hConOut, str, 4, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 3);
|
|
ok_int(str[0], u9580[0]);
|
|
ok_int(str[1], L'A');
|
|
ok_int(str[2], L'A');
|
|
if (s_bIs8Plus)
|
|
ok_int(str[3], 0);
|
|
else
|
|
ok_int(str[3], 0x7F7F);
|
|
|
|
/* set cursor */
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* write u9580 */
|
|
ret = WriteConsoleW(hConOut, u9580, 1, &len, NULL);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 1);
|
|
|
|
/* read output */
|
|
c.X = c.Y = 0;
|
|
ZeroMemory(&sr, sizeof(sr));
|
|
sr.Right = buffSize.X - 1;
|
|
ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
|
|
ok_int(ret, 1);
|
|
ok_int(sr.Left, 0);
|
|
ok_int(sr.Top, 0);
|
|
ok_int(sr.Right, buffSize.X - 1);
|
|
ok_int(sr.Bottom, 0);
|
|
|
|
/* check buff */
|
|
if (s_bIs8Plus)
|
|
{
|
|
ok_int(buff[0].Char.UnicodeChar, u9580[0]);
|
|
ok_int(buff[0].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(buff[1].Char.UnicodeChar, u9580[0]);
|
|
ok_int(buff[1].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(buff[2].Char.UnicodeChar, u9580[0]);
|
|
ok_int(buff[2].Attributes, ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
}
|
|
else
|
|
{
|
|
ok_int(buff[0].Char.UnicodeChar, L' ');
|
|
ok_int(buff[0].Attributes, ATTR);
|
|
ok_int(buff[1].Char.UnicodeChar, u9580[0]);
|
|
ok_int(buff[1].Attributes, ATTR);
|
|
ok_int(buff[2].Char.UnicodeChar, L'A');
|
|
ok_int(buff[2].Attributes, ATTR);
|
|
}
|
|
ok_int(buff[3].Char.UnicodeChar, L'A');
|
|
ok_int(buff[3].Attributes, ATTR);
|
|
|
|
/* read attr */
|
|
c.X = c.Y = 0;
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, ARRAYSIZE(attrs));
|
|
|
|
if (s_bIs8Plus)
|
|
{
|
|
ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
}
|
|
else
|
|
{
|
|
ok_int(attrs[0], ATTR);
|
|
}
|
|
ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(attrs[2], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
ok_int(attrs[3], ATTR);
|
|
|
|
/* set cursor */
|
|
c.X = csbi.dwSize.X - 1;
|
|
c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
|
|
/* write u9580 */
|
|
WriteConsoleW(hConOut, u9580, 1, &len, NULL);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 1);
|
|
|
|
/* reset buff */
|
|
buffSize.X = ARRAYSIZE(buff);
|
|
buffSize.Y = 1;
|
|
memset(buff, 0x7F, sizeof(buff));
|
|
|
|
/* read output */
|
|
c.X = c.Y = 0;
|
|
sr.Left = csbi.dwSize.X - 2;
|
|
sr.Top = 0;
|
|
sr.Right = csbi.dwSize.X - 1;
|
|
sr.Bottom = 0;
|
|
ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
|
|
ok_int(ret, 1);
|
|
ok_int(sr.Left, csbi.dwSize.X - 2);
|
|
ok_int(sr.Top, 0);
|
|
ok_int(sr.Right, csbi.dwSize.X - 1);
|
|
ok_int(sr.Bottom, 0);
|
|
|
|
/* check buff */
|
|
ok_int(buff[0].Char.UnicodeChar, L'A');
|
|
ok_int(buff[0].Attributes, ATTR);
|
|
ok_int(buff[1].Char.UnicodeChar, L'A');
|
|
ok_int(buff[1].Attributes, ATTR);
|
|
|
|
/* read attr */
|
|
c.X = csbi.dwSize.X - 2;
|
|
c.Y = 0;
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, ARRAYSIZE(attrs), c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, ARRAYSIZE(attrs));
|
|
ok_int(attrs[0], ATTR);
|
|
ok_int(attrs[1], ATTR);
|
|
|
|
/* read char */
|
|
memset(str, 0x7F, sizeof(str));
|
|
ret = ReadConsoleOutputCharacterW(hConOut, str, 2, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 2);
|
|
ok_int(str[0], L'A');
|
|
ok_int(str[1], L'A');
|
|
|
|
/* fill by 'A' */
|
|
c.X = c.Y = 0;
|
|
ret = FillConsoleOutputCharacterW(hConOut, L'A', 10, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 10);
|
|
|
|
/* fill by u9580 */
|
|
c.X = 1;
|
|
c.Y = 0;
|
|
ret = FillConsoleOutputCharacterW(hConOut, u9580[0], 1, c, &len);
|
|
c.X = c.Y = 0;
|
|
ok_int(ret, 1);
|
|
ok_long(len, 1);
|
|
|
|
/* reset buff */
|
|
buffSize.X = ARRAYSIZE(buff);
|
|
buffSize.Y = 1;
|
|
memset(buff, 0x7F, sizeof(buff));
|
|
|
|
/* read output */
|
|
c.X = c.Y = 0;
|
|
sr.Left = 0;
|
|
sr.Top = 0;
|
|
sr.Right = 4;
|
|
sr.Bottom = 0;
|
|
ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
|
|
ok_int(ret, 1);
|
|
ok_int(sr.Left, 0);
|
|
ok_int(sr.Top, 0);
|
|
ok_int(sr.Right, 4);
|
|
ok_int(sr.Bottom, 0);
|
|
|
|
/* check buff */
|
|
ok_int(buff[0].Char.UnicodeChar, L'A');
|
|
ok_int(buff[0].Attributes, ATTR);
|
|
if (s_bIs8Plus)
|
|
{
|
|
ok_int(buff[1].Char.UnicodeChar, u9580[0]);
|
|
ok_int(buff[1].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(buff[2].Char.UnicodeChar, u9580[0]);
|
|
ok_int(buff[2].Attributes, ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
}
|
|
else
|
|
{
|
|
ok_int(buff[1].Char.UnicodeChar, L' ');
|
|
ok_int(buff[1].Attributes, ATTR);
|
|
ok_int(buff[2].Char.UnicodeChar, L'A');
|
|
ok_int(buff[2].Attributes, ATTR);
|
|
}
|
|
ok_int(buff[3].Char.UnicodeChar, L'A');
|
|
ok_int(buff[3].Attributes, ATTR);
|
|
ok_int(buff[4].Char.UnicodeChar, L'A');
|
|
ok_int(buff[4].Attributes, ATTR);
|
|
|
|
/* read attrs */
|
|
c.X = 0;
|
|
c.Y = 0;
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 4);
|
|
ok_int(attrs[0], ATTR);
|
|
if (s_bIs8Plus)
|
|
{
|
|
ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(attrs[2], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
}
|
|
else
|
|
{
|
|
ok_int(attrs[1], ATTR);
|
|
ok_int(attrs[2], ATTR);
|
|
}
|
|
ok_int(attrs[3], ATTR);
|
|
}
|
|
|
|
/* FillConsoleOutputAttribute and WriteConsoleOutput */
|
|
{
|
|
c.X = c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
for (n = 0; n < count; ++n)
|
|
{
|
|
ret = WriteConsoleW(hConOut, space, lstrlenW(space), &len, NULL);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 1);
|
|
}
|
|
|
|
/* fill attrs */
|
|
c.X = c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
ret = FillConsoleOutputAttribute(hConOut, 0xFFFF, 2, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 2);
|
|
|
|
/* read attrs */
|
|
memset(attrs, 0x7F, sizeof(attrs));
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 3, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 3);
|
|
if (s_bIs8Plus)
|
|
{
|
|
ok_int(attrs[0], 0xDCFF);
|
|
ok_int(attrs[1], 0xDCFF);
|
|
}
|
|
else
|
|
{
|
|
ok_int(attrs[0], 0xFCFF);
|
|
ok_int(attrs[1], 0xFCFF);
|
|
}
|
|
ok_int(attrs[2], ATTR);
|
|
|
|
/* fill attrs */
|
|
c.X = c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
ret = FillConsoleOutputAttribute(hConOut, ATTR, 4, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 4);
|
|
|
|
/* write */
|
|
c.X = c.Y = 0;
|
|
sr.Left = 0;
|
|
sr.Top = 0;
|
|
sr.Right = 4;
|
|
sr.Bottom = 0;
|
|
// Check how Read/WriteConsoleOutput() handle inconsistent DBCS flags.
|
|
buff[0].Char.UnicodeChar = u9580[0];
|
|
buff[0].Attributes = ATTR | COMMON_LVB_LEADING_BYTE;
|
|
buff[1].Char.UnicodeChar = u9580[0];
|
|
buff[1].Attributes = ATTR | COMMON_LVB_LEADING_BYTE;
|
|
buff[2].Char.UnicodeChar = u9580[0];
|
|
buff[2].Attributes = ATTR | COMMON_LVB_TRAILING_BYTE;
|
|
buff[3].Char.UnicodeChar = L'A';
|
|
buff[3].Attributes = ATTR;
|
|
buff[4].Char.UnicodeChar = L' ';
|
|
buff[4].Attributes = 0xFFFF;
|
|
buffSize.X = 4;
|
|
buffSize.Y = 1;
|
|
ret = WriteConsoleOutputW(hConOut, buff, buffSize, c, &sr);
|
|
ok_int(ret, 1);
|
|
ok_int(sr.Left, 0);
|
|
ok_int(sr.Top, 0);
|
|
ok_int(sr.Right, 3);
|
|
ok_int(sr.Bottom, 0);
|
|
|
|
/* read output */
|
|
sr.Left = 0;
|
|
sr.Top = 0;
|
|
sr.Right = 4;
|
|
sr.Bottom = 0;
|
|
memset(buff, 0x7F, sizeof(buff));
|
|
ret = ReadConsoleOutputW(hConOut, buff, buffSize, c, &sr);
|
|
ok_int(ret, 1);
|
|
ok_int(sr.Left, 0);
|
|
ok_int(sr.Top, 0);
|
|
ok_int(sr.Right, 3);
|
|
ok_int(sr.Bottom, 0);
|
|
|
|
/* check buff */
|
|
if (s_bIs8Plus)
|
|
{
|
|
ok_int(buff[0].Char.UnicodeChar, u9580[0]);
|
|
ok_int(buff[0].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(buff[1].Char.UnicodeChar, u9580[0]);
|
|
ok_int(buff[1].Attributes, ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(buff[2].Char.UnicodeChar, u9580[0]);
|
|
ok_int(buff[2].Attributes, ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
ok_int(buff[3].Char.UnicodeChar, L'A');
|
|
ok_int(buff[3].Attributes, ATTR);
|
|
ok_int(buff[4].Char.UnicodeChar, 0x7F7F);
|
|
ok_int(buff[4].Attributes, 0x7F7F);
|
|
}
|
|
else
|
|
{
|
|
ok_int(buff[0].Char.UnicodeChar, u9580[0]);
|
|
ok_int(buff[0].Attributes, ATTR);
|
|
ok_int(buff[1].Char.UnicodeChar, u9580[0]);
|
|
ok_int(buff[1].Attributes, ATTR);
|
|
ok_int(buff[2].Char.UnicodeChar, 0);
|
|
ok_int(buff[2].Attributes, 0);
|
|
ok_int(buff[3].Char.UnicodeChar, 0);
|
|
ok_int(buff[3].Attributes, 0);
|
|
ok_int(buff[4].Char.UnicodeChar, 0x7F7F);
|
|
ok_int(buff[4].Attributes, 0x7F7F);
|
|
}
|
|
|
|
/* read attrs */
|
|
c.X = c.Y = 0;
|
|
memset(attrs, 0x7F, sizeof(attrs));
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 6, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 6);
|
|
ok_int(attrs[0], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
if (s_bIs8Plus)
|
|
{
|
|
ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(attrs[2], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
ok_int(attrs[3], ATTR);
|
|
}
|
|
else
|
|
{
|
|
ok_int(attrs[1], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
ok_int(attrs[2], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(attrs[3], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
}
|
|
ok_int(attrs[4], ATTR);
|
|
ok_int(attrs[5], ATTR);
|
|
}
|
|
|
|
/* WriteConsoleOutputCharacterW and WriteConsoleOutputAttribute */
|
|
{
|
|
c.X = c.Y = 0;
|
|
SetConsoleCursorPosition(hConOut, c);
|
|
okCURSOR(hConOut, c);
|
|
for (n = 0; n < count; ++n)
|
|
{
|
|
ret = WriteConsoleW(hConOut, space, lstrlenW(space), &len, NULL);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 1);
|
|
}
|
|
|
|
/* write attrs */
|
|
attrs[0] = ATTR;
|
|
attrs[1] = 0xFFFF;
|
|
attrs[2] = ATTR;
|
|
attrs[3] = 0;
|
|
ret = WriteConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 4);
|
|
|
|
/* read attrs */
|
|
memset(attrs, 0x7F, sizeof(attrs));
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 4);
|
|
ok_int(attrs[0], ATTR);
|
|
if (s_bIs8Plus)
|
|
ok_int(attrs[1], 0xDCFF);
|
|
else
|
|
ok_int(attrs[1], 0xFCFF);
|
|
ok_int(attrs[2], ATTR);
|
|
ok_int(attrs[3], 0);
|
|
|
|
/* fill attr */
|
|
ret = FillConsoleOutputAttribute(hConOut, ATTR, 4, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 4);
|
|
|
|
/* write char */
|
|
ret = WriteConsoleOutputCharacterW(hConOut, s_str, 4, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 4);
|
|
|
|
/* read attrs */
|
|
memset(attrs, 0x7F, sizeof(attrs));
|
|
ret = ReadConsoleOutputAttribute(hConOut, attrs, 4, c, &len);
|
|
ok_int(ret, 1);
|
|
ok_long(len, 4);
|
|
ok_int(attrs[0], ATTR);
|
|
ok_int(attrs[1], ATTR | COMMON_LVB_LEADING_BYTE);
|
|
ok_int(attrs[2], ATTR | COMMON_LVB_TRAILING_BYTE);
|
|
ok_int(attrs[3], ATTR);
|
|
}
|
|
|
|
/* Restore code page */
|
|
SetConsoleOutputCP(oldcp);
|
|
}
|
|
|
|
|
|
START_TEST(ConsoleCP)
|
|
{
|
|
HANDLE hConIn, hConOut;
|
|
OSVERSIONINFOA osver = { sizeof(osver) };
|
|
|
|
// https://github.com/reactos/reactos/pull/2131#issuecomment-563189380
|
|
GetVersionExA(&osver);
|
|
s_bIs8Plus = (osver.dwMajorVersion > 6) ||
|
|
(osver.dwMajorVersion == 6 && osver.dwMinorVersion >= 2);
|
|
|
|
FreeConsole();
|
|
ok(AllocConsole(), "Couldn't alloc console\n");
|
|
|
|
hConIn = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
|
|
hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
|
|
ok(hConIn != INVALID_HANDLE_VALUE, "Opening ConIn\n");
|
|
ok(hConOut != INVALID_HANDLE_VALUE, "Opening ConOut\n");
|
|
|
|
/* Retrieve the system OEM code page */
|
|
s_uOEMCP = GetOEMCP();
|
|
trace("Running on %s system (codepage %d)\n",
|
|
IsCJKCodePage(s_uOEMCP) ? "CJK" : "Non-CJK",
|
|
s_uOEMCP);
|
|
|
|
/* Test thread lang ID syncing with console code page */
|
|
test_CP_ThreadLang();
|
|
|
|
if (IsValidLocale(lcidRussian, LCID_INSTALLED))
|
|
{
|
|
if (!IsCJKCodePage(s_uOEMCP))
|
|
test_cp855(hConOut);
|
|
else
|
|
skip("Russian testcase is skipped because of CJK\n");
|
|
}
|
|
else
|
|
{
|
|
skip("Russian locale is not installed\n");
|
|
}
|
|
|
|
if (IsValidLocale(lcidJapanese, LCID_INSTALLED))
|
|
{
|
|
if (IsCJKCodePage(s_uOEMCP))
|
|
test_cp932(hConOut);
|
|
else
|
|
skip("Japanese testcase is skipped because of not CJK\n");
|
|
}
|
|
else
|
|
{
|
|
skip("Japanese locale is not installed\n");
|
|
}
|
|
|
|
CloseHandle(hConIn);
|
|
CloseHandle(hConOut);
|
|
FreeConsole();
|
|
ok(AllocConsole(), "Couldn't alloc console\n");
|
|
}
|