user32: Prefer loading color cursors in LoadImage.
[wine.git] / dlls / imm32 / imm.c
blobfbb683f50d4e1d987040653bfde5d9a4c268d167
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>
23 #include <stdio.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winerror.h"
30 #include "wine/debug.h"
31 #include "imm.h"
32 #include "ddk/imm.h"
33 #include "winnls.h"
34 #include "winreg.h"
35 #include "wine/gdi_driver.h"
36 #include "wine/list.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(imm);
40 typedef struct tagIMCCInternal
42 DWORD dwLock;
43 DWORD dwSize;
44 } IMCCInternal;
46 #define MAKE_FUNCPTR(f) typeof(f) * p##f
47 typedef struct _tagImmHkl{
48 struct list entry;
49 HKL hkl;
50 HMODULE hIME;
51 IMEINFO imeInfo;
52 WCHAR imeClassName[17]; /* 16 character max */
53 ULONG uSelected;
54 HWND UIWnd;
56 /* Function Pointers */
57 MAKE_FUNCPTR(ImeInquire);
58 MAKE_FUNCPTR(ImeConfigure);
59 MAKE_FUNCPTR(ImeDestroy);
60 MAKE_FUNCPTR(ImeEscape);
61 MAKE_FUNCPTR(ImeSelect);
62 MAKE_FUNCPTR(ImeSetActiveContext);
63 MAKE_FUNCPTR(ImeToAsciiEx);
64 MAKE_FUNCPTR(NotifyIME);
65 MAKE_FUNCPTR(ImeRegisterWord);
66 MAKE_FUNCPTR(ImeUnregisterWord);
67 MAKE_FUNCPTR(ImeEnumRegisterWord);
68 MAKE_FUNCPTR(ImeSetCompositionString);
69 MAKE_FUNCPTR(ImeConversionList);
70 MAKE_FUNCPTR(ImeProcessKey);
71 MAKE_FUNCPTR(ImeGetRegisterWordStyle);
72 MAKE_FUNCPTR(ImeGetImeMenuItems);
73 } ImmHkl;
74 #undef MAKE_FUNCPTR
76 typedef struct tagInputContextData
78 DWORD dwLock;
79 INPUTCONTEXT IMC;
81 ImmHkl *immKbd;
82 UINT lastVK;
83 } InputContextData;
85 typedef struct _tagTRANSMSG {
86 UINT message;
87 WPARAM wParam;
88 LPARAM lParam;
89 } TRANSMSG, *LPTRANSMSG;
91 typedef struct _tagIMMThreadData {
92 HIMC defaultContext;
93 HWND hwndDefault;
94 } IMMThreadData;
96 static DWORD tlsIndex = 0;
97 static struct list ImmHklList = LIST_INIT(ImmHklList);
99 /* MSIME messages */
100 static UINT WM_MSIME_SERVICE;
101 static UINT WM_MSIME_RECONVERTOPTIONS;
102 static UINT WM_MSIME_MOUSE;
103 static UINT WM_MSIME_RECONVERTREQUEST;
104 static UINT WM_MSIME_RECONVERT;
105 static UINT WM_MSIME_QUERYPOSITION;
106 static UINT WM_MSIME_DOCUMENTFEED;
108 static const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
110 static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
111 static const WCHAR szLayoutTextW[] = {'L','a','y','o','u','t',' ','T','e','x','t',0};
112 static const WCHAR szImeRegFmt[] = {'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','l','x',0};
114 static const WCHAR szwIME[] = {'I','M','E',0};
116 static LRESULT WINAPI DefIME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
117 LPARAM lParam);
119 #define is_himc_ime_unicode(p) (p->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE)
120 #define is_kbd_ime_unicode(p) (p->imeInfo.fdwProperty & IME_PROP_UNICODE)
122 static BOOL IMM_DestroyContext(HIMC hIMC);
124 static inline WCHAR *strdupAtoW( const char *str )
126 WCHAR *ret = NULL;
127 if (str)
129 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
130 if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
131 MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
133 return ret;
136 static inline CHAR *strdupWtoA( const WCHAR *str )
138 CHAR *ret = NULL;
139 if (str)
141 DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
142 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
143 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
145 return ret;
148 static DWORD convert_candidatelist_WtoA(
149 LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen)
151 DWORD ret, i, len;
153 ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] );
154 if ( lpDst && dwBufLen > 0 )
156 *lpDst = *lpSrc;
157 lpDst->dwOffset[0] = ret;
160 for ( i = 0; i < lpSrc->dwCount; i++)
162 LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
164 if ( lpDst && dwBufLen > 0 )
166 LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
168 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1,
169 (LPSTR)dest, dwBufLen, NULL, NULL);
171 if ( i + 1 < lpSrc->dwCount )
172 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(char);
173 dwBufLen -= len * sizeof(char);
175 else
176 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, NULL, 0, NULL, NULL);
178 ret += len * sizeof(char);
181 if ( lpDst )
182 lpDst->dwSize = ret;
184 return ret;
187 static DWORD convert_candidatelist_AtoW(
188 LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen)
190 DWORD ret, i, len;
192 ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] );
193 if ( lpDst && dwBufLen > 0 )
195 *lpDst = *lpSrc;
196 lpDst->dwOffset[0] = ret;
199 for ( i = 0; i < lpSrc->dwCount; i++)
201 LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
203 if ( lpDst && dwBufLen > 0 )
205 LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
207 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1,
208 (LPWSTR)dest, dwBufLen);
210 if ( i + 1 < lpSrc->dwCount )
211 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(WCHAR);
212 dwBufLen -= len * sizeof(WCHAR);
214 else
215 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, NULL, 0);
217 ret += len * sizeof(WCHAR);
220 if ( lpDst )
221 lpDst->dwSize = ret;
223 return ret;
226 static IMMThreadData* IMM_GetThreadData(void)
228 IMMThreadData* data = TlsGetValue(tlsIndex);
229 if (!data)
231 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
232 sizeof(IMMThreadData));
233 TlsSetValue(tlsIndex,data);
234 TRACE("Thread Data Created\n");
236 return data;
239 static void IMM_FreeThreadData(void)
241 IMMThreadData* data = TlsGetValue(tlsIndex);
242 if (data)
244 IMM_DestroyContext(data->defaultContext);
245 DestroyWindow(data->hwndDefault);
246 HeapFree(GetProcessHeap(),0,data);
247 TRACE("Thread Data Destroyed\n");
251 /* ImmHkl loading and freeing */
252 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
253 static ImmHkl *IMM_GetImmHkl(HKL hkl)
255 ImmHkl *ptr;
256 WCHAR filename[MAX_PATH];
258 TRACE("Seeking ime for keyboard %p\n",hkl);
260 LIST_FOR_EACH_ENTRY(ptr, &ImmHklList, ImmHkl, entry)
262 if (ptr->hkl == hkl)
263 return ptr;
265 /* not found... create it */
267 ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ImmHkl));
269 ptr->hkl = hkl;
270 if (ImmGetIMEFileNameW(hkl, filename, MAX_PATH)) ptr->hIME = LoadLibraryW(filename);
271 if (!ptr->hIME)
273 HDC hdc = GetDC( 0 );
274 GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
275 (LPCWSTR)__wine_get_driver_module( hdc ), &ptr->hIME );
276 ReleaseDC( 0, hdc );
278 if (ptr->hIME)
280 LOAD_FUNCPTR(ImeInquire);
281 if (!ptr->pImeInquire || !ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL))
283 FreeLibrary(ptr->hIME);
284 ptr->hIME = NULL;
286 else
288 LOAD_FUNCPTR(ImeDestroy);
289 LOAD_FUNCPTR(ImeSelect);
290 if (!ptr->pImeSelect || !ptr->pImeDestroy)
292 FreeLibrary(ptr->hIME);
293 ptr->hIME = NULL;
295 else
297 LOAD_FUNCPTR(ImeConfigure);
298 LOAD_FUNCPTR(ImeEscape);
299 LOAD_FUNCPTR(ImeSetActiveContext);
300 LOAD_FUNCPTR(ImeToAsciiEx);
301 LOAD_FUNCPTR(NotifyIME);
302 LOAD_FUNCPTR(ImeRegisterWord);
303 LOAD_FUNCPTR(ImeUnregisterWord);
304 LOAD_FUNCPTR(ImeEnumRegisterWord);
305 LOAD_FUNCPTR(ImeSetCompositionString);
306 LOAD_FUNCPTR(ImeConversionList);
307 LOAD_FUNCPTR(ImeProcessKey);
308 LOAD_FUNCPTR(ImeGetRegisterWordStyle);
309 LOAD_FUNCPTR(ImeGetImeMenuItems);
310 /* make sure our classname is WCHAR */
311 if (!is_kbd_ime_unicode(ptr))
313 WCHAR bufW[17];
314 MultiByteToWideChar(CP_ACP, 0, (LPSTR)ptr->imeClassName,
315 -1, bufW, 17);
316 lstrcpyW(ptr->imeClassName, bufW);
321 list_add_head(&ImmHklList,&ptr->entry);
323 return ptr;
325 #undef LOAD_FUNCPTR
327 static void IMM_FreeAllImmHkl(void)
329 ImmHkl *ptr,*cursor2;
331 LIST_FOR_EACH_ENTRY_SAFE(ptr, cursor2, &ImmHklList, ImmHkl, entry)
333 list_remove(&ptr->entry);
334 if (ptr->hIME)
336 ptr->pImeDestroy(1);
337 FreeLibrary(ptr->hIME);
339 if (ptr->UIWnd)
340 DestroyWindow(ptr->UIWnd);
341 HeapFree(GetProcessHeap(),0,ptr);
345 static void IMM_RegisterMessages(void)
347 WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");
348 WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions");
349 WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
350 WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
351 WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
352 WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
353 WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
356 static void IMM_RegisterIMEClass(void)
358 WNDCLASSW wndClass;
360 ZeroMemory(&wndClass, sizeof(WNDCLASSW));
362 wndClass.style = CS_GLOBALCLASS;
363 wndClass.lpfnWndProc = (WNDPROC) DefIME_WindowProc;
364 wndClass.cbWndExtra = 2 * sizeof(LONG_PTR);
365 wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
366 wndClass.lpszClassName = szwIME;
368 RegisterClassW(&wndClass);
371 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
373 TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
374 switch (fdwReason)
376 case DLL_PROCESS_ATTACH:
377 IMM_RegisterMessages();
378 tlsIndex = TlsAlloc();
379 if (tlsIndex == TLS_OUT_OF_INDEXES)
380 return FALSE;
381 IMM_RegisterIMEClass();
382 break;
383 case DLL_THREAD_ATTACH:
384 break;
385 case DLL_THREAD_DETACH:
386 IMM_FreeThreadData();
387 break;
388 case DLL_PROCESS_DETACH:
389 IMM_FreeThreadData();
390 IMM_FreeAllImmHkl();
391 TlsFree(tlsIndex);
392 UnregisterClassW(szwIME, NULL);
393 break;
395 return TRUE;
398 /* for posting messages as the IME */
399 static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
401 HWND target = GetFocus();
402 if (!target)
403 PostMessageW(data->IMC.hWnd,msg,wParam,lParam);
404 else
405 PostMessageW(target, msg, wParam, lParam);
408 static LRESULT ImmInternalSendIMENotify(InputContextData *data, WPARAM notify, LPARAM lParam)
410 HWND target;
412 target = data->IMC.hWnd;
413 if (!target) target = GetFocus();
415 if (target)
416 return SendMessageW(target, WM_IME_NOTIFY, notify, lParam);
418 return 0;
421 static HIMCC ImmCreateBlankCompStr(void)
423 HIMCC rc;
424 LPCOMPOSITIONSTRING ptr;
425 rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
426 ptr = ImmLockIMCC(rc);
427 memset(ptr,0,sizeof(COMPOSITIONSTRING));
428 ptr->dwSize = sizeof(COMPOSITIONSTRING);
429 ImmUnlockIMCC(rc);
430 return rc;
433 /***********************************************************************
434 * ImmAssociateContext (IMM32.@)
436 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
438 HIMC old = NULL;
439 InputContextData *data = hIMC;
441 TRACE("(%p, %p):\n", hWnd, hIMC);
443 if (!IMM_GetThreadData()->defaultContext)
444 IMM_GetThreadData()->defaultContext = ImmCreateContext();
447 * If already associated just return
449 if (hIMC && data->IMC.hWnd == hWnd)
450 return hIMC;
452 if (hWnd)
454 old = RemovePropW(hWnd,szwWineIMCProperty);
456 if (old == NULL)
457 old = IMM_GetThreadData()->defaultContext;
458 else if (old == (HIMC)-1)
459 old = NULL;
461 if (hIMC != IMM_GetThreadData()->defaultContext)
463 if (hIMC == NULL) /* Meaning disable imm for that window*/
464 SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1);
465 else
466 SetPropW(hWnd,szwWineIMCProperty,hIMC);
469 if (old)
471 InputContextData *old_data = old;
472 if (old_data->IMC.hWnd == hWnd)
473 old_data->IMC.hWnd = NULL;
477 if (!hIMC)
478 return old;
480 if (IsWindow(data->IMC.hWnd))
483 * Post a message that your context is switching
485 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
488 data->IMC.hWnd = hWnd;
490 if (IsWindow(data->IMC.hWnd))
493 * Post a message that your context is switching
495 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
498 return old;
503 * Helper function for ImmAssociateContextEx
505 static BOOL CALLBACK _ImmAssociateContextExEnumProc(HWND hwnd, LPARAM lParam)
507 HIMC hImc = (HIMC)lParam;
508 ImmAssociateContext(hwnd,hImc);
509 return TRUE;
512 /***********************************************************************
513 * ImmAssociateContextEx (IMM32.@)
515 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
517 TRACE("(%p, %p, 0x%x):\n", hWnd, hIMC, dwFlags);
519 if (!IMM_GetThreadData()->defaultContext)
520 IMM_GetThreadData()->defaultContext = ImmCreateContext();
522 if (!hWnd) return FALSE;
524 switch (dwFlags)
526 case 0:
527 ImmAssociateContext(hWnd,hIMC);
528 return TRUE;
529 case IACE_DEFAULT:
530 ImmAssociateContext(hWnd,IMM_GetThreadData()->defaultContext);
531 return TRUE;
532 case IACE_IGNORENOCONTEXT:
533 if (GetPropW(hWnd,szwWineIMCProperty))
534 ImmAssociateContext(hWnd,hIMC);
535 return TRUE;
536 case IACE_CHILDREN:
537 EnumChildWindows(hWnd,_ImmAssociateContextExEnumProc,(LPARAM)hIMC);
538 return TRUE;
539 default:
540 FIXME("Unknown dwFlags 0x%x\n",dwFlags);
541 return FALSE;
545 /***********************************************************************
546 * ImmConfigureIMEA (IMM32.@)
548 BOOL WINAPI ImmConfigureIMEA(
549 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
551 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
553 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
555 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
556 return FALSE;
558 if (immHkl->hIME && immHkl->pImeConfigure)
560 if (dwMode != IME_CONFIG_REGISTERWORD || !is_kbd_ime_unicode(immHkl))
561 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
562 else
564 REGISTERWORDW rww;
565 REGISTERWORDA *rwa = lpData;
566 BOOL rc;
568 rww.lpReading = strdupAtoW(rwa->lpReading);
569 rww.lpWord = strdupAtoW(rwa->lpWord);
570 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rww);
571 HeapFree(GetProcessHeap(),0,rww.lpReading);
572 HeapFree(GetProcessHeap(),0,rww.lpWord);
573 return rc;
576 else
577 return FALSE;
580 /***********************************************************************
581 * ImmConfigureIMEW (IMM32.@)
583 BOOL WINAPI ImmConfigureIMEW(
584 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
586 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
588 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
590 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
591 return FALSE;
593 if (immHkl->hIME && immHkl->pImeConfigure)
595 if (dwMode != IME_CONFIG_REGISTERWORD || is_kbd_ime_unicode(immHkl))
596 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
597 else
599 REGISTERWORDW *rww = lpData;
600 REGISTERWORDA rwa;
601 BOOL rc;
603 rwa.lpReading = strdupWtoA(rww->lpReading);
604 rwa.lpWord = strdupWtoA(rww->lpWord);
605 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rwa);
606 HeapFree(GetProcessHeap(),0,rwa.lpReading);
607 HeapFree(GetProcessHeap(),0,rwa.lpWord);
608 return rc;
611 else
612 return FALSE;
615 /***********************************************************************
616 * ImmCreateContext (IMM32.@)
618 HIMC WINAPI ImmCreateContext(void)
620 InputContextData *new_context;
621 LPGUIDELINE gl;
622 LPCANDIDATEINFO ci;
624 new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
626 /* Load the IME */
627 new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0));
629 if (!new_context->immKbd->hIME)
631 TRACE("IME dll could not be loaded\n");
632 HeapFree(GetProcessHeap(),0,new_context);
633 return 0;
636 /* the HIMCCs are never NULL */
637 new_context->IMC.hCompStr = ImmCreateBlankCompStr();
638 new_context->IMC.hMsgBuf = ImmCreateIMCC(0);
639 new_context->IMC.hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
640 ci = ImmLockIMCC(new_context->IMC.hCandInfo);
641 memset(ci,0,sizeof(CANDIDATEINFO));
642 ci->dwSize = sizeof(CANDIDATEINFO);
643 ImmUnlockIMCC(new_context->IMC.hCandInfo);
644 new_context->IMC.hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
645 gl = ImmLockIMCC(new_context->IMC.hGuideLine);
646 memset(gl,0,sizeof(GUIDELINE));
647 gl->dwSize = sizeof(GUIDELINE);
648 ImmUnlockIMCC(new_context->IMC.hGuideLine);
650 /* Initialize the IME Private */
651 new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
653 if (!new_context->immKbd->pImeSelect(new_context, TRUE))
655 TRACE("Selection of IME failed\n");
656 IMM_DestroyContext(new_context);
657 return 0;
659 SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)GetKeyboardLayout(0));
661 new_context->immKbd->uSelected++;
662 TRACE("Created context %p\n",new_context);
664 return new_context;
667 static BOOL IMM_DestroyContext(HIMC hIMC)
669 InputContextData *data = hIMC;
671 TRACE("Destroying %p\n",hIMC);
673 if (hIMC)
675 data->immKbd->uSelected --;
676 data->immKbd->pImeSelect(hIMC, FALSE);
677 SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)GetKeyboardLayout(0));
679 ImmDestroyIMCC(data->IMC.hCompStr);
680 ImmDestroyIMCC(data->IMC.hCandInfo);
681 ImmDestroyIMCC(data->IMC.hGuideLine);
682 ImmDestroyIMCC(data->IMC.hPrivate);
683 ImmDestroyIMCC(data->IMC.hMsgBuf);
685 HeapFree(GetProcessHeap(),0,data);
687 return TRUE;
690 /***********************************************************************
691 * ImmDestroyContext (IMM32.@)
693 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
695 if (hIMC != IMM_GetThreadData()->defaultContext)
696 return IMM_DestroyContext(hIMC);
697 else
698 return FALSE;
701 /***********************************************************************
702 * ImmDisableIME (IMM32.@)
704 BOOL WINAPI ImmDisableIME(DWORD idThread)
706 FIXME("(%d): stub\n", idThread);
707 return TRUE;
710 /***********************************************************************
711 * ImmEnumRegisterWordA (IMM32.@)
713 UINT WINAPI ImmEnumRegisterWordA(
714 HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
715 LPCSTR lpszReading, DWORD dwStyle,
716 LPCSTR lpszRegister, LPVOID lpData)
718 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
719 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
720 debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister), lpData);
721 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
723 if (!is_kbd_ime_unicode(immHkl))
724 return immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
725 (LPCWSTR)lpszReading, dwStyle, (LPCWSTR)lpszRegister, lpData);
726 else
728 LPWSTR lpszwReading = strdupAtoW(lpszReading);
729 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
730 BOOL rc;
732 rc = immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
733 lpszwReading, dwStyle, lpszwRegister,
734 lpData);
736 HeapFree(GetProcessHeap(),0,lpszwReading);
737 HeapFree(GetProcessHeap(),0,lpszwRegister);
738 return rc;
741 else
742 return 0;
745 /***********************************************************************
746 * ImmEnumRegisterWordW (IMM32.@)
748 UINT WINAPI ImmEnumRegisterWordW(
749 HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
750 LPCWSTR lpszReading, DWORD dwStyle,
751 LPCWSTR lpszRegister, LPVOID lpData)
753 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
754 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
755 debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister), lpData);
756 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
758 if (is_kbd_ime_unicode(immHkl))
759 return immHkl->pImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
760 lpszRegister, lpData);
761 else
763 LPSTR lpszaReading = strdupWtoA(lpszReading);
764 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
765 BOOL rc;
767 rc = immHkl->pImeEnumRegisterWord(lpfnEnumProc, (LPCWSTR)lpszaReading,
768 dwStyle, (LPCWSTR)lpszaRegister, lpData);
770 HeapFree(GetProcessHeap(),0,lpszaReading);
771 HeapFree(GetProcessHeap(),0,lpszaRegister);
772 return rc;
775 else
776 return 0;
779 static inline BOOL EscapeRequiresWA(UINT uEscape)
781 if (uEscape == IME_ESC_GET_EUDC_DICTIONARY ||
782 uEscape == IME_ESC_SET_EUDC_DICTIONARY ||
783 uEscape == IME_ESC_IME_NAME ||
784 uEscape == IME_ESC_GETHELPFILENAME)
785 return TRUE;
786 return FALSE;
789 /***********************************************************************
790 * ImmEscapeA (IMM32.@)
792 LRESULT WINAPI ImmEscapeA(
793 HKL hKL, HIMC hIMC,
794 UINT uEscape, LPVOID lpData)
796 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
797 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
799 if (immHkl->hIME && immHkl->pImeEscape)
801 if (!EscapeRequiresWA(uEscape) || !is_kbd_ime_unicode(immHkl))
802 return immHkl->pImeEscape(hIMC,uEscape,lpData);
803 else
805 WCHAR buffer[81]; /* largest required buffer should be 80 */
806 LRESULT rc;
807 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
809 MultiByteToWideChar(CP_ACP,0,lpData,-1,buffer,81);
810 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
812 else
814 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
815 WideCharToMultiByte(CP_ACP,0,buffer,-1,lpData,80, NULL, NULL);
817 return rc;
820 else
821 return 0;
824 /***********************************************************************
825 * ImmEscapeW (IMM32.@)
827 LRESULT WINAPI ImmEscapeW(
828 HKL hKL, HIMC hIMC,
829 UINT uEscape, LPVOID lpData)
831 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
832 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
834 if (immHkl->hIME && immHkl->pImeEscape)
836 if (!EscapeRequiresWA(uEscape) || is_kbd_ime_unicode(immHkl))
837 return immHkl->pImeEscape(hIMC,uEscape,lpData);
838 else
840 CHAR buffer[81]; /* largest required buffer should be 80 */
841 LRESULT rc;
842 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
844 WideCharToMultiByte(CP_ACP,0,lpData,-1,buffer,81, NULL, NULL);
845 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
847 else
849 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
850 MultiByteToWideChar(CP_ACP,0,buffer,-1,lpData,80);
852 return rc;
855 else
856 return 0;
859 /***********************************************************************
860 * ImmGetCandidateListA (IMM32.@)
862 DWORD WINAPI ImmGetCandidateListA(
863 HIMC hIMC, DWORD dwIndex,
864 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
866 InputContextData *data = hIMC;
867 LPCANDIDATEINFO candinfo;
868 LPCANDIDATELIST candlist;
869 DWORD ret = 0;
871 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
873 if (!data || !data->IMC.hCandInfo)
874 return 0;
876 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
877 if ( dwIndex >= candinfo->dwCount ||
878 dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
879 goto done;
881 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
882 if ( !candlist->dwSize || !candlist->dwCount )
883 goto done;
885 if ( !is_himc_ime_unicode(data) )
887 ret = candlist->dwSize;
888 if ( lpCandList && dwBufLen >= ret )
889 memcpy(lpCandList, candlist, ret);
891 else
892 ret = convert_candidatelist_WtoA( candlist, lpCandList, dwBufLen);
894 done:
895 ImmUnlockIMCC(data->IMC.hCandInfo);
896 return ret;
899 /***********************************************************************
900 * ImmGetCandidateListCountA (IMM32.@)
902 DWORD WINAPI ImmGetCandidateListCountA(
903 HIMC hIMC, LPDWORD lpdwListCount)
905 InputContextData *data = hIMC;
906 LPCANDIDATEINFO candinfo;
907 DWORD ret, count;
909 TRACE("%p, %p\n", hIMC, lpdwListCount);
911 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
912 return 0;
914 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
916 *lpdwListCount = count = candinfo->dwCount;
918 if ( !is_himc_ime_unicode(data) )
919 ret = candinfo->dwSize;
920 else
922 ret = sizeof(CANDIDATEINFO);
923 while ( count-- )
924 ret += ImmGetCandidateListA(hIMC, count, NULL, 0);
927 ImmUnlockIMCC(data->IMC.hCandInfo);
928 return ret;
931 /***********************************************************************
932 * ImmGetCandidateListCountW (IMM32.@)
934 DWORD WINAPI ImmGetCandidateListCountW(
935 HIMC hIMC, LPDWORD lpdwListCount)
937 InputContextData *data = hIMC;
938 LPCANDIDATEINFO candinfo;
939 DWORD ret, count;
941 TRACE("%p, %p\n", hIMC, lpdwListCount);
943 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
944 return 0;
946 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
948 *lpdwListCount = count = candinfo->dwCount;
950 if ( is_himc_ime_unicode(data) )
951 ret = candinfo->dwSize;
952 else
954 ret = sizeof(CANDIDATEINFO);
955 while ( count-- )
956 ret += ImmGetCandidateListW(hIMC, count, NULL, 0);
959 ImmUnlockIMCC(data->IMC.hCandInfo);
960 return ret;
963 /***********************************************************************
964 * ImmGetCandidateListW (IMM32.@)
966 DWORD WINAPI ImmGetCandidateListW(
967 HIMC hIMC, DWORD dwIndex,
968 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
970 InputContextData *data = hIMC;
971 LPCANDIDATEINFO candinfo;
972 LPCANDIDATELIST candlist;
973 DWORD ret = 0;
975 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
977 if (!data || !data->IMC.hCandInfo)
978 return 0;
980 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
981 if ( dwIndex >= candinfo->dwCount ||
982 dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
983 goto done;
985 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
986 if ( !candlist->dwSize || !candlist->dwCount )
987 goto done;
989 if ( is_himc_ime_unicode(data) )
991 ret = candlist->dwSize;
992 if ( lpCandList && dwBufLen >= ret )
993 memcpy(lpCandList, candlist, ret);
995 else
996 ret = convert_candidatelist_AtoW( candlist, lpCandList, dwBufLen);
998 done:
999 ImmUnlockIMCC(data->IMC.hCandInfo);
1000 return ret;
1003 /***********************************************************************
1004 * ImmGetCandidateWindow (IMM32.@)
1006 BOOL WINAPI ImmGetCandidateWindow(
1007 HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
1009 InputContextData *data = hIMC;
1011 TRACE("%p, %d, %p\n", hIMC, dwIndex, lpCandidate);
1013 if (!data || !lpCandidate)
1014 return FALSE;
1016 if ( dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
1017 return FALSE;
1019 *lpCandidate = data->IMC.cfCandForm[dwIndex];
1021 return TRUE;
1024 /***********************************************************************
1025 * ImmGetCompositionFontA (IMM32.@)
1027 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1029 LOGFONTW lfW;
1030 BOOL rc;
1032 TRACE("(%p, %p):\n", hIMC, lplf);
1034 rc = ImmGetCompositionFontW(hIMC,&lfW);
1035 if (!rc || !lplf)
1036 return FALSE;
1038 memcpy(lplf,&lfW,sizeof(LOGFONTA));
1039 WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName,
1040 LF_FACESIZE, NULL, NULL);
1041 return TRUE;
1044 /***********************************************************************
1045 * ImmGetCompositionFontW (IMM32.@)
1047 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1049 InputContextData *data = hIMC;
1051 TRACE("(%p, %p):\n", hIMC, lplf);
1053 if (!data || !lplf)
1054 return FALSE;
1056 *lplf = data->IMC.lfFont.W;
1058 return TRUE;
1062 /* Helpers for the GetCompositionString functions */
1064 static INT CopyCompStringIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE target, INT tlen,
1065 BOOL unicode )
1067 INT rc;
1069 if (is_himc_ime_unicode(data) && !unicode)
1070 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)source, slen, (LPSTR)target, tlen, NULL, NULL);
1071 else if (!is_himc_ime_unicode(data) && unicode)
1072 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)source, slen, (LPWSTR)target, tlen) * sizeof(WCHAR);
1073 else
1075 int dlen = (unicode)?sizeof(WCHAR):sizeof(CHAR);
1076 memcpy( target, source, min(slen,tlen)*dlen);
1077 rc = slen*dlen;
1080 return rc;
1083 static INT CopyCompAttrIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen,
1084 LPBYTE target, INT tlen, BOOL unicode )
1086 INT rc;
1088 if (is_himc_ime_unicode(data) && !unicode)
1090 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, sslen, NULL, 0, NULL, NULL);
1091 if (tlen)
1093 const BYTE *src = source;
1094 LPBYTE dst = target;
1095 int i, j = 0, k = 0;
1097 if (rc < tlen)
1098 tlen = rc;
1099 for (i = 0; i < sslen; ++i)
1101 int len;
1103 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)ssource + i, 1,
1104 NULL, 0, NULL, NULL);
1105 for (; len > 0; --len)
1107 dst[j++] = src[k];
1109 if (j >= tlen)
1110 goto end;
1112 ++k;
1114 end:
1115 rc = j;
1118 else if (!is_himc_ime_unicode(data) && unicode)
1120 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, sslen, NULL, 0);
1121 if (tlen)
1123 const BYTE *src = source;
1124 LPBYTE dst = target;
1125 int i, j = 0;
1127 if (rc < tlen)
1128 tlen = rc;
1129 for (i = 0; i < sslen; ++i)
1131 if (IsDBCSLeadByte(((LPSTR)ssource)[i]))
1132 continue;
1134 dst[j++] = src[i];
1136 if (j >= tlen)
1137 break;
1139 rc = j;
1142 else
1144 memcpy( target, source, min(slen,tlen));
1145 rc = slen;
1148 return rc;
1151 static INT CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource,
1152 LPBYTE target, INT tlen, BOOL unicode )
1154 INT rc;
1156 if (is_himc_ime_unicode(data) && !unicode)
1158 if (tlen)
1160 int i;
1162 if (slen < tlen)
1163 tlen = slen;
1164 tlen /= sizeof (DWORD);
1165 for (i = 0; i < tlen; ++i)
1167 ((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource,
1168 ((DWORD *)source)[i],
1169 NULL, 0,
1170 NULL, NULL);
1172 rc = sizeof (DWORD) * i;
1174 else
1175 rc = slen;
1177 else if (!is_himc_ime_unicode(data) && unicode)
1179 if (tlen)
1181 int i;
1183 if (slen < tlen)
1184 tlen = slen;
1185 tlen /= sizeof (DWORD);
1186 for (i = 0; i < tlen; ++i)
1188 ((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource,
1189 ((DWORD *)source)[i],
1190 NULL, 0);
1192 rc = sizeof (DWORD) * i;
1194 else
1195 rc = slen;
1197 else
1199 memcpy( target, source, min(slen,tlen));
1200 rc = slen;
1203 return rc;
1206 static INT CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE ssource, BOOL unicode)
1208 int rc;
1210 if (is_himc_ime_unicode(data) && !unicode)
1212 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, NULL, NULL);
1214 else if (!is_himc_ime_unicode(data) && unicode)
1216 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0);
1218 else
1219 rc = offset;
1221 return rc;
1224 static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf,
1225 DWORD dwBufLen, BOOL unicode)
1227 LONG rc = 0;
1228 InputContextData *data = hIMC;
1229 LPCOMPOSITIONSTRING compstr;
1230 LPBYTE compdata;
1232 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
1234 if (!data)
1235 return FALSE;
1237 if (!data->IMC.hCompStr)
1238 return FALSE;
1240 compdata = ImmLockIMCC(data->IMC.hCompStr);
1241 compstr = (LPCOMPOSITIONSTRING)compdata;
1243 switch (dwIndex)
1245 case GCS_RESULTSTR:
1246 TRACE("GCS_RESULTSTR\n");
1247 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, lpBuf, dwBufLen, unicode);
1248 break;
1249 case GCS_COMPSTR:
1250 TRACE("GCS_COMPSTR\n");
1251 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, lpBuf, dwBufLen, unicode);
1252 break;
1253 case GCS_COMPATTR:
1254 TRACE("GCS_COMPATTR\n");
1255 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompAttrOffset, compstr->dwCompAttrLen,
1256 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1257 lpBuf, dwBufLen, unicode);
1258 break;
1259 case GCS_COMPCLAUSE:
1260 TRACE("GCS_COMPCLAUSE\n");
1261 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompClauseOffset,compstr->dwCompClauseLen,
1262 compdata + compstr->dwCompStrOffset,
1263 lpBuf, dwBufLen, unicode);
1264 break;
1265 case GCS_RESULTCLAUSE:
1266 TRACE("GCS_RESULTCLAUSE\n");
1267 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen,
1268 compdata + compstr->dwResultStrOffset,
1269 lpBuf, dwBufLen, unicode);
1270 break;
1271 case GCS_RESULTREADSTR:
1272 TRACE("GCS_RESULTREADSTR\n");
1273 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultReadStrOffset, compstr->dwResultReadStrLen, lpBuf, dwBufLen, unicode);
1274 break;
1275 case GCS_RESULTREADCLAUSE:
1276 TRACE("GCS_RESULTREADCLAUSE\n");
1277 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultReadClauseOffset,compstr->dwResultReadClauseLen,
1278 compdata + compstr->dwResultStrOffset,
1279 lpBuf, dwBufLen, unicode);
1280 break;
1281 case GCS_COMPREADSTR:
1282 TRACE("GCS_COMPREADSTR\n");
1283 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, lpBuf, dwBufLen, unicode);
1284 break;
1285 case GCS_COMPREADATTR:
1286 TRACE("GCS_COMPREADATTR\n");
1287 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompReadAttrOffset, compstr->dwCompReadAttrLen,
1288 compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen,
1289 lpBuf, dwBufLen, unicode);
1290 break;
1291 case GCS_COMPREADCLAUSE:
1292 TRACE("GCS_COMPREADCLAUSE\n");
1293 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompReadClauseOffset,compstr->dwCompReadClauseLen,
1294 compdata + compstr->dwCompStrOffset,
1295 lpBuf, dwBufLen, unicode);
1296 break;
1297 case GCS_CURSORPOS:
1298 TRACE("GCS_CURSORPOS\n");
1299 rc = CopyCompOffsetIMEtoClient(data, compstr->dwCursorPos, compdata + compstr->dwCompStrOffset, unicode);
1300 break;
1301 case GCS_DELTASTART:
1302 TRACE("GCS_DELTASTART\n");
1303 rc = CopyCompOffsetIMEtoClient(data, compstr->dwDeltaStart, compdata + compstr->dwCompStrOffset, unicode);
1304 break;
1305 default:
1306 FIXME("Unhandled index 0x%x\n",dwIndex);
1307 break;
1310 ImmUnlockIMCC(data->IMC.hCompStr);
1312 return rc;
1315 /***********************************************************************
1316 * ImmGetCompositionStringA (IMM32.@)
1318 LONG WINAPI ImmGetCompositionStringA(
1319 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
1321 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
1325 /***********************************************************************
1326 * ImmGetCompositionStringW (IMM32.@)
1328 LONG WINAPI ImmGetCompositionStringW(
1329 HIMC hIMC, DWORD dwIndex,
1330 LPVOID lpBuf, DWORD dwBufLen)
1332 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
1335 /***********************************************************************
1336 * ImmGetCompositionWindow (IMM32.@)
1338 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1340 InputContextData *data = hIMC;
1342 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1344 if (!data)
1345 return FALSE;
1347 *lpCompForm = data->IMC.cfCompForm;
1348 return 1;
1351 /***********************************************************************
1352 * ImmGetContext (IMM32.@)
1355 HIMC WINAPI ImmGetContext(HWND hWnd)
1357 HIMC rc;
1359 TRACE("%p\n", hWnd);
1361 if (!IsWindow(hWnd))
1363 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
1364 return NULL;
1366 if (!IMM_GetThreadData()->defaultContext)
1367 IMM_GetThreadData()->defaultContext = ImmCreateContext();
1369 rc = GetPropW(hWnd,szwWineIMCProperty);
1370 if (rc == (HIMC)-1)
1371 rc = NULL;
1372 else if (rc == NULL)
1373 rc = IMM_GetThreadData()->defaultContext;
1375 if (rc)
1377 InputContextData *data = rc;
1378 data->IMC.hWnd = hWnd;
1380 TRACE("returning %p\n", rc);
1382 return rc;
1385 /***********************************************************************
1386 * ImmGetConversionListA (IMM32.@)
1388 DWORD WINAPI ImmGetConversionListA(
1389 HKL hKL, HIMC hIMC,
1390 LPCSTR pSrc, LPCANDIDATELIST lpDst,
1391 DWORD dwBufLen, UINT uFlag)
1393 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1394 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_a(pSrc), lpDst,
1395 dwBufLen, uFlag);
1396 if (immHkl->hIME && immHkl->pImeConversionList)
1398 if (!is_kbd_ime_unicode(immHkl))
1399 return immHkl->pImeConversionList(hIMC,(LPCWSTR)pSrc,lpDst,dwBufLen,uFlag);
1400 else
1402 LPCANDIDATELIST lpwDst;
1403 DWORD ret = 0, len;
1404 LPWSTR pwSrc = strdupAtoW(pSrc);
1406 len = immHkl->pImeConversionList(hIMC, pwSrc, NULL, 0, uFlag);
1407 lpwDst = HeapAlloc(GetProcessHeap(), 0, len);
1408 if ( lpwDst )
1410 immHkl->pImeConversionList(hIMC, pwSrc, lpwDst, len, uFlag);
1411 ret = convert_candidatelist_WtoA( lpwDst, lpDst, dwBufLen);
1412 HeapFree(GetProcessHeap(), 0, lpwDst);
1414 HeapFree(GetProcessHeap(), 0, pwSrc);
1416 return ret;
1419 else
1420 return 0;
1423 /***********************************************************************
1424 * ImmGetConversionListW (IMM32.@)
1426 DWORD WINAPI ImmGetConversionListW(
1427 HKL hKL, HIMC hIMC,
1428 LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1429 DWORD dwBufLen, UINT uFlag)
1431 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1432 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_w(pSrc), lpDst,
1433 dwBufLen, uFlag);
1434 if (immHkl->hIME && immHkl->pImeConversionList)
1436 if (is_kbd_ime_unicode(immHkl))
1437 return immHkl->pImeConversionList(hIMC,pSrc,lpDst,dwBufLen,uFlag);
1438 else
1440 LPCANDIDATELIST lpaDst;
1441 DWORD ret = 0, len;
1442 LPSTR paSrc = strdupWtoA(pSrc);
1444 len = immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, NULL, 0, uFlag);
1445 lpaDst = HeapAlloc(GetProcessHeap(), 0, len);
1446 if ( lpaDst )
1448 immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, lpaDst, len, uFlag);
1449 ret = convert_candidatelist_AtoW( lpaDst, lpDst, dwBufLen);
1450 HeapFree(GetProcessHeap(), 0, lpaDst);
1452 HeapFree(GetProcessHeap(), 0, paSrc);
1454 return ret;
1457 else
1458 return 0;
1461 /***********************************************************************
1462 * ImmGetConversionStatus (IMM32.@)
1464 BOOL WINAPI ImmGetConversionStatus(
1465 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1467 InputContextData *data = hIMC;
1469 TRACE("%p %p %p\n", hIMC, lpfdwConversion, lpfdwSentence);
1471 if (!data)
1472 return FALSE;
1474 if (lpfdwConversion)
1475 *lpfdwConversion = data->IMC.fdwConversion;
1476 if (lpfdwSentence)
1477 *lpfdwSentence = data->IMC.fdwSentence;
1479 return TRUE;
1482 /***********************************************************************
1483 * ImmGetDefaultIMEWnd (IMM32.@)
1485 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1487 if (IMM_GetThreadData()->hwndDefault == NULL)
1488 IMM_GetThreadData()->hwndDefault = CreateWindowExW( WS_EX_TOOLWINDOW,
1489 szwIME, NULL, WS_POPUP, 0, 0, 1, 1, 0, 0, 0, 0);
1490 TRACE("Default is %p\n",IMM_GetThreadData()->hwndDefault);
1491 return IMM_GetThreadData()->hwndDefault;
1494 /***********************************************************************
1495 * ImmGetDescriptionA (IMM32.@)
1497 UINT WINAPI ImmGetDescriptionA(
1498 HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1500 WCHAR *buf;
1501 DWORD len;
1503 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1505 /* find out how many characters in the unicode buffer */
1506 len = ImmGetDescriptionW( hKL, NULL, 0 );
1508 /* allocate a buffer of that size */
1509 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1510 if( !buf )
1511 return 0;
1513 /* fetch the unicode buffer */
1514 len = ImmGetDescriptionW( hKL, buf, len + 1 );
1516 /* convert it back to ASCII */
1517 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1518 lpszDescription, uBufLen, NULL, NULL );
1520 HeapFree( GetProcessHeap(), 0, buf );
1522 return len;
1525 /***********************************************************************
1526 * ImmGetDescriptionW (IMM32.@)
1528 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1530 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1532 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1534 if (!uBufLen) return lstrlenW( name );
1535 lstrcpynW( lpszDescription, name, uBufLen );
1536 return lstrlenW( lpszDescription );
1539 /***********************************************************************
1540 * ImmGetGuideLineA (IMM32.@)
1542 DWORD WINAPI ImmGetGuideLineA(
1543 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1545 FIXME("(%p, %d, %s, %d): stub\n",
1546 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1548 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1549 return 0;
1552 /***********************************************************************
1553 * ImmGetGuideLineW (IMM32.@)
1555 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1557 FIXME("(%p, %d, %s, %d): stub\n",
1558 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1560 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1561 return 0;
1564 /***********************************************************************
1565 * ImmGetIMEFileNameA (IMM32.@)
1567 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1569 LPWSTR bufW = NULL;
1570 UINT wBufLen = uBufLen;
1571 UINT rc;
1573 if (uBufLen && lpszFileName)
1574 bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR));
1575 else /* We need this to get the number of byte required */
1577 bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR));
1578 wBufLen = MAX_PATH;
1581 rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen);
1583 if (rc > 0)
1585 if (uBufLen && lpszFileName)
1586 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName,
1587 uBufLen, NULL, NULL);
1588 else /* get the length */
1589 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL,
1590 NULL);
1593 HeapFree(GetProcessHeap(),0,bufW);
1594 return rc;
1597 /***********************************************************************
1598 * ImmGetIMEFileNameW (IMM32.@)
1600 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1602 HKEY hkey;
1603 DWORD length;
1604 DWORD rc;
1605 WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
1607 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hKL );
1608 rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey);
1609 if (rc != ERROR_SUCCESS)
1611 SetLastError(rc);
1612 return 0;
1615 length = 0;
1616 rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length);
1618 if (rc != ERROR_SUCCESS)
1620 RegCloseKey(hkey);
1621 SetLastError(rc);
1622 return 0;
1624 if (length > uBufLen * sizeof(WCHAR) || !lpszFileName)
1626 RegCloseKey(hkey);
1627 if (lpszFileName)
1629 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1630 return 0;
1632 else
1633 return length / sizeof(WCHAR);
1636 RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length);
1638 RegCloseKey(hkey);
1640 return length / sizeof(WCHAR);
1643 /***********************************************************************
1644 * ImmGetOpenStatus (IMM32.@)
1646 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1648 InputContextData *data = hIMC;
1649 static int i;
1651 if (!data)
1652 return FALSE;
1654 TRACE("(%p): semi-stub\n", hIMC);
1656 if (!i++)
1657 FIXME("(%p): semi-stub\n", hIMC);
1659 return data->IMC.fOpen;
1662 /***********************************************************************
1663 * ImmGetProperty (IMM32.@)
1665 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1667 DWORD rc = 0;
1668 ImmHkl *kbd;
1670 TRACE("(%p, %d)\n", hKL, fdwIndex);
1671 kbd = IMM_GetImmHkl(hKL);
1673 if (kbd && kbd->hIME)
1675 switch (fdwIndex)
1677 case IGP_PROPERTY: rc = kbd->imeInfo.fdwProperty; break;
1678 case IGP_CONVERSION: rc = kbd->imeInfo.fdwConversionCaps; break;
1679 case IGP_SENTENCE: rc = kbd->imeInfo.fdwSentenceCaps; break;
1680 case IGP_SETCOMPSTR: rc = kbd->imeInfo.fdwSCSCaps; break;
1681 case IGP_SELECT: rc = kbd->imeInfo.fdwSelectCaps; break;
1682 case IGP_GETIMEVERSION: rc = IMEVER_0400; break;
1683 case IGP_UI: rc = 0; break;
1684 default: rc = 0;
1687 return rc;
1690 /***********************************************************************
1691 * ImmGetRegisterWordStyleA (IMM32.@)
1693 UINT WINAPI ImmGetRegisterWordStyleA(
1694 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1696 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1697 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1698 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1700 if (!is_kbd_ime_unicode(immHkl))
1701 return immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)lpStyleBuf);
1702 else
1704 STYLEBUFW sbw;
1705 UINT rc;
1707 rc = immHkl->pImeGetRegisterWordStyle(nItem,&sbw);
1708 WideCharToMultiByte(CP_ACP, 0, sbw.szDescription, -1,
1709 lpStyleBuf->szDescription, 32, NULL, NULL);
1710 lpStyleBuf->dwStyle = sbw.dwStyle;
1711 return rc;
1714 else
1715 return 0;
1718 /***********************************************************************
1719 * ImmGetRegisterWordStyleW (IMM32.@)
1721 UINT WINAPI ImmGetRegisterWordStyleW(
1722 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1724 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1725 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1726 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1728 if (is_kbd_ime_unicode(immHkl))
1729 return immHkl->pImeGetRegisterWordStyle(nItem,lpStyleBuf);
1730 else
1732 STYLEBUFA sba;
1733 UINT rc;
1735 rc = immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)&sba);
1736 MultiByteToWideChar(CP_ACP, 0, sba.szDescription, -1,
1737 lpStyleBuf->szDescription, 32);
1738 lpStyleBuf->dwStyle = sba.dwStyle;
1739 return rc;
1742 else
1743 return 0;
1746 /***********************************************************************
1747 * ImmGetStatusWindowPos (IMM32.@)
1749 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1751 InputContextData *data = hIMC;
1753 TRACE("(%p, %p)\n", hIMC, lpptPos);
1755 if (!data || !lpptPos)
1756 return FALSE;
1758 *lpptPos = data->IMC.ptStatusWndPos;
1760 return TRUE;
1763 /***********************************************************************
1764 * ImmGetVirtualKey (IMM32.@)
1766 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1768 OSVERSIONINFOA version;
1769 InputContextData *data = ImmGetContext( hWnd );
1770 TRACE("%p\n", hWnd);
1772 if ( data )
1773 return data->lastVK;
1775 version.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
1776 GetVersionExA( &version );
1777 switch(version.dwPlatformId)
1779 case VER_PLATFORM_WIN32_WINDOWS:
1780 return VK_PROCESSKEY;
1781 case VER_PLATFORM_WIN32_NT:
1782 return 0;
1783 default:
1784 FIXME("%d not supported\n",version.dwPlatformId);
1785 return VK_PROCESSKEY;
1789 /***********************************************************************
1790 * ImmInstallIMEA (IMM32.@)
1792 HKL WINAPI ImmInstallIMEA(
1793 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1795 LPWSTR lpszwIMEFileName;
1796 LPWSTR lpszwLayoutText;
1797 HKL hkl;
1799 TRACE ("(%s, %s)\n", debugstr_a(lpszIMEFileName),
1800 debugstr_a(lpszLayoutText));
1802 lpszwIMEFileName = strdupAtoW(lpszIMEFileName);
1803 lpszwLayoutText = strdupAtoW(lpszLayoutText);
1805 hkl = ImmInstallIMEW(lpszwIMEFileName, lpszwLayoutText);
1807 HeapFree(GetProcessHeap(),0,lpszwIMEFileName);
1808 HeapFree(GetProcessHeap(),0,lpszwLayoutText);
1809 return hkl;
1812 /***********************************************************************
1813 * ImmInstallIMEW (IMM32.@)
1815 HKL WINAPI ImmInstallIMEW(
1816 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1818 INT lcid = GetUserDefaultLCID();
1819 INT count;
1820 HKL hkl;
1821 DWORD rc;
1822 HKEY hkey;
1823 WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
1825 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName),
1826 debugstr_w(lpszLayoutText));
1828 /* Start with 2. e001 will be blank and so default to the wine internal IME */
1829 count = 2;
1831 while (count < 0xfff)
1833 DWORD disposition = 0;
1835 hkl = (HKL)MAKELPARAM( lcid, 0xe000 | count );
1836 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hkl);
1838 rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &disposition);
1839 if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
1840 break;
1841 else if (rc == ERROR_SUCCESS)
1842 RegCloseKey(hkey);
1844 count++;
1847 if (count == 0xfff)
1849 WARN("Unable to find slot to install IME\n");
1850 return 0;
1853 if (rc == ERROR_SUCCESS)
1855 rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (const BYTE*)lpszIMEFileName,
1856 (lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR));
1857 if (rc == ERROR_SUCCESS)
1858 rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (const BYTE*)lpszLayoutText,
1859 (lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR));
1860 RegCloseKey(hkey);
1861 return hkl;
1863 else
1865 WARN("Unable to set IME registry values\n");
1866 return 0;
1870 /***********************************************************************
1871 * ImmIsIME (IMM32.@)
1873 BOOL WINAPI ImmIsIME(HKL hKL)
1875 ImmHkl *ptr;
1876 TRACE("(%p):\n", hKL);
1877 ptr = IMM_GetImmHkl(hKL);
1878 return (ptr && ptr->hIME);
1881 /***********************************************************************
1882 * ImmIsUIMessageA (IMM32.@)
1884 BOOL WINAPI ImmIsUIMessageA(
1885 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1887 BOOL rc = FALSE;
1889 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1890 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1891 (msg == WM_IME_SETCONTEXT) ||
1892 (msg == WM_IME_NOTIFY) ||
1893 (msg == WM_IME_COMPOSITIONFULL) ||
1894 (msg == WM_IME_SELECT) ||
1895 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */) ||
1896 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1897 (msg == WM_MSIME_MOUSE) ||
1898 (msg == WM_MSIME_RECONVERTREQUEST) ||
1899 (msg == WM_MSIME_RECONVERT) ||
1900 (msg == WM_MSIME_QUERYPOSITION) ||
1901 (msg == WM_MSIME_DOCUMENTFEED))
1903 if (hWndIME)
1904 SendMessageA(hWndIME, msg, wParam, lParam);
1906 rc = TRUE;
1908 return rc;
1911 /***********************************************************************
1912 * ImmIsUIMessageW (IMM32.@)
1914 BOOL WINAPI ImmIsUIMessageW(
1915 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1917 BOOL rc = FALSE;
1919 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1920 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1921 (msg == WM_IME_SETCONTEXT) ||
1922 (msg == WM_IME_NOTIFY) ||
1923 (msg == WM_IME_COMPOSITIONFULL) ||
1924 (msg == WM_IME_SELECT) ||
1925 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */) ||
1926 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1927 (msg == WM_MSIME_MOUSE) ||
1928 (msg == WM_MSIME_RECONVERTREQUEST) ||
1929 (msg == WM_MSIME_RECONVERT) ||
1930 (msg == WM_MSIME_QUERYPOSITION) ||
1931 (msg == WM_MSIME_DOCUMENTFEED))
1933 if (hWndIME)
1934 SendMessageW(hWndIME, msg, wParam, lParam);
1936 rc = TRUE;
1938 return rc;
1941 /***********************************************************************
1942 * ImmNotifyIME (IMM32.@)
1944 BOOL WINAPI ImmNotifyIME(
1945 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
1947 InputContextData *data = hIMC;
1949 TRACE("(%p, %d, %d, %d)\n",
1950 hIMC, dwAction, dwIndex, dwValue);
1952 if (!data || ! data->immKbd->pNotifyIME)
1953 return FALSE;
1955 return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue);
1958 /***********************************************************************
1959 * ImmRegisterWordA (IMM32.@)
1961 BOOL WINAPI ImmRegisterWordA(
1962 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
1964 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1965 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
1966 debugstr_a(lpszRegister));
1967 if (immHkl->hIME && immHkl->pImeRegisterWord)
1969 if (!is_kbd_ime_unicode(immHkl))
1970 return immHkl->pImeRegisterWord((LPCWSTR)lpszReading,dwStyle,
1971 (LPCWSTR)lpszRegister);
1972 else
1974 LPWSTR lpszwReading = strdupAtoW(lpszReading);
1975 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
1976 BOOL rc;
1978 rc = immHkl->pImeRegisterWord(lpszwReading,dwStyle,lpszwRegister);
1979 HeapFree(GetProcessHeap(),0,lpszwReading);
1980 HeapFree(GetProcessHeap(),0,lpszwRegister);
1981 return rc;
1984 else
1985 return FALSE;
1988 /***********************************************************************
1989 * ImmRegisterWordW (IMM32.@)
1991 BOOL WINAPI ImmRegisterWordW(
1992 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
1994 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1995 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
1996 debugstr_w(lpszRegister));
1997 if (immHkl->hIME && immHkl->pImeRegisterWord)
1999 if (is_kbd_ime_unicode(immHkl))
2000 return immHkl->pImeRegisterWord(lpszReading,dwStyle,lpszRegister);
2001 else
2003 LPSTR lpszaReading = strdupWtoA(lpszReading);
2004 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
2005 BOOL rc;
2007 rc = immHkl->pImeRegisterWord((LPCWSTR)lpszaReading,dwStyle,
2008 (LPCWSTR)lpszaRegister);
2009 HeapFree(GetProcessHeap(),0,lpszaReading);
2010 HeapFree(GetProcessHeap(),0,lpszaRegister);
2011 return rc;
2014 else
2015 return FALSE;
2018 /***********************************************************************
2019 * ImmReleaseContext (IMM32.@)
2021 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
2023 static int shown = 0;
2025 if (!shown) {
2026 FIXME("(%p, %p): stub\n", hWnd, hIMC);
2027 shown = 1;
2029 return TRUE;
2032 /***********************************************************************
2033 * ImmRequestMessageA(IMM32.@)
2035 LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2037 InputContextData *data = hIMC;
2039 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2041 if (data && IsWindow(data->IMC.hWnd))
2042 return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2044 return 0;
2047 /***********************************************************************
2048 * ImmRequestMessageW(IMM32.@)
2050 LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2052 InputContextData *data = hIMC;
2054 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2056 if (data && IsWindow(data->IMC.hWnd))
2057 return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2059 return 0;
2062 /***********************************************************************
2063 * ImmSetCandidateWindow (IMM32.@)
2065 BOOL WINAPI ImmSetCandidateWindow(
2066 HIMC hIMC, LPCANDIDATEFORM lpCandidate)
2068 InputContextData *data = hIMC;
2070 TRACE("(%p, %p)\n", hIMC, lpCandidate);
2072 if (!data || !lpCandidate)
2073 return FALSE;
2075 TRACE("\t%x, %x, (%i,%i), (%i,%i - %i,%i)\n",
2076 lpCandidate->dwIndex, lpCandidate->dwStyle,
2077 lpCandidate->ptCurrentPos.x, lpCandidate->ptCurrentPos.y,
2078 lpCandidate->rcArea.top, lpCandidate->rcArea.left,
2079 lpCandidate->rcArea.bottom, lpCandidate->rcArea.right);
2081 if ( lpCandidate->dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
2082 return FALSE;
2084 data->IMC.cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
2085 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS);
2086 ImmInternalSendIMENotify(data, IMN_SETCANDIDATEPOS, 1 << lpCandidate->dwIndex);
2088 return TRUE;
2091 /***********************************************************************
2092 * ImmSetCompositionFontA (IMM32.@)
2094 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
2096 InputContextData *data = hIMC;
2097 TRACE("(%p, %p)\n", hIMC, lplf);
2099 if (!data || !lplf)
2100 return FALSE;
2102 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
2103 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
2104 LF_FACESIZE);
2105 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2106 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2108 return TRUE;
2111 /***********************************************************************
2112 * ImmSetCompositionFontW (IMM32.@)
2114 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
2116 InputContextData *data = hIMC;
2117 TRACE("(%p, %p)\n", hIMC, lplf);
2119 if (!data || !lplf)
2120 return FALSE;
2122 data->IMC.lfFont.W = *lplf;
2123 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2124 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2126 return TRUE;
2129 /***********************************************************************
2130 * ImmSetCompositionStringA (IMM32.@)
2132 BOOL WINAPI ImmSetCompositionStringA(
2133 HIMC hIMC, DWORD dwIndex,
2134 LPCVOID lpComp, DWORD dwCompLen,
2135 LPCVOID lpRead, DWORD dwReadLen)
2137 DWORD comp_len;
2138 DWORD read_len;
2139 WCHAR *CompBuffer = NULL;
2140 WCHAR *ReadBuffer = NULL;
2141 BOOL rc;
2142 InputContextData *data = hIMC;
2144 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2145 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2147 if (!data)
2148 return FALSE;
2150 if (!(dwIndex == SCS_SETSTR ||
2151 dwIndex == SCS_CHANGEATTR ||
2152 dwIndex == SCS_CHANGECLAUSE ||
2153 dwIndex == SCS_SETRECONVERTSTRING ||
2154 dwIndex == SCS_QUERYRECONVERTSTRING))
2155 return FALSE;
2157 if (!is_himc_ime_unicode(data))
2158 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2159 dwCompLen, lpRead, dwReadLen);
2161 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
2162 if (comp_len)
2164 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
2165 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
2168 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
2169 if (read_len)
2171 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
2172 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
2175 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
2176 ReadBuffer, read_len);
2178 HeapFree(GetProcessHeap(), 0, CompBuffer);
2179 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2181 return rc;
2184 /***********************************************************************
2185 * ImmSetCompositionStringW (IMM32.@)
2187 BOOL WINAPI ImmSetCompositionStringW(
2188 HIMC hIMC, DWORD dwIndex,
2189 LPCVOID lpComp, DWORD dwCompLen,
2190 LPCVOID lpRead, DWORD dwReadLen)
2192 DWORD comp_len;
2193 DWORD read_len;
2194 CHAR *CompBuffer = NULL;
2195 CHAR *ReadBuffer = NULL;
2196 BOOL rc;
2197 InputContextData *data = hIMC;
2199 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2200 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2202 if (!data)
2203 return FALSE;
2205 if (!(dwIndex == SCS_SETSTR ||
2206 dwIndex == SCS_CHANGEATTR ||
2207 dwIndex == SCS_CHANGECLAUSE ||
2208 dwIndex == SCS_SETRECONVERTSTRING ||
2209 dwIndex == SCS_QUERYRECONVERTSTRING))
2210 return FALSE;
2212 if (is_himc_ime_unicode(data))
2213 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2214 dwCompLen, lpRead, dwReadLen);
2216 comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL,
2217 NULL);
2218 if (comp_len)
2220 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len);
2221 WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len,
2222 NULL, NULL);
2225 read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL,
2226 NULL);
2227 if (read_len)
2229 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len);
2230 WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len,
2231 NULL, NULL);
2234 rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len,
2235 ReadBuffer, read_len);
2237 HeapFree(GetProcessHeap(), 0, CompBuffer);
2238 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2240 return rc;
2243 /***********************************************************************
2244 * ImmSetCompositionWindow (IMM32.@)
2246 BOOL WINAPI ImmSetCompositionWindow(
2247 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
2249 BOOL reshow = FALSE;
2250 InputContextData *data = hIMC;
2252 TRACE("(%p, %p)\n", hIMC, lpCompForm);
2253 TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
2254 lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
2255 lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
2257 if (!data)
2258 return FALSE;
2260 data->IMC.cfCompForm = *lpCompForm;
2262 if (IsWindowVisible(data->immKbd->UIWnd))
2264 reshow = TRUE;
2265 ShowWindow(data->immKbd->UIWnd,SW_HIDE);
2268 /* FIXME: this is a partial stub */
2270 if (reshow)
2271 ShowWindow(data->immKbd->UIWnd,SW_SHOWNOACTIVATE);
2273 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0);
2274 return TRUE;
2277 /***********************************************************************
2278 * ImmSetConversionStatus (IMM32.@)
2280 BOOL WINAPI ImmSetConversionStatus(
2281 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
2283 DWORD oldConversion, oldSentence;
2284 InputContextData *data = hIMC;
2286 TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence);
2288 if (!data)
2289 return FALSE;
2291 if ( fdwConversion != data->IMC.fdwConversion )
2293 oldConversion = data->IMC.fdwConversion;
2294 data->IMC.fdwConversion = fdwConversion;
2295 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldConversion, IMC_SETCONVERSIONMODE);
2296 ImmInternalSendIMENotify(data, IMN_SETCONVERSIONMODE, 0);
2298 if ( fdwSentence != data->IMC.fdwSentence )
2300 oldSentence = data->IMC.fdwSentence;
2301 data->IMC.fdwSentence = fdwSentence;
2302 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldSentence, IMC_SETSENTENCEMODE);
2303 ImmInternalSendIMENotify(data, IMN_SETSENTENCEMODE, 0);
2306 return TRUE;
2309 /***********************************************************************
2310 * ImmSetOpenStatus (IMM32.@)
2312 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
2314 InputContextData *data = hIMC;
2316 TRACE("%p %d\n", hIMC, fOpen);
2318 if (!data)
2319 return FALSE;
2321 if (data->immKbd->UIWnd == NULL)
2323 /* create the ime window */
2324 data->immKbd->UIWnd = CreateWindowExW( WS_EX_TOOLWINDOW,
2325 data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0,
2326 0, data->immKbd->hIME, 0);
2327 SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
2329 else if (fOpen)
2330 SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
2332 if (!fOpen != !data->IMC.fOpen)
2334 data->IMC.fOpen = fOpen;
2335 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS);
2336 ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0);
2339 return TRUE;
2342 /***********************************************************************
2343 * ImmSetStatusWindowPos (IMM32.@)
2345 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
2347 InputContextData *data = hIMC;
2349 TRACE("(%p, %p)\n", hIMC, lpptPos);
2351 if (!data || !lpptPos)
2352 return FALSE;
2354 TRACE("\t(%i,%i)\n", lpptPos->x, lpptPos->y);
2356 data->IMC.ptStatusWndPos = *lpptPos;
2357 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETSTATUSWINDOWPOS);
2358 ImmInternalSendIMENotify(data, IMN_SETSTATUSWINDOWPOS, 0);
2360 return TRUE;
2363 /***********************************************************************
2364 * ImmCreateSoftKeyboard(IMM32.@)
2366 HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y)
2368 FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y);
2369 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2370 return 0;
2373 /***********************************************************************
2374 * ImmDestroySoftKeyboard(IMM32.@)
2376 BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd)
2378 FIXME("(%p): stub\n", hSoftWnd);
2379 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2380 return FALSE;
2383 /***********************************************************************
2384 * ImmShowSoftKeyboard(IMM32.@)
2386 BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow)
2388 FIXME("(%p, %d): stub\n", hSoftWnd, nCmdShow);
2389 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2390 return FALSE;
2393 /***********************************************************************
2394 * ImmSimulateHotKey (IMM32.@)
2396 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
2398 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
2399 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2400 return FALSE;
2403 /***********************************************************************
2404 * ImmUnregisterWordA (IMM32.@)
2406 BOOL WINAPI ImmUnregisterWordA(
2407 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
2409 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2410 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2411 debugstr_a(lpszUnregister));
2412 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2414 if (!is_kbd_ime_unicode(immHkl))
2415 return immHkl->pImeUnregisterWord((LPCWSTR)lpszReading,dwStyle,
2416 (LPCWSTR)lpszUnregister);
2417 else
2419 LPWSTR lpszwReading = strdupAtoW(lpszReading);
2420 LPWSTR lpszwUnregister = strdupAtoW(lpszUnregister);
2421 BOOL rc;
2423 rc = immHkl->pImeUnregisterWord(lpszwReading,dwStyle,lpszwUnregister);
2424 HeapFree(GetProcessHeap(),0,lpszwReading);
2425 HeapFree(GetProcessHeap(),0,lpszwUnregister);
2426 return rc;
2429 else
2430 return FALSE;
2433 /***********************************************************************
2434 * ImmUnregisterWordW (IMM32.@)
2436 BOOL WINAPI ImmUnregisterWordW(
2437 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
2439 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2440 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2441 debugstr_w(lpszUnregister));
2442 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2444 if (is_kbd_ime_unicode(immHkl))
2445 return immHkl->pImeUnregisterWord(lpszReading,dwStyle,lpszUnregister);
2446 else
2448 LPSTR lpszaReading = strdupWtoA(lpszReading);
2449 LPSTR lpszaUnregister = strdupWtoA(lpszUnregister);
2450 BOOL rc;
2452 rc = immHkl->pImeUnregisterWord((LPCWSTR)lpszaReading,dwStyle,
2453 (LPCWSTR)lpszaUnregister);
2454 HeapFree(GetProcessHeap(),0,lpszaReading);
2455 HeapFree(GetProcessHeap(),0,lpszaUnregister);
2456 return rc;
2459 else
2460 return FALSE;
2463 /***********************************************************************
2464 * ImmGetImeMenuItemsA (IMM32.@)
2466 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2467 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
2468 DWORD dwSize)
2470 InputContextData *data = hIMC;
2471 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2472 lpImeParentMenu, lpImeMenu, dwSize);
2473 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2475 if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2476 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2477 (IMEMENUITEMINFOW*)lpImeParentMenu,
2478 (IMEMENUITEMINFOW*)lpImeMenu, dwSize);
2479 else
2481 IMEMENUITEMINFOW lpImeParentMenuW;
2482 IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL;
2483 DWORD rc;
2485 if (lpImeParentMenu)
2486 parent = &lpImeParentMenuW;
2487 if (lpImeMenu)
2489 int count = dwSize / sizeof(LPIMEMENUITEMINFOA);
2490 dwSize = count * sizeof(IMEMENUITEMINFOW);
2491 lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize);
2493 else
2494 lpImeMenuW = NULL;
2496 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2497 parent, lpImeMenuW, dwSize);
2499 if (lpImeParentMenu)
2501 memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA));
2502 lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem;
2503 WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString,
2504 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE,
2505 NULL, NULL);
2507 if (lpImeMenu && rc)
2509 unsigned int i;
2510 for (i = 0; i < rc; i++)
2512 memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA));
2513 lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem;
2514 WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString,
2515 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE,
2516 NULL, NULL);
2519 HeapFree(GetProcessHeap(),0,lpImeMenuW);
2520 return rc;
2523 else
2524 return 0;
2527 /***********************************************************************
2528 * ImmGetImeMenuItemsW (IMM32.@)
2530 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2531 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
2532 DWORD dwSize)
2534 InputContextData *data = hIMC;
2535 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2536 lpImeParentMenu, lpImeMenu, dwSize);
2537 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2539 if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2540 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2541 lpImeParentMenu, lpImeMenu, dwSize);
2542 else
2544 IMEMENUITEMINFOA lpImeParentMenuA;
2545 IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL;
2546 DWORD rc;
2548 if (lpImeParentMenu)
2549 parent = &lpImeParentMenuA;
2550 if (lpImeMenu)
2552 int count = dwSize / sizeof(LPIMEMENUITEMINFOW);
2553 dwSize = count * sizeof(IMEMENUITEMINFOA);
2554 lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize);
2556 else
2557 lpImeMenuA = NULL;
2559 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2560 (IMEMENUITEMINFOW*)parent,
2561 (IMEMENUITEMINFOW*)lpImeMenuA, dwSize);
2563 if (lpImeParentMenu)
2565 memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA));
2566 lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem;
2567 MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString,
2568 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE);
2570 if (lpImeMenu && rc)
2572 unsigned int i;
2573 for (i = 0; i < rc; i++)
2575 memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA));
2576 lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem;
2577 MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString,
2578 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE);
2581 HeapFree(GetProcessHeap(),0,lpImeMenuA);
2582 return rc;
2585 else
2586 return 0;
2589 /***********************************************************************
2590 * ImmLockIMC(IMM32.@)
2592 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
2594 InputContextData *data = hIMC;
2596 if (!data)
2597 return NULL;
2598 data->dwLock++;
2599 return &data->IMC;
2602 /***********************************************************************
2603 * ImmUnlockIMC(IMM32.@)
2605 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
2607 InputContextData *data = hIMC;
2608 data->dwLock--;
2609 return (data->dwLock!=0);
2612 /***********************************************************************
2613 * ImmGetIMCLockCount(IMM32.@)
2615 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
2617 InputContextData *data = hIMC;
2618 return data->dwLock;
2621 /***********************************************************************
2622 * ImmCreateIMCC(IMM32.@)
2624 HIMCC WINAPI ImmCreateIMCC(DWORD size)
2626 IMCCInternal *internal;
2627 int real_size = size + sizeof(IMCCInternal);
2629 internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size);
2630 if (internal == NULL)
2631 return NULL;
2633 internal->dwSize = size;
2634 return internal;
2637 /***********************************************************************
2638 * ImmDestroyIMCC(IMM32.@)
2640 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
2642 HeapFree(GetProcessHeap(),0,block);
2643 return NULL;
2646 /***********************************************************************
2647 * ImmLockIMCC(IMM32.@)
2649 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
2651 IMCCInternal *internal;
2652 internal = imcc;
2654 internal->dwLock ++;
2655 return internal + 1;
2658 /***********************************************************************
2659 * ImmUnlockIMCC(IMM32.@)
2661 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
2663 IMCCInternal *internal;
2664 internal = imcc;
2666 internal->dwLock --;
2667 return (internal->dwLock!=0);
2670 /***********************************************************************
2671 * ImmGetIMCCLockCount(IMM32.@)
2673 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
2675 IMCCInternal *internal;
2676 internal = imcc;
2678 return internal->dwLock;
2681 /***********************************************************************
2682 * ImmReSizeIMCC(IMM32.@)
2684 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
2686 IMCCInternal *internal,*newone;
2687 int real_size = size + sizeof(IMCCInternal);
2689 internal = imcc;
2691 newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size);
2692 newone->dwSize = size;
2694 return newone;
2697 /***********************************************************************
2698 * ImmGetIMCCSize(IMM32.@)
2700 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2702 IMCCInternal *internal;
2703 internal = imcc;
2705 return internal->dwSize;
2708 /***********************************************************************
2709 * ImmGenerateMessage(IMM32.@)
2711 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2713 InputContextData *data = hIMC;
2715 TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
2716 if (data->IMC.dwNumMsgBuf > 0)
2718 LPTRANSMSG lpTransMsg;
2719 DWORD i;
2721 lpTransMsg = ImmLockIMCC(data->IMC.hMsgBuf);
2722 for (i = 0; i < data->IMC.dwNumMsgBuf; i++)
2723 ImmInternalPostIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
2725 ImmUnlockIMCC(data->IMC.hMsgBuf);
2727 data->IMC.dwNumMsgBuf = 0;
2730 return TRUE;
2733 /***********************************************************************
2734 * ImmTranslateMessage(IMM32.@)
2735 * ( Undocumented, call internally and from user32.dll )
2737 BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData)
2739 InputContextData *data;
2740 HIMC imc = ImmGetContext(hwnd);
2741 BYTE state[256];
2742 UINT scancode;
2743 LPVOID list = 0;
2744 UINT msg_count;
2745 UINT uVirtKey;
2746 static const DWORD list_count = 10;
2748 TRACE("%p %x %x %x\n",hwnd, msg, (UINT)wParam, (UINT)lKeyData);
2750 if (imc)
2751 data = imc;
2752 else
2753 return FALSE;
2755 if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx)
2756 return FALSE;
2758 GetKeyboardState(state);
2759 scancode = lKeyData >> 0x10 & 0xff;
2761 list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list_count * sizeof(TRANSMSG) + sizeof(DWORD));
2762 ((DWORD*)list)[0] = list_count;
2764 if (data->immKbd->imeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST)
2766 WCHAR chr;
2768 if (!is_himc_ime_unicode(data))
2769 ToAscii(data->lastVK, scancode, state, &chr, 0);
2770 else
2771 ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0, GetKeyboardLayout(0));
2772 uVirtKey = MAKELONG(data->lastVK,chr);
2774 else
2775 uVirtKey = data->lastVK;
2777 msg_count = data->immKbd->pImeToAsciiEx(uVirtKey, scancode, state, list, 0, imc);
2778 TRACE("%i messages generated\n",msg_count);
2779 if (msg_count && msg_count <= list_count)
2781 UINT i;
2782 LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD));
2784 for (i = 0; i < msg_count; i++)
2785 ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam);
2787 else if (msg_count > list_count)
2788 ImmGenerateMessage(imc);
2790 HeapFree(GetProcessHeap(),0,list);
2792 data->lastVK = VK_PROCESSKEY;
2794 return (msg_count > 0);
2797 /***********************************************************************
2798 * ImmProcessKey(IMM32.@)
2799 * ( Undocumented, called from user32.dll )
2801 BOOL WINAPI ImmProcessKey(HWND hwnd, HKL hKL, UINT vKey, LPARAM lKeyData, DWORD unknown)
2803 InputContextData *data;
2804 HIMC imc = ImmGetContext(hwnd);
2805 BYTE state[256];
2807 TRACE("%p %p %x %x %x\n",hwnd, hKL, vKey, (UINT)lKeyData, unknown);
2809 if (imc)
2810 data = imc;
2811 else
2812 return FALSE;
2814 if (!data->immKbd->hIME || !data->immKbd->pImeProcessKey)
2815 return FALSE;
2817 GetKeyboardState(state);
2818 if (data->immKbd->pImeProcessKey(imc, vKey, lKeyData, state))
2820 data->lastVK = vKey;
2821 return TRUE;
2824 data->lastVK = VK_PROCESSKEY;
2825 return FALSE;
2828 /***********************************************************************
2829 * ImmDisableTextFrameService(IMM32.@)
2831 BOOL WINAPI ImmDisableTextFrameService(DWORD idThread)
2833 FIXME("Stub\n");
2834 return FALSE;
2837 /***********************************************************************
2838 * ImmEnumInputContext(IMM32.@)
2841 BOOL WINAPI ImmEnumInputContext(DWORD idThread, IMCENUMPROC lpfn, LPARAM lParam)
2843 FIXME("Stub\n");
2844 return FALSE;
2847 /***********************************************************************
2848 * ImmGetHotKey(IMM32.@)
2851 BOOL WINAPI ImmGetHotKey(DWORD hotkey, UINT *modifiers, UINT *key, HKL hkl)
2853 FIXME("%x, %p, %p, %p: stub\n", hotkey, modifiers, key, hkl);
2854 return FALSE;
2859 * Window Proc for the Default IME window class
2861 static LRESULT WINAPI DefIME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
2862 LPARAM lParam)
2864 switch (uMsg)
2866 case WM_CREATE:
2867 case WM_NCCREATE:
2868 return TRUE;
2869 case WM_IME_STARTCOMPOSITION:
2870 case WM_IME_ENDCOMPOSITION:
2871 case WM_IME_COMPOSITION:
2872 case WM_IME_SETCONTEXT:
2873 case WM_IME_NOTIFY:
2874 case WM_IME_CONTROL:
2875 case WM_IME_COMPOSITIONFULL:
2876 case WM_IME_SELECT:
2877 case WM_IME_CHAR:
2878 case WM_IME_REQUEST:
2879 case WM_IME_KEYDOWN:
2880 case WM_IME_KEYUP:
2882 ImmHkl *immHkl = IMM_GetImmHkl(GetKeyboardLayout(0));
2883 if (immHkl->UIWnd)
2884 return SendMessageW(immHkl->UIWnd,uMsg,wParam,lParam);
2885 else
2886 return FALSE;
2888 default:
2889 if ((uMsg == WM_MSIME_RECONVERTOPTIONS) ||
2890 (uMsg == WM_MSIME_SERVICE) ||
2891 (uMsg == WM_MSIME_MOUSE) ||
2892 (uMsg == WM_MSIME_RECONVERTREQUEST) ||
2893 (uMsg == WM_MSIME_RECONVERT) ||
2894 (uMsg == WM_MSIME_QUERYPOSITION) ||
2895 (uMsg == WM_MSIME_DOCUMENTFEED))
2897 ImmHkl *immHkl = IMM_GetImmHkl(GetKeyboardLayout(0));
2898 if (immHkl->UIWnd)
2899 return SendMessageW(immHkl->UIWnd,uMsg,wParam,lParam);
2900 else
2901 return FALSE;
2903 return DefWindowProcW(hwnd, uMsg, wParam, lParam);