You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1143 lines
30 KiB
1143 lines
30 KiB
/**************************************************************************\
|
|
* Module Name: misc.c
|
|
*
|
|
* Copyright (c) 1985 - 1999, Microsoft Corporation
|
|
*
|
|
*
|
|
* History:
|
|
* 03-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#ifdef HIRO_DEBUG
|
|
#define D(x) x
|
|
#else
|
|
#define D(x)
|
|
#endif
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmGetDefaultIMEWnd
|
|
*
|
|
* 03-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
HWND WINAPI ImmGetDefaultIMEWnd(
|
|
HWND hWnd)
|
|
{
|
|
if (!IS_IME_ENABLED()) {
|
|
return NULL;
|
|
}
|
|
if (hWnd == NULL) {
|
|
/*
|
|
* Query default IME window of current thread.
|
|
*/
|
|
return (HWND)NtUserGetThreadState(UserThreadStateDefaultImeWindow);
|
|
}
|
|
|
|
return (HWND)NtUserQueryWindow(hWnd, WindowDefaultImeWindow);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmDisableIME
|
|
*
|
|
* 13-Sep-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
BOOL WINAPI ImmDisableIME(DWORD dwThreadId)
|
|
{
|
|
#ifdef LATER // hiro
|
|
if (dwThreadId == -1) {
|
|
// Unload all IMEs
|
|
RtlEnterCriticalSection(&gcsImeDpi);
|
|
while (gpImeDpi) {
|
|
PIMEDPI pImeDpi = gpImeDpi;
|
|
gpImeDpi = gpImeDpi->pNext;
|
|
UnloadIME(pImeDpi, TRUE);
|
|
ImmLocalFree(pImeDpi);
|
|
}
|
|
RtlLeaveCriticalSection(&gcsImeDpi);
|
|
}
|
|
#endif
|
|
return (BOOL)NtUserDisableThreadIme(dwThreadId);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* ImmIsUIMessageA
|
|
*
|
|
* Filter messages needed for IME window.
|
|
*
|
|
* 03-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
BOOL WINAPI ImmIsUIMessageA(
|
|
HWND hIMEWnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
return ImmIsUIMessageWorker(hIMEWnd, message, wParam, lParam, TRUE);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmIsUIMessageW
|
|
*
|
|
* Filter messages needed for IME window.
|
|
*
|
|
* 29-Feb-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
BOOL WINAPI ImmIsUIMessageW(
|
|
HWND hIMEWnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
return ImmIsUIMessageWorker(hIMEWnd, message, wParam, lParam, FALSE);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmIsUIMessageWorker
|
|
*
|
|
* Worker function of ImmIsUIMessageA/ImmIsUIMessageW.
|
|
*
|
|
* Return: True if message is processed by IME UI.
|
|
* False otherwise.
|
|
*
|
|
* 29-Feb-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
BOOL ImmIsUIMessageWorker(
|
|
HWND hIMEWnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam,
|
|
BOOL fAnsi)
|
|
{
|
|
D(DbgPrint("ImmIsUIMessageWorker(wnd[%08X], msg[%04X], wp[%08X], lp[%08X], Ansi[%d]\n",
|
|
hIMEWnd, message, wParam, lParam, fAnsi));
|
|
|
|
switch (message) {
|
|
case WM_IME_STARTCOMPOSITION:
|
|
case WM_IME_ENDCOMPOSITION:
|
|
case WM_IME_COMPOSITION:
|
|
case WM_IME_SETCONTEXT:
|
|
case WM_IME_COMPOSITIONFULL:
|
|
case WM_IME_SELECT:
|
|
case WM_IME_NOTIFY:
|
|
case WM_IME_SYSTEM:
|
|
|
|
if (!hIMEWnd)
|
|
return TRUE;
|
|
|
|
#if DBG
|
|
if (!IsWindow(hIMEWnd)) {
|
|
RIPMSG1(RIP_WARNING,
|
|
"ImmIsUIMessage: Invalid window handle %x", hIMEWnd);
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
if (fAnsi) {
|
|
SendMessageA(hIMEWnd, message, wParam, lParam);
|
|
}
|
|
else {
|
|
SendMessageW(hIMEWnd, message, wParam, lParam);
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmGenerateMessage
|
|
*
|
|
* Sends message(s) that are stored in hMsgBuf of hImc to hWnd of hImc.
|
|
*
|
|
* 29-Feb-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
BOOL WINAPI ImmGenerateMessage(
|
|
HIMC hImc)
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
PINPUTCONTEXT pInputContext;
|
|
PTRANSMSG pTransMsg;
|
|
INT iNum;
|
|
INT i;
|
|
BOOL fUnicodeImc;
|
|
|
|
if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
|
|
RIPMSG1(RIP_WARNING,
|
|
"ImmGenerateMessage: Invalid input context access %lx.", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
pClientImc = ImmLockClientImc(hImc);
|
|
if (pClientImc == NULL)
|
|
return FALSE;
|
|
|
|
fUnicodeImc = TestICF(pClientImc, IMCF_UNICODE);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (!pInputContext) {
|
|
RIPMSG1(RIP_WARNING, "ImmGenerateMessage: Lock hImc %lx failed.", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
iNum = (int)pInputContext->dwNumMsgBuf;
|
|
|
|
if (iNum && (pTransMsg = (PTRANSMSG)ImmLockIMCC(pInputContext->hMsgBuf))) {
|
|
PTRANSMSG pTransMsgBuf, pTransMsgTemp;
|
|
|
|
pTransMsgBuf = (PTRANSMSG)ImmLocalAlloc(0, iNum * sizeof(TRANSMSG));
|
|
|
|
if (pTransMsgBuf != NULL) {
|
|
|
|
RtlCopyMemory(pTransMsgBuf, pTransMsg, iNum * sizeof(TRANSMSG));
|
|
|
|
if (GetClientInfo()->dwExpWinVer < VER40) {
|
|
/*
|
|
* translate messages for those applications that expect
|
|
* old style IME messages.
|
|
*/
|
|
DWORD dwLangId;
|
|
dwLangId = PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID()));
|
|
if ( (dwLangId == LANG_KOREAN && TransGetLevel(pInputContext->hWnd) == 3) ||
|
|
(dwLangId == LANG_JAPANESE) ) {
|
|
iNum = WINNLSTranslateMessage(iNum,
|
|
pTransMsgBuf,
|
|
hImc,
|
|
!fUnicodeImc,
|
|
dwLangId );
|
|
}
|
|
}
|
|
|
|
pTransMsgTemp = pTransMsgBuf;
|
|
|
|
for (i = 0; i < iNum; i++) {
|
|
if (fUnicodeImc) {
|
|
SendMessageW( pInputContext->hWnd,
|
|
pTransMsgTemp->message,
|
|
pTransMsgTemp->wParam,
|
|
pTransMsgTemp->lParam );
|
|
} else {
|
|
SendMessageW( pInputContext->hWnd,
|
|
pTransMsgTemp->message,
|
|
pTransMsgTemp->wParam,
|
|
pTransMsgTemp->lParam );
|
|
}
|
|
pTransMsgTemp++;
|
|
}
|
|
|
|
ImmLocalFree(pTransMsgBuf);
|
|
}
|
|
|
|
ImmUnlockIMCC(pInputContext->hMsgBuf);
|
|
}
|
|
|
|
/*
|
|
* We should not reallocate the message buffer
|
|
*/
|
|
pInputContext->dwNumMsgBuf = 0L;
|
|
|
|
ImmUnlockIMC(hImc);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
#ifdef CUAS_ENABLE
|
|
BOOL WINAPI CtfImmGenerateMessage(
|
|
HIMC hImc,
|
|
BOOL fSendMsg)
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
PINPUTCONTEXT pInputContext;
|
|
PTRANSMSG pTransMsg;
|
|
INT iNum;
|
|
INT i;
|
|
BOOL fUnicodeImc;
|
|
|
|
if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
|
|
RIPMSG1(RIP_WARNING,
|
|
"ImmGenerateMessage: Invalid input context access %lx.", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
pClientImc = ImmLockClientImc(hImc);
|
|
if (pClientImc == NULL)
|
|
return FALSE;
|
|
|
|
fUnicodeImc = TestICF(pClientImc, IMCF_UNICODE);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (!pInputContext) {
|
|
RIPMSG1(RIP_WARNING, "ImmGenerateMessage: Lock hImc %lx failed.", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
iNum = (int)pInputContext->dwNumMsgBuf;
|
|
|
|
if (iNum && (pTransMsg = (PTRANSMSG)ImmLockIMCC(pInputContext->hMsgBuf))) {
|
|
PTRANSMSG pTransMsgBuf, pTransMsgTemp;
|
|
|
|
pTransMsgBuf = (PTRANSMSG)ImmLocalAlloc(0, iNum * sizeof(TRANSMSG));
|
|
|
|
if (pTransMsgBuf != NULL) {
|
|
|
|
RtlCopyMemory(pTransMsgBuf, pTransMsg, iNum * sizeof(TRANSMSG));
|
|
|
|
pTransMsgTemp = pTransMsgBuf;
|
|
|
|
for (i = 0; i < iNum; i++) {
|
|
if (fSendMsg)
|
|
{
|
|
if (fUnicodeImc) {
|
|
SendMessageW( pInputContext->hWnd,
|
|
pTransMsgTemp->message,
|
|
pTransMsgTemp->wParam,
|
|
pTransMsgTemp->lParam );
|
|
} else {
|
|
SendMessageA( pInputContext->hWnd,
|
|
pTransMsgTemp->message,
|
|
pTransMsgTemp->wParam,
|
|
pTransMsgTemp->lParam );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (fUnicodeImc) {
|
|
PostMessageW( pInputContext->hWnd,
|
|
pTransMsgTemp->message,
|
|
pTransMsgTemp->wParam,
|
|
pTransMsgTemp->lParam );
|
|
} else {
|
|
PostMessageA( pInputContext->hWnd,
|
|
pTransMsgTemp->message,
|
|
pTransMsgTemp->wParam,
|
|
pTransMsgTemp->lParam );
|
|
}
|
|
}
|
|
pTransMsgTemp++;
|
|
}
|
|
|
|
ImmLocalFree(pTransMsgBuf);
|
|
}
|
|
|
|
ImmUnlockIMCC(pInputContext->hMsgBuf);
|
|
}
|
|
|
|
/*
|
|
* We should not reallocate the message buffer
|
|
*/
|
|
pInputContext->dwNumMsgBuf = 0L;
|
|
|
|
ImmUnlockIMC(hImc);
|
|
|
|
return TRUE;
|
|
}
|
|
#endif // CUAS_ENABLE
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmGetVirtualKey
|
|
*
|
|
* Gets the actual virtual key which is preprocessed by an IME.
|
|
*
|
|
* 03-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
UINT WINAPI ImmGetVirtualKey(
|
|
HWND hWnd)
|
|
{
|
|
HIMC hImc;
|
|
PINPUTCONTEXT pInputContext;
|
|
UINT uVirtKey;
|
|
|
|
hImc = ImmGetContext(hWnd);
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (!pInputContext) {
|
|
RIPMSG1(RIP_WARNING, "ImmGetVirtualKey: lock IMC %x failure", hImc);
|
|
return (VK_PROCESSKEY);
|
|
}
|
|
|
|
if (pInputContext->fChgMsg) {
|
|
uVirtKey = pInputContext->uSavedVKey;
|
|
} else {
|
|
uVirtKey = VK_PROCESSKEY;
|
|
}
|
|
|
|
ImmUnlockIMC(hImc);
|
|
return (uVirtKey);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmLockIMC
|
|
*
|
|
* 03-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
PINPUTCONTEXT WINAPI InternalImmLockIMC(
|
|
HIMC hImc,
|
|
BOOL fCanCallImeSelect)
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
PINPUTCONTEXT pInputContext;
|
|
DWORD dwImcThreadId;
|
|
|
|
if ((pClientImc = ImmLockClientImc(hImc)) == NULL)
|
|
return NULL;
|
|
|
|
EnterImcCrit(pClientImc);
|
|
|
|
if (pClientImc->hInputContext == NULL) {
|
|
|
|
#ifdef CUAS_ENABLE
|
|
dwImcThreadId = (DWORD)NtUserQueryInputContext(hImc, InputContextThread);
|
|
#endif // CUAS_ENABLE
|
|
|
|
#ifdef CUAS_ENABLE
|
|
|
|
if (dwImcThreadId == GetCurrentThreadId() &&
|
|
IS_CICERO_ENABLED_AND_NOT16BIT()) {
|
|
/*
|
|
* Cicero IME. Activate Thread Input Manager.
|
|
*/
|
|
PIMEDPI pImeDpi;
|
|
LANGID lg = LOWORD(HandleToUlong(GetKeyboardLayout(0)));
|
|
DWORD dwKL = MAKELONG(lg, lg);
|
|
|
|
pImeDpi = FindOrLoadImeDpi(UlongToHandle(dwKL));
|
|
if (pImeDpi == NULL) {
|
|
RIPMSG0(RIP_WARNING, "InternalImmLockIMC: no pImeDpi entry.");
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Activate TIM
|
|
* For this call, CTFIME's tim->Activate retreive TfClientId value
|
|
* when user32!LoadThreadLayout calls ImmTIMActivate with non-IME hKL.
|
|
* Because tim->Activate calls keyboard layout change and it occurred
|
|
* InternalImmLockIMC via IMS_ACTIVATETHREADLAYOUT.
|
|
* Also this hIMC is used at first time.
|
|
* In this case, this code block calls ImmTIMCreateInputContext and
|
|
* create IC by dim->CreateContext(TfClientId).
|
|
* If this code is disabled, TfClientId is not yet ready and
|
|
* doesn't create IC.
|
|
*/
|
|
CtfImmTIMActivate(UlongToHandle(dwKL));
|
|
}
|
|
}
|
|
#endif // CUAS_ENABLE
|
|
|
|
/*
|
|
* If the owner thread of this hImc does not have
|
|
* default IME window, don't bother to create the
|
|
* INPUTCONTEXT. It could happen when some other
|
|
* thread which call ImmGetContext() to retrieve
|
|
* the associate hImc before the default IME window
|
|
* is created.
|
|
*/
|
|
if ((HWND)NtUserQueryInputContext(hImc,
|
|
InputContextDefaultImeWindow) == NULL) {
|
|
LeaveImcCrit(pClientImc);
|
|
ImmUnlockClientImc(pClientImc);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* This is a delay creation of INPUTCONTEXT structure. Create
|
|
* it now for this hImc.
|
|
*/
|
|
pClientImc->hInputContext = LocalAlloc(LHND, sizeof(INPUTCONTEXT));
|
|
|
|
if (pClientImc->hInputContext == NULL) {
|
|
LeaveImcCrit(pClientImc);
|
|
ImmUnlockClientImc(pClientImc);
|
|
return NULL;
|
|
}
|
|
|
|
#ifndef CUAS_ENABLE
|
|
dwImcThreadId = (DWORD)NtUserQueryInputContext(hImc, InputContextThread);
|
|
#endif // CUAS_ENABLE
|
|
|
|
if (!CreateInputContext(hImc, GetKeyboardLayout(dwImcThreadId), fCanCallImeSelect)) {
|
|
RIPMSG0(RIP_WARNING, "ImmLockIMC: CreateInputContext failed");
|
|
LocalFree(pClientImc->hInputContext);
|
|
pClientImc->hInputContext = NULL;
|
|
LeaveImcCrit(pClientImc);
|
|
ImmUnlockClientImc(pClientImc);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
#ifdef CUAS_ENABLE
|
|
/*
|
|
* Create Cicero Input Context.
|
|
*/
|
|
CtfImmTIMCreateInputContext(hImc);
|
|
#endif // CUAS_ENABLE
|
|
|
|
|
|
LeaveImcCrit(pClientImc);
|
|
|
|
pInputContext = (PINPUTCONTEXT)LocalLock(pClientImc->hInputContext);
|
|
|
|
/*
|
|
* Increment lock count so that the ImmUnlockClientImc() won't
|
|
* free up the pClientImc->hInputContext.
|
|
*/
|
|
InterlockedIncrement(&pClientImc->cLockObj);
|
|
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return pInputContext;
|
|
}
|
|
|
|
PINPUTCONTEXT WINAPI ImmLockIMC(
|
|
HIMC hImc)
|
|
{
|
|
return InternalImmLockIMC(hImc, TRUE);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* ImmUnlockIMC
|
|
*
|
|
* 03-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
BOOL WINAPI ImmUnlockIMC(
|
|
HIMC hImc)
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
|
|
if ((pClientImc = ImmLockClientImc(hImc)) == NULL)
|
|
return FALSE;
|
|
|
|
if (pClientImc->hInputContext != NULL)
|
|
LocalUnlock(pClientImc->hInputContext);
|
|
|
|
/*
|
|
* Decrement lock count so that the ImmUnlockClientImc() can
|
|
* free up the pClientImc->hInputContext if required.
|
|
*/
|
|
InterlockedDecrement(&pClientImc->cLockObj);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmGetIMCLockCount
|
|
*
|
|
* 03-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
DWORD WINAPI ImmGetIMCLockCount(
|
|
HIMC hImc)
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
DWORD dwRet = 0;
|
|
|
|
if ((pClientImc = ImmLockClientImc(hImc)) == NULL)
|
|
return dwRet;
|
|
|
|
if (pClientImc->hInputContext != NULL)
|
|
dwRet = (DWORD)(LocalFlags(pClientImc->hInputContext) & LMEM_LOCKCOUNT);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmCreateIMCC
|
|
*
|
|
* 03-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
HIMCC WINAPI ImmCreateIMCC(
|
|
DWORD dwSize)
|
|
{
|
|
// At least size should be DWORD.
|
|
if (dwSize < sizeof(DWORD)) {
|
|
dwSize = sizeof(DWORD);
|
|
}
|
|
|
|
return (HIMCC)LocalAlloc(LHND, dwSize);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmDestroyIMCC
|
|
*
|
|
* 03-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
HIMCC WINAPI ImmDestroyIMCC(
|
|
HIMCC hIMCC)
|
|
{
|
|
if (hIMCC == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
return (HIMCC)LocalFree(hIMCC);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmLockIMCC
|
|
*
|
|
* 03-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
LPVOID WINAPI ImmLockIMCC(
|
|
HIMCC hIMCC)
|
|
{
|
|
if (hIMCC == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
return LocalLock(hIMCC);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmUnlockIMCC
|
|
*
|
|
* 03-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
BOOL WINAPI ImmUnlockIMCC(
|
|
HIMCC hIMCC)
|
|
{
|
|
if (hIMCC == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
return LocalUnlock(hIMCC);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmGetIMCCLockCount
|
|
*
|
|
* 03-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
DWORD WINAPI ImmGetIMCCLockCount(
|
|
HIMCC hIMCC)
|
|
{
|
|
if (hIMCC == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
return (DWORD)(LocalFlags(hIMCC) & LMEM_LOCKCOUNT);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmReSizeIMCC
|
|
*
|
|
* 03-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
HIMCC WINAPI ImmReSizeIMCC(
|
|
HIMCC hIMCC,
|
|
DWORD dwSize)
|
|
{
|
|
if (hIMCC == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
return (HIMCC)LocalReAlloc(hIMCC, dwSize, LHND);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmGetIMCCSize
|
|
*
|
|
* 03-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
DWORD WINAPI ImmGetIMCCSize(
|
|
HIMCC hIMCC)
|
|
{
|
|
if (hIMCC == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
return (DWORD)LocalSize(hIMCC);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmLocalAlloc
|
|
*
|
|
* 18-Jun-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
LPVOID ImmLocalAlloc(
|
|
DWORD uFlag,
|
|
DWORD uBytes)
|
|
{
|
|
if (pImmHeap == NULL) {
|
|
pImmHeap = RtlProcessHeap();
|
|
if (pImmHeap == NULL) {
|
|
RIPMSG0(RIP_WARNING, "ImmLocalAlloc: NULL pImmHeap!");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return HeapAlloc(pImmHeap, uFlag, uBytes);
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* PtiCurrent
|
|
*
|
|
* Returns the THREADINFO structure for the current thread.
|
|
* LATER: Get DLL_THREAD_ATTACH initialization working right and we won't
|
|
* need this connect code.
|
|
*
|
|
* History:
|
|
* 10-28-90 DavidPe Created.
|
|
* 02-21-96 wkwok Copied from USER32.DLL
|
|
\***************************************************************************/
|
|
|
|
PTHREADINFO PtiCurrent(VOID)
|
|
{
|
|
ConnectIfNecessary(0);
|
|
return (PTHREADINFO)NtCurrentTebShared()->Win32ThreadInfo;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* TestInputContextProcess
|
|
*
|
|
* 02-21-96 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
BOOL TestInputContextProcess(
|
|
PIMC pImc)
|
|
{
|
|
/*
|
|
* If the threads are the same, don't bother going to the kernel
|
|
* to get the input context's process id.
|
|
*/
|
|
if (GETPTI(pImc) == PtiCurrent()) {
|
|
return TRUE;
|
|
}
|
|
|
|
return (GetInputContextProcess(PtoH(pImc)) == GETPROCESSID());
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* TestWindowProcess
|
|
*
|
|
* 11-14-94 JimA Created.
|
|
* 02-29-96 wkwok Copied from USER32.DLL
|
|
\**************************************************************************/
|
|
|
|
BOOL TestWindowProcess(
|
|
PWND pwnd)
|
|
{
|
|
/*
|
|
* If the threads are the same, don't bother going to the kernel
|
|
* to get the window's process id.
|
|
*/
|
|
if (GETPTI(pwnd) == PtiCurrent()) {
|
|
return TRUE;
|
|
}
|
|
|
|
return (GetWindowProcess(HW(pwnd)) == GETPROCESSID());
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* GetKeyboardLayoutCP
|
|
*
|
|
* 12-Mar-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
static LCID CachedLCID = 0;
|
|
static UINT CachedCP = CP_ACP;
|
|
|
|
UINT GetKeyboardLayoutCP(
|
|
HKL hKL)
|
|
{
|
|
#define LOCALE_CPDATA 7
|
|
WCHAR wszCodePage[LOCALE_CPDATA];
|
|
LCID lcid;
|
|
|
|
lcid = MAKELCID(LOWORD(HandleToUlong(hKL)), SORT_DEFAULT);
|
|
|
|
if (lcid == CachedLCID)
|
|
return CachedCP;
|
|
|
|
if (!GetLocaleInfoW(lcid, LOCALE_IDEFAULTANSICODEPAGE,
|
|
wszCodePage, LOCALE_CPDATA))
|
|
return CP_ACP;
|
|
|
|
CachedLCID = lcid;
|
|
CachedCP = (UINT)wcstol(wszCodePage, NULL, 10);
|
|
|
|
return CachedCP;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* GetKeyboardLayoutCP
|
|
*
|
|
* 12-Mar-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
UINT GetThreadKeyboardLayoutCP(
|
|
DWORD dwThreadId)
|
|
{
|
|
HKL hKL;
|
|
|
|
hKL = GetKeyboardLayout(dwThreadId);
|
|
|
|
return GetKeyboardLayoutCP(hKL);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmLockClientImc
|
|
*
|
|
* 13-Mar-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
PCLIENTIMC WINAPI ImmLockClientImc(
|
|
HIMC hImc)
|
|
{
|
|
PIMC pImc;
|
|
PCLIENTIMC pClientImc;
|
|
|
|
if (hImc == NULL_HIMC)
|
|
return NULL;
|
|
|
|
pImc = HMValidateHandle((HANDLE)hImc, TYPE_INPUTCONTEXT);
|
|
|
|
/*
|
|
* Cannot access input context from other process.
|
|
*/
|
|
if (pImc == NULL || !TestInputContextProcess(pImc))
|
|
return NULL;
|
|
|
|
pClientImc = (PCLIENTIMC)pImc->dwClientImcData;
|
|
|
|
if (pClientImc == NULL) {
|
|
/*
|
|
* We delay the creation of client side per-thread default Imc.
|
|
* Now, this is the time to create it.
|
|
*/
|
|
pClientImc = ImmLocalAlloc(HEAP_ZERO_MEMORY, sizeof(CLIENTIMC));
|
|
if (pClientImc == NULL)
|
|
return NULL;
|
|
|
|
InitImcCrit(pClientImc);
|
|
pClientImc->dwImeCompatFlags = (DWORD)NtUserGetThreadState(UserThreadStateImeCompatFlags);
|
|
|
|
/*
|
|
* Update the kernel side input context.
|
|
*/
|
|
if (!NtUserUpdateInputContext(hImc,
|
|
UpdateClientInputContext, (ULONG_PTR)pClientImc)) {
|
|
ImmLocalFree(pClientImc);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Marks with default input context signature.
|
|
*/
|
|
SetICF(pClientImc, IMCF_DEFAULTIMC);
|
|
}
|
|
else if (TestICF(pClientImc, IMCF_INDESTROY)) {
|
|
/*
|
|
* Cannot access destroyed input context.
|
|
*/
|
|
return NULL;
|
|
}
|
|
|
|
InterlockedIncrement(&pClientImc->cLockObj);
|
|
|
|
return pClientImc;
|
|
}
|
|
|
|
|
|
VOID WINAPI ImmUnlockClientImc(
|
|
PCLIENTIMC pClientImc)
|
|
{
|
|
if (InterlockedDecrement(&pClientImc->cLockObj) == 0) {
|
|
if (TestICF(pClientImc, IMCF_INDESTROY)) {
|
|
if (pClientImc->hInputContext != NULL)
|
|
LocalFree(pClientImc->hInputContext);
|
|
|
|
DeleteImcCrit(pClientImc);
|
|
ImmLocalFree(pClientImc);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* ImmGetImeDpi
|
|
*
|
|
* 08-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
PIMEDPI WINAPI ImmGetImeDpi(
|
|
HKL hKL)
|
|
{
|
|
PIMEDPI pImeDpi;
|
|
|
|
RtlEnterCriticalSection(&gcsImeDpi);
|
|
|
|
pImeDpi = gpImeDpi;
|
|
|
|
while (pImeDpi != NULL && pImeDpi->hKL != hKL)
|
|
pImeDpi = pImeDpi->pNext;
|
|
|
|
RtlLeaveCriticalSection(&gcsImeDpi);
|
|
|
|
return (PIMEDPI)pImeDpi;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmLockImeDpi
|
|
*
|
|
* 08-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
PIMEDPI WINAPI ImmLockImeDpi(
|
|
HKL hKL)
|
|
{
|
|
PIMEDPI pImeDpi;
|
|
|
|
RtlEnterCriticalSection(&gcsImeDpi);
|
|
|
|
pImeDpi = gpImeDpi;
|
|
|
|
while (pImeDpi != NULL && pImeDpi->hKL != hKL)
|
|
pImeDpi = pImeDpi->pNext;
|
|
|
|
if (pImeDpi != NULL) {
|
|
if (pImeDpi->dwFlag & IMEDPI_UNLOADED)
|
|
pImeDpi = NULL;
|
|
else
|
|
pImeDpi->cLock++;
|
|
}
|
|
|
|
RtlLeaveCriticalSection(&gcsImeDpi);
|
|
|
|
return (PIMEDPI)pImeDpi;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmUnlockImeDpi
|
|
*
|
|
* 03-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
VOID WINAPI ImmUnlockImeDpi(
|
|
PIMEDPI pImeDpi)
|
|
{
|
|
PIMEDPI pImeDpiT;
|
|
|
|
if (pImeDpi == NULL)
|
|
return;
|
|
|
|
RtlEnterCriticalSection(&gcsImeDpi);
|
|
|
|
if (--pImeDpi->cLock == 0) {
|
|
|
|
if ((pImeDpi->dwFlag & IMEDPI_UNLOADED) ||
|
|
((pImeDpi->dwFlag & IMEDPI_UNLOCKUNLOAD) &&
|
|
(pImeDpi->ImeInfo.fdwProperty & IME_PROP_END_UNLOAD)))
|
|
{
|
|
/*
|
|
* Unlink it.
|
|
*/
|
|
if (gpImeDpi == pImeDpi) {
|
|
gpImeDpi = pImeDpi->pNext;
|
|
}
|
|
else {
|
|
pImeDpiT = gpImeDpi;
|
|
|
|
while (pImeDpiT != NULL && pImeDpiT->pNext != pImeDpi)
|
|
pImeDpiT = pImeDpiT->pNext;
|
|
|
|
if (pImeDpiT != NULL)
|
|
pImeDpiT->pNext = pImeDpi->pNext;
|
|
}
|
|
|
|
/*
|
|
* Unload the IME DLL.
|
|
*/
|
|
UnloadIME(pImeDpi, TRUE);
|
|
ImmLocalFree(pImeDpi);
|
|
}
|
|
}
|
|
|
|
RtlLeaveCriticalSection(&gcsImeDpi);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmGetImeInfoEx
|
|
*
|
|
* 03-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
BOOL WINAPI ImmGetImeInfoEx(
|
|
PIMEINFOEX piiex,
|
|
IMEINFOEXCLASS SearchType,
|
|
PVOID pvSearchKey)
|
|
{
|
|
#if defined(CUAS_ENABLE)
|
|
BOOL fCUAS_OFF = FALSE;
|
|
#endif
|
|
ImmAssert(piiex != NULL && pvSearchKey != NULL);
|
|
|
|
switch (SearchType) {
|
|
#if defined(CUAS_ENABLE)
|
|
case ImeInfoExKeyboardLayoutWithCUAS:
|
|
fCUAS_OFF = CtfImmIsTextFrameServiceDisabled();
|
|
SearchType = ImeInfoExKeyboardLayout;
|
|
#endif
|
|
case ImeInfoExKeyboardLayout:
|
|
piiex->hkl = *((HKL *)pvSearchKey);
|
|
/*
|
|
* Quick return for non-IME based keyboard layout
|
|
*/
|
|
#if !defined(CUAS_ENABLE)
|
|
if (!IS_IME_KBDLAYOUT(piiex->hkl))
|
|
return FALSE;
|
|
#else
|
|
if (! IS_IME_KBDLAYOUT(piiex->hkl) &&
|
|
(! IS_CICERO_ENABLED_AND_NOT16BIT() || fCUAS_OFF))
|
|
return FALSE;
|
|
#endif
|
|
break;
|
|
|
|
case ImeInfoExImeFileName:
|
|
|
|
wcsncpy(piiex->wszImeFile, (PWSTR)pvSearchKey, IM_FILE_SIZE-1);
|
|
piiex->wszImeFile[IM_FILE_SIZE - 1] = L'\0';
|
|
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return NtUserGetImeInfoEx(piiex, SearchType);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* ImmGetAppCompatFlags
|
|
*
|
|
* private function
|
|
* returns Win95 compatible IME Compatibility flags
|
|
*
|
|
* 02-July-1996 takaok Created
|
|
\**************************************************************************/
|
|
DWORD ImmGetAppCompatFlags( HIMC hImc )
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
DWORD dwImeCompat = 0;
|
|
|
|
pClientImc = ImmLockClientImc( hImc );
|
|
if ( pClientImc != NULL ) {
|
|
dwImeCompat = pClientImc->dwImeCompatFlags;
|
|
ImmUnlockClientImc( pClientImc );
|
|
}
|
|
#ifdef CUAS_ENABLE
|
|
dwImeCompat |= g_aimm_compat_flags;
|
|
#endif // CUAS_ENABLE
|
|
return dwImeCompat;
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* ImmPtInRect
|
|
*
|
|
* private function
|
|
*
|
|
* 02-July-1997 hiroyama Created
|
|
\**************************************************************************/
|
|
|
|
BOOL ImmPtInRect(
|
|
int left,
|
|
int top,
|
|
int width,
|
|
int height,
|
|
LPPOINT lppt)
|
|
{
|
|
return (lppt->x >= left && lppt->x < (left + width) &&
|
|
lppt->y >= top && lppt->y < (top + height));
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmSystemHandler
|
|
*
|
|
* private function
|
|
*
|
|
* IMM bulk helper to handle WM_IME_SYSTEM message
|
|
*
|
|
* 02-July-1997 hiroyama Created
|
|
\**************************************************************************/
|
|
|
|
LRESULT ImmSystemHandler(
|
|
HIMC hImc,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
LRESULT lRet = 0;
|
|
|
|
switch (wParam) {
|
|
case IMS_SENDNOTIFICATION:
|
|
ImmSendNotification((BOOL)lParam);
|
|
break;
|
|
case IMS_FINALIZE_COMPSTR:
|
|
ImmNotifyIME(hImc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
|
|
break;
|
|
#ifdef CUAS_ENABLE
|
|
case IMS_SETLANGBAND:
|
|
case IMS_RESETLANGBAND:
|
|
lRet = CtfImmSetLangBand((HWND)lParam, wParam == IMS_SETLANGBAND ? TRUE : FALSE);
|
|
break;
|
|
#endif // CUAS_ENABLE
|
|
}
|
|
|
|
return lRet;
|
|
}
|