2005-12-12 20:59:55 +00:00
|
|
|
/*
|
2021-08-17 23:42:12 +00:00
|
|
|
* PROJECT: ReactOS IMM32
|
|
|
|
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
|
|
|
* PURPOSE: Implementing Far-Eastern languages input
|
|
|
|
* COPYRIGHT: Copyright 1998 Patrik Stridvall
|
|
|
|
* Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
|
|
|
|
* Copyright 2017 James Tabor <james.tabor@reactos.org>
|
|
|
|
* Copyright 2018 Amine Khaldi <amine.khaldi@reactos.org>
|
|
|
|
* Copyright 2020 Oleg Dubinskiy <oleg.dubinskij2013@yandex.ua>
|
|
|
|
* Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
2005-12-12 20:59:55 +00:00
|
|
|
*/
|
|
|
|
|
2018-03-15 11:31:05 +00:00
|
|
|
#include <stdarg.h>
|
2010-03-07 11:27:14 +00:00
|
|
|
#include <stdio.h>
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2020-08-09 13:41:11 +00:00
|
|
|
#define WIN32_NO_STATUS
|
2021-07-11 00:48:15 +00:00
|
|
|
#include <windef.h>
|
|
|
|
#include <winbase.h>
|
|
|
|
#include <wingdi.h>
|
|
|
|
#include <winuser.h>
|
|
|
|
#include <winerror.h>
|
|
|
|
#include <wine/debug.h>
|
|
|
|
#include <imm.h>
|
|
|
|
#include <ddk/imm.h>
|
|
|
|
#include <winnls.h>
|
|
|
|
#include <winreg.h>
|
|
|
|
#include <wine/list.h>
|
2021-07-03 23:18:15 +00:00
|
|
|
#include <stdlib.h>
|
2020-08-09 13:41:11 +00:00
|
|
|
#include <ndk/umtypes.h>
|
|
|
|
#include <ndk/pstypes.h>
|
2021-07-11 00:48:15 +00:00
|
|
|
#include <ndk/rtlfuncs.h>
|
2020-08-09 13:41:11 +00:00
|
|
|
#include "../../../win32ss/include/ntuser.h"
|
2021-07-25 02:56:17 +00:00
|
|
|
#include "../../../win32ss/include/ntwin32.h"
|
2021-08-18 23:18:20 +00:00
|
|
|
#include <undocuser.h>
|
2021-07-03 23:18:15 +00:00
|
|
|
#include <imm32_undoc.h>
|
|
|
|
#include <strsafe.h>
|
2005-12-12 20:59:55 +00:00
|
|
|
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(imm);
|
|
|
|
|
2017-12-08 03:14:21 +00:00
|
|
|
#define IMM_INIT_MAGIC 0x19650412
|
2021-07-15 18:04:00 +00:00
|
|
|
#define IMM_INVALID_CANDFORM ULONG_MAX
|
2021-08-20 22:22:43 +00:00
|
|
|
#define INVALID_HOTKEY_ID 0xFFFFFFFF
|
2021-08-17 23:42:12 +00:00
|
|
|
#define MAX_CANDIDATEFORM 4
|
|
|
|
|
2021-07-31 06:56:11 +00:00
|
|
|
#define LANGID_CHINESE_SIMPLIFIED MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
|
|
|
|
#define LANGID_CHINESE_TRADITIONAL MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
|
|
|
|
#define LANGID_JAPANESE MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT)
|
|
|
|
|
2021-07-28 14:25:10 +00:00
|
|
|
#define REGKEY_KEYBOARD_LAYOUTS \
|
|
|
|
L"System\\CurrentControlSet\\Control\\Keyboard Layouts"
|
|
|
|
#define REGKEY_IMM \
|
|
|
|
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\IMM"
|
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
#define ROUNDUP4(n) (((n) + 3) & ~3) /* DWORD alignment */
|
|
|
|
|
|
|
|
HMODULE g_hImm32Inst = NULL;
|
2021-07-25 02:57:57 +00:00
|
|
|
RTL_CRITICAL_SECTION g_csImeDpi;
|
|
|
|
PIMEDPI g_pImeDpiList = NULL;
|
2021-07-28 14:25:10 +00:00
|
|
|
PSERVERINFO g_psi = NULL;
|
2021-08-04 00:41:59 +00:00
|
|
|
SHAREDINFO g_SharedInfo = { NULL };
|
|
|
|
BYTE g_bClientRegd = FALSE;
|
|
|
|
HANDLE g_hImm32Heap = NULL;
|
2021-07-25 02:57:57 +00:00
|
|
|
|
2021-08-23 21:50:39 +00:00
|
|
|
static PWND FASTCALL ValidateHwndNoErr(HWND hwnd)
|
|
|
|
{
|
|
|
|
PCLIENTINFO ClientInfo = GetWin32ClientInfo();
|
|
|
|
INT index;
|
|
|
|
PUSER_HANDLE_TABLE ht;
|
2021-09-07 20:05:54 +00:00
|
|
|
PUSER_HANDLE_ENTRY he;
|
2021-08-23 21:50:39 +00:00
|
|
|
WORD generation;
|
|
|
|
|
|
|
|
/* See if the window is cached */
|
|
|
|
if (hwnd == ClientInfo->CallbackWnd.hWnd)
|
|
|
|
return ClientInfo->CallbackWnd.pWnd;
|
|
|
|
|
|
|
|
if (!NtUserValidateHandleSecure(hwnd))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ht = g_SharedInfo.aheList; /* handle table */
|
2021-09-07 20:05:54 +00:00
|
|
|
ASSERT(ht);
|
|
|
|
/* ReactOS-Specific! */
|
|
|
|
ASSERT(g_SharedInfo.ulSharedDelta != 0);
|
|
|
|
he = (PUSER_HANDLE_ENTRY)((ULONG_PTR)ht->handles - g_SharedInfo.ulSharedDelta);
|
|
|
|
|
2021-08-23 21:50:39 +00:00
|
|
|
index = (LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1;
|
2021-09-07 20:05:54 +00:00
|
|
|
if (index < 0 || index >= ht->nb_handles || he[index].type != TYPE_WINDOW)
|
2021-08-23 21:50:39 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
generation = HIWORD(hwnd);
|
2021-09-07 20:05:54 +00:00
|
|
|
if (generation != he[index].generation && generation && generation != 0xFFFF)
|
2021-08-23 21:50:39 +00:00
|
|
|
return NULL;
|
|
|
|
|
2021-09-07 20:05:54 +00:00
|
|
|
return (PWND)&he[index];
|
2021-08-23 21:50:39 +00:00
|
|
|
}
|
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
static BOOL APIENTRY Imm32InitInstance(HMODULE hMod)
|
|
|
|
{
|
|
|
|
NTSTATUS status;
|
|
|
|
|
|
|
|
if (hMod)
|
|
|
|
g_hImm32Inst = hMod;
|
|
|
|
|
|
|
|
if (g_bClientRegd)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
status = RtlInitializeCriticalSection(&g_csImeDpi);
|
|
|
|
if (NT_ERROR(status))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
g_bClientRegd = TRUE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
LPVOID APIENTRY Imm32HeapAlloc(DWORD dwFlags, DWORD dwBytes)
|
|
|
|
{
|
|
|
|
if (!g_hImm32Heap)
|
|
|
|
{
|
|
|
|
g_hImm32Heap = RtlGetProcessHeap();
|
|
|
|
if (g_hImm32Heap == NULL)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return HeapAlloc(g_hImm32Heap, dwFlags, dwBytes);
|
|
|
|
}
|
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
static LPWSTR APIENTRY Imm32WideFromAnsi(LPCSTR pszA)
|
|
|
|
{
|
|
|
|
INT cch = lstrlenA(pszA);
|
|
|
|
LPWSTR pszW = Imm32HeapAlloc(0, (cch + 1) * sizeof(WCHAR));
|
|
|
|
if (pszW == NULL)
|
|
|
|
return NULL;
|
|
|
|
cch = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszA, cch, pszW, cch + 1);
|
|
|
|
pszW[cch] = 0;
|
|
|
|
return pszW;
|
|
|
|
}
|
|
|
|
|
|
|
|
static LPSTR APIENTRY Imm32AnsiFromWide(LPCWSTR pszW)
|
|
|
|
{
|
|
|
|
INT cchW = lstrlenW(pszW);
|
|
|
|
INT cchA = (cchW + 1) * sizeof(WCHAR);
|
|
|
|
LPSTR pszA = Imm32HeapAlloc(0, cchA);
|
|
|
|
if (!pszA)
|
|
|
|
return NULL;
|
|
|
|
cchA = WideCharToMultiByte(CP_ACP, 0, pszW, cchW, pszA, cchA, NULL, NULL);
|
|
|
|
pszA[cchA] = 0;
|
|
|
|
return pszA;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline BOOL Imm32IsCrossThreadAccess(HIMC hIMC)
|
|
|
|
{
|
2021-08-16 06:45:11 +00:00
|
|
|
DWORD dwImeThreadId = NtUserQueryInputContext(hIMC, 1);
|
2021-08-14 01:38:06 +00:00
|
|
|
DWORD dwThreadId = GetCurrentThreadId();
|
|
|
|
return (dwImeThreadId != dwThreadId);
|
|
|
|
}
|
|
|
|
|
2021-08-23 21:50:39 +00:00
|
|
|
static BOOL Imm32IsCrossProcessAccess(HWND hWnd)
|
|
|
|
{
|
|
|
|
return (NtUserQueryWindow(hWnd, QUERY_WINDOW_UNIQUE_PROCESS_ID) !=
|
|
|
|
(DWORD_PTR)NtCurrentTeb()->ClientId.UniqueProcess);
|
|
|
|
}
|
|
|
|
|
2021-07-25 02:57:57 +00:00
|
|
|
static VOID APIENTRY Imm32FreeImeDpi(PIMEDPI pImeDpi, BOOL bDestroy)
|
|
|
|
{
|
|
|
|
if (pImeDpi->hInst == NULL)
|
|
|
|
return;
|
|
|
|
if (bDestroy)
|
|
|
|
pImeDpi->ImeDestroy(0);
|
|
|
|
FreeLibrary(pImeDpi->hInst);
|
|
|
|
pImeDpi->hInst = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL APIENTRY
|
|
|
|
Imm32NotifyAction(HIMC hIMC, HWND hwnd, DWORD dwAction, DWORD_PTR dwIndex, DWORD_PTR dwValue,
|
|
|
|
DWORD_PTR dwCommand, DWORD_PTR dwData)
|
|
|
|
{
|
|
|
|
DWORD dwLayout;
|
|
|
|
HKL hKL;
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
|
|
|
|
if (dwAction)
|
|
|
|
{
|
2021-08-16 06:45:11 +00:00
|
|
|
dwLayout = NtUserQueryInputContext(hIMC, 1);
|
2021-07-25 02:57:57 +00:00
|
|
|
if (dwLayout)
|
|
|
|
{
|
|
|
|
/* find keyboard layout and lock it */
|
|
|
|
hKL = GetKeyboardLayout(dwLayout);
|
|
|
|
pImeDpi = ImmLockImeDpi(hKL);
|
|
|
|
if (pImeDpi)
|
|
|
|
{
|
|
|
|
/* do notify */
|
|
|
|
pImeDpi->NotifyIME(hIMC, dwAction, dwIndex, dwValue);
|
|
|
|
|
|
|
|
ImmUnlockImeDpi(pImeDpi); /* unlock */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hwnd && dwCommand)
|
|
|
|
SendMessageW(hwnd, WM_IME_NOTIFY, dwCommand, dwData);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
static PIMEDPI APIENTRY Imm32FindImeDpi(HKL hKL)
|
|
|
|
{
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
|
|
|
|
RtlEnterCriticalSection(&g_csImeDpi);
|
|
|
|
for (pImeDpi = g_pImeDpiList; pImeDpi != NULL; pImeDpi = pImeDpi->pNext)
|
|
|
|
{
|
|
|
|
if (pImeDpi->hKL == hKL)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
RtlLeaveCriticalSection(&g_csImeDpi);
|
|
|
|
|
|
|
|
return pImeDpi;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL Imm32GetSystemLibraryPath(LPWSTR pszPath, DWORD cchPath, LPCWSTR pszFileName)
|
|
|
|
{
|
|
|
|
if (!pszFileName[0] || !GetSystemDirectoryW(pszPath, cchPath))
|
|
|
|
return FALSE;
|
|
|
|
StringCchCatW(pszPath, cchPath, L"\\");
|
|
|
|
StringCchCatW(pszPath, cchPath, pszFileName);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL APIENTRY Imm32InquireIme(PIMEDPI pImeDpi)
|
|
|
|
{
|
|
|
|
WCHAR szUIClass[64];
|
|
|
|
WNDCLASSW wcW;
|
|
|
|
DWORD dwSysInfoFlags = 0; // TODO: ???
|
|
|
|
LPIMEINFO pImeInfo = &pImeDpi->ImeInfo;
|
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
// TODO: NtUserGetThreadState(16);
|
2021-08-04 00:41:59 +00:00
|
|
|
|
|
|
|
if (!IS_IME_HKL(pImeDpi->hKL))
|
|
|
|
{
|
|
|
|
if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED) &&
|
|
|
|
pImeDpi->CtfImeInquireExW)
|
|
|
|
{
|
|
|
|
// TODO:
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pImeDpi->ImeInquire(pImeInfo, szUIClass, dwSysInfoFlags))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
szUIClass[_countof(szUIClass) - 1] = 0;
|
|
|
|
|
|
|
|
if (pImeInfo->dwPrivateDataSize == 0)
|
|
|
|
pImeInfo->dwPrivateDataSize = 4;
|
|
|
|
|
|
|
|
#define VALID_IME_PROP (IME_PROP_AT_CARET | \
|
|
|
|
IME_PROP_SPECIAL_UI | \
|
|
|
|
IME_PROP_CANDLIST_START_FROM_1 | \
|
|
|
|
IME_PROP_UNICODE | \
|
|
|
|
IME_PROP_COMPLETE_ON_UNSELECT | \
|
|
|
|
IME_PROP_END_UNLOAD | \
|
|
|
|
IME_PROP_KBD_CHAR_FIRST | \
|
|
|
|
IME_PROP_IGNORE_UPKEYS | \
|
|
|
|
IME_PROP_NEED_ALTKEY | \
|
|
|
|
IME_PROP_NO_KEYS_ON_CLOSE | \
|
|
|
|
IME_PROP_ACCEPT_WIDE_VKEY)
|
|
|
|
#define VALID_CMODE_CAPS (IME_CMODE_ALPHANUMERIC | \
|
|
|
|
IME_CMODE_NATIVE | \
|
|
|
|
IME_CMODE_KATAKANA | \
|
|
|
|
IME_CMODE_LANGUAGE | \
|
|
|
|
IME_CMODE_FULLSHAPE | \
|
|
|
|
IME_CMODE_ROMAN | \
|
|
|
|
IME_CMODE_CHARCODE | \
|
|
|
|
IME_CMODE_HANJACONVERT | \
|
|
|
|
IME_CMODE_SOFTKBD | \
|
|
|
|
IME_CMODE_NOCONVERSION | \
|
|
|
|
IME_CMODE_EUDC | \
|
|
|
|
IME_CMODE_SYMBOL | \
|
|
|
|
IME_CMODE_FIXED)
|
|
|
|
#define VALID_SMODE_CAPS (IME_SMODE_NONE | \
|
|
|
|
IME_SMODE_PLAURALCLAUSE | \
|
|
|
|
IME_SMODE_SINGLECONVERT | \
|
|
|
|
IME_SMODE_AUTOMATIC | \
|
|
|
|
IME_SMODE_PHRASEPREDICT | \
|
|
|
|
IME_SMODE_CONVERSATION)
|
|
|
|
#define VALID_UI_CAPS (UI_CAP_2700 | \
|
|
|
|
UI_CAP_ROT90 | \
|
|
|
|
UI_CAP_ROTANY | \
|
|
|
|
UI_CAP_SOFTKBD)
|
|
|
|
#define VALID_SCS_CAPS (SCS_CAP_COMPSTR | \
|
|
|
|
SCS_CAP_MAKEREAD | \
|
|
|
|
SCS_CAP_SETRECONVERTSTRING)
|
|
|
|
#define VALID_SELECT_CAPS (SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE)
|
|
|
|
|
|
|
|
if (pImeInfo->fdwProperty & ~VALID_IME_PROP)
|
|
|
|
return FALSE;
|
|
|
|
if (pImeInfo->fdwConversionCaps & ~VALID_CMODE_CAPS)
|
|
|
|
return FALSE;
|
|
|
|
if (pImeInfo->fdwSentenceCaps & ~VALID_SMODE_CAPS)
|
|
|
|
return FALSE;
|
|
|
|
if (pImeInfo->fdwUICaps & ~VALID_UI_CAPS)
|
|
|
|
return FALSE;
|
|
|
|
if (pImeInfo->fdwSCSCaps & ~VALID_SCS_CAPS)
|
|
|
|
return FALSE;
|
|
|
|
if (pImeInfo->fdwSelectCaps & ~VALID_SELECT_CAPS)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
#undef VALID_IME_PROP
|
|
|
|
#undef VALID_CMODE_CAPS
|
|
|
|
#undef VALID_SMODE_CAPS
|
|
|
|
#undef VALID_UI_CAPS
|
|
|
|
#undef VALID_SCS_CAPS
|
|
|
|
#undef VALID_SELECT_CAPS
|
|
|
|
|
|
|
|
if (pImeInfo->fdwProperty & IME_PROP_UNICODE)
|
|
|
|
{
|
|
|
|
StringCchCopyW(pImeDpi->szUIClass, _countof(pImeDpi->szUIClass), szUIClass);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (pImeDpi->uCodePage != GetACP() && pImeDpi->uCodePage)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPSTR)szUIClass, -1,
|
|
|
|
pImeDpi->szUIClass, _countof(pImeDpi->szUIClass));
|
|
|
|
}
|
|
|
|
|
|
|
|
return GetClassInfoW(pImeDpi->hInst, pImeDpi->szUIClass, &wcW);
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL APIENTRY Imm32LoadImeInfo(PIMEINFOEX pImeInfoEx, PIMEDPI pImeDpi)
|
|
|
|
{
|
|
|
|
WCHAR szPath[MAX_PATH];
|
|
|
|
HINSTANCE hIME;
|
|
|
|
FARPROC fn;
|
|
|
|
|
|
|
|
if (!Imm32GetSystemLibraryPath(szPath, _countof(szPath), pImeInfoEx->wszImeFile))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
hIME = GetModuleHandleW(szPath);
|
|
|
|
if (hIME == NULL)
|
|
|
|
{
|
|
|
|
hIME = LoadLibraryW(szPath);
|
|
|
|
if (hIME == NULL)
|
|
|
|
{
|
|
|
|
ERR("Imm32LoadImeInfo: LoadLibraryW(%S) failed\n", szPath);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pImeDpi->hInst = hIME;
|
|
|
|
|
|
|
|
#define DEFINE_IME_ENTRY(type, name, params, extended) \
|
|
|
|
do { \
|
|
|
|
fn = GetProcAddress(hIME, #name); \
|
|
|
|
if (fn) pImeDpi->name = (FN_##name)fn; \
|
|
|
|
else if (!extended) goto Failed; \
|
|
|
|
} while (0);
|
|
|
|
#include "../../../win32ss/include/imetable.h"
|
|
|
|
#undef DEFINE_IME_ENTRY
|
|
|
|
|
|
|
|
if (!Imm32InquireIme(pImeDpi))
|
|
|
|
{
|
|
|
|
ERR("Imm32LoadImeInfo: Imm32InquireIme failed\n");
|
|
|
|
goto Failed;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pImeInfoEx->fLoadFlag)
|
|
|
|
return TRUE;
|
|
|
|
|
2021-08-16 06:45:11 +00:00
|
|
|
NtUserSetImeOwnerWindow(pImeInfoEx, TRUE);
|
2021-08-04 00:41:59 +00:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
Failed:
|
|
|
|
FreeLibrary(pImeDpi->hInst);
|
|
|
|
pImeDpi->hInst = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
#ifdef IMP_SUPPORT /* 3.x support */
|
|
|
|
static DWORD APIENTRY
|
|
|
|
ImpJTransCompA(LPINPUTCONTEXTDX pIC, LPCOMPOSITIONSTRING pCS,
|
|
|
|
const TRANSMSG *pSrc, LPTRANSMSG pDest)
|
|
|
|
{
|
|
|
|
// FIXME
|
|
|
|
*pDest = *pSrc;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DWORD APIENTRY
|
|
|
|
ImpJTransCompW(LPINPUTCONTEXTDX pIC, LPCOMPOSITIONSTRING pCS,
|
|
|
|
const TRANSMSG *pSrc, LPTRANSMSG pDest)
|
|
|
|
{
|
|
|
|
// FIXME
|
|
|
|
*pDest = *pSrc;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef LRESULT (WINAPI *FN_SendMessage)(HWND, UINT, WPARAM, LPARAM);
|
|
|
|
|
|
|
|
static DWORD APIENTRY
|
|
|
|
ImpJTrans(DWORD dwCount, LPTRANSMSG pTrans, LPINPUTCONTEXTDX pIC,
|
|
|
|
LPCOMPOSITIONSTRING pCS, BOOL bAnsi)
|
|
|
|
{
|
|
|
|
DWORD ret = 0;
|
|
|
|
HWND hWnd, hwndDefIME;
|
|
|
|
LPTRANSMSG pTempList, pEntry, pNext;
|
|
|
|
DWORD dwIndex, iCandForm, dwNumber, cbTempList;
|
|
|
|
HGLOBAL hGlobal;
|
|
|
|
CANDIDATEFORM CandForm;
|
|
|
|
FN_SendMessage pSendMessage;
|
|
|
|
|
|
|
|
hWnd = pIC->hWnd;
|
|
|
|
hwndDefIME = ImmGetDefaultIMEWnd(hWnd);
|
|
|
|
pSendMessage = (IsWindowUnicode(hWnd) ? SendMessageW : SendMessageA);
|
|
|
|
|
|
|
|
// clone the message list
|
|
|
|
cbTempList = (dwCount + 1) * sizeof(TRANSMSG);
|
|
|
|
pTempList = Imm32HeapAlloc(HEAP_ZERO_MEMORY, cbTempList);
|
|
|
|
if (pTempList == NULL)
|
|
|
|
return 0;
|
|
|
|
RtlCopyMemory(pTempList, pTrans, dwCount * sizeof(TRANSMSG));
|
|
|
|
|
|
|
|
if (pIC->dwUIFlags & 0x2)
|
|
|
|
{
|
|
|
|
// find WM_IME_ENDCOMPOSITION
|
|
|
|
pEntry = pTempList;
|
|
|
|
for (dwIndex = 0; dwIndex < dwCount; ++dwIndex, ++pEntry)
|
|
|
|
{
|
|
|
|
if (pEntry->message == WM_IME_ENDCOMPOSITION)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pEntry->message == WM_IME_ENDCOMPOSITION) // if found
|
|
|
|
{
|
|
|
|
// move WM_IME_ENDCOMPOSITION to the end of the list
|
|
|
|
for (pNext = pEntry + 1; pNext->message != 0; ++pEntry, ++pNext)
|
|
|
|
*pEntry = *pNext;
|
|
|
|
|
|
|
|
pEntry->message = WM_IME_ENDCOMPOSITION;
|
|
|
|
pEntry->wParam = 0;
|
|
|
|
pEntry->lParam = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (pEntry = pTempList; pEntry->message != 0; ++pEntry)
|
|
|
|
{
|
|
|
|
switch (pEntry->message)
|
|
|
|
{
|
|
|
|
case WM_IME_STARTCOMPOSITION:
|
|
|
|
if (!(pIC->dwUIFlags & 0x2))
|
|
|
|
{
|
|
|
|
// send IR_OPENCONVERT
|
|
|
|
if (pIC->cfCompForm.dwStyle != CFS_DEFAULT)
|
|
|
|
pSendMessage(hWnd, WM_IME_REPORT, IR_OPENCONVERT, 0);
|
|
|
|
|
|
|
|
goto DoDefault;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_IME_ENDCOMPOSITION:
|
|
|
|
if (pIC->dwUIFlags & 0x2)
|
|
|
|
{
|
|
|
|
// send IR_UNDETERMINE
|
|
|
|
hGlobal = GlobalAlloc(GHND | GMEM_SHARE, sizeof(UNDETERMINESTRUCT));
|
|
|
|
if (hGlobal)
|
|
|
|
{
|
|
|
|
pSendMessage(hWnd, WM_IME_REPORT, IR_UNDETERMINE, (LPARAM)hGlobal);
|
|
|
|
GlobalFree(hGlobal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// send IR_CLOSECONVERT
|
|
|
|
if (pIC->cfCompForm.dwStyle != CFS_DEFAULT)
|
|
|
|
pSendMessage(hWnd, WM_IME_REPORT, IR_CLOSECONVERT, 0);
|
|
|
|
|
|
|
|
goto DoDefault;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_IME_COMPOSITION:
|
|
|
|
if (bAnsi)
|
|
|
|
dwNumber = ImpJTransCompA(pIC, pCS, pEntry, pTrans);
|
|
|
|
else
|
|
|
|
dwNumber = ImpJTransCompW(pIC, pCS, pEntry, pTrans);
|
|
|
|
|
|
|
|
ret += dwNumber;
|
|
|
|
pTrans += dwNumber;
|
|
|
|
|
|
|
|
// send IR_CHANGECONVERT
|
|
|
|
if (!(pIC->dwUIFlags & 0x2))
|
|
|
|
{
|
|
|
|
if (pIC->cfCompForm.dwStyle != CFS_DEFAULT)
|
|
|
|
pSendMessage(hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_IME_NOTIFY:
|
|
|
|
if (pEntry->wParam == IMN_OPENCANDIDATE)
|
|
|
|
{
|
|
|
|
if (IsWindow(hWnd) && (pIC->dwUIFlags & 0x2))
|
|
|
|
{
|
|
|
|
// send IMC_SETCANDIDATEPOS
|
|
|
|
for (iCandForm = 0; iCandForm < MAX_CANDIDATEFORM; ++iCandForm)
|
|
|
|
{
|
|
|
|
if (!(pEntry->lParam & (1 << iCandForm)))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
CandForm.dwIndex = iCandForm;
|
|
|
|
CandForm.dwStyle = CFS_EXCLUDE;
|
|
|
|
CandForm.ptCurrentPos = pIC->cfCompForm.ptCurrentPos;
|
|
|
|
CandForm.rcArea = pIC->cfCompForm.rcArea;
|
|
|
|
pSendMessage(hwndDefIME, WM_IME_CONTROL, IMC_SETCANDIDATEPOS,
|
|
|
|
(LPARAM)&CandForm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(pIC->dwUIFlags & 0x2))
|
|
|
|
goto DoDefault;
|
|
|
|
|
|
|
|
// send a WM_IME_NOTIFY notification to the default ime window
|
|
|
|
pSendMessage(hwndDefIME, pEntry->message, pEntry->wParam, pEntry->lParam);
|
|
|
|
break;
|
|
|
|
|
|
|
|
DoDefault:
|
|
|
|
default:
|
|
|
|
// default processing
|
|
|
|
*pTrans++ = *pEntry;
|
|
|
|
++ret;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
HeapFree(g_hImm32Heap, 0, pTempList);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DWORD APIENTRY
|
|
|
|
ImpKTrans(DWORD dwCount, LPTRANSMSG pEntries, LPINPUTCONTEXTDX pIC,
|
|
|
|
LPCOMPOSITIONSTRING pCS, BOOL bAnsi)
|
|
|
|
{
|
|
|
|
return dwCount; // FIXME
|
|
|
|
}
|
|
|
|
|
|
|
|
static DWORD APIENTRY
|
|
|
|
ImpTrans(DWORD dwCount, LPTRANSMSG pEntries, HIMC hIMC, BOOL bAnsi, WORD wLang)
|
|
|
|
{
|
|
|
|
BOOL ret = FALSE;
|
|
|
|
LPINPUTCONTEXTDX pIC;
|
|
|
|
LPCOMPOSITIONSTRING pCS;
|
|
|
|
|
|
|
|
pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
pCS = ImmLockIMCC(pIC->hCompStr);
|
|
|
|
if (pCS)
|
|
|
|
{
|
|
|
|
if (wLang == LANG_JAPANESE)
|
|
|
|
ret = ImpJTrans(dwCount, pEntries, pIC, pCS, bAnsi);
|
|
|
|
else if (wLang == LANG_KOREAN)
|
|
|
|
ret = ImpKTrans(dwCount, pEntries, pIC, pCS, bAnsi);
|
|
|
|
ImmUnlockIMCC(pIC->hCompStr);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif /* def IMP_SUPPORT */
|
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
static PIMEDPI APIENTRY Ime32LoadImeDpi(HKL hKL, BOOL bLock)
|
|
|
|
{
|
|
|
|
IMEINFOEX ImeInfoEx;
|
|
|
|
CHARSETINFO ci;
|
|
|
|
PIMEDPI pImeDpiNew, pImeDpiFound;
|
|
|
|
UINT uCodePage;
|
|
|
|
LCID lcid;
|
|
|
|
|
|
|
|
if (!ImmGetImeInfoEx(&ImeInfoEx, ImeInfoExKeyboardLayout, &hKL) ||
|
|
|
|
ImeInfoEx.fLoadFlag == 1)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pImeDpiNew = Imm32HeapAlloc(HEAP_ZERO_MEMORY, sizeof(IMEDPI));
|
|
|
|
if (pImeDpiNew == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
pImeDpiNew->hKL = hKL;
|
|
|
|
|
|
|
|
lcid = LOWORD(hKL);
|
|
|
|
if (TranslateCharsetInfo((LPDWORD)(DWORD_PTR)lcid, &ci, TCI_SRCLOCALE))
|
|
|
|
uCodePage = ci.ciACP;
|
|
|
|
else
|
|
|
|
uCodePage = CP_ACP;
|
|
|
|
pImeDpiNew->uCodePage = uCodePage;
|
|
|
|
|
|
|
|
if (!Imm32LoadImeInfo(&ImeInfoEx, pImeDpiNew))
|
|
|
|
{
|
|
|
|
HeapFree(g_hImm32Heap, 0, pImeDpiNew);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlEnterCriticalSection(&g_csImeDpi);
|
|
|
|
|
|
|
|
pImeDpiFound = Imm32FindImeDpi(hKL);
|
|
|
|
if (pImeDpiFound)
|
|
|
|
{
|
|
|
|
if (!bLock)
|
|
|
|
pImeDpiFound->dwFlags &= ~IMEDPI_FLAG_LOCKED;
|
|
|
|
|
|
|
|
RtlLeaveCriticalSection(&g_csImeDpi);
|
|
|
|
|
|
|
|
Imm32FreeImeDpi(pImeDpiNew, FALSE);
|
|
|
|
HeapFree(g_hImm32Heap, 0, pImeDpiNew);
|
|
|
|
return pImeDpiFound;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (bLock)
|
|
|
|
{
|
|
|
|
pImeDpiNew->dwFlags |= IMEDPI_FLAG_LOCKED;
|
|
|
|
pImeDpiNew->cLockObj = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
pImeDpiNew->pNext = g_pImeDpiList;
|
|
|
|
g_pImeDpiList = pImeDpiNew;
|
|
|
|
|
|
|
|
RtlLeaveCriticalSection(&g_csImeDpi);
|
|
|
|
return pImeDpiNew;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmLoadIME (IMM32.@)
|
|
|
|
*/
|
2021-08-04 00:41:59 +00:00
|
|
|
BOOL WINAPI ImmLoadIME(HKL hKL)
|
|
|
|
{
|
|
|
|
PW32CLIENTINFO pInfo;
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
|
|
|
|
if (!IS_IME_HKL(hKL))
|
|
|
|
{
|
|
|
|
if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
pInfo = (PW32CLIENTINFO)(NtCurrentTeb()->Win32ClientInfo);
|
|
|
|
if ((pInfo->W32ClientInfo[0] & 2))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pImeDpi = Imm32FindImeDpi(hKL);
|
|
|
|
if (pImeDpi == NULL)
|
|
|
|
pImeDpi = Ime32LoadImeDpi(hKL, FALSE);
|
|
|
|
return (pImeDpi != NULL);
|
|
|
|
}
|
|
|
|
|
2021-08-09 23:08:23 +00:00
|
|
|
PIMEDPI APIENTRY ImmLockOrLoadImeDpi(HKL hKL)
|
|
|
|
{
|
|
|
|
PW32CLIENTINFO pInfo;
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
|
|
|
|
if (!IS_IME_HKL(hKL))
|
|
|
|
{
|
|
|
|
if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
pInfo = (PW32CLIENTINFO)(NtCurrentTeb()->Win32ClientInfo);
|
|
|
|
if ((pInfo->W32ClientInfo[0] & 2))
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pImeDpi = ImmLockImeDpi(hKL);
|
|
|
|
if (pImeDpi == NULL)
|
|
|
|
pImeDpi = Ime32LoadImeDpi(hKL, TRUE);
|
|
|
|
return pImeDpi;
|
|
|
|
}
|
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmLoadLayout (IMM32.@)
|
|
|
|
*/
|
2021-07-28 14:25:10 +00:00
|
|
|
HKL WINAPI ImmLoadLayout(HKL hKL, PIMEINFOEX pImeInfoEx)
|
|
|
|
{
|
|
|
|
DWORD cbData;
|
|
|
|
UNICODE_STRING UnicodeString;
|
|
|
|
HKEY hLayoutKey = NULL, hLayoutsKey = NULL;
|
|
|
|
LONG error;
|
|
|
|
NTSTATUS Status;
|
|
|
|
WCHAR szLayout[MAX_PATH];
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p, %p)\n", hKL, pImeInfoEx);
|
2021-07-28 14:25:10 +00:00
|
|
|
|
|
|
|
if (IS_IME_HKL(hKL) ||
|
2021-08-04 00:41:59 +00:00
|
|
|
!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED) ||
|
2021-07-28 14:25:10 +00:00
|
|
|
((PW32CLIENTINFO)NtCurrentTeb()->Win32ClientInfo)->W32ClientInfo[0] & 2)
|
|
|
|
{
|
|
|
|
UnicodeString.Buffer = szLayout;
|
|
|
|
UnicodeString.MaximumLength = sizeof(szLayout);
|
|
|
|
Status = RtlIntegerToUnicodeString((DWORD_PTR)hKL, 16, &UnicodeString);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
error = RegOpenKeyW(HKEY_LOCAL_MACHINE, REGKEY_KEYBOARD_LAYOUTS, &hLayoutsKey);
|
|
|
|
if (error)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
error = RegOpenKeyW(hLayoutsKey, szLayout, &hLayoutKey);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
error = RegOpenKeyW(HKEY_LOCAL_MACHINE, REGKEY_IMM, &hLayoutKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error)
|
|
|
|
{
|
|
|
|
ERR("RegOpenKeyW error: 0x%08lX\n", error);
|
|
|
|
hKL = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cbData = sizeof(pImeInfoEx->wszImeFile);
|
|
|
|
error = RegQueryValueExW(hLayoutKey, L"Ime File", 0, 0,
|
|
|
|
(LPBYTE)pImeInfoEx->wszImeFile, &cbData);
|
|
|
|
if (error)
|
|
|
|
hKL = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
RegCloseKey(hLayoutKey);
|
|
|
|
if (hLayoutsKey)
|
|
|
|
RegCloseKey(hLayoutsKey);
|
|
|
|
return hKL;
|
|
|
|
}
|
|
|
|
|
2008-04-04 13:20:27 +00:00
|
|
|
typedef struct _tagImmHkl{
|
|
|
|
struct list entry;
|
|
|
|
HKL hkl;
|
|
|
|
HMODULE hIME;
|
|
|
|
IMEINFO imeInfo;
|
|
|
|
WCHAR imeClassName[17]; /* 16 character max */
|
|
|
|
ULONG uSelected;
|
2013-02-03 20:58:12 +00:00
|
|
|
HWND UIWnd;
|
2008-04-04 13:20:27 +00:00
|
|
|
|
|
|
|
/* Function Pointers */
|
2018-10-01 11:53:21 +00:00
|
|
|
BOOL (WINAPI *pImeInquire)(IMEINFO *, WCHAR *, const WCHAR *);
|
|
|
|
BOOL (WINAPI *pImeConfigure)(HKL, HWND, DWORD, void *);
|
|
|
|
BOOL (WINAPI *pImeDestroy)(UINT);
|
|
|
|
LRESULT (WINAPI *pImeEscape)(HIMC, UINT, void *);
|
|
|
|
BOOL (WINAPI *pImeSelect)(HIMC, BOOL);
|
|
|
|
BOOL (WINAPI *pImeSetActiveContext)(HIMC, BOOL);
|
|
|
|
UINT (WINAPI *pImeToAsciiEx)(UINT, UINT, const BYTE *, DWORD *, UINT, HIMC);
|
|
|
|
BOOL (WINAPI *pNotifyIME)(HIMC, DWORD, DWORD, DWORD);
|
|
|
|
BOOL (WINAPI *pImeRegisterWord)(const WCHAR *, DWORD, const WCHAR *);
|
|
|
|
BOOL (WINAPI *pImeUnregisterWord)(const WCHAR *, DWORD, const WCHAR *);
|
|
|
|
UINT (WINAPI *pImeEnumRegisterWord)(REGISTERWORDENUMPROCW, const WCHAR *, DWORD, const WCHAR *, void *);
|
|
|
|
BOOL (WINAPI *pImeSetCompositionString)(HIMC, DWORD, const void *, DWORD, const void *, DWORD);
|
|
|
|
DWORD (WINAPI *pImeConversionList)(HIMC, const WCHAR *, CANDIDATELIST *, DWORD, UINT);
|
|
|
|
BOOL (WINAPI *pImeProcessKey)(HIMC, UINT, LPARAM, const BYTE *);
|
|
|
|
UINT (WINAPI *pImeGetRegisterWordStyle)(UINT, STYLEBUFW *);
|
|
|
|
DWORD (WINAPI *pImeGetImeMenuItems)(HIMC, DWORD, DWORD, IMEMENUITEMINFOW *, IMEMENUITEMINFOW *, DWORD);
|
2008-04-04 13:20:27 +00:00
|
|
|
} ImmHkl;
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
typedef struct tagInputContextData
|
|
|
|
{
|
2007-09-14 08:03:04 +00:00
|
|
|
DWORD dwLock;
|
|
|
|
INPUTCONTEXT IMC;
|
2017-12-08 03:14:21 +00:00
|
|
|
DWORD threadID;
|
2008-04-04 13:20:27 +00:00
|
|
|
|
|
|
|
ImmHkl *immKbd;
|
2010-03-07 11:27:14 +00:00
|
|
|
UINT lastVK;
|
2017-12-08 03:14:21 +00:00
|
|
|
BOOL threadDefault;
|
2014-09-28 18:27:58 +00:00
|
|
|
DWORD magic;
|
2005-12-12 20:59:55 +00:00
|
|
|
} InputContextData;
|
|
|
|
|
2014-09-28 18:27:58 +00:00
|
|
|
#define WINE_IMC_VALID_MAGIC 0x56434D49
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
typedef struct _tagIMMThreadData {
|
2017-12-08 03:14:21 +00:00
|
|
|
struct list entry;
|
|
|
|
DWORD threadID;
|
2010-03-07 11:27:14 +00:00
|
|
|
HIMC defaultContext;
|
|
|
|
HWND hwndDefault;
|
2017-12-08 03:14:21 +00:00
|
|
|
BOOL disableIME;
|
|
|
|
DWORD windowRefs;
|
2010-03-07 11:27:14 +00:00
|
|
|
} IMMThreadData;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2008-04-04 13:20:27 +00:00
|
|
|
static struct list ImmHklList = LIST_INIT(ImmHklList);
|
2017-12-08 03:14:21 +00:00
|
|
|
static struct list ImmThreadDataList = LIST_INIT(ImmThreadDataList);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2008-04-04 13:20:27 +00:00
|
|
|
static const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
|
2010-03-07 11:27:14 +00:00
|
|
|
|
|
|
|
static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
|
|
|
|
static const WCHAR szLayoutTextW[] = {'L','a','y','o','u','t',' ','T','e','x','t',0};
|
|
|
|
static const WCHAR szImeRegFmt[] = {'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','s','\\','%','0','8','l','x',0};
|
|
|
|
|
2013-02-03 20:58:12 +00:00
|
|
|
static const WCHAR szwIME[] = {'I','M','E',0};
|
2017-12-08 03:14:21 +00:00
|
|
|
static const WCHAR szwDefaultIME[] = {'D','e','f','a','u','l','t',' ','I','M','E',0};
|
2013-02-03 20:58:12 +00:00
|
|
|
|
2017-12-08 03:14:21 +00:00
|
|
|
static CRITICAL_SECTION threaddata_cs;
|
|
|
|
static CRITICAL_SECTION_DEBUG critsect_debug =
|
|
|
|
{
|
|
|
|
0, 0, &threaddata_cs,
|
|
|
|
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
|
|
|
|
0, 0, { (DWORD_PTR)(__FILE__ ": threaddata_cs") }
|
|
|
|
};
|
|
|
|
static CRITICAL_SECTION threaddata_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2019-11-02 17:34:15 +00:00
|
|
|
static inline BOOL is_himc_ime_unicode(const InputContextData *data)
|
|
|
|
{
|
|
|
|
return !!(data->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline BOOL is_kbd_ime_unicode(const ImmHkl *hkl)
|
|
|
|
{
|
|
|
|
return !!(hkl->imeInfo.fdwProperty & IME_PROP_UNICODE);
|
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2017-12-08 03:14:21 +00:00
|
|
|
static InputContextData* get_imc_data(HIMC hIMC);
|
2010-03-07 11:27:14 +00:00
|
|
|
|
|
|
|
static inline WCHAR *strdupAtoW( const char *str )
|
|
|
|
{
|
|
|
|
WCHAR *ret = NULL;
|
|
|
|
if (str)
|
|
|
|
{
|
|
|
|
DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
|
|
|
|
if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
|
|
|
|
MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline CHAR *strdupWtoA( const WCHAR *str )
|
|
|
|
{
|
|
|
|
CHAR *ret = NULL;
|
|
|
|
if (str)
|
|
|
|
{
|
|
|
|
DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
|
|
|
|
if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
|
|
|
|
WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-09-28 18:27:58 +00:00
|
|
|
static HMODULE load_graphics_driver(void)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2014-09-28 18:27:58 +00:00
|
|
|
static const WCHAR display_device_guid_propW[] = {
|
|
|
|
'_','_','w','i','n','e','_','d','i','s','p','l','a','y','_',
|
|
|
|
'd','e','v','i','c','e','_','g','u','i','d',0 };
|
|
|
|
static const WCHAR key_pathW[] = {
|
|
|
|
'S','y','s','t','e','m','\\',
|
|
|
|
'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
|
|
|
|
'C','o','n','t','r','o','l','\\',
|
|
|
|
'V','i','d','e','o','\\','{',0};
|
|
|
|
static const WCHAR displayW[] = {'}','\\','0','0','0','0',0};
|
|
|
|
static const WCHAR driverW[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0};
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2014-09-28 18:27:58 +00:00
|
|
|
HMODULE ret = 0;
|
|
|
|
HKEY hkey;
|
|
|
|
DWORD size;
|
|
|
|
WCHAR path[MAX_PATH];
|
2018-10-01 11:53:21 +00:00
|
|
|
WCHAR key[ARRAY_SIZE( key_pathW ) + ARRAY_SIZE( displayW ) + 40];
|
2014-09-28 18:27:58 +00:00
|
|
|
UINT guid_atom = HandleToULong( GetPropW( GetDesktopWindow(), display_device_guid_propW ));
|
|
|
|
|
|
|
|
if (!guid_atom) return 0;
|
|
|
|
memcpy( key, key_pathW, sizeof(key_pathW) );
|
2019-11-02 17:34:15 +00:00
|
|
|
if (!GlobalGetAtomNameW( guid_atom, key + lstrlenW(key), 40 )) return 0;
|
|
|
|
lstrcatW( key, displayW );
|
2014-09-28 18:27:58 +00:00
|
|
|
if (RegOpenKeyW( HKEY_LOCAL_MACHINE, key, &hkey )) return 0;
|
|
|
|
size = sizeof(path);
|
|
|
|
if (!RegQueryValueExW( hkey, driverW, NULL, NULL, (BYTE *)path, &size )) ret = LoadLibraryW( path );
|
|
|
|
RegCloseKey( hkey );
|
|
|
|
TRACE( "%s %p\n", debugstr_w(path), ret );
|
|
|
|
return ret;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2008-04-04 13:20:27 +00:00
|
|
|
/* ImmHkl loading and freeing */
|
|
|
|
#define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
|
|
|
|
static ImmHkl *IMM_GetImmHkl(HKL hkl)
|
|
|
|
{
|
|
|
|
ImmHkl *ptr;
|
|
|
|
WCHAR filename[MAX_PATH];
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
TRACE("Seeking ime for keyboard %p\n",hkl);
|
2008-04-04 13:20:27 +00:00
|
|
|
|
|
|
|
LIST_FOR_EACH_ENTRY(ptr, &ImmHklList, ImmHkl, entry)
|
|
|
|
{
|
|
|
|
if (ptr->hkl == hkl)
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
/* not found... create it */
|
|
|
|
|
|
|
|
ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ImmHkl));
|
|
|
|
|
|
|
|
ptr->hkl = hkl;
|
|
|
|
if (ImmGetIMEFileNameW(hkl, filename, MAX_PATH)) ptr->hIME = LoadLibraryW(filename);
|
2014-09-28 18:27:58 +00:00
|
|
|
if (!ptr->hIME) ptr->hIME = load_graphics_driver();
|
2008-04-04 13:20:27 +00:00
|
|
|
if (ptr->hIME)
|
|
|
|
{
|
|
|
|
LOAD_FUNCPTR(ImeInquire);
|
2010-03-07 11:27:14 +00:00
|
|
|
if (!ptr->pImeInquire || !ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL))
|
2008-04-04 13:20:27 +00:00
|
|
|
{
|
|
|
|
FreeLibrary(ptr->hIME);
|
|
|
|
ptr->hIME = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-03-07 11:27:14 +00:00
|
|
|
LOAD_FUNCPTR(ImeDestroy);
|
|
|
|
LOAD_FUNCPTR(ImeSelect);
|
|
|
|
if (!ptr->pImeSelect || !ptr->pImeDestroy)
|
|
|
|
{
|
|
|
|
FreeLibrary(ptr->hIME);
|
|
|
|
ptr->hIME = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LOAD_FUNCPTR(ImeConfigure);
|
|
|
|
LOAD_FUNCPTR(ImeEscape);
|
|
|
|
LOAD_FUNCPTR(ImeSetActiveContext);
|
|
|
|
LOAD_FUNCPTR(ImeToAsciiEx);
|
|
|
|
LOAD_FUNCPTR(NotifyIME);
|
|
|
|
LOAD_FUNCPTR(ImeRegisterWord);
|
|
|
|
LOAD_FUNCPTR(ImeUnregisterWord);
|
|
|
|
LOAD_FUNCPTR(ImeEnumRegisterWord);
|
|
|
|
LOAD_FUNCPTR(ImeSetCompositionString);
|
|
|
|
LOAD_FUNCPTR(ImeConversionList);
|
|
|
|
LOAD_FUNCPTR(ImeProcessKey);
|
|
|
|
LOAD_FUNCPTR(ImeGetRegisterWordStyle);
|
|
|
|
LOAD_FUNCPTR(ImeGetImeMenuItems);
|
|
|
|
/* make sure our classname is WCHAR */
|
|
|
|
if (!is_kbd_ime_unicode(ptr))
|
|
|
|
{
|
|
|
|
WCHAR bufW[17];
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, (LPSTR)ptr->imeClassName,
|
|
|
|
-1, bufW, 17);
|
|
|
|
lstrcpyW(ptr->imeClassName, bufW);
|
|
|
|
}
|
|
|
|
}
|
2008-04-04 13:20:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
list_add_head(&ImmHklList,&ptr->entry);
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
#undef LOAD_FUNCPTR
|
|
|
|
|
2014-09-28 18:27:58 +00:00
|
|
|
static InputContextData* get_imc_data(HIMC hIMC)
|
|
|
|
{
|
2021-08-16 06:33:51 +00:00
|
|
|
InputContextData *data = (InputContextData *)hIMC;
|
2014-09-28 18:27:58 +00:00
|
|
|
|
|
|
|
if (hIMC == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if(IsBadReadPtr(data, sizeof(InputContextData)) || data->magic != WINE_IMC_VALID_MAGIC)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2017-12-08 03:14:21 +00:00
|
|
|
static HIMC get_default_context( HWND hwnd )
|
|
|
|
{
|
2021-08-04 00:41:59 +00:00
|
|
|
FIXME("Don't use this function\n");
|
|
|
|
return FALSE;
|
2017-12-08 03:14:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL IMM_IsCrossThreadAccess(HWND hWnd, HIMC hIMC)
|
|
|
|
{
|
|
|
|
InputContextData *data;
|
|
|
|
|
|
|
|
if (hWnd)
|
|
|
|
{
|
|
|
|
DWORD thread = GetWindowThreadProcessId(hWnd, NULL);
|
|
|
|
if (thread != GetCurrentThreadId()) return TRUE;
|
|
|
|
}
|
|
|
|
data = get_imc_data(hIMC);
|
|
|
|
if (data && data->threadID != GetCurrentThreadId())
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmAssociateContext (IMM32.@)
|
|
|
|
*/
|
|
|
|
HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
|
|
|
|
{
|
2008-04-04 13:20:27 +00:00
|
|
|
HIMC old = NULL;
|
2014-09-28 18:27:58 +00:00
|
|
|
InputContextData *data = get_imc_data(hIMC);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2008-04-04 13:20:27 +00:00
|
|
|
TRACE("(%p, %p):\n", hWnd, hIMC);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2014-09-28 18:27:58 +00:00
|
|
|
if(hIMC && !data)
|
|
|
|
return NULL;
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
/*
|
|
|
|
* If already associated just return
|
|
|
|
*/
|
2008-04-04 13:20:27 +00:00
|
|
|
if (hIMC && data->IMC.hWnd == hWnd)
|
2006-07-06 11:22:04 +00:00
|
|
|
return hIMC;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2017-12-08 03:14:21 +00:00
|
|
|
if (hIMC && IMM_IsCrossThreadAccess(hWnd, hIMC))
|
|
|
|
return NULL;
|
|
|
|
|
2008-04-04 13:20:27 +00:00
|
|
|
if (hWnd)
|
|
|
|
{
|
2017-12-08 03:14:21 +00:00
|
|
|
HIMC defaultContext = get_default_context( hWnd );
|
2010-03-07 11:27:14 +00:00
|
|
|
old = RemovePropW(hWnd,szwWineIMCProperty);
|
2008-04-04 13:20:27 +00:00
|
|
|
|
|
|
|
if (old == NULL)
|
2017-12-08 03:14:21 +00:00
|
|
|
old = defaultContext;
|
2008-04-04 13:20:27 +00:00
|
|
|
else if (old == (HIMC)-1)
|
|
|
|
old = NULL;
|
|
|
|
|
2017-12-08 03:14:21 +00:00
|
|
|
if (hIMC != defaultContext)
|
2008-04-04 13:20:27 +00:00
|
|
|
{
|
|
|
|
if (hIMC == NULL) /* Meaning disable imm for that window*/
|
|
|
|
SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1);
|
|
|
|
else
|
2010-03-07 11:27:14 +00:00
|
|
|
SetPropW(hWnd,szwWineIMCProperty,hIMC);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (old)
|
|
|
|
{
|
2021-08-16 06:33:51 +00:00
|
|
|
InputContextData *old_data = (InputContextData *)old;
|
2010-03-07 11:27:14 +00:00
|
|
|
if (old_data->IMC.hWnd == hWnd)
|
|
|
|
old_data->IMC.hWnd = NULL;
|
2008-04-04 13:20:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hIMC)
|
|
|
|
return old;
|
|
|
|
|
2019-01-26 12:10:01 +00:00
|
|
|
if(GetActiveWindow() == data->IMC.hWnd)
|
|
|
|
{
|
|
|
|
SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
|
|
|
|
data->IMC.hWnd = hWnd;
|
|
|
|
SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
|
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2008-04-04 13:20:27 +00:00
|
|
|
return old;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Helper function for ImmAssociateContextEx
|
|
|
|
*/
|
|
|
|
static BOOL CALLBACK _ImmAssociateContextExEnumProc(HWND hwnd, LPARAM lParam)
|
|
|
|
{
|
|
|
|
HIMC hImc = (HIMC)lParam;
|
|
|
|
ImmAssociateContext(hwnd,hImc);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmAssociateContextEx (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
|
|
|
|
{
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
TRACE("(%p, %p, 0x%x):\n", hWnd, hIMC, dwFlags);
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2017-12-08 03:14:21 +00:00
|
|
|
if (!hWnd)
|
|
|
|
return FALSE;
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
|
|
|
|
switch (dwFlags)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
case 0:
|
|
|
|
ImmAssociateContext(hWnd,hIMC);
|
|
|
|
return TRUE;
|
|
|
|
case IACE_DEFAULT:
|
2017-12-08 03:14:21 +00:00
|
|
|
{
|
|
|
|
HIMC defaultContext = get_default_context( hWnd );
|
|
|
|
if (!defaultContext) return FALSE;
|
|
|
|
ImmAssociateContext(hWnd,defaultContext);
|
2010-03-07 11:27:14 +00:00
|
|
|
return TRUE;
|
2017-12-08 03:14:21 +00:00
|
|
|
}
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
case IACE_IGNORENOCONTEXT:
|
2010-03-07 11:27:14 +00:00
|
|
|
if (GetPropW(hWnd,szwWineIMCProperty))
|
|
|
|
ImmAssociateContext(hWnd,hIMC);
|
|
|
|
return TRUE;
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
case IACE_CHILDREN:
|
2010-03-07 11:27:14 +00:00
|
|
|
EnumChildWindows(hWnd,_ImmAssociateContextExEnumProc,(LPARAM)hIMC);
|
|
|
|
return TRUE;
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
default:
|
|
|
|
FIXME("Unknown dwFlags 0x%x\n",dwFlags);
|
2010-03-07 11:27:14 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmConfigureIMEA (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmConfigureIMEA(
|
|
|
|
HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
|
|
|
|
{
|
2010-03-07 11:27:14 +00:00
|
|
|
ImmHkl *immHkl = IMM_GetImmHkl(hKL);
|
|
|
|
|
|
|
|
TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
|
|
|
|
|
|
|
|
if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (immHkl->hIME && immHkl->pImeConfigure)
|
|
|
|
{
|
|
|
|
if (dwMode != IME_CONFIG_REGISTERWORD || !is_kbd_ime_unicode(immHkl))
|
|
|
|
return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
REGISTERWORDW rww;
|
|
|
|
REGISTERWORDA *rwa = lpData;
|
|
|
|
BOOL rc;
|
|
|
|
|
|
|
|
rww.lpReading = strdupAtoW(rwa->lpReading);
|
|
|
|
rww.lpWord = strdupAtoW(rwa->lpWord);
|
|
|
|
rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rww);
|
|
|
|
HeapFree(GetProcessHeap(),0,rww.lpReading);
|
|
|
|
HeapFree(GetProcessHeap(),0,rww.lpWord);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return FALSE;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmConfigureIMEW (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmConfigureIMEW(
|
|
|
|
HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
|
|
|
|
{
|
2010-03-07 11:27:14 +00:00
|
|
|
ImmHkl *immHkl = IMM_GetImmHkl(hKL);
|
|
|
|
|
|
|
|
TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
|
|
|
|
|
|
|
|
if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (immHkl->hIME && immHkl->pImeConfigure)
|
|
|
|
{
|
|
|
|
if (dwMode != IME_CONFIG_REGISTERWORD || is_kbd_ime_unicode(immHkl))
|
|
|
|
return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
REGISTERWORDW *rww = lpData;
|
|
|
|
REGISTERWORDA rwa;
|
|
|
|
BOOL rc;
|
|
|
|
|
|
|
|
rwa.lpReading = strdupWtoA(rww->lpReading);
|
|
|
|
rwa.lpWord = strdupWtoA(rww->lpWord);
|
|
|
|
rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rwa);
|
|
|
|
HeapFree(GetProcessHeap(),0,rwa.lpReading);
|
|
|
|
HeapFree(GetProcessHeap(),0,rwa.lpWord);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return FALSE;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmCreateContext (IMM32.@)
|
|
|
|
*/
|
|
|
|
HIMC WINAPI ImmCreateContext(void)
|
|
|
|
{
|
2021-08-04 00:41:59 +00:00
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
HIMC hIMC;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("()\n");
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
if (g_psi == NULL || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
|
|
|
|
return NULL;
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
pClientImc = Imm32HeapAlloc(HEAP_ZERO_MEMORY, sizeof(CLIENTIMC));
|
|
|
|
if (pClientImc == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2021-08-16 06:45:11 +00:00
|
|
|
hIMC = NtUserCreateInputContext(pClientImc);
|
2021-08-04 00:41:59 +00:00
|
|
|
if (hIMC == NULL)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-08-04 00:41:59 +00:00
|
|
|
HeapFree(g_hImm32Heap, 0, pClientImc);
|
|
|
|
return NULL;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
RtlInitializeCriticalSection(&pClientImc->cs);
|
2021-08-17 23:42:12 +00:00
|
|
|
|
|
|
|
// FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
|
|
|
|
pClientImc->unknown = NtUserGetThreadState(13);
|
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
return hIMC;
|
|
|
|
}
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
static VOID APIENTRY Imm32CleanupContextExtra(LPINPUTCONTEXT pIC)
|
|
|
|
{
|
|
|
|
FIXME("We have to do something do here");
|
|
|
|
}
|
2014-09-28 18:27:58 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
static PCLIENTIMC APIENTRY Imm32FindClientImc(HIMC hIMC)
|
|
|
|
{
|
|
|
|
// FIXME
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
BOOL APIENTRY Imm32CleanupContext(HIMC hIMC, HKL hKL, BOOL bKeep)
|
|
|
|
{
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
PCLIENTIMC pClientImc;
|
2014-09-28 18:27:58 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
if (g_psi == NULL || !(g_psi->dwSRVIFlags & SRVINFO_IMM32) || hIMC == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
FIXME("We have do something to do here\n");
|
|
|
|
pClientImc = Imm32FindClientImc(hIMC);
|
|
|
|
if (!pClientImc)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (pClientImc->hImc == NULL)
|
2008-04-04 13:20:27 +00:00
|
|
|
{
|
2021-08-04 00:41:59 +00:00
|
|
|
pClientImc->dwFlags |= CLIENTIMC_UNKNOWN1;
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
if (!bKeep)
|
2021-08-16 06:45:11 +00:00
|
|
|
return NtUserDestroyInputContext(hIMC);
|
2021-08-04 00:41:59 +00:00
|
|
|
return TRUE;
|
2008-04-04 13:20:27 +00:00
|
|
|
}
|
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
|
|
|
{
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
FIXME("We have do something to do here\n");
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
if (pClientImc->hKL == hKL)
|
|
|
|
{
|
|
|
|
pImeDpi = ImmLockImeDpi(hKL);
|
|
|
|
if (pImeDpi != NULL)
|
|
|
|
{
|
|
|
|
if (IS_IME_HKL(hKL))
|
|
|
|
{
|
|
|
|
pImeDpi->ImeSelect(hIMC, FALSE);
|
|
|
|
}
|
|
|
|
else if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
|
|
|
|
{
|
|
|
|
FIXME("We have do something to do here\n");
|
|
|
|
}
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
}
|
|
|
|
pClientImc->hKL = NULL;
|
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
ImmDestroyIMCC(pIC->hPrivate);
|
|
|
|
ImmDestroyIMCC(pIC->hMsgBuf);
|
|
|
|
ImmDestroyIMCC(pIC->hGuideLine);
|
|
|
|
ImmDestroyIMCC(pIC->hCandInfo);
|
|
|
|
ImmDestroyIMCC(pIC->hCompStr);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
Imm32CleanupContextExtra(pIC);
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
ImmUnlockIMC(hIMC);
|
2014-09-28 18:27:58 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
pClientImc->dwFlags |= CLIENTIMC_UNKNOWN1;
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
2014-09-28 18:27:58 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
if (!bKeep)
|
2021-08-16 06:45:11 +00:00
|
|
|
return NtUserDestroyInputContext(hIMC);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmDestroyContext (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmDestroyContext(HIMC hIMC)
|
|
|
|
{
|
2021-08-04 00:41:59 +00:00
|
|
|
HKL hKL;
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p)\n", hIMC);
|
2021-08-04 00:41:59 +00:00
|
|
|
|
|
|
|
if (g_psi == NULL || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
|
2010-03-07 11:27:14 +00:00
|
|
|
return FALSE;
|
2021-08-04 00:41:59 +00:00
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
if (Imm32IsCrossThreadAccess(hIMC))
|
2021-08-04 00:41:59 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
hKL = GetKeyboardLayout(0);
|
|
|
|
return Imm32CleanupContext(hIMC, hKL, FALSE);
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmDisableIME (IMM32.@)
|
|
|
|
*/
|
2021-07-28 23:21:33 +00:00
|
|
|
BOOL WINAPI ImmDisableIME(DWORD dwThreadId)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2021-07-28 23:21:33 +00:00
|
|
|
return NtUserDisableThreadIme(dwThreadId);
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
2021-08-16 06:31:39 +00:00
|
|
|
/*
|
|
|
|
* These functions absorb the difference between Ansi and Wide.
|
|
|
|
*/
|
|
|
|
typedef struct ENUM_WORD_A2W
|
|
|
|
{
|
|
|
|
REGISTERWORDENUMPROCW lpfnEnumProc;
|
|
|
|
LPVOID lpData;
|
|
|
|
UINT ret;
|
|
|
|
} ENUM_WORD_A2W, *LPENUM_WORD_A2W;
|
|
|
|
|
|
|
|
typedef struct ENUM_WORD_W2A
|
|
|
|
{
|
|
|
|
REGISTERWORDENUMPROCA lpfnEnumProc;
|
|
|
|
LPVOID lpData;
|
|
|
|
UINT ret;
|
|
|
|
} ENUM_WORD_W2A, *LPENUM_WORD_W2A;
|
|
|
|
|
|
|
|
static INT CALLBACK
|
|
|
|
Imm32EnumWordProcA2W(LPCSTR pszReadingA, DWORD dwStyle, LPCSTR pszRegisterA, LPVOID lpData)
|
|
|
|
{
|
|
|
|
INT ret = 0;
|
|
|
|
LPENUM_WORD_A2W lpEnumData = lpData;
|
|
|
|
LPWSTR pszReadingW = NULL, pszRegisterW = NULL;
|
|
|
|
|
|
|
|
if (pszReadingA)
|
|
|
|
{
|
|
|
|
pszReadingW = Imm32WideFromAnsi(pszReadingA);
|
|
|
|
if (pszReadingW == NULL)
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pszRegisterA)
|
|
|
|
{
|
|
|
|
pszRegisterW = Imm32WideFromAnsi(pszRegisterA);
|
|
|
|
if (pszRegisterW == NULL)
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = lpEnumData->lpfnEnumProc(pszReadingW, dwStyle, pszRegisterW, lpEnumData->lpData);
|
|
|
|
lpEnumData->ret = ret;
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
if (pszReadingW)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszReadingW);
|
|
|
|
if (pszRegisterW)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszRegisterW);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static INT CALLBACK
|
|
|
|
Imm32EnumWordProcW2A(LPCWSTR pszReadingW, DWORD dwStyle, LPCWSTR pszRegisterW, LPVOID lpData)
|
|
|
|
{
|
|
|
|
INT ret = 0;
|
|
|
|
LPENUM_WORD_W2A lpEnumData = lpData;
|
|
|
|
LPSTR pszReadingA = NULL, pszRegisterA = NULL;
|
|
|
|
|
|
|
|
if (pszReadingW)
|
|
|
|
{
|
|
|
|
pszReadingA = Imm32AnsiFromWide(pszReadingW);
|
|
|
|
if (pszReadingW == NULL)
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pszRegisterW)
|
|
|
|
{
|
|
|
|
pszRegisterA = Imm32AnsiFromWide(pszRegisterW);
|
|
|
|
if (pszRegisterA == NULL)
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = lpEnumData->lpfnEnumProc(pszReadingA, dwStyle, pszRegisterA, lpEnumData->lpData);
|
|
|
|
lpEnumData->ret = ret;
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
if (pszReadingA)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszReadingA);
|
|
|
|
if (pszRegisterA)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszRegisterA);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmEnumRegisterWordA (IMM32.@)
|
|
|
|
*/
|
|
|
|
UINT WINAPI ImmEnumRegisterWordA(
|
|
|
|
HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
|
|
|
|
LPCSTR lpszReading, DWORD dwStyle,
|
|
|
|
LPCSTR lpszRegister, LPVOID lpData)
|
|
|
|
{
|
2021-08-16 06:31:39 +00:00
|
|
|
UINT ret = 0;
|
|
|
|
LPWSTR pszReadingW = NULL, pszRegisterW = NULL;
|
|
|
|
ENUM_WORD_W2A EnumDataW2A;
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
|
|
|
|
TRACE("(%p, %p, %s, 0x%lX, %s, %p)", hKL, lpfnEnumProc, debugstr_a(lpszReading),
|
|
|
|
dwStyle, debugstr_a(lpszRegister), lpData);
|
|
|
|
|
|
|
|
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
|
|
|
if (!pImeDpi)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-08-16 06:31:39 +00:00
|
|
|
ret = pImeDpi->ImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
|
|
|
|
lpszRegister, lpData);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-16 06:31:39 +00:00
|
|
|
if (lpszReading)
|
|
|
|
{
|
|
|
|
pszReadingW = Imm32WideFromAnsi(lpszReading);
|
|
|
|
if (pszReadingW == NULL)
|
|
|
|
goto Quit;
|
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-16 06:31:39 +00:00
|
|
|
if (lpszRegister)
|
|
|
|
{
|
|
|
|
pszRegisterW = Imm32WideFromAnsi(lpszRegister);
|
|
|
|
if (pszRegisterW == NULL)
|
|
|
|
goto Quit;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2021-08-16 06:31:39 +00:00
|
|
|
|
|
|
|
EnumDataW2A.lpfnEnumProc = lpfnEnumProc;
|
|
|
|
EnumDataW2A.lpData = lpData;
|
|
|
|
EnumDataW2A.ret = 0;
|
|
|
|
pImeDpi->ImeEnumRegisterWord(Imm32EnumWordProcW2A, pszReadingW, dwStyle,
|
|
|
|
pszRegisterW, &EnumDataW2A);
|
|
|
|
ret = EnumDataW2A.ret;
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
if (pszReadingW)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszReadingW);
|
|
|
|
if (pszRegisterW)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszRegisterW);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmEnumRegisterWordW (IMM32.@)
|
|
|
|
*/
|
|
|
|
UINT WINAPI ImmEnumRegisterWordW(
|
|
|
|
HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
|
|
|
|
LPCWSTR lpszReading, DWORD dwStyle,
|
|
|
|
LPCWSTR lpszRegister, LPVOID lpData)
|
|
|
|
{
|
2021-08-16 06:31:39 +00:00
|
|
|
UINT ret = 0;
|
|
|
|
LPSTR pszReadingA = NULL, pszRegisterA = NULL;
|
|
|
|
ENUM_WORD_A2W EnumDataA2W;
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
|
|
|
|
TRACE("(%p, %p, %s, 0x%lX, %s, %p)", hKL, lpfnEnumProc, debugstr_w(lpszReading),
|
|
|
|
dwStyle, debugstr_w(lpszRegister), lpData);
|
|
|
|
|
|
|
|
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
|
|
|
if (!pImeDpi)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-08-16 06:31:39 +00:00
|
|
|
ret = pImeDpi->ImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
|
|
|
|
lpszRegister, lpData);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-16 06:31:39 +00:00
|
|
|
if (lpszReading)
|
|
|
|
{
|
|
|
|
pszReadingA = Imm32AnsiFromWide(lpszReading);
|
|
|
|
if (pszReadingA == NULL)
|
|
|
|
goto Quit;
|
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-16 06:31:39 +00:00
|
|
|
if (lpszRegister)
|
|
|
|
{
|
|
|
|
pszRegisterA = Imm32AnsiFromWide(lpszRegister);
|
|
|
|
if (pszRegisterA == NULL)
|
|
|
|
goto Quit;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2021-08-16 06:31:39 +00:00
|
|
|
|
|
|
|
EnumDataA2W.lpfnEnumProc = lpfnEnumProc;
|
|
|
|
EnumDataA2W.lpData = lpData;
|
|
|
|
EnumDataA2W.ret = 0;
|
|
|
|
pImeDpi->ImeEnumRegisterWord(Imm32EnumWordProcA2W, pszReadingA, dwStyle,
|
|
|
|
pszRegisterA, &EnumDataA2W);
|
|
|
|
ret = EnumDataA2W.ret;
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
if (pszReadingA)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszReadingA);
|
|
|
|
if (pszRegisterA)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszRegisterA);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline BOOL EscapeRequiresWA(UINT uEscape)
|
|
|
|
{
|
|
|
|
if (uEscape == IME_ESC_GET_EUDC_DICTIONARY ||
|
|
|
|
uEscape == IME_ESC_SET_EUDC_DICTIONARY ||
|
|
|
|
uEscape == IME_ESC_IME_NAME ||
|
|
|
|
uEscape == IME_ESC_GETHELPFILENAME)
|
|
|
|
return TRUE;
|
|
|
|
return FALSE;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmEscapeA (IMM32.@)
|
|
|
|
*/
|
|
|
|
LRESULT WINAPI ImmEscapeA(
|
|
|
|
HKL hKL, HIMC hIMC,
|
|
|
|
UINT uEscape, LPVOID lpData)
|
|
|
|
{
|
2010-03-07 11:27:14 +00:00
|
|
|
ImmHkl *immHkl = IMM_GetImmHkl(hKL);
|
|
|
|
TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
|
|
|
|
|
|
|
|
if (immHkl->hIME && immHkl->pImeEscape)
|
|
|
|
{
|
|
|
|
if (!EscapeRequiresWA(uEscape) || !is_kbd_ime_unicode(immHkl))
|
|
|
|
return immHkl->pImeEscape(hIMC,uEscape,lpData);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WCHAR buffer[81]; /* largest required buffer should be 80 */
|
|
|
|
LRESULT rc;
|
|
|
|
if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
|
|
|
|
{
|
|
|
|
MultiByteToWideChar(CP_ACP,0,lpData,-1,buffer,81);
|
|
|
|
rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
|
|
|
|
WideCharToMultiByte(CP_ACP,0,buffer,-1,lpData,80, NULL, NULL);
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return 0;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmEscapeW (IMM32.@)
|
|
|
|
*/
|
|
|
|
LRESULT WINAPI ImmEscapeW(
|
|
|
|
HKL hKL, HIMC hIMC,
|
|
|
|
UINT uEscape, LPVOID lpData)
|
|
|
|
{
|
2010-03-07 11:27:14 +00:00
|
|
|
ImmHkl *immHkl = IMM_GetImmHkl(hKL);
|
|
|
|
TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
|
|
|
|
|
|
|
|
if (immHkl->hIME && immHkl->pImeEscape)
|
|
|
|
{
|
|
|
|
if (!EscapeRequiresWA(uEscape) || is_kbd_ime_unicode(immHkl))
|
|
|
|
return immHkl->pImeEscape(hIMC,uEscape,lpData);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CHAR buffer[81]; /* largest required buffer should be 80 */
|
|
|
|
LRESULT rc;
|
|
|
|
if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
|
|
|
|
{
|
|
|
|
WideCharToMultiByte(CP_ACP,0,lpData,-1,buffer,81, NULL, NULL);
|
|
|
|
rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
|
|
|
|
MultiByteToWideChar(CP_ACP,0,buffer,-1,lpData,80);
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return 0;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
2021-07-11 00:48:15 +00:00
|
|
|
static PCLIENTIMC APIENTRY Imm32GetClientImcCache(void)
|
|
|
|
{
|
|
|
|
// FIXME: Do something properly here
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-07-31 06:45:07 +00:00
|
|
|
static DWORD APIENTRY Imm32AllocAndBuildHimcList(DWORD dwThreadId, HIMC **pphList)
|
|
|
|
{
|
|
|
|
#define INITIAL_COUNT 0x40
|
|
|
|
#define MAX_RETRY 10
|
|
|
|
NTSTATUS Status;
|
|
|
|
DWORD dwCount = INITIAL_COUNT, cRetry = 0;
|
|
|
|
HIMC *phNewList;
|
|
|
|
|
|
|
|
phNewList = Imm32HeapAlloc(0, dwCount * sizeof(HIMC));
|
|
|
|
if (phNewList == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2021-08-16 06:45:11 +00:00
|
|
|
Status = NtUserBuildHimcList(dwThreadId, dwCount, phNewList, &dwCount);
|
2021-07-31 06:45:07 +00:00
|
|
|
while (Status == STATUS_BUFFER_TOO_SMALL)
|
|
|
|
{
|
|
|
|
HeapFree(g_hImm32Heap, 0, phNewList);
|
|
|
|
if (cRetry++ >= MAX_RETRY)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
phNewList = Imm32HeapAlloc(0, dwCount * sizeof(HIMC));
|
|
|
|
if (phNewList == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2021-08-16 06:45:11 +00:00
|
|
|
Status = NtUserBuildHimcList(dwThreadId, dwCount, phNewList, &dwCount);
|
2021-07-31 06:45:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NT_ERROR(Status) || !dwCount)
|
|
|
|
{
|
|
|
|
HeapFree(g_hImm32Heap, 0, phNewList);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
*pphList = phNewList;
|
|
|
|
return dwCount;
|
|
|
|
#undef INITIAL_COUNT
|
|
|
|
#undef MAX_RETRY
|
|
|
|
}
|
|
|
|
|
2021-07-31 06:56:11 +00:00
|
|
|
static BOOL APIENTRY Imm32ImeNonImeToggle(HIMC hIMC, HKL hKL, HWND hWnd, LANGID LangID)
|
|
|
|
{
|
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
BOOL fOpen;
|
|
|
|
|
|
|
|
if (hWnd != NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!IS_IME_HKL(hKL) || LOWORD(hKL) != LangID)
|
|
|
|
{
|
|
|
|
FIXME("We have to do something here\n");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
fOpen = pIC->fOpen;
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
|
|
|
|
if (!fOpen)
|
|
|
|
{
|
|
|
|
ImmSetOpenStatus(hIMC, TRUE);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
FIXME("We have to do something here\n");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL APIENTRY Imm32CShapeToggle(HIMC hIMC, HKL hKL, HWND hWnd)
|
|
|
|
{
|
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
BOOL fOpen;
|
|
|
|
DWORD dwConversion, dwSentence;
|
|
|
|
|
|
|
|
if (hWnd == NULL || !IS_IME_HKL(hKL))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
fOpen = pIC->fOpen;
|
|
|
|
if (fOpen)
|
|
|
|
{
|
|
|
|
dwConversion = (pIC->fdwConversion ^ IME_CMODE_FULLSHAPE);
|
|
|
|
dwSentence = pIC->fdwSentence;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
|
|
|
|
if (fOpen)
|
|
|
|
ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
|
|
|
|
else
|
|
|
|
ImmSetOpenStatus(hIMC, TRUE);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL APIENTRY Imm32CSymbolToggle(HIMC hIMC, HKL hKL, HWND hWnd)
|
|
|
|
{
|
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
BOOL fOpen;
|
|
|
|
DWORD dwConversion, dwSentence;
|
|
|
|
|
|
|
|
if (hWnd == NULL || !IS_IME_HKL(hKL))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
fOpen = pIC->fOpen;
|
|
|
|
if (fOpen)
|
|
|
|
{
|
|
|
|
dwConversion = (pIC->fdwConversion ^ IME_CMODE_SYMBOL);
|
|
|
|
dwSentence = pIC->fdwSentence;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
|
|
|
|
if (fOpen)
|
|
|
|
ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
|
|
|
|
else
|
|
|
|
ImmSetOpenStatus(hIMC, TRUE);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL APIENTRY Imm32JCloseOpen(HIMC hIMC, HKL hKL, HWND hWnd)
|
|
|
|
{
|
|
|
|
BOOL fOpen;
|
|
|
|
|
|
|
|
if (ImmIsIME(hKL) && LOWORD(hKL) == LANGID_JAPANESE)
|
|
|
|
{
|
|
|
|
fOpen = ImmGetOpenStatus(hIMC);
|
|
|
|
ImmSetOpenStatus(hIMC, !fOpen);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
FIXME("We have to do something here\n");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL APIENTRY Imm32KShapeToggle(HIMC hIMC)
|
|
|
|
{
|
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
DWORD dwConversion, dwSentence;
|
|
|
|
|
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
dwConversion = (pIC->fdwConversion ^ IME_CMODE_FULLSHAPE);
|
|
|
|
dwSentence = pIC->fdwSentence;
|
|
|
|
ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
|
|
|
|
|
|
|
|
if (pIC->fdwConversion & (IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE))
|
|
|
|
ImmSetOpenStatus(hIMC, TRUE);
|
|
|
|
else
|
|
|
|
ImmSetOpenStatus(hIMC, FALSE);
|
|
|
|
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL APIENTRY Imm32KHanjaConvert(HIMC hIMC)
|
|
|
|
{
|
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
DWORD dwConversion, dwSentence;
|
|
|
|
|
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (!pIC)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
dwConversion = (pIC->fdwConversion ^ IME_CMODE_HANJACONVERT);
|
|
|
|
dwSentence = pIC->fdwSentence;
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
|
|
|
|
ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL APIENTRY Imm32KEnglish(HIMC hIMC)
|
|
|
|
{
|
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
DWORD dwConversion, dwSentence;
|
|
|
|
BOOL fOpen;
|
|
|
|
|
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
dwConversion = (pIC->fdwConversion ^ IME_CMODE_NATIVE);
|
|
|
|
dwSentence = pIC->fdwSentence;
|
|
|
|
ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
|
|
|
|
|
|
|
|
fOpen = ((pIC->fdwConversion & (IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE)) != 0);
|
|
|
|
ImmSetOpenStatus(hIMC, fOpen);
|
|
|
|
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL APIENTRY Imm32ProcessHotKey(HWND hWnd, HIMC hIMC, HKL hKL, DWORD dwHotKeyID)
|
|
|
|
{
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
BOOL ret;
|
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
if (hIMC && Imm32IsCrossThreadAccess(hIMC))
|
|
|
|
return FALSE;
|
2021-07-31 06:56:11 +00:00
|
|
|
|
|
|
|
switch (dwHotKeyID)
|
|
|
|
{
|
|
|
|
case IME_CHOTKEY_IME_NONIME_TOGGLE:
|
|
|
|
return Imm32ImeNonImeToggle(hIMC, hKL, hWnd, LANGID_CHINESE_SIMPLIFIED);
|
|
|
|
|
|
|
|
case IME_CHOTKEY_SHAPE_TOGGLE:
|
|
|
|
return Imm32CShapeToggle(hIMC, hKL, hWnd);
|
|
|
|
|
|
|
|
case IME_CHOTKEY_SYMBOL_TOGGLE:
|
|
|
|
return Imm32CSymbolToggle(hIMC, hKL, hWnd);
|
|
|
|
|
|
|
|
case IME_JHOTKEY_CLOSE_OPEN:
|
|
|
|
return Imm32JCloseOpen(hIMC, hKL, hWnd);
|
|
|
|
|
|
|
|
case IME_KHOTKEY_SHAPE_TOGGLE:
|
|
|
|
return Imm32KShapeToggle(hIMC);
|
|
|
|
|
|
|
|
case IME_KHOTKEY_HANJACONVERT:
|
|
|
|
return Imm32KHanjaConvert(hIMC);
|
|
|
|
|
|
|
|
case IME_KHOTKEY_ENGLISH:
|
|
|
|
return Imm32KEnglish(hIMC);
|
|
|
|
|
|
|
|
case IME_THOTKEY_IME_NONIME_TOGGLE:
|
|
|
|
return Imm32ImeNonImeToggle(hIMC, hKL, hWnd, LANGID_CHINESE_TRADITIONAL);
|
|
|
|
|
|
|
|
case IME_THOTKEY_SHAPE_TOGGLE:
|
|
|
|
return Imm32CShapeToggle(hIMC, hKL, hWnd);
|
|
|
|
|
|
|
|
case IME_THOTKEY_SYMBOL_TOGGLE:
|
|
|
|
return Imm32CSymbolToggle(hIMC, hKL, hWnd);
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dwHotKeyID < IME_HOTKEY_PRIVATE_FIRST || IME_HOTKEY_PRIVATE_LAST < dwHotKeyID)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
pImeDpi = ImmLockImeDpi(hKL);
|
|
|
|
if (pImeDpi == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
ret = (BOOL)pImeDpi->ImeEscape(hIMC, IME_ESC_PRIVATE_HOTKEY, &dwHotKeyID);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmLockClientImc (IMM32.@)
|
|
|
|
*/
|
2021-07-11 00:48:15 +00:00
|
|
|
PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc)
|
|
|
|
{
|
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p)\n", hImc);
|
2021-07-11 00:48:15 +00:00
|
|
|
|
|
|
|
if (hImc == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
pClientImc = Imm32GetClientImcCache();
|
|
|
|
if (!pClientImc)
|
|
|
|
{
|
|
|
|
pClientImc = Imm32HeapAlloc(HEAP_ZERO_MEMORY, sizeof(CLIENTIMC));
|
|
|
|
if (!pClientImc)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
RtlInitializeCriticalSection(&pClientImc->cs);
|
2021-08-17 23:42:12 +00:00
|
|
|
|
|
|
|
// FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
|
|
|
|
pClientImc->unknown = NtUserGetThreadState(13);
|
2021-07-11 00:48:15 +00:00
|
|
|
|
2021-08-16 06:45:11 +00:00
|
|
|
if (!NtUserUpdateInputContext(hImc, 0, pClientImc))
|
2021-07-11 00:48:15 +00:00
|
|
|
{
|
|
|
|
HeapFree(g_hImm32Heap, 0, pClientImc);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pClientImc->dwFlags |= CLIENTIMC_UNKNOWN2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-07-25 02:55:03 +00:00
|
|
|
if (pClientImc->dwFlags & CLIENTIMC_UNKNOWN1)
|
2021-07-11 00:48:15 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
InterlockedIncrement(&pClientImc->cLockObj);
|
|
|
|
return pClientImc;
|
|
|
|
}
|
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmUnlockClientImc (IMM32.@)
|
|
|
|
*/
|
2021-07-11 00:48:15 +00:00
|
|
|
VOID WINAPI ImmUnlockClientImc(PCLIENTIMC pClientImc)
|
|
|
|
{
|
|
|
|
LONG cLocks;
|
|
|
|
HIMC hImc;
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p)\n", pClientImc);
|
2021-07-11 00:48:15 +00:00
|
|
|
|
|
|
|
cLocks = InterlockedDecrement(&pClientImc->cLockObj);
|
2021-07-25 02:55:03 +00:00
|
|
|
if (cLocks != 0 || !(pClientImc->dwFlags & CLIENTIMC_UNKNOWN1))
|
2021-07-11 00:48:15 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
hImc = pClientImc->hImc;
|
|
|
|
if (hImc)
|
|
|
|
LocalFree(hImc);
|
|
|
|
|
|
|
|
RtlDeleteCriticalSection(&pClientImc->cs);
|
|
|
|
HeapFree(g_hImm32Heap, 0, pClientImc);
|
|
|
|
}
|
|
|
|
|
2021-08-23 21:50:39 +00:00
|
|
|
static HIMC APIENTRY Imm32GetContextEx(HWND hWnd, DWORD dwContextFlags)
|
|
|
|
{
|
|
|
|
HIMC hIMC;
|
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
PWND pWnd;
|
|
|
|
|
|
|
|
if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!hWnd)
|
|
|
|
{
|
|
|
|
// FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
|
|
|
|
hIMC = (HIMC)NtUserGetThreadState(4);
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
pWnd = ValidateHwndNoErr(hWnd);
|
|
|
|
if (!pWnd || Imm32IsCrossProcessAccess(hWnd))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
hIMC = pWnd->hImc;
|
|
|
|
if (!hIMC && (dwContextFlags & 1))
|
|
|
|
hIMC = (HIMC)NtUserQueryWindow(hWnd, QUERY_WINDOW_DEFAULT_ICONTEXT);
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
pClientImc = ImmLockClientImc(hIMC);
|
|
|
|
if (pClientImc == NULL)
|
|
|
|
return NULL;
|
|
|
|
if ((dwContextFlags & 2) && (pClientImc->dwFlags & CLIENTIMC_UNKNOWN3))
|
|
|
|
hIMC = NULL;
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return hIMC;
|
|
|
|
}
|
|
|
|
|
2021-07-11 00:48:15 +00:00
|
|
|
static DWORD APIENTRY
|
|
|
|
CandidateListWideToAnsi(const CANDIDATELIST *pWideCL, LPCANDIDATELIST pAnsiCL, DWORD dwBufLen,
|
|
|
|
UINT uCodePage)
|
|
|
|
{
|
|
|
|
BOOL bUsedDefault;
|
|
|
|
DWORD dwSize, dwIndex, cbGot, cbLeft;
|
|
|
|
const BYTE *pbWide;
|
|
|
|
LPBYTE pbAnsi;
|
|
|
|
LPDWORD pibOffsets;
|
|
|
|
|
|
|
|
/* calculate total ansi size */
|
|
|
|
if (pWideCL->dwCount > 0)
|
|
|
|
{
|
|
|
|
dwSize = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * sizeof(DWORD));
|
|
|
|
for (dwIndex = 0; dwIndex < pWideCL->dwCount; ++dwIndex)
|
|
|
|
{
|
|
|
|
pbWide = (const BYTE *)pWideCL + pWideCL->dwOffset[dwIndex];
|
|
|
|
cbGot = WideCharToMultiByte(uCodePage, 0, (LPCWSTR)pbWide, -1, NULL, 0,
|
|
|
|
NULL, &bUsedDefault);
|
|
|
|
dwSize += cbGot;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dwSize = sizeof(CANDIDATELIST);
|
|
|
|
}
|
|
|
|
|
|
|
|
dwSize = ROUNDUP4(dwSize);
|
|
|
|
if (dwBufLen == 0)
|
|
|
|
return dwSize;
|
|
|
|
if (dwBufLen < dwSize)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* store to ansi */
|
|
|
|
pAnsiCL->dwSize = dwBufLen;
|
|
|
|
pAnsiCL->dwStyle = pWideCL->dwStyle;
|
|
|
|
pAnsiCL->dwCount = pWideCL->dwCount;
|
|
|
|
pAnsiCL->dwSelection = pWideCL->dwSelection;
|
|
|
|
pAnsiCL->dwPageStart = pWideCL->dwPageStart;
|
|
|
|
pAnsiCL->dwPageSize = pWideCL->dwPageSize;
|
|
|
|
|
|
|
|
pibOffsets = pAnsiCL->dwOffset;
|
|
|
|
if (pWideCL->dwCount > 0)
|
|
|
|
{
|
|
|
|
pibOffsets[0] = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * sizeof(DWORD));
|
|
|
|
cbLeft = dwBufLen - pibOffsets[0];
|
|
|
|
|
|
|
|
for (dwIndex = 0; dwIndex < pWideCL->dwCount; ++dwIndex)
|
|
|
|
{
|
|
|
|
pbWide = (const BYTE *)pWideCL + pWideCL->dwOffset[dwIndex];
|
|
|
|
pbAnsi = (LPBYTE)pAnsiCL + pibOffsets[dwIndex];
|
|
|
|
|
|
|
|
/* convert to ansi */
|
|
|
|
cbGot = WideCharToMultiByte(uCodePage, 0, (LPCWSTR)pbWide, -1,
|
|
|
|
(LPSTR)pbAnsi, cbLeft, NULL, &bUsedDefault);
|
|
|
|
cbLeft -= cbGot;
|
|
|
|
|
|
|
|
if (dwIndex < pWideCL->dwCount - 1)
|
|
|
|
pibOffsets[dwIndex + 1] = pibOffsets[dwIndex] + cbGot;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pibOffsets[0] = sizeof(CANDIDATELIST);
|
|
|
|
}
|
|
|
|
|
|
|
|
return dwBufLen;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DWORD APIENTRY
|
|
|
|
CandidateListAnsiToWide(const CANDIDATELIST *pAnsiCL, LPCANDIDATELIST pWideCL, DWORD dwBufLen,
|
|
|
|
UINT uCodePage)
|
|
|
|
{
|
|
|
|
DWORD dwSize, dwIndex, cchGot, cbGot, cbLeft;
|
|
|
|
const BYTE *pbAnsi;
|
|
|
|
LPBYTE pbWide;
|
|
|
|
LPDWORD pibOffsets;
|
|
|
|
|
|
|
|
/* calculate total wide size */
|
|
|
|
if (pAnsiCL->dwCount > 0)
|
|
|
|
{
|
|
|
|
dwSize = sizeof(CANDIDATELIST) + ((pAnsiCL->dwCount - 1) * sizeof(DWORD));
|
|
|
|
for (dwIndex = 0; dwIndex < pAnsiCL->dwCount; ++dwIndex)
|
|
|
|
{
|
|
|
|
pbAnsi = (const BYTE *)pAnsiCL + pAnsiCL->dwOffset[dwIndex];
|
|
|
|
cchGot = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, (LPCSTR)pbAnsi, -1, NULL, 0);
|
|
|
|
dwSize += cchGot * sizeof(WCHAR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dwSize = sizeof(CANDIDATELIST);
|
|
|
|
}
|
|
|
|
|
|
|
|
dwSize = ROUNDUP4(dwSize);
|
|
|
|
if (dwBufLen == 0)
|
|
|
|
return dwSize;
|
|
|
|
if (dwBufLen < dwSize)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* store to wide */
|
|
|
|
pWideCL->dwSize = dwBufLen;
|
|
|
|
pWideCL->dwStyle = pAnsiCL->dwStyle;
|
|
|
|
pWideCL->dwCount = pAnsiCL->dwCount;
|
|
|
|
pWideCL->dwSelection = pAnsiCL->dwSelection;
|
|
|
|
pWideCL->dwPageStart = pAnsiCL->dwPageStart;
|
|
|
|
pWideCL->dwPageSize = pAnsiCL->dwPageSize;
|
|
|
|
|
|
|
|
pibOffsets = pWideCL->dwOffset;
|
|
|
|
if (pAnsiCL->dwCount > 0)
|
|
|
|
{
|
|
|
|
pibOffsets[0] = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * sizeof(DWORD));
|
|
|
|
cbLeft = dwBufLen - pibOffsets[0];
|
|
|
|
|
|
|
|
for (dwIndex = 0; dwIndex < pAnsiCL->dwCount; ++dwIndex)
|
|
|
|
{
|
|
|
|
pbAnsi = (const BYTE *)pAnsiCL + pAnsiCL->dwOffset[dwIndex];
|
|
|
|
pbWide = (LPBYTE)pWideCL + pibOffsets[dwIndex];
|
|
|
|
|
|
|
|
/* convert to wide */
|
|
|
|
cchGot = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, (LPCSTR)pbAnsi, -1,
|
|
|
|
(LPWSTR)pbWide, cbLeft / sizeof(WCHAR));
|
|
|
|
cbGot = cchGot * sizeof(WCHAR);
|
|
|
|
cbLeft -= cbGot;
|
|
|
|
|
|
|
|
if (dwIndex + 1 < pAnsiCL->dwCount)
|
|
|
|
pibOffsets[dwIndex + 1] = pibOffsets[dwIndex] + cbGot;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pibOffsets[0] = sizeof(CANDIDATELIST);
|
|
|
|
}
|
|
|
|
|
|
|
|
return dwBufLen;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DWORD APIENTRY
|
|
|
|
ImmGetCandidateListAW(HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen,
|
|
|
|
BOOL bAnsi)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2010-03-07 11:27:14 +00:00
|
|
|
DWORD ret = 0;
|
2021-07-11 00:48:15 +00:00
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
LPCANDIDATEINFO pCI;
|
|
|
|
LPCANDIDATELIST pCL;
|
|
|
|
DWORD dwSize;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-07-11 00:48:15 +00:00
|
|
|
pClientImc = ImmLockClientImc(hIMC);
|
|
|
|
if (!pClientImc)
|
|
|
|
return 0;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-07-11 00:48:15 +00:00
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
|
|
|
{
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return 0;
|
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-07-11 00:48:15 +00:00
|
|
|
pCI = ImmLockIMCC(pIC->hCandInfo);
|
|
|
|
if (pCI == NULL)
|
|
|
|
{
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return 0;
|
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-07-11 00:48:15 +00:00
|
|
|
if (pCI->dwSize < sizeof(CANDIDATEINFO) || pCI->dwCount <= dwIndex)
|
|
|
|
goto Quit;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-07-11 00:48:15 +00:00
|
|
|
/* get required size */
|
|
|
|
pCL = (LPCANDIDATELIST)((LPBYTE)pCI + pCI->dwOffset[dwIndex]);
|
|
|
|
if (bAnsi)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-07-11 00:48:15 +00:00
|
|
|
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
|
|
|
dwSize = CandidateListAnsiToWide(pCL, NULL, 0, CP_ACP);
|
|
|
|
else
|
|
|
|
dwSize = pCL->dwSize;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
|
|
|
else
|
2021-07-11 00:48:15 +00:00
|
|
|
{
|
|
|
|
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
|
|
|
dwSize = pCL->dwSize;
|
|
|
|
else
|
|
|
|
dwSize = CandidateListWideToAnsi(pCL, NULL, 0, CP_ACP);
|
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-07-11 00:48:15 +00:00
|
|
|
if (dwBufLen != 0 && dwSize != 0)
|
|
|
|
{
|
|
|
|
if (lpCandList == NULL || dwBufLen < dwSize)
|
|
|
|
goto Quit;
|
|
|
|
|
|
|
|
/* store */
|
|
|
|
if (bAnsi)
|
|
|
|
{
|
|
|
|
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
|
|
|
CandidateListAnsiToWide(pCL, lpCandList, dwSize, CP_ACP);
|
|
|
|
else
|
|
|
|
RtlCopyMemory(lpCandList, pCL, dwSize);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
|
|
|
RtlCopyMemory(lpCandList, pCL, dwSize);
|
|
|
|
else
|
|
|
|
CandidateListWideToAnsi(pCL, lpCandList, dwSize, CP_ACP);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = dwSize;
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
ImmUnlockIMCC(pIC->hCandInfo);
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
2010-03-07 11:27:14 +00:00
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
2021-07-13 11:17:17 +00:00
|
|
|
DWORD APIENTRY ImmGetCandidateListCountAW(HIMC hIMC, LPDWORD lpdwListCount, BOOL bAnsi)
|
|
|
|
{
|
|
|
|
DWORD ret = 0, cbGot, dwIndex;
|
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
const CANDIDATEINFO *pCI;
|
|
|
|
const BYTE *pb;
|
|
|
|
const CANDIDATELIST *pCL;
|
|
|
|
const DWORD *pdwOffsets;
|
|
|
|
|
|
|
|
if (lpdwListCount == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
*lpdwListCount = 0;
|
|
|
|
|
|
|
|
pClientImc = ImmLockClientImc(hIMC);
|
|
|
|
if (pClientImc == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
|
|
|
{
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
pCI = ImmLockIMCC(pIC->hCandInfo);
|
|
|
|
if (pCI == NULL)
|
|
|
|
{
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pCI->dwSize < sizeof(CANDIDATEINFO))
|
|
|
|
goto Quit;
|
|
|
|
|
|
|
|
*lpdwListCount = pCI->dwCount; /* the number of candidate lists */
|
|
|
|
|
|
|
|
/* calculate total size of candidate lists */
|
|
|
|
if (bAnsi)
|
|
|
|
{
|
|
|
|
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
|
|
|
{
|
|
|
|
ret = ROUNDUP4(pCI->dwPrivateSize);
|
|
|
|
pdwOffsets = pCI->dwOffset;
|
|
|
|
for (dwIndex = 0; dwIndex < pCI->dwCount; ++dwIndex)
|
|
|
|
{
|
|
|
|
pb = (const BYTE *)pCI + pdwOffsets[dwIndex];
|
|
|
|
pCL = (const CANDIDATELIST *)pb;
|
|
|
|
cbGot = CandidateListWideToAnsi(pCL, NULL, 0, CP_ACP);
|
|
|
|
ret += cbGot;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = pCI->dwSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
|
|
|
{
|
|
|
|
ret = pCI->dwSize;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = ROUNDUP4(pCI->dwPrivateSize);
|
|
|
|
pdwOffsets = pCI->dwOffset;
|
|
|
|
for (dwIndex = 0; dwIndex < pCI->dwCount; ++dwIndex)
|
|
|
|
{
|
|
|
|
pb = (const BYTE *)pCI + pdwOffsets[dwIndex];
|
|
|
|
pCL = (const CANDIDATELIST *)pb;
|
|
|
|
cbGot = CandidateListAnsiToWide(pCL, NULL, 0, CP_ACP);
|
|
|
|
ret += cbGot;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
ImmUnlockIMCC(pIC->hCandInfo);
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-07-11 00:48:15 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetCandidateListA (IMM32.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI ImmGetCandidateListA(
|
|
|
|
HIMC hIMC, DWORD dwIndex,
|
|
|
|
LPCANDIDATELIST lpCandList, DWORD dwBufLen)
|
|
|
|
{
|
|
|
|
return ImmGetCandidateListAW(hIMC, dwIndex, lpCandList, dwBufLen, TRUE);
|
|
|
|
}
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetCandidateListCountA (IMM32.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI ImmGetCandidateListCountA(
|
|
|
|
HIMC hIMC, LPDWORD lpdwListCount)
|
|
|
|
{
|
2021-07-13 11:17:17 +00:00
|
|
|
return ImmGetCandidateListCountAW(hIMC, lpdwListCount, TRUE);
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetCandidateListCountW (IMM32.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI ImmGetCandidateListCountW(
|
|
|
|
HIMC hIMC, LPDWORD lpdwListCount)
|
|
|
|
{
|
2021-07-13 11:17:17 +00:00
|
|
|
return ImmGetCandidateListCountAW(hIMC, lpdwListCount, FALSE);
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetCandidateListW (IMM32.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI ImmGetCandidateListW(
|
2010-03-07 11:27:14 +00:00
|
|
|
HIMC hIMC, DWORD dwIndex,
|
2005-12-12 20:59:55 +00:00
|
|
|
LPCANDIDATELIST lpCandList, DWORD dwBufLen)
|
|
|
|
{
|
2021-07-11 00:48:15 +00:00
|
|
|
return ImmGetCandidateListAW(hIMC, dwIndex, lpCandList, dwBufLen, FALSE);
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetCandidateWindow (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmGetCandidateWindow(
|
2010-03-07 11:27:14 +00:00
|
|
|
HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2021-07-15 18:04:00 +00:00
|
|
|
BOOL ret = FALSE;
|
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
LPCANDIDATEFORM pCF;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p, %lu, %p)\n", hIMC, dwIndex, lpCandidate);
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-07-15 18:04:00 +00:00
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
2014-09-28 18:27:58 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-07-15 18:04:00 +00:00
|
|
|
pCF = &pIC->cfCandForm[dwIndex];
|
|
|
|
if (pCF->dwIndex != IMM_INVALID_CANDFORM)
|
|
|
|
{
|
|
|
|
*lpCandidate = *pCF;
|
|
|
|
ret = TRUE;
|
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-07-15 18:04:00 +00:00
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
2021-07-13 11:51:28 +00:00
|
|
|
static VOID APIENTRY LogFontAnsiToWide(const LOGFONTA *plfA, LPLOGFONTW plfW)
|
|
|
|
{
|
|
|
|
size_t cch;
|
|
|
|
RtlCopyMemory(plfW, plfA, offsetof(LOGFONTA, lfFaceName));
|
|
|
|
StringCchLengthA(plfA->lfFaceName, _countof(plfA->lfFaceName), &cch);
|
|
|
|
cch = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, plfA->lfFaceName, (INT)cch,
|
|
|
|
plfW->lfFaceName, _countof(plfW->lfFaceName));
|
|
|
|
if (cch > _countof(plfW->lfFaceName) - 1)
|
|
|
|
cch = _countof(plfW->lfFaceName) - 1;
|
|
|
|
plfW->lfFaceName[cch] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VOID APIENTRY LogFontWideToAnsi(const LOGFONTW *plfW, LPLOGFONTA plfA)
|
|
|
|
{
|
|
|
|
size_t cch;
|
|
|
|
RtlCopyMemory(plfA, plfW, offsetof(LOGFONTW, lfFaceName));
|
|
|
|
StringCchLengthW(plfW->lfFaceName, _countof(plfW->lfFaceName), &cch);
|
|
|
|
cch = WideCharToMultiByte(CP_ACP, 0, plfW->lfFaceName, (INT)cch,
|
|
|
|
plfA->lfFaceName, _countof(plfA->lfFaceName), NULL, NULL);
|
|
|
|
if (cch > _countof(plfA->lfFaceName) - 1)
|
|
|
|
cch = _countof(plfA->lfFaceName) - 1;
|
|
|
|
plfA->lfFaceName[cch] = 0;
|
|
|
|
}
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetCompositionFontA (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
|
|
|
|
{
|
2021-07-13 11:51:28 +00:00
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
BOOL ret = FALSE, bWide;
|
|
|
|
LPINPUTCONTEXT pIC;
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p, %p)\n", hIMC, lplf);
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-07-13 11:51:28 +00:00
|
|
|
pClientImc = ImmLockClientImc(hIMC);
|
|
|
|
if (pClientImc == NULL)
|
2010-03-07 11:27:14 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-07-13 11:51:28 +00:00
|
|
|
bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
|
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (pIC->fdwInit & INIT_LOGFONT)
|
|
|
|
{
|
|
|
|
if (bWide)
|
|
|
|
LogFontWideToAnsi(&pIC->lfFont.W, lplf);
|
|
|
|
else
|
|
|
|
*lplf = pIC->lfFont.A;
|
|
|
|
|
|
|
|
ret = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetCompositionFontW (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
|
|
|
|
{
|
2021-07-13 11:51:28 +00:00
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
BOOL bWide;
|
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
BOOL ret = FALSE;
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p, %p)\n", hIMC, lplf);
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-07-13 11:51:28 +00:00
|
|
|
pClientImc = ImmLockClientImc(hIMC);
|
|
|
|
if (pClientImc == NULL)
|
2008-04-04 13:20:27 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-07-13 11:51:28 +00:00
|
|
|
bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-07-13 11:51:28 +00:00
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (pIC->fdwInit & INIT_LOGFONT)
|
|
|
|
{
|
|
|
|
if (bWide)
|
|
|
|
*lplf = pIC->lfFont.W;
|
|
|
|
else
|
|
|
|
LogFontAnsiToWide(&pIC->lfFont.A, lplf);
|
|
|
|
|
|
|
|
ret = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
|
|
|
|
/* Helpers for the GetCompositionString functions */
|
|
|
|
|
2019-11-02 17:34:15 +00:00
|
|
|
/* Source encoding is defined by context, source length is always given in respective characters. Destination buffer
|
|
|
|
length is always in bytes. */
|
|
|
|
static INT CopyCompStringIMEtoClient(const InputContextData *data, const void *src, INT src_len, void *dst,
|
|
|
|
INT dst_len, BOOL unicode)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2019-11-02 17:34:15 +00:00
|
|
|
int char_size = unicode ? sizeof(WCHAR) : sizeof(char);
|
|
|
|
INT ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2019-11-02 17:34:15 +00:00
|
|
|
if (is_himc_ime_unicode(data) ^ unicode)
|
|
|
|
{
|
|
|
|
if (unicode)
|
|
|
|
ret = MultiByteToWideChar(CP_ACP, 0, src, src_len, dst, dst_len / sizeof(WCHAR));
|
|
|
|
else
|
|
|
|
ret = WideCharToMultiByte(CP_ACP, 0, src, src_len, dst, dst_len, NULL, NULL);
|
|
|
|
ret *= char_size;
|
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
else
|
|
|
|
{
|
2019-11-02 17:34:15 +00:00
|
|
|
if (dst_len)
|
|
|
|
{
|
|
|
|
ret = min(src_len * char_size, dst_len);
|
|
|
|
memcpy(dst, src, ret);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = src_len * char_size;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2019-11-02 17:34:15 +00:00
|
|
|
return ret;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2019-11-02 17:34:15 +00:00
|
|
|
/* Composition string encoding is defined by context, returned attributes correspond to string, converted according to
|
|
|
|
passed mode. String length is in characters, attributes are in byte arrays. */
|
|
|
|
static INT CopyCompAttrIMEtoClient(const InputContextData *data, const BYTE *src, INT src_len, const void *comp_string,
|
|
|
|
INT str_len, BYTE *dst, INT dst_len, BOOL unicode)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2019-11-02 17:34:15 +00:00
|
|
|
union
|
|
|
|
{
|
|
|
|
const void *str;
|
|
|
|
const WCHAR *strW;
|
|
|
|
const char *strA;
|
|
|
|
} string;
|
2010-03-07 11:27:14 +00:00
|
|
|
INT rc;
|
2007-09-14 08:03:04 +00:00
|
|
|
|
2019-11-02 17:34:15 +00:00
|
|
|
string.str = comp_string;
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
if (is_himc_ime_unicode(data) && !unicode)
|
|
|
|
{
|
2019-11-02 17:34:15 +00:00
|
|
|
rc = WideCharToMultiByte(CP_ACP, 0, string.strW, str_len, NULL, 0, NULL, NULL);
|
|
|
|
if (dst_len)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
|
|
|
int i, j = 0, k = 0;
|
2007-09-14 08:03:04 +00:00
|
|
|
|
2019-11-02 17:34:15 +00:00
|
|
|
if (rc < dst_len)
|
|
|
|
dst_len = rc;
|
|
|
|
for (i = 0; i < str_len; ++i)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
|
|
|
int len;
|
|
|
|
|
2019-11-02 17:34:15 +00:00
|
|
|
len = WideCharToMultiByte(CP_ACP, 0, string.strW + i, 1, NULL, 0, NULL, NULL);
|
2010-03-07 11:27:14 +00:00
|
|
|
for (; len > 0; --len)
|
|
|
|
{
|
|
|
|
dst[j++] = src[k];
|
|
|
|
|
2019-11-02 17:34:15 +00:00
|
|
|
if (j >= dst_len)
|
2010-03-07 11:27:14 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
++k;
|
|
|
|
}
|
|
|
|
end:
|
|
|
|
rc = j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!is_himc_ime_unicode(data) && unicode)
|
|
|
|
{
|
2019-11-02 17:34:15 +00:00
|
|
|
rc = MultiByteToWideChar(CP_ACP, 0, string.strA, str_len, NULL, 0);
|
|
|
|
if (dst_len)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
|
|
|
int i, j = 0;
|
|
|
|
|
2019-11-02 17:34:15 +00:00
|
|
|
if (rc < dst_len)
|
|
|
|
dst_len = rc;
|
|
|
|
for (i = 0; i < str_len; ++i)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2019-11-02 17:34:15 +00:00
|
|
|
if (IsDBCSLeadByte(string.strA[i]))
|
2010-03-07 11:27:14 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
dst[j++] = src[i];
|
|
|
|
|
2019-11-02 17:34:15 +00:00
|
|
|
if (j >= dst_len)
|
2010-03-07 11:27:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
rc = j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2019-11-02 17:34:15 +00:00
|
|
|
memcpy(dst, src, min(src_len, dst_len));
|
|
|
|
rc = src_len;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
return rc;
|
|
|
|
}
|
2007-09-14 08:03:04 +00:00
|
|
|
|
2011-12-15 00:40:35 +00:00
|
|
|
static INT CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource,
|
2010-03-07 11:27:14 +00:00
|
|
|
LPBYTE target, INT tlen, BOOL unicode )
|
|
|
|
{
|
|
|
|
INT rc;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
if (is_himc_ime_unicode(data) && !unicode)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2010-03-07 11:27:14 +00:00
|
|
|
if (tlen)
|
|
|
|
{
|
|
|
|
int i;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
if (slen < tlen)
|
|
|
|
tlen = slen;
|
|
|
|
tlen /= sizeof (DWORD);
|
|
|
|
for (i = 0; i < tlen; ++i)
|
|
|
|
{
|
|
|
|
((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource,
|
|
|
|
((DWORD *)source)[i],
|
|
|
|
NULL, 0,
|
|
|
|
NULL, NULL);
|
|
|
|
}
|
|
|
|
rc = sizeof (DWORD) * i;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = slen;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
else if (!is_himc_ime_unicode(data) && unicode)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2010-03-07 11:27:14 +00:00
|
|
|
if (tlen)
|
|
|
|
{
|
|
|
|
int i;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
if (slen < tlen)
|
|
|
|
tlen = slen;
|
|
|
|
tlen /= sizeof (DWORD);
|
|
|
|
for (i = 0; i < tlen; ++i)
|
|
|
|
{
|
|
|
|
((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource,
|
|
|
|
((DWORD *)source)[i],
|
|
|
|
NULL, 0);
|
|
|
|
}
|
|
|
|
rc = sizeof (DWORD) * i;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = slen;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
else
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2010-03-07 11:27:14 +00:00
|
|
|
memcpy( target, source, min(slen,tlen));
|
|
|
|
rc = slen;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
2007-03-14 14:34:47 +00:00
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static INT CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE ssource, BOOL unicode)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (is_himc_ime_unicode(data) && !unicode)
|
2007-09-14 08:03:04 +00:00
|
|
|
{
|
2010-03-07 11:27:14 +00:00
|
|
|
rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, NULL, NULL);
|
2007-09-14 08:03:04 +00:00
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
else if (!is_himc_ime_unicode(data) && unicode)
|
2007-09-14 08:03:04 +00:00
|
|
|
{
|
2010-03-07 11:27:14 +00:00
|
|
|
rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0);
|
2007-03-14 14:34:47 +00:00
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
else
|
2010-03-07 11:27:14 +00:00
|
|
|
rc = offset;
|
2007-09-14 08:03:04 +00:00
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf,
|
|
|
|
DWORD dwBufLen, BOOL unicode)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2006-04-16 17:04:45 +00:00
|
|
|
LONG rc = 0;
|
2014-09-28 18:27:58 +00:00
|
|
|
InputContextData *data = get_imc_data(hIMC);
|
2007-09-14 08:03:04 +00:00
|
|
|
LPCOMPOSITIONSTRING compstr;
|
|
|
|
LPBYTE compdata;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2006-11-26 21:05:00 +00:00
|
|
|
TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
|
|
|
if (!data)
|
|
|
|
return FALSE;
|
|
|
|
|
2007-09-14 08:03:04 +00:00
|
|
|
if (!data->IMC.hCompStr)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
compdata = ImmLockIMCC(data->IMC.hCompStr);
|
|
|
|
compstr = (LPCOMPOSITIONSTRING)compdata;
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
switch (dwIndex)
|
|
|
|
{
|
|
|
|
case GCS_RESULTSTR:
|
|
|
|
TRACE("GCS_RESULTSTR\n");
|
|
|
|
rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_COMPSTR:
|
|
|
|
TRACE("GCS_COMPSTR\n");
|
|
|
|
rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_COMPATTR:
|
|
|
|
TRACE("GCS_COMPATTR\n");
|
|
|
|
rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompAttrOffset, compstr->dwCompAttrLen,
|
|
|
|
compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
|
|
|
|
lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_COMPCLAUSE:
|
|
|
|
TRACE("GCS_COMPCLAUSE\n");
|
|
|
|
rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompClauseOffset,compstr->dwCompClauseLen,
|
2011-12-15 00:40:35 +00:00
|
|
|
compdata + compstr->dwCompStrOffset,
|
2010-03-07 11:27:14 +00:00
|
|
|
lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_RESULTCLAUSE:
|
|
|
|
TRACE("GCS_RESULTCLAUSE\n");
|
|
|
|
rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen,
|
2011-12-15 00:40:35 +00:00
|
|
|
compdata + compstr->dwResultStrOffset,
|
2010-03-07 11:27:14 +00:00
|
|
|
lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_RESULTREADSTR:
|
|
|
|
TRACE("GCS_RESULTREADSTR\n");
|
|
|
|
rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultReadStrOffset, compstr->dwResultReadStrLen, lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_RESULTREADCLAUSE:
|
|
|
|
TRACE("GCS_RESULTREADCLAUSE\n");
|
|
|
|
rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultReadClauseOffset,compstr->dwResultReadClauseLen,
|
2011-12-15 00:40:35 +00:00
|
|
|
compdata + compstr->dwResultStrOffset,
|
2010-03-07 11:27:14 +00:00
|
|
|
lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_COMPREADSTR:
|
|
|
|
TRACE("GCS_COMPREADSTR\n");
|
|
|
|
rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_COMPREADATTR:
|
|
|
|
TRACE("GCS_COMPREADATTR\n");
|
|
|
|
rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompReadAttrOffset, compstr->dwCompReadAttrLen,
|
|
|
|
compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen,
|
|
|
|
lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_COMPREADCLAUSE:
|
|
|
|
TRACE("GCS_COMPREADCLAUSE\n");
|
|
|
|
rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompReadClauseOffset,compstr->dwCompReadClauseLen,
|
2011-12-15 00:40:35 +00:00
|
|
|
compdata + compstr->dwCompStrOffset,
|
2010-03-07 11:27:14 +00:00
|
|
|
lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_CURSORPOS:
|
|
|
|
TRACE("GCS_CURSORPOS\n");
|
|
|
|
rc = CopyCompOffsetIMEtoClient(data, compstr->dwCursorPos, compdata + compstr->dwCompStrOffset, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_DELTASTART:
|
2007-09-14 08:03:04 +00:00
|
|
|
TRACE("GCS_DELTASTART\n");
|
2010-03-07 11:27:14 +00:00
|
|
|
rc = CopyCompOffsetIMEtoClient(data, compstr->dwDeltaStart, compdata + compstr->dwCompStrOffset, unicode);
|
|
|
|
break;
|
|
|
|
default:
|
2006-11-26 21:05:00 +00:00
|
|
|
FIXME("Unhandled index 0x%x\n",dwIndex);
|
2010-03-07 11:27:14 +00:00
|
|
|
break;
|
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2007-09-14 08:03:04 +00:00
|
|
|
ImmUnlockIMCC(data->IMC.hCompStr);
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetCompositionStringA (IMM32.@)
|
|
|
|
*/
|
|
|
|
LONG WINAPI ImmGetCompositionStringA(
|
|
|
|
HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
|
|
|
|
{
|
|
|
|
return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetCompositionStringW (IMM32.@)
|
|
|
|
*/
|
|
|
|
LONG WINAPI ImmGetCompositionStringW(
|
|
|
|
HIMC hIMC, DWORD dwIndex,
|
|
|
|
LPVOID lpBuf, DWORD dwBufLen)
|
|
|
|
{
|
|
|
|
return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
|
|
|
|
}
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetCompositionWindow (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
|
|
|
|
{
|
2021-07-13 12:13:39 +00:00
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
BOOL ret = FALSE;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p, %p)\n", hIMC, lpCompForm);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-07-13 12:13:39 +00:00
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (!pIC)
|
2005-12-12 20:59:55 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-07-13 12:13:39 +00:00
|
|
|
if (pIC->fdwInit & INIT_COMPFORM)
|
|
|
|
{
|
|
|
|
*lpCompForm = pIC->cfCompForm;
|
|
|
|
ret = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetContext (IMM32.@)
|
|
|
|
*/
|
|
|
|
HIMC WINAPI ImmGetContext(HWND hWnd)
|
|
|
|
{
|
2021-08-23 21:50:39 +00:00
|
|
|
TRACE("(%p)\n", hWnd);
|
|
|
|
if (hWnd == NULL)
|
2011-12-15 00:40:35 +00:00
|
|
|
return NULL;
|
2021-08-23 21:50:39 +00:00
|
|
|
return Imm32GetContextEx(hWnd, 2);
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetConversionListA (IMM32.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI ImmGetConversionListA(
|
|
|
|
HKL hKL, HIMC hIMC,
|
|
|
|
LPCSTR pSrc, LPCANDIDATELIST lpDst,
|
|
|
|
DWORD dwBufLen, UINT uFlag)
|
|
|
|
{
|
2021-08-12 03:32:02 +00:00
|
|
|
DWORD ret = 0;
|
|
|
|
UINT cb;
|
|
|
|
LPWSTR pszSrcW = NULL;
|
|
|
|
LPCANDIDATELIST pCL = NULL;
|
|
|
|
PIMEDPI pImeDpi;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-12 03:32:02 +00:00
|
|
|
TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL, hIMC, debugstr_a(pSrc),
|
|
|
|
lpDst, dwBufLen, uFlag);
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-12 03:32:02 +00:00
|
|
|
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
|
|
|
if (pImeDpi == NULL)
|
2010-03-07 11:27:14 +00:00
|
|
|
return 0;
|
2021-08-12 03:32:02 +00:00
|
|
|
|
|
|
|
if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))
|
|
|
|
{
|
|
|
|
ret = pImeDpi->ImeConversionList(hIMC, pSrc, lpDst, dwBufLen, uFlag);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pSrc)
|
|
|
|
{
|
2021-08-14 01:38:06 +00:00
|
|
|
pszSrcW = Imm32WideFromAnsi(pSrc);
|
2021-08-12 03:32:02 +00:00
|
|
|
if (pszSrcW == NULL)
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
cb = pImeDpi->ImeConversionList(hIMC, pszSrcW, NULL, 0, uFlag);
|
|
|
|
if (cb == 0)
|
|
|
|
goto Quit;
|
|
|
|
|
|
|
|
pCL = Imm32HeapAlloc(0, cb);
|
|
|
|
if (pCL == NULL)
|
|
|
|
goto Quit;
|
|
|
|
|
|
|
|
cb = pImeDpi->ImeConversionList(hIMC, pszSrcW, pCL, cb, uFlag);
|
|
|
|
if (cb == 0)
|
|
|
|
goto Quit;
|
|
|
|
|
|
|
|
ret = CandidateListWideToAnsi(pCL, lpDst, dwBufLen, CP_ACP);
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
if (pszSrcW)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszSrcW);
|
|
|
|
if (pCL)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pCL);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetConversionListW (IMM32.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI ImmGetConversionListW(
|
|
|
|
HKL hKL, HIMC hIMC,
|
|
|
|
LPCWSTR pSrc, LPCANDIDATELIST lpDst,
|
|
|
|
DWORD dwBufLen, UINT uFlag)
|
|
|
|
{
|
2021-08-12 03:32:02 +00:00
|
|
|
DWORD ret = 0;
|
2021-08-14 01:38:06 +00:00
|
|
|
INT cb;
|
2021-08-12 03:32:02 +00:00
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
LPCANDIDATELIST pCL = NULL;
|
|
|
|
LPSTR pszSrcA = NULL;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-12 03:32:02 +00:00
|
|
|
TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL, hIMC, debugstr_w(pSrc),
|
|
|
|
lpDst, dwBufLen, uFlag);
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-12 03:32:02 +00:00
|
|
|
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
|
|
|
if (!pImeDpi)
|
2010-03-07 11:27:14 +00:00
|
|
|
return 0;
|
2021-08-12 03:32:02 +00:00
|
|
|
|
|
|
|
if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
|
|
|
|
{
|
|
|
|
ret = pImeDpi->ImeConversionList(hIMC, pSrc, lpDst, dwBufLen, uFlag);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pSrc)
|
|
|
|
{
|
2021-08-14 01:38:06 +00:00
|
|
|
pszSrcA = Imm32AnsiFromWide(pSrc);
|
2021-08-12 03:32:02 +00:00
|
|
|
if (pszSrcA == NULL)
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
cb = pImeDpi->ImeConversionList(hIMC, pszSrcA, NULL, 0, uFlag);
|
|
|
|
if (cb == 0)
|
|
|
|
goto Quit;
|
|
|
|
|
|
|
|
pCL = Imm32HeapAlloc(0, cb);
|
|
|
|
if (!pCL)
|
|
|
|
goto Quit;
|
|
|
|
|
|
|
|
cb = pImeDpi->ImeConversionList(hIMC, pszSrcA, pCL, cb, uFlag);
|
|
|
|
if (!cb)
|
|
|
|
goto Quit;
|
|
|
|
|
|
|
|
ret = CandidateListAnsiToWide(pCL, lpDst, dwBufLen, CP_ACP);
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
if (pszSrcA)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszSrcA);
|
|
|
|
if (pCL)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pCL);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetConversionStatus (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmGetConversionStatus(
|
|
|
|
HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
|
|
|
|
{
|
2021-07-05 12:20:20 +00:00
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p %p %p)\n", hIMC, lpfdwConversion, lpfdwSentence);
|
2021-07-05 12:20:20 +00:00
|
|
|
|
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (!pIC)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (lpfdwConversion)
|
|
|
|
*lpfdwConversion = pIC->fdwConversion;
|
|
|
|
if (lpfdwSentence)
|
|
|
|
*lpfdwSentence = pIC->fdwSentence;
|
|
|
|
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
return TRUE;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetDefaultIMEWnd (IMM32.@)
|
|
|
|
*/
|
|
|
|
HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
|
|
|
|
{
|
2021-08-04 00:41:59 +00:00
|
|
|
if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
|
2017-12-08 03:14:21 +00:00
|
|
|
return NULL;
|
2021-07-15 12:59:53 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
// FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
|
2021-07-15 12:59:53 +00:00
|
|
|
if (hWnd == NULL)
|
2021-08-17 23:42:12 +00:00
|
|
|
return (HWND)NtUserGetThreadState(3);
|
2021-07-15 12:59:53 +00:00
|
|
|
|
2021-08-16 06:45:11 +00:00
|
|
|
return (HWND)NtUserQueryWindow(hWnd, QUERY_WINDOW_DEFAULT_IME);
|
2021-07-15 12:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* CtfImmIsCiceroEnabled (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI CtfImmIsCiceroEnabled(VOID)
|
|
|
|
{
|
2021-08-04 00:41:59 +00:00
|
|
|
return (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED));
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetDescriptionA (IMM32.@)
|
|
|
|
*/
|
|
|
|
UINT WINAPI ImmGetDescriptionA(
|
|
|
|
HKL hKL, LPSTR lpszDescription, UINT uBufLen)
|
|
|
|
{
|
2021-07-03 23:18:15 +00:00
|
|
|
IMEINFOEX info;
|
|
|
|
size_t cch;
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p,%p,%d)\n", hKL, lpszDescription, uBufLen);
|
2021-07-03 23:18:15 +00:00
|
|
|
|
2021-07-11 00:48:15 +00:00
|
|
|
if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || !IS_IME_HKL(hKL))
|
2021-07-03 23:18:15 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
StringCchLengthW(info.wszImeDescription, _countof(info.wszImeDescription), &cch);
|
|
|
|
cch = WideCharToMultiByte(CP_ACP, 0, info.wszImeDescription, (INT)cch,
|
|
|
|
lpszDescription, uBufLen, NULL, NULL);
|
|
|
|
if (uBufLen)
|
|
|
|
lpszDescription[cch] = 0;
|
2021-08-23 21:50:39 +00:00
|
|
|
return (UINT)cch;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetDescriptionW (IMM32.@)
|
|
|
|
*/
|
|
|
|
UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
|
|
|
|
{
|
2021-07-03 23:18:15 +00:00
|
|
|
IMEINFOEX info;
|
|
|
|
size_t cch;
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p, %p, %d)\n", hKL, lpszDescription, uBufLen);
|
2021-07-03 23:18:15 +00:00
|
|
|
|
2021-07-11 00:48:15 +00:00
|
|
|
if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || !IS_IME_HKL(hKL))
|
2021-07-03 23:18:15 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (uBufLen != 0)
|
|
|
|
StringCchCopyW(lpszDescription, uBufLen, info.wszImeDescription);
|
|
|
|
|
|
|
|
StringCchLengthW(info.wszImeDescription, _countof(info.wszImeDescription), &cch);
|
|
|
|
return (UINT)cch;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
2021-08-05 12:43:21 +00:00
|
|
|
static DWORD APIENTRY
|
|
|
|
ImmGetGuideLineAW(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen, BOOL bAnsi)
|
|
|
|
{
|
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
LPGUIDELINE pGuideLine;
|
|
|
|
DWORD cb, ret = 0;
|
|
|
|
LPVOID pvStr, pvPrivate;
|
|
|
|
BOOL bUsedDefault;
|
|
|
|
|
|
|
|
pClientImc = ImmLockClientImc(hIMC);
|
|
|
|
if (!pClientImc)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (!pIC)
|
|
|
|
{
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
pGuideLine = ImmLockIMCC(pIC->hGuideLine);
|
|
|
|
if (!pGuideLine)
|
|
|
|
{
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dwIndex == GGL_LEVEL)
|
|
|
|
{
|
|
|
|
ret = pGuideLine->dwLevel;
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dwIndex == GGL_INDEX)
|
|
|
|
{
|
|
|
|
ret = pGuideLine->dwIndex;
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dwIndex == GGL_STRING)
|
|
|
|
{
|
|
|
|
pvStr = (LPBYTE)pGuideLine + pGuideLine->dwStrOffset;
|
|
|
|
|
|
|
|
/* get size */
|
|
|
|
if (bAnsi)
|
|
|
|
{
|
|
|
|
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
|
|
|
{
|
|
|
|
cb = WideCharToMultiByte(CP_ACP, 0, pvStr, pGuideLine->dwStrLen,
|
|
|
|
NULL, 0, NULL, &bUsedDefault);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cb = pGuideLine->dwStrLen * sizeof(CHAR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
|
|
|
{
|
|
|
|
cb = pGuideLine->dwStrLen * sizeof(WCHAR);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cb = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pvStr, pGuideLine->dwStrLen,
|
|
|
|
NULL, 0) * sizeof(WCHAR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dwBufLen == 0 || cb == 0 || lpBuf == NULL || dwBufLen < cb)
|
|
|
|
{
|
|
|
|
ret = cb;
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* store to buffer */
|
|
|
|
if (bAnsi)
|
|
|
|
{
|
|
|
|
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
|
|
|
{
|
|
|
|
ret = WideCharToMultiByte(CP_ACP, 0, pvStr, pGuideLine->dwStrLen,
|
|
|
|
lpBuf, dwBufLen, NULL, &bUsedDefault);
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!(pClientImc->dwFlags & CLIENTIMC_WIDE))
|
|
|
|
{
|
|
|
|
ret = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pvStr, pGuideLine->dwStrLen,
|
|
|
|
lpBuf, dwBufLen) * sizeof(WCHAR);
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlCopyMemory(lpBuf, pvStr, cb);
|
|
|
|
ret = cb;
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dwIndex == GGL_PRIVATE)
|
|
|
|
{
|
|
|
|
pvPrivate = (LPBYTE)pGuideLine + pGuideLine->dwPrivateOffset;
|
|
|
|
|
|
|
|
/* get size */
|
|
|
|
if (bAnsi)
|
|
|
|
{
|
|
|
|
if ((pClientImc->dwFlags & CLIENTIMC_WIDE) &&
|
|
|
|
pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
|
|
|
|
{
|
|
|
|
cb = CandidateListWideToAnsi(pvPrivate, NULL, 0, CP_ACP);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cb = pGuideLine->dwPrivateSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!(pClientImc->dwFlags & CLIENTIMC_WIDE) &&
|
|
|
|
pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
|
|
|
|
{
|
|
|
|
cb = CandidateListAnsiToWide(pvPrivate, NULL, 0, CP_ACP);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cb = pGuideLine->dwPrivateSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dwBufLen == 0 || cb == 0 || lpBuf == NULL || dwBufLen < cb)
|
|
|
|
{
|
|
|
|
ret = cb;
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* store to buffer */
|
|
|
|
if (bAnsi)
|
|
|
|
{
|
|
|
|
if ((pClientImc->dwFlags & CLIENTIMC_WIDE) &&
|
|
|
|
pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
|
|
|
|
{
|
|
|
|
ret = CandidateListWideToAnsi(pvPrivate, lpBuf, cb, CP_ACP);
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!(pClientImc->dwFlags & CLIENTIMC_WIDE) &&
|
|
|
|
pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
|
|
|
|
{
|
|
|
|
ret = CandidateListAnsiToWide(pvPrivate, lpBuf, cb, CP_ACP);
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlCopyMemory(lpBuf, pvPrivate, cb);
|
|
|
|
ret = cb;
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
ImmUnlockIMCC(pIC->hGuideLine);
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetGuideLineA (IMM32.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI ImmGetGuideLineA(
|
|
|
|
HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
|
|
|
|
{
|
2021-08-05 12:43:21 +00:00
|
|
|
TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen);
|
|
|
|
return ImmGetGuideLineAW(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetGuideLineW (IMM32.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
|
|
|
|
{
|
2021-08-05 12:43:21 +00:00
|
|
|
TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen);
|
|
|
|
return ImmGetGuideLineAW(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetIMEFileNameA (IMM32.@)
|
|
|
|
*/
|
2008-04-04 13:20:27 +00:00
|
|
|
UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2021-07-15 14:01:50 +00:00
|
|
|
BOOL bDefUsed;
|
|
|
|
IMEINFOEX info;
|
|
|
|
size_t cch;
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p, %p, %u)\n", hKL, lpszFileName, uBufLen);
|
2021-07-15 14:01:50 +00:00
|
|
|
|
|
|
|
if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || !IS_IME_HKL(hKL))
|
2008-04-04 13:20:27 +00:00
|
|
|
{
|
2021-07-15 14:01:50 +00:00
|
|
|
if (uBufLen > 0)
|
|
|
|
lpszFileName[0] = 0;
|
|
|
|
return 0;
|
2008-04-04 13:20:27 +00:00
|
|
|
}
|
|
|
|
|
2021-07-15 14:01:50 +00:00
|
|
|
StringCchLengthW(info.wszImeFile, _countof(info.wszImeFile), &cch);
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-07-15 14:01:50 +00:00
|
|
|
cch = WideCharToMultiByte(CP_ACP, 0, info.wszImeFile, (INT)cch,
|
|
|
|
lpszFileName, uBufLen, NULL, &bDefUsed);
|
|
|
|
if (uBufLen == 0)
|
|
|
|
return (UINT)cch;
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-07-15 14:01:50 +00:00
|
|
|
if (cch > uBufLen - 1)
|
|
|
|
cch = uBufLen - 1;
|
|
|
|
|
|
|
|
lpszFileName[cch] = 0;
|
|
|
|
return (UINT)cch;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetIMEFileNameW (IMM32.@)
|
|
|
|
*/
|
2008-04-04 13:20:27 +00:00
|
|
|
UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2021-07-15 14:01:50 +00:00
|
|
|
IMEINFOEX info;
|
|
|
|
size_t cch;
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p, %p, %u)\n", hKL, lpszFileName, uBufLen);
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-07-15 14:01:50 +00:00
|
|
|
if (!ImmGetImeInfoEx(&info, ImeInfoExKeyboardLayout, &hKL) || !IS_IME_HKL(hKL))
|
2008-04-04 13:20:27 +00:00
|
|
|
{
|
2021-07-15 14:01:50 +00:00
|
|
|
if (uBufLen > 0)
|
|
|
|
lpszFileName[0] = 0;
|
2008-04-04 13:20:27 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-15 14:01:50 +00:00
|
|
|
StringCchLengthW(info.wszImeFile, _countof(info.wszImeFile), &cch);
|
|
|
|
if (uBufLen == 0)
|
|
|
|
return (UINT)cch;
|
|
|
|
|
|
|
|
StringCchCopyNW(lpszFileName, uBufLen, info.wszImeFile, cch);
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-07-15 14:01:50 +00:00
|
|
|
if (cch > uBufLen - 1)
|
|
|
|
cch = uBufLen - 1;
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-07-15 14:01:50 +00:00
|
|
|
lpszFileName[cch] = 0;
|
|
|
|
return (UINT)cch;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetOpenStatus (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
|
|
|
|
{
|
2021-07-08 05:24:27 +00:00
|
|
|
BOOL ret;
|
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p)\n", hIMC);
|
2021-07-08 05:24:27 +00:00
|
|
|
|
|
|
|
if (!hIMC)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (!pIC)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
ret = pIC->fOpen;
|
|
|
|
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetProperty (IMM32.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
|
|
|
|
{
|
2021-08-12 03:33:12 +00:00
|
|
|
IMEINFOEX ImeInfoEx;
|
|
|
|
LPIMEINFO pImeInfo;
|
|
|
|
DWORD dwValue;
|
|
|
|
PIMEDPI pImeDpi = NULL;
|
|
|
|
|
|
|
|
TRACE("(%p, %lu)\n", hKL, fdwIndex);
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-12 03:33:12 +00:00
|
|
|
if (!ImmGetImeInfoEx(&ImeInfoEx, ImeInfoExKeyboardLayout, &hKL))
|
|
|
|
return FALSE;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-12 03:33:12 +00:00
|
|
|
if (fdwIndex == IGP_GETIMEVERSION)
|
|
|
|
return ImeInfoEx.dwImeWinVersion;
|
|
|
|
|
|
|
|
if (ImeInfoEx.fLoadFlag != 2)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2021-08-12 03:33:12 +00:00
|
|
|
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
|
|
|
if (pImeDpi == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
pImeInfo = &pImeDpi->ImeInfo;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
2021-08-12 03:33:12 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
pImeInfo = &ImeInfoEx.ImeInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (fdwIndex)
|
|
|
|
{
|
|
|
|
case IGP_PROPERTY: dwValue = pImeInfo->fdwProperty; break;
|
|
|
|
case IGP_CONVERSION: dwValue = pImeInfo->fdwConversionCaps; break;
|
|
|
|
case IGP_SENTENCE: dwValue = pImeInfo->fdwSentenceCaps; break;
|
|
|
|
case IGP_UI: dwValue = pImeInfo->fdwUICaps; break;
|
|
|
|
case IGP_SETCOMPSTR: dwValue = pImeInfo->fdwSCSCaps; break;
|
|
|
|
case IGP_SELECT: dwValue = pImeInfo->fdwSelectCaps; break;
|
|
|
|
default: dwValue = 0; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pImeDpi)
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return dwValue;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetRegisterWordStyleA (IMM32.@)
|
|
|
|
*/
|
|
|
|
UINT WINAPI ImmGetRegisterWordStyleA(
|
|
|
|
HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
|
|
|
|
{
|
2021-08-14 01:39:20 +00:00
|
|
|
UINT iItem, ret = 0;
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
LPSTYLEBUFA pDestA;
|
|
|
|
LPSTYLEBUFW pSrcW, pNewStylesW = NULL;
|
|
|
|
size_t cchW;
|
|
|
|
INT cchA;
|
|
|
|
|
|
|
|
TRACE("(%p, %u, %p)\n", hKL, nItem, lpStyleBuf);
|
|
|
|
|
|
|
|
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
|
|
|
if (!pImeDpi)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-08-14 01:39:20 +00:00
|
|
|
ret = pImeDpi->ImeGetRegisterWordStyle(nItem, lpStyleBuf);
|
|
|
|
goto Quit;
|
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-14 01:39:20 +00:00
|
|
|
if (nItem > 0)
|
|
|
|
{
|
|
|
|
pNewStylesW = Imm32HeapAlloc(0, nItem * sizeof(STYLEBUFW));
|
|
|
|
if (!pNewStylesW)
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = pImeDpi->ImeGetRegisterWordStyle(nItem, pNewStylesW);
|
|
|
|
|
|
|
|
if (nItem > 0)
|
|
|
|
{
|
|
|
|
/* lpStyleBuf <-- pNewStylesW */
|
|
|
|
for (iItem = 0; iItem < ret; ++iItem)
|
|
|
|
{
|
|
|
|
pSrcW = &pNewStylesW[iItem];
|
|
|
|
pDestA = &lpStyleBuf[iItem];
|
|
|
|
pDestA->dwStyle = pSrcW->dwStyle;
|
|
|
|
StringCchLengthW(pSrcW->szDescription, _countof(pSrcW->szDescription), &cchW);
|
|
|
|
cchA = WideCharToMultiByte(CP_ACP, MB_PRECOMPOSED,
|
|
|
|
pSrcW->szDescription, (INT)cchW,
|
|
|
|
pDestA->szDescription, _countof(pDestA->szDescription),
|
|
|
|
NULL, NULL);
|
|
|
|
if (cchA > _countof(pDestA->szDescription) - 1)
|
|
|
|
cchA = _countof(pDestA->szDescription) - 1;
|
|
|
|
pDestA->szDescription[cchA] = 0;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
|
|
|
}
|
2021-08-14 01:39:20 +00:00
|
|
|
|
|
|
|
Quit:
|
|
|
|
if (pNewStylesW)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pNewStylesW);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetRegisterWordStyleW (IMM32.@)
|
|
|
|
*/
|
|
|
|
UINT WINAPI ImmGetRegisterWordStyleW(
|
|
|
|
HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
|
|
|
|
{
|
2021-08-14 01:39:20 +00:00
|
|
|
UINT iItem, ret = 0;
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
LPSTYLEBUFA pSrcA, pNewStylesA = NULL;
|
|
|
|
LPSTYLEBUFW pDestW;
|
|
|
|
size_t cchA;
|
|
|
|
INT cchW;
|
|
|
|
|
|
|
|
TRACE("(%p, %u, %p)\n", hKL, nItem, lpStyleBuf);
|
|
|
|
|
|
|
|
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
|
|
|
if (!pImeDpi)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-08-14 01:39:20 +00:00
|
|
|
ret = pImeDpi->ImeGetRegisterWordStyle(nItem, lpStyleBuf);
|
|
|
|
goto Quit;
|
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-14 01:39:20 +00:00
|
|
|
if (nItem > 0)
|
|
|
|
{
|
|
|
|
pNewStylesA = Imm32HeapAlloc(0, nItem * sizeof(STYLEBUFA));
|
|
|
|
if (!pNewStylesA)
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = pImeDpi->ImeGetRegisterWordStyle(nItem, pNewStylesA);
|
|
|
|
|
|
|
|
if (nItem > 0)
|
|
|
|
{
|
|
|
|
/* lpStyleBuf <-- pNewStylesA */
|
|
|
|
for (iItem = 0; iItem < ret; ++iItem)
|
|
|
|
{
|
|
|
|
pSrcA = &pNewStylesA[iItem];
|
|
|
|
pDestW = &lpStyleBuf[iItem];
|
|
|
|
pDestW->dwStyle = pSrcA->dwStyle;
|
|
|
|
StringCchLengthA(pSrcA->szDescription, _countof(pSrcA->szDescription), &cchA);
|
|
|
|
cchW = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
|
|
|
|
pSrcA->szDescription, (INT)cchA,
|
|
|
|
pDestW->szDescription, _countof(pDestW->szDescription));
|
|
|
|
if (cchW > _countof(pDestW->szDescription) - 1)
|
|
|
|
cchW = _countof(pDestW->szDescription) - 1;
|
|
|
|
pDestW->szDescription[cchW] = 0;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
|
|
|
}
|
2021-08-14 01:39:20 +00:00
|
|
|
|
|
|
|
Quit:
|
|
|
|
if (pNewStylesA)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pNewStylesA);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetStatusWindowPos (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
|
|
|
|
{
|
2021-07-15 22:30:55 +00:00
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
BOOL ret;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p, %p)\n", hIMC, lpptPos);
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-07-15 22:30:55 +00:00
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
2010-03-07 11:27:14 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-07-15 22:30:55 +00:00
|
|
|
ret = !!(pIC->fdwInit & INIT_STATUSWNDPOS);
|
|
|
|
if (ret)
|
|
|
|
*lpptPos = pIC->ptStatusWndPos;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-07-15 22:30:55 +00:00
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetVirtualKey (IMM32.@)
|
|
|
|
*/
|
|
|
|
UINT WINAPI ImmGetVirtualKey(HWND hWnd)
|
|
|
|
{
|
2021-08-09 23:03:32 +00:00
|
|
|
HIMC hIMC;
|
|
|
|
LPINPUTCONTEXTDX pIC;
|
|
|
|
UINT ret = VK_PROCESSKEY;
|
|
|
|
|
|
|
|
TRACE("(%p)\n", hWnd);
|
|
|
|
|
|
|
|
hIMC = ImmGetContext(hWnd);
|
|
|
|
pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
|
|
|
|
if (!pIC)
|
|
|
|
return ret;
|
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
if (pIC->bNeedsTrans)
|
2021-08-09 23:03:32 +00:00
|
|
|
ret = pIC->nVKey;
|
|
|
|
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmInstallIMEA (IMM32.@)
|
|
|
|
*/
|
|
|
|
HKL WINAPI ImmInstallIMEA(
|
|
|
|
LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
|
|
|
|
{
|
2021-08-14 01:38:06 +00:00
|
|
|
HKL hKL = NULL;
|
|
|
|
LPWSTR pszFileNameW = NULL, pszLayoutTextW = NULL;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-03 22:32:13 +00:00
|
|
|
TRACE("(%s, %s)\n", debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText));
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
pszFileNameW = Imm32WideFromAnsi(lpszIMEFileName);
|
2021-08-03 22:32:13 +00:00
|
|
|
if (pszFileNameW == NULL)
|
2021-08-14 01:38:06 +00:00
|
|
|
goto Quit;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
pszLayoutTextW = Imm32WideFromAnsi(lpszLayoutText);
|
2021-08-03 22:32:13 +00:00
|
|
|
if (pszLayoutTextW == NULL)
|
2021-08-14 01:38:06 +00:00
|
|
|
goto Quit;
|
2021-08-03 22:32:13 +00:00
|
|
|
|
|
|
|
hKL = ImmInstallIMEW(pszFileNameW, pszLayoutTextW);
|
2021-08-14 01:38:06 +00:00
|
|
|
|
|
|
|
Quit:
|
|
|
|
if (pszFileNameW)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszFileNameW);
|
|
|
|
if (pszLayoutTextW)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszLayoutTextW);
|
2021-08-03 22:32:13 +00:00
|
|
|
return hKL;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmInstallIMEW (IMM32.@)
|
|
|
|
*/
|
|
|
|
HKL WINAPI ImmInstallIMEW(
|
|
|
|
LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
|
|
|
|
{
|
2010-03-07 11:27:14 +00:00
|
|
|
INT lcid = GetUserDefaultLCID();
|
|
|
|
INT count;
|
|
|
|
HKL hkl;
|
|
|
|
DWORD rc;
|
|
|
|
HKEY hkey;
|
2018-10-01 11:53:21 +00:00
|
|
|
WCHAR regKey[ARRAY_SIZE(szImeRegFmt)+8];
|
2010-03-07 11:27:14 +00:00
|
|
|
|
|
|
|
TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName),
|
|
|
|
debugstr_w(lpszLayoutText));
|
|
|
|
|
|
|
|
/* Start with 2. e001 will be blank and so default to the wine internal IME */
|
|
|
|
count = 2;
|
|
|
|
|
|
|
|
while (count < 0xfff)
|
|
|
|
{
|
|
|
|
DWORD disposition = 0;
|
|
|
|
|
|
|
|
hkl = (HKL)MAKELPARAM( lcid, 0xe000 | count );
|
|
|
|
wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hkl);
|
|
|
|
|
|
|
|
rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &disposition);
|
|
|
|
if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
|
|
|
|
break;
|
|
|
|
else if (rc == ERROR_SUCCESS)
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count == 0xfff)
|
|
|
|
{
|
|
|
|
WARN("Unable to find slot to install IME\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rc == ERROR_SUCCESS)
|
|
|
|
{
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (const BYTE*)lpszIMEFileName,
|
2010-03-07 11:27:14 +00:00
|
|
|
(lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR));
|
|
|
|
if (rc == ERROR_SUCCESS)
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (const BYTE*)lpszLayoutText,
|
2010-03-07 11:27:14 +00:00
|
|
|
(lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR));
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
return hkl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WARN("Unable to set IME registry values\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmIsIME (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmIsIME(HKL hKL)
|
|
|
|
{
|
2021-07-08 05:23:25 +00:00
|
|
|
IMEINFOEX info;
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p)\n", hKL);
|
2021-07-08 05:23:25 +00:00
|
|
|
return !!ImmGetImeInfoEx(&info, ImeInfoExImeWindow, &hKL);
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
2021-08-16 06:33:51 +00:00
|
|
|
static BOOL APIENTRY
|
|
|
|
ImmIsUIMessageAW(HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam, BOOL bAnsi)
|
|
|
|
{
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_IME_STARTCOMPOSITION: case WM_IME_ENDCOMPOSITION:
|
|
|
|
case WM_IME_COMPOSITION: case WM_IME_SETCONTEXT: case WM_IME_NOTIFY:
|
|
|
|
case WM_IME_COMPOSITIONFULL: case WM_IME_SELECT: case WM_IME_SYSTEM:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hWndIME)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if (bAnsi)
|
|
|
|
SendMessageA(hWndIME, msg, wParam, lParam);
|
|
|
|
else
|
|
|
|
SendMessageW(hWndIME, msg, wParam, lParam);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmIsUIMessageA (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmIsUIMessageA(
|
|
|
|
HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2021-08-16 06:33:51 +00:00
|
|
|
TRACE("(%p, 0x%X, %p, %p)\n", hWndIME, msg, wParam, lParam);
|
|
|
|
return ImmIsUIMessageAW(hWndIME, msg, wParam, lParam, TRUE);
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmIsUIMessageW (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmIsUIMessageW(
|
|
|
|
HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2021-08-16 06:33:51 +00:00
|
|
|
TRACE("(%p, 0x%X, %p, %p)\n", hWndIME, msg, wParam, lParam);
|
|
|
|
return ImmIsUIMessageAW(hWndIME, msg, wParam, lParam, FALSE);
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmNotifyIME (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmNotifyIME(
|
|
|
|
HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
|
|
|
|
{
|
2021-07-28 14:24:09 +00:00
|
|
|
HKL hKL;
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
BOOL ret;
|
2006-04-16 17:04:45 +00:00
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p, %lu, %lu, %lu)\n", hIMC, dwAction, dwIndex, dwValue);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
if (hIMC && Imm32IsCrossThreadAccess(hIMC))
|
|
|
|
return FALSE;
|
2014-09-28 18:27:58 +00:00
|
|
|
|
2021-07-28 14:24:09 +00:00
|
|
|
hKL = GetKeyboardLayout(0);
|
|
|
|
pImeDpi = ImmLockImeDpi(hKL);
|
|
|
|
if (pImeDpi == NULL)
|
2010-03-07 11:27:14 +00:00
|
|
|
return FALSE;
|
2007-09-14 08:03:04 +00:00
|
|
|
|
2021-07-28 14:24:09 +00:00
|
|
|
ret = pImeDpi->NotifyIME(hIMC, dwAction, dwIndex, dwValue);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmRegisterWordA (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmRegisterWordA(
|
|
|
|
HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
|
|
|
|
{
|
2021-08-09 23:08:23 +00:00
|
|
|
BOOL ret = FALSE;
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
LPWSTR pszReadingW = NULL, pszRegisterW = NULL;
|
|
|
|
|
|
|
|
TRACE("(%p, %s, 0x%lX, %s)\n", hKL, debugstr_a(lpszReading), dwStyle,
|
|
|
|
debugstr_a(lpszRegister));
|
|
|
|
|
|
|
|
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
|
|
|
if (!pImeDpi)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-08-09 23:08:23 +00:00
|
|
|
ret = pImeDpi->ImeRegisterWord(lpszReading, dwStyle, lpszRegister);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-09 23:08:23 +00:00
|
|
|
if (lpszReading)
|
|
|
|
{
|
2021-08-14 01:38:06 +00:00
|
|
|
pszReadingW = Imm32WideFromAnsi(lpszReading);
|
2021-08-09 23:08:23 +00:00
|
|
|
if (pszReadingW == NULL)
|
|
|
|
goto Quit;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2021-08-09 23:08:23 +00:00
|
|
|
|
|
|
|
if (lpszRegister)
|
|
|
|
{
|
2021-08-14 01:38:06 +00:00
|
|
|
pszRegisterW = Imm32WideFromAnsi(lpszRegister);
|
2021-08-09 23:08:23 +00:00
|
|
|
if (pszRegisterW == NULL)
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
2021-08-12 03:29:02 +00:00
|
|
|
ret = pImeDpi->ImeRegisterWord(pszReadingW, dwStyle, pszRegisterW);
|
2021-08-09 23:08:23 +00:00
|
|
|
|
|
|
|
Quit:
|
|
|
|
if (pszReadingW)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszReadingW);
|
|
|
|
if (pszRegisterW)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszRegisterW);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmRegisterWordW (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmRegisterWordW(
|
|
|
|
HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
|
|
|
|
{
|
2021-08-12 03:29:02 +00:00
|
|
|
BOOL ret = FALSE;
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
LPSTR pszReadingA = NULL, pszRegisterA = NULL;
|
|
|
|
|
|
|
|
TRACE("(%p, %s, 0x%lX, %s)\n", hKL, debugstr_w(lpszReading), dwStyle,
|
|
|
|
debugstr_w(lpszRegister));
|
|
|
|
|
|
|
|
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
|
|
|
if (!pImeDpi)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-08-12 03:29:02 +00:00
|
|
|
ret = pImeDpi->ImeRegisterWord(lpszReading, dwStyle, lpszRegister);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-12 03:29:02 +00:00
|
|
|
if (lpszReading)
|
|
|
|
{
|
2021-08-14 01:38:06 +00:00
|
|
|
pszReadingA = Imm32AnsiFromWide(lpszReading);
|
2021-08-12 03:29:02 +00:00
|
|
|
if (!pszReadingA)
|
|
|
|
goto Quit;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2021-08-12 03:29:02 +00:00
|
|
|
|
|
|
|
if (lpszRegister)
|
|
|
|
{
|
2021-08-14 01:38:06 +00:00
|
|
|
pszRegisterA = Imm32AnsiFromWide(lpszRegister);
|
2021-08-12 03:29:02 +00:00
|
|
|
if (!pszRegisterA)
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = pImeDpi->ImeRegisterWord(pszReadingA, dwStyle, pszRegisterA);
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
if (pszReadingA)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszReadingA);
|
|
|
|
if (pszRegisterA)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszRegisterA);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
2008-05-08 16:03:10 +00:00
|
|
|
* ImmReleaseContext (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2021-08-23 21:50:39 +00:00
|
|
|
TRACE("(%p, %p)\n", hWnd, hIMC);
|
|
|
|
UNREFERENCED_PARAMETER(hWnd);
|
|
|
|
UNREFERENCED_PARAMETER(hIMC);
|
|
|
|
return TRUE; // Do nothing. This is correct.
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmRequestMessageA(IMM32.@)
|
|
|
|
*/
|
|
|
|
LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2014-09-28 18:27:58 +00:00
|
|
|
InputContextData *data = get_imc_data(hIMC);
|
2010-03-07 11:27:14 +00:00
|
|
|
|
|
|
|
TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
|
|
|
|
|
2017-12-08 03:14:21 +00:00
|
|
|
if (data) return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2017-12-08 03:14:21 +00:00
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return 0;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmRequestMessageW(IMM32.@)
|
|
|
|
*/
|
|
|
|
LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2014-09-28 18:27:58 +00:00
|
|
|
InputContextData *data = get_imc_data(hIMC);
|
2008-05-06 09:16:21 +00:00
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
|
|
|
|
|
2017-12-08 03:14:21 +00:00
|
|
|
if (data) return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2017-12-08 03:14:21 +00:00
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return 0;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmSetCandidateWindow (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmSetCandidateWindow(
|
|
|
|
HIMC hIMC, LPCANDIDATEFORM lpCandidate)
|
|
|
|
{
|
2021-08-07 23:34:47 +00:00
|
|
|
HWND hWnd;
|
|
|
|
LPINPUTCONTEXT pIC;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
|
|
|
TRACE("(%p, %p)\n", hIMC, lpCandidate);
|
|
|
|
|
2021-08-07 23:34:47 +00:00
|
|
|
if (lpCandidate->dwIndex >= MAX_CANDIDATEFORM)
|
2010-03-07 11:27:14 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
if (Imm32IsCrossThreadAccess(hIMC))
|
2017-12-08 03:14:21 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-08-07 23:34:47 +00:00
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
2010-03-07 11:27:14 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-08-07 23:34:47 +00:00
|
|
|
hWnd = pIC->hWnd;
|
|
|
|
pIC->cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
|
|
|
|
|
|
|
|
ImmUnlockIMC(hIMC);
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-07 23:34:47 +00:00
|
|
|
Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS,
|
2021-08-23 21:50:39 +00:00
|
|
|
IMN_SETCANDIDATEPOS, (1 << (BYTE)lpCandidate->dwIndex));
|
2010-03-07 11:27:14 +00:00
|
|
|
return TRUE;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
2021-08-08 08:35:34 +00:00
|
|
|
static VOID APIENTRY WideToAnsiLogFont(const LOGFONTW *plfW, LPLOGFONTA plfA)
|
|
|
|
{
|
|
|
|
BOOL bUsedDef;
|
|
|
|
size_t cchW, cchA = _countof(plfA->lfFaceName);
|
|
|
|
RtlCopyMemory(plfA, plfW, offsetof(LOGFONTA, lfFaceName));
|
|
|
|
StringCchLengthW(plfW->lfFaceName, _countof(plfW->lfFaceName), &cchW);
|
|
|
|
cchA = WideCharToMultiByte(CP_ACP, 0, plfW->lfFaceName, (INT)cchW,
|
|
|
|
plfA->lfFaceName, (INT)cchA, NULL, &bUsedDef);
|
|
|
|
if (cchA > _countof(plfA->lfFaceName) - 1)
|
|
|
|
cchA = _countof(plfA->lfFaceName) - 1;
|
|
|
|
plfA->lfFaceName[cchA] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VOID APIENTRY AnsiToWideLogFont(const LOGFONTA *plfA, LPLOGFONTW plfW)
|
|
|
|
{
|
|
|
|
size_t cchA, cchW = _countof(plfW->lfFaceName);
|
|
|
|
RtlCopyMemory(plfW, plfA, offsetof(LOGFONTW, lfFaceName));
|
|
|
|
StringCchLengthA(plfA->lfFaceName, _countof(plfA->lfFaceName), &cchA);
|
|
|
|
cchW = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, plfA->lfFaceName, (INT)cchA,
|
2021-08-23 21:50:39 +00:00
|
|
|
plfW->lfFaceName, (INT)cchW);
|
2021-08-08 08:35:34 +00:00
|
|
|
if (cchW > _countof(plfW->lfFaceName) - 1)
|
|
|
|
cchW = _countof(plfW->lfFaceName) - 1;
|
|
|
|
plfW->lfFaceName[cchW] = 0;
|
|
|
|
}
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmSetCompositionFontA (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
|
|
|
|
{
|
2021-08-08 08:35:34 +00:00
|
|
|
LOGFONTW lfW;
|
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
BOOL bWide;
|
|
|
|
LPINPUTCONTEXTDX pIC;
|
|
|
|
LCID lcid;
|
|
|
|
HWND hWnd;
|
|
|
|
PTEB pTeb;
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
TRACE("(%p, %p)\n", hIMC, lplf);
|
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
if (Imm32IsCrossThreadAccess(hIMC))
|
2021-08-08 08:35:34 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
pClientImc = ImmLockClientImc(hIMC);
|
|
|
|
if (pClientImc == NULL)
|
2005-12-12 20:59:55 +00:00
|
|
|
return FALSE;
|
2021-08-08 08:35:34 +00:00
|
|
|
|
|
|
|
bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
|
|
|
|
if (bWide)
|
|
|
|
{
|
|
|
|
AnsiToWideLogFont(lplf, &lfW);
|
|
|
|
return ImmSetCompositionFontW(hIMC, &lfW);
|
2014-09-28 18:27:58 +00:00
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-08 08:35:34 +00:00
|
|
|
pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
2017-12-08 03:14:21 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-08-08 08:35:34 +00:00
|
|
|
pTeb = NtCurrentTeb();
|
|
|
|
if (pTeb->Win32ClientInfo[2] < 0x400)
|
|
|
|
{
|
|
|
|
lcid = GetSystemDefaultLCID();
|
|
|
|
if (PRIMARYLANGID(lcid) == LANG_JAPANESE && !(pIC->dwUIFlags & 2) &&
|
|
|
|
pIC->cfCompForm.dwStyle != CFS_DEFAULT)
|
|
|
|
{
|
|
|
|
PostMessageA(pIC->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pIC->lfFont.A = *lplf;
|
|
|
|
pIC->fdwInit |= INIT_LOGFONT;
|
|
|
|
hWnd = pIC->hWnd;
|
|
|
|
|
|
|
|
ImmUnlockIMC(hIMC);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-08 08:35:34 +00:00
|
|
|
Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT,
|
|
|
|
IMN_SETCOMPOSITIONFONT, 0);
|
2005-12-12 20:59:55 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmSetCompositionFontW (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
|
|
|
|
{
|
2021-08-08 08:35:34 +00:00
|
|
|
LOGFONTA lfA;
|
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
BOOL bWide;
|
|
|
|
HWND hWnd;
|
|
|
|
LPINPUTCONTEXTDX pIC;
|
|
|
|
PTEB pTeb;
|
|
|
|
LCID lcid;
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
TRACE("(%p, %p)\n", hIMC, lplf);
|
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
if (Imm32IsCrossThreadAccess(hIMC))
|
2005-12-12 20:59:55 +00:00
|
|
|
return FALSE;
|
2021-08-08 08:35:34 +00:00
|
|
|
|
|
|
|
pClientImc = ImmLockClientImc(hIMC);
|
|
|
|
if (pClientImc == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
bWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
|
|
|
|
if (!bWide)
|
|
|
|
{
|
|
|
|
WideToAnsiLogFont(lplf, &lfA);
|
|
|
|
return ImmSetCompositionFontA(hIMC, &lfA);
|
2014-09-28 18:27:58 +00:00
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-08 08:35:34 +00:00
|
|
|
pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
2017-12-08 03:14:21 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-08-08 08:35:34 +00:00
|
|
|
pTeb = NtCurrentTeb();
|
|
|
|
if (pTeb->Win32ClientInfo[2] < 0x400)
|
|
|
|
{
|
|
|
|
lcid = GetSystemDefaultLCID();
|
|
|
|
if (PRIMARYLANGID(lcid) == LANG_JAPANESE &&
|
|
|
|
!(pIC->dwUIFlags & 2) &&
|
|
|
|
pIC->cfCompForm.dwStyle != CFS_DEFAULT)
|
|
|
|
{
|
|
|
|
PostMessageW(pIC->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pIC->lfFont.W = *lplf;
|
|
|
|
pIC->fdwInit |= INIT_LOGFONT;
|
|
|
|
hWnd = pIC->hWnd;
|
|
|
|
|
|
|
|
ImmUnlockIMC(hIMC);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-08 08:35:34 +00:00
|
|
|
Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT,
|
|
|
|
IMN_SETCOMPOSITIONFONT, 0);
|
2005-12-12 20:59:55 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmSetCompositionStringA (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmSetCompositionStringA(
|
|
|
|
HIMC hIMC, DWORD dwIndex,
|
|
|
|
LPCVOID lpComp, DWORD dwCompLen,
|
|
|
|
LPCVOID lpRead, DWORD dwReadLen)
|
|
|
|
{
|
|
|
|
DWORD comp_len;
|
|
|
|
DWORD read_len;
|
|
|
|
WCHAR *CompBuffer = NULL;
|
|
|
|
WCHAR *ReadBuffer = NULL;
|
|
|
|
BOOL rc;
|
2014-09-28 18:27:58 +00:00
|
|
|
InputContextData *data = get_imc_data(hIMC);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
TRACE("(%p, %d, %p, %d, %p, %d):\n",
|
2005-12-12 20:59:55 +00:00
|
|
|
hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
if (!data)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(dwIndex == SCS_SETSTR ||
|
|
|
|
dwIndex == SCS_CHANGEATTR ||
|
|
|
|
dwIndex == SCS_CHANGECLAUSE ||
|
|
|
|
dwIndex == SCS_SETRECONVERTSTRING ||
|
|
|
|
dwIndex == SCS_QUERYRECONVERTSTRING))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!is_himc_ime_unicode(data))
|
|
|
|
return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
|
|
|
|
dwCompLen, lpRead, dwReadLen);
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
|
|
|
|
if (comp_len)
|
|
|
|
{
|
|
|
|
CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
|
|
|
|
if (read_len)
|
|
|
|
{
|
|
|
|
ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
|
|
|
|
ReadBuffer, read_len);
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, CompBuffer);
|
|
|
|
HeapFree(GetProcessHeap(), 0, ReadBuffer);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmSetCompositionStringW (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmSetCompositionStringW(
|
|
|
|
HIMC hIMC, DWORD dwIndex,
|
|
|
|
LPCVOID lpComp, DWORD dwCompLen,
|
|
|
|
LPCVOID lpRead, DWORD dwReadLen)
|
|
|
|
{
|
2010-03-07 11:27:14 +00:00
|
|
|
DWORD comp_len;
|
|
|
|
DWORD read_len;
|
|
|
|
CHAR *CompBuffer = NULL;
|
|
|
|
CHAR *ReadBuffer = NULL;
|
|
|
|
BOOL rc;
|
2014-09-28 18:27:58 +00:00
|
|
|
InputContextData *data = get_imc_data(hIMC);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
TRACE("(%p, %d, %p, %d, %p, %d):\n",
|
|
|
|
hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
if (!data)
|
|
|
|
return FALSE;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
if (!(dwIndex == SCS_SETSTR ||
|
|
|
|
dwIndex == SCS_CHANGEATTR ||
|
|
|
|
dwIndex == SCS_CHANGECLAUSE ||
|
|
|
|
dwIndex == SCS_SETRECONVERTSTRING ||
|
|
|
|
dwIndex == SCS_QUERYRECONVERTSTRING))
|
|
|
|
return FALSE;
|
2008-05-08 16:03:10 +00:00
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
if (is_himc_ime_unicode(data))
|
|
|
|
return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
|
|
|
|
dwCompLen, lpRead, dwReadLen);
|
2008-05-08 16:03:10 +00:00
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL,
|
|
|
|
NULL);
|
|
|
|
if (comp_len)
|
2008-05-06 09:16:21 +00:00
|
|
|
{
|
2010-03-07 11:27:14 +00:00
|
|
|
CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len);
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len,
|
|
|
|
NULL, NULL);
|
|
|
|
}
|
2008-05-08 16:03:10 +00:00
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL,
|
|
|
|
NULL);
|
|
|
|
if (read_len)
|
|
|
|
{
|
|
|
|
ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len);
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len,
|
|
|
|
NULL, NULL);
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len,
|
|
|
|
ReadBuffer, read_len);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, CompBuffer);
|
|
|
|
HeapFree(GetProcessHeap(), 0, ReadBuffer);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
return rc;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmSetCompositionWindow (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmSetCompositionWindow(
|
|
|
|
HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
|
|
|
|
{
|
2021-07-28 14:26:02 +00:00
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
HWND hWnd;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
if (Imm32IsCrossThreadAccess(hIMC))
|
2005-12-12 20:59:55 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-07-28 14:26:02 +00:00
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
2017-12-08 03:14:21 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-07-28 14:26:02 +00:00
|
|
|
pIC->cfCompForm = *lpCompForm;
|
|
|
|
pIC->fdwInit |= INIT_COMPFORM;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-07-28 14:26:02 +00:00
|
|
|
hWnd = pIC->hWnd;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-07-28 14:26:02 +00:00
|
|
|
ImmUnlockIMC(hIMC);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-07-28 14:26:02 +00:00
|
|
|
Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0,
|
|
|
|
IMC_SETCOMPOSITIONWINDOW, IMN_SETCOMPOSITIONWINDOW, 0);
|
2005-12-12 20:59:55 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmSetConversionStatus (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmSetConversionStatus(
|
|
|
|
HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
|
|
|
|
{
|
2021-08-05 22:15:19 +00:00
|
|
|
HKL hKL;
|
|
|
|
LPINPUTCONTEXT pIC;
|
2021-08-14 01:38:06 +00:00
|
|
|
DWORD dwOldConversion, dwOldSentence;
|
2021-08-05 22:15:19 +00:00
|
|
|
BOOL fConversionChange = FALSE, fSentenceChange = FALSE;
|
|
|
|
HWND hWnd;
|
2008-05-06 09:16:21 +00:00
|
|
|
|
2021-08-05 22:15:19 +00:00
|
|
|
TRACE("(%p, 0x%lX, 0x%lX)\n", hIMC, fdwConversion, fdwSentence);
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-05 22:15:19 +00:00
|
|
|
hKL = GetKeyboardLayout(0);
|
|
|
|
if (!IS_IME_HKL(hKL))
|
2014-09-28 18:27:58 +00:00
|
|
|
{
|
2021-08-05 22:15:19 +00:00
|
|
|
if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
|
|
|
|
{
|
|
|
|
FIXME("Cicero\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2014-09-28 18:27:58 +00:00
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
if (Imm32IsCrossThreadAccess(hIMC))
|
2021-08-05 22:15:19 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
2017-12-08 03:14:21 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-08-05 22:15:19 +00:00
|
|
|
if (pIC->fdwConversion != fdwConversion)
|
|
|
|
{
|
|
|
|
dwOldConversion = pIC->fdwConversion;
|
|
|
|
pIC->fdwConversion = fdwConversion;
|
|
|
|
fConversionChange = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pIC->fdwSentence != fdwSentence)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-08-05 22:15:19 +00:00
|
|
|
dwOldSentence = pIC->fdwSentence;
|
|
|
|
pIC->fdwSentence = fdwSentence;
|
|
|
|
fSentenceChange = TRUE;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2021-08-05 22:15:19 +00:00
|
|
|
|
|
|
|
hWnd = pIC->hWnd;
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
|
|
|
|
if (fConversionChange)
|
|
|
|
{
|
|
|
|
Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, dwOldConversion,
|
|
|
|
IMC_SETCONVERSIONMODE, IMN_SETCONVERSIONMODE, 0);
|
2021-08-16 06:45:11 +00:00
|
|
|
NtUserNotifyIMEStatus(hWnd, hIMC, fdwConversion);
|
2021-08-05 22:15:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fSentenceChange)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-08-05 22:15:19 +00:00
|
|
|
Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, dwOldSentence,
|
|
|
|
IMC_SETSENTENCEMODE, IMN_SETSENTENCEMODE, 0);
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
2021-07-25 02:57:57 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmLockImeDpi (IMM32.@)
|
|
|
|
*/
|
|
|
|
PIMEDPI WINAPI ImmLockImeDpi(HKL hKL)
|
|
|
|
{
|
|
|
|
PIMEDPI pImeDpi = NULL;
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p)\n", hKL);
|
2021-07-25 02:57:57 +00:00
|
|
|
|
|
|
|
RtlEnterCriticalSection(&g_csImeDpi);
|
|
|
|
|
|
|
|
/* Find by hKL */
|
|
|
|
for (pImeDpi = g_pImeDpiList; pImeDpi; pImeDpi = pImeDpi->pNext)
|
|
|
|
{
|
|
|
|
if (pImeDpi->hKL == hKL) /* found */
|
|
|
|
{
|
|
|
|
/* lock if possible */
|
|
|
|
if (pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN)
|
|
|
|
pImeDpi = NULL;
|
|
|
|
else
|
|
|
|
++(pImeDpi->cLockObj);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlLeaveCriticalSection(&g_csImeDpi);
|
|
|
|
return pImeDpi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmUnlockImeDpi (IMM32.@)
|
|
|
|
*/
|
|
|
|
VOID WINAPI ImmUnlockImeDpi(PIMEDPI pImeDpi)
|
|
|
|
{
|
|
|
|
PIMEDPI *ppEntry;
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p)\n", pImeDpi);
|
2021-07-25 02:57:57 +00:00
|
|
|
|
|
|
|
if (pImeDpi == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
RtlEnterCriticalSection(&g_csImeDpi);
|
|
|
|
|
|
|
|
/* unlock */
|
|
|
|
--(pImeDpi->cLockObj);
|
|
|
|
if (pImeDpi->cLockObj != 0)
|
|
|
|
{
|
|
|
|
RtlLeaveCriticalSection(&g_csImeDpi);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN) == 0)
|
|
|
|
{
|
2021-08-04 00:41:59 +00:00
|
|
|
if ((pImeDpi->dwFlags & IMEDPI_FLAG_LOCKED) == 0 ||
|
|
|
|
(pImeDpi->ImeInfo.fdwProperty & IME_PROP_END_UNLOAD) == 0)
|
2021-07-25 02:57:57 +00:00
|
|
|
{
|
|
|
|
RtlLeaveCriticalSection(&g_csImeDpi);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Remove from list */
|
|
|
|
for (ppEntry = &g_pImeDpiList; *ppEntry; ppEntry = &((*ppEntry)->pNext))
|
|
|
|
{
|
|
|
|
if (*ppEntry == pImeDpi) /* found */
|
|
|
|
{
|
|
|
|
*ppEntry = pImeDpi->pNext;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Imm32FreeImeDpi(pImeDpi, TRUE);
|
|
|
|
HeapFree(g_hImm32Heap, 0, pImeDpi);
|
|
|
|
|
|
|
|
RtlLeaveCriticalSection(&g_csImeDpi);
|
|
|
|
}
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmSetOpenStatus (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
|
|
|
|
{
|
2021-08-14 01:38:06 +00:00
|
|
|
DWORD dwConversion;
|
2021-07-25 02:57:57 +00:00
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
HWND hWnd;
|
|
|
|
BOOL bHasChange = FALSE;
|
2006-04-16 17:04:45 +00:00
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p, %d)\n", hIMC, fOpen);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
if (Imm32IsCrossThreadAccess(hIMC))
|
2008-05-08 16:03:10 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-07-25 02:57:57 +00:00
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
2017-12-08 03:14:21 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-07-25 02:57:57 +00:00
|
|
|
if (pIC->fOpen != fOpen)
|
2008-05-06 09:16:21 +00:00
|
|
|
{
|
2021-07-25 02:57:57 +00:00
|
|
|
pIC->fOpen = fOpen;
|
|
|
|
hWnd = pIC->hWnd;
|
|
|
|
dwConversion = pIC->fdwConversion;
|
|
|
|
bHasChange = TRUE;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-07-25 02:57:57 +00:00
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
|
|
|
|
if (bHasChange)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-07-25 02:57:57 +00:00
|
|
|
Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0,
|
|
|
|
IMC_SETOPENSTATUS, IMN_SETOPENSTATUS, 0);
|
2021-08-16 06:45:11 +00:00
|
|
|
NtUserNotifyIMEStatus(hWnd, hIMC, dwConversion);
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmSetStatusWindowPos (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
|
|
|
|
{
|
2021-07-28 14:23:09 +00:00
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
HWND hWnd;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p, {%ld, %ld})\n", hIMC, lpptPos->x, lpptPos->y);
|
2008-05-06 09:16:21 +00:00
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
if (Imm32IsCrossThreadAccess(hIMC))
|
2005-12-12 20:59:55 +00:00
|
|
|
return FALSE;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-07-28 14:23:09 +00:00
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (!pIC)
|
2017-12-08 03:14:21 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-07-28 14:23:09 +00:00
|
|
|
hWnd = pIC->hWnd;
|
|
|
|
pIC->ptStatusWndPos = *lpptPos;
|
|
|
|
pIC->fdwInit |= INIT_STATUSWNDPOS;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-07-28 14:23:09 +00:00
|
|
|
ImmUnlockIMC(hIMC);
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-07-28 14:23:09 +00:00
|
|
|
Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0,
|
|
|
|
IMC_SETSTATUSWINDOWPOS, IMN_SETSTATUSWINDOWPOS, 0);
|
2005-12-12 20:59:55 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
2010-03-07 11:27:14 +00:00
|
|
|
* ImmCreateSoftKeyboard(IMM32.@)
|
2008-05-06 09:16:21 +00:00
|
|
|
*/
|
2010-03-07 11:27:14 +00:00
|
|
|
HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y)
|
2008-05-06 09:16:21 +00:00
|
|
|
{
|
2010-03-07 11:27:14 +00:00
|
|
|
FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y);
|
|
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmDestroySoftKeyboard(IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd)
|
|
|
|
{
|
2020-08-09 13:42:17 +00:00
|
|
|
TRACE("(%p)\n", hSoftWnd);
|
|
|
|
return DestroyWindow(hSoftWnd);
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmShowSoftKeyboard(IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow)
|
|
|
|
{
|
2020-08-09 13:42:17 +00:00
|
|
|
TRACE("(%p, %d)\n", hSoftWnd, nCmdShow);
|
|
|
|
if (hSoftWnd)
|
|
|
|
return ShowWindow(hSoftWnd, nCmdShow);
|
2010-03-07 11:27:14 +00:00
|
|
|
return FALSE;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmSimulateHotKey (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
|
|
|
|
{
|
2021-07-31 06:56:11 +00:00
|
|
|
HIMC hIMC;
|
|
|
|
DWORD dwThreadId;
|
|
|
|
HKL hKL;
|
|
|
|
BOOL ret;
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p, 0x%lX)\n", hWnd, dwHotKeyID);
|
2021-07-31 06:56:11 +00:00
|
|
|
|
|
|
|
hIMC = ImmGetContext(hWnd);
|
|
|
|
dwThreadId = GetWindowThreadProcessId(hWnd, NULL);
|
|
|
|
hKL = GetKeyboardLayout(dwThreadId);
|
|
|
|
ret = Imm32ProcessHotKey(hWnd, hIMC, hKL, dwHotKeyID);
|
|
|
|
ImmReleaseContext(hWnd, hIMC);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmUnregisterWordA (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmUnregisterWordA(
|
|
|
|
HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
|
|
|
|
{
|
2021-08-12 03:30:13 +00:00
|
|
|
BOOL ret = FALSE;
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
LPWSTR pszReadingW = NULL, pszUnregisterW = NULL;
|
|
|
|
|
|
|
|
TRACE("(%p, %s, 0x%lX, %s)\n", hKL, debugstr_a(lpszReading), dwStyle,
|
|
|
|
debugstr_a(lpszUnregister));
|
|
|
|
|
|
|
|
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
|
|
|
if (pImeDpi == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-08-12 03:30:13 +00:00
|
|
|
ret = pImeDpi->ImeUnregisterWord(lpszReading, dwStyle, lpszUnregister);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-12 03:30:13 +00:00
|
|
|
if (lpszReading)
|
|
|
|
{
|
2021-08-14 01:38:06 +00:00
|
|
|
pszReadingW = Imm32WideFromAnsi(lpszReading);
|
2021-08-12 03:30:13 +00:00
|
|
|
if (pszReadingW == NULL)
|
|
|
|
goto Quit;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2021-08-12 03:30:13 +00:00
|
|
|
|
|
|
|
if (lpszUnregister)
|
|
|
|
{
|
2021-08-14 01:38:06 +00:00
|
|
|
pszUnregisterW = Imm32WideFromAnsi(lpszUnregister);
|
2021-08-12 03:30:13 +00:00
|
|
|
if (pszUnregisterW == NULL)
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = pImeDpi->ImeUnregisterWord(pszReadingW, dwStyle, pszUnregisterW);
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
if (pszReadingW)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszReadingW);
|
|
|
|
if (pszUnregisterW)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszUnregisterW);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmUnregisterWordW (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmUnregisterWordW(
|
|
|
|
HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
|
|
|
|
{
|
2021-08-12 03:31:06 +00:00
|
|
|
BOOL ret = FALSE;
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
LPSTR pszReadingA = NULL, pszUnregisterA = NULL;
|
|
|
|
|
|
|
|
TRACE("(%p, %s, 0x%lX, %s)\n", hKL, debugstr_w(lpszReading), dwStyle,
|
|
|
|
debugstr_w(lpszUnregister));
|
|
|
|
|
|
|
|
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
|
|
|
if (!pImeDpi)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-08-12 03:31:06 +00:00
|
|
|
ret = pImeDpi->ImeUnregisterWord(lpszReading, dwStyle, lpszUnregister);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-12 03:31:06 +00:00
|
|
|
if (lpszReading)
|
|
|
|
{
|
2021-08-14 01:38:06 +00:00
|
|
|
pszReadingA = Imm32AnsiFromWide(lpszReading);
|
2021-08-12 03:31:06 +00:00
|
|
|
if (!pszReadingA)
|
|
|
|
goto Quit;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2021-08-12 03:31:06 +00:00
|
|
|
|
|
|
|
if (lpszUnregister)
|
|
|
|
{
|
2021-08-14 01:38:06 +00:00
|
|
|
pszUnregisterA = Imm32AnsiFromWide(lpszUnregister);
|
2021-08-12 03:31:06 +00:00
|
|
|
if (!pszUnregisterA)
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = pImeDpi->ImeUnregisterWord(pszReadingA, dwStyle, pszUnregisterA);
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
if (pszReadingA)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszReadingA);
|
|
|
|
if (pszUnregisterA)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pszUnregisterA);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
return ret;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
2007-03-14 14:34:47 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetImeMenuItemsA (IMM32.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
|
|
|
|
LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
|
|
|
|
DWORD dwSize)
|
|
|
|
{
|
2014-09-28 18:27:58 +00:00
|
|
|
InputContextData *data = get_imc_data(hIMC);
|
2010-03-07 11:27:14 +00:00
|
|
|
TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
|
|
|
|
lpImeParentMenu, lpImeMenu, dwSize);
|
2014-09-28 18:27:58 +00:00
|
|
|
|
|
|
|
if (!data)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
|
|
|
|
{
|
|
|
|
if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
|
|
|
|
return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
|
|
|
|
(IMEMENUITEMINFOW*)lpImeParentMenu,
|
|
|
|
(IMEMENUITEMINFOW*)lpImeMenu, dwSize);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
IMEMENUITEMINFOW lpImeParentMenuW;
|
|
|
|
IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL;
|
|
|
|
DWORD rc;
|
|
|
|
|
|
|
|
if (lpImeParentMenu)
|
|
|
|
parent = &lpImeParentMenuW;
|
|
|
|
if (lpImeMenu)
|
|
|
|
{
|
|
|
|
int count = dwSize / sizeof(LPIMEMENUITEMINFOA);
|
|
|
|
dwSize = count * sizeof(IMEMENUITEMINFOW);
|
|
|
|
lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
lpImeMenuW = NULL;
|
|
|
|
|
|
|
|
rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
|
|
|
|
parent, lpImeMenuW, dwSize);
|
|
|
|
|
|
|
|
if (lpImeParentMenu)
|
|
|
|
{
|
|
|
|
memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA));
|
|
|
|
lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem;
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString,
|
|
|
|
-1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE,
|
|
|
|
NULL, NULL);
|
|
|
|
}
|
|
|
|
if (lpImeMenu && rc)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < rc; i++)
|
|
|
|
{
|
|
|
|
memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA));
|
|
|
|
lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem;
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString,
|
|
|
|
-1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE,
|
|
|
|
NULL, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(),0,lpImeMenuW);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return 0;
|
2007-03-14 14:34:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetImeMenuItemsW (IMM32.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
|
|
|
|
LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
|
|
|
|
DWORD dwSize)
|
|
|
|
{
|
2014-09-28 18:27:58 +00:00
|
|
|
InputContextData *data = get_imc_data(hIMC);
|
2010-03-07 11:27:14 +00:00
|
|
|
TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
|
|
|
|
lpImeParentMenu, lpImeMenu, dwSize);
|
2014-09-28 18:27:58 +00:00
|
|
|
|
|
|
|
if (!data)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
|
|
|
|
{
|
|
|
|
if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
|
|
|
|
return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
|
|
|
|
lpImeParentMenu, lpImeMenu, dwSize);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
IMEMENUITEMINFOA lpImeParentMenuA;
|
|
|
|
IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL;
|
|
|
|
DWORD rc;
|
|
|
|
|
|
|
|
if (lpImeParentMenu)
|
|
|
|
parent = &lpImeParentMenuA;
|
|
|
|
if (lpImeMenu)
|
|
|
|
{
|
|
|
|
int count = dwSize / sizeof(LPIMEMENUITEMINFOW);
|
|
|
|
dwSize = count * sizeof(IMEMENUITEMINFOA);
|
|
|
|
lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
lpImeMenuA = NULL;
|
|
|
|
|
|
|
|
rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
|
|
|
|
(IMEMENUITEMINFOW*)parent,
|
|
|
|
(IMEMENUITEMINFOW*)lpImeMenuA, dwSize);
|
|
|
|
|
|
|
|
if (lpImeParentMenu)
|
|
|
|
{
|
|
|
|
memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA));
|
|
|
|
lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem;
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString,
|
|
|
|
-1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE);
|
|
|
|
}
|
|
|
|
if (lpImeMenu && rc)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < rc; i++)
|
|
|
|
{
|
|
|
|
memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA));
|
|
|
|
lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem;
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString,
|
|
|
|
-1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(),0,lpImeMenuA);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return 0;
|
2007-03-14 14:34:47 +00:00
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2007-09-14 08:03:04 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmLockIMC(IMM32.@)
|
|
|
|
*/
|
|
|
|
LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
|
|
|
|
{
|
2014-09-28 18:27:58 +00:00
|
|
|
InputContextData *data = get_imc_data(hIMC);
|
2007-09-14 08:03:04 +00:00
|
|
|
|
|
|
|
if (!data)
|
|
|
|
return NULL;
|
|
|
|
data->dwLock++;
|
|
|
|
return &data->IMC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmUnlockIMC(IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
|
|
|
|
{
|
2021-07-13 11:17:17 +00:00
|
|
|
PCLIENTIMC pClientImc;
|
2021-07-11 00:48:15 +00:00
|
|
|
HIMC hClientImc;
|
2014-09-28 18:27:58 +00:00
|
|
|
|
2021-07-13 11:17:17 +00:00
|
|
|
pClientImc = ImmLockClientImc(hIMC);
|
|
|
|
if (pClientImc == NULL)
|
2014-09-28 18:27:58 +00:00
|
|
|
return FALSE;
|
2021-07-11 00:48:15 +00:00
|
|
|
|
2021-07-13 11:17:17 +00:00
|
|
|
hClientImc = pClientImc->hImc;
|
2021-07-11 00:48:15 +00:00
|
|
|
if (hClientImc)
|
|
|
|
LocalUnlock(hClientImc);
|
|
|
|
|
2021-07-13 11:17:17 +00:00
|
|
|
InterlockedDecrement(&pClientImc->cLockObj);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
2013-12-01 15:57:34 +00:00
|
|
|
return TRUE;
|
2007-09-14 08:03:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetIMCLockCount(IMM32.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
|
|
|
|
{
|
2021-07-11 00:48:15 +00:00
|
|
|
DWORD ret;
|
|
|
|
HIMC hClientImc;
|
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
|
|
|
|
pClientImc = ImmLockClientImc(hIMC);
|
|
|
|
if (pClientImc == NULL)
|
2014-09-28 18:27:58 +00:00
|
|
|
return 0;
|
2021-07-11 00:48:15 +00:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
hClientImc = pClientImc->hImc;
|
|
|
|
if (hClientImc)
|
|
|
|
ret = (LocalFlags(hClientImc) & LMEM_LOCKCOUNT);
|
|
|
|
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return ret;
|
2007-09-14 08:03:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmCreateIMCC(IMM32.@)
|
|
|
|
*/
|
|
|
|
HIMCC WINAPI ImmCreateIMCC(DWORD size)
|
|
|
|
{
|
2021-07-07 01:04:30 +00:00
|
|
|
if (size < 4)
|
|
|
|
size = 4;
|
|
|
|
return LocalAlloc(LHND, size);
|
2007-09-14 08:03:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmDestroyIMCC(IMM32.@)
|
|
|
|
*/
|
|
|
|
HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
|
|
|
|
{
|
2021-07-07 01:04:30 +00:00
|
|
|
if (block)
|
|
|
|
return LocalFree(block);
|
|
|
|
return NULL;
|
2007-09-14 08:03:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmLockIMCC(IMM32.@)
|
|
|
|
*/
|
|
|
|
LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
|
|
|
|
{
|
2021-07-07 01:04:30 +00:00
|
|
|
if (imcc)
|
|
|
|
return LocalLock(imcc);
|
|
|
|
return NULL;
|
2007-09-14 08:03:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmUnlockIMCC(IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
|
|
|
|
{
|
2021-07-07 01:04:30 +00:00
|
|
|
if (imcc)
|
|
|
|
return LocalUnlock(imcc);
|
|
|
|
return FALSE;
|
2007-09-14 08:03:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetIMCCLockCount(IMM32.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
|
|
|
|
{
|
2021-07-07 01:04:30 +00:00
|
|
|
return LocalFlags(imcc) & LMEM_LOCKCOUNT;
|
2007-09-14 08:03:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmReSizeIMCC(IMM32.@)
|
|
|
|
*/
|
|
|
|
HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
|
|
|
|
{
|
2021-07-07 01:04:30 +00:00
|
|
|
if (!imcc)
|
|
|
|
return NULL;
|
|
|
|
return LocalReAlloc(imcc, size, LHND);
|
2007-09-14 08:03:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetIMCCSize(IMM32.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
|
|
|
|
{
|
2021-07-07 01:04:30 +00:00
|
|
|
if (imcc)
|
|
|
|
return LocalSize(imcc);
|
|
|
|
return 0;
|
2007-09-14 08:03:04 +00:00
|
|
|
}
|
|
|
|
|
2008-04-04 13:20:27 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmGenerateMessage(IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
|
|
|
|
{
|
2021-08-17 23:42:12 +00:00
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
LPTRANSMSG pMsgs, pTrans = NULL, pItem;
|
|
|
|
HWND hWnd;
|
|
|
|
DWORD dwIndex, dwCount, cbTrans;
|
|
|
|
HIMCC hMsgBuf = NULL;
|
|
|
|
BOOL bAnsi;
|
2014-09-28 18:27:58 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
TRACE("(%p)\n", hIMC);
|
|
|
|
|
|
|
|
if (Imm32IsCrossThreadAccess(hIMC))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
pClientImc = ImmLockClientImc(hIMC);
|
|
|
|
if (pClientImc == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
bAnsi = !(pClientImc->dwFlags & CLIENTIMC_WIDE);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
|
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
2014-09-28 18:27:58 +00:00
|
|
|
return FALSE;
|
2021-08-17 23:42:12 +00:00
|
|
|
|
|
|
|
dwCount = pIC->dwNumMsgBuf;
|
|
|
|
if (dwCount == 0)
|
|
|
|
goto Quit;
|
|
|
|
|
|
|
|
hMsgBuf = pIC->hMsgBuf;
|
|
|
|
pMsgs = ImmLockIMCC(hMsgBuf);
|
|
|
|
if (pMsgs == NULL)
|
|
|
|
goto Quit;
|
|
|
|
|
|
|
|
cbTrans = dwCount * sizeof(TRANSMSG);
|
|
|
|
pTrans = Imm32HeapAlloc(0, cbTrans);
|
|
|
|
if (pTrans == NULL)
|
|
|
|
goto Quit;
|
|
|
|
|
|
|
|
RtlCopyMemory(pTrans, pMsgs, cbTrans);
|
|
|
|
|
|
|
|
#ifdef IMP_SUPPORT
|
2021-08-18 10:53:14 +00:00
|
|
|
if (GetWin32ClientInfo()->dwExpWinVer < _WIN32_WINNT_NT4) /* old version (3.x)? */
|
2021-08-17 23:42:12 +00:00
|
|
|
{
|
|
|
|
LANGID LangID = LANGIDFROMLCID(GetSystemDefaultLCID());
|
|
|
|
WORD wLang = PRIMARYLANGID(LangID);
|
|
|
|
|
|
|
|
/* translate the messages if Japanese or Korean */
|
|
|
|
if (wLang == LANG_JAPANESE ||
|
|
|
|
(wLang == LANG_KOREAN && NtUserGetAppImeLevel(pIC->hWnd) == 3))
|
|
|
|
{
|
|
|
|
dwCount = ImpTrans(dwCount, pTrans, hIMC, bAnsi, wLang);
|
|
|
|
}
|
2014-09-28 18:27:58 +00:00
|
|
|
}
|
2021-08-17 23:42:12 +00:00
|
|
|
#endif
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
/* send them */
|
|
|
|
hWnd = pIC->hWnd;
|
|
|
|
pItem = pTrans;
|
|
|
|
for (dwIndex = 0; dwIndex < dwCount; ++dwIndex, ++pItem)
|
2008-04-04 13:20:27 +00:00
|
|
|
{
|
2021-08-17 23:42:12 +00:00
|
|
|
if (bAnsi)
|
|
|
|
SendMessageA(hWnd, pItem->message, pItem->wParam, pItem->lParam);
|
|
|
|
else
|
|
|
|
SendMessageW(hWnd, pItem->message, pItem->wParam, pItem->lParam);
|
|
|
|
}
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
Quit:
|
|
|
|
if (pTrans)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pTrans);
|
|
|
|
if (hMsgBuf)
|
|
|
|
ImmUnlockIMCC(hMsgBuf);
|
|
|
|
pIC->dwNumMsgBuf = 0; /* done */
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
static VOID APIENTRY
|
|
|
|
Imm32PostMessages(HWND hwnd, HIMC hIMC, DWORD dwCount, LPTRANSMSG lpTransMsg)
|
|
|
|
{
|
|
|
|
DWORD dwIndex;
|
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
LPTRANSMSG pNewTransMsg = lpTransMsg, pItem;
|
|
|
|
BOOL bAnsi;
|
2017-12-08 03:14:21 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
pClientImc = ImmLockClientImc(hIMC);
|
|
|
|
if (pClientImc == NULL)
|
|
|
|
return;
|
2017-12-08 03:14:21 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
bAnsi = !(pClientImc->dwFlags & CLIENTIMC_WIDE);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
|
|
|
|
#ifdef IMP_SUPPORT
|
2021-08-18 10:53:14 +00:00
|
|
|
if (GetWin32ClientInfo()->dwExpWinVer < _WIN32_WINNT_NT4) /* old version (3.x)? */
|
2021-08-17 23:42:12 +00:00
|
|
|
{
|
|
|
|
LANGID LangID = LANGIDFROMLCID(GetSystemDefaultLCID());
|
|
|
|
WORD Lang = PRIMARYLANGID(LangID);
|
|
|
|
|
|
|
|
/* translate the messages if Japanese or Korean */
|
|
|
|
if (Lang == LANG_JAPANESE ||
|
|
|
|
(Lang == LANG_KOREAN && NtUserGetAppImeLevel(hwnd) == 3))
|
|
|
|
{
|
|
|
|
DWORD cbTransMsg = dwCount * sizeof(TRANSMSG);
|
|
|
|
pNewTransMsg = Imm32HeapAlloc(0, cbTransMsg);
|
|
|
|
if (pNewTransMsg)
|
|
|
|
{
|
|
|
|
RtlCopyMemory(pNewTransMsg, lpTransMsg, cbTransMsg);
|
|
|
|
dwCount = ImpTrans(dwCount, pNewTransMsg, hIMC, bAnsi, Lang);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pNewTransMsg = lpTransMsg;
|
|
|
|
}
|
|
|
|
}
|
2008-04-04 13:20:27 +00:00
|
|
|
}
|
2021-08-17 23:42:12 +00:00
|
|
|
#endif
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
/* post them */
|
|
|
|
pItem = pNewTransMsg;
|
|
|
|
for (dwIndex = 0; dwIndex < dwCount; ++dwIndex, ++pItem)
|
|
|
|
{
|
|
|
|
if (bAnsi)
|
|
|
|
PostMessageA(hwnd, pItem->message, pItem->wParam, pItem->lParam);
|
|
|
|
else
|
|
|
|
PostMessageW(hwnd, pItem->message, pItem->wParam, pItem->lParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef IMP_SUPPORT
|
|
|
|
if (pNewTransMsg && pNewTransMsg != lpTransMsg)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pNewTransMsg);
|
|
|
|
#endif
|
2008-04-04 13:20:27 +00:00
|
|
|
}
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmTranslateMessage(IMM32.@)
|
|
|
|
* ( Undocumented, call internally and from user32.dll )
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2021-08-17 23:42:12 +00:00
|
|
|
#define MSG_COUNT 0x100
|
|
|
|
BOOL ret = FALSE;
|
|
|
|
INT kret;
|
|
|
|
LPINPUTCONTEXTDX pIC;
|
|
|
|
PIMEDPI pImeDpi = NULL;
|
|
|
|
LPTRANSMSGLIST pList = NULL;
|
|
|
|
LPTRANSMSG pTransMsg;
|
|
|
|
BYTE abKeyState[256];
|
|
|
|
HIMC hIMC;
|
|
|
|
HKL hKL;
|
|
|
|
UINT vk;
|
|
|
|
DWORD dwThreadId, dwCount, cbList;
|
|
|
|
WCHAR wch;
|
|
|
|
WORD wChar;
|
2007-09-14 08:03:04 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
TRACE("(%p, 0x%X, %p, %p)\n", hwnd, msg, wParam, lKeyData);
|
2007-09-14 08:03:04 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
/* filter the message */
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_KEYDOWN: case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-05-08 16:03:10 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
hIMC = ImmGetContext(hwnd);
|
|
|
|
pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
|
|
|
{
|
|
|
|
ImmReleaseContext(hwnd, hIMC);
|
2010-03-07 11:27:14 +00:00
|
|
|
return FALSE;
|
2021-08-17 23:42:12 +00:00
|
|
|
}
|
2008-05-08 16:03:10 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
if (!pIC->bNeedsTrans) /* is translation needed? */
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-08-17 23:42:12 +00:00
|
|
|
/* directly post them */
|
|
|
|
dwCount = pIC->dwNumMsgBuf;
|
|
|
|
if (dwCount == 0)
|
|
|
|
goto Quit;
|
2008-05-08 16:03:10 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
pTransMsg = ImmLockIMCC(pIC->hMsgBuf);
|
|
|
|
if (pTransMsg)
|
|
|
|
{
|
|
|
|
Imm32PostMessages(hwnd, hIMC, dwCount, pTransMsg);
|
|
|
|
ImmUnlockIMCC(pIC->hMsgBuf);
|
|
|
|
ret = TRUE;
|
|
|
|
}
|
|
|
|
pIC->dwNumMsgBuf = 0; /* done */
|
|
|
|
goto Quit;
|
2008-05-06 09:16:21 +00:00
|
|
|
}
|
2021-08-17 23:42:12 +00:00
|
|
|
pIC->bNeedsTrans = FALSE; /* clear the flag */
|
2007-09-14 08:03:04 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
dwThreadId = GetWindowThreadProcessId(hwnd, NULL);
|
|
|
|
hKL = GetKeyboardLayout(dwThreadId);
|
|
|
|
pImeDpi = ImmLockImeDpi(hKL);
|
|
|
|
if (pImeDpi == NULL)
|
|
|
|
goto Quit;
|
2008-05-08 16:03:10 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
if (!GetKeyboardState(abKeyState)) /* get keyboard ON/OFF status */
|
|
|
|
goto Quit;
|
|
|
|
|
|
|
|
/* convert a virtual key if IME_PROP_KBD_CHAR_FIRST */
|
|
|
|
vk = pIC->nVKey;
|
|
|
|
if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST)
|
|
|
|
{
|
|
|
|
if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
|
|
|
|
{
|
|
|
|
wch = 0;
|
|
|
|
kret = ToUnicode(vk, HIWORD(lKeyData), abKeyState, &wch, 1, 0);
|
|
|
|
if (kret == 1)
|
|
|
|
vk = MAKELONG(LOBYTE(vk), wch);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
wChar = 0;
|
|
|
|
kret = ToAsciiEx(vk, HIWORD(lKeyData), abKeyState, &wChar, 0, hKL);
|
|
|
|
if (kret > 0)
|
|
|
|
vk = MAKEWORD(vk, wChar);
|
|
|
|
}
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2008-05-08 16:03:10 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
/* allocate a list */
|
|
|
|
cbList = offsetof(TRANSMSGLIST, TransMsg) + MSG_COUNT * sizeof(TRANSMSG);
|
|
|
|
pList = Imm32HeapAlloc(0, cbList);
|
|
|
|
if (!pList)
|
|
|
|
goto Quit;
|
|
|
|
|
|
|
|
/* use IME conversion engine and convert the list */
|
|
|
|
pList->uMsgCount = MSG_COUNT;
|
|
|
|
kret = pImeDpi->ImeToAsciiEx(vk, HIWORD(lKeyData), abKeyState, pList, 0, hIMC);
|
|
|
|
if (kret <= 0)
|
|
|
|
goto Quit;
|
2007-09-14 08:03:04 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
/* post them */
|
|
|
|
if (kret <= MSG_COUNT)
|
|
|
|
{
|
|
|
|
Imm32PostMessages(hwnd, hIMC, kret, pList->TransMsg);
|
|
|
|
ret = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pTransMsg = ImmLockIMCC(pIC->hMsgBuf);
|
|
|
|
if (pTransMsg == NULL)
|
|
|
|
goto Quit;
|
|
|
|
Imm32PostMessages(hwnd, hIMC, kret, pTransMsg);
|
|
|
|
ImmUnlockIMCC(pIC->hMsgBuf);
|
|
|
|
}
|
2007-09-14 08:03:04 +00:00
|
|
|
|
2021-08-17 23:42:12 +00:00
|
|
|
Quit:
|
|
|
|
if (pList)
|
|
|
|
HeapFree(g_hImm32Heap, 0, pList);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
ImmReleaseContext(hwnd, hIMC);
|
|
|
|
return ret;
|
|
|
|
#undef MSG_COUNT
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmProcessKey(IMM32.@)
|
|
|
|
* ( Undocumented, called from user32.dll )
|
|
|
|
*/
|
2021-08-20 22:22:43 +00:00
|
|
|
DWORD WINAPI ImmProcessKey(HWND hWnd, HKL hKL, UINT vKey, LPARAM lParam, DWORD dwHotKeyID)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2021-08-20 22:22:43 +00:00
|
|
|
DWORD ret = 0;
|
|
|
|
HIMC hIMC;
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
LPINPUTCONTEXTDX pIC;
|
|
|
|
BYTE KeyState[256];
|
|
|
|
UINT vk;
|
|
|
|
BOOL bUseIme = TRUE, bSkipThisKey = FALSE, bLowWordOnly = FALSE;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-20 22:22:43 +00:00
|
|
|
TRACE("(%p, %p, 0x%X, %p, 0x%lX)\n", hWnd, hKL, vKey, lParam, dwHotKeyID);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-20 22:22:43 +00:00
|
|
|
hIMC = ImmGetContext(hWnd);
|
|
|
|
pImeDpi = ImmLockImeDpi(hKL);
|
|
|
|
if (pImeDpi)
|
2017-12-08 03:14:21 +00:00
|
|
|
{
|
2021-08-20 22:22:43 +00:00
|
|
|
pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
|
|
|
|
if (pIC)
|
2017-12-08 03:14:21 +00:00
|
|
|
{
|
2021-08-20 22:22:43 +00:00
|
|
|
if (LOBYTE(vKey) == VK_PACKET &&
|
|
|
|
!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_ACCEPT_WIDE_VKEY))
|
|
|
|
{
|
|
|
|
if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
|
|
|
|
{
|
|
|
|
bLowWordOnly = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bUseIme = FALSE;
|
|
|
|
if (pIC->fOpen)
|
|
|
|
bSkipThisKey = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bUseIme)
|
|
|
|
{
|
|
|
|
if (GetKeyboardState(KeyState))
|
|
|
|
{
|
|
|
|
vk = (bLowWordOnly ? LOWORD(vKey) : vKey);
|
|
|
|
if (pImeDpi->ImeProcessKey(hIMC, vk, lParam, KeyState))
|
|
|
|
{
|
|
|
|
pIC->bNeedsTrans = TRUE;
|
|
|
|
pIC->nVKey = vKey;
|
|
|
|
ret |= IPHK_PROCESSBYIME;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (bSkipThisKey)
|
|
|
|
{
|
|
|
|
ret |= IPHK_SKIPTHISKEY;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImmUnlockIMC(hIMC);
|
2017-12-08 03:14:21 +00:00
|
|
|
}
|
2021-08-20 22:22:43 +00:00
|
|
|
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
2017-12-08 03:14:21 +00:00
|
|
|
}
|
|
|
|
|
2021-08-20 22:22:43 +00:00
|
|
|
if (dwHotKeyID != INVALID_HOTKEY_ID)
|
|
|
|
{
|
|
|
|
if (Imm32ProcessHotKey(hWnd, hIMC, hKL, dwHotKeyID))
|
|
|
|
{
|
|
|
|
if (vKey != VK_KANJI || dwHotKeyID != IME_JHOTKEY_CLOSE_OPEN)
|
|
|
|
ret |= IPHK_HOTKEY;
|
|
|
|
}
|
|
|
|
}
|
2008-05-08 16:03:10 +00:00
|
|
|
|
2021-08-20 22:22:43 +00:00
|
|
|
if (ret & IPHK_PROCESSBYIME)
|
2008-05-08 16:03:10 +00:00
|
|
|
{
|
2021-08-20 22:22:43 +00:00
|
|
|
FIXME("TODO: We have to do something here.\n");
|
2008-05-08 16:03:10 +00:00
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-20 22:22:43 +00:00
|
|
|
ImmReleaseContext(hWnd, hIMC);
|
|
|
|
return ret;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmDisableTextFrameService(IMM32.@)
|
|
|
|
*/
|
2021-07-28 23:21:33 +00:00
|
|
|
BOOL WINAPI ImmDisableTextFrameService(DWORD dwThreadId)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
|
|
|
FIXME("Stub\n");
|
|
|
|
return FALSE;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
2011-12-15 00:40:35 +00:00
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmEnumInputContext(IMM32.@)
|
|
|
|
*/
|
2021-07-28 23:21:33 +00:00
|
|
|
BOOL WINAPI ImmEnumInputContext(DWORD dwThreadId, IMCENUMPROC lpfn, LPARAM lParam)
|
2011-12-15 00:40:35 +00:00
|
|
|
{
|
2021-07-31 06:45:07 +00:00
|
|
|
HIMC *phList;
|
|
|
|
DWORD dwIndex, dwCount;
|
|
|
|
BOOL ret = TRUE;
|
|
|
|
HIMC hIMC;
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%lu, %p, %p)\n", dwThreadId, lpfn, lParam);
|
2021-07-31 06:45:07 +00:00
|
|
|
|
|
|
|
dwCount = Imm32AllocAndBuildHimcList(dwThreadId, &phList);
|
|
|
|
if (!dwCount)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
|
|
|
|
{
|
|
|
|
hIMC = phList[dwIndex];
|
|
|
|
ret = (*lpfn)(hIMC, lParam);
|
|
|
|
if (!ret)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
HeapFree(g_hImm32Heap, 0, phList);
|
|
|
|
return ret;
|
2011-12-15 00:40:35 +00:00
|
|
|
}
|
2012-03-15 21:42:01 +00:00
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetHotKey(IMM32.@)
|
|
|
|
*/
|
2020-08-09 13:41:11 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
ImmGetHotKey(IN DWORD dwHotKey,
|
|
|
|
OUT LPUINT lpuModifiers,
|
|
|
|
OUT LPUINT lpuVKey,
|
|
|
|
OUT LPHKL lphKL)
|
|
|
|
{
|
2021-08-20 22:22:43 +00:00
|
|
|
TRACE("(0x%lX, %p, %p, %p)\n", dwHotKey, lpuModifiers, lpuVKey, lphKL);
|
2020-08-09 13:41:11 +00:00
|
|
|
if (lpuModifiers && lpuVKey)
|
|
|
|
return NtUserGetImeHotKey(dwHotKey, lpuModifiers, lpuVKey, lphKL);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2018-03-15 11:31:05 +00:00
|
|
|
|
|
|
|
/***********************************************************************
|
2018-06-04 02:36:30 +00:00
|
|
|
* ImmDisableLegacyIME(IMM32.@)
|
2018-03-15 11:31:05 +00:00
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmDisableLegacyIME(void)
|
|
|
|
{
|
|
|
|
FIXME("stub\n");
|
|
|
|
return TRUE;
|
|
|
|
}
|
2020-08-08 00:46:13 +00:00
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmSetActiveContext(IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmSetActiveContext(HWND hwnd, HIMC hIMC, BOOL fFlag)
|
|
|
|
{
|
2020-08-09 13:42:17 +00:00
|
|
|
FIXME("(%p, %p, %d): stub\n", hwnd, hIMC, fFlag);
|
2020-08-08 00:46:13 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmSetActiveContextConsoleIME(IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmSetActiveContextConsoleIME(HWND hwnd, BOOL fFlag)
|
|
|
|
{
|
2020-08-09 13:42:17 +00:00
|
|
|
HIMC hIMC;
|
|
|
|
TRACE("(%p, %d)\n", hwnd, fFlag);
|
|
|
|
|
|
|
|
hIMC = ImmGetContext(hwnd);
|
2020-08-08 00:46:13 +00:00
|
|
|
if (hIMC)
|
|
|
|
return ImmSetActiveContext(hwnd, hIMC, fFlag);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2020-08-09 13:49:00 +00:00
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmRegisterClient(IMM32.@)
|
|
|
|
* ( Undocumented, called from user32.dll )
|
|
|
|
*/
|
2021-08-04 00:41:59 +00:00
|
|
|
BOOL WINAPI ImmRegisterClient(PSHAREDINFO ptr, HINSTANCE hMod)
|
2020-08-09 13:49:00 +00:00
|
|
|
{
|
2021-08-04 00:41:59 +00:00
|
|
|
g_SharedInfo = *ptr;
|
|
|
|
g_psi = g_SharedInfo.psi;
|
|
|
|
return Imm32InitInstance(hMod);
|
2020-08-09 13:49:00 +00:00
|
|
|
}
|
2020-08-11 21:03:29 +00:00
|
|
|
|
2021-07-25 02:56:17 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* CtfImmIsTextFrameServiceDisabled(IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI CtfImmIsTextFrameServiceDisabled(VOID)
|
|
|
|
{
|
|
|
|
PTEB pTeb = NtCurrentTeb();
|
|
|
|
if (((PW32CLIENTINFO)pTeb->Win32ClientInfo)->CI_flags & CI_TFSDISABLED)
|
|
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetImeInfoEx (IMM32.@)
|
|
|
|
*/
|
2020-08-11 21:03:29 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx,
|
|
|
|
IMEINFOEXCLASS SearchType,
|
|
|
|
PVOID pvSearchKey)
|
|
|
|
{
|
2021-07-25 02:56:17 +00:00
|
|
|
BOOL bDisabled = FALSE;
|
|
|
|
HKL hKL;
|
|
|
|
PTEB pTeb;
|
|
|
|
|
2020-08-11 21:03:29 +00:00
|
|
|
switch (SearchType)
|
|
|
|
{
|
|
|
|
case ImeInfoExKeyboardLayout:
|
|
|
|
break;
|
|
|
|
|
2021-07-25 02:56:17 +00:00
|
|
|
case ImeInfoExImeWindow:
|
|
|
|
bDisabled = CtfImmIsTextFrameServiceDisabled();
|
|
|
|
SearchType = ImeInfoExKeyboardLayout;
|
2020-08-11 21:03:29 +00:00
|
|
|
break;
|
|
|
|
|
2021-07-25 02:56:17 +00:00
|
|
|
case ImeInfoExImeFileName:
|
|
|
|
StringCchCopyW(pImeInfoEx->wszImeFile, _countof(pImeInfoEx->wszImeFile),
|
|
|
|
pvSearchKey);
|
|
|
|
goto Quit;
|
2020-08-11 21:03:29 +00:00
|
|
|
}
|
2021-07-25 02:56:17 +00:00
|
|
|
|
|
|
|
hKL = *(HKL*)pvSearchKey;
|
|
|
|
pImeInfoEx->hkl = hKL;
|
|
|
|
|
|
|
|
if (!IS_IME_HKL(hKL))
|
|
|
|
{
|
2021-08-04 00:41:59 +00:00
|
|
|
if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
|
2021-07-25 02:56:17 +00:00
|
|
|
{
|
|
|
|
pTeb = NtCurrentTeb();
|
|
|
|
if (((PW32CLIENTINFO)pTeb->Win32ClientInfo)->W32ClientInfo[0] & 2)
|
|
|
|
return FALSE;
|
|
|
|
if (!bDisabled)
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Quit:
|
2021-08-16 06:45:11 +00:00
|
|
|
return NtUserGetImeInfoEx(pImeInfoEx, SearchType);
|
2020-08-11 21:03:29 +00:00
|
|
|
}
|
2021-08-04 00:41:59 +00:00
|
|
|
|
2021-08-20 22:24:12 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmWINNLSGetIMEHotkey (IMM32.@)
|
|
|
|
*/
|
|
|
|
UINT WINAPI ImmWINNLSGetIMEHotkey(HWND hwndIme)
|
|
|
|
{
|
|
|
|
TRACE("(%p)\n", hwndIme);
|
2021-08-23 21:50:39 +00:00
|
|
|
UNREFERENCED_PARAMETER(hwndIme);
|
2021-08-20 22:24:12 +00:00
|
|
|
return 0; /* This is correct. This function of Windows just returns zero. */
|
|
|
|
}
|
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
BOOL WINAPI User32InitializeImmEntryTable(DWORD);
|
|
|
|
|
|
|
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
|
|
|
|
{
|
|
|
|
HKL hKL;
|
2021-08-16 06:33:51 +00:00
|
|
|
HIMC hIMC;
|
2021-08-04 00:41:59 +00:00
|
|
|
PTEB pTeb;
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p, 0x%X, %p)\n", hinstDLL, fdwReason, lpReserved);
|
2021-08-04 00:41:59 +00:00
|
|
|
|
|
|
|
switch (fdwReason)
|
|
|
|
{
|
|
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
//Imm32GenerateRandomSeed(hinstDLL, 1, lpReserved); // Non-sense
|
|
|
|
if (!Imm32InitInstance(hinstDLL))
|
|
|
|
{
|
|
|
|
ERR("Imm32InitInstance failed\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC))
|
|
|
|
{
|
|
|
|
ERR("User32InitializeImmEntryTable failed\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DLL_THREAD_DETACH:
|
|
|
|
if (g_psi == NULL || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
pTeb = NtCurrentTeb();
|
|
|
|
if (pTeb->Win32ThreadInfo == NULL)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
hKL = GetKeyboardLayout(0);
|
2021-08-16 06:33:51 +00:00
|
|
|
// FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
|
2021-08-16 06:45:11 +00:00
|
|
|
hIMC = (HIMC)NtUserGetThreadState(4);
|
2021-08-16 06:33:51 +00:00
|
|
|
Imm32CleanupContext(hIMC, hKL, TRUE);
|
2021-08-04 00:41:59 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
RtlDeleteCriticalSection(&g_csImeDpi);
|
2021-08-23 07:25:21 +00:00
|
|
|
TRACE("imm32.dll is unloaded\n");
|
2021-08-04 00:41:59 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|