|
|
/**************************************************************************\
* Module Name: immime.c (corresponds to Win95 ime.c) * * Copyright (c) 1985 - 1999, Microsoft Corporation * * IME DLL related functinality * * History: * 03-Jan-1996 wkwok Created \**************************************************************************/
#include "precomp.h"
#pragma hdrstop
typedef struct tagSELECTCONTEXT_ENUM { HKL hSelKL; HKL hUnSelKL; } SCE, *PSCE;
BOOL NotifyIMEProc( HIMC hImc, LPARAM lParam) { UserAssert(lParam == CPS_COMPLETE || lParam == CPS_CANCEL); ImmNotifyIME(hImc, NI_COMPOSITIONSTR, (DWORD)lParam, 0); return TRUE; }
BOOL SelectContextProc( HIMC hImc, PSCE psce) { SelectInputContext(psce->hSelKL, psce->hUnSelKL, hImc); return TRUE; }
BOOL InquireIme( PIMEDPI pImeDpi) { WNDCLASS wc; BYTE ClassName[IM_UI_CLASS_SIZE * sizeof(WCHAR)]; DWORD dwSystemInfoFlags; PIMEINFO pImeInfo = &pImeDpi->ImeInfo;
/*
* Check if this process requires the security. * Adding to the pid check, the current desktop check is required, * for there are applications run on the secure desktop. */ dwSystemInfoFlags = (NtUserGetThreadState(UserThreadStateNeedsSecurity) ? IME_SYSINFO_WINLOGON : 0);
if (GetClientInfo()->dwTIFlags & TIF_16BIT) dwSystemInfoFlags |= IME_SYSINFO_WOW16;
#if !defined(CUAS_ENABLE)
(*pImeDpi->pfn.ImeInquire.w)(pImeInfo, (PVOID)ClassName, dwSystemInfoFlags); #else
if (! IS_IME_KBDLAYOUT(pImeDpi->hKL) && IS_CICERO_ENABLED_AND_NOT16BIT()) { if ((*pImeDpi->pfn.CtfImeInquireExW)(pImeInfo, (PVOID)ClassName, dwSystemInfoFlags, pImeDpi->hKL) == S_OK) { } else { RIPMSG0(RIP_WARNING, "InquireIme: pImeDpi->pfn.ImeInquireExW failed"); return FALSE; } } else { (*pImeDpi->pfn.ImeInquire.w)(pImeInfo, (PVOID)ClassName, dwSystemInfoFlags); } #endif
/*
* parameter checking for each fields. */ if (pImeInfo->dwPrivateDataSize == 0) pImeInfo->dwPrivateDataSize = sizeof(UINT);
if (pImeInfo->fdwProperty & ~(IME_PROP_ALL)) { RIPMSG0(RIP_WARNING, "wrong property"); return FALSE; }
if (pImeInfo->fdwConversionCaps & ~(IME_CMODE_ALL)) { RIPMSG0(RIP_WARNING, "wrong conversion capabilities"); return FALSE; }
if (pImeInfo->fdwSentenceCaps & ~(IME_SMODE_ALL)) { RIPMSG0(RIP_WARNING, "wrong sentence capabilities"); return FALSE; }
if (pImeInfo->fdwUICaps & ~(UI_CAP_ALL)) { RIPMSG0(RIP_WARNING, "wrong UI capabilities"); return FALSE; }
if (pImeInfo->fdwSCSCaps & ~(SCS_CAP_ALL)) { RIPMSG0(RIP_WARNING, "wrong set comp string capabilities"); return FALSE; }
if (pImeInfo->fdwSelectCaps & ~(SELECT_CAP_ALL)) { RIPMSG0(RIP_WARNING, "wrong select capabilities"); return FALSE; }
if (!(pImeInfo->fdwProperty & IME_PROP_UNICODE)) {
/*
* This is ANSI IME. Ensure that it is usable under current system * codepage. */ if (pImeDpi->dwCodePage != GetACP() && pImeDpi->dwCodePage != CP_ACP) { // Note: in the future, if possible, these reference to dwCodepage
// should be IMECodePage()...
RIPMSG1(RIP_WARNING, "incompatible codepage(%d) for ANSI IME", pImeDpi->dwCodePage); return FALSE; }
/*
* ANSI -> Unicode Class name. */ MultiByteToWideChar(IMECodePage(pImeDpi), (DWORD)MB_PRECOMPOSED, (LPSTR)ClassName, // src
(INT)-1, pImeDpi->wszUIClass, // dest
IM_UI_CLASS_SIZE); } else { RtlCopyMemory(pImeDpi->wszUIClass, ClassName, sizeof(ClassName)); } pImeDpi->wszUIClass[IM_UI_CLASS_SIZE-1] = L'\0';
if (!GetClassInfoW((HINSTANCE)pImeDpi->hInst, pImeDpi->wszUIClass, &wc)) { RIPMSG1(RIP_WARNING, "UI class (%ws) not found in this IME", pImeDpi->wszUIClass); return FALSE; } else if (wc.cbWndExtra < sizeof(DWORD) * 2) { RIPMSG0(RIP_WARNING, "UI class cbWndExtra problem"); return FALSE; }
return TRUE; }
BOOL CheckAndApplyAppCompat(LPWSTR wszImeFile) { DWORD dwReason; HMODULE hAppHelp; typedef BOOL (*PFNApphelpCheckIME)( IN LPCWSTR pwszPath // Unicode path to the executable (DOS_PATH)
); PFNApphelpCheckIME pfnAppHelpCheckIME; BOOL bRunIME = TRUE; //
// tentative prototype (find out a semi-public header to include! [and a lib too])
//
BOOL WINAPI BaseCheckAppcompatCache( LPCWSTR pwszPath, HANDLE hFile, PVOID pEnvironment, DWORD* dwReason );
//
// Assuming most of IMEs are just fine, not needing
// Shim's help, let's check the good guy cache first
// so that the overhead should be minimum. This API
// is meant to be really light weight.
//
if (BaseCheckAppcompatCache(wszImeFile, INVALID_HANDLE_VALUE, NULL, &dwReason)) { // This IME is in the good guy cache. Just bail out quietly.
return bRunIME; }
// What's a good use of dwReason?
RIPMSG1(RIP_VERBOSE, "Shim'ing this IME='%ls'", wszImeFile);
//
// Call the real Shim helper for this IME.
//
hAppHelp = GetModuleHandleW(L"apphelp.dll"); if (hAppHelp == NULL) { hAppHelp = LoadLibraryW(L"apphelp.dll"); if (hAppHelp == NULL) { // Failed to load apphelp.dll.
// We have no other choice than bailing out.
RIPMSG0(RIP_WARNING, "CheckAndApplyAppCompat: failed to load apphelp.dll"); return bRunIME; } } UserAssert(hAppHelp);
pfnAppHelpCheckIME = (PFNApphelpCheckIME)GetProcAddress(hAppHelp, "ApphelpCheckIME"); if (pfnAppHelpCheckIME == NULL) { RIPMSG0(RIP_WARNING, "CheckAndApplyAppCompat: failed to getproc ApphelpCheckIME"); return bRunIME; }
//
// return result has no meaning for this ca
//
bRunIME = pfnAppHelpCheckIME(wszImeFile);
return bRunIME; }
BOOL LoadIME( PIMEINFOEX piiex, PIMEDPI pImeDpi) { WCHAR wszImeFile[MAX_PATH]; BOOL fSuccess;
GetSystemPathName(wszImeFile, piiex->wszImeFile, MAX_PATH);
if (!CheckAndApplyAppCompat(wszImeFile)) { RIPMSG1(RIP_WARNING, "LoadIME: IME (%ws) blocked by appcompat", wszImeFile); goto LoadIME_ErrOut; }
pImeDpi->hInst = LoadLibraryW(wszImeFile);
if (!pImeDpi->hInst) { RIPMSG1(RIP_WARNING, "LoadIME: LoadLibraryW(%ws) failed", wszImeFile); goto LoadIME_ErrOut; }
#define GET_IMEPROCT(x) \
if (!(pImeDpi->pfn.##x.t = (PVOID) GetProcAddress(pImeDpi->hInst, #x))) { \ RIPMSG1(RIP_WARNING, "LoadIME: " #x " not supported in %ws", wszImeFile); \ goto LoadIME_ErrOut; }
#define GET_IMEPROC(x) \
if (!(pImeDpi->pfn.##x = (PVOID) GetProcAddress(pImeDpi->hInst, #x))) { \ RIPMSG1(RIP_WARNING, "LoadIME: " #x " not supported in %ws", wszImeFile); \ goto LoadIME_ErrOut; }
GET_IMEPROCT(ImeInquire); GET_IMEPROCT(ImeConversionList); GET_IMEPROCT(ImeRegisterWord); GET_IMEPROCT(ImeUnregisterWord); GET_IMEPROCT(ImeGetRegisterWordStyle); GET_IMEPROCT(ImeEnumRegisterWord); GET_IMEPROC (ImeConfigure); GET_IMEPROC (ImeDestroy); GET_IMEPROC (ImeEscape); GET_IMEPROC (ImeProcessKey); GET_IMEPROC (ImeSelect); GET_IMEPROC (ImeSetActiveContext); GET_IMEPROC (ImeToAsciiEx); GET_IMEPROC (NotifyIME); GET_IMEPROC (ImeSetCompositionString);
// 4.0 IMEs don't have this entry. could be NULL.
pImeDpi->pfn.ImeGetImeMenuItems = (PVOID)GetProcAddress(pImeDpi->hInst, "ImeGetImeMenuItems");
#ifdef CUAS_ENABLE
//
// Cicero IME
//
if (! IS_IME_KBDLAYOUT(pImeDpi->hKL) && IS_CICERO_ENABLED_AND_NOT16BIT()) { GET_IMEPROC (CtfImeInquireExW); GET_IMEPROC (CtfImeSelectEx); GET_IMEPROC (CtfImeEscapeEx); GET_IMEPROC (CtfImeGetGuidAtom); GET_IMEPROC (CtfImeIsGuidMapEnable); } #endif // CUAS_ENABLE
#undef GET_IMEPROCT
#undef GET_IMEPROC
if (!InquireIme(pImeDpi)) { RIPMSG0(RIP_WARNING, "LoadIME: InquireIme failed"); LoadIME_ErrOut: FreeLibrary(pImeDpi->hInst); pImeDpi->hInst = NULL; fSuccess = FALSE; } else { fSuccess = TRUE; }
/*
* Update kernel side IMEINFOEX for this keyboard layout if * this is its first loading. */ if (piiex->fLoadFlag == IMEF_NONLOAD) { if (fSuccess) { RtlCopyMemory((PBYTE)&piiex->ImeInfo, (PBYTE)&pImeDpi->ImeInfo, sizeof(IMEINFO)); RtlCopyMemory((PBYTE)piiex->wszUIClass, (PBYTE)pImeDpi->wszUIClass, sizeof(pImeDpi->wszUIClass)); piiex->fLoadFlag = IMEF_LOADED; } else { piiex->fLoadFlag = IMEF_LOADERROR; RIPMSG1(RIP_WARNING, "LoadIME: hKL=%lx piiex->fLoadFlag = IMEF_LOADERROR", piiex->hkl); } NtUserSetImeInfoEx(piiex); }
return fSuccess; }
VOID UnloadIME( PIMEDPI pImeDpi, BOOL fTerminateIme) { if (pImeDpi->hInst == NULL) { RIPMSG0(RIP_WARNING, "UnloadIME: No IME's hInst."); return; }
if (fTerminateIme) { /*
* Destroy IME first. */ (*pImeDpi->pfn.ImeDestroy)(0); }
FreeLibrary(pImeDpi->hInst); pImeDpi->hInst = NULL;
return; }
PIMEDPI LoadImeDpi( HKL hKL, BOOL fLock) { PIMEDPI pImeDpi, pImeDpiT; IMEINFOEX iiex;
/*
* Query the IME information. */ if (!ImmGetImeInfoEx(&iiex, ImeInfoExKeyboardLayout, &hKL)) { RIPMSG1(RIP_WARNING, "LoadImeDpi: ImmGetImeInfoEx(%lx) failed", hKL); return NULL; }
/*
* Win95 behaviour: If there was an IME load error for this layout, * further attempt to load the same IME layout will be rejected. */ if (iiex.fLoadFlag == IMEF_LOADERROR) { RIPMSG1(RIP_WARNING, "LoadImeDpi: hKL=%lx iiex.fLoadFlag = IMEF_LOADERROR", iiex.hkl); return NULL; }
/*
* Allocate a new IMEDPI for this layout. */ pImeDpi = (PIMEDPI)ImmLocalAlloc(HEAP_ZERO_MEMORY, sizeof(IMEDPI)); if (pImeDpi == NULL) return NULL;
pImeDpi->hKL = hKL;
// get code page of IME
{ CHARSETINFO cs; if (TranslateCharsetInfo((DWORD*)LOWORD(HandleToUlong(hKL)), &cs, TCI_SRCLOCALE)) { pImeDpi->dwCodePage = cs.ciACP; } else { pImeDpi->dwCodePage = CP_ACP; } }
/*
* Load up IME DLL. */ if (!LoadIME(&iiex, pImeDpi)) { ImmLocalFree(pImeDpi); return NULL; }
/*
* Link in the newly allocated entry. */ RtlEnterCriticalSection(&gcsImeDpi);
pImeDpiT = ImmGetImeDpi(hKL);
if (pImeDpiT == NULL) { if (fLock) { /*
* Newly loaded with lock, will unload upon unlock. */ pImeDpi->cLock = 1; pImeDpi->dwFlag |= IMEDPI_UNLOCKUNLOAD; }
/*
* Update the global list for this new pImeDpi entry. */ pImeDpi->pNext = gpImeDpi; gpImeDpi = pImeDpi;
RtlLeaveCriticalSection(&gcsImeDpi); } else {
if (!fLock) { pImeDpiT->dwFlag &= ~IMEDPI_UNLOCKUNLOAD; }
/*
* The same IME has been loaded, discard this extra entry. */ RtlLeaveCriticalSection(&gcsImeDpi); UnloadIME(pImeDpi, FALSE); ImmLocalFree(pImeDpi); pImeDpi = pImeDpiT; }
return pImeDpi; }
PIMEDPI FindOrLoadImeDpi( HKL hKL) { PIMEDPI pImeDpi;
/*
* Non IME based keyboard layout doesn't have IMEDPI. */ #if !defined(CUAS_ENABLE)
if (!IS_IME_KBDLAYOUT(hKL)) return (PIMEDPI)NULL; #else
if (! IS_IME_KBDLAYOUT(hKL) && ! IS_CICERO_ENABLED_AND_NOT16BIT()) return (PIMEDPI)NULL; #endif
pImeDpi = ImmLockImeDpi(hKL); if (pImeDpi == NULL) pImeDpi = LoadImeDpi(hKL, TRUE);
return pImeDpi; }
BOOL WINAPI ImmLoadIME( HKL hKL) { PIMEDPI pImeDpi;
/*
* Non IME based keyboard layout doesn't have IMEDPI. */ #if !defined(CUAS_ENABLE)
if (!IS_IME_KBDLAYOUT(hKL)) return FALSE; #else
if (! IS_IME_KBDLAYOUT(hKL) && ! IS_CICERO_ENABLED_AND_NOT16BIT()) return FALSE; #endif
pImeDpi = ImmGetImeDpi(hKL); if (pImeDpi == NULL) pImeDpi = LoadImeDpi(hKL, FALSE);
return (pImeDpi != NULL); }
BOOL WINAPI ImmUnloadIME( HKL hKL) { PIMEDPI pImeDpi, pImeDpiT;
RtlEnterCriticalSection(&gcsImeDpi);
pImeDpi = gpImeDpi;
while (pImeDpi != NULL && pImeDpi->hKL != hKL) pImeDpi = pImeDpi->pNext;
if (pImeDpi == NULL) { RtlLeaveCriticalSection(&gcsImeDpi); return TRUE; } else if (pImeDpi->cLock != 0) { pImeDpi->dwFlag |= IMEDPI_UNLOADED; RtlLeaveCriticalSection(&gcsImeDpi); return FALSE; }
/*
* 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 TRUE; }
BOOL WINAPI ImmFreeLayout( DWORD dwFlag) { PIMEDPI pImeDpi; HKL *phklRoot, hklCurrent; WCHAR pwszNonImeKLID[KL_NAMELENGTH]; UINT nLayouts, uNonImeKLID = 0, i;
hklCurrent = GetKeyboardLayout(0);
switch (dwFlag) {
case IFL_DEACTIVATEIME: /*
* Do nothing if no IME to be deactivated. */ if (!IS_IME_KBDLAYOUT(hklCurrent)) return TRUE;
/*
* Deactivate IME based layout by activating a non-IME based * keyboard layout. */ uNonImeKLID = (UINT)LANGIDFROMLCID(GetSystemDefaultLCID());
nLayouts = GetKeyboardLayoutList(0, NULL);
if (nLayouts != 0) { phklRoot = ImmLocalAlloc(0, nLayouts * sizeof(HKL)); if (phklRoot == NULL) return FALSE;
nLayouts = GetKeyboardLayoutList(nLayouts, phklRoot);
for (i = 0; i < nLayouts && IS_IME_KBDLAYOUT(phklRoot[i]); i++) ;
if (i < nLayouts) uNonImeKLID = HandleToUlong(phklRoot[i]) & 0xffff;
ImmLocalFree(phklRoot); }
wsprintf(pwszNonImeKLID, L"%08x", uNonImeKLID);
if (LoadKeyboardLayoutW(pwszNonImeKLID, KLF_ACTIVATE) == NULL) { RIPMSG1(RIP_WARNING, "ImmFreeLayout: LoadKeyboardLayoutW(%S, KLF_ACTIVATE) failed. Trying 00000409", pwszNonImeKLID); // Somehow it failed (probably a bad setup), let's try
// 409 KL, which should be installed on all localized NTs.
if (LoadKeyboardLayoutW(L"00000409", KLF_ACTIVATE | KLF_FAILSAFE) == NULL) { RIPMSG0(RIP_WARNING, "LoadKeyboardLayoutW(00000409) failed either. will try NULL."); } }
break;
case IFL_UNLOADIME: RtlEnterCriticalSection(&gcsImeDpi); UnloadImeDpiLoop: for (pImeDpi = gpImeDpi; pImeDpi != NULL; pImeDpi = pImeDpi->pNext) { if (ImmUnloadIME(pImeDpi->hKL)) goto UnloadImeDpiLoop; // Rescan as list was updated.
} RtlLeaveCriticalSection(&gcsImeDpi); break;
default: { HKL hklFlag = (HKL)LongToHandle( dwFlag ); if (IS_IME_KBDLAYOUT(hklFlag) && hklFlag != hklCurrent) { ImmUnloadIME(hklFlag); } } break; }
return TRUE; }
BOOL WINAPI ImmActivateLayout( HKL hSelKL) { HKL hUnSelKL; HWND hWndDefaultIme; SCE sce; DWORD dwCPS; PIMEDPI pImeDpi; BOOLEAN fOptimizeActivation = TRUE;
hUnSelKL = GetKeyboardLayout(0);
{ PCLIENTINFO pClientInfo = GetClientInfo();
if (pClientInfo->CI_flags & CI_INPUTCONTEXT_REINIT) { fOptimizeActivation = FALSE; } }
/*
* if already current active, do nothing */ if (hUnSelKL == hSelKL && fOptimizeActivation) return TRUE;
ImmLoadIME(hSelKL);
if (hUnSelKL != hSelKL) { pImeDpi = ImmLockImeDpi(hUnSelKL); if (pImeDpi != NULL) { /*
* Send out CPS_CANCEL or CPS_COMPLETE to every input * context assoicated to window(s) created by this thread. * Starting from SUR, we only assoicate input context to window created * by the same thread. */ dwCPS = (pImeDpi->ImeInfo.fdwProperty & IME_PROP_COMPLETE_ON_UNSELECT) ? CPS_COMPLETE : CPS_CANCEL; ImmUnlockImeDpi(pImeDpi); ImmEnumInputContext(0, NotifyIMEProc, dwCPS); }
hWndDefaultIme = ImmGetDefaultIMEWnd(NULL);
if (IsWindow(hWndDefaultIme)) SendMessage(hWndDefaultIme, WM_IME_SELECT, FALSE, (LPARAM)hUnSelKL);
/*
* This is the time to update the kernel side layout handles. * We must do this before sending WM_IME_SELECT. */ NtUserSetThreadLayoutHandles(hSelKL, hUnSelKL); }
/*
* Unselect and select input context(s). */ sce.hSelKL = hSelKL; sce.hUnSelKL = hUnSelKL; ImmEnumInputContext(0, (IMCENUMPROC)SelectContextProc, (LPARAM)&sce);
/*
* inform UI select after all hIMC select */ if (IsWindow(hWndDefaultIme)) SendMessage(hWndDefaultIme, WM_IME_SELECT, TRUE, (LPARAM)hSelKL);
return (TRUE); }
/***************************************************************************\
* ImmConfigureIMEA * * Brings up the configuration dialogbox of the IME with the specified hKL. * * History: * 29-Feb-1995 wkwok Created \***************************************************************************/
BOOL WINAPI ImmConfigureIMEA( HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) { PWND pWnd; PIMEDPI pImeDpi; BOOL fRet = FALSE;
if ((pWnd = ValidateHwnd(hWnd)) == (PWND)NULL) { RIPMSG1(RIP_WARNING, "ImmConfigureIMEA: invalid window handle %x", hWnd); return FALSE; }
if (!TestWindowProcess(pWnd)) { RIPMSG1(RIP_WARNING, "ImmConfigureIMEA: hWnd=%lx belongs to different process!", hWnd); return FALSE; }
pImeDpi = FindOrLoadImeDpi(hKL); if (pImeDpi == NULL) { RIPMSG0(RIP_WARNING, "ImmConfigureIMEA: no pImeDpi entry."); return FALSE; }
if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) || lpData == NULL) { /*
* Doesn't need A/W conversion. Calls directly to IME to * bring up the configuration dialogbox. */ // This message handles by Console IME.
SendMessage(hWnd, WM_IME_SYSTEM, IMS_OPENPROPERTYWINDOW, 0L); fRet = (*pImeDpi->pfn.ImeConfigure)(hKL, hWnd, dwMode, lpData); // This message handles by Console IME.
SendMessage(hWnd, WM_IME_SYSTEM, IMS_CLOSEPROPERTYWINDOW, 0L); ImmUnlockImeDpi(pImeDpi); return fRet; }
/*
* ANSI caller, Unicode IME. Needs A/W conversion on lpData when * dwMode == IME_CONFIG_REGISTERWORD. In this case, lpData points * to a structure of REGISTERWORDA. */ switch (dwMode) { case IME_CONFIG_REGISTERWORD: { LPREGISTERWORDA lpRegisterWordA; REGISTERWORDW RegisterWordW; LPVOID lpBuffer; ULONG cbBuffer; INT i;
lpRegisterWordA = (LPREGISTERWORDA)lpData; cbBuffer = 0; lpBuffer = NULL;
if (lpRegisterWordA->lpReading != NULL) cbBuffer += strlen(lpRegisterWordA->lpReading) + 1;
if (lpRegisterWordA->lpWord != NULL) cbBuffer += strlen(lpRegisterWordA->lpWord) + 1;
if (cbBuffer != 0) { cbBuffer *= sizeof(WCHAR); if ((lpBuffer = ImmLocalAlloc(0, cbBuffer)) == NULL) { RIPMSG0(RIP_WARNING, "ImmConfigureIMEA: memory failure."); break; } }
if (lpRegisterWordA->lpReading != NULL) { RegisterWordW.lpReading = lpBuffer; i = MultiByteToWideChar(IMECodePage(pImeDpi), (DWORD)MB_PRECOMPOSED, (LPSTR)lpRegisterWordA->lpReading, (INT)strlen(lpRegisterWordA->lpReading), (LPWSTR)RegisterWordW.lpReading, (INT)(cbBuffer/sizeof(WCHAR))); RegisterWordW.lpReading[i] = L'\0'; cbBuffer -= (i * sizeof(WCHAR)); } else { RegisterWordW.lpReading = NULL; }
if (lpRegisterWordA->lpWord != NULL) { if (RegisterWordW.lpReading != NULL) RegisterWordW.lpWord = &RegisterWordW.lpReading[i+1]; else RegisterWordW.lpWord = lpBuffer; i = MultiByteToWideChar(IMECodePage(pImeDpi), (DWORD)MB_PRECOMPOSED, (LPSTR)lpRegisterWordA->lpWord, (INT)strlen(lpRegisterWordA->lpWord), (LPWSTR)RegisterWordW.lpWord, (INT)(cbBuffer/sizeof(WCHAR))); RegisterWordW.lpWord[i] = L'\0'; } else RegisterWordW.lpWord = NULL;
fRet = ImmConfigureIMEW(hKL, hWnd, dwMode, &RegisterWordW);
if (lpBuffer != NULL) ImmLocalFree(lpBuffer);
break; } default: fRet = ImmConfigureIMEW(hKL, hWnd, dwMode, lpData); break; }
ImmUnlockImeDpi(pImeDpi);
return fRet; }
/***************************************************************************\
* ImmConfigureIMEW * * Brings up the configuration dialogbox of the IME with the specified hKL. * * History: * 29-Feb-1995 wkwok Created \***************************************************************************/
BOOL WINAPI ImmConfigureIMEW( HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) { PWND pWnd; PIMEDPI pImeDpi; BOOL fRet = FALSE;
if ((pWnd = ValidateHwnd(hWnd)) == (PWND)NULL) { RIPMSG1(RIP_WARNING, "ImmConfigureIMEA: invalid window handle %x", hWnd); return FALSE; }
if (!TestWindowProcess(pWnd)) { RIPMSG1(RIP_WARNING, "ImmConfigureIMEA: hWnd=%lx belongs to different process!", hWnd); return FALSE; }
pImeDpi = FindOrLoadImeDpi(hKL); if (pImeDpi == NULL) { RIPMSG0(RIP_WARNING, "ImmConfigureIMEA: no pImeDpi entry."); return FALSE; }
if ((pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) || lpData == NULL) { /*
* Doesn't need A/W conversion. Calls directly to IME to * bring up the configuration dialogbox. */ // This message handles by Console IME.
SendMessage(hWnd, WM_IME_SYSTEM, IMS_OPENPROPERTYWINDOW, 0L); fRet = (*pImeDpi->pfn.ImeConfigure)(hKL, hWnd, dwMode, lpData); // This message handles by Console IME.
SendMessage(hWnd, WM_IME_SYSTEM, IMS_CLOSEPROPERTYWINDOW, 0L); ImmUnlockImeDpi(pImeDpi); return fRet; }
/*
* Unicode caller, ANSI IME. Needs A/W conversion on lpData when * dwMode == IME_CONFIG_REGISTERWORD. In this case, lpData points * to a structure of REGISTERWORDW. */ switch (dwMode) { case IME_CONFIG_REGISTERWORD: { LPREGISTERWORDW lpRegisterWordW; REGISTERWORDA RegisterWordA; LPVOID lpBuffer; ULONG cbBuffer; BOOL bUDC; INT i;
lpRegisterWordW = (LPREGISTERWORDW)lpData; cbBuffer = 0; lpBuffer = NULL;
if (lpRegisterWordW->lpReading != NULL) cbBuffer += wcslen(lpRegisterWordW->lpReading) + 1;
if (lpRegisterWordW->lpWord != NULL) cbBuffer += wcslen(lpRegisterWordW->lpWord) + 1;
if (cbBuffer != 0) { cbBuffer *= sizeof(WCHAR); if ((lpBuffer = ImmLocalAlloc(0, cbBuffer)) == NULL) { RIPMSG0(RIP_WARNING, "ImmConfigureIMEW: memory failure."); break; } }
if (lpRegisterWordW->lpReading != NULL) { RegisterWordA.lpReading = lpBuffer; i = WideCharToMultiByte(IMECodePage(pImeDpi), (DWORD)0, (LPWSTR)lpRegisterWordW->lpReading, (INT)wcslen(lpRegisterWordW->lpReading), (LPSTR)RegisterWordA.lpReading, (INT)cbBuffer, (LPSTR)NULL, (LPBOOL)&bUDC); RegisterWordA.lpReading[i] = '\0'; cbBuffer -= (i * sizeof(CHAR)); } else { RegisterWordA.lpReading = NULL; }
if (lpRegisterWordW->lpWord != NULL) { if (RegisterWordA.lpReading != NULL) RegisterWordA.lpWord = &RegisterWordA.lpReading[i+1]; else RegisterWordA.lpWord = lpBuffer; i = WideCharToMultiByte(IMECodePage(pImeDpi), (DWORD)0, (LPWSTR)lpRegisterWordW->lpWord, (INT)wcslen(lpRegisterWordW->lpWord), (LPSTR)RegisterWordA.lpWord, (INT)cbBuffer, (LPSTR)NULL, (LPBOOL)&bUDC); RegisterWordA.lpWord[i] = '\0'; } else RegisterWordA.lpWord = NULL;
fRet = ImmConfigureIMEA(hKL, hWnd, dwMode, &RegisterWordA);
if (lpBuffer != NULL) ImmLocalFree(lpBuffer);
break; } default: fRet = ImmConfigureIMEA(hKL, hWnd, dwMode, lpData); break; }
ImmUnlockImeDpi(pImeDpi);
return fRet; }
#define IME_T_EUDC_DIC_SIZE 80 // the Traditional Chinese EUDC dictionary
/***************************************************************************\
* ImmEscapeA * * This API allows an application to access capabilities of a particular * IME with specified hKL not directly available thru. other IMM APIs. * This is necessary mainly for country specific functions or private * functions in IME. * * History: * 29-Feb-1995 wkwok Created \***************************************************************************/
LRESULT WINAPI ImmEscapeA( HKL hKL, HIMC hImc, UINT uSubFunc, LPVOID lpData) { PIMEDPI pImeDpi; LRESULT lRet = 0;
pImeDpi = FindOrLoadImeDpi(hKL); if (pImeDpi == NULL) { RIPMSG0(RIP_WARNING, "ImmEscapeA: no pImeDpi entry."); return lRet; }
if ((pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) == 0 || lpData == NULL) { /*
* Doesn't need A/W conversion. Calls directly to IME to * bring up the configuration dialogbox. */ #if !defined(CUAS_ENABLE)
lRet = (*pImeDpi->pfn.ImeEscape)(hImc, uSubFunc, lpData); #else
if (IS_IME_KBDLAYOUT(hKL)) { lRet = (*pImeDpi->pfn.ImeEscape)(hImc, uSubFunc, lpData); } else if (IS_CICERO_ENABLED_AND_NOT16BIT()) { lRet = (*pImeDpi->pfn.CtfImeEscapeEx)(hImc, uSubFunc, lpData, hKL); } #endif
ImmUnlockImeDpi(pImeDpi); return lRet; }
/*
* ANSI caller, Unicode IME. Needs A/W conversion depending on * uSubFunc. */ switch (uSubFunc) { case IME_ESC_GET_EUDC_DICTIONARY: case IME_ESC_IME_NAME: case IME_ESC_GETHELPFILENAME: { WCHAR wszData[IME_T_EUDC_DIC_SIZE]; BOOL bUDC; INT i;
lRet = ImmEscapeW(hKL, hImc, uSubFunc, (LPVOID)wszData);
if (lRet != 0) {
try { i = WideCharToMultiByte(IMECodePage(pImeDpi), (DWORD)0, (LPWSTR)wszData, // src
(INT)wcslen(wszData), (LPSTR)lpData, // dest
(INT)IME_T_EUDC_DIC_SIZE, (LPSTR)NULL, (LPBOOL)&bUDC); ((LPSTR)lpData)[i] = '\0'; } except (EXCEPTION_EXECUTE_HANDLER) { lRet = 0; } }
break; }
case IME_ESC_SET_EUDC_DICTIONARY: case IME_ESC_HANJA_MODE: { WCHAR wszData[IME_T_EUDC_DIC_SIZE]; INT i;
i = MultiByteToWideChar(IMECodePage(pImeDpi), (DWORD)MB_PRECOMPOSED, (LPSTR)lpData, // src
(INT)strlen(lpData), (LPWSTR)wszData, // dest
(INT)sizeof(wszData)/sizeof(WCHAR)); wszData[i] = L'\0';
lRet = ImmEscapeW(hKL, hImc, uSubFunc, (LPVOID)wszData);
break; }
case IME_ESC_SEQUENCE_TO_INTERNAL: { CHAR szData[4]; WCHAR wszData[4]; INT i = 0;
lRet = ImmEscapeW(hKL, hImc, uSubFunc, lpData);
if (HIWORD(lRet)) wszData[i++] = HIWORD(lRet);
if (LOWORD(lRet)) wszData[i++] = LOWORD(lRet);
i = WideCharToMultiByte(IMECodePage(pImeDpi), (DWORD)0, (LPWSTR)wszData, // src
(INT)i, (LPSTR)szData, // dest
(INT)sizeof(szData), (LPSTR)NULL, (LPBOOL)NULL);
switch (i) { case 1: lRet = MAKELONG(MAKEWORD(szData[0], 0), 0); break;
case 2: lRet = MAKELONG(MAKEWORD(szData[1], szData[0]), 0); break;
case 3: lRet = MAKELONG(MAKEWORD(szData[2], szData[1]), MAKEWORD(szData[0], 0)); break;
case 4: lRet = MAKELONG(MAKEWORD(szData[3], szData[2]), MAKEWORD(szData[1], szData[0])); break;
default: lRet = 0; break; }
break; } default: lRet = ImmEscapeW(hKL, hImc, uSubFunc, lpData); break; }
ImmUnlockImeDpi(pImeDpi);
return lRet; }
/***************************************************************************\
* ImmEscapeW * * This API allows an application to access capabilities of a particular * IME with specified hKL not directly available thru. other IMM APIs. * This is necessary mainly for country specific functions or private * functions in IME. * * History: * 29-Feb-1995 wkwok Created \***************************************************************************/
LRESULT WINAPI ImmEscapeW( HKL hKL, HIMC hImc, UINT uSubFunc, LPVOID lpData) { PIMEDPI pImeDpi; LRESULT lRet = 0;
pImeDpi = FindOrLoadImeDpi(hKL); if (pImeDpi == NULL) { RIPMSG0(RIP_WARNING, "ImmEscapeW: no pImeDpi entry."); return lRet; }
if ((pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) || lpData == NULL) { /*
* Doesn't need W/A conversion. Calls directly to IME to * bring up the configuration dialogbox. */ #if !defined(CUAS_ENABLE)
lRet = (*pImeDpi->pfn.ImeEscape)(hImc, uSubFunc, lpData); #else
if (IS_IME_KBDLAYOUT(hKL)) { lRet = (*pImeDpi->pfn.ImeEscape)(hImc, uSubFunc, lpData); } else if (IS_CICERO_ENABLED_AND_NOT16BIT()) { lRet = (*pImeDpi->pfn.CtfImeEscapeEx)(hImc, uSubFunc, lpData, hKL); } #endif
ImmUnlockImeDpi(pImeDpi); return lRet; }
/*
* Unicode caller, ANSI IME. Needs W/A conversion depending on * uSubFunc. */ switch (uSubFunc) { case IME_ESC_GET_EUDC_DICTIONARY: case IME_ESC_IME_NAME: case IME_ESC_GETHELPFILENAME: { CHAR szData[IME_T_EUDC_DIC_SIZE]; INT i;
lRet = ImmEscapeA(hKL, hImc, uSubFunc, (LPVOID)szData);
if (lRet != 0) {
try { i = MultiByteToWideChar(IMECodePage(pImeDpi), (DWORD)MB_PRECOMPOSED, (LPSTR)szData, // src
(INT)strlen(szData), (LPWSTR)lpData, // dest
(INT)IME_T_EUDC_DIC_SIZE); ((LPWSTR)lpData)[i] = L'\0'; } except (EXCEPTION_EXECUTE_HANDLER) { lRet = 0; } }
break; }
case IME_ESC_SET_EUDC_DICTIONARY: case IME_ESC_HANJA_MODE: { CHAR szData[IME_T_EUDC_DIC_SIZE]; BOOL bUDC; INT i;
i = WideCharToMultiByte(IMECodePage(pImeDpi), (DWORD)0, (LPWSTR)lpData, // src
(INT)wcslen(lpData), (LPSTR)szData, // dest
(INT)sizeof(szData), (LPSTR)NULL, (LPBOOL)&bUDC); szData[i] = '\0';
lRet = ImmEscapeA(hKL, hImc, uSubFunc, (LPVOID)szData);
break; }
case IME_ESC_SEQUENCE_TO_INTERNAL: { CHAR szData[4]; WCHAR wszData[4]; INT i = 0;
lRet = ImmEscapeA(hKL, hImc, uSubFunc, lpData);
if (HIBYTE(LOWORD(lRet))) szData[i++] = HIBYTE(LOWORD(lRet));
if (LOBYTE(LOWORD(lRet))) szData[i++] = LOBYTE(LOWORD(lRet));
i = MultiByteToWideChar(IMECodePage(pImeDpi), (DWORD)MB_PRECOMPOSED, (LPSTR)szData, // src
i, (LPWSTR)wszData, // dest
(INT)sizeof(wszData)/sizeof(WCHAR));
switch (i) { case 1: lRet = MAKELONG(wszData[0], 0); break;
case 2: lRet = MAKELONG(wszData[1], wszData[0]); break;
default: lRet = 0; break; }
break; }
default: lRet = ImmEscapeA(hKL, hImc, uSubFunc, lpData); break; }
ImmUnlockImeDpi(pImeDpi);
return lRet; }
BOOL WINAPI ImmNotifyIME( HIMC hImc, DWORD dwAction, DWORD dwIndex, DWORD dwValue) { PIMEDPI pImeDpi; BOOL bRet;
if (hImc != NULL_HIMC && GetInputContextThread(hImc) != GetCurrentThreadId()) { RIPMSG1(RIP_WARNING, "ImmNotifyIME: Invalid input context access %lx.", hImc); return FALSE; }
pImeDpi = ImmLockImeDpi(GetKeyboardLayout(0)); if (pImeDpi == NULL) return FALSE;
bRet = (*pImeDpi->pfn.NotifyIME)(hImc, dwAction, dwIndex, dwValue);
ImmUnlockImeDpi(pImeDpi);
return bRet; }
|