Aric Stewart : imm32: Begin to add basic framework for loading IMEs as dlls .
Alexandre Julliard
julliard at winehq.org
Tue Apr 1 06:51:34 CDT 2008
Module: wine
Branch: master
Commit: 0a44a778f00c5283347646083f682333c11bccf3
URL: http://source.winehq.org/git/wine.git/?a=commit;h=0a44a778f00c5283347646083f682333c11bccf3
Author: Aric Stewart <aric at codeweavers.com>
Date: Mon Mar 31 09:15:29 2008 -0500
imm32: Begin to add basic framework for loading IMEs as dlls.
---
dlls/imm32/imm.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 134 insertions(+), 0 deletions(-)
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c
index 950fdc5..9173d1b 100644
--- a/dlls/imm32/imm.c
+++ b/dlls/imm32/imm.c
@@ -31,6 +31,7 @@
#include "ddk/imm.h"
#include "winnls.h"
#include "winreg.h"
+#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(imm);
@@ -44,6 +45,35 @@ typedef struct tagIMCCInternal
DWORD dwSize;
} IMCCInternal;
+#define MAKE_FUNCPTR(f) typeof(f) * p##f
+typedef struct _tagImmHkl{
+ struct list entry;
+ HKL hkl;
+ HMODULE hIME;
+ IMEINFO imeInfo;
+ WCHAR imeClassName[17]; /* 16 character max */
+ ULONG uSelected;
+
+ /* Function Pointers */
+ MAKE_FUNCPTR(ImeInquire);
+ MAKE_FUNCPTR(ImeConfigure);
+ MAKE_FUNCPTR(ImeDestroy);
+ MAKE_FUNCPTR(ImeEscape);
+ MAKE_FUNCPTR(ImeSelect);
+ MAKE_FUNCPTR(ImeSetActiveContext);
+ MAKE_FUNCPTR(ImeToAsciiEx);
+ MAKE_FUNCPTR(NotifyIME);
+ MAKE_FUNCPTR(ImeRegisterWord);
+ MAKE_FUNCPTR(ImeUnregisterWord);
+ MAKE_FUNCPTR(ImeEnumRegisterWord);
+ MAKE_FUNCPTR(ImeSetCompositionString);
+ MAKE_FUNCPTR(ImeConversionList);
+ MAKE_FUNCPTR(ImeProcessKey);
+ MAKE_FUNCPTR(ImeGetRegisterWordStyle);
+ MAKE_FUNCPTR(ImeGetImeMenuItems);
+} ImmHkl;
+#undef MAKE_FUNCPTR
+
typedef struct tagInputContextData
{
BOOL bInternalState;
@@ -53,6 +83,8 @@ typedef struct tagInputContextData
DWORD dwLock;
INPUTCONTEXT IMC;
+
+ ImmHkl *immKbd;
} InputContextData;
typedef struct _tagTRANSMSG {
@@ -67,6 +99,8 @@ static HANDLE hImeInst;
static const WCHAR WC_IMECLASSNAME[] = {'I','M','E',0};
static ATOM atIMEClass = 0;
+static struct list ImmHklList = LIST_INIT(ImmHklList);
+
/* MSIME messages */
static UINT WM_MSIME_SERVICE;
static UINT WM_MSIME_RECONVERTOPTIONS;
@@ -86,6 +120,77 @@ static void ImmInternalPostIMEMessage(InputContextData*, UINT, WPARAM, LPARAM);
static void ImmInternalSetOpenStatus(BOOL fOpen);
static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len);
+/* 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];
+
+ TRACE("Seeking ime for keyboard 0x%x\n",(unsigned)hkl);
+
+ 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;
+ ImmGetIMEFileNameW(hkl, filename, MAX_PATH);
+ ptr->hIME = LoadLibraryW(filename);
+ if (ptr->hIME)
+ {
+ LOAD_FUNCPTR(ImeInquire);
+ LOAD_FUNCPTR(ImeDestroy);
+ LOAD_FUNCPTR(ImeSelect);
+ if (!ptr->pImeInquire || !ptr->pImeDestroy || !ptr->pImeSelect)
+ {
+ FreeLibrary(ptr->hIME);
+ ptr->hIME = NULL;
+ }
+ else
+ {
+ ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL);
+ 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);
+ }
+ }
+ list_add_head(&ImmHklList,&ptr->entry);
+
+ return ptr;
+}
+#undef LOAD_FUNCPTR
+
+static void IMM_FreeAllImmHkl(void)
+{
+ ImmHkl *ptr,*cursor2;
+
+ LIST_FOR_EACH_ENTRY_SAFE(ptr, cursor2, &ImmHklList, ImmHkl, entry);
+ {
+ list_remove(&ptr->entry);
+ if (ptr->hIME)
+ {
+ ptr->pImeDestroy(1);
+ FreeLibrary(ptr->hIME);
+ }
+ HeapFree(GetProcessHeap(),0,ptr);
+ }
+}
+
static VOID IMM_PostResult(InputContextData *data)
{
unsigned int i;
@@ -167,6 +272,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
hwndDefault = 0;
}
IMM_Unregister();
+ IMM_FreeAllImmHkl();
break;
}
return TRUE;
@@ -610,10 +716,34 @@ HIMC WINAPI ImmCreateContext(void)
new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
+ /* Load the IME */
+ new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0));
+
+ /*
+ * Once we depend on the IME for all the processing like we should
+ * these will become hard errors and result in creation failures
+ */
+ if (!new_context->immKbd->hIME)
+ TRACE("IME dll could not be loaded\n");
+
/* hCompStr is never NULL */
new_context->IMC.hCompStr = ImmCreateBlankCompStr();
new_context->IMC.hMsgBuf = ImmCreateIMCC(1);
+ /* Initialize the IME Private */
+ new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
+
+ if (new_context->immKbd->hIME &&
+ !new_context->immKbd->pImeSelect(new_context, TRUE))
+ {
+ TRACE("Selection of IME failed\n");
+ ImmDestroyContext(new_context);
+ return 0;
+ }
+
+ new_context->immKbd->uSelected++;
+ TRACE("Created context 0x%x\n",(UINT)new_context);
+
return (HIMC)new_context;
}
@@ -628,6 +758,10 @@ BOOL WINAPI ImmDestroyContext(HIMC hIMC)
if (hIMC)
{
+ data->immKbd->uSelected --;
+ if (data->immKbd->hIME)
+ data->immKbd->pImeSelect(hIMC, FALSE);
+
ImmDestroyIMCC(data->IMC.hCompStr);
ImmDestroyIMCC(data->IMC.hCandInfo);
ImmDestroyIMCC(data->IMC.hGuideLine);
More information about the wine-cvs
mailing list