|
|
|
@@ -1,10 +1,9 @@
|
|
|
|
|
/*
|
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
|
* PROJECT: ReactOS user32.dll
|
|
|
|
|
* FILE: win32ss/user/user32/misc/imm.c
|
|
|
|
|
* PURPOSE: User32.dll Imm functions
|
|
|
|
|
* PROGRAMMERS: Dmitry Chapyshev ([email protected])
|
|
|
|
|
* Katayama Hirofumi MZ ([email protected])
|
|
|
|
|
* PROJECT: ReactOS user32.dll
|
|
|
|
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
|
|
|
|
* PURPOSE: User32.dll Imm functions
|
|
|
|
|
* COPYRIGHT: Copyright Dmitry Chapyshev ([email protected])
|
|
|
|
|
* Copyright Katayama Hirofumi MZ ([email protected])
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <user32.h>
|
|
|
|
@@ -17,11 +16,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(user32);
|
|
|
|
|
#define MAX_CANDIDATEFORM 4
|
|
|
|
|
|
|
|
|
|
/* Is != NULL when we have loaded the IMM ourselves */
|
|
|
|
|
HINSTANCE ghImm32 = NULL; // Win: ghImm32
|
|
|
|
|
HINSTANCE ghImm32 = NULL;
|
|
|
|
|
|
|
|
|
|
BOOL gbImmInitializing = FALSE; // Win: bImmInitializing
|
|
|
|
|
BOOL gbImmInitializing = FALSE;
|
|
|
|
|
|
|
|
|
|
INT gfConIme = -1; // Win: gfConIme
|
|
|
|
|
INT gfConIme = -1;
|
|
|
|
|
|
|
|
|
|
HWND FASTCALL IntGetTopLevelWindow(HWND hWnd)
|
|
|
|
|
{
|
|
|
|
@@ -43,7 +42,6 @@ HWND FASTCALL IntGetTopLevelWindow(HWND hWnd)
|
|
|
|
|
static type WINAPI IMMSTUB_##name params { IMM_RETURN_##retkind((type)retval); }
|
|
|
|
|
#include "immtable.h"
|
|
|
|
|
|
|
|
|
|
// Win: gImmApiEntries
|
|
|
|
|
Imm32ApiTable gImmApiEntries = {
|
|
|
|
|
/* initialize by stubs */
|
|
|
|
|
#undef DEFINE_IMM_ENTRY
|
|
|
|
@@ -52,21 +50,25 @@ Imm32ApiTable gImmApiEntries = {
|
|
|
|
|
#include "immtable.h"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Win: GetImmFileName
|
|
|
|
|
HRESULT
|
|
|
|
|
User32GetImmFileName(_Out_ LPWSTR lpBuffer, _In_ size_t cchBuffer)
|
|
|
|
|
User32GetSystemFilePath(
|
|
|
|
|
_Out_writes_(cchBuffer) PWSTR lpBuffer,
|
|
|
|
|
_In_ SIZE_T cchBuffer,
|
|
|
|
|
_In_ PCWSTR pszFileName)
|
|
|
|
|
{
|
|
|
|
|
UINT length = GetSystemDirectoryW(lpBuffer, cchBuffer);
|
|
|
|
|
if (length && length < cchBuffer)
|
|
|
|
|
{
|
|
|
|
|
StringCchCatW(lpBuffer, cchBuffer, L"\\");
|
|
|
|
|
return StringCchCatW(lpBuffer, cchBuffer, L"imm32.dll");
|
|
|
|
|
return StringCchCatW(lpBuffer, cchBuffer, pszFileName);
|
|
|
|
|
}
|
|
|
|
|
return StringCchCopyW(lpBuffer, cchBuffer, L"imm32.dll");
|
|
|
|
|
DWORD dwError = GetLastError();
|
|
|
|
|
ERR("GetSystemDirectoryW failed (error %lu)\n", dwError);
|
|
|
|
|
StringCchCopyW(lpBuffer, cchBuffer, pszFileName);
|
|
|
|
|
return HRESULT_FROM_WIN32(dwError);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// @unimplemented
|
|
|
|
|
// Win: _InitializeImmEntryTable
|
|
|
|
|
static BOOL IntInitializeImmEntryTable(VOID)
|
|
|
|
|
{
|
|
|
|
|
WCHAR ImmFile[MAX_PATH];
|
|
|
|
@@ -76,8 +78,8 @@ static BOOL IntInitializeImmEntryTable(VOID)
|
|
|
|
|
if (IMM_FN(ImmWINNLSEnableIME) != IMMSTUB_ImmWINNLSEnableIME)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
User32GetImmFileName(ImmFile, _countof(ImmFile));
|
|
|
|
|
TRACE("File %S\n", ImmFile);
|
|
|
|
|
User32GetSystemFilePath(ImmFile, _countof(ImmFile), L"imm32.dll");
|
|
|
|
|
TRACE("File %s\n", debugstr_w(ImmFile));
|
|
|
|
|
|
|
|
|
|
/* If IMM32 is already loaded, use it without increasing reference count. */
|
|
|
|
|
if (imm32 == NULL)
|
|
|
|
@@ -115,14 +117,12 @@ static BOOL IntInitializeImmEntryTable(VOID)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Win: InitializeImmEntryTable
|
|
|
|
|
BOOL WINAPI InitializeImmEntryTable(VOID)
|
|
|
|
|
{
|
|
|
|
|
gbImmInitializing = TRUE;
|
|
|
|
|
return IntInitializeImmEntryTable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Win: User32InitializeImmEntryTable
|
|
|
|
|
BOOL WINAPI User32InitializeImmEntryTable(DWORD magic)
|
|
|
|
|
{
|
|
|
|
|
TRACE("Imm (%x)\n", magic);
|
|
|
|
@@ -139,7 +139,7 @@ BOOL WINAPI User32InitializeImmEntryTable(DWORD magic)
|
|
|
|
|
if (ghImm32 == NULL && !gbImmInitializing)
|
|
|
|
|
{
|
|
|
|
|
WCHAR ImmFile[MAX_PATH];
|
|
|
|
|
User32GetImmFileName(ImmFile, _countof(ImmFile));
|
|
|
|
|
User32GetSystemFilePath(ImmFile, _countof(ImmFile), L"imm32.dll");
|
|
|
|
|
ghImm32 = LoadLibraryW(ImmFile);
|
|
|
|
|
if (ghImm32 == NULL)
|
|
|
|
|
{
|
|
|
|
@@ -151,21 +151,18 @@ BOOL WINAPI User32InitializeImmEntryTable(DWORD magic)
|
|
|
|
|
return IMM_FN(ImmRegisterClient)(&gSharedInfo, ghImm32);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Win: ImeIsUsableContext
|
|
|
|
|
static BOOL User32CanSetImeWindowToImc(HIMC hIMC, HWND hImeWnd)
|
|
|
|
|
{
|
|
|
|
|
PIMC pIMC = ValidateHandle(hIMC, TYPE_INPUTCONTEXT);
|
|
|
|
|
return pIMC && (!pIMC->hImeWnd || pIMC->hImeWnd == hImeWnd || !ValidateHwnd(pIMC->hImeWnd));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Win: GetIMEShowStatus
|
|
|
|
|
static BOOL User32GetImeShowStatus(VOID)
|
|
|
|
|
{
|
|
|
|
|
return (BOOL)NtUserCallNoParam(NOPARAM_ROUTINE_GETIMESHOWSTATUS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Sends a message to the IME UI window. */
|
|
|
|
|
/* Win: SendMessageToUI(pimeui, uMsg, wParam, lParam, !unicode) */
|
|
|
|
|
static LRESULT
|
|
|
|
|
User32SendImeUIMessage(PIMEUI pimeui, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL unicode)
|
|
|
|
|
{
|
|
|
|
@@ -195,7 +192,6 @@ User32SendImeUIMessage(PIMEUI pimeui, UINT uMsg, WPARAM wParam, LPARAM lParam, B
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Win: SendOpenStatusNotify
|
|
|
|
|
static VOID User32NotifyOpenStatus(PIMEUI pimeui, HWND hwndIMC, BOOL bOpen)
|
|
|
|
|
{
|
|
|
|
|
WPARAM wParam = (bOpen ? IMN_OPENSTATUSWINDOW : IMN_CLOSESTATUSWINDOW);
|
|
|
|
@@ -210,7 +206,6 @@ static VOID User32NotifyOpenStatus(PIMEUI pimeui, HWND hwndIMC, BOOL bOpen)
|
|
|
|
|
User32SendImeUIMessage(pimeui, WM_IME_NOTIFY, wParam, 0, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Win: ImeMarkUsedContext
|
|
|
|
|
static VOID User32SetImeWindowOfImc(HIMC hIMC, HWND hImeWnd)
|
|
|
|
|
{
|
|
|
|
|
PIMC pIMC = ValidateHandle(hIMC, TYPE_INPUTCONTEXT);
|
|
|
|
@@ -220,7 +215,6 @@ static VOID User32SetImeWindowOfImc(HIMC hIMC, HWND hImeWnd)
|
|
|
|
|
NtUserUpdateInputContext(hIMC, UIC_IMEWINDOW, (ULONG_PTR)hImeWnd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Win: ImeSetImc
|
|
|
|
|
static VOID User32UpdateImcOfImeUI(PIMEUI pimeui, HIMC hNewIMC)
|
|
|
|
|
{
|
|
|
|
|
HWND hImeWnd;
|
|
|
|
@@ -242,7 +236,6 @@ static VOID User32UpdateImcOfImeUI(PIMEUI pimeui, HIMC hNewIMC)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Handles WM_IME_NOTIFY message of the default IME window. */
|
|
|
|
|
/* Win: ImeNotifyHandler */
|
|
|
|
|
static LRESULT ImeWnd_OnImeNotify(PIMEUI pimeui, WPARAM wParam, LPARAM lParam)
|
|
|
|
|
{
|
|
|
|
|
LRESULT ret = 0;
|
|
|
|
@@ -293,7 +286,6 @@ static LRESULT ImeWnd_OnImeNotify(PIMEUI pimeui, WPARAM wParam, LPARAM lParam)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Creates the IME UI window. */
|
|
|
|
|
/* Win: CreateIMEUI */
|
|
|
|
|
static HWND User32CreateImeUIWindow(PIMEUI pimeui, HKL hKL)
|
|
|
|
|
{
|
|
|
|
|
IMEINFOEX ImeInfoEx;
|
|
|
|
@@ -339,7 +331,6 @@ Quit:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Initializes the default IME window. */
|
|
|
|
|
/* Win: ImeWndCreateHandler */
|
|
|
|
|
static INT ImeWnd_OnCreate(PIMEUI pimeui, LPCREATESTRUCT lpCS)
|
|
|
|
|
{
|
|
|
|
|
PWND pParentWnd, pWnd = pimeui->spwnd;
|
|
|
|
@@ -371,7 +362,6 @@ static INT ImeWnd_OnCreate(PIMEUI pimeui, LPCREATESTRUCT lpCS)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Destroys the IME UI window. */
|
|
|
|
|
/* Win: DestroyIMEUI */
|
|
|
|
|
static VOID User32DestroyImeUIWindow(PIMEUI pimeui)
|
|
|
|
|
{
|
|
|
|
|
HWND hwndUI = pimeui->hwndUI;
|
|
|
|
@@ -387,7 +377,6 @@ static VOID User32DestroyImeUIWindow(PIMEUI pimeui)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Handles WM_IME_SELECT message of the default IME window. */
|
|
|
|
|
/* Win: ImeSelectHandler */
|
|
|
|
|
static VOID ImeWnd_OnImeSelect(PIMEUI pimeui, WPARAM wParam, LPARAM lParam)
|
|
|
|
|
{
|
|
|
|
|
HKL hKL;
|
|
|
|
@@ -422,7 +411,6 @@ static VOID ImeWnd_OnImeSelect(PIMEUI pimeui, WPARAM wParam, LPARAM lParam)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Handles WM_IME_CONTROL message of the default IME window. */
|
|
|
|
|
/* Win: ImeControlHandler(pimeui, wParam, lParam, !unicode) */
|
|
|
|
|
static LRESULT
|
|
|
|
|
ImeWnd_OnImeControl(PIMEUI pimeui, WPARAM wParam, LPARAM lParam, BOOL unicode)
|
|
|
|
|
{
|
|
|
|
@@ -558,7 +546,6 @@ ImeWnd_OnImeControl(PIMEUI pimeui, WPARAM wParam, LPARAM lParam, BOOL unicode)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Modify the IME activation status. */
|
|
|
|
|
/* Win: FocusSetIMCContext */
|
|
|
|
|
static VOID FASTCALL User32SetImeActivenessOfWindow(HWND hWnd, BOOL bActive)
|
|
|
|
|
{
|
|
|
|
|
HIMC hIMC;
|
|
|
|
@@ -574,7 +561,6 @@ static VOID FASTCALL User32SetImeActivenessOfWindow(HWND hWnd, BOOL bActive)
|
|
|
|
|
IMM_FN(ImmReleaseContext)(hWnd, hIMC);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Win: CtfLoadThreadLayout */
|
|
|
|
|
VOID FASTCALL CtfLoadThreadLayout(PIMEUI pimeui)
|
|
|
|
|
{
|
|
|
|
|
IMM_FN(CtfImmTIMActivate)(pimeui->hKL);
|
|
|
|
@@ -636,6 +622,59 @@ ImeWnd_SwitchSoftKbdProc(_In_ HIMC hIMC, _In_ LPARAM lParam)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// indicdll!12
|
|
|
|
|
typedef VOID (CALLBACK *FN_GetPenMenuData)(PUINT pnID, PDWORD_PTR pdwMenuData);
|
|
|
|
|
static FN_GetPenMenuData s_pGetPenMenuData = NULL;
|
|
|
|
|
#define IFN_GetPenMenuData 12
|
|
|
|
|
|
|
|
|
|
static BOOL CALLBACK
|
|
|
|
|
User32GetPenMenuData(_Out_ PUINT pnID, _Out_ PDWORD_PTR pdwMenuData)
|
|
|
|
|
{
|
|
|
|
|
if (!s_pGetPenMenuData)
|
|
|
|
|
{
|
|
|
|
|
WCHAR szPath[MAX_PATH];
|
|
|
|
|
HMODULE hIndicDll = GetModuleHandleW(L"indicdll.dll");
|
|
|
|
|
if (!hIndicDll)
|
|
|
|
|
{
|
|
|
|
|
User32GetSystemFilePath(szPath, _countof(szPath), L"indicdll.dll");
|
|
|
|
|
hIndicDll = LoadLibraryW(szPath);
|
|
|
|
|
}
|
|
|
|
|
if (!hIndicDll)
|
|
|
|
|
{
|
|
|
|
|
ERR("indicdll.dll not loaded: %s\n", debugstr_w(szPath));
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s_pGetPenMenuData =
|
|
|
|
|
(FN_GetPenMenuData)GetProcAddress(hIndicDll, MAKEINTRESOURCEA(IFN_GetPenMenuData));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!s_pGetPenMenuData)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
s_pGetPenMenuData(pnID, pdwMenuData);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IMS_IMEMENUITEMSELECTED
|
|
|
|
|
static VOID
|
|
|
|
|
User32ImeMenuItemSelected(HWND hwndTarget)
|
|
|
|
|
{
|
|
|
|
|
if (!IsWindow(hwndTarget))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
HIMC hIMC = IMM_FN(ImmGetContext)(hwndTarget);
|
|
|
|
|
if (!hIMC)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
UINT nID = 0;
|
|
|
|
|
DWORD_PTR dwMenuData = 0;
|
|
|
|
|
if (User32GetPenMenuData(&nID, &dwMenuData))
|
|
|
|
|
IMM_FN(ImmNotifyIME)(hIMC, NI_IMEMENUSELECTED, nID, dwMenuData);
|
|
|
|
|
|
|
|
|
|
IMM_FN(ImmReleaseContext)(hwndTarget, hIMC);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Handles WM_IME_SYSTEM message of the default IME window. */
|
|
|
|
|
static LRESULT ImeWnd_OnImeSystem(PIMEUI pimeui, WPARAM wParam, LPARAM lParam)
|
|
|
|
|
{
|
|
|
|
@@ -765,8 +804,8 @@ static LRESULT ImeWnd_OnImeSystem(PIMEUI pimeui, WPARAM wParam, LPARAM lParam)
|
|
|
|
|
ret = IMM_FN(ImmPutImeMenuItemsIntoMappedFile)((HIMC)lParam);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 0x1D:
|
|
|
|
|
FIXME("\n");
|
|
|
|
|
case IMS_IMEMENUITEMSELECTED:
|
|
|
|
|
User32ImeMenuItemSelected((HWND)lParam);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case IMS_GETCONTEXT:
|
|
|
|
@@ -792,7 +831,6 @@ static LRESULT ImeWnd_OnImeSystem(PIMEUI pimeui, WPARAM wParam, LPARAM lParam)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Handles WM_IME_SETCONTEXT message of the default IME window. */
|
|
|
|
|
/* Win: ImeSetContextHandler */
|
|
|
|
|
LRESULT ImeWnd_OnImeSetContext(PIMEUI pimeui, WPARAM wParam, LPARAM lParam)
|
|
|
|
|
{
|
|
|
|
|
LRESULT ret;
|
|
|
|
@@ -947,7 +985,6 @@ LRESULT ImeWnd_OnImeSetContext(PIMEUI pimeui, WPARAM wParam, LPARAM lParam)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The window procedure of the default IME window */
|
|
|
|
|
/* Win: ImeWndProcWorker(pWnd, msg, wParam, lParam, !unicode) */
|
|
|
|
|
LRESULT WINAPI
|
|
|
|
|
ImeWndProc_common(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode) // ReactOS
|
|
|
|
|
{
|
|
|
|
@@ -1103,19 +1140,16 @@ Finish:
|
|
|
|
|
return DefWindowProcA(hwnd, msg, wParam, lParam);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Win: ImeWndProcA
|
|
|
|
|
LRESULT WINAPI ImeWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
|
|
|
|
|
{
|
|
|
|
|
return ImeWndProc_common(hwnd, msg, wParam, lParam, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Win: ImeWndProcW
|
|
|
|
|
LRESULT WINAPI ImeWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
|
|
|
|
|
{
|
|
|
|
|
return ImeWndProc_common(hwnd, msg, wParam, lParam, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Win: UpdatePerUserImmEnabling
|
|
|
|
|
BOOL WINAPI UpdatePerUserImmEnabling(VOID)
|
|
|
|
|
{
|
|
|
|
|
HMODULE imm32;
|
|
|
|
|