mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[IMM32_APITEST] Add JapanImeConvTestA/W testcases (#4820)
Add IME conversion tests to verify IMM/IME support. CORE-11700
This commit is contained in:
parent
36f7d1a953
commit
fb58782012
6 changed files with 326 additions and 1 deletions
|
@ -7,7 +7,10 @@ list(APPEND SOURCE
|
|||
imcc.c
|
||||
ImmGetImeInfoEx.c
|
||||
ImmIsUIMessage.c
|
||||
testlist.c)
|
||||
JapanImeConvTestA.c
|
||||
JapanImeConvTestW.c
|
||||
testlist.c
|
||||
resource.rc)
|
||||
|
||||
add_executable(imm32_apitest ${SOURCE})
|
||||
target_link_libraries(imm32_apitest wine ${PSEH_LIB})
|
||||
|
|
284
modules/rostests/apitests/imm32/JapanImeConvTest.h
Normal file
284
modules/rostests/apitests/imm32/JapanImeConvTest.h
Normal file
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
* PROJECT: ReactOS api tests
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Test for Japanese IME conversion
|
||||
* COPYRIGHT: Copyright 2022 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <imm.h>
|
||||
#include <wine/test.h>
|
||||
|
||||
/*
|
||||
* We emulate some keyboard typing on dialog box and watch the conversion of Japanese IME.
|
||||
* This program needs Japanese environment and Japanese IME.
|
||||
* Tested on Japanese WinXP and Japanese Win10.
|
||||
*/
|
||||
|
||||
#define INTERVAL 300
|
||||
#define WM_PRESS_KEY_COMPLETE (WM_USER + 100)
|
||||
|
||||
/* The test entry structure */
|
||||
typedef struct tagTEST_ENTRY
|
||||
{
|
||||
const UINT *pKeys;
|
||||
UINT cKeys;
|
||||
const void *pvResult;
|
||||
INT cWM_IME_ENDCOMPOSITION;
|
||||
} TEST_ENTRY, *PTEST_ENTRY;
|
||||
|
||||
// The Japanese word "テスト" conversion in Romaji
|
||||
static const UINT s_keys1[] =
|
||||
{
|
||||
'T', 'E', 'S', 'U', 'T', 'O', VK_SPACE, VK_RETURN
|
||||
};
|
||||
// The Japanese word "調査員" conversion in Romaji
|
||||
static const UINT s_keys2[] =
|
||||
{
|
||||
'C', 'H', 'O', 'U', 'S', 'A', 'I', 'N', 'N', VK_SPACE, VK_RETURN
|
||||
};
|
||||
|
||||
#ifdef UNICODE
|
||||
#define AorW(a, w) w
|
||||
#else
|
||||
#define AorW(a, w) a
|
||||
#endif
|
||||
|
||||
/* The test entries */
|
||||
static const TEST_ENTRY s_entries[] =
|
||||
{
|
||||
// "テスト"
|
||||
{ s_keys1, _countof(s_keys1), AorW("\x83\x65\x83\x58\x83\x67", L"\x30C6\x30B9\x30C8"), 1 },
|
||||
// "調査員"
|
||||
{ s_keys2, _countof(s_keys2), AorW("\x92\xB2\x8D\xB8\x88\xF5", L"\x8ABF\x67FB\x54E1"), 1 },
|
||||
};
|
||||
|
||||
static INT s_iEntry = 0;
|
||||
static INT s_cWM_IME_ENDCOMPOSITION = 0;
|
||||
static WNDPROC s_fnOldEditWndProc = NULL;
|
||||
|
||||
#ifdef UNICODE
|
||||
static LPSTR WideToAnsi(INT nCodePage, LPCWSTR pszWide)
|
||||
{
|
||||
static CHAR s_sz[512];
|
||||
WideCharToMultiByte(nCodePage, 0, pszWide, -1, s_sz, _countof(s_sz), NULL, NULL);
|
||||
return s_sz;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The window procedure for textbox to watch the IME conversion */
|
||||
static LRESULT CALLBACK
|
||||
EditWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_IME_ENDCOMPOSITION:
|
||||
{
|
||||
const TEST_ENTRY *entry = &s_entries[s_iEntry];
|
||||
HIMC hIMC;
|
||||
LONG cbResult, cbBuffer;
|
||||
LPTSTR pszResult;
|
||||
|
||||
/* Check conversion results of composition string */
|
||||
hIMC = ImmGetContext(hwnd);
|
||||
cbResult = ImmGetCompositionString(hIMC, GCS_RESULTSTR, NULL, 0);
|
||||
trace("cbResult: %ld\n", cbResult);
|
||||
if (cbResult > 0) /* Ignore zero string */
|
||||
{
|
||||
ok(hIMC != NULL, "hIMC was NULL\n");
|
||||
++s_cWM_IME_ENDCOMPOSITION;
|
||||
|
||||
cbBuffer = cbResult + sizeof(WCHAR);
|
||||
pszResult = (LPTSTR)calloc(cbBuffer, sizeof(BYTE)); /* Zero-fill */
|
||||
ok(pszResult != NULL, "pszResult was NULL\n");
|
||||
ImmGetCompositionString(hIMC, GCS_RESULTSTR, pszResult, cbBuffer);
|
||||
#ifdef UNICODE
|
||||
trace("%s\n", WideToAnsi(CP_ACP, (LPTSTR)pszResult));
|
||||
#else
|
||||
trace("%s\n", (LPTSTR)pszResult);
|
||||
#endif
|
||||
ok(lstrcmp(pszResult, (LPTSTR)entry->pvResult) == 0, "pszResult differs\n");
|
||||
free(pszResult);
|
||||
}
|
||||
|
||||
ImmReleaseContext(hwnd, hIMC);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return CallWindowProc(s_fnOldEditWndProc, hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
/* Timer IDs */
|
||||
#define STAGE_1 10001
|
||||
#define STAGE_2 10002
|
||||
#define STAGE_3 10003
|
||||
#define STAGE_4 10004
|
||||
#define STAGE_5 10005
|
||||
|
||||
/* WM_INITDIALOG */
|
||||
static BOOL OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
|
||||
{
|
||||
/* Subclass the textbox to watch the IME conversion */
|
||||
HWND hEdt1 = GetDlgItem(hwnd, edt1);
|
||||
s_fnOldEditWndProc = (WNDPROC)SetWindowLongPtr(hEdt1, GWLP_WNDPROC, (LONG_PTR)EditWindowProc);
|
||||
|
||||
/* Go to first stage */
|
||||
SetTimer(hwnd, STAGE_1, INTERVAL, 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* WM_COMMAND */
|
||||
static void OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case IDOK:
|
||||
case IDCANCEL:
|
||||
EndDialog(hwnd, id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Emulate keyboard typing */
|
||||
static VOID PressKey(UINT vk)
|
||||
{
|
||||
INPUT inputs[2];
|
||||
ZeroMemory(inputs, sizeof(inputs));
|
||||
inputs[0].type = INPUT_KEYBOARD;
|
||||
inputs[0].ki.wVk = vk;
|
||||
inputs[1].type = INPUT_KEYBOARD;
|
||||
inputs[1].ki.wVk = vk;
|
||||
inputs[1].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
SendInput(_countof(inputs), inputs, sizeof(INPUT));
|
||||
}
|
||||
|
||||
/* WM_TIMER */
|
||||
static void OnTimer(HWND hwnd, UINT id)
|
||||
{
|
||||
HIMC hIMC;
|
||||
INT i;
|
||||
const TEST_ENTRY *entry = &s_entries[s_iEntry];
|
||||
static DWORD dwOldConversion, dwOldSentence;
|
||||
|
||||
KillTimer(hwnd, id);
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case STAGE_1:
|
||||
/* Check focus. See WM_INITDIALOG return code. */
|
||||
ok(GetFocus() == GetDlgItem(hwnd, edt1), "GetFocus() was %p\n", GetFocus());
|
||||
|
||||
hIMC = ImmGetContext(hwnd);
|
||||
ok(hIMC != NULL, "hIMC was NULL");
|
||||
if (hIMC)
|
||||
{
|
||||
/* Open the IME */
|
||||
ImmSetOpenStatus(hIMC, TRUE);
|
||||
/* Save the IME conversion status */
|
||||
ImmGetConversionStatus(hIMC, &dwOldConversion, &dwOldSentence);
|
||||
/* Modify the IME conversion status */
|
||||
ImmSetConversionStatus(hIMC,
|
||||
IME_CMODE_FULLSHAPE | IME_CMODE_ROMAN | IME_CMODE_NATIVE,
|
||||
IME_SMODE_SINGLECONVERT);
|
||||
|
||||
ImmReleaseContext(hwnd, hIMC);
|
||||
}
|
||||
/* Initialize the counter */
|
||||
s_cWM_IME_ENDCOMPOSITION = 0;
|
||||
/* Go to next stage */
|
||||
SetTimer(hwnd, STAGE_2, INTERVAL, NULL);
|
||||
break;
|
||||
|
||||
case STAGE_2:
|
||||
/* Emulate keyboard typing */
|
||||
for (i = 0; i < entry->cKeys; ++i)
|
||||
{
|
||||
PressKey(entry->pKeys[i]);
|
||||
}
|
||||
/* Wait for message queue processed */
|
||||
PostMessage(hwnd, WM_PRESS_KEY_COMPLETE, 0, 0);
|
||||
break;
|
||||
|
||||
case STAGE_3:
|
||||
/* Revert the IME conversion status */
|
||||
hIMC = ImmGetContext(hwnd);
|
||||
ok(hIMC != NULL, "hIMC was NULL");
|
||||
if (hIMC)
|
||||
{
|
||||
ImmSetConversionStatus(hIMC, dwOldConversion, dwOldSentence);
|
||||
ImmReleaseContext(hwnd, hIMC);
|
||||
}
|
||||
/* Go to next stage */
|
||||
SetTimer(hwnd, STAGE_4, INTERVAL, NULL);
|
||||
break;
|
||||
|
||||
case STAGE_4:
|
||||
/* Check the counter */
|
||||
ok_int(s_cWM_IME_ENDCOMPOSITION, entry->cWM_IME_ENDCOMPOSITION);
|
||||
if (s_cWM_IME_ENDCOMPOSITION < entry->cWM_IME_ENDCOMPOSITION)
|
||||
{
|
||||
skip("Some tests were skipped.\n");
|
||||
}
|
||||
|
||||
/* Go to next test entry */
|
||||
++s_iEntry;
|
||||
if (s_iEntry == _countof(s_entries))
|
||||
PostMessage(hwnd, WM_CLOSE, 0, 0); /* No more entry */
|
||||
else
|
||||
SetTimer(hwnd, STAGE_1, INTERVAL, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dialog procedure */
|
||||
static INT_PTR CALLBACK
|
||||
DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (uMsg)
|
||||
{
|
||||
HANDLE_MSG(hwnd, WM_INITDIALOG, OnInitDialog);
|
||||
HANDLE_MSG(hwnd, WM_COMMAND, OnCommand);
|
||||
HANDLE_MSG(hwnd, WM_TIMER, OnTimer);
|
||||
|
||||
case WM_PRESS_KEY_COMPLETE:
|
||||
/* Message queue is processed. Go to next stage. */
|
||||
SetTimer(hwnd, STAGE_3, INTERVAL, NULL);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef UNICODE
|
||||
START_TEST(JapanImeConvTestW)
|
||||
#else
|
||||
START_TEST(JapanImeConvTestA)
|
||||
#endif
|
||||
{
|
||||
/* Is the system Japanese? */
|
||||
if (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_JAPANESE)
|
||||
{
|
||||
skip("This testcase is for Japanese only.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is IMM enabled? */
|
||||
if (!GetSystemMetrics(SM_IMMENABLED))
|
||||
{
|
||||
skip("SM_IMMENABLED is OFF.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check the current keyboard layout is IME */
|
||||
if (!ImmIsIME(GetKeyboardLayout(0)))
|
||||
{
|
||||
skip("The IME keyboard layout was not default\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(1), NULL, DialogProc);
|
||||
|
||||
if (s_iEntry < _countof(s_entries))
|
||||
skip("Some tests were skipped.\n");
|
||||
}
|
9
modules/rostests/apitests/imm32/JapanImeConvTestA.c
Normal file
9
modules/rostests/apitests/imm32/JapanImeConvTestA.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* PROJECT: ReactOS api tests
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Test for Japanese IME conversion
|
||||
* COPYRIGHT: Copyright 2022 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||
*/
|
||||
|
||||
#undef UNICODE /* ANSI */
|
||||
#include "JapanImeConvTest.h"
|
9
modules/rostests/apitests/imm32/JapanImeConvTestW.c
Normal file
9
modules/rostests/apitests/imm32/JapanImeConvTestW.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* PROJECT: ReactOS api tests
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Test for Japanese IME conversion
|
||||
* COPYRIGHT: Copyright 2022 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||
*/
|
||||
|
||||
#define UNICODE /* Unicode */
|
||||
#include "JapanImeConvTest.h"
|
16
modules/rostests/apitests/imm32/resource.rc
Normal file
16
modules/rostests/apitests/imm32/resource.rc
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#pragma code_page(65001) /* UTF-8 */
|
||||
|
||||
LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
|
||||
|
||||
1 DIALOG 0, 0, 215, 135
|
||||
CAPTION "JapanImeConvTest"
|
||||
STYLE DS_CENTER | DS_MODALFRAME | WS_POPUPWINDOW | WS_CAPTION
|
||||
FONT 9, "MS UI Gothic"
|
||||
{
|
||||
EDITTEXT edt1, 8, 7, 147, 14
|
||||
LISTBOX lst1, 7, 30, 202, 82, LBS_NOINTEGRALHEIGHT | LBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
|
||||
DEFPUSHBUTTON "OK", IDOK, 35, 115, 60, 14
|
||||
PUSHBUTTON "Cancel", IDCANCEL, 115, 115, 60, 14
|
||||
}
|
|
@ -7,6 +7,8 @@ extern void func_himc(void);
|
|||
extern void func_imcc(void);
|
||||
extern void func_ImmGetImeInfoEx(void);
|
||||
extern void func_ImmIsUIMessage(void);
|
||||
extern void func_JapanImeConvTestA(void);
|
||||
extern void func_JapanImeConvTestW(void);
|
||||
|
||||
const struct test winetest_testlist[] =
|
||||
{
|
||||
|
@ -15,5 +17,7 @@ const struct test winetest_testlist[] =
|
|||
{ "imcc", func_imcc },
|
||||
{ "ImmGetImeInfoEx", func_ImmGetImeInfoEx },
|
||||
{ "ImmIsUIMessage", func_ImmIsUIMessage },
|
||||
{ "JapanImeConvTestA", func_JapanImeConvTestA },
|
||||
{ "JapanImeConvTestW", func_JapanImeConvTestW },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue