imm: Implement GetCompositionFont.
[wine/hacks.git] / dlls / imm32 / imm.c
blobab57bcea4b1c2c5323404ae2329d3ba07ad6c07c
1 /*
2 * IMM32 library
4 * Copyright 1998 Patrik Stridvall
5 * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "winerror.h"
29 #include "wine/debug.h"
30 #include "imm.h"
31 #include "ddk/imm.h"
32 #include "winnls.h"
33 #include "winreg.h"
34 #include "wine/list.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(imm);
38 #define FROM_IME 0xcafe1337
40 static void (*pX11DRV_ForceXIMReset)(HWND);
42 typedef struct tagIMCCInternal
44 DWORD dwLock;
45 DWORD dwSize;
46 } IMCCInternal;
48 #define MAKE_FUNCPTR(f) typeof(f) * p##f
49 typedef struct _tagImmHkl{
50 struct list entry;
51 HKL hkl;
52 HMODULE hIME;
53 IMEINFO imeInfo;
54 WCHAR imeClassName[17]; /* 16 character max */
55 ULONG uSelected;
57 /* Function Pointers */
58 MAKE_FUNCPTR(ImeInquire);
59 MAKE_FUNCPTR(ImeConfigure);
60 MAKE_FUNCPTR(ImeDestroy);
61 MAKE_FUNCPTR(ImeEscape);
62 MAKE_FUNCPTR(ImeSelect);
63 MAKE_FUNCPTR(ImeSetActiveContext);
64 MAKE_FUNCPTR(ImeToAsciiEx);
65 MAKE_FUNCPTR(NotifyIME);
66 MAKE_FUNCPTR(ImeRegisterWord);
67 MAKE_FUNCPTR(ImeUnregisterWord);
68 MAKE_FUNCPTR(ImeEnumRegisterWord);
69 MAKE_FUNCPTR(ImeSetCompositionString);
70 MAKE_FUNCPTR(ImeConversionList);
71 MAKE_FUNCPTR(ImeProcessKey);
72 MAKE_FUNCPTR(ImeGetRegisterWordStyle);
73 MAKE_FUNCPTR(ImeGetImeMenuItems);
74 } ImmHkl;
75 #undef MAKE_FUNCPTR
77 typedef struct tagInputContextData
79 BOOL bInternalState;
80 BOOL bRead;
81 BOOL bInComposition;
82 HFONT textfont;
84 DWORD dwLock;
85 INPUTCONTEXT IMC;
87 ImmHkl *immKbd;
88 } InputContextData;
90 typedef struct _tagTRANSMSG {
91 UINT message;
92 WPARAM wParam;
93 LPARAM lParam;
94 } TRANSMSG, *LPTRANSMSG;
96 static InputContextData *root_context = NULL;
97 static HWND hwndDefault = NULL;
98 static HANDLE hImeInst;
99 static const WCHAR WC_IMECLASSNAME[] = {'I','M','E',0};
100 static ATOM atIMEClass = 0;
102 static struct list ImmHklList = LIST_INIT(ImmHklList);
104 /* MSIME messages */
105 static UINT WM_MSIME_SERVICE;
106 static UINT WM_MSIME_RECONVERTOPTIONS;
107 static UINT WM_MSIME_MOUSE;
108 static UINT WM_MSIME_RECONVERTREQUEST;
109 static UINT WM_MSIME_RECONVERT;
110 static UINT WM_MSIME_QUERYPOSITION;
111 static UINT WM_MSIME_DOCUMENTFEED;
114 * prototypes
116 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
117 LPARAM lParam);
118 static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable);
119 static void ImmInternalPostIMEMessage(InputContextData*, UINT, WPARAM, LPARAM);
120 static void ImmInternalSetOpenStatus(BOOL fOpen);
121 static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len);
123 /* ImmHkl loading and freeing */
124 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
125 static ImmHkl *IMM_GetImmHkl(HKL hkl)
127 ImmHkl *ptr;
128 WCHAR filename[MAX_PATH];
130 TRACE("Seeking ime for keyboard 0x%x\n",(unsigned)hkl);
132 LIST_FOR_EACH_ENTRY(ptr, &ImmHklList, ImmHkl, entry)
134 if (ptr->hkl == hkl)
135 return ptr;
137 /* not found... create it */
139 ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ImmHkl));
141 ptr->hkl = hkl;
142 if (ImmGetIMEFileNameW(hkl, filename, MAX_PATH)) ptr->hIME = LoadLibraryW(filename);
143 if (ptr->hIME)
145 LOAD_FUNCPTR(ImeInquire);
146 LOAD_FUNCPTR(ImeDestroy);
147 LOAD_FUNCPTR(ImeSelect);
148 if (!ptr->pImeInquire || !ptr->pImeDestroy || !ptr->pImeSelect)
150 FreeLibrary(ptr->hIME);
151 ptr->hIME = NULL;
153 else
155 ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL);
156 LOAD_FUNCPTR(ImeConfigure);
157 LOAD_FUNCPTR(ImeEscape);
158 LOAD_FUNCPTR(ImeSetActiveContext);
159 LOAD_FUNCPTR(ImeToAsciiEx);
160 LOAD_FUNCPTR(NotifyIME);
161 LOAD_FUNCPTR(ImeRegisterWord);
162 LOAD_FUNCPTR(ImeUnregisterWord);
163 LOAD_FUNCPTR(ImeEnumRegisterWord);
164 LOAD_FUNCPTR(ImeSetCompositionString);
165 LOAD_FUNCPTR(ImeConversionList);
166 LOAD_FUNCPTR(ImeProcessKey);
167 LOAD_FUNCPTR(ImeGetRegisterWordStyle);
168 LOAD_FUNCPTR(ImeGetImeMenuItems);
171 list_add_head(&ImmHklList,&ptr->entry);
173 return ptr;
175 #undef LOAD_FUNCPTR
177 static void IMM_FreeAllImmHkl(void)
179 ImmHkl *ptr,*cursor2;
181 LIST_FOR_EACH_ENTRY_SAFE(ptr, cursor2, &ImmHklList, ImmHkl, entry)
183 list_remove(&ptr->entry);
184 if (ptr->hIME)
186 ptr->pImeDestroy(1);
187 FreeLibrary(ptr->hIME);
189 HeapFree(GetProcessHeap(),0,ptr);
193 static VOID IMM_PostResult(InputContextData *data)
195 unsigned int i;
196 LPCOMPOSITIONSTRING compstr;
197 LPBYTE compdata;
198 LPWSTR ResultStr;
199 HIMCC newCompStr;
201 TRACE("Posting result as IME_CHAR\n");
202 compdata = ImmLockIMCC(root_context->IMC.hCompStr);
203 compstr = (LPCOMPOSITIONSTRING)compdata;
204 ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
206 for (i = 0; i < compstr->dwResultStrLen; i++)
207 ImmInternalPostIMEMessage (root_context, WM_IME_CHAR, ResultStr[i], 1);
209 ImmUnlockIMCC(root_context->IMC.hCompStr);
211 /* clear the buffer */
212 newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0);
213 ImmDestroyIMCC(root_context->IMC.hCompStr);
214 root_context->IMC.hCompStr = newCompStr;
217 static void IMM_Register(void)
219 WNDCLASSW wndClass;
220 ZeroMemory(&wndClass, sizeof(WNDCLASSW));
221 wndClass.style = CS_GLOBALCLASS | CS_IME | CS_HREDRAW | CS_VREDRAW;
222 wndClass.lpfnWndProc = (WNDPROC) IME_WindowProc;
223 wndClass.cbClsExtra = 0;
224 wndClass.cbWndExtra = 0;
225 wndClass.hInstance = hImeInst;
226 wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
227 wndClass.hIcon = NULL;
228 wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW +1);
229 wndClass.lpszMenuName = 0;
230 wndClass.lpszClassName = WC_IMECLASSNAME;
231 atIMEClass = RegisterClassW(&wndClass);
234 static void IMM_Unregister(void)
236 if (atIMEClass) {
237 UnregisterClassW(WC_IMECLASSNAME, NULL);
241 static void IMM_RegisterMessages(void)
243 WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");
244 WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions");
245 WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
246 WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
247 WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
248 WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
249 WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
253 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
255 HMODULE x11drv;
257 TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
258 switch (fdwReason)
260 case DLL_PROCESS_ATTACH:
261 DisableThreadLibraryCalls(hInstDLL);
262 hImeInst = hInstDLL;
263 IMM_RegisterMessages();
264 x11drv = GetModuleHandleA("winex11.drv");
265 if (x11drv) pX11DRV_ForceXIMReset = (void *)GetProcAddress( x11drv, "ForceXIMReset");
266 break;
267 case DLL_PROCESS_DETACH:
268 if (hwndDefault)
270 DestroyWindow(hwndDefault);
271 hwndDefault = 0;
273 IMM_Unregister();
274 IMM_FreeAllImmHkl();
275 break;
277 return TRUE;
280 /* for posting messages as the IME */
281 static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
283 HWND target = GetFocus();
284 if (!target)
285 PostMessageW(data->IMC.hWnd,msg,wParam,lParam);
286 else
287 PostMessageW(target, msg, wParam, lParam);
290 static LRESULT ImmInternalSendIMENotify(InputContextData *data, WPARAM notify, LPARAM lParam)
292 HWND target;
294 target = data->IMC.hWnd;
295 if (!target) target = GetFocus();
297 if (target)
298 return SendMessageW(target, WM_IME_NOTIFY, notify, lParam);
300 return 0;
303 static HIMCC ImmCreateBlankCompStr(void)
305 HIMCC rc;
306 LPCOMPOSITIONSTRING ptr;
307 rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
308 ptr = (LPCOMPOSITIONSTRING)ImmLockIMCC(rc);
309 memset(ptr,0,sizeof(COMPOSITIONSTRING));
310 ptr->dwSize = sizeof(COMPOSITIONSTRING);
311 ImmUnlockIMCC(rc);
312 return rc;
315 static void ImmInternalSetOpenStatus(BOOL fOpen)
317 TRACE("Setting internal state to %s\n",(fOpen)?"OPEN":"CLOSED");
319 if (root_context->IMC.fOpen && fOpen == FALSE)
321 ShowWindow(hwndDefault,SW_HIDE);
322 ImmDestroyIMCC(root_context->IMC.hCompStr);
323 root_context->IMC.hCompStr = ImmCreateBlankCompStr();
326 root_context->IMC.fOpen = fOpen;
327 root_context->bInternalState = fOpen;
329 ImmInternalSendIMENotify(root_context, IMN_SETOPENSTATUS, 0);
332 static int updateField(DWORD origLen, DWORD origOffset, DWORD currentOffset,
333 LPBYTE target, LPBYTE source, DWORD* lenParam,
334 DWORD* offsetParam, BOOL wchars )
336 if (origLen > 0 && origOffset > 0)
338 int truelen = origLen;
339 if (wchars)
340 truelen *= sizeof(WCHAR);
342 memcpy(&target[currentOffset], &source[origOffset], truelen);
344 *lenParam = origLen;
345 *offsetParam = currentOffset;
346 currentOffset += truelen;
348 return currentOffset;
351 static HIMCC updateCompStr(HIMCC old, LPWSTR compstr, DWORD len)
353 /* we need to make sure the CompStr, CompClaus and CompAttr fields are all
354 * set and correct */
355 int needed_size;
356 HIMCC rc;
357 LPBYTE newdata = NULL;
358 LPBYTE olddata = NULL;
359 LPCOMPOSITIONSTRING new_one;
360 LPCOMPOSITIONSTRING lpcs = NULL;
361 INT current_offset = 0;
363 TRACE("%s, %i\n",debugstr_wn(compstr,len),len);
365 if (old == NULL && compstr == NULL && len == 0)
366 return NULL;
368 if (old != NULL)
370 olddata = ImmLockIMCC(old);
371 lpcs = (LPCOMPOSITIONSTRING)olddata;
374 needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
375 len + sizeof(DWORD) * 2;
377 if (lpcs != NULL)
379 needed_size += lpcs->dwCompReadAttrLen;
380 needed_size += lpcs->dwCompReadClauseLen;
381 needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
382 needed_size += lpcs->dwResultReadClauseLen;
383 needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
384 needed_size += lpcs->dwResultClauseLen;
385 needed_size += lpcs->dwResultStrLen * sizeof(DWORD);
386 needed_size += lpcs->dwPrivateSize;
388 rc = ImmCreateIMCC(needed_size);
389 newdata = ImmLockIMCC(rc);
390 new_one = (LPCOMPOSITIONSTRING)newdata;
392 new_one->dwSize = needed_size;
393 current_offset = sizeof(COMPOSITIONSTRING);
394 if (lpcs != NULL)
396 current_offset = updateField(lpcs->dwCompReadAttrLen,
397 lpcs->dwCompReadAttrOffset,
398 current_offset, newdata, olddata,
399 &new_one->dwCompReadAttrLen,
400 &new_one->dwCompReadAttrOffset, FALSE);
402 current_offset = updateField(lpcs->dwCompReadClauseLen,
403 lpcs->dwCompReadClauseOffset,
404 current_offset, newdata, olddata,
405 &new_one->dwCompReadClauseLen,
406 &new_one->dwCompReadClauseOffset, FALSE);
408 current_offset = updateField(lpcs->dwCompReadStrLen,
409 lpcs->dwCompReadStrOffset,
410 current_offset, newdata, olddata,
411 &new_one->dwCompReadStrLen,
412 &new_one->dwCompReadStrOffset, TRUE);
414 /* new CompAttr, CompClause, CompStr, dwCursorPos */
415 new_one->dwDeltaStart = 0;
417 current_offset = updateField(lpcs->dwResultReadClauseLen,
418 lpcs->dwResultReadClauseOffset,
419 current_offset, newdata, olddata,
420 &new_one->dwResultReadClauseLen,
421 &new_one->dwResultReadClauseOffset, FALSE);
423 current_offset = updateField(lpcs->dwResultReadStrLen,
424 lpcs->dwResultReadStrOffset,
425 current_offset, newdata, olddata,
426 &new_one->dwResultReadStrLen,
427 &new_one->dwResultReadStrOffset, TRUE);
429 current_offset = updateField(lpcs->dwResultClauseLen,
430 lpcs->dwResultClauseOffset,
431 current_offset, newdata, olddata,
432 &new_one->dwResultClauseLen,
433 &new_one->dwResultClauseOffset, FALSE);
435 current_offset = updateField(lpcs->dwResultStrLen,
436 lpcs->dwResultStrOffset,
437 current_offset, newdata, olddata,
438 &new_one->dwResultStrLen,
439 &new_one->dwResultStrOffset, TRUE);
441 current_offset = updateField(lpcs->dwPrivateSize,
442 lpcs->dwPrivateOffset,
443 current_offset, newdata, olddata,
444 &new_one->dwPrivateSize,
445 &new_one->dwPrivateOffset, FALSE);
448 /* set new data */
449 /* CompAttr */
450 new_one->dwCompAttrLen = len;
451 if (len > 0)
453 new_one->dwCompAttrOffset = current_offset;
454 memset(&newdata[current_offset],ATTR_INPUT,len);
455 current_offset += len;
458 /* CompClause */
459 if (len > 0)
461 new_one->dwCompClauseLen = sizeof(DWORD) * 2;
462 new_one->dwCompClauseOffset = current_offset;
463 *(DWORD*)(&newdata[current_offset]) = 0;
464 current_offset += sizeof(DWORD);
465 *(DWORD*)(&newdata[current_offset]) = len;
466 current_offset += sizeof(DWORD);
469 /* CompStr */
470 new_one->dwCompStrLen = len;
471 if (len > 0)
473 new_one->dwCompStrOffset = current_offset;
474 memcpy(&newdata[current_offset],compstr,len*sizeof(WCHAR));
477 /* CursorPos */
478 new_one->dwCursorPos = len;
480 ImmUnlockIMCC(rc);
481 if (lpcs)
482 ImmUnlockIMCC(old);
484 return rc;
487 static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len)
489 /* we need to make sure the ResultStr and ResultClause fields are all
490 * set and correct */
491 int needed_size;
492 HIMCC rc;
493 LPBYTE newdata = NULL;
494 LPBYTE olddata = NULL;
495 LPCOMPOSITIONSTRING new_one;
496 LPCOMPOSITIONSTRING lpcs = NULL;
497 INT current_offset = 0;
499 TRACE("%s, %i\n",debugstr_wn(resultstr,len),len);
501 if (old == NULL && resultstr == NULL && len == 0)
502 return NULL;
504 if (old != NULL)
506 olddata = ImmLockIMCC(old);
507 lpcs = (LPCOMPOSITIONSTRING)olddata;
510 needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
511 sizeof(DWORD) * 2;
513 if (lpcs != NULL)
515 needed_size += lpcs->dwCompReadAttrLen;
516 needed_size += lpcs->dwCompReadClauseLen;
517 needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
518 needed_size += lpcs->dwCompAttrLen;
519 needed_size += lpcs->dwCompClauseLen;
520 needed_size += lpcs->dwCompStrLen * sizeof(DWORD);
521 needed_size += lpcs->dwResultReadClauseLen;
522 needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
523 needed_size += lpcs->dwPrivateSize;
525 rc = ImmCreateIMCC(needed_size);
526 newdata = ImmLockIMCC(rc);
527 new_one = (LPCOMPOSITIONSTRING)newdata;
529 new_one->dwSize = needed_size;
530 current_offset = sizeof(COMPOSITIONSTRING);
531 if (lpcs != NULL)
533 current_offset = updateField(lpcs->dwCompReadAttrLen,
534 lpcs->dwCompReadAttrOffset,
535 current_offset, newdata, olddata,
536 &new_one->dwCompReadAttrLen,
537 &new_one->dwCompReadAttrOffset, FALSE);
539 current_offset = updateField(lpcs->dwCompReadClauseLen,
540 lpcs->dwCompReadClauseOffset,
541 current_offset, newdata, olddata,
542 &new_one->dwCompReadClauseLen,
543 &new_one->dwCompReadClauseOffset, FALSE);
545 current_offset = updateField(lpcs->dwCompReadStrLen,
546 lpcs->dwCompReadStrOffset,
547 current_offset, newdata, olddata,
548 &new_one->dwCompReadStrLen,
549 &new_one->dwCompReadStrOffset, TRUE);
551 current_offset = updateField(lpcs->dwCompAttrLen,
552 lpcs->dwCompAttrOffset,
553 current_offset, newdata, olddata,
554 &new_one->dwCompAttrLen,
555 &new_one->dwCompAttrOffset, FALSE);
557 current_offset = updateField(lpcs->dwCompClauseLen,
558 lpcs->dwCompClauseOffset,
559 current_offset, newdata, olddata,
560 &new_one->dwCompClauseLen,
561 &new_one->dwCompClauseOffset, FALSE);
563 current_offset = updateField(lpcs->dwCompStrLen,
564 lpcs->dwCompStrOffset,
565 current_offset, newdata, olddata,
566 &new_one->dwCompStrLen,
567 &new_one->dwCompStrOffset, TRUE);
569 new_one->dwCursorPos = lpcs->dwCursorPos;
570 new_one->dwDeltaStart = 0;
572 current_offset = updateField(lpcs->dwResultReadClauseLen,
573 lpcs->dwResultReadClauseOffset,
574 current_offset, newdata, olddata,
575 &new_one->dwResultReadClauseLen,
576 &new_one->dwResultReadClauseOffset, FALSE);
578 current_offset = updateField(lpcs->dwResultReadStrLen,
579 lpcs->dwResultReadStrOffset,
580 current_offset, newdata, olddata,
581 &new_one->dwResultReadStrLen,
582 &new_one->dwResultReadStrOffset, TRUE);
584 /* new ResultClause , ResultStr */
586 current_offset = updateField(lpcs->dwPrivateSize,
587 lpcs->dwPrivateOffset,
588 current_offset, newdata, olddata,
589 &new_one->dwPrivateSize,
590 &new_one->dwPrivateOffset, FALSE);
593 /* set new data */
594 /* ResultClause */
595 if (len > 0)
597 new_one->dwResultClauseLen = sizeof(DWORD) * 2;
598 new_one->dwResultClauseOffset = current_offset;
599 *(DWORD*)(&newdata[current_offset]) = 0;
600 current_offset += sizeof(DWORD);
601 *(DWORD*)(&newdata[current_offset]) = len;
602 current_offset += sizeof(DWORD);
605 /* ResultStr */
606 new_one->dwResultStrLen = len;
607 if (len > 0)
609 new_one->dwResultStrOffset = current_offset;
610 memcpy(&newdata[current_offset],resultstr,len*sizeof(WCHAR));
612 ImmUnlockIMCC(rc);
613 if (lpcs)
614 ImmUnlockIMCC(old);
616 return rc;
621 /***********************************************************************
622 * ImmAssociateContext (IMM32.@)
624 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
626 InputContextData *data = (InputContextData*)hIMC;
628 WARN("(%p, %p): semi-stub\n", hWnd, hIMC);
630 if (!hIMC)
631 return NULL;
634 * WINE SPECIFIC! MAY CONFLICT
635 * associate the root context we have an XIM created
637 if (hWnd == 0x000)
639 root_context = (InputContextData*)hIMC;
643 * If already associated just return
645 if (data->IMC.hWnd == hWnd)
646 return hIMC;
648 if (IsWindow(data->IMC.hWnd))
651 * Post a message that your context is switching
653 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
656 data->IMC.hWnd = hWnd;
658 if (IsWindow(data->IMC.hWnd))
661 * Post a message that your context is switching
663 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
667 * TODO: We need to keep track of the old context associated
668 * with a window and return it for now we will return NULL;
670 return NULL;
673 /***********************************************************************
674 * ImmAssociateContextEx (IMM32.@)
676 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
678 FIXME("(%p, %p, %d): stub\n", hWnd, hIMC, dwFlags);
679 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
680 return FALSE;
683 /***********************************************************************
684 * ImmConfigureIMEA (IMM32.@)
686 BOOL WINAPI ImmConfigureIMEA(
687 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
689 FIXME("(%p, %p, %d, %p): stub\n",
690 hKL, hWnd, dwMode, lpData
692 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
693 return FALSE;
696 /***********************************************************************
697 * ImmConfigureIMEW (IMM32.@)
699 BOOL WINAPI ImmConfigureIMEW(
700 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
702 FIXME("(%p, %p, %d, %p): stub\n",
703 hKL, hWnd, dwMode, lpData
705 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
706 return FALSE;
709 /***********************************************************************
710 * ImmCreateContext (IMM32.@)
712 HIMC WINAPI ImmCreateContext(void)
714 InputContextData *new_context;
716 new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
718 /* Load the IME */
719 new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0));
722 * Once we depend on the IME for all the processing like we should
723 * these will become hard errors and result in creation failures
725 if (!new_context->immKbd->hIME)
726 TRACE("IME dll could not be loaded\n");
728 /* hCompStr is never NULL */
729 new_context->IMC.hCompStr = ImmCreateBlankCompStr();
730 new_context->IMC.hMsgBuf = ImmCreateIMCC(1);
732 /* Initialize the IME Private */
733 new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
735 if (new_context->immKbd->hIME &&
736 !new_context->immKbd->pImeSelect(new_context, TRUE))
738 TRACE("Selection of IME failed\n");
739 ImmDestroyContext(new_context);
740 return 0;
743 new_context->immKbd->uSelected++;
744 TRACE("Created context 0x%x\n",(UINT)new_context);
746 return (HIMC)new_context;
749 /***********************************************************************
750 * ImmDestroyContext (IMM32.@)
752 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
754 InputContextData *data = (InputContextData*)hIMC;
756 TRACE("Destroying %p\n",hIMC);
758 if (hIMC)
760 data->immKbd->uSelected --;
761 if (data->immKbd->hIME)
762 data->immKbd->pImeSelect(hIMC, FALSE);
764 ImmDestroyIMCC(data->IMC.hCompStr);
765 ImmDestroyIMCC(data->IMC.hCandInfo);
766 ImmDestroyIMCC(data->IMC.hGuideLine);
767 ImmDestroyIMCC(data->IMC.hPrivate);
768 ImmDestroyIMCC(data->IMC.hMsgBuf);
770 if (data->textfont)
772 DeleteObject(data->textfont);
773 data->textfont = NULL;
776 HeapFree(GetProcessHeap(),0,data);
778 return TRUE;
781 /***********************************************************************
782 * ImmDisableIME (IMM32.@)
784 BOOL WINAPI ImmDisableIME(DWORD idThread)
786 FIXME("(%d): stub\n", idThread);
787 return TRUE;
790 /***********************************************************************
791 * ImmEnumRegisterWordA (IMM32.@)
793 UINT WINAPI ImmEnumRegisterWordA(
794 HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
795 LPCSTR lpszReading, DWORD dwStyle,
796 LPCSTR lpszRegister, LPVOID lpData)
798 FIXME("(%p, %p, %s, %d, %s, %p): stub\n",
799 hKL, lpfnEnumProc,
800 debugstr_a(lpszReading), dwStyle,
801 debugstr_a(lpszRegister), lpData
803 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
804 return 0;
807 /***********************************************************************
808 * ImmEnumRegisterWordW (IMM32.@)
810 UINT WINAPI ImmEnumRegisterWordW(
811 HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
812 LPCWSTR lpszReading, DWORD dwStyle,
813 LPCWSTR lpszRegister, LPVOID lpData)
815 FIXME("(%p, %p, %s, %d, %s, %p): stub\n",
816 hKL, lpfnEnumProc,
817 debugstr_w(lpszReading), dwStyle,
818 debugstr_w(lpszRegister), lpData
820 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
821 return 0;
824 /***********************************************************************
825 * ImmEscapeA (IMM32.@)
827 LRESULT WINAPI ImmEscapeA(
828 HKL hKL, HIMC hIMC,
829 UINT uEscape, LPVOID lpData)
831 FIXME("(%p, %p, %d, %p): stub\n",
832 hKL, hIMC, uEscape, lpData
834 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
835 return 0;
838 /***********************************************************************
839 * ImmEscapeW (IMM32.@)
841 LRESULT WINAPI ImmEscapeW(
842 HKL hKL, HIMC hIMC,
843 UINT uEscape, LPVOID lpData)
845 FIXME("(%p, %p, %d, %p): stub\n",
846 hKL, hIMC, uEscape, lpData
848 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
849 return 0;
852 /***********************************************************************
853 * ImmGetCandidateListA (IMM32.@)
855 DWORD WINAPI ImmGetCandidateListA(
856 HIMC hIMC, DWORD deIndex,
857 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
859 FIXME("(%p, %d, %p, %d): stub\n",
860 hIMC, deIndex,
861 lpCandList, dwBufLen
863 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
864 return 0;
867 /***********************************************************************
868 * ImmGetCandidateListCountA (IMM32.@)
870 DWORD WINAPI ImmGetCandidateListCountA(
871 HIMC hIMC, LPDWORD lpdwListCount)
873 FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
874 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
875 return 0;
878 /***********************************************************************
879 * ImmGetCandidateListCountW (IMM32.@)
881 DWORD WINAPI ImmGetCandidateListCountW(
882 HIMC hIMC, LPDWORD lpdwListCount)
884 FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
885 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
886 return 0;
889 /***********************************************************************
890 * ImmGetCandidateListW (IMM32.@)
892 DWORD WINAPI ImmGetCandidateListW(
893 HIMC hIMC, DWORD deIndex,
894 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
896 FIXME("(%p, %d, %p, %d): stub\n",
897 hIMC, deIndex,
898 lpCandList, dwBufLen
900 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
901 return 0;
904 /***********************************************************************
905 * ImmGetCandidateWindow (IMM32.@)
907 BOOL WINAPI ImmGetCandidateWindow(
908 HIMC hIMC, DWORD dwBufLen, LPCANDIDATEFORM lpCandidate)
910 FIXME("(%p, %d, %p): stub\n", hIMC, dwBufLen, lpCandidate);
911 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
912 return FALSE;
915 /***********************************************************************
916 * ImmGetCompositionFontA (IMM32.@)
918 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
920 LOGFONTW lfW;
921 BOOL rc;
923 TRACE("(%p, %p):\n", hIMC, lplf);
925 rc = ImmGetCompositionFontW(hIMC,&lfW);
926 if (rc)
928 memcpy(lplf,&lfW,sizeof(LOGFONTA));
929 WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName,
930 LF_FACESIZE, NULL, NULL);
932 return rc;
935 /***********************************************************************
936 * ImmGetCompositionFontW (IMM32.@)
938 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
940 InputContextData *data = (InputContextData*)hIMC;
942 TRACE("(%p, %p):\n", hIMC, lplf);
944 if (!data)
945 return FALSE;
947 *lplf = data->IMC.lfFont.W;
949 return TRUE;
952 /***********************************************************************
953 * ImmGetCompositionStringA (IMM32.@)
955 LONG WINAPI ImmGetCompositionStringA(
956 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
958 CHAR *buf;
959 LONG rc = 0;
960 InputContextData *data = (InputContextData*)hIMC;
961 LPCOMPOSITIONSTRING compstr;
962 LPBYTE compdata;
964 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
966 if (!data)
967 return FALSE;
969 if (!data->IMC.hCompStr)
970 return FALSE;
972 compdata = ImmLockIMCC(data->IMC.hCompStr);
973 compstr = (LPCOMPOSITIONSTRING)compdata;
975 if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 &&
976 compstr->dwResultStrOffset > 0)
978 LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
980 TRACE("GSC_RESULTSTR %p %i\n",ResultStr,
981 compstr->dwResultStrLen);
983 buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwResultStrLen * 3 );
984 rc = WideCharToMultiByte(CP_ACP, 0, ResultStr,
985 compstr->dwResultStrLen , buf,
986 compstr->dwResultStrLen * 3, NULL, NULL);
987 if (dwBufLen >= rc)
988 memcpy(lpBuf,buf,rc);
990 data->bRead = TRUE;
991 HeapFree( GetProcessHeap(), 0, buf );
993 else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 &&
994 compstr->dwCompStrOffset > 0)
996 LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
998 TRACE("GSC_COMPSTR %p %i\n", CompString, compstr->dwCompStrLen);
1000 buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwCompStrLen * 3 );
1001 rc = WideCharToMultiByte(CP_ACP, 0, CompString,
1002 compstr->dwCompStrLen, buf,
1003 compstr->dwCompStrLen * 3, NULL, NULL);
1004 if (dwBufLen >= rc)
1005 memcpy(lpBuf,buf,rc);
1006 HeapFree( GetProcessHeap(), 0, buf );
1008 else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 &&
1009 compstr->dwCompAttrOffset > 0)
1011 LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset);
1012 TRACE("GSC_COMPATTR %p %i\n", Compattr , compstr->dwCompAttrLen);
1014 rc = compstr->dwCompAttrLen;
1015 if (dwBufLen >= rc)
1016 memcpy(lpBuf,Compattr,rc);
1018 else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 &&
1019 compstr->dwCompClauseOffset > 0)
1021 LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset);
1022 TRACE("GSC_COMPCLAUSE %p %i\n", Compclause, compstr->dwCompClauseLen);
1024 rc = compstr->dwCompClauseLen;
1025 if (dwBufLen >= compstr->dwCompClauseLen)
1026 memcpy(lpBuf,Compclause,rc);
1028 else if (dwIndex == GCS_RESULTCLAUSE && compstr->dwResultClauseLen > 0 &&
1029 compstr->dwResultClauseOffset > 0)
1031 LPWSTR Resultclause = (LPWSTR)(compdata + compstr->dwResultClauseOffset);
1032 TRACE("GSC_RESULTCLAUSE %p %i\n", Resultclause, compstr->dwResultClauseLen);
1034 rc = compstr->dwResultClauseLen;
1035 if (dwBufLen >= compstr->dwResultClauseLen)
1036 memcpy(lpBuf,Resultclause,rc);
1038 else if (dwIndex == GCS_CURSORPOS)
1040 TRACE("GSC_CURSORPOS\n");
1041 rc = compstr->dwCursorPos;
1043 else if (dwIndex == GCS_DELTASTART)
1045 TRACE("GCS_DELTASTART\n");
1046 rc = compstr->dwDeltaStart;
1048 else
1050 FIXME("Unhandled index 0x%x\n",dwIndex);
1053 ImmUnlockIMCC(data->IMC.hCompStr);
1055 return rc;
1058 /***********************************************************************
1059 * ImmGetCompositionStringW (IMM32.@)
1061 LONG WINAPI ImmGetCompositionStringW(
1062 HIMC hIMC, DWORD dwIndex,
1063 LPVOID lpBuf, DWORD dwBufLen)
1065 LONG rc = 0;
1066 InputContextData *data = (InputContextData*)hIMC;
1067 LPCOMPOSITIONSTRING compstr;
1068 LPBYTE compdata;
1070 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
1072 if (!data)
1073 return FALSE;
1075 if (!data->IMC.hCompStr)
1076 return FALSE;
1078 compdata = ImmLockIMCC(data->IMC.hCompStr);
1079 compstr = (LPCOMPOSITIONSTRING)compdata;
1081 if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 &&
1082 compstr->dwResultStrOffset > 0)
1084 LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
1085 data->bRead = TRUE;
1086 rc = compstr->dwResultStrLen * sizeof(WCHAR);
1088 if (dwBufLen >= rc)
1089 memcpy(lpBuf,ResultStr,rc);
1091 else if (dwIndex == GCS_RESULTREADSTR && compstr->dwResultReadStrLen > 0 &&
1092 compstr->dwResultReadStrOffset > 0)
1094 LPWSTR ResultReadString = (LPWSTR)(compdata + compstr->dwResultReadStrOffset);
1096 rc = compstr->dwResultReadStrLen * sizeof(WCHAR);
1097 if (dwBufLen >= rc)
1098 memcpy(lpBuf,ResultReadString,rc);
1100 else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 &&
1101 compstr->dwCompStrOffset > 0)
1103 LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
1104 rc = compstr->dwCompStrLen * sizeof(WCHAR);
1105 if (dwBufLen >= rc)
1106 memcpy(lpBuf,CompString,rc);
1108 else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 &&
1109 compstr->dwCompAttrOffset > 0)
1112 LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset);
1114 rc = compstr->dwCompAttrLen;
1115 if (dwBufLen >= rc)
1116 memcpy(lpBuf,Compattr,rc);
1118 else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 &&
1119 compstr->dwCompClauseOffset > 0)
1121 LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset);
1123 rc = compstr->dwCompClauseLen;
1124 if (dwBufLen >= compstr->dwCompClauseLen)
1125 memcpy(lpBuf,Compclause,rc);
1127 else if (dwIndex == GCS_COMPREADSTR && compstr->dwCompReadStrLen > 0 &&
1128 compstr->dwCompReadStrOffset > 0)
1130 LPWSTR CompReadString = (LPWSTR)(compdata + compstr->dwCompReadStrOffset);
1132 rc = compstr->dwCompReadStrLen * sizeof(WCHAR);
1134 if (dwBufLen >= rc)
1135 memcpy(lpBuf,CompReadString,rc);
1137 else if (dwIndex == GCS_CURSORPOS)
1139 TRACE("GSC_CURSORPOS\n");
1140 rc = compstr->dwCursorPos;
1142 else if (dwIndex == GCS_DELTASTART)
1144 TRACE("GCS_DELTASTART\n");
1145 rc = compstr->dwDeltaStart;
1147 else
1149 FIXME("Unhandled index 0x%x\n",dwIndex);
1152 ImmUnlockIMCC(data->IMC.hCompStr);
1154 return rc;
1157 /***********************************************************************
1158 * ImmGetCompositionWindow (IMM32.@)
1160 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1162 InputContextData *data = (InputContextData*)hIMC;
1164 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1166 if (!data)
1167 return FALSE;
1169 *lpCompForm = data->IMC.cfCompForm;
1170 return 1;
1173 /***********************************************************************
1174 * ImmGetContext (IMM32.@)
1177 HIMC WINAPI ImmGetContext(HWND hWnd)
1179 TRACE("%p\n", hWnd);
1181 if (!root_context)
1182 return NULL;
1184 root_context->IMC.hWnd = hWnd;
1185 return (HIMC)root_context;
1188 /***********************************************************************
1189 * ImmGetConversionListA (IMM32.@)
1191 DWORD WINAPI ImmGetConversionListA(
1192 HKL hKL, HIMC hIMC,
1193 LPCSTR pSrc, LPCANDIDATELIST lpDst,
1194 DWORD dwBufLen, UINT uFlag)
1196 FIXME("(%p, %p, %s, %p, %d, %d): stub\n",
1197 hKL, hIMC, debugstr_a(pSrc), lpDst, dwBufLen, uFlag
1199 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1200 return 0;
1203 /***********************************************************************
1204 * ImmGetConversionListW (IMM32.@)
1206 DWORD WINAPI ImmGetConversionListW(
1207 HKL hKL, HIMC hIMC,
1208 LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1209 DWORD dwBufLen, UINT uFlag)
1211 FIXME("(%p, %p, %s, %p, %d, %d): stub\n",
1212 hKL, hIMC, debugstr_w(pSrc), lpDst, dwBufLen, uFlag
1214 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1215 return 0;
1218 /***********************************************************************
1219 * ImmGetConversionStatus (IMM32.@)
1221 BOOL WINAPI ImmGetConversionStatus(
1222 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1224 TRACE("(%p, %p, %p): best guess\n", hIMC, lpfdwConversion, lpfdwSentence);
1225 if (lpfdwConversion)
1226 *lpfdwConversion = IME_CMODE_NATIVE;
1227 if (lpfdwSentence)
1228 *lpfdwSentence = IME_SMODE_NONE;
1229 return TRUE;
1232 /***********************************************************************
1233 * ImmGetDefaultIMEWnd (IMM32.@)
1235 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1237 static int shown = 0;
1239 if (!shown) {
1240 FIXME("(%p - %p %p ): semi-stub\n", hWnd,hwndDefault, root_context);
1241 shown = 1;
1244 if (hwndDefault == NULL)
1246 static const WCHAR the_name[] = {'I','M','E','\0'};
1248 IMM_Register();
1249 hwndDefault = CreateWindowExW( WS_EX_TOOLWINDOW, WC_IMECLASSNAME,
1250 the_name, WS_POPUP, 0, 0, 1, 1, 0, 0,
1251 hImeInst, 0);
1253 TRACE("Default created (%p)\n",hwndDefault);
1256 return hwndDefault;
1259 /***********************************************************************
1260 * ImmGetDescriptionA (IMM32.@)
1262 UINT WINAPI ImmGetDescriptionA(
1263 HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1265 WCHAR *buf;
1266 DWORD len;
1268 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1270 /* find out how many characters in the unicode buffer */
1271 len = ImmGetDescriptionW( hKL, NULL, 0 );
1273 /* allocate a buffer of that size */
1274 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1275 if( !buf )
1276 return 0;
1278 /* fetch the unicode buffer */
1279 len = ImmGetDescriptionW( hKL, buf, len + 1 );
1281 /* convert it back to ASCII */
1282 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1283 lpszDescription, uBufLen, NULL, NULL );
1285 HeapFree( GetProcessHeap(), 0, buf );
1287 return len;
1290 /***********************************************************************
1291 * ImmGetDescriptionW (IMM32.@)
1293 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1295 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1297 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1299 if (!uBufLen) return lstrlenW( name );
1300 lstrcpynW( lpszDescription, name, uBufLen );
1301 return lstrlenW( lpszDescription );
1304 /***********************************************************************
1305 * ImmGetGuideLineA (IMM32.@)
1307 DWORD WINAPI ImmGetGuideLineA(
1308 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1310 FIXME("(%p, %d, %s, %d): stub\n",
1311 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1313 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1314 return 0;
1317 /***********************************************************************
1318 * ImmGetGuideLineW (IMM32.@)
1320 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1322 FIXME("(%p, %d, %s, %d): stub\n",
1323 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1325 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1326 return 0;
1329 /***********************************************************************
1330 * ImmGetIMEFileNameA (IMM32.@)
1332 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1334 LPWSTR bufW = NULL;
1335 UINT wBufLen = uBufLen;
1336 UINT rc;
1338 if (uBufLen && lpszFileName)
1339 bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR));
1340 else /* We need this to get the number of byte required */
1342 bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR));
1343 wBufLen = MAX_PATH;
1346 rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen);
1348 if (rc > 0)
1350 if (uBufLen && lpszFileName)
1351 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName,
1352 uBufLen, NULL, NULL);
1353 else /* get the length */
1354 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL,
1355 NULL);
1358 HeapFree(GetProcessHeap(),0,bufW);
1359 return rc;
1362 /***********************************************************************
1363 * ImmGetIMEFileNameW (IMM32.@)
1365 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1367 static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
1368 static const WCHAR fmt[] = {'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','x',0};
1370 HKEY hkey;
1371 DWORD length;
1372 DWORD rc;
1373 WCHAR regKey[sizeof(fmt)/sizeof(WCHAR)+8];
1375 wsprintfW( regKey, fmt, (unsigned)hKL );
1376 rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey);
1377 if (rc != ERROR_SUCCESS)
1379 SetLastError(rc);
1380 return 0;
1383 length = 0;
1384 rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length);
1386 if (rc != ERROR_SUCCESS)
1388 RegCloseKey(hkey);
1389 SetLastError(rc);
1390 return 0;
1392 if (length > uBufLen * sizeof(WCHAR) || !lpszFileName)
1394 RegCloseKey(hkey);
1395 if (lpszFileName)
1397 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1398 return 0;
1400 else
1401 return length / sizeof(WCHAR);
1404 RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length);
1406 RegCloseKey(hkey);
1408 return length / sizeof(WCHAR);
1411 /***********************************************************************
1412 * ImmGetOpenStatus (IMM32.@)
1414 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1416 InputContextData *data = (InputContextData*)hIMC;
1418 if (!data)
1419 return FALSE;
1420 FIXME("(%p): semi-stub\n", hIMC);
1422 return data->IMC.fOpen;
1425 /***********************************************************************
1426 * ImmGetProperty (IMM32.@)
1428 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1430 DWORD rc = 0;
1431 TRACE("(%p, %d)\n", hKL, fdwIndex);
1433 switch (fdwIndex)
1435 case IGP_PROPERTY:
1436 TRACE("(%s)\n", "IGP_PROPERTY");
1437 rc = IME_PROP_UNICODE | IME_PROP_AT_CARET;
1438 break;
1439 case IGP_CONVERSION:
1440 FIXME("(%s)\n", "IGP_CONVERSION");
1441 rc = IME_CMODE_NATIVE;
1442 break;
1443 case IGP_SENTENCE:
1444 FIXME("%s)\n", "IGP_SENTENCE");
1445 rc = IME_SMODE_AUTOMATIC;
1446 break;
1447 case IGP_SETCOMPSTR:
1448 TRACE("(%s)\n", "IGP_SETCOMPSTR");
1449 rc = 0;
1450 break;
1451 case IGP_SELECT:
1452 TRACE("(%s)\n", "IGP_SELECT");
1453 rc = SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE;
1454 break;
1455 case IGP_GETIMEVERSION:
1456 TRACE("(%s)\n", "IGP_GETIMEVERSION");
1457 rc = IMEVER_0400;
1458 break;
1459 case IGP_UI:
1460 TRACE("(%s)\n", "IGP_UI");
1461 rc = 0;
1462 break;
1463 default:
1464 rc = 0;
1466 return rc;
1469 /***********************************************************************
1470 * ImmGetRegisterWordStyleA (IMM32.@)
1472 UINT WINAPI ImmGetRegisterWordStyleA(
1473 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1475 FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
1476 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1477 return 0;
1480 /***********************************************************************
1481 * ImmGetRegisterWordStyleW (IMM32.@)
1483 UINT WINAPI ImmGetRegisterWordStyleW(
1484 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1486 FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
1487 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1488 return 0;
1491 /***********************************************************************
1492 * ImmGetStatusWindowPos (IMM32.@)
1494 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1496 FIXME("(%p, %p): stub\n", hIMC, lpptPos);
1497 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1498 return FALSE;
1501 /***********************************************************************
1502 * ImmGetVirtualKey (IMM32.@)
1504 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1506 OSVERSIONINFOA version;
1507 FIXME("(%p): stub\n", hWnd);
1508 GetVersionExA( &version );
1509 switch(version.dwPlatformId)
1511 case VER_PLATFORM_WIN32_WINDOWS:
1512 return VK_PROCESSKEY;
1513 case VER_PLATFORM_WIN32_NT:
1514 return 0;
1515 default:
1516 FIXME("%d not supported\n",version.dwPlatformId);
1517 return VK_PROCESSKEY;
1521 /***********************************************************************
1522 * ImmInstallIMEA (IMM32.@)
1524 HKL WINAPI ImmInstallIMEA(
1525 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1527 FIXME("(%s, %s): stub\n",
1528 debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText)
1530 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1531 return NULL;
1534 /***********************************************************************
1535 * ImmInstallIMEW (IMM32.@)
1537 HKL WINAPI ImmInstallIMEW(
1538 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1540 FIXME("(%s, %s): stub\n",
1541 debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText)
1543 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1544 return NULL;
1547 /***********************************************************************
1548 * ImmIsIME (IMM32.@)
1550 BOOL WINAPI ImmIsIME(HKL hKL)
1552 TRACE("(%p): semi-stub\n", hKL);
1554 * FIXME: Dead key locales will return TRUE here when they should not
1555 * There is probably a more proper way to check this.
1557 return (root_context != NULL);
1560 /***********************************************************************
1561 * ImmIsUIMessageA (IMM32.@)
1563 BOOL WINAPI ImmIsUIMessageA(
1564 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1566 BOOL rc = FALSE;
1568 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1569 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1570 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1571 (msg == WM_MSIME_SERVICE) ||
1572 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1573 (msg == WM_MSIME_MOUSE) ||
1574 (msg == WM_MSIME_RECONVERTREQUEST) ||
1575 (msg == WM_MSIME_RECONVERT) ||
1576 (msg == WM_MSIME_QUERYPOSITION) ||
1577 (msg == WM_MSIME_DOCUMENTFEED))
1580 if (!hwndDefault)
1581 ImmGetDefaultIMEWnd(NULL);
1583 if (hWndIME == NULL)
1584 PostMessageA(hwndDefault, msg, wParam, lParam);
1586 rc = TRUE;
1588 return rc;
1591 /***********************************************************************
1592 * ImmIsUIMessageW (IMM32.@)
1594 BOOL WINAPI ImmIsUIMessageW(
1595 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1597 BOOL rc = FALSE;
1598 TRACE("(%p, %d, %ld, %ld): stub\n", hWndIME, msg, wParam, lParam);
1599 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1600 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1601 (msg == WM_MSIME_SERVICE) ||
1602 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1603 (msg == WM_MSIME_MOUSE) ||
1604 (msg == WM_MSIME_RECONVERTREQUEST) ||
1605 (msg == WM_MSIME_RECONVERT) ||
1606 (msg == WM_MSIME_QUERYPOSITION) ||
1607 (msg == WM_MSIME_DOCUMENTFEED))
1608 rc = TRUE;
1609 return rc;
1612 /***********************************************************************
1613 * ImmNotifyIME (IMM32.@)
1615 BOOL WINAPI ImmNotifyIME(
1616 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
1618 BOOL rc = FALSE;
1620 TRACE("(%p, %d, %d, %d)\n",
1621 hIMC, dwAction, dwIndex, dwValue);
1623 if (!root_context)
1624 return rc;
1626 switch(dwAction)
1628 case NI_CHANGECANDIDATELIST:
1629 FIXME("%s\n","NI_CHANGECANDIDATELIST");
1630 break;
1631 case NI_CLOSECANDIDATE:
1632 FIXME("%s\n","NI_CLOSECANDIDATE");
1633 break;
1634 case NI_COMPOSITIONSTR:
1635 switch (dwIndex)
1637 case CPS_CANCEL:
1638 TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_CANCEL");
1640 BOOL send;
1641 LPCOMPOSITIONSTRING lpCompStr;
1643 if (pX11DRV_ForceXIMReset)
1644 pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
1646 lpCompStr = ImmLockIMCC(root_context->IMC.hCompStr);
1647 send = (lpCompStr->dwCompStrLen != 0);
1648 ImmUnlockIMCC(root_context->IMC.hCompStr);
1650 ImmDestroyIMCC(root_context->IMC.hCompStr);
1651 root_context->IMC.hCompStr = ImmCreateBlankCompStr();
1653 if (send)
1654 ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION, 0,
1655 GCS_COMPSTR);
1656 rc = TRUE;
1658 break;
1659 case CPS_COMPLETE:
1660 TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_COMPLETE");
1661 if (hIMC != (HIMC)FROM_IME && pX11DRV_ForceXIMReset)
1662 pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
1664 HIMCC newCompStr;
1665 DWORD cplen = 0;
1666 LPWSTR cpstr;
1667 LPCOMPOSITIONSTRING cs = NULL;
1668 LPBYTE cdata = NULL;
1670 /* clear existing result */
1671 newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0);
1672 ImmDestroyIMCC(root_context->IMC.hCompStr);
1673 root_context->IMC.hCompStr = newCompStr;
1675 if (root_context->IMC.hCompStr)
1677 cdata = ImmLockIMCC(root_context->IMC.hCompStr);
1678 cs = (LPCOMPOSITIONSTRING)cdata;
1679 cplen = cs->dwCompStrLen;
1680 cpstr = (LPWSTR)&(cdata[cs->dwCompStrOffset]);
1681 ImmUnlockIMCC(root_context->IMC.hCompStr);
1683 if (cplen > 0)
1685 WCHAR param = cpstr[0];
1686 newCompStr = updateResultStr(root_context->IMC.hCompStr, cpstr, cplen);
1687 ImmDestroyIMCC(root_context->IMC.hCompStr);
1688 root_context->IMC.hCompStr = newCompStr;
1689 newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
1690 ImmDestroyIMCC(root_context->IMC.hCompStr);
1691 root_context->IMC.hCompStr = newCompStr;
1693 root_context->bRead = FALSE;
1695 ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION, 0,
1696 GCS_COMPSTR);
1698 ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION,
1699 param,
1700 GCS_RESULTSTR|GCS_RESULTCLAUSE);
1703 ImmInternalPostIMEMessage(root_context, WM_IME_ENDCOMPOSITION, 0, 0);
1704 root_context->bInComposition = FALSE;
1706 break;
1707 case CPS_CONVERT:
1708 FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_CONVERT");
1709 break;
1710 case CPS_REVERT:
1711 FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_REVERT");
1712 break;
1713 default:
1714 ERR("%s - %s (%i)\n","NI_COMPOSITIONSTR","UNKNOWN",dwIndex);
1715 break;
1717 break;
1718 case NI_IMEMENUSELECTED:
1719 FIXME("%s\n", "NI_IMEMENUSELECTED");
1720 break;
1721 case NI_OPENCANDIDATE:
1722 FIXME("%s\n", "NI_OPENCANDIDATE");
1723 break;
1724 case NI_SELECTCANDIDATESTR:
1725 FIXME("%s\n", "NI_SELECTCANDIDATESTR");
1726 break;
1727 case NI_SETCANDIDATE_PAGESIZE:
1728 FIXME("%s\n", "NI_SETCANDIDATE_PAGESIZE");
1729 break;
1730 case NI_SETCANDIDATE_PAGESTART:
1731 FIXME("%s\n", "NI_SETCANDIDATE_PAGESTART");
1732 break;
1733 default:
1734 ERR("Unknown\n");
1737 return rc;
1740 /***********************************************************************
1741 * ImmRegisterWordA (IMM32.@)
1743 BOOL WINAPI ImmRegisterWordA(
1744 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
1746 FIXME("(%p, %s, %d, %s): stub\n",
1747 hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister)
1749 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1750 return FALSE;
1753 /***********************************************************************
1754 * ImmRegisterWordW (IMM32.@)
1756 BOOL WINAPI ImmRegisterWordW(
1757 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
1759 FIXME("(%p, %s, %d, %s): stub\n",
1760 hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister)
1762 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1763 return FALSE;
1766 /***********************************************************************
1767 * ImmReleaseContext (IMM32.@)
1769 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
1771 static int shown = 0;
1773 if (!shown) {
1774 FIXME("(%p, %p): stub\n", hWnd, hIMC);
1775 shown = 1;
1777 return TRUE;
1780 /***********************************************************************
1781 * ImmSetCandidateWindow (IMM32.@)
1783 BOOL WINAPI ImmSetCandidateWindow(
1784 HIMC hIMC, LPCANDIDATEFORM lpCandidate)
1786 FIXME("(%p, %p): stub\n", hIMC, lpCandidate);
1787 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1788 return FALSE;
1791 /***********************************************************************
1792 * ImmSetCompositionFontA (IMM32.@)
1794 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1796 InputContextData *data = (InputContextData*)hIMC;
1797 TRACE("(%p, %p)\n", hIMC, lplf);
1799 if (!data)
1800 return FALSE;
1802 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
1803 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
1804 LF_FACESIZE);
1806 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
1808 if (data->textfont)
1810 DeleteObject(data->textfont);
1811 data->textfont = NULL;
1814 data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
1815 return TRUE;
1818 /***********************************************************************
1819 * ImmSetCompositionFontW (IMM32.@)
1821 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1823 InputContextData *data = (InputContextData*)hIMC;
1824 TRACE("(%p, %p)\n", hIMC, lplf);
1826 if (!data)
1827 return FALSE;
1829 data->IMC.lfFont.W = *lplf;
1830 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
1832 if (data->textfont)
1834 DeleteObject(data->textfont);
1835 data->textfont = NULL;
1837 data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
1838 return TRUE;
1841 /***********************************************************************
1842 * ImmSetCompositionStringA (IMM32.@)
1844 BOOL WINAPI ImmSetCompositionStringA(
1845 HIMC hIMC, DWORD dwIndex,
1846 LPCVOID lpComp, DWORD dwCompLen,
1847 LPCVOID lpRead, DWORD dwReadLen)
1849 DWORD comp_len;
1850 DWORD read_len;
1851 WCHAR *CompBuffer = NULL;
1852 WCHAR *ReadBuffer = NULL;
1853 BOOL rc;
1855 TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
1856 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
1858 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
1859 if (comp_len)
1861 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
1862 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
1865 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
1866 if (read_len)
1868 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
1869 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
1872 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
1873 ReadBuffer, read_len);
1875 HeapFree(GetProcessHeap(), 0, CompBuffer);
1876 HeapFree(GetProcessHeap(), 0, ReadBuffer);
1878 return rc;
1881 /***********************************************************************
1882 * ImmSetCompositionStringW (IMM32.@)
1884 BOOL WINAPI ImmSetCompositionStringW(
1885 HIMC hIMC, DWORD dwIndex,
1886 LPCVOID lpComp, DWORD dwCompLen,
1887 LPCVOID lpRead, DWORD dwReadLen)
1889 DWORD flags = 0;
1890 WCHAR wParam = 0;
1892 TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
1893 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
1896 if (hIMC != (HIMC)FROM_IME)
1897 FIXME("PROBLEM: This only sets the wine level string\n");
1900 * Explanation:
1901 * this sets the composition string in the imm32.dll level
1902 * of the composition buffer. we cannot manipulate the xim level
1903 * buffer, which means that once the xim level buffer changes again
1904 * any call to this function from the application will be lost
1907 if (lpRead && dwReadLen)
1908 FIXME("Reading string unimplemented\n");
1911 * app operating this api to also receive the message from xim
1914 if (dwIndex == SCS_SETSTR)
1916 HIMCC newCompStr;
1917 if (!root_context->bInComposition)
1919 ImmInternalPostIMEMessage(root_context, WM_IME_STARTCOMPOSITION, 0, 0);
1920 root_context->bInComposition = TRUE;
1923 flags = GCS_COMPSTR;
1925 if (dwCompLen && lpComp)
1927 newCompStr = updateCompStr(root_context->IMC.hCompStr, (LPWSTR)lpComp, dwCompLen / sizeof(WCHAR));
1928 ImmDestroyIMCC(root_context->IMC.hCompStr);
1929 root_context->IMC.hCompStr = newCompStr;
1931 wParam = ((const WCHAR*)lpComp)[0];
1932 flags |= GCS_COMPCLAUSE | GCS_COMPATTR | GCS_DELTASTART;
1934 else
1936 newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
1937 ImmDestroyIMCC(root_context->IMC.hCompStr);
1938 root_context->IMC.hCompStr = newCompStr;
1942 UpdateDataInDefaultIMEWindow(hwndDefault,FALSE);
1944 ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION, wParam, flags);
1946 return TRUE;
1949 /***********************************************************************
1950 * ImmSetCompositionWindow (IMM32.@)
1952 BOOL WINAPI ImmSetCompositionWindow(
1953 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1955 BOOL reshow = FALSE;
1956 InputContextData *data = (InputContextData*)hIMC;
1958 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1959 TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
1960 lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
1961 lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
1963 if (!data)
1964 return FALSE;
1966 data->IMC.cfCompForm = *lpCompForm;
1968 if (IsWindowVisible(hwndDefault))
1970 reshow = TRUE;
1971 ShowWindow(hwndDefault,SW_HIDE);
1974 /* FIXME: this is a partial stub */
1976 if (reshow)
1977 ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
1979 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0);
1980 return TRUE;
1983 /***********************************************************************
1984 * ImmSetConversionStatus (IMM32.@)
1986 BOOL WINAPI ImmSetConversionStatus(
1987 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
1989 static int shown = 0;
1991 if (!shown) {
1992 FIXME("(%p, %d, %d): stub\n",
1993 hIMC, fdwConversion, fdwSentence
1995 shown = 1;
1997 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1998 return FALSE;
2001 /***********************************************************************
2002 * ImmSetOpenStatus (IMM32.@)
2004 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
2006 InputContextData *data = (InputContextData*)hIMC;
2008 TRACE("%p %d\n", hIMC, fOpen);
2010 if (hIMC == (HIMC)FROM_IME)
2012 ImmInternalSetOpenStatus(fOpen);
2013 ImmInternalSendIMENotify(root_context, IMN_SETOPENSTATUS, 0);
2014 return TRUE;
2017 if (!data)
2018 return FALSE;
2020 if (fOpen != data->bInternalState)
2022 if (fOpen == FALSE && pX11DRV_ForceXIMReset)
2023 pX11DRV_ForceXIMReset(data->IMC.hWnd);
2025 if (fOpen == FALSE)
2026 ImmInternalPostIMEMessage(data, WM_IME_ENDCOMPOSITION,0,0);
2027 else
2028 ImmInternalPostIMEMessage(data, WM_IME_STARTCOMPOSITION,0,0);
2030 ImmInternalSetOpenStatus(fOpen);
2031 ImmInternalSetOpenStatus(!fOpen);
2033 if (data->IMC.fOpen == FALSE)
2034 ImmInternalPostIMEMessage(data, WM_IME_ENDCOMPOSITION,0,0);
2035 else
2036 ImmInternalPostIMEMessage(data, WM_IME_STARTCOMPOSITION,0,0);
2038 return FALSE;
2040 return TRUE;
2043 /***********************************************************************
2044 * ImmSetStatusWindowPos (IMM32.@)
2046 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
2048 FIXME("(%p, %p): stub\n", hIMC, lpptPos);
2049 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2050 return FALSE;
2053 /***********************************************************************
2054 * ImmSimulateHotKey (IMM32.@)
2056 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
2058 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
2059 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2060 return FALSE;
2063 /***********************************************************************
2064 * ImmUnregisterWordA (IMM32.@)
2066 BOOL WINAPI ImmUnregisterWordA(
2067 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
2069 FIXME("(%p, %s, %d, %s): stub\n",
2070 hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszUnregister)
2072 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2073 return FALSE;
2076 /***********************************************************************
2077 * ImmUnregisterWordW (IMM32.@)
2079 BOOL WINAPI ImmUnregisterWordW(
2080 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
2082 FIXME("(%p, %s, %d, %s): stub\n",
2083 hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszUnregister)
2085 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2086 return FALSE;
2089 /***********************************************************************
2090 * ImmGetImeMenuItemsA (IMM32.@)
2092 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2093 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
2094 DWORD dwSize)
2096 FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType,
2097 lpImeParentMenu, lpImeMenu, dwSize);
2098 return 0;
2101 /***********************************************************************
2102 * ImmGetImeMenuItemsW (IMM32.@)
2104 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2105 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
2106 DWORD dwSize)
2108 FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType,
2109 lpImeParentMenu, lpImeMenu, dwSize);
2110 return 0;
2113 /***********************************************************************
2114 * ImmLockIMC(IMM32.@)
2116 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
2118 InputContextData *data = (InputContextData*)hIMC;
2120 if (!data)
2121 return NULL;
2122 data->dwLock++;
2123 return &data->IMC;
2126 /***********************************************************************
2127 * ImmUnlockIMC(IMM32.@)
2129 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
2131 InputContextData *data = (InputContextData*)hIMC;
2132 data->dwLock--;
2133 return (data->dwLock!=0);
2136 /***********************************************************************
2137 * ImmGetIMCLockCount(IMM32.@)
2139 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
2141 InputContextData *data = (InputContextData*)hIMC;
2142 return data->dwLock;
2145 /***********************************************************************
2146 * ImmCreateIMCC(IMM32.@)
2148 HIMCC WINAPI ImmCreateIMCC(DWORD size)
2150 IMCCInternal *internal;
2151 int real_size = size + sizeof(IMCCInternal);
2153 internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size);
2154 if (internal == NULL)
2155 return NULL;
2157 internal->dwSize = size;
2158 return (HIMCC)internal;
2161 /***********************************************************************
2162 * ImmDestroyIMCC(IMM32.@)
2164 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
2166 HeapFree(GetProcessHeap(),0,block);
2167 return NULL;
2170 /***********************************************************************
2171 * ImmLockIMCC(IMM32.@)
2173 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
2175 IMCCInternal *internal;
2176 internal = (IMCCInternal*) imcc;
2178 internal->dwLock ++;
2179 return internal + 1;
2182 /***********************************************************************
2183 * ImmUnlockIMCC(IMM32.@)
2185 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
2187 IMCCInternal *internal;
2188 internal = (IMCCInternal*) imcc;
2190 internal->dwLock --;
2191 return (internal->dwLock!=0);
2194 /***********************************************************************
2195 * ImmGetIMCCLockCount(IMM32.@)
2197 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
2199 IMCCInternal *internal;
2200 internal = (IMCCInternal*) imcc;
2202 return internal->dwLock;
2205 /***********************************************************************
2206 * ImmReSizeIMCC(IMM32.@)
2208 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
2210 IMCCInternal *internal,*newone;
2211 int real_size = size + sizeof(IMCCInternal);
2213 internal = (IMCCInternal*) imcc;
2215 newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size);
2216 newone->dwSize = size;
2218 return newone;
2221 /***********************************************************************
2222 * ImmGetIMCCSize(IMM32.@)
2224 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2226 IMCCInternal *internal;
2227 internal = (IMCCInternal*) imcc;
2229 return internal->dwSize;
2232 /***********************************************************************
2233 * ImmGenerateMessage(IMM32.@)
2235 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2237 InputContextData *data = (InputContextData*)hIMC;
2239 TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
2240 if (data->IMC.dwNumMsgBuf > 0)
2242 LPTRANSMSG lpTransMsg;
2243 INT i;
2245 lpTransMsg = (LPTRANSMSG)ImmLockIMCC(data->IMC.hMsgBuf);
2246 for (i = 0; i < data->IMC.dwNumMsgBuf; i++)
2247 ImmInternalPostIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
2249 ImmUnlockIMCC(data->IMC.hMsgBuf);
2251 data->IMC.dwNumMsgBuf = 0;
2254 return TRUE;
2257 /*****
2258 * Internal functions to help with IME window management
2260 static void PaintDefaultIMEWnd(HWND hwnd)
2262 PAINTSTRUCT ps;
2263 RECT rect;
2264 HDC hdc = BeginPaint(hwnd,&ps);
2265 LPCOMPOSITIONSTRING compstr;
2266 LPBYTE compdata = NULL;
2267 HMONITOR monitor;
2268 MONITORINFO mon_info;
2269 INT offX=0, offY=0;
2271 GetClientRect(hwnd,&rect);
2272 FillRect(hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1));
2274 compdata = ImmLockIMCC(root_context->IMC.hCompStr);
2275 compstr = (LPCOMPOSITIONSTRING)compdata;
2277 if (compstr->dwCompStrLen && compstr->dwCompStrOffset)
2279 SIZE size;
2280 POINT pt;
2281 HFONT oldfont = NULL;
2282 LPWSTR CompString;
2284 CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
2285 if (root_context->textfont)
2286 oldfont = SelectObject(hdc,root_context->textfont);
2289 GetTextExtentPoint32W(hdc, CompString, compstr->dwCompStrLen, &size);
2290 pt.x = size.cx;
2291 pt.y = size.cy;
2292 LPtoDP(hdc,&pt,1);
2295 * How this works based on tests on windows:
2296 * CFS_POINT: then we start our window at the point and grow it as large
2297 * as it needs to be for the string.
2298 * CFS_RECT: we still use the ptCurrentPos as a starting point and our
2299 * window is only as large as we need for the string, but we do not
2300 * grow such that our window exceeds the given rect. Wrapping if
2301 * needed and possible. If our ptCurrentPos is outside of our rect
2302 * then no window is displayed.
2303 * CFS_FORCE_POSITION: appears to behave just like CFS_POINT
2304 * maybe becase the default MSIME does not do any IME adjusting.
2306 if (root_context->IMC.cfCompForm.dwStyle != CFS_DEFAULT)
2308 POINT cpt = root_context->IMC.cfCompForm.ptCurrentPos;
2309 ClientToScreen(root_context->IMC.hWnd,&cpt);
2310 rect.left = cpt.x;
2311 rect.top = cpt.y;
2312 rect.right = rect.left + pt.x;
2313 rect.bottom = rect.top + pt.y;
2314 monitor = MonitorFromPoint(cpt, MONITOR_DEFAULTTOPRIMARY);
2316 else /* CFS_DEFAULT */
2318 /* Windows places the default IME window in the bottom left */
2319 HWND target = root_context->IMC.hWnd;
2320 if (!target) target = GetFocus();
2322 GetWindowRect(target,&rect);
2323 rect.top = rect.bottom;
2324 rect.right = rect.left + pt.x + 20;
2325 rect.bottom = rect.top + pt.y + 20;
2326 offX=offY=10;
2327 monitor = MonitorFromWindow(target, MONITOR_DEFAULTTOPRIMARY);
2330 if (root_context->IMC.cfCompForm.dwStyle == CFS_RECT)
2332 RECT client;
2333 client =root_context->IMC.cfCompForm.rcArea;
2334 MapWindowPoints( root_context->IMC.hWnd, 0, (POINT *)&client, 2 );
2335 IntersectRect(&rect,&rect,&client);
2336 /* TODO: Wrap the input if needed */
2339 if (root_context->IMC.cfCompForm.dwStyle == CFS_DEFAULT)
2341 /* make sure we are on the desktop */
2342 mon_info.cbSize = sizeof(mon_info);
2343 GetMonitorInfoW(monitor, &mon_info);
2345 if (rect.bottom > mon_info.rcWork.bottom)
2347 int shift = rect.bottom - mon_info.rcWork.bottom;
2348 rect.top -= shift;
2349 rect.bottom -= shift;
2351 if (rect.left < 0)
2353 rect.right -= rect.left;
2354 rect.left = 0;
2356 if (rect.right > mon_info.rcWork.right)
2358 int shift = rect.right - mon_info.rcWork.right;
2359 rect.left -= shift;
2360 rect.right -= shift;
2364 SetWindowPos(hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE);
2366 TextOutW(hdc, offX,offY, CompString, compstr->dwCompStrLen);
2368 if (oldfont)
2369 SelectObject(hdc,oldfont);
2372 ImmUnlockIMCC(root_context->IMC.hCompStr);
2374 EndPaint(hwnd,&ps);
2377 static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable)
2379 LPCOMPOSITIONSTRING compstr;
2381 if (root_context->IMC.hCompStr)
2382 compstr = ImmLockIMCC(root_context->IMC.hCompStr);
2383 else
2384 compstr = NULL;
2386 if (compstr == NULL || compstr->dwCompStrLen == 0)
2387 ShowWindow(hwndDefault,SW_HIDE);
2388 else if (showable)
2389 ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
2391 RedrawWindow(hwnd,NULL,NULL,RDW_ERASENOW|RDW_INVALIDATE);
2393 if (compstr != NULL)
2394 ImmUnlockIMCC(root_context->IMC.hCompStr);
2398 * The window proc for the default IME window
2400 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam,
2401 LPARAM lParam)
2403 LRESULT rc = 0;
2405 TRACE("Incoming Message 0x%x (0x%08x, 0x%08x)\n", msg, (UINT)wParam,
2406 (UINT)lParam);
2408 switch(msg)
2410 case WM_PAINT:
2411 PaintDefaultIMEWnd(hwnd);
2412 return FALSE;
2414 case WM_NCCREATE:
2415 return TRUE;
2417 case WM_CREATE:
2418 SetWindowTextA(hwnd,"Wine Ime Active");
2419 return TRUE;
2421 case WM_SETFOCUS:
2422 if (wParam)
2423 SetFocus((HWND)wParam);
2424 else
2425 FIXME("Received focus, should never have focus\n");
2426 break;
2427 case WM_IME_COMPOSITION:
2428 TRACE("IME message %s, 0x%x, 0x%x (%i)\n",
2429 "WM_IME_COMPOSITION", (UINT)wParam, (UINT)lParam,
2430 root_context->bRead);
2431 if (lParam & GCS_RESULTSTR)
2432 IMM_PostResult(root_context);
2433 else
2434 UpdateDataInDefaultIMEWindow(hwnd,TRUE);
2435 break;
2436 case WM_IME_STARTCOMPOSITION:
2437 TRACE("IME message %s, 0x%x, 0x%x\n",
2438 "WM_IME_STARTCOMPOSITION", (UINT)wParam, (UINT)lParam);
2439 root_context->IMC.hWnd = GetFocus();
2440 ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
2441 break;
2442 case WM_IME_ENDCOMPOSITION:
2443 TRACE("IME message %s, 0x%x, 0x%x\n",
2444 "WM_IME_ENDCOMPOSITION", (UINT)wParam, (UINT)lParam);
2445 ShowWindow(hwndDefault,SW_HIDE);
2446 break;
2447 case WM_IME_SELECT:
2448 TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_SELECT",
2449 (UINT)wParam, (UINT)lParam);
2450 break;
2451 case WM_IME_CONTROL:
2452 TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_CONTROL",
2453 (UINT)wParam, (UINT)lParam);
2454 rc = 1;
2455 break;
2456 case WM_IME_NOTIFY:
2457 TRACE("!! IME NOTIFY\n");
2458 break;
2459 default:
2460 TRACE("Non-standard message 0x%x\n",msg);
2462 /* check the MSIME messages */
2463 if (msg == WM_MSIME_SERVICE)
2465 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_SERVICE",
2466 (UINT)wParam, (UINT)lParam);
2467 rc = FALSE;
2469 else if (msg == WM_MSIME_RECONVERTOPTIONS)
2471 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTOPTIONS",
2472 (UINT)wParam, (UINT)lParam);
2474 else if (msg == WM_MSIME_MOUSE)
2476 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_MOUSE",
2477 (UINT)wParam, (UINT)lParam);
2479 else if (msg == WM_MSIME_RECONVERTREQUEST)
2481 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTREQUEST",
2482 (UINT)wParam, (UINT)lParam);
2484 else if (msg == WM_MSIME_RECONVERT)
2486 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERT",
2487 (UINT)wParam, (UINT)lParam);
2489 else if (msg == WM_MSIME_QUERYPOSITION)
2491 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_QUERYPOSITION",
2492 (UINT)wParam, (UINT)lParam);
2494 else if (msg == WM_MSIME_DOCUMENTFEED)
2496 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_DOCUMENTFEED",
2497 (UINT)wParam, (UINT)lParam);
2499 /* DefWndProc if not an IME message */
2500 else if (!rc && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2501 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP)))
2502 rc = DefWindowProcW(hwnd,msg,wParam,lParam);
2504 return rc;