mirror of https://github.com/lianthony/NT4.0
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.
884 lines
24 KiB
884 lines
24 KiB
/**************************************************************************\
|
|
* Module Name: context.c
|
|
*
|
|
* Copyright (c) Microsoft Corp. 1995 All Rights Reserved
|
|
*
|
|
* Context management routines for imm32 dll
|
|
*
|
|
* History:
|
|
* 03-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#define IMCC_ALLOC_TOOLARGE 0x1000
|
|
|
|
|
|
/***************************************************************************\
|
|
* ImmCreateDefaultContext (Internal: Callback from Win32K.SYS)
|
|
*
|
|
* Create client side input context sturcture for a given hImc
|
|
*
|
|
* History:
|
|
* 31-Jan-1996 wkwok Created
|
|
\***************************************************************************/
|
|
|
|
BOOL WINAPI ImmCreateDefaultContext(
|
|
HIMC hImc)
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
|
|
/*
|
|
* ImmLockClientImc() will create client side Imc.
|
|
*/
|
|
pClientImc = ImmLockClientImc(hImc);
|
|
if (pClientImc != NULL) {
|
|
/*
|
|
* Marks with default input context signature.
|
|
*/
|
|
SetICF(pClientImc, IMCF_DEFAULTIMC);
|
|
ImmUnlockClientImc(pClientImc);
|
|
}
|
|
|
|
/*
|
|
* Load up the IME DLL of current keyboard layout.
|
|
*/
|
|
ImmLoadIME(GetKeyboardLayout(0));
|
|
|
|
return (pClientImc != NULL);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmCreateContext
|
|
*
|
|
* Creates and initializes an input context.
|
|
*
|
|
* 17-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
HIMC WINAPI ImmCreateContext(void)
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
HIMC hImc = NULL_HIMC;
|
|
|
|
pClientImc = ImmLocalAlloc(HEAP_ZERO_MEMORY, sizeof(CLIENTIMC));
|
|
|
|
if (pClientImc != NULL) {
|
|
|
|
hImc = NtUserCreateInputContext((DWORD)pClientImc);
|
|
if (hImc == NULL_HIMC) {
|
|
ImmLocalFree(pClientImc);
|
|
return NULL_HIMC;
|
|
}
|
|
|
|
InitImcCrit(pClientImc);
|
|
pClientImc->hImc = hImc;
|
|
}
|
|
|
|
return hImc;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmDestroyContext
|
|
*
|
|
* Destroys an input context.
|
|
*
|
|
* 17-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
BOOL WINAPI ImmDestroyContext(
|
|
HIMC hImc)
|
|
{
|
|
return DestroyInputContext(hImc, GetKeyboardLayout(0));
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmAssociateContext
|
|
*
|
|
* Associates an input context to the specified window handle.
|
|
*
|
|
* 17-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
HIMC WINAPI ImmAssociateContext(
|
|
HWND hWnd,
|
|
HIMC hImc)
|
|
{
|
|
PWND pWnd;
|
|
HIMC hPrevImc, hDefImc;
|
|
PINPUTCONTEXT pInputContext;
|
|
|
|
if ((pWnd = ValidateHwnd(hWnd)) == (PWND)NULL) {
|
|
RIPMSG1(RIP_WARNING,
|
|
"ImmAssociateContext: invalid window handle %x", hWnd);
|
|
return NULL_HIMC;
|
|
}
|
|
|
|
/*
|
|
* associate to the same input context, do nothing.
|
|
*/
|
|
if (pWnd->hImc == hImc)
|
|
return hImc;
|
|
|
|
hPrevImc = NtUserAssociateInputContext(hWnd, hImc);
|
|
if (hPrevImc == NULL_HIMC)
|
|
return hPrevImc;
|
|
|
|
hDefImc = (HIMC)NtUserQueryWindow(hWnd, WindowDefaultInputContext);
|
|
|
|
/*
|
|
* Update the hPrevImc if it is not the default IMC.
|
|
*/
|
|
if (hDefImc != hPrevImc) {
|
|
pInputContext = ImmLockIMC(hPrevImc);
|
|
if (pInputContext != NULL) {
|
|
pInputContext->hWnd = NULL;
|
|
ImmUnlockIMC(hPrevImc);
|
|
}
|
|
}
|
|
|
|
if (GetFocus() == hWnd) {
|
|
ImmSetActiveContext(hWnd, hPrevImc, FALSE);
|
|
ImmSetActiveContext(hWnd, hImc, TRUE);
|
|
}
|
|
|
|
return hPrevImc;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmGetContext
|
|
*
|
|
* Retrieves the input context that is associated to the given window.
|
|
*
|
|
* 17-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
HIMC WINAPI ImmGetContext(
|
|
HWND hWnd)
|
|
{
|
|
PWND pwnd;
|
|
|
|
if ((pwnd = ValidateHwnd(hWnd)) == (PWND)NULL) {
|
|
RIPMSG1(RIP_WARNING,
|
|
"ImmGetContext: invalid window handle %x", hWnd);
|
|
return NULL_HIMC;
|
|
}
|
|
|
|
/*
|
|
* Don't allow other process to access input context
|
|
*/
|
|
if (!TestWindowProcess(pwnd)) {
|
|
RIPMSG0(RIP_WARNING,
|
|
"ImmGetContext: can not get input context of other process");
|
|
return NULL_HIMC;
|
|
}
|
|
|
|
return pwnd->hImc;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmGetSaveContext
|
|
*
|
|
* Retrieves the input context that is associated to the given window.
|
|
*
|
|
* 15-Mar-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
HIMC ImmGetSaveContext(
|
|
HWND hWnd,
|
|
DWORD dwFlag)
|
|
{
|
|
HIMC hRetImc;
|
|
PCLIENTIMC pClientImc;
|
|
|
|
if (hWnd == NULL) {
|
|
/*
|
|
* Retrieves the default input context of current thread.
|
|
*/
|
|
hRetImc = NtUserGetThreadState(UserThreadStateDefaultInputContext);
|
|
}
|
|
else {
|
|
/*
|
|
* Retrieves the input context associated to the given window.
|
|
*/
|
|
hRetImc = ImmGetContext(hWnd);
|
|
if (hRetImc == NULL_HIMC && (dwFlag & IGSC_DEFIMCFALLBACK)) {
|
|
/*
|
|
* hWnd associated with NULL input context, retrieves the
|
|
* default input context of the hWnd's creator thread.
|
|
*/
|
|
hRetImc = (HIMC)NtUserQueryWindow(hWnd, WindowDefaultInputContext);
|
|
}
|
|
}
|
|
|
|
pClientImc = ImmLockClientImc(hRetImc);
|
|
if (pClientImc == NULL)
|
|
return NULL_HIMC;
|
|
|
|
if ((dwFlag & IGSC_WINNLSCHECK) && TestICF(pClientImc, IMCF_WINNLSDISABLE))
|
|
hRetImc = NULL_HIMC;
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return hRetImc;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmReleaseContext
|
|
*
|
|
* Releases the input context retrieved by ImmGetContext().
|
|
*
|
|
* 17-Jan-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
BOOL WINAPI ImmReleaseContext(
|
|
HWND hWnd,
|
|
HIMC hImc)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* ImmSetActiveContext
|
|
*
|
|
* 15-Mar-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
BOOL ImmSetActiveContext(
|
|
HWND hWnd,
|
|
HIMC hImc,
|
|
BOOL fActivate)
|
|
{
|
|
PCLIENTIMC pClientImc;
|
|
PINPUTCONTEXT pInputContext;
|
|
PIMEDPI pImeDpi;
|
|
DWORD dwISC;
|
|
HIMC hSaveImc;
|
|
HWND hDefImeWnd;
|
|
#ifdef DEBUG
|
|
PWND pWnd = ValidateHwnd(hWnd);
|
|
|
|
if (pWnd != NULL && GETPTI(pWnd) != PtiCurrent()) {
|
|
RIPMSG1(RIP_WARNING, "hWnd (=%lx) is not of current thread.", hWnd);
|
|
}
|
|
#endif
|
|
|
|
dwISC = ISC_SHOWUIALL;
|
|
|
|
pClientImc = ImmLockClientImc(hImc);
|
|
|
|
if (!fActivate) {
|
|
if (pClientImc != NULL)
|
|
ClrICF(pClientImc, IMCF_ACTIVE);
|
|
goto NotifySetActive;
|
|
}
|
|
|
|
if (hImc == NULL_HIMC) {
|
|
hSaveImc = ImmGetSaveContext(hWnd, 0);
|
|
pInputContext = ImmLockIMC(hSaveImc);
|
|
if (pInputContext != NULL) {
|
|
pInputContext->hWnd = hWnd;
|
|
ImmUnlockIMC(hSaveImc);
|
|
}
|
|
goto NotifySetActive;
|
|
}
|
|
|
|
/*
|
|
* Non-NULL input context, window handle have to be updated.
|
|
*/
|
|
if (pClientImc == NULL)
|
|
return FALSE;
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (pInputContext == NULL) {
|
|
ImmUnlockClientImc(pClientImc);
|
|
return FALSE;
|
|
}
|
|
|
|
pInputContext->hWnd = hWnd;
|
|
SetICF(pClientImc, IMCF_ACTIVE);
|
|
|
|
#ifdef LATER
|
|
// Do uNumLangVKey checking later
|
|
#endif
|
|
|
|
if (pInputContext->fdw31Compat & F31COMPAT_MCWHIDDEN)
|
|
dwISC = ISC_SHOWUIALL - ISC_SHOWUICOMPOSITIONWINDOW;
|
|
|
|
ImmUnlockIMC(hImc);
|
|
|
|
NotifySetActive:
|
|
|
|
if (hImc != NULL_HIMC) {
|
|
pImeDpi = ImmLockImeDpi(GetKeyboardLayout(0));
|
|
if (pImeDpi != NULL) {
|
|
(*pImeDpi->pfn.ImeSetActiveContext)(hImc, fActivate);
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Notify UI
|
|
*/
|
|
if (IsWindow(hWnd)) {
|
|
SendMessage(hWnd, WM_IME_SETCONTEXT, fActivate, dwISC);
|
|
}
|
|
else if (!fActivate) {
|
|
/*
|
|
* Because hWnd is not there (maybe destroyed), we send
|
|
* WM_IME_SETCONTEXT to the default IME window.
|
|
*/
|
|
if ((hDefImeWnd = ImmGetDefaultIMEWnd(NULL)) != NULL) {
|
|
SendMessage(hDefImeWnd, WM_IME_SETCONTEXT, fActivate, dwISC);
|
|
}
|
|
else {
|
|
RIPMSG0(RIP_WARNING,
|
|
"ImmSetActiveContext: can't send WM_IME_SETCONTEXT(FALSE).");
|
|
}
|
|
}
|
|
#ifdef DEBUG
|
|
else {
|
|
RIPMSG0(RIP_WARNING,
|
|
"ImmSetActiveContext: can't send WM_IME_SETCONTEXT(TRUE).");
|
|
}
|
|
#endif
|
|
|
|
#ifdef LATER
|
|
// Implements ProcessIMCEvent() later.
|
|
#endif
|
|
|
|
if (pClientImc != NULL)
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* CreateInputContext
|
|
*
|
|
* 20-Feb-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
BOOL CreateInputContext(
|
|
HIMC hImc,
|
|
HKL hKL)
|
|
{
|
|
PIMEDPI pImeDpi;
|
|
PCLIENTIMC pClientImc;
|
|
DWORD dwPrivateDataSize;
|
|
DWORD fdwInitConvMode = 0; // do it later
|
|
BOOL fInitOpen = FALSE; // do it later
|
|
PINPUTCONTEXT pInputContext;
|
|
PCOMPOSITIONSTRING pCompStr;
|
|
PCANDIDATEINFO pCandInfo;
|
|
PGUIDELINE pGuideLine;
|
|
int i;
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (!pInputContext) {
|
|
RIPMSG1(RIP_WARNING, "CreateContext: Lock hIMC %x failure", hImc);
|
|
goto CrIMCLockErrOut;
|
|
}
|
|
|
|
/*
|
|
* Initialize the member of INPUTCONTEXT
|
|
*/
|
|
pInputContext->hCompStr = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
|
|
if (!pInputContext->hCompStr) {
|
|
RIPMSG0(RIP_WARNING, "CreateContext: Create hCompStr failure");
|
|
goto CrIMCUnlockIMC;
|
|
}
|
|
|
|
pCompStr = (PCOMPOSITIONSTRING)ImmLockIMCC(pInputContext->hCompStr);
|
|
if (!pCompStr) {
|
|
RIPMSG1(RIP_WARNING,
|
|
"CreateContext: Lock hCompStr %x failure", pInputContext->hCompStr);
|
|
goto CrIMCFreeCompStr;
|
|
}
|
|
|
|
pCompStr->dwSize = sizeof(COMPOSITIONSTRING);
|
|
ImmUnlockIMCC(pInputContext->hCompStr);
|
|
|
|
pInputContext->hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
|
|
if (!pInputContext->hCandInfo) {
|
|
RIPMSG0(RIP_WARNING, "CreateContext: Create hCandInfo failure");
|
|
goto CrIMCFreeCompStr;
|
|
}
|
|
|
|
pCandInfo = (PCANDIDATEINFO)ImmLockIMCC(pInputContext->hCandInfo);
|
|
if (!pCandInfo) {
|
|
RIPMSG1(RIP_WARNING,
|
|
"CreateContext: Lock hCandInfo %x failure", pInputContext->hCandInfo);
|
|
goto CrIMCFreeCandInfo;
|
|
}
|
|
|
|
pCandInfo->dwSize = sizeof(CANDIDATEINFO);
|
|
ImmUnlockIMCC(pInputContext->hCandInfo);
|
|
|
|
pInputContext->hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
|
|
if (!pInputContext->hGuideLine) {
|
|
RIPMSG0(RIP_WARNING, "CreateContext: Create hGuideLine failure");
|
|
goto CrIMCFreeCandInfo;
|
|
}
|
|
|
|
pGuideLine = (PGUIDELINE)ImmLockIMCC(pInputContext->hGuideLine);
|
|
if (!pGuideLine) {
|
|
RIPMSG1(RIP_WARNING,
|
|
"CreateContext: Lock hGuideLine %x failure", pInputContext->hGuideLine);
|
|
goto CrIMCFreeGuideLine;
|
|
}
|
|
|
|
pGuideLine->dwSize = sizeof(GUIDELINE);
|
|
ImmUnlockIMCC(pInputContext->hGuideLine);
|
|
|
|
pInputContext->hMsgBuf = ImmCreateIMCC(sizeof(UINT));
|
|
if (!pInputContext->hMsgBuf) {
|
|
RIPMSG0(RIP_WARNING, "CreateContext: Create hMsgBuf failure");
|
|
goto CrIMCFreeGuideLine;
|
|
}
|
|
|
|
pInputContext->dwNumMsgBuf = 0;
|
|
pInputContext->fOpen = fInitOpen;
|
|
pInputContext->fdwConversion = fdwInitConvMode;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
pInputContext->cfCandForm[i].dwIndex = (DWORD)(-1);
|
|
}
|
|
|
|
pImeDpi = ImmLockImeDpi(hKL);
|
|
if (pImeDpi != NULL) {
|
|
if ((pClientImc = ImmLockClientImc(hImc)) == NULL) {
|
|
RIPMSG0(RIP_WARNING, "CreateContext: ImmLockClientImc() failure");
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
goto CrIMCFreeMsgBuf;
|
|
}
|
|
|
|
/*
|
|
* Unicode based IME expects an Uncode based input context.
|
|
*/
|
|
if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
|
|
SetICF(pClientImc, IMCF_UNICODE);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
dwPrivateDataSize = pImeDpi->ImeInfo.dwPrivateDataSize;
|
|
}
|
|
else {
|
|
dwPrivateDataSize = sizeof(UINT);
|
|
}
|
|
|
|
pInputContext->hPrivate = ImmCreateIMCC(dwPrivateDataSize);
|
|
if (!pInputContext->hPrivate) {
|
|
RIPMSG0(RIP_WARNING, "CreateContext: Create hPrivate failure");
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
goto CrIMCFreeMsgBuf;
|
|
}
|
|
|
|
if (pImeDpi != NULL) {
|
|
(*pImeDpi->pfn.ImeSelect)(hImc, TRUE);
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
}
|
|
|
|
ImmUnlockIMC(hImc);
|
|
return TRUE;
|
|
|
|
/*
|
|
* context failure case
|
|
*/
|
|
CrIMCFreeMsgBuf:
|
|
ImmDestroyIMCC(pInputContext->hMsgBuf);
|
|
CrIMCFreeGuideLine:
|
|
ImmDestroyIMCC(pInputContext->hGuideLine);
|
|
CrIMCFreeCandInfo:
|
|
ImmDestroyIMCC(pInputContext->hCandInfo);
|
|
CrIMCFreeCompStr:
|
|
ImmDestroyIMCC(pInputContext->hCompStr);
|
|
CrIMCUnlockIMC:
|
|
ImmUnlockIMC(hImc);
|
|
CrIMCLockErrOut:
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* DestroyInputContext
|
|
*
|
|
* 20-Feb-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
BOOL DestroyInputContext(
|
|
HIMC hImc,
|
|
HKL hKL)
|
|
{
|
|
PINPUTCONTEXT pInputContext;
|
|
PIMEDPI pImeDpi;
|
|
PIMC pImc;
|
|
PCLIENTIMC pClientImc;
|
|
|
|
if (hImc == NULL_HIMC)
|
|
return FALSE;
|
|
|
|
pImc = HMValidateHandle((HANDLE)hImc, TYPE_INPUTCONTEXT);
|
|
|
|
/*
|
|
* Cannot destroy input context from other thread.
|
|
*/
|
|
if (pImc == NULL || GETPTI(pImc) != PtiCurrent())
|
|
return FALSE;
|
|
|
|
/*
|
|
* We are destroying this hImc and we don't bother
|
|
* to lock its pClientImc.
|
|
*/
|
|
pClientImc = (PCLIENTIMC)pImc->dwClientImcData;
|
|
if (pClientImc == NULL) {
|
|
/*
|
|
* Client side Imc has not been initialzed yet.
|
|
* We simply destroy this input context from kernel.
|
|
*/
|
|
return NtUserDestroyInputContext(hImc);
|
|
}
|
|
|
|
if (TestICF(pClientImc, IMCF_DEFAULTIMC)) {
|
|
/*
|
|
* Cannot destroy default input context.
|
|
*/
|
|
return FALSE;
|
|
}
|
|
|
|
if (TestICF(pClientImc, IMCF_INDESTROY)) {
|
|
/*
|
|
* This hImc is being destroyed. Returns as success.
|
|
*/
|
|
return TRUE;
|
|
}
|
|
|
|
pInputContext = ImmLockIMC(hImc);
|
|
if (!pInputContext) {
|
|
RIPMSG1(RIP_WARNING, "DestroyContext: Lock hImc %x failure", hImc);
|
|
return FALSE;
|
|
}
|
|
|
|
pImeDpi = ImmLockImeDpi(hKL);
|
|
if (pImeDpi != NULL) {
|
|
(*pImeDpi->pfn.ImeSelect)(hImc, FALSE);
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
}
|
|
|
|
SetICF(pClientImc, IMCF_INDESTROY);
|
|
|
|
ImmDestroyIMCC(pInputContext->hPrivate);
|
|
ImmDestroyIMCC(pInputContext->hMsgBuf);
|
|
ImmDestroyIMCC(pInputContext->hGuideLine);
|
|
ImmDestroyIMCC(pInputContext->hCandInfo);
|
|
ImmDestroyIMCC(pInputContext->hCompStr);
|
|
|
|
ImmUnlockIMC(hImc);
|
|
|
|
return NtUserDestroyInputContext(hImc);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* SelectInputContext
|
|
*
|
|
* 20-Feb-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
VOID SelectInputContext(
|
|
HKL hSelKL,
|
|
HKL hUnSelKL,
|
|
HIMC hImc)
|
|
{
|
|
PIMEDPI pSelImeDpi, pUnSelImeDpi;
|
|
PCLIENTIMC pClientImc;
|
|
PINPUTCONTEXT pInputContext;
|
|
DWORD dwSelPriv = 0, dwUnSelPriv = 0, dwSize;
|
|
HIMCC hImcc;
|
|
PCOMPOSITIONSTRING pCompStr;
|
|
PCANDIDATEINFO pCandInfo;
|
|
PGUIDELINE pGuideLine;
|
|
BOOL fLogFontInited;
|
|
|
|
pClientImc = ImmLockClientImc(hImc);
|
|
if (pClientImc == NULL)
|
|
return;
|
|
|
|
pSelImeDpi = ImmLockImeDpi(hSelKL);
|
|
pUnSelImeDpi = ImmLockImeDpi(hUnSelKL);
|
|
|
|
/*
|
|
* According to private memory size of the two layout, we decide
|
|
* whether we nee to reallocate this memory block
|
|
*/
|
|
if (pSelImeDpi != NULL)
|
|
dwSelPriv = pSelImeDpi->ImeInfo.dwPrivateDataSize;
|
|
|
|
if (pUnSelImeDpi != NULL)
|
|
dwUnSelPriv = pUnSelImeDpi->ImeInfo.dwPrivateDataSize;
|
|
|
|
dwSelPriv = max(dwSelPriv, sizeof(UINT));
|
|
dwUnSelPriv = max(dwUnSelPriv, sizeof(UINT));
|
|
|
|
/*
|
|
* Unselect the input context.
|
|
*/
|
|
if (pUnSelImeDpi != NULL)
|
|
(*pUnSelImeDpi->pfn.ImeSelect)(hImc, FALSE);
|
|
|
|
/*
|
|
* Reinitialize the client side input context for the selected layout.
|
|
*/
|
|
if ((pInputContext = ImmLockIMC(hImc)) != NULL) {
|
|
|
|
fLogFontInited = ((pInputContext->fdwInit & INIT_LOGFONT) == INIT_LOGFONT);
|
|
|
|
if (TestICF(pClientImc, IMCF_UNICODE) && pSelImeDpi != NULL &&
|
|
!(pSelImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)) {
|
|
/*
|
|
* Check if there is any LOGFONT to be converted.
|
|
*/
|
|
if (fLogFontInited) {
|
|
LOGFONTA LogFontA;
|
|
|
|
LFontWtoLFontA(&pInputContext->lfFont.W, &LogFontA);
|
|
RtlCopyMemory(&pInputContext->lfFont.A, &LogFontA, sizeof(LOGFONTA));
|
|
}
|
|
|
|
ClrICF(pClientImc, IMCF_UNICODE);
|
|
}
|
|
else if (!TestICF(pClientImc, IMCF_UNICODE) && pSelImeDpi != NULL &&
|
|
(pSelImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)) {
|
|
/*
|
|
* Check if there is any LOGFONT to be converted.
|
|
*/
|
|
if (fLogFontInited) {
|
|
LOGFONTW LogFontW;
|
|
|
|
LFontAtoLFontW(&pInputContext->lfFont.A, &LogFontW);
|
|
RtlCopyMemory(&pInputContext->lfFont.W, &LogFontW, sizeof(LOGFONTW));
|
|
}
|
|
|
|
SetICF(pClientImc, IMCF_UNICODE);
|
|
}
|
|
|
|
/*
|
|
* hPrivate
|
|
*/
|
|
if (dwUnSelPriv != dwSelPriv) {
|
|
hImcc = ImmReSizeIMCC(pInputContext->hPrivate, dwSelPriv);
|
|
if (hImcc) {
|
|
pInputContext->hPrivate = hImcc;
|
|
}
|
|
else {
|
|
RIPMSG1(RIP_WARNING,
|
|
"SelectContext: resize hPrivate %lX failure",
|
|
pInputContext->hPrivate);
|
|
ImmDestroyIMCC(pInputContext->hPrivate);
|
|
pInputContext->hPrivate = ImmCreateIMCC(dwSelPriv);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* hMsgBuf
|
|
*/
|
|
dwSize = ImmGetIMCCSize(pInputContext->hMsgBuf);
|
|
|
|
if (ImmGetIMCCLockCount(pInputContext->hMsgBuf) != 0 ||
|
|
dwSize > IMCC_ALLOC_TOOLARGE) {
|
|
|
|
RIPMSG0(RIP_WARNING, "SelectContext: create new hMsgBuf");
|
|
ImmDestroyIMCC(pInputContext->hMsgBuf);
|
|
pInputContext->hMsgBuf = ImmCreateIMCC(sizeof(UINT));
|
|
pInputContext->dwNumMsgBuf = 0;
|
|
}
|
|
|
|
/*
|
|
* hGuideLine
|
|
*/
|
|
dwSize = ImmGetIMCCSize(pInputContext->hGuideLine);
|
|
|
|
if (ImmGetIMCCLockCount(pInputContext->hGuideLine) != 0 ||
|
|
dwSize < sizeof(GUIDELINE) || dwSize > IMCC_ALLOC_TOOLARGE) {
|
|
|
|
RIPMSG0(RIP_WARNING, "SelectContext: create new hGuideLine");
|
|
ImmDestroyIMCC(pInputContext->hGuideLine);
|
|
pInputContext->hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
|
|
pGuideLine = (PGUIDELINE)ImmLockIMCC(pInputContext->hGuideLine);
|
|
|
|
if (pGuideLine != NULL) {
|
|
pGuideLine->dwSize = sizeof(GUIDELINE);
|
|
ImmUnlockIMCC(pInputContext->hGuideLine);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* hCandInfo
|
|
*/
|
|
dwSize = ImmGetIMCCSize(pInputContext->hCandInfo);
|
|
|
|
if (ImmGetIMCCLockCount(pInputContext->hCandInfo) != 0 ||
|
|
dwSize < sizeof(CANDIDATEINFO) || dwSize > IMCC_ALLOC_TOOLARGE) {
|
|
|
|
RIPMSG0(RIP_WARNING, "SelectContext: create new hCandInfo");
|
|
ImmDestroyIMCC(pInputContext->hCandInfo);
|
|
pInputContext->hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
|
|
pCandInfo = (PCANDIDATEINFO)ImmLockIMCC(pInputContext->hCandInfo);
|
|
|
|
if (pCandInfo != NULL) {
|
|
pCandInfo->dwSize = sizeof(CANDIDATEINFO);
|
|
ImmUnlockIMCC(pInputContext->hCandInfo);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* hCompStr
|
|
*/
|
|
dwSize = ImmGetIMCCSize(pInputContext->hCompStr);
|
|
|
|
if (ImmGetIMCCLockCount(pInputContext->hCompStr) != 0 ||
|
|
dwSize < sizeof(COMPOSITIONSTRING) || dwSize > IMCC_ALLOC_TOOLARGE) {
|
|
|
|
RIPMSG0(RIP_WARNING, "SelectContext: create new hCompStr");
|
|
ImmDestroyIMCC(pInputContext->hCompStr);
|
|
pInputContext->hCompStr = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
|
|
pCompStr = (PCOMPOSITIONSTRING)ImmLockIMCC(pInputContext->hCompStr);
|
|
|
|
if (pCompStr != NULL) {
|
|
pCompStr->dwSize = sizeof(COMPOSITIONSTRING);
|
|
ImmUnlockIMCC(pInputContext->hCompStr);
|
|
}
|
|
}
|
|
|
|
ImmUnlockIMC(hImc);
|
|
}
|
|
|
|
/*
|
|
* Select the input context.
|
|
*/
|
|
if (pSelImeDpi != NULL)
|
|
(*pSelImeDpi->pfn.ImeSelect)(hImc, TRUE);
|
|
|
|
ImmUnlockImeDpi(pUnSelImeDpi);
|
|
ImmUnlockImeDpi(pSelImeDpi);
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* EnumInputContext
|
|
*
|
|
* 20-Feb-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
BOOL EnumInputContext(
|
|
DWORD idThread,
|
|
IMCENUMPROC lpfn,
|
|
LONG lParam)
|
|
{
|
|
UINT i;
|
|
UINT cHimc;
|
|
HIMC *phimcT;
|
|
HIMC *phimcFirst;
|
|
BOOL fSuccess = TRUE;
|
|
|
|
/*
|
|
* Get the himc list. It is returned in a block of memory
|
|
* allocated with ImmLocalAlloc.
|
|
*/
|
|
if ((cHimc = BuildHimcList(idThread, &phimcFirst)) == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Loop through the input contexts, call the function pointer back for
|
|
* each one. End loop if either FALSE is returned or the end-of-list is
|
|
* reached.
|
|
*/
|
|
phimcT = phimcFirst;
|
|
for (i = 0; i < cHimc; i++) {
|
|
if (RevalidateHimc(*phimcT)) {
|
|
if (!(fSuccess = (*lpfn)(*phimcT, lParam)))
|
|
break;
|
|
}
|
|
phimcT++;
|
|
}
|
|
|
|
/*
|
|
* Free up buffer and return status - TRUE if entire list was enumerated,
|
|
* FALSE otherwise.
|
|
*/
|
|
ImmLocalFree(phimcFirst);
|
|
|
|
return fSuccess;
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* BuildHimcList
|
|
*
|
|
* 20-Feb-1996 wkwok Created
|
|
\**************************************************************************/
|
|
|
|
DWORD BuildHimcList(
|
|
DWORD idThread,
|
|
HIMC **pphimcFirst)
|
|
{
|
|
UINT cHimc;
|
|
HIMC *phimcFirst;
|
|
NTSTATUS Status;
|
|
int cTries;
|
|
|
|
/*
|
|
* Allocate a buffer to hold the names.
|
|
*/
|
|
cHimc = 64;
|
|
phimcFirst = ImmLocalAlloc(0, cHimc * sizeof(HIMC));
|
|
if (phimcFirst == NULL)
|
|
return 0;
|
|
|
|
Status = NtUserBuildHimcList(idThread, cHimc, phimcFirst, &cHimc);
|
|
|
|
/*
|
|
* If the buffer wasn't big enough, reallocate
|
|
* the buffer and try again.
|
|
*/
|
|
cTries = 0;
|
|
while (Status == STATUS_BUFFER_TOO_SMALL) {
|
|
ImmLocalFree(phimcFirst);
|
|
|
|
/*
|
|
* If we can't seem to get it right,
|
|
* call it quits
|
|
*/
|
|
if (cTries++ == 10)
|
|
return 0;
|
|
|
|
phimcFirst = ImmLocalAlloc(0, cHimc * sizeof(HIMC));
|
|
if (phimcFirst == NULL)
|
|
return 0;
|
|
|
|
Status = NtUserBuildHimcList(idThread, cHimc, phimcFirst, &cHimc);
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status) || cHimc == 0) {
|
|
ImmLocalFree(phimcFirst);
|
|
return 0;
|
|
}
|
|
|
|
*pphimcFirst = phimcFirst;
|
|
|
|
return cHimc;
|
|
}
|