https://git.reactos.org/?p=reactos.git;a=commitdiff;h=fb58782012d5d0b3ba95b388731fa43a262cfea4

commit fb58782012d5d0b3ba95b388731fa43a262cfea4
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Sat Oct 29 13:49:28 2022 +0900
Commit:     GitHub <[email protected]>
CommitDate: Sat Oct 29 13:49:28 2022 +0900

    [IMM32_APITEST] Add JapanImeConvTestA/W testcases (#4820)
    
    Add IME conversion tests to verify IMM/IME support. CORE-11700
---
 modules/rostests/apitests/imm32/CMakeLists.txt     |   5 +-
 modules/rostests/apitests/imm32/JapanImeConvTest.h | 284 +++++++++++++++++++++
 .../rostests/apitests/imm32/JapanImeConvTestA.c    |   9 +
 .../rostests/apitests/imm32/JapanImeConvTestW.c    |   9 +
 modules/rostests/apitests/imm32/resource.rc        |  16 ++
 modules/rostests/apitests/imm32/testlist.c         |   4 +
 6 files changed, 326 insertions(+), 1 deletion(-)

diff --git a/modules/rostests/apitests/imm32/CMakeLists.txt 
b/modules/rostests/apitests/imm32/CMakeLists.txt
index 30b7dd66a8e..9c6486a8508 100644
--- a/modules/rostests/apitests/imm32/CMakeLists.txt
+++ b/modules/rostests/apitests/imm32/CMakeLists.txt
@@ -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})
diff --git a/modules/rostests/apitests/imm32/JapanImeConvTest.h 
b/modules/rostests/apitests/imm32/JapanImeConvTest.h
new file mode 100644
index 00000000000..8878553d1c1
--- /dev/null
+++ b/modules/rostests/apitests/imm32/JapanImeConvTest.h
@@ -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 
([email protected])
+ */
+
+#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");
+}
diff --git a/modules/rostests/apitests/imm32/JapanImeConvTestA.c 
b/modules/rostests/apitests/imm32/JapanImeConvTestA.c
new file mode 100644
index 00000000000..72d2e83581f
--- /dev/null
+++ b/modules/rostests/apitests/imm32/JapanImeConvTestA.c
@@ -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 
([email protected])
+ */
+
+#undef UNICODE /* ANSI */
+#include "JapanImeConvTest.h"
diff --git a/modules/rostests/apitests/imm32/JapanImeConvTestW.c 
b/modules/rostests/apitests/imm32/JapanImeConvTestW.c
new file mode 100644
index 00000000000..9499b861931
--- /dev/null
+++ b/modules/rostests/apitests/imm32/JapanImeConvTestW.c
@@ -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 
([email protected])
+ */
+
+#define UNICODE /* Unicode */
+#include "JapanImeConvTest.h"
diff --git a/modules/rostests/apitests/imm32/resource.rc 
b/modules/rostests/apitests/imm32/resource.rc
new file mode 100644
index 00000000000..c01bc75b2da
--- /dev/null
+++ b/modules/rostests/apitests/imm32/resource.rc
@@ -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
+}
diff --git a/modules/rostests/apitests/imm32/testlist.c 
b/modules/rostests/apitests/imm32/testlist.c
index d73e9878113..b9c16be52cf 100644
--- a/modules/rostests/apitests/imm32/testlist.c
+++ b/modules/rostests/apitests/imm32/testlist.c
@@ -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 }
 };

Reply via email to