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
30 #include "wine/debug.h"
35 #include "wine/list.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(imm);
39 #define FROM_IME 0xcafe1337
41 static void (*pX11DRV_ForceXIMReset)(HWND);
43 typedef struct tagIMCCInternal
49 #define MAKE_FUNCPTR(f) typeof(f) * p##f
50 typedef struct _tagImmHkl{
55 WCHAR imeClassName[17]; /* 16 character max */
58 /* Function Pointers */
59 MAKE_FUNCPTR(ImeInquire);
60 MAKE_FUNCPTR(ImeConfigure);
61 MAKE_FUNCPTR(ImeDestroy);
62 MAKE_FUNCPTR(ImeEscape);
63 MAKE_FUNCPTR(ImeSelect);
64 MAKE_FUNCPTR(ImeSetActiveContext);
65 MAKE_FUNCPTR(ImeToAsciiEx);
66 MAKE_FUNCPTR(NotifyIME);
67 MAKE_FUNCPTR(ImeRegisterWord);
68 MAKE_FUNCPTR(ImeUnregisterWord);
69 MAKE_FUNCPTR(ImeEnumRegisterWord);
70 MAKE_FUNCPTR(ImeSetCompositionString);
71 MAKE_FUNCPTR(ImeConversionList);
72 MAKE_FUNCPTR(ImeProcessKey);
73 MAKE_FUNCPTR(ImeGetRegisterWordStyle);
74 MAKE_FUNCPTR(ImeGetImeMenuItems);
78 typedef struct tagInputContextData
91 typedef struct _tagTRANSMSG {
95 } TRANSMSG, *LPTRANSMSG;
97 static InputContextData *root_context = NULL;
98 static HWND hwndDefault = NULL;
99 static HANDLE hImeInst;
100 static const WCHAR WC_IMECLASSNAME[] = {'I','M','E',0};
101 static ATOM atIMEClass = 0;
103 static struct list ImmHklList = LIST_INIT(ImmHklList);
106 static UINT WM_MSIME_SERVICE;
107 static UINT WM_MSIME_RECONVERTOPTIONS;
108 static UINT WM_MSIME_MOUSE;
109 static UINT WM_MSIME_RECONVERTREQUEST;
110 static UINT WM_MSIME_RECONVERT;
111 static UINT WM_MSIME_QUERYPOSITION;
112 static UINT WM_MSIME_DOCUMENTFEED;
114 static const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
118 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
120 static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable);
121 static void ImmInternalPostIMEMessage(InputContextData*, UINT, WPARAM, LPARAM);
122 static void ImmInternalSetOpenStatus(BOOL fOpen);
123 static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len);
125 #define is_himc_ime_unicode(p) (p->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE)
126 #define is_kbd_ime_unicode(p) (p->imeInfo.fdwProperty & IME_PROP_UNICODE)
128 static inline WCHAR *strdupAtoW( const char *str )
133 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
134 if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
135 MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
140 static inline CHAR *strdupWtoA( const WCHAR *str )
145 DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
146 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
147 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
152 static HMODULE LoadDefaultWineIME(void)
154 char buffer[MAX_PATH], libname[32], *name, *next;
158 TRACE("Attempting to fall back to wine default IME\n");
160 strcpy( buffer, "x11" ); /* default value */
161 /* @@ Wine registry key: HKCU\Software\Wine\Drivers */
162 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hkey ))
164 DWORD type, count = sizeof(buffer);
165 RegQueryValueExA( hkey, "Ime", 0, &type, (LPBYTE) buffer, &count );
172 next = strchr( name, ',' );
173 if (next) *next++ = 0;
175 snprintf( libname, sizeof(libname), "wine%s.drv", name );
176 if ((module = LoadLibraryA( libname )) != 0) break;
183 /* ImmHkl loading and freeing */
184 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
185 static ImmHkl *IMM_GetImmHkl(HKL hkl)
188 WCHAR filename[MAX_PATH];
190 TRACE("Seeking ime for keyboard 0x%x\n",(unsigned)hkl);
192 LIST_FOR_EACH_ENTRY(ptr, &ImmHklList, ImmHkl, entry)
197 /* not found... create it */
199 ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ImmHkl));
202 if (ImmGetIMEFileNameW(hkl, filename, MAX_PATH)) ptr->hIME = LoadLibraryW(filename);
204 ptr->hIME = LoadDefaultWineIME();
207 LOAD_FUNCPTR(ImeInquire);
208 if (!ptr->pImeInquire || !ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL))
210 FreeLibrary(ptr->hIME);
215 LOAD_FUNCPTR(ImeDestroy);
216 LOAD_FUNCPTR(ImeSelect);
217 if (!ptr->pImeSelect || !ptr->pImeDestroy)
219 FreeLibrary(ptr->hIME);
224 LOAD_FUNCPTR(ImeConfigure);
225 LOAD_FUNCPTR(ImeEscape);
226 LOAD_FUNCPTR(ImeSetActiveContext);
227 LOAD_FUNCPTR(ImeToAsciiEx);
228 LOAD_FUNCPTR(NotifyIME);
229 LOAD_FUNCPTR(ImeRegisterWord);
230 LOAD_FUNCPTR(ImeUnregisterWord);
231 LOAD_FUNCPTR(ImeEnumRegisterWord);
232 LOAD_FUNCPTR(ImeSetCompositionString);
233 LOAD_FUNCPTR(ImeConversionList);
234 LOAD_FUNCPTR(ImeProcessKey);
235 LOAD_FUNCPTR(ImeGetRegisterWordStyle);
236 LOAD_FUNCPTR(ImeGetImeMenuItems);
237 /* make sure our classname is WCHAR */
238 if (!is_kbd_ime_unicode(ptr))
241 MultiByteToWideChar(CP_ACP, 0, (LPSTR)ptr->imeClassName,
243 lstrcpyW(ptr->imeClassName, bufW);
248 list_add_head(&ImmHklList,&ptr->entry);
254 static void IMM_FreeAllImmHkl(void)
256 ImmHkl *ptr,*cursor2;
258 LIST_FOR_EACH_ENTRY_SAFE(ptr, cursor2, &ImmHklList, ImmHkl, entry)
260 list_remove(&ptr->entry);
264 FreeLibrary(ptr->hIME);
266 HeapFree(GetProcessHeap(),0,ptr);
270 static VOID IMM_PostResult(InputContextData *data)
273 LPCOMPOSITIONSTRING compstr;
278 TRACE("Posting result as IME_CHAR\n");
279 compdata = ImmLockIMCC(root_context->IMC.hCompStr);
280 compstr = (LPCOMPOSITIONSTRING)compdata;
281 ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
283 for (i = 0; i < compstr->dwResultStrLen; i++)
284 ImmInternalPostIMEMessage (root_context, WM_IME_CHAR, ResultStr[i], 1);
286 ImmUnlockIMCC(root_context->IMC.hCompStr);
288 /* clear the buffer */
289 newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0);
290 ImmDestroyIMCC(root_context->IMC.hCompStr);
291 root_context->IMC.hCompStr = newCompStr;
294 static void IMM_Register(void)
297 ZeroMemory(&wndClass, sizeof(WNDCLASSW));
298 wndClass.style = CS_GLOBALCLASS | CS_IME | CS_HREDRAW | CS_VREDRAW;
299 wndClass.lpfnWndProc = (WNDPROC) IME_WindowProc;
300 wndClass.cbClsExtra = 0;
301 wndClass.cbWndExtra = 0;
302 wndClass.hInstance = hImeInst;
303 wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
304 wndClass.hIcon = NULL;
305 wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW +1);
306 wndClass.lpszMenuName = 0;
307 wndClass.lpszClassName = WC_IMECLASSNAME;
308 atIMEClass = RegisterClassW(&wndClass);
311 static void IMM_Unregister(void)
314 UnregisterClassW(WC_IMECLASSNAME, NULL);
318 static void IMM_RegisterMessages(void)
320 WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");
321 WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions");
322 WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
323 WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
324 WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
325 WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
326 WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
330 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
334 TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
337 case DLL_PROCESS_ATTACH:
338 DisableThreadLibraryCalls(hInstDLL);
340 IMM_RegisterMessages();
341 x11drv = GetModuleHandleA("winex11.drv");
342 if (x11drv) pX11DRV_ForceXIMReset = (void *)GetProcAddress( x11drv, "ForceXIMReset");
344 case DLL_PROCESS_DETACH:
347 DestroyWindow(hwndDefault);
357 /* for posting messages as the IME */
358 static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
360 HWND target = GetFocus();
362 PostMessageW(data->IMC.hWnd,msg,wParam,lParam);
364 PostMessageW(target, msg, wParam, lParam);
367 static LRESULT ImmInternalSendIMENotify(InputContextData *data, WPARAM notify, LPARAM lParam)
371 target = data->IMC.hWnd;
372 if (!target) target = GetFocus();
375 return SendMessageW(target, WM_IME_NOTIFY, notify, lParam);
380 static HIMCC ImmCreateBlankCompStr(void)
383 LPCOMPOSITIONSTRING ptr;
384 rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
385 ptr = (LPCOMPOSITIONSTRING)ImmLockIMCC(rc);
386 memset(ptr,0,sizeof(COMPOSITIONSTRING));
387 ptr->dwSize = sizeof(COMPOSITIONSTRING);
392 static void ImmInternalSetOpenStatus(BOOL fOpen)
394 TRACE("Setting internal state to %s\n",(fOpen)?"OPEN":"CLOSED");
396 if (root_context->IMC.fOpen && fOpen == FALSE)
398 ShowWindow(hwndDefault,SW_HIDE);
399 ImmDestroyIMCC(root_context->IMC.hCompStr);
400 root_context->IMC.hCompStr = ImmCreateBlankCompStr();
403 root_context->IMC.fOpen = fOpen;
404 root_context->bInternalState = fOpen;
406 ImmInternalSendIMENotify(root_context, IMN_SETOPENSTATUS, 0);
409 static int updateField(DWORD origLen, DWORD origOffset, DWORD currentOffset,
410 LPBYTE target, LPBYTE source, DWORD* lenParam,
411 DWORD* offsetParam, BOOL wchars )
413 if (origLen > 0 && origOffset > 0)
415 int truelen = origLen;
417 truelen *= sizeof(WCHAR);
419 memcpy(&target[currentOffset], &source[origOffset], truelen);
422 *offsetParam = currentOffset;
423 currentOffset += truelen;
425 return currentOffset;
428 static HIMCC updateCompStr(HIMCC old, LPWSTR compstr, DWORD len)
430 /* we need to make sure the CompStr, CompClaus and CompAttr fields are all
434 LPBYTE newdata = NULL;
435 LPBYTE olddata = NULL;
436 LPCOMPOSITIONSTRING new_one;
437 LPCOMPOSITIONSTRING lpcs = NULL;
438 INT current_offset = 0;
440 TRACE("%s, %i\n",debugstr_wn(compstr,len),len);
442 if (old == NULL && compstr == NULL && len == 0)
447 olddata = ImmLockIMCC(old);
448 lpcs = (LPCOMPOSITIONSTRING)olddata;
451 needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
452 len + sizeof(DWORD) * 2;
456 needed_size += lpcs->dwCompReadAttrLen;
457 needed_size += lpcs->dwCompReadClauseLen;
458 needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
459 needed_size += lpcs->dwResultReadClauseLen;
460 needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
461 needed_size += lpcs->dwResultClauseLen;
462 needed_size += lpcs->dwResultStrLen * sizeof(DWORD);
463 needed_size += lpcs->dwPrivateSize;
465 rc = ImmCreateIMCC(needed_size);
466 newdata = ImmLockIMCC(rc);
467 new_one = (LPCOMPOSITIONSTRING)newdata;
469 new_one->dwSize = needed_size;
470 current_offset = sizeof(COMPOSITIONSTRING);
473 current_offset = updateField(lpcs->dwCompReadAttrLen,
474 lpcs->dwCompReadAttrOffset,
475 current_offset, newdata, olddata,
476 &new_one->dwCompReadAttrLen,
477 &new_one->dwCompReadAttrOffset, FALSE);
479 current_offset = updateField(lpcs->dwCompReadClauseLen,
480 lpcs->dwCompReadClauseOffset,
481 current_offset, newdata, olddata,
482 &new_one->dwCompReadClauseLen,
483 &new_one->dwCompReadClauseOffset, FALSE);
485 current_offset = updateField(lpcs->dwCompReadStrLen,
486 lpcs->dwCompReadStrOffset,
487 current_offset, newdata, olddata,
488 &new_one->dwCompReadStrLen,
489 &new_one->dwCompReadStrOffset, TRUE);
491 /* new CompAttr, CompClause, CompStr, dwCursorPos */
492 new_one->dwDeltaStart = 0;
494 current_offset = updateField(lpcs->dwResultReadClauseLen,
495 lpcs->dwResultReadClauseOffset,
496 current_offset, newdata, olddata,
497 &new_one->dwResultReadClauseLen,
498 &new_one->dwResultReadClauseOffset, FALSE);
500 current_offset = updateField(lpcs->dwResultReadStrLen,
501 lpcs->dwResultReadStrOffset,
502 current_offset, newdata, olddata,
503 &new_one->dwResultReadStrLen,
504 &new_one->dwResultReadStrOffset, TRUE);
506 current_offset = updateField(lpcs->dwResultClauseLen,
507 lpcs->dwResultClauseOffset,
508 current_offset, newdata, olddata,
509 &new_one->dwResultClauseLen,
510 &new_one->dwResultClauseOffset, FALSE);
512 current_offset = updateField(lpcs->dwResultStrLen,
513 lpcs->dwResultStrOffset,
514 current_offset, newdata, olddata,
515 &new_one->dwResultStrLen,
516 &new_one->dwResultStrOffset, TRUE);
518 current_offset = updateField(lpcs->dwPrivateSize,
519 lpcs->dwPrivateOffset,
520 current_offset, newdata, olddata,
521 &new_one->dwPrivateSize,
522 &new_one->dwPrivateOffset, FALSE);
527 new_one->dwCompAttrLen = len;
530 new_one->dwCompAttrOffset = current_offset;
531 memset(&newdata[current_offset],ATTR_INPUT,len);
532 current_offset += len;
538 new_one->dwCompClauseLen = sizeof(DWORD) * 2;
539 new_one->dwCompClauseOffset = current_offset;
540 *(DWORD*)(&newdata[current_offset]) = 0;
541 current_offset += sizeof(DWORD);
542 *(DWORD*)(&newdata[current_offset]) = len;
543 current_offset += sizeof(DWORD);
547 new_one->dwCompStrLen = len;
550 new_one->dwCompStrOffset = current_offset;
551 memcpy(&newdata[current_offset],compstr,len*sizeof(WCHAR));
555 new_one->dwCursorPos = len;
564 static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len)
566 /* we need to make sure the ResultStr and ResultClause fields are all
570 LPBYTE newdata = NULL;
571 LPBYTE olddata = NULL;
572 LPCOMPOSITIONSTRING new_one;
573 LPCOMPOSITIONSTRING lpcs = NULL;
574 INT current_offset = 0;
576 TRACE("%s, %i\n",debugstr_wn(resultstr,len),len);
578 if (old == NULL && resultstr == NULL && len == 0)
583 olddata = ImmLockIMCC(old);
584 lpcs = (LPCOMPOSITIONSTRING)olddata;
587 needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
592 needed_size += lpcs->dwCompReadAttrLen;
593 needed_size += lpcs->dwCompReadClauseLen;
594 needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
595 needed_size += lpcs->dwCompAttrLen;
596 needed_size += lpcs->dwCompClauseLen;
597 needed_size += lpcs->dwCompStrLen * sizeof(DWORD);
598 needed_size += lpcs->dwResultReadClauseLen;
599 needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
600 needed_size += lpcs->dwPrivateSize;
602 rc = ImmCreateIMCC(needed_size);
603 newdata = ImmLockIMCC(rc);
604 new_one = (LPCOMPOSITIONSTRING)newdata;
606 new_one->dwSize = needed_size;
607 current_offset = sizeof(COMPOSITIONSTRING);
610 current_offset = updateField(lpcs->dwCompReadAttrLen,
611 lpcs->dwCompReadAttrOffset,
612 current_offset, newdata, olddata,
613 &new_one->dwCompReadAttrLen,
614 &new_one->dwCompReadAttrOffset, FALSE);
616 current_offset = updateField(lpcs->dwCompReadClauseLen,
617 lpcs->dwCompReadClauseOffset,
618 current_offset, newdata, olddata,
619 &new_one->dwCompReadClauseLen,
620 &new_one->dwCompReadClauseOffset, FALSE);
622 current_offset = updateField(lpcs->dwCompReadStrLen,
623 lpcs->dwCompReadStrOffset,
624 current_offset, newdata, olddata,
625 &new_one->dwCompReadStrLen,
626 &new_one->dwCompReadStrOffset, TRUE);
628 current_offset = updateField(lpcs->dwCompAttrLen,
629 lpcs->dwCompAttrOffset,
630 current_offset, newdata, olddata,
631 &new_one->dwCompAttrLen,
632 &new_one->dwCompAttrOffset, FALSE);
634 current_offset = updateField(lpcs->dwCompClauseLen,
635 lpcs->dwCompClauseOffset,
636 current_offset, newdata, olddata,
637 &new_one->dwCompClauseLen,
638 &new_one->dwCompClauseOffset, FALSE);
640 current_offset = updateField(lpcs->dwCompStrLen,
641 lpcs->dwCompStrOffset,
642 current_offset, newdata, olddata,
643 &new_one->dwCompStrLen,
644 &new_one->dwCompStrOffset, TRUE);
646 new_one->dwCursorPos = lpcs->dwCursorPos;
647 new_one->dwDeltaStart = 0;
649 current_offset = updateField(lpcs->dwResultReadClauseLen,
650 lpcs->dwResultReadClauseOffset,
651 current_offset, newdata, olddata,
652 &new_one->dwResultReadClauseLen,
653 &new_one->dwResultReadClauseOffset, FALSE);
655 current_offset = updateField(lpcs->dwResultReadStrLen,
656 lpcs->dwResultReadStrOffset,
657 current_offset, newdata, olddata,
658 &new_one->dwResultReadStrLen,
659 &new_one->dwResultReadStrOffset, TRUE);
661 /* new ResultClause , ResultStr */
663 current_offset = updateField(lpcs->dwPrivateSize,
664 lpcs->dwPrivateOffset,
665 current_offset, newdata, olddata,
666 &new_one->dwPrivateSize,
667 &new_one->dwPrivateOffset, FALSE);
674 new_one->dwResultClauseLen = sizeof(DWORD) * 2;
675 new_one->dwResultClauseOffset = current_offset;
676 *(DWORD*)(&newdata[current_offset]) = 0;
677 current_offset += sizeof(DWORD);
678 *(DWORD*)(&newdata[current_offset]) = len;
679 current_offset += sizeof(DWORD);
683 new_one->dwResultStrLen = len;
686 new_one->dwResultStrOffset = current_offset;
687 memcpy(&newdata[current_offset],resultstr,len*sizeof(WCHAR));
698 /***********************************************************************
699 * ImmAssociateContext (IMM32.@)
701 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
704 InputContextData *data = (InputContextData*)hIMC;
706 TRACE("(%p, %p):\n", hWnd, hIMC);
709 * WINE SPECIFIC! MAY CONFLICT
710 * associate the root context we have an XIM created
714 root_context = (InputContextData*)hIMC;
718 * If already associated just return
720 if (hIMC && data->IMC.hWnd == hWnd)
725 old = (HIMC)RemovePropW(hWnd,szwWineIMCProperty);
728 old = (HIMC)root_context;
729 else if (old == (HIMC)-1)
732 if (hIMC != (HIMC)root_context)
734 if (hIMC == NULL) /* Meaning disable imm for that window*/
735 SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1);
737 SetPropW(hWnd,szwWineIMCProperty,(HANDLE)hIMC);
744 if (IsWindow(data->IMC.hWnd))
747 * Post a message that your context is switching
749 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
752 data->IMC.hWnd = hWnd;
754 if (IsWindow(data->IMC.hWnd))
757 * Post a message that your context is switching
759 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
765 /***********************************************************************
766 * ImmAssociateContextEx (IMM32.@)
768 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
770 FIXME("(%p, %p, %d): stub\n", hWnd, hIMC, dwFlags);
771 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
775 /***********************************************************************
776 * ImmConfigureIMEA (IMM32.@)
778 BOOL WINAPI ImmConfigureIMEA(
779 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
781 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
783 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
785 if (immHkl->hIME && immHkl->pImeConfigure)
787 if (dwMode != IME_CONFIG_REGISTERWORD || !is_kbd_ime_unicode(immHkl))
788 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
792 REGISTERWORDA *rwa = (REGISTERWORDA*)lpData;
795 rww.lpReading = strdupAtoW(rwa->lpReading);
796 rww.lpWord = strdupAtoW(rwa->lpWord);
797 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rww);
798 HeapFree(GetProcessHeap(),0,rww.lpReading);
799 HeapFree(GetProcessHeap(),0,rww.lpWord);
807 /***********************************************************************
808 * ImmConfigureIMEW (IMM32.@)
810 BOOL WINAPI ImmConfigureIMEW(
811 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
813 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
815 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
817 if (immHkl->hIME && immHkl->pImeConfigure)
819 if (dwMode != IME_CONFIG_REGISTERWORD || is_kbd_ime_unicode(immHkl))
820 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
823 REGISTERWORDW *rww = (REGISTERWORDW*)lpData;
827 rwa.lpReading = strdupWtoA(rww->lpReading);
828 rwa.lpWord = strdupWtoA(rww->lpWord);
829 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rwa);
830 HeapFree(GetProcessHeap(),0,rwa.lpReading);
831 HeapFree(GetProcessHeap(),0,rwa.lpWord);
839 /***********************************************************************
840 * ImmCreateContext (IMM32.@)
842 HIMC WINAPI ImmCreateContext(void)
844 InputContextData *new_context;
846 new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
849 new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0));
852 * Once we depend on the IME for all the processing like we should
853 * these will become hard errors and result in creation failures
855 if (!new_context->immKbd->hIME)
856 TRACE("IME dll could not be loaded\n");
858 /* hCompStr is never NULL */
859 new_context->IMC.hCompStr = ImmCreateBlankCompStr();
860 new_context->IMC.hMsgBuf = ImmCreateIMCC(1);
862 /* Initialize the IME Private */
863 new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
865 if (new_context->immKbd->hIME &&
866 !new_context->immKbd->pImeSelect(new_context, TRUE))
868 TRACE("Selection of IME failed\n");
869 ImmDestroyContext(new_context);
873 new_context->immKbd->uSelected++;
874 TRACE("Created context 0x%x\n",(UINT)new_context);
876 return (HIMC)new_context;
879 /***********************************************************************
880 * ImmDestroyContext (IMM32.@)
882 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
884 InputContextData *data = (InputContextData*)hIMC;
886 TRACE("Destroying %p\n",hIMC);
890 data->immKbd->uSelected --;
891 if (data->immKbd->hIME)
892 data->immKbd->pImeSelect(hIMC, FALSE);
894 ImmDestroyIMCC(data->IMC.hCompStr);
895 ImmDestroyIMCC(data->IMC.hCandInfo);
896 ImmDestroyIMCC(data->IMC.hGuideLine);
897 ImmDestroyIMCC(data->IMC.hPrivate);
898 ImmDestroyIMCC(data->IMC.hMsgBuf);
902 DeleteObject(data->textfont);
903 data->textfont = NULL;
906 HeapFree(GetProcessHeap(),0,data);
911 /***********************************************************************
912 * ImmDisableIME (IMM32.@)
914 BOOL WINAPI ImmDisableIME(DWORD idThread)
916 FIXME("(%d): stub\n", idThread);
920 /***********************************************************************
921 * ImmEnumRegisterWordA (IMM32.@)
923 UINT WINAPI ImmEnumRegisterWordA(
924 HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
925 LPCSTR lpszReading, DWORD dwStyle,
926 LPCSTR lpszRegister, LPVOID lpData)
928 FIXME("(%p, %p, %s, %d, %s, %p): stub\n",
930 debugstr_a(lpszReading), dwStyle,
931 debugstr_a(lpszRegister), lpData
933 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
937 /***********************************************************************
938 * ImmEnumRegisterWordW (IMM32.@)
940 UINT WINAPI ImmEnumRegisterWordW(
941 HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
942 LPCWSTR lpszReading, DWORD dwStyle,
943 LPCWSTR lpszRegister, LPVOID lpData)
945 FIXME("(%p, %p, %s, %d, %s, %p): stub\n",
947 debugstr_w(lpszReading), dwStyle,
948 debugstr_w(lpszRegister), lpData
950 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
954 /***********************************************************************
955 * ImmEscapeA (IMM32.@)
957 LRESULT WINAPI ImmEscapeA(
959 UINT uEscape, LPVOID lpData)
961 FIXME("(%p, %p, %d, %p): stub\n",
962 hKL, hIMC, uEscape, lpData
964 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
968 /***********************************************************************
969 * ImmEscapeW (IMM32.@)
971 LRESULT WINAPI ImmEscapeW(
973 UINT uEscape, LPVOID lpData)
975 FIXME("(%p, %p, %d, %p): stub\n",
976 hKL, hIMC, uEscape, lpData
978 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
982 /***********************************************************************
983 * ImmGetCandidateListA (IMM32.@)
985 DWORD WINAPI ImmGetCandidateListA(
986 HIMC hIMC, DWORD deIndex,
987 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
989 FIXME("(%p, %d, %p, %d): stub\n",
993 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
997 /***********************************************************************
998 * ImmGetCandidateListCountA (IMM32.@)
1000 DWORD WINAPI ImmGetCandidateListCountA(
1001 HIMC hIMC, LPDWORD lpdwListCount)
1003 FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
1004 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1008 /***********************************************************************
1009 * ImmGetCandidateListCountW (IMM32.@)
1011 DWORD WINAPI ImmGetCandidateListCountW(
1012 HIMC hIMC, LPDWORD lpdwListCount)
1014 FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
1015 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1019 /***********************************************************************
1020 * ImmGetCandidateListW (IMM32.@)
1022 DWORD WINAPI ImmGetCandidateListW(
1023 HIMC hIMC, DWORD deIndex,
1024 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
1026 FIXME("(%p, %d, %p, %d): stub\n",
1028 lpCandList, dwBufLen
1030 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1034 /***********************************************************************
1035 * ImmGetCandidateWindow (IMM32.@)
1037 BOOL WINAPI ImmGetCandidateWindow(
1038 HIMC hIMC, DWORD dwBufLen, LPCANDIDATEFORM lpCandidate)
1040 FIXME("(%p, %d, %p): stub\n", hIMC, dwBufLen, lpCandidate);
1041 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1045 /***********************************************************************
1046 * ImmGetCompositionFontA (IMM32.@)
1048 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1053 TRACE("(%p, %p):\n", hIMC, lplf);
1055 rc = ImmGetCompositionFontW(hIMC,&lfW);
1058 memcpy(lplf,&lfW,sizeof(LOGFONTA));
1059 WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName,
1060 LF_FACESIZE, NULL, NULL);
1065 /***********************************************************************
1066 * ImmGetCompositionFontW (IMM32.@)
1068 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1070 InputContextData *data = (InputContextData*)hIMC;
1072 TRACE("(%p, %p):\n", hIMC, lplf);
1077 *lplf = data->IMC.lfFont.W;
1082 /***********************************************************************
1083 * ImmGetCompositionStringA (IMM32.@)
1085 LONG WINAPI ImmGetCompositionStringA(
1086 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
1090 InputContextData *data = (InputContextData*)hIMC;
1091 LPCOMPOSITIONSTRING compstr;
1094 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
1099 if (!data->IMC.hCompStr)
1102 compdata = ImmLockIMCC(data->IMC.hCompStr);
1103 compstr = (LPCOMPOSITIONSTRING)compdata;
1105 if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 &&
1106 compstr->dwResultStrOffset > 0)
1108 LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
1110 TRACE("GSC_RESULTSTR %p %i\n",ResultStr,
1111 compstr->dwResultStrLen);
1113 buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwResultStrLen * 3 );
1114 rc = WideCharToMultiByte(CP_ACP, 0, ResultStr,
1115 compstr->dwResultStrLen , buf,
1116 compstr->dwResultStrLen * 3, NULL, NULL);
1118 memcpy(lpBuf,buf,rc);
1121 HeapFree( GetProcessHeap(), 0, buf );
1123 else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 &&
1124 compstr->dwCompStrOffset > 0)
1126 LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
1128 TRACE("GSC_COMPSTR %p %i\n", CompString, compstr->dwCompStrLen);
1130 buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwCompStrLen * 3 );
1131 rc = WideCharToMultiByte(CP_ACP, 0, CompString,
1132 compstr->dwCompStrLen, buf,
1133 compstr->dwCompStrLen * 3, NULL, NULL);
1135 memcpy(lpBuf,buf,rc);
1136 HeapFree( GetProcessHeap(), 0, buf );
1138 else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 &&
1139 compstr->dwCompAttrOffset > 0)
1141 LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset);
1142 TRACE("GSC_COMPATTR %p %i\n", Compattr , compstr->dwCompAttrLen);
1144 rc = compstr->dwCompAttrLen;
1146 memcpy(lpBuf,Compattr,rc);
1148 else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 &&
1149 compstr->dwCompClauseOffset > 0)
1151 LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset);
1152 TRACE("GSC_COMPCLAUSE %p %i\n", Compclause, compstr->dwCompClauseLen);
1154 rc = compstr->dwCompClauseLen;
1155 if (dwBufLen >= compstr->dwCompClauseLen)
1156 memcpy(lpBuf,Compclause,rc);
1158 else if (dwIndex == GCS_RESULTCLAUSE && compstr->dwResultClauseLen > 0 &&
1159 compstr->dwResultClauseOffset > 0)
1161 LPWSTR Resultclause = (LPWSTR)(compdata + compstr->dwResultClauseOffset);
1162 TRACE("GSC_RESULTCLAUSE %p %i\n", Resultclause, compstr->dwResultClauseLen);
1164 rc = compstr->dwResultClauseLen;
1165 if (dwBufLen >= compstr->dwResultClauseLen)
1166 memcpy(lpBuf,Resultclause,rc);
1168 else if (dwIndex == GCS_CURSORPOS)
1170 TRACE("GSC_CURSORPOS\n");
1171 rc = compstr->dwCursorPos;
1173 else if (dwIndex == GCS_DELTASTART)
1175 TRACE("GCS_DELTASTART\n");
1176 rc = compstr->dwDeltaStart;
1180 FIXME("Unhandled index 0x%x\n",dwIndex);
1183 ImmUnlockIMCC(data->IMC.hCompStr);
1188 /***********************************************************************
1189 * ImmGetCompositionStringW (IMM32.@)
1191 LONG WINAPI ImmGetCompositionStringW(
1192 HIMC hIMC, DWORD dwIndex,
1193 LPVOID lpBuf, DWORD dwBufLen)
1196 InputContextData *data = (InputContextData*)hIMC;
1197 LPCOMPOSITIONSTRING compstr;
1200 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
1205 if (!data->IMC.hCompStr)
1208 compdata = ImmLockIMCC(data->IMC.hCompStr);
1209 compstr = (LPCOMPOSITIONSTRING)compdata;
1211 if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 &&
1212 compstr->dwResultStrOffset > 0)
1214 LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
1216 rc = compstr->dwResultStrLen * sizeof(WCHAR);
1219 memcpy(lpBuf,ResultStr,rc);
1221 else if (dwIndex == GCS_RESULTREADSTR && compstr->dwResultReadStrLen > 0 &&
1222 compstr->dwResultReadStrOffset > 0)
1224 LPWSTR ResultReadString = (LPWSTR)(compdata + compstr->dwResultReadStrOffset);
1226 rc = compstr->dwResultReadStrLen * sizeof(WCHAR);
1228 memcpy(lpBuf,ResultReadString,rc);
1230 else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 &&
1231 compstr->dwCompStrOffset > 0)
1233 LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
1234 rc = compstr->dwCompStrLen * sizeof(WCHAR);
1236 memcpy(lpBuf,CompString,rc);
1238 else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 &&
1239 compstr->dwCompAttrOffset > 0)
1242 LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset);
1244 rc = compstr->dwCompAttrLen;
1246 memcpy(lpBuf,Compattr,rc);
1248 else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 &&
1249 compstr->dwCompClauseOffset > 0)
1251 LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset);
1253 rc = compstr->dwCompClauseLen;
1254 if (dwBufLen >= compstr->dwCompClauseLen)
1255 memcpy(lpBuf,Compclause,rc);
1257 else if (dwIndex == GCS_COMPREADSTR && compstr->dwCompReadStrLen > 0 &&
1258 compstr->dwCompReadStrOffset > 0)
1260 LPWSTR CompReadString = (LPWSTR)(compdata + compstr->dwCompReadStrOffset);
1262 rc = compstr->dwCompReadStrLen * sizeof(WCHAR);
1265 memcpy(lpBuf,CompReadString,rc);
1267 else if (dwIndex == GCS_CURSORPOS)
1269 TRACE("GSC_CURSORPOS\n");
1270 rc = compstr->dwCursorPos;
1272 else if (dwIndex == GCS_DELTASTART)
1274 TRACE("GCS_DELTASTART\n");
1275 rc = compstr->dwDeltaStart;
1279 FIXME("Unhandled index 0x%x\n",dwIndex);
1282 ImmUnlockIMCC(data->IMC.hCompStr);
1287 /***********************************************************************
1288 * ImmGetCompositionWindow (IMM32.@)
1290 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1292 InputContextData *data = (InputContextData*)hIMC;
1294 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1299 *lpCompForm = data->IMC.cfCompForm;
1303 /***********************************************************************
1304 * ImmGetContext (IMM32.@)
1307 HIMC WINAPI ImmGetContext(HWND hWnd)
1311 TRACE("%p\n", hWnd);
1313 rc = (HIMC)GetPropW(hWnd,szwWineIMCProperty);
1316 else if (rc == NULL)
1317 rc = (HIMC)root_context;
1321 InputContextData *data = (InputContextData*)rc;
1322 data->IMC.hWnd = hWnd;
1324 TRACE("returning %p\n", rc);
1329 /***********************************************************************
1330 * ImmGetConversionListA (IMM32.@)
1332 DWORD WINAPI ImmGetConversionListA(
1334 LPCSTR pSrc, LPCANDIDATELIST lpDst,
1335 DWORD dwBufLen, UINT uFlag)
1337 FIXME("(%p, %p, %s, %p, %d, %d): stub\n",
1338 hKL, hIMC, debugstr_a(pSrc), lpDst, dwBufLen, uFlag
1340 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1344 /***********************************************************************
1345 * ImmGetConversionListW (IMM32.@)
1347 DWORD WINAPI ImmGetConversionListW(
1349 LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1350 DWORD dwBufLen, UINT uFlag)
1352 FIXME("(%p, %p, %s, %p, %d, %d): stub\n",
1353 hKL, hIMC, debugstr_w(pSrc), lpDst, dwBufLen, uFlag
1355 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1359 /***********************************************************************
1360 * ImmGetConversionStatus (IMM32.@)
1362 BOOL WINAPI ImmGetConversionStatus(
1363 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1365 TRACE("(%p, %p, %p): best guess\n", hIMC, lpfdwConversion, lpfdwSentence);
1366 if (lpfdwConversion)
1367 *lpfdwConversion = IME_CMODE_NATIVE;
1369 *lpfdwSentence = IME_SMODE_NONE;
1373 /***********************************************************************
1374 * ImmGetDefaultIMEWnd (IMM32.@)
1376 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1378 static int shown = 0;
1381 FIXME("(%p - %p %p ): semi-stub\n", hWnd,hwndDefault, root_context);
1385 if (hwndDefault == NULL)
1387 static const WCHAR the_name[] = {'I','M','E','\0'};
1390 hwndDefault = CreateWindowExW( WS_EX_TOOLWINDOW, WC_IMECLASSNAME,
1391 the_name, WS_POPUP, 0, 0, 1, 1, 0, 0,
1394 TRACE("Default created (%p)\n",hwndDefault);
1400 /***********************************************************************
1401 * ImmGetDescriptionA (IMM32.@)
1403 UINT WINAPI ImmGetDescriptionA(
1404 HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1409 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1411 /* find out how many characters in the unicode buffer */
1412 len = ImmGetDescriptionW( hKL, NULL, 0 );
1414 /* allocate a buffer of that size */
1415 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1419 /* fetch the unicode buffer */
1420 len = ImmGetDescriptionW( hKL, buf, len + 1 );
1422 /* convert it back to ASCII */
1423 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1424 lpszDescription, uBufLen, NULL, NULL );
1426 HeapFree( GetProcessHeap(), 0, buf );
1431 /***********************************************************************
1432 * ImmGetDescriptionW (IMM32.@)
1434 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1436 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1438 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1440 if (!uBufLen) return lstrlenW( name );
1441 lstrcpynW( lpszDescription, name, uBufLen );
1442 return lstrlenW( lpszDescription );
1445 /***********************************************************************
1446 * ImmGetGuideLineA (IMM32.@)
1448 DWORD WINAPI ImmGetGuideLineA(
1449 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1451 FIXME("(%p, %d, %s, %d): stub\n",
1452 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1454 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1458 /***********************************************************************
1459 * ImmGetGuideLineW (IMM32.@)
1461 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1463 FIXME("(%p, %d, %s, %d): stub\n",
1464 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1466 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1470 /***********************************************************************
1471 * ImmGetIMEFileNameA (IMM32.@)
1473 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1476 UINT wBufLen = uBufLen;
1479 if (uBufLen && lpszFileName)
1480 bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR));
1481 else /* We need this to get the number of byte required */
1483 bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR));
1487 rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen);
1491 if (uBufLen && lpszFileName)
1492 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName,
1493 uBufLen, NULL, NULL);
1494 else /* get the length */
1495 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL,
1499 HeapFree(GetProcessHeap(),0,bufW);
1503 /***********************************************************************
1504 * ImmGetIMEFileNameW (IMM32.@)
1506 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1508 static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
1509 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};
1514 WCHAR regKey[sizeof(fmt)/sizeof(WCHAR)+8];
1516 wsprintfW( regKey, fmt, (unsigned)hKL );
1517 rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey);
1518 if (rc != ERROR_SUCCESS)
1525 rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length);
1527 if (rc != ERROR_SUCCESS)
1533 if (length > uBufLen * sizeof(WCHAR) || !lpszFileName)
1538 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1542 return length / sizeof(WCHAR);
1545 RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length);
1549 return length / sizeof(WCHAR);
1552 /***********************************************************************
1553 * ImmGetOpenStatus (IMM32.@)
1555 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1557 InputContextData *data = (InputContextData*)hIMC;
1561 FIXME("(%p): semi-stub\n", hIMC);
1563 return data->IMC.fOpen;
1566 /***********************************************************************
1567 * ImmGetProperty (IMM32.@)
1569 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1572 TRACE("(%p, %d)\n", hKL, fdwIndex);
1577 TRACE("(%s)\n", "IGP_PROPERTY");
1578 rc = IME_PROP_UNICODE | IME_PROP_AT_CARET;
1580 case IGP_CONVERSION:
1581 FIXME("(%s)\n", "IGP_CONVERSION");
1582 rc = IME_CMODE_NATIVE;
1585 FIXME("%s)\n", "IGP_SENTENCE");
1586 rc = IME_SMODE_AUTOMATIC;
1588 case IGP_SETCOMPSTR:
1589 TRACE("(%s)\n", "IGP_SETCOMPSTR");
1593 TRACE("(%s)\n", "IGP_SELECT");
1594 rc = SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE;
1596 case IGP_GETIMEVERSION:
1597 TRACE("(%s)\n", "IGP_GETIMEVERSION");
1601 TRACE("(%s)\n", "IGP_UI");
1610 /***********************************************************************
1611 * ImmGetRegisterWordStyleA (IMM32.@)
1613 UINT WINAPI ImmGetRegisterWordStyleA(
1614 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1616 FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
1617 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1621 /***********************************************************************
1622 * ImmGetRegisterWordStyleW (IMM32.@)
1624 UINT WINAPI ImmGetRegisterWordStyleW(
1625 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1627 FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
1628 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1632 /***********************************************************************
1633 * ImmGetStatusWindowPos (IMM32.@)
1635 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1637 FIXME("(%p, %p): stub\n", hIMC, lpptPos);
1638 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1642 /***********************************************************************
1643 * ImmGetVirtualKey (IMM32.@)
1645 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1647 OSVERSIONINFOA version;
1648 FIXME("(%p): stub\n", hWnd);
1649 GetVersionExA( &version );
1650 switch(version.dwPlatformId)
1652 case VER_PLATFORM_WIN32_WINDOWS:
1653 return VK_PROCESSKEY;
1654 case VER_PLATFORM_WIN32_NT:
1657 FIXME("%d not supported\n",version.dwPlatformId);
1658 return VK_PROCESSKEY;
1662 /***********************************************************************
1663 * ImmInstallIMEA (IMM32.@)
1665 HKL WINAPI ImmInstallIMEA(
1666 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1668 FIXME("(%s, %s): stub\n",
1669 debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText)
1671 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1675 /***********************************************************************
1676 * ImmInstallIMEW (IMM32.@)
1678 HKL WINAPI ImmInstallIMEW(
1679 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1681 FIXME("(%s, %s): stub\n",
1682 debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText)
1684 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1688 /***********************************************************************
1689 * ImmIsIME (IMM32.@)
1691 BOOL WINAPI ImmIsIME(HKL hKL)
1693 TRACE("(%p): semi-stub\n", hKL);
1695 * FIXME: Dead key locales will return TRUE here when they should not
1696 * There is probably a more proper way to check this.
1698 return (root_context != NULL);
1701 /***********************************************************************
1702 * ImmIsUIMessageA (IMM32.@)
1704 BOOL WINAPI ImmIsUIMessageA(
1705 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1709 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1710 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1711 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1712 (msg == WM_MSIME_SERVICE) ||
1713 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1714 (msg == WM_MSIME_MOUSE) ||
1715 (msg == WM_MSIME_RECONVERTREQUEST) ||
1716 (msg == WM_MSIME_RECONVERT) ||
1717 (msg == WM_MSIME_QUERYPOSITION) ||
1718 (msg == WM_MSIME_DOCUMENTFEED))
1722 ImmGetDefaultIMEWnd(NULL);
1724 if (hWndIME == NULL)
1725 PostMessageA(hwndDefault, msg, wParam, lParam);
1732 /***********************************************************************
1733 * ImmIsUIMessageW (IMM32.@)
1735 BOOL WINAPI ImmIsUIMessageW(
1736 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1739 TRACE("(%p, %d, %ld, %ld): stub\n", hWndIME, msg, wParam, lParam);
1740 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1741 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1742 (msg == WM_MSIME_SERVICE) ||
1743 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1744 (msg == WM_MSIME_MOUSE) ||
1745 (msg == WM_MSIME_RECONVERTREQUEST) ||
1746 (msg == WM_MSIME_RECONVERT) ||
1747 (msg == WM_MSIME_QUERYPOSITION) ||
1748 (msg == WM_MSIME_DOCUMENTFEED))
1753 /***********************************************************************
1754 * ImmNotifyIME (IMM32.@)
1756 BOOL WINAPI ImmNotifyIME(
1757 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
1761 TRACE("(%p, %d, %d, %d)\n",
1762 hIMC, dwAction, dwIndex, dwValue);
1769 case NI_CHANGECANDIDATELIST:
1770 FIXME("%s\n","NI_CHANGECANDIDATELIST");
1772 case NI_CLOSECANDIDATE:
1773 FIXME("%s\n","NI_CLOSECANDIDATE");
1775 case NI_COMPOSITIONSTR:
1779 TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_CANCEL");
1782 LPCOMPOSITIONSTRING lpCompStr;
1784 if (pX11DRV_ForceXIMReset)
1785 pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
1787 lpCompStr = ImmLockIMCC(root_context->IMC.hCompStr);
1788 send = (lpCompStr->dwCompStrLen != 0);
1789 ImmUnlockIMCC(root_context->IMC.hCompStr);
1791 ImmDestroyIMCC(root_context->IMC.hCompStr);
1792 root_context->IMC.hCompStr = ImmCreateBlankCompStr();
1795 ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION, 0,
1801 TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_COMPLETE");
1802 if (hIMC != (HIMC)FROM_IME && pX11DRV_ForceXIMReset)
1803 pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
1808 LPCOMPOSITIONSTRING cs = NULL;
1809 LPBYTE cdata = NULL;
1811 /* clear existing result */
1812 newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0);
1813 ImmDestroyIMCC(root_context->IMC.hCompStr);
1814 root_context->IMC.hCompStr = newCompStr;
1816 if (root_context->IMC.hCompStr)
1818 cdata = ImmLockIMCC(root_context->IMC.hCompStr);
1819 cs = (LPCOMPOSITIONSTRING)cdata;
1820 cplen = cs->dwCompStrLen;
1821 cpstr = (LPWSTR)&(cdata[cs->dwCompStrOffset]);
1822 ImmUnlockIMCC(root_context->IMC.hCompStr);
1826 WCHAR param = cpstr[0];
1827 newCompStr = updateResultStr(root_context->IMC.hCompStr, cpstr, cplen);
1828 ImmDestroyIMCC(root_context->IMC.hCompStr);
1829 root_context->IMC.hCompStr = newCompStr;
1830 newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
1831 ImmDestroyIMCC(root_context->IMC.hCompStr);
1832 root_context->IMC.hCompStr = newCompStr;
1834 root_context->bRead = FALSE;
1836 ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION, 0,
1839 ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION,
1841 GCS_RESULTSTR|GCS_RESULTCLAUSE);
1844 ImmInternalPostIMEMessage(root_context, WM_IME_ENDCOMPOSITION, 0, 0);
1845 root_context->bInComposition = FALSE;
1849 FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_CONVERT");
1852 FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_REVERT");
1855 ERR("%s - %s (%i)\n","NI_COMPOSITIONSTR","UNKNOWN",dwIndex);
1859 case NI_IMEMENUSELECTED:
1860 FIXME("%s\n", "NI_IMEMENUSELECTED");
1862 case NI_OPENCANDIDATE:
1863 FIXME("%s\n", "NI_OPENCANDIDATE");
1865 case NI_SELECTCANDIDATESTR:
1866 FIXME("%s\n", "NI_SELECTCANDIDATESTR");
1868 case NI_SETCANDIDATE_PAGESIZE:
1869 FIXME("%s\n", "NI_SETCANDIDATE_PAGESIZE");
1871 case NI_SETCANDIDATE_PAGESTART:
1872 FIXME("%s\n", "NI_SETCANDIDATE_PAGESTART");
1881 /***********************************************************************
1882 * ImmRegisterWordA (IMM32.@)
1884 BOOL WINAPI ImmRegisterWordA(
1885 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
1887 FIXME("(%p, %s, %d, %s): stub\n",
1888 hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister)
1890 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1894 /***********************************************************************
1895 * ImmRegisterWordW (IMM32.@)
1897 BOOL WINAPI ImmRegisterWordW(
1898 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
1900 FIXME("(%p, %s, %d, %s): stub\n",
1901 hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister)
1903 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1907 /***********************************************************************
1908 * ImmReleaseContext (IMM32.@)
1910 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
1912 static int shown = 0;
1915 FIXME("(%p, %p): stub\n", hWnd, hIMC);
1921 /***********************************************************************
1922 * ImmSetCandidateWindow (IMM32.@)
1924 BOOL WINAPI ImmSetCandidateWindow(
1925 HIMC hIMC, LPCANDIDATEFORM lpCandidate)
1927 FIXME("(%p, %p): stub\n", hIMC, lpCandidate);
1928 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1932 /***********************************************************************
1933 * ImmSetCompositionFontA (IMM32.@)
1935 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1937 InputContextData *data = (InputContextData*)hIMC;
1938 TRACE("(%p, %p)\n", hIMC, lplf);
1943 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
1944 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
1947 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
1951 DeleteObject(data->textfont);
1952 data->textfont = NULL;
1955 data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
1959 /***********************************************************************
1960 * ImmSetCompositionFontW (IMM32.@)
1962 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1964 InputContextData *data = (InputContextData*)hIMC;
1965 TRACE("(%p, %p)\n", hIMC, lplf);
1970 data->IMC.lfFont.W = *lplf;
1971 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
1975 DeleteObject(data->textfont);
1976 data->textfont = NULL;
1978 data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
1982 /***********************************************************************
1983 * ImmSetCompositionStringA (IMM32.@)
1985 BOOL WINAPI ImmSetCompositionStringA(
1986 HIMC hIMC, DWORD dwIndex,
1987 LPCVOID lpComp, DWORD dwCompLen,
1988 LPCVOID lpRead, DWORD dwReadLen)
1992 WCHAR *CompBuffer = NULL;
1993 WCHAR *ReadBuffer = NULL;
1996 TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
1997 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
1999 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
2002 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
2003 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
2006 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
2009 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
2010 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
2013 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
2014 ReadBuffer, read_len);
2016 HeapFree(GetProcessHeap(), 0, CompBuffer);
2017 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2022 /***********************************************************************
2023 * ImmSetCompositionStringW (IMM32.@)
2025 BOOL WINAPI ImmSetCompositionStringW(
2026 HIMC hIMC, DWORD dwIndex,
2027 LPCVOID lpComp, DWORD dwCompLen,
2028 LPCVOID lpRead, DWORD dwReadLen)
2033 TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
2034 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2037 if (hIMC != (HIMC)FROM_IME)
2038 FIXME("PROBLEM: This only sets the wine level string\n");
2042 * this sets the composition string in the imm32.dll level
2043 * of the composition buffer. we cannot manipulate the xim level
2044 * buffer, which means that once the xim level buffer changes again
2045 * any call to this function from the application will be lost
2048 if (lpRead && dwReadLen)
2049 FIXME("Reading string unimplemented\n");
2052 * app operating this api to also receive the message from xim
2055 if (dwIndex == SCS_SETSTR)
2058 if (!root_context->bInComposition)
2060 ImmInternalPostIMEMessage(root_context, WM_IME_STARTCOMPOSITION, 0, 0);
2061 root_context->bInComposition = TRUE;
2064 flags = GCS_COMPSTR;
2066 if (dwCompLen && lpComp)
2068 newCompStr = updateCompStr(root_context->IMC.hCompStr, (LPWSTR)lpComp, dwCompLen / sizeof(WCHAR));
2069 ImmDestroyIMCC(root_context->IMC.hCompStr);
2070 root_context->IMC.hCompStr = newCompStr;
2072 wParam = ((const WCHAR*)lpComp)[0];
2073 flags |= GCS_COMPCLAUSE | GCS_COMPATTR | GCS_DELTASTART;
2077 newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
2078 ImmDestroyIMCC(root_context->IMC.hCompStr);
2079 root_context->IMC.hCompStr = newCompStr;
2083 UpdateDataInDefaultIMEWindow(hwndDefault,FALSE);
2085 ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION, wParam, flags);
2090 /***********************************************************************
2091 * ImmSetCompositionWindow (IMM32.@)
2093 BOOL WINAPI ImmSetCompositionWindow(
2094 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
2096 BOOL reshow = FALSE;
2097 InputContextData *data = (InputContextData*)hIMC;
2099 TRACE("(%p, %p)\n", hIMC, lpCompForm);
2100 TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
2101 lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
2102 lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
2107 data->IMC.cfCompForm = *lpCompForm;
2109 if (IsWindowVisible(hwndDefault))
2112 ShowWindow(hwndDefault,SW_HIDE);
2115 /* FIXME: this is a partial stub */
2118 ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
2120 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0);
2124 /***********************************************************************
2125 * ImmSetConversionStatus (IMM32.@)
2127 BOOL WINAPI ImmSetConversionStatus(
2128 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
2130 static int shown = 0;
2133 FIXME("(%p, %d, %d): stub\n",
2134 hIMC, fdwConversion, fdwSentence
2138 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2142 /***********************************************************************
2143 * ImmSetOpenStatus (IMM32.@)
2145 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
2147 InputContextData *data = (InputContextData*)hIMC;
2149 TRACE("%p %d\n", hIMC, fOpen);
2151 if (hIMC == (HIMC)FROM_IME)
2153 ImmInternalSetOpenStatus(fOpen);
2154 ImmInternalSendIMENotify(root_context, IMN_SETOPENSTATUS, 0);
2161 if (fOpen != data->bInternalState)
2163 if (fOpen == FALSE && pX11DRV_ForceXIMReset)
2164 pX11DRV_ForceXIMReset(data->IMC.hWnd);
2167 ImmInternalPostIMEMessage(data, WM_IME_ENDCOMPOSITION,0,0);
2169 ImmInternalPostIMEMessage(data, WM_IME_STARTCOMPOSITION,0,0);
2171 ImmInternalSetOpenStatus(fOpen);
2172 ImmInternalSetOpenStatus(!fOpen);
2174 if (data->IMC.fOpen == FALSE)
2175 ImmInternalPostIMEMessage(data, WM_IME_ENDCOMPOSITION,0,0);
2177 ImmInternalPostIMEMessage(data, WM_IME_STARTCOMPOSITION,0,0);
2184 /***********************************************************************
2185 * ImmSetStatusWindowPos (IMM32.@)
2187 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
2189 FIXME("(%p, %p): stub\n", hIMC, lpptPos);
2190 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2194 /***********************************************************************
2195 * ImmSimulateHotKey (IMM32.@)
2197 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
2199 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
2200 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2204 /***********************************************************************
2205 * ImmUnregisterWordA (IMM32.@)
2207 BOOL WINAPI ImmUnregisterWordA(
2208 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
2210 FIXME("(%p, %s, %d, %s): stub\n",
2211 hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszUnregister)
2213 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2217 /***********************************************************************
2218 * ImmUnregisterWordW (IMM32.@)
2220 BOOL WINAPI ImmUnregisterWordW(
2221 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
2223 FIXME("(%p, %s, %d, %s): stub\n",
2224 hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszUnregister)
2226 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2230 /***********************************************************************
2231 * ImmGetImeMenuItemsA (IMM32.@)
2233 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2234 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
2237 InputContextData *data = (InputContextData*)hIMC;
2238 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2239 lpImeParentMenu, lpImeMenu, dwSize);
2240 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2242 if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2243 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2244 (IMEMENUITEMINFOW*)lpImeParentMenu,
2245 (IMEMENUITEMINFOW*)lpImeMenu, dwSize);
2248 IMEMENUITEMINFOW lpImeParentMenuW;
2249 IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL;
2252 if (lpImeParentMenu)
2253 parent = &lpImeParentMenuW;
2256 int count = dwSize / sizeof(LPIMEMENUITEMINFOA);
2257 dwSize = count * sizeof(IMEMENUITEMINFOW);
2258 lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize);
2263 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2264 parent, lpImeMenuW, dwSize);
2266 if (lpImeParentMenu)
2268 memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA));
2269 lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem;
2270 WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString,
2271 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE,
2274 if (lpImeMenu && rc)
2277 for (i = 0; i < rc; i++)
2279 memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA));
2280 lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem;
2281 WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString,
2282 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE,
2286 HeapFree(GetProcessHeap(),0,lpImeMenuW);
2294 /***********************************************************************
2295 * ImmGetImeMenuItemsW (IMM32.@)
2297 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2298 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
2301 InputContextData *data = (InputContextData*)hIMC;
2302 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2303 lpImeParentMenu, lpImeMenu, dwSize);
2304 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2306 if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2307 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2308 lpImeParentMenu, lpImeMenu, dwSize);
2311 IMEMENUITEMINFOA lpImeParentMenuA;
2312 IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL;
2315 if (lpImeParentMenu)
2316 parent = &lpImeParentMenuA;
2319 int count = dwSize / sizeof(LPIMEMENUITEMINFOW);
2320 dwSize = count * sizeof(IMEMENUITEMINFOA);
2321 lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize);
2326 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2327 (IMEMENUITEMINFOW*)parent,
2328 (IMEMENUITEMINFOW*)lpImeMenuA, dwSize);
2330 if (lpImeParentMenu)
2332 memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA));
2333 lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem;
2334 MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString,
2335 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE);
2337 if (lpImeMenu && rc)
2340 for (i = 0; i < rc; i++)
2342 memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA));
2343 lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem;
2344 MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString,
2345 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE);
2348 HeapFree(GetProcessHeap(),0,lpImeMenuA);
2356 /***********************************************************************
2357 * ImmLockIMC(IMM32.@)
2359 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
2361 InputContextData *data = (InputContextData*)hIMC;
2369 /***********************************************************************
2370 * ImmUnlockIMC(IMM32.@)
2372 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
2374 InputContextData *data = (InputContextData*)hIMC;
2376 return (data->dwLock!=0);
2379 /***********************************************************************
2380 * ImmGetIMCLockCount(IMM32.@)
2382 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
2384 InputContextData *data = (InputContextData*)hIMC;
2385 return data->dwLock;
2388 /***********************************************************************
2389 * ImmCreateIMCC(IMM32.@)
2391 HIMCC WINAPI ImmCreateIMCC(DWORD size)
2393 IMCCInternal *internal;
2394 int real_size = size + sizeof(IMCCInternal);
2396 internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size);
2397 if (internal == NULL)
2400 internal->dwSize = size;
2401 return (HIMCC)internal;
2404 /***********************************************************************
2405 * ImmDestroyIMCC(IMM32.@)
2407 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
2409 HeapFree(GetProcessHeap(),0,block);
2413 /***********************************************************************
2414 * ImmLockIMCC(IMM32.@)
2416 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
2418 IMCCInternal *internal;
2419 internal = (IMCCInternal*) imcc;
2421 internal->dwLock ++;
2422 return internal + 1;
2425 /***********************************************************************
2426 * ImmUnlockIMCC(IMM32.@)
2428 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
2430 IMCCInternal *internal;
2431 internal = (IMCCInternal*) imcc;
2433 internal->dwLock --;
2434 return (internal->dwLock!=0);
2437 /***********************************************************************
2438 * ImmGetIMCCLockCount(IMM32.@)
2440 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
2442 IMCCInternal *internal;
2443 internal = (IMCCInternal*) imcc;
2445 return internal->dwLock;
2448 /***********************************************************************
2449 * ImmReSizeIMCC(IMM32.@)
2451 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
2453 IMCCInternal *internal,*newone;
2454 int real_size = size + sizeof(IMCCInternal);
2456 internal = (IMCCInternal*) imcc;
2458 newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size);
2459 newone->dwSize = size;
2464 /***********************************************************************
2465 * ImmGetIMCCSize(IMM32.@)
2467 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2469 IMCCInternal *internal;
2470 internal = (IMCCInternal*) imcc;
2472 return internal->dwSize;
2475 /***********************************************************************
2476 * ImmGenerateMessage(IMM32.@)
2478 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2480 InputContextData *data = (InputContextData*)hIMC;
2482 TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
2483 if (data->IMC.dwNumMsgBuf > 0)
2485 LPTRANSMSG lpTransMsg;
2488 lpTransMsg = (LPTRANSMSG)ImmLockIMCC(data->IMC.hMsgBuf);
2489 for (i = 0; i < data->IMC.dwNumMsgBuf; i++)
2490 ImmInternalPostIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
2492 ImmUnlockIMCC(data->IMC.hMsgBuf);
2494 data->IMC.dwNumMsgBuf = 0;
2501 * Internal functions to help with IME window management
2503 static void PaintDefaultIMEWnd(HWND hwnd)
2507 HDC hdc = BeginPaint(hwnd,&ps);
2508 LPCOMPOSITIONSTRING compstr;
2509 LPBYTE compdata = NULL;
2511 MONITORINFO mon_info;
2514 GetClientRect(hwnd,&rect);
2515 FillRect(hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1));
2517 compdata = ImmLockIMCC(root_context->IMC.hCompStr);
2518 compstr = (LPCOMPOSITIONSTRING)compdata;
2520 if (compstr->dwCompStrLen && compstr->dwCompStrOffset)
2524 HFONT oldfont = NULL;
2527 CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
2528 if (root_context->textfont)
2529 oldfont = SelectObject(hdc,root_context->textfont);
2532 GetTextExtentPoint32W(hdc, CompString, compstr->dwCompStrLen, &size);
2538 * How this works based on tests on windows:
2539 * CFS_POINT: then we start our window at the point and grow it as large
2540 * as it needs to be for the string.
2541 * CFS_RECT: we still use the ptCurrentPos as a starting point and our
2542 * window is only as large as we need for the string, but we do not
2543 * grow such that our window exceeds the given rect. Wrapping if
2544 * needed and possible. If our ptCurrentPos is outside of our rect
2545 * then no window is displayed.
2546 * CFS_FORCE_POSITION: appears to behave just like CFS_POINT
2547 * maybe becase the default MSIME does not do any IME adjusting.
2549 if (root_context->IMC.cfCompForm.dwStyle != CFS_DEFAULT)
2551 POINT cpt = root_context->IMC.cfCompForm.ptCurrentPos;
2552 ClientToScreen(root_context->IMC.hWnd,&cpt);
2555 rect.right = rect.left + pt.x;
2556 rect.bottom = rect.top + pt.y;
2557 monitor = MonitorFromPoint(cpt, MONITOR_DEFAULTTOPRIMARY);
2559 else /* CFS_DEFAULT */
2561 /* Windows places the default IME window in the bottom left */
2562 HWND target = root_context->IMC.hWnd;
2563 if (!target) target = GetFocus();
2565 GetWindowRect(target,&rect);
2566 rect.top = rect.bottom;
2567 rect.right = rect.left + pt.x + 20;
2568 rect.bottom = rect.top + pt.y + 20;
2570 monitor = MonitorFromWindow(target, MONITOR_DEFAULTTOPRIMARY);
2573 if (root_context->IMC.cfCompForm.dwStyle == CFS_RECT)
2576 client =root_context->IMC.cfCompForm.rcArea;
2577 MapWindowPoints( root_context->IMC.hWnd, 0, (POINT *)&client, 2 );
2578 IntersectRect(&rect,&rect,&client);
2579 /* TODO: Wrap the input if needed */
2582 if (root_context->IMC.cfCompForm.dwStyle == CFS_DEFAULT)
2584 /* make sure we are on the desktop */
2585 mon_info.cbSize = sizeof(mon_info);
2586 GetMonitorInfoW(monitor, &mon_info);
2588 if (rect.bottom > mon_info.rcWork.bottom)
2590 int shift = rect.bottom - mon_info.rcWork.bottom;
2592 rect.bottom -= shift;
2596 rect.right -= rect.left;
2599 if (rect.right > mon_info.rcWork.right)
2601 int shift = rect.right - mon_info.rcWork.right;
2603 rect.right -= shift;
2607 SetWindowPos(hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE);
2609 TextOutW(hdc, offX,offY, CompString, compstr->dwCompStrLen);
2612 SelectObject(hdc,oldfont);
2615 ImmUnlockIMCC(root_context->IMC.hCompStr);
2620 static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable)
2622 LPCOMPOSITIONSTRING compstr;
2624 if (root_context->IMC.hCompStr)
2625 compstr = ImmLockIMCC(root_context->IMC.hCompStr);
2629 if (compstr == NULL || compstr->dwCompStrLen == 0)
2630 ShowWindow(hwndDefault,SW_HIDE);
2632 ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
2634 RedrawWindow(hwnd,NULL,NULL,RDW_ERASENOW|RDW_INVALIDATE);
2636 if (compstr != NULL)
2637 ImmUnlockIMCC(root_context->IMC.hCompStr);
2641 * The window proc for the default IME window
2643 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam,
2648 TRACE("Incoming Message 0x%x (0x%08x, 0x%08x)\n", msg, (UINT)wParam,
2654 PaintDefaultIMEWnd(hwnd);
2661 SetWindowTextA(hwnd,"Wine Ime Active");
2666 SetFocus((HWND)wParam);
2668 FIXME("Received focus, should never have focus\n");
2670 case WM_IME_COMPOSITION:
2671 TRACE("IME message %s, 0x%x, 0x%x (%i)\n",
2672 "WM_IME_COMPOSITION", (UINT)wParam, (UINT)lParam,
2673 root_context->bRead);
2674 if (lParam & GCS_RESULTSTR)
2675 IMM_PostResult(root_context);
2677 UpdateDataInDefaultIMEWindow(hwnd,TRUE);
2679 case WM_IME_STARTCOMPOSITION:
2680 TRACE("IME message %s, 0x%x, 0x%x\n",
2681 "WM_IME_STARTCOMPOSITION", (UINT)wParam, (UINT)lParam);
2682 root_context->IMC.hWnd = GetFocus();
2683 ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
2685 case WM_IME_ENDCOMPOSITION:
2686 TRACE("IME message %s, 0x%x, 0x%x\n",
2687 "WM_IME_ENDCOMPOSITION", (UINT)wParam, (UINT)lParam);
2688 ShowWindow(hwndDefault,SW_HIDE);
2691 TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_SELECT",
2692 (UINT)wParam, (UINT)lParam);
2694 case WM_IME_CONTROL:
2695 TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_CONTROL",
2696 (UINT)wParam, (UINT)lParam);
2700 TRACE("!! IME NOTIFY\n");
2703 TRACE("Non-standard message 0x%x\n",msg);
2705 /* check the MSIME messages */
2706 if (msg == WM_MSIME_SERVICE)
2708 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_SERVICE",
2709 (UINT)wParam, (UINT)lParam);
2712 else if (msg == WM_MSIME_RECONVERTOPTIONS)
2714 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTOPTIONS",
2715 (UINT)wParam, (UINT)lParam);
2717 else if (msg == WM_MSIME_MOUSE)
2719 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_MOUSE",
2720 (UINT)wParam, (UINT)lParam);
2722 else if (msg == WM_MSIME_RECONVERTREQUEST)
2724 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTREQUEST",
2725 (UINT)wParam, (UINT)lParam);
2727 else if (msg == WM_MSIME_RECONVERT)
2729 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERT",
2730 (UINT)wParam, (UINT)lParam);
2732 else if (msg == WM_MSIME_QUERYPOSITION)
2734 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_QUERYPOSITION",
2735 (UINT)wParam, (UINT)lParam);
2737 else if (msg == WM_MSIME_DOCUMENTFEED)
2739 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_DOCUMENTFEED",
2740 (UINT)wParam, (UINT)lParam);
2742 /* DefWndProc if not an IME message */
2743 else if (!rc && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2744 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP)))
2745 rc = DefWindowProcW(hwnd,msg,wParam,lParam);