imm32: Have IMM class use DefWindowProc.
[wine.git] / dlls / imm32 / imm.c
blob015b8ab5ba0fd5a4253708e9ecb2ece3f5a88458
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/list.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(imm);
39 typedef struct tagIMCCInternal
41 DWORD dwLock;
42 DWORD dwSize;
43 } IMCCInternal;
45 #define MAKE_FUNCPTR(f) typeof(f) * p##f
46 typedef struct _tagImmHkl{
47 struct list entry;
48 HKL hkl;
49 HMODULE hIME;
50 IMEINFO imeInfo;
51 WCHAR imeClassName[17]; /* 16 character max */
52 ULONG uSelected;
53 HWND UIWnd;
55 /* Function Pointers */
56 MAKE_FUNCPTR(ImeInquire);
57 MAKE_FUNCPTR(ImeConfigure);
58 MAKE_FUNCPTR(ImeDestroy);
59 MAKE_FUNCPTR(ImeEscape);
60 MAKE_FUNCPTR(ImeSelect);
61 MAKE_FUNCPTR(ImeSetActiveContext);
62 MAKE_FUNCPTR(ImeToAsciiEx);
63 MAKE_FUNCPTR(NotifyIME);
64 MAKE_FUNCPTR(ImeRegisterWord);
65 MAKE_FUNCPTR(ImeUnregisterWord);
66 MAKE_FUNCPTR(ImeEnumRegisterWord);
67 MAKE_FUNCPTR(ImeSetCompositionString);
68 MAKE_FUNCPTR(ImeConversionList);
69 MAKE_FUNCPTR(ImeProcessKey);
70 MAKE_FUNCPTR(ImeGetRegisterWordStyle);
71 MAKE_FUNCPTR(ImeGetImeMenuItems);
72 } ImmHkl;
73 #undef MAKE_FUNCPTR
75 typedef struct tagInputContextData
77 DWORD dwLock;
78 INPUTCONTEXT IMC;
80 ImmHkl *immKbd;
81 UINT lastVK;
82 } InputContextData;
84 typedef struct _tagTRANSMSG {
85 UINT message;
86 WPARAM wParam;
87 LPARAM lParam;
88 } TRANSMSG, *LPTRANSMSG;
90 typedef struct _tagIMMThreadData {
91 HIMC defaultContext;
92 HWND hwndDefault;
93 } IMMThreadData;
95 static DWORD tlsIndex = 0;
96 static struct list ImmHklList = LIST_INIT(ImmHklList);
98 /* MSIME messages */
99 static UINT WM_MSIME_SERVICE;
100 static UINT WM_MSIME_RECONVERTOPTIONS;
101 static UINT WM_MSIME_MOUSE;
102 static UINT WM_MSIME_RECONVERTREQUEST;
103 static UINT WM_MSIME_RECONVERT;
104 static UINT WM_MSIME_QUERYPOSITION;
105 static UINT WM_MSIME_DOCUMENTFEED;
107 static const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
109 static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
110 static const WCHAR szLayoutTextW[] = {'L','a','y','o','u','t',' ','T','e','x','t',0};
111 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};
113 static LRESULT WINAPI DefIME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
114 LPARAM lParam);
116 #define is_himc_ime_unicode(p) (p->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE)
117 #define is_kbd_ime_unicode(p) (p->imeInfo.fdwProperty & IME_PROP_UNICODE)
119 static BOOL IMM_DestroyContext(HIMC hIMC);
121 static inline WCHAR *strdupAtoW( const char *str )
123 WCHAR *ret = NULL;
124 if (str)
126 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
127 if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
128 MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
130 return ret;
133 static inline CHAR *strdupWtoA( const WCHAR *str )
135 CHAR *ret = NULL;
136 if (str)
138 DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
139 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
140 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
142 return ret;
145 static DWORD convert_candidatelist_WtoA(
146 LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen)
148 DWORD ret, i, len;
150 ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] );
151 if ( lpDst && dwBufLen > 0 )
153 *lpDst = *lpSrc;
154 lpDst->dwOffset[0] = ret;
157 for ( i = 0; i < lpSrc->dwCount; i++)
159 LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
161 if ( lpDst && dwBufLen > 0 )
163 LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
165 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1,
166 (LPSTR)dest, dwBufLen, NULL, NULL);
168 if ( i + 1 < lpSrc->dwCount )
169 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(char);
170 dwBufLen -= len * sizeof(char);
172 else
173 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, NULL, 0, NULL, NULL);
175 ret += len * sizeof(char);
178 if ( lpDst )
179 lpDst->dwSize = ret;
181 return ret;
184 static DWORD convert_candidatelist_AtoW(
185 LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen)
187 DWORD ret, i, len;
189 ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] );
190 if ( lpDst && dwBufLen > 0 )
192 *lpDst = *lpSrc;
193 lpDst->dwOffset[0] = ret;
196 for ( i = 0; i < lpSrc->dwCount; i++)
198 LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
200 if ( lpDst && dwBufLen > 0 )
202 LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
204 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1,
205 (LPWSTR)dest, dwBufLen);
207 if ( i + 1 < lpSrc->dwCount )
208 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(WCHAR);
209 dwBufLen -= len * sizeof(WCHAR);
211 else
212 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, NULL, 0);
214 ret += len * sizeof(WCHAR);
217 if ( lpDst )
218 lpDst->dwSize = ret;
220 return ret;
223 static IMMThreadData* IMM_GetThreadData(void)
225 IMMThreadData* data = TlsGetValue(tlsIndex);
226 if (!data)
228 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
229 sizeof(IMMThreadData));
230 TlsSetValue(tlsIndex,data);
231 TRACE("Thread Data Created\n");
233 return data;
236 static void IMM_FreeThreadData(void)
238 IMMThreadData* data = TlsGetValue(tlsIndex);
239 if (data)
241 IMM_DestroyContext(data->defaultContext);
242 DestroyWindow(data->hwndDefault);
243 HeapFree(GetProcessHeap(),0,data);
244 TRACE("Thread Data Destroyed\n");
248 static HMODULE LoadDefaultWineIME(void)
250 char buffer[MAX_PATH], libname[32], *name, *next;
251 HMODULE module = 0;
252 HKEY hkey;
254 TRACE("Attempting to fall back to wine default IME\n");
256 strcpy( buffer, "x11" ); /* default value */
257 /* @@ Wine registry key: HKCU\Software\Wine\Drivers */
258 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hkey ))
260 DWORD type, count = sizeof(buffer);
261 RegQueryValueExA( hkey, "Ime", 0, &type, (LPBYTE) buffer, &count );
262 RegCloseKey( hkey );
265 name = buffer;
266 while (name)
268 next = strchr( name, ',' );
269 if (next) *next++ = 0;
271 snprintf( libname, sizeof(libname), "wine%s.drv", name );
272 if ((module = LoadLibraryA( libname )) != 0) break;
273 name = next;
276 return module;
279 /* ImmHkl loading and freeing */
280 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
281 static ImmHkl *IMM_GetImmHkl(HKL hkl)
283 ImmHkl *ptr;
284 WCHAR filename[MAX_PATH];
286 TRACE("Seeking ime for keyboard %p\n",hkl);
288 LIST_FOR_EACH_ENTRY(ptr, &ImmHklList, ImmHkl, entry)
290 if (ptr->hkl == hkl)
291 return ptr;
293 /* not found... create it */
295 ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ImmHkl));
297 ptr->hkl = hkl;
298 if (ImmGetIMEFileNameW(hkl, filename, MAX_PATH)) ptr->hIME = LoadLibraryW(filename);
299 if (!ptr->hIME)
300 ptr->hIME = LoadDefaultWineIME();
301 if (ptr->hIME)
303 LOAD_FUNCPTR(ImeInquire);
304 if (!ptr->pImeInquire || !ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL))
306 FreeLibrary(ptr->hIME);
307 ptr->hIME = NULL;
309 else
311 LOAD_FUNCPTR(ImeDestroy);
312 LOAD_FUNCPTR(ImeSelect);
313 if (!ptr->pImeSelect || !ptr->pImeDestroy)
315 FreeLibrary(ptr->hIME);
316 ptr->hIME = NULL;
318 else
320 LOAD_FUNCPTR(ImeConfigure);
321 LOAD_FUNCPTR(ImeEscape);
322 LOAD_FUNCPTR(ImeSetActiveContext);
323 LOAD_FUNCPTR(ImeToAsciiEx);
324 LOAD_FUNCPTR(NotifyIME);
325 LOAD_FUNCPTR(ImeRegisterWord);
326 LOAD_FUNCPTR(ImeUnregisterWord);
327 LOAD_FUNCPTR(ImeEnumRegisterWord);
328 LOAD_FUNCPTR(ImeSetCompositionString);
329 LOAD_FUNCPTR(ImeConversionList);
330 LOAD_FUNCPTR(ImeProcessKey);
331 LOAD_FUNCPTR(ImeGetRegisterWordStyle);
332 LOAD_FUNCPTR(ImeGetImeMenuItems);
333 /* make sure our classname is WCHAR */
334 if (!is_kbd_ime_unicode(ptr))
336 WCHAR bufW[17];
337 MultiByteToWideChar(CP_ACP, 0, (LPSTR)ptr->imeClassName,
338 -1, bufW, 17);
339 lstrcpyW(ptr->imeClassName, bufW);
344 list_add_head(&ImmHklList,&ptr->entry);
346 return ptr;
348 #undef LOAD_FUNCPTR
350 static void IMM_FreeAllImmHkl(void)
352 ImmHkl *ptr,*cursor2;
354 LIST_FOR_EACH_ENTRY_SAFE(ptr, cursor2, &ImmHklList, ImmHkl, entry)
356 list_remove(&ptr->entry);
357 if (ptr->hIME)
359 ptr->pImeDestroy(1);
360 FreeLibrary(ptr->hIME);
362 if (ptr->UIWnd)
363 DestroyWindow(ptr->UIWnd);
364 HeapFree(GetProcessHeap(),0,ptr);
368 static void IMM_RegisterMessages(void)
370 WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");
371 WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions");
372 WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
373 WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
374 WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
375 WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
376 WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
379 static void IMM_RegisterIMEClass(HINSTANCE hInstDLL)
381 static const WCHAR szwIME[] = {'I','M','E',0};
382 WNDCLASSW wndClass;
384 ZeroMemory(&wndClass, sizeof(WNDCLASSW));
386 wndClass.style = CS_GLOBALCLASS;
387 wndClass.lpfnWndProc = (WNDPROC) DefIME_WindowProc;
388 wndClass.cbWndExtra = 2 * sizeof(LONG_PTR);
389 wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
390 wndClass.lpszClassName = szwIME;
392 RegisterClassW(&wndClass);
395 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
397 TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
398 switch (fdwReason)
400 case DLL_PROCESS_ATTACH:
401 IMM_RegisterMessages();
402 tlsIndex = TlsAlloc();
403 if (tlsIndex == TLS_OUT_OF_INDEXES)
404 return FALSE;
405 IMM_RegisterIMEClass(hInstDLL);
406 break;
407 case DLL_THREAD_ATTACH:
408 break;
409 case DLL_THREAD_DETACH:
410 IMM_FreeThreadData();
411 break;
412 case DLL_PROCESS_DETACH:
413 IMM_FreeThreadData();
414 IMM_FreeAllImmHkl();
415 TlsFree(tlsIndex);
416 break;
418 return TRUE;
421 /* for posting messages as the IME */
422 static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
424 HWND target = GetFocus();
425 if (!target)
426 PostMessageW(data->IMC.hWnd,msg,wParam,lParam);
427 else
428 PostMessageW(target, msg, wParam, lParam);
431 static LRESULT ImmInternalSendIMENotify(InputContextData *data, WPARAM notify, LPARAM lParam)
433 HWND target;
435 target = data->IMC.hWnd;
436 if (!target) target = GetFocus();
438 if (target)
439 return SendMessageW(target, WM_IME_NOTIFY, notify, lParam);
441 return 0;
444 static HIMCC ImmCreateBlankCompStr(void)
446 HIMCC rc;
447 LPCOMPOSITIONSTRING ptr;
448 rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
449 ptr = ImmLockIMCC(rc);
450 memset(ptr,0,sizeof(COMPOSITIONSTRING));
451 ptr->dwSize = sizeof(COMPOSITIONSTRING);
452 ImmUnlockIMCC(rc);
453 return rc;
456 /***********************************************************************
457 * ImmAssociateContext (IMM32.@)
459 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
461 HIMC old = NULL;
462 InputContextData *data = hIMC;
464 TRACE("(%p, %p):\n", hWnd, hIMC);
466 if (!IMM_GetThreadData()->defaultContext)
467 IMM_GetThreadData()->defaultContext = ImmCreateContext();
470 * If already associated just return
472 if (hIMC && data->IMC.hWnd == hWnd)
473 return hIMC;
475 if (hWnd)
477 old = RemovePropW(hWnd,szwWineIMCProperty);
479 if (old == NULL)
480 old = IMM_GetThreadData()->defaultContext;
481 else if (old == (HIMC)-1)
482 old = NULL;
484 if (hIMC != IMM_GetThreadData()->defaultContext)
486 if (hIMC == NULL) /* Meaning disable imm for that window*/
487 SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1);
488 else
489 SetPropW(hWnd,szwWineIMCProperty,hIMC);
492 if (old)
494 InputContextData *old_data = old;
495 if (old_data->IMC.hWnd == hWnd)
496 old_data->IMC.hWnd = NULL;
500 if (!hIMC)
501 return old;
503 if (IsWindow(data->IMC.hWnd))
506 * Post a message that your context is switching
508 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
511 data->IMC.hWnd = hWnd;
513 if (IsWindow(data->IMC.hWnd))
516 * Post a message that your context is switching
518 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
521 return old;
526 * Helper function for ImmAssociateContextEx
528 static BOOL CALLBACK _ImmAssociateContextExEnumProc(HWND hwnd, LPARAM lParam)
530 HIMC hImc = (HIMC)lParam;
531 ImmAssociateContext(hwnd,hImc);
532 return TRUE;
535 /***********************************************************************
536 * ImmAssociateContextEx (IMM32.@)
538 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
540 TRACE("(%p, %p, 0x%x):\n", hWnd, hIMC, dwFlags);
542 if (!IMM_GetThreadData()->defaultContext)
543 IMM_GetThreadData()->defaultContext = ImmCreateContext();
545 if (!hWnd) return FALSE;
547 switch (dwFlags)
549 case 0:
550 ImmAssociateContext(hWnd,hIMC);
551 return TRUE;
552 case IACE_DEFAULT:
553 ImmAssociateContext(hWnd,IMM_GetThreadData()->defaultContext);
554 return TRUE;
555 case IACE_IGNORENOCONTEXT:
556 if (GetPropW(hWnd,szwWineIMCProperty))
557 ImmAssociateContext(hWnd,hIMC);
558 return TRUE;
559 case IACE_CHILDREN:
560 EnumChildWindows(hWnd,_ImmAssociateContextExEnumProc,(LPARAM)hIMC);
561 return TRUE;
562 default:
563 FIXME("Unknown dwFlags 0x%x\n",dwFlags);
564 return FALSE;
568 /***********************************************************************
569 * ImmConfigureIMEA (IMM32.@)
571 BOOL WINAPI ImmConfigureIMEA(
572 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
574 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
576 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
578 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
579 return FALSE;
581 if (immHkl->hIME && immHkl->pImeConfigure)
583 if (dwMode != IME_CONFIG_REGISTERWORD || !is_kbd_ime_unicode(immHkl))
584 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
585 else
587 REGISTERWORDW rww;
588 REGISTERWORDA *rwa = lpData;
589 BOOL rc;
591 rww.lpReading = strdupAtoW(rwa->lpReading);
592 rww.lpWord = strdupAtoW(rwa->lpWord);
593 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rww);
594 HeapFree(GetProcessHeap(),0,rww.lpReading);
595 HeapFree(GetProcessHeap(),0,rww.lpWord);
596 return rc;
599 else
600 return FALSE;
603 /***********************************************************************
604 * ImmConfigureIMEW (IMM32.@)
606 BOOL WINAPI ImmConfigureIMEW(
607 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
609 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
611 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
613 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
614 return FALSE;
616 if (immHkl->hIME && immHkl->pImeConfigure)
618 if (dwMode != IME_CONFIG_REGISTERWORD || is_kbd_ime_unicode(immHkl))
619 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
620 else
622 REGISTERWORDW *rww = lpData;
623 REGISTERWORDA rwa;
624 BOOL rc;
626 rwa.lpReading = strdupWtoA(rww->lpReading);
627 rwa.lpWord = strdupWtoA(rww->lpWord);
628 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rwa);
629 HeapFree(GetProcessHeap(),0,rwa.lpReading);
630 HeapFree(GetProcessHeap(),0,rwa.lpWord);
631 return rc;
634 else
635 return FALSE;
638 /***********************************************************************
639 * ImmCreateContext (IMM32.@)
641 HIMC WINAPI ImmCreateContext(void)
643 InputContextData *new_context;
644 LPGUIDELINE gl;
645 LPCANDIDATEINFO ci;
647 new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
649 /* Load the IME */
650 new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0));
652 if (!new_context->immKbd->hIME)
654 TRACE("IME dll could not be loaded\n");
655 HeapFree(GetProcessHeap(),0,new_context);
656 return 0;
659 /* the HIMCCs are never NULL */
660 new_context->IMC.hCompStr = ImmCreateBlankCompStr();
661 new_context->IMC.hMsgBuf = ImmCreateIMCC(0);
662 new_context->IMC.hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
663 ci = ImmLockIMCC(new_context->IMC.hCandInfo);
664 memset(ci,0,sizeof(CANDIDATEINFO));
665 ci->dwSize = sizeof(CANDIDATEINFO);
666 ImmUnlockIMCC(new_context->IMC.hCandInfo);
667 new_context->IMC.hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
668 gl = ImmLockIMCC(new_context->IMC.hGuideLine);
669 memset(gl,0,sizeof(GUIDELINE));
670 gl->dwSize = sizeof(GUIDELINE);
671 ImmUnlockIMCC(new_context->IMC.hGuideLine);
673 /* Initialize the IME Private */
674 new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
676 if (!new_context->immKbd->pImeSelect(new_context, TRUE))
678 TRACE("Selection of IME failed\n");
679 IMM_DestroyContext(new_context);
680 return 0;
682 SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)GetKeyboardLayout(0));
684 new_context->immKbd->uSelected++;
685 TRACE("Created context %p\n",new_context);
687 return new_context;
690 static BOOL IMM_DestroyContext(HIMC hIMC)
692 InputContextData *data = hIMC;
694 TRACE("Destroying %p\n",hIMC);
696 if (hIMC)
698 data->immKbd->uSelected --;
699 data->immKbd->pImeSelect(hIMC, FALSE);
700 SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)GetKeyboardLayout(0));
702 ImmDestroyIMCC(data->IMC.hCompStr);
703 ImmDestroyIMCC(data->IMC.hCandInfo);
704 ImmDestroyIMCC(data->IMC.hGuideLine);
705 ImmDestroyIMCC(data->IMC.hPrivate);
706 ImmDestroyIMCC(data->IMC.hMsgBuf);
708 HeapFree(GetProcessHeap(),0,data);
710 return TRUE;
713 /***********************************************************************
714 * ImmDestroyContext (IMM32.@)
716 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
718 if (hIMC != IMM_GetThreadData()->defaultContext)
719 return IMM_DestroyContext(hIMC);
720 else
721 return FALSE;
724 /***********************************************************************
725 * ImmDisableIME (IMM32.@)
727 BOOL WINAPI ImmDisableIME(DWORD idThread)
729 FIXME("(%d): stub\n", idThread);
730 return TRUE;
733 /***********************************************************************
734 * ImmEnumRegisterWordA (IMM32.@)
736 UINT WINAPI ImmEnumRegisterWordA(
737 HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
738 LPCSTR lpszReading, DWORD dwStyle,
739 LPCSTR lpszRegister, LPVOID lpData)
741 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
742 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
743 debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister), lpData);
744 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
746 if (!is_kbd_ime_unicode(immHkl))
747 return immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
748 (LPCWSTR)lpszReading, dwStyle, (LPCWSTR)lpszRegister, lpData);
749 else
751 LPWSTR lpszwReading = strdupAtoW(lpszReading);
752 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
753 BOOL rc;
755 rc = immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
756 lpszwReading, dwStyle, lpszwRegister,
757 lpData);
759 HeapFree(GetProcessHeap(),0,lpszwReading);
760 HeapFree(GetProcessHeap(),0,lpszwRegister);
761 return rc;
764 else
765 return 0;
768 /***********************************************************************
769 * ImmEnumRegisterWordW (IMM32.@)
771 UINT WINAPI ImmEnumRegisterWordW(
772 HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
773 LPCWSTR lpszReading, DWORD dwStyle,
774 LPCWSTR lpszRegister, LPVOID lpData)
776 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
777 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
778 debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister), lpData);
779 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
781 if (is_kbd_ime_unicode(immHkl))
782 return immHkl->pImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
783 lpszRegister, lpData);
784 else
786 LPSTR lpszaReading = strdupWtoA(lpszReading);
787 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
788 BOOL rc;
790 rc = immHkl->pImeEnumRegisterWord(lpfnEnumProc, (LPCWSTR)lpszaReading,
791 dwStyle, (LPCWSTR)lpszaRegister, lpData);
793 HeapFree(GetProcessHeap(),0,lpszaReading);
794 HeapFree(GetProcessHeap(),0,lpszaRegister);
795 return rc;
798 else
799 return 0;
802 static inline BOOL EscapeRequiresWA(UINT uEscape)
804 if (uEscape == IME_ESC_GET_EUDC_DICTIONARY ||
805 uEscape == IME_ESC_SET_EUDC_DICTIONARY ||
806 uEscape == IME_ESC_IME_NAME ||
807 uEscape == IME_ESC_GETHELPFILENAME)
808 return TRUE;
809 return FALSE;
812 /***********************************************************************
813 * ImmEscapeA (IMM32.@)
815 LRESULT WINAPI ImmEscapeA(
816 HKL hKL, HIMC hIMC,
817 UINT uEscape, LPVOID lpData)
819 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
820 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
822 if (immHkl->hIME && immHkl->pImeEscape)
824 if (!EscapeRequiresWA(uEscape) || !is_kbd_ime_unicode(immHkl))
825 return immHkl->pImeEscape(hIMC,uEscape,lpData);
826 else
828 WCHAR buffer[81]; /* largest required buffer should be 80 */
829 LRESULT rc;
830 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
832 MultiByteToWideChar(CP_ACP,0,lpData,-1,buffer,81);
833 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
835 else
837 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
838 WideCharToMultiByte(CP_ACP,0,buffer,-1,lpData,80, NULL, NULL);
840 return rc;
843 else
844 return 0;
847 /***********************************************************************
848 * ImmEscapeW (IMM32.@)
850 LRESULT WINAPI ImmEscapeW(
851 HKL hKL, HIMC hIMC,
852 UINT uEscape, LPVOID lpData)
854 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
855 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
857 if (immHkl->hIME && immHkl->pImeEscape)
859 if (!EscapeRequiresWA(uEscape) || is_kbd_ime_unicode(immHkl))
860 return immHkl->pImeEscape(hIMC,uEscape,lpData);
861 else
863 CHAR buffer[81]; /* largest required buffer should be 80 */
864 LRESULT rc;
865 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
867 WideCharToMultiByte(CP_ACP,0,lpData,-1,buffer,81, NULL, NULL);
868 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
870 else
872 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
873 MultiByteToWideChar(CP_ACP,0,buffer,-1,lpData,80);
875 return rc;
878 else
879 return 0;
882 /***********************************************************************
883 * ImmGetCandidateListA (IMM32.@)
885 DWORD WINAPI ImmGetCandidateListA(
886 HIMC hIMC, DWORD dwIndex,
887 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
889 InputContextData *data = hIMC;
890 LPCANDIDATEINFO candinfo;
891 LPCANDIDATELIST candlist;
892 DWORD ret = 0;
894 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
896 if (!data || !data->IMC.hCandInfo)
897 return 0;
899 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
900 if ( dwIndex >= candinfo->dwCount ||
901 dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
902 goto done;
904 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
905 if ( !candlist->dwSize || !candlist->dwCount )
906 goto done;
908 if ( !is_himc_ime_unicode(data) )
910 ret = candlist->dwSize;
911 if ( lpCandList && dwBufLen >= ret )
912 memcpy(lpCandList, candlist, ret);
914 else
915 ret = convert_candidatelist_WtoA( candlist, lpCandList, dwBufLen);
917 done:
918 ImmUnlockIMCC(data->IMC.hCandInfo);
919 return ret;
922 /***********************************************************************
923 * ImmGetCandidateListCountA (IMM32.@)
925 DWORD WINAPI ImmGetCandidateListCountA(
926 HIMC hIMC, LPDWORD lpdwListCount)
928 InputContextData *data = hIMC;
929 LPCANDIDATEINFO candinfo;
930 DWORD ret, count;
932 TRACE("%p, %p\n", hIMC, lpdwListCount);
934 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
935 return 0;
937 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
939 *lpdwListCount = count = candinfo->dwCount;
941 if ( !is_himc_ime_unicode(data) )
942 ret = candinfo->dwSize;
943 else
945 ret = sizeof(CANDIDATEINFO);
946 while ( count-- )
947 ret += ImmGetCandidateListA(hIMC, count, NULL, 0);
950 ImmUnlockIMCC(data->IMC.hCandInfo);
951 return ret;
954 /***********************************************************************
955 * ImmGetCandidateListCountW (IMM32.@)
957 DWORD WINAPI ImmGetCandidateListCountW(
958 HIMC hIMC, LPDWORD lpdwListCount)
960 InputContextData *data = hIMC;
961 LPCANDIDATEINFO candinfo;
962 DWORD ret, count;
964 TRACE("%p, %p\n", hIMC, lpdwListCount);
966 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
967 return 0;
969 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
971 *lpdwListCount = count = candinfo->dwCount;
973 if ( is_himc_ime_unicode(data) )
974 ret = candinfo->dwSize;
975 else
977 ret = sizeof(CANDIDATEINFO);
978 while ( count-- )
979 ret += ImmGetCandidateListW(hIMC, count, NULL, 0);
982 ImmUnlockIMCC(data->IMC.hCandInfo);
983 return ret;
986 /***********************************************************************
987 * ImmGetCandidateListW (IMM32.@)
989 DWORD WINAPI ImmGetCandidateListW(
990 HIMC hIMC, DWORD dwIndex,
991 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
993 InputContextData *data = hIMC;
994 LPCANDIDATEINFO candinfo;
995 LPCANDIDATELIST candlist;
996 DWORD ret = 0;
998 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
1000 if (!data || !data->IMC.hCandInfo)
1001 return 0;
1003 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
1004 if ( dwIndex >= candinfo->dwCount ||
1005 dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
1006 goto done;
1008 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
1009 if ( !candlist->dwSize || !candlist->dwCount )
1010 goto done;
1012 if ( is_himc_ime_unicode(data) )
1014 ret = candlist->dwSize;
1015 if ( lpCandList && dwBufLen >= ret )
1016 memcpy(lpCandList, candlist, ret);
1018 else
1019 ret = convert_candidatelist_AtoW( candlist, lpCandList, dwBufLen);
1021 done:
1022 ImmUnlockIMCC(data->IMC.hCandInfo);
1023 return ret;
1026 /***********************************************************************
1027 * ImmGetCandidateWindow (IMM32.@)
1029 BOOL WINAPI ImmGetCandidateWindow(
1030 HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
1032 InputContextData *data = hIMC;
1034 TRACE("%p, %d, %p\n", hIMC, dwIndex, lpCandidate);
1036 if (!data || !lpCandidate)
1037 return FALSE;
1039 if ( dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
1040 return FALSE;
1042 *lpCandidate = data->IMC.cfCandForm[dwIndex];
1044 return TRUE;
1047 /***********************************************************************
1048 * ImmGetCompositionFontA (IMM32.@)
1050 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1052 LOGFONTW lfW;
1053 BOOL rc;
1055 TRACE("(%p, %p):\n", hIMC, lplf);
1057 rc = ImmGetCompositionFontW(hIMC,&lfW);
1058 if (!rc || !lplf)
1059 return FALSE;
1061 memcpy(lplf,&lfW,sizeof(LOGFONTA));
1062 WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName,
1063 LF_FACESIZE, NULL, NULL);
1064 return TRUE;
1067 /***********************************************************************
1068 * ImmGetCompositionFontW (IMM32.@)
1070 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1072 InputContextData *data = hIMC;
1074 TRACE("(%p, %p):\n", hIMC, lplf);
1076 if (!data || !lplf)
1077 return FALSE;
1079 *lplf = data->IMC.lfFont.W;
1081 return TRUE;
1085 /* Helpers for the GetCompositionString functions */
1087 static INT CopyCompStringIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE target, INT tlen,
1088 BOOL unicode )
1090 INT rc;
1092 if (is_himc_ime_unicode(data) && !unicode)
1093 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)source, slen, (LPSTR)target, tlen, NULL, NULL);
1094 else if (!is_himc_ime_unicode(data) && unicode)
1095 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)source, slen, (LPWSTR)target, tlen) * sizeof(WCHAR);
1096 else
1098 int dlen = (unicode)?sizeof(WCHAR):sizeof(CHAR);
1099 memcpy( target, source, min(slen,tlen)*dlen);
1100 rc = slen*dlen;
1103 return rc;
1106 static INT CopyCompAttrIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen,
1107 LPBYTE target, INT tlen, BOOL unicode )
1109 INT rc;
1111 if (is_himc_ime_unicode(data) && !unicode)
1113 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, sslen, NULL, 0, NULL, NULL);
1114 if (tlen)
1116 const BYTE *src = source;
1117 LPBYTE dst = target;
1118 int i, j = 0, k = 0;
1120 if (rc < tlen)
1121 tlen = rc;
1122 for (i = 0; i < sslen; ++i)
1124 int len;
1126 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)ssource + i, 1,
1127 NULL, 0, NULL, NULL);
1128 for (; len > 0; --len)
1130 dst[j++] = src[k];
1132 if (j >= tlen)
1133 goto end;
1135 ++k;
1137 end:
1138 rc = j;
1141 else if (!is_himc_ime_unicode(data) && unicode)
1143 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, sslen, NULL, 0);
1144 if (tlen)
1146 const BYTE *src = source;
1147 LPBYTE dst = target;
1148 int i, j = 0;
1150 if (rc < tlen)
1151 tlen = rc;
1152 for (i = 0; i < sslen; ++i)
1154 if (IsDBCSLeadByte(((LPSTR)ssource)[i]))
1155 continue;
1157 dst[j++] = src[i];
1159 if (j >= tlen)
1160 break;
1162 rc = j;
1165 else
1167 memcpy( target, source, min(slen,tlen));
1168 rc = slen;
1171 return rc;
1174 static INT CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource,
1175 LPBYTE target, INT tlen, BOOL unicode )
1177 INT rc;
1179 if (is_himc_ime_unicode(data) && !unicode)
1181 if (tlen)
1183 int i;
1185 if (slen < tlen)
1186 tlen = slen;
1187 tlen /= sizeof (DWORD);
1188 for (i = 0; i < tlen; ++i)
1190 ((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource,
1191 ((DWORD *)source)[i],
1192 NULL, 0,
1193 NULL, NULL);
1195 rc = sizeof (DWORD) * i;
1197 else
1198 rc = slen;
1200 else if (!is_himc_ime_unicode(data) && unicode)
1202 if (tlen)
1204 int i;
1206 if (slen < tlen)
1207 tlen = slen;
1208 tlen /= sizeof (DWORD);
1209 for (i = 0; i < tlen; ++i)
1211 ((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource,
1212 ((DWORD *)source)[i],
1213 NULL, 0);
1215 rc = sizeof (DWORD) * i;
1217 else
1218 rc = slen;
1220 else
1222 memcpy( target, source, min(slen,tlen));
1223 rc = slen;
1226 return rc;
1229 static INT CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE ssource, BOOL unicode)
1231 int rc;
1233 if (is_himc_ime_unicode(data) && !unicode)
1235 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, NULL, NULL);
1237 else if (!is_himc_ime_unicode(data) && unicode)
1239 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0);
1241 else
1242 rc = offset;
1244 return rc;
1247 static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf,
1248 DWORD dwBufLen, BOOL unicode)
1250 LONG rc = 0;
1251 InputContextData *data = hIMC;
1252 LPCOMPOSITIONSTRING compstr;
1253 LPBYTE compdata;
1255 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
1257 if (!data)
1258 return FALSE;
1260 if (!data->IMC.hCompStr)
1261 return FALSE;
1263 compdata = ImmLockIMCC(data->IMC.hCompStr);
1264 compstr = (LPCOMPOSITIONSTRING)compdata;
1266 switch (dwIndex)
1268 case GCS_RESULTSTR:
1269 TRACE("GCS_RESULTSTR\n");
1270 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, lpBuf, dwBufLen, unicode);
1271 break;
1272 case GCS_COMPSTR:
1273 TRACE("GCS_COMPSTR\n");
1274 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, lpBuf, dwBufLen, unicode);
1275 break;
1276 case GCS_COMPATTR:
1277 TRACE("GCS_COMPATTR\n");
1278 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompAttrOffset, compstr->dwCompAttrLen,
1279 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1280 lpBuf, dwBufLen, unicode);
1281 break;
1282 case GCS_COMPCLAUSE:
1283 TRACE("GCS_COMPCLAUSE\n");
1284 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompClauseOffset,compstr->dwCompClauseLen,
1285 compdata + compstr->dwCompStrOffset,
1286 lpBuf, dwBufLen, unicode);
1287 break;
1288 case GCS_RESULTCLAUSE:
1289 TRACE("GCS_RESULTCLAUSE\n");
1290 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen,
1291 compdata + compstr->dwResultStrOffset,
1292 lpBuf, dwBufLen, unicode);
1293 break;
1294 case GCS_RESULTREADSTR:
1295 TRACE("GCS_RESULTREADSTR\n");
1296 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultReadStrOffset, compstr->dwResultReadStrLen, lpBuf, dwBufLen, unicode);
1297 break;
1298 case GCS_RESULTREADCLAUSE:
1299 TRACE("GCS_RESULTREADCLAUSE\n");
1300 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultReadClauseOffset,compstr->dwResultReadClauseLen,
1301 compdata + compstr->dwResultStrOffset,
1302 lpBuf, dwBufLen, unicode);
1303 break;
1304 case GCS_COMPREADSTR:
1305 TRACE("GCS_COMPREADSTR\n");
1306 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, lpBuf, dwBufLen, unicode);
1307 break;
1308 case GCS_COMPREADATTR:
1309 TRACE("GCS_COMPREADATTR\n");
1310 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompReadAttrOffset, compstr->dwCompReadAttrLen,
1311 compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen,
1312 lpBuf, dwBufLen, unicode);
1313 break;
1314 case GCS_COMPREADCLAUSE:
1315 TRACE("GCS_COMPREADCLAUSE\n");
1316 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompReadClauseOffset,compstr->dwCompReadClauseLen,
1317 compdata + compstr->dwCompStrOffset,
1318 lpBuf, dwBufLen, unicode);
1319 break;
1320 case GCS_CURSORPOS:
1321 TRACE("GCS_CURSORPOS\n");
1322 rc = CopyCompOffsetIMEtoClient(data, compstr->dwCursorPos, compdata + compstr->dwCompStrOffset, unicode);
1323 break;
1324 case GCS_DELTASTART:
1325 TRACE("GCS_DELTASTART\n");
1326 rc = CopyCompOffsetIMEtoClient(data, compstr->dwDeltaStart, compdata + compstr->dwCompStrOffset, unicode);
1327 break;
1328 default:
1329 FIXME("Unhandled index 0x%x\n",dwIndex);
1330 break;
1333 ImmUnlockIMCC(data->IMC.hCompStr);
1335 return rc;
1338 /***********************************************************************
1339 * ImmGetCompositionStringA (IMM32.@)
1341 LONG WINAPI ImmGetCompositionStringA(
1342 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
1344 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
1348 /***********************************************************************
1349 * ImmGetCompositionStringW (IMM32.@)
1351 LONG WINAPI ImmGetCompositionStringW(
1352 HIMC hIMC, DWORD dwIndex,
1353 LPVOID lpBuf, DWORD dwBufLen)
1355 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
1358 /***********************************************************************
1359 * ImmGetCompositionWindow (IMM32.@)
1361 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1363 InputContextData *data = hIMC;
1365 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1367 if (!data)
1368 return FALSE;
1370 *lpCompForm = data->IMC.cfCompForm;
1371 return 1;
1374 /***********************************************************************
1375 * ImmGetContext (IMM32.@)
1378 HIMC WINAPI ImmGetContext(HWND hWnd)
1380 HIMC rc;
1382 TRACE("%p\n", hWnd);
1384 if (!IsWindow(hWnd))
1386 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
1387 return NULL;
1389 if (!IMM_GetThreadData()->defaultContext)
1390 IMM_GetThreadData()->defaultContext = ImmCreateContext();
1392 rc = GetPropW(hWnd,szwWineIMCProperty);
1393 if (rc == (HIMC)-1)
1394 rc = NULL;
1395 else if (rc == NULL)
1396 rc = IMM_GetThreadData()->defaultContext;
1398 if (rc)
1400 InputContextData *data = rc;
1401 data->IMC.hWnd = hWnd;
1403 TRACE("returning %p\n", rc);
1405 return rc;
1408 /***********************************************************************
1409 * ImmGetConversionListA (IMM32.@)
1411 DWORD WINAPI ImmGetConversionListA(
1412 HKL hKL, HIMC hIMC,
1413 LPCSTR pSrc, LPCANDIDATELIST lpDst,
1414 DWORD dwBufLen, UINT uFlag)
1416 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1417 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_a(pSrc), lpDst,
1418 dwBufLen, uFlag);
1419 if (immHkl->hIME && immHkl->pImeConversionList)
1421 if (!is_kbd_ime_unicode(immHkl))
1422 return immHkl->pImeConversionList(hIMC,(LPCWSTR)pSrc,lpDst,dwBufLen,uFlag);
1423 else
1425 LPCANDIDATELIST lpwDst;
1426 DWORD ret = 0, len;
1427 LPWSTR pwSrc = strdupAtoW(pSrc);
1429 len = immHkl->pImeConversionList(hIMC, pwSrc, NULL, 0, uFlag);
1430 lpwDst = HeapAlloc(GetProcessHeap(), 0, len);
1431 if ( lpwDst )
1433 immHkl->pImeConversionList(hIMC, pwSrc, lpwDst, len, uFlag);
1434 ret = convert_candidatelist_WtoA( lpwDst, lpDst, dwBufLen);
1435 HeapFree(GetProcessHeap(), 0, lpwDst);
1437 HeapFree(GetProcessHeap(), 0, pwSrc);
1439 return ret;
1442 else
1443 return 0;
1446 /***********************************************************************
1447 * ImmGetConversionListW (IMM32.@)
1449 DWORD WINAPI ImmGetConversionListW(
1450 HKL hKL, HIMC hIMC,
1451 LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1452 DWORD dwBufLen, UINT uFlag)
1454 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1455 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_w(pSrc), lpDst,
1456 dwBufLen, uFlag);
1457 if (immHkl->hIME && immHkl->pImeConversionList)
1459 if (is_kbd_ime_unicode(immHkl))
1460 return immHkl->pImeConversionList(hIMC,pSrc,lpDst,dwBufLen,uFlag);
1461 else
1463 LPCANDIDATELIST lpaDst;
1464 DWORD ret = 0, len;
1465 LPSTR paSrc = strdupWtoA(pSrc);
1467 len = immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, NULL, 0, uFlag);
1468 lpaDst = HeapAlloc(GetProcessHeap(), 0, len);
1469 if ( lpaDst )
1471 immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, lpaDst, len, uFlag);
1472 ret = convert_candidatelist_AtoW( lpaDst, lpDst, dwBufLen);
1473 HeapFree(GetProcessHeap(), 0, lpaDst);
1475 HeapFree(GetProcessHeap(), 0, paSrc);
1477 return ret;
1480 else
1481 return 0;
1484 /***********************************************************************
1485 * ImmGetConversionStatus (IMM32.@)
1487 BOOL WINAPI ImmGetConversionStatus(
1488 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1490 InputContextData *data = hIMC;
1492 TRACE("%p %p %p\n", hIMC, lpfdwConversion, lpfdwSentence);
1494 if (!data)
1495 return FALSE;
1497 if (lpfdwConversion)
1498 *lpfdwConversion = data->IMC.fdwConversion;
1499 if (lpfdwSentence)
1500 *lpfdwSentence = data->IMC.fdwSentence;
1502 return TRUE;
1505 /***********************************************************************
1506 * ImmGetDefaultIMEWnd (IMM32.@)
1508 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1510 static const WCHAR szwIME[] = {'I','M','E',0};
1511 if (IMM_GetThreadData()->hwndDefault == NULL)
1512 IMM_GetThreadData()->hwndDefault = CreateWindowExW( WS_EX_TOOLWINDOW,
1513 szwIME, NULL, WS_POPUP, 0, 0, 1, 1, 0, 0, 0, 0);
1514 TRACE("Default is %p\n",IMM_GetThreadData()->hwndDefault);
1515 return IMM_GetThreadData()->hwndDefault;
1518 /***********************************************************************
1519 * ImmGetDescriptionA (IMM32.@)
1521 UINT WINAPI ImmGetDescriptionA(
1522 HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1524 WCHAR *buf;
1525 DWORD len;
1527 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1529 /* find out how many characters in the unicode buffer */
1530 len = ImmGetDescriptionW( hKL, NULL, 0 );
1532 /* allocate a buffer of that size */
1533 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1534 if( !buf )
1535 return 0;
1537 /* fetch the unicode buffer */
1538 len = ImmGetDescriptionW( hKL, buf, len + 1 );
1540 /* convert it back to ASCII */
1541 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1542 lpszDescription, uBufLen, NULL, NULL );
1544 HeapFree( GetProcessHeap(), 0, buf );
1546 return len;
1549 /***********************************************************************
1550 * ImmGetDescriptionW (IMM32.@)
1552 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1554 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1556 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1558 if (!uBufLen) return lstrlenW( name );
1559 lstrcpynW( lpszDescription, name, uBufLen );
1560 return lstrlenW( lpszDescription );
1563 /***********************************************************************
1564 * ImmGetGuideLineA (IMM32.@)
1566 DWORD WINAPI ImmGetGuideLineA(
1567 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1569 FIXME("(%p, %d, %s, %d): stub\n",
1570 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1572 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1573 return 0;
1576 /***********************************************************************
1577 * ImmGetGuideLineW (IMM32.@)
1579 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1581 FIXME("(%p, %d, %s, %d): stub\n",
1582 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1584 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1585 return 0;
1588 /***********************************************************************
1589 * ImmGetIMEFileNameA (IMM32.@)
1591 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1593 LPWSTR bufW = NULL;
1594 UINT wBufLen = uBufLen;
1595 UINT rc;
1597 if (uBufLen && lpszFileName)
1598 bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR));
1599 else /* We need this to get the number of byte required */
1601 bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR));
1602 wBufLen = MAX_PATH;
1605 rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen);
1607 if (rc > 0)
1609 if (uBufLen && lpszFileName)
1610 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName,
1611 uBufLen, NULL, NULL);
1612 else /* get the length */
1613 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL,
1614 NULL);
1617 HeapFree(GetProcessHeap(),0,bufW);
1618 return rc;
1621 /***********************************************************************
1622 * ImmGetIMEFileNameW (IMM32.@)
1624 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1626 HKEY hkey;
1627 DWORD length;
1628 DWORD rc;
1629 WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
1631 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hKL );
1632 rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey);
1633 if (rc != ERROR_SUCCESS)
1635 SetLastError(rc);
1636 return 0;
1639 length = 0;
1640 rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length);
1642 if (rc != ERROR_SUCCESS)
1644 RegCloseKey(hkey);
1645 SetLastError(rc);
1646 return 0;
1648 if (length > uBufLen * sizeof(WCHAR) || !lpszFileName)
1650 RegCloseKey(hkey);
1651 if (lpszFileName)
1653 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1654 return 0;
1656 else
1657 return length / sizeof(WCHAR);
1660 RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length);
1662 RegCloseKey(hkey);
1664 return length / sizeof(WCHAR);
1667 /***********************************************************************
1668 * ImmGetOpenStatus (IMM32.@)
1670 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1672 InputContextData *data = hIMC;
1673 static int i;
1675 if (!data)
1676 return FALSE;
1678 TRACE("(%p): semi-stub\n", hIMC);
1680 if (!i++)
1681 FIXME("(%p): semi-stub\n", hIMC);
1683 return data->IMC.fOpen;
1686 /***********************************************************************
1687 * ImmGetProperty (IMM32.@)
1689 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1691 DWORD rc = 0;
1692 ImmHkl *kbd;
1694 TRACE("(%p, %d)\n", hKL, fdwIndex);
1695 kbd = IMM_GetImmHkl(hKL);
1697 if (kbd && kbd->hIME)
1699 switch (fdwIndex)
1701 case IGP_PROPERTY: rc = kbd->imeInfo.fdwProperty; break;
1702 case IGP_CONVERSION: rc = kbd->imeInfo.fdwConversionCaps; break;
1703 case IGP_SENTENCE: rc = kbd->imeInfo.fdwSentenceCaps; break;
1704 case IGP_SETCOMPSTR: rc = kbd->imeInfo.fdwSCSCaps; break;
1705 case IGP_SELECT: rc = kbd->imeInfo.fdwSelectCaps; break;
1706 case IGP_GETIMEVERSION: rc = IMEVER_0400; break;
1707 case IGP_UI: rc = 0; break;
1708 default: rc = 0;
1711 return rc;
1714 /***********************************************************************
1715 * ImmGetRegisterWordStyleA (IMM32.@)
1717 UINT WINAPI ImmGetRegisterWordStyleA(
1718 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1720 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1721 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1722 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1724 if (!is_kbd_ime_unicode(immHkl))
1725 return immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)lpStyleBuf);
1726 else
1728 STYLEBUFW sbw;
1729 UINT rc;
1731 rc = immHkl->pImeGetRegisterWordStyle(nItem,&sbw);
1732 WideCharToMultiByte(CP_ACP, 0, sbw.szDescription, -1,
1733 lpStyleBuf->szDescription, 32, NULL, NULL);
1734 lpStyleBuf->dwStyle = sbw.dwStyle;
1735 return rc;
1738 else
1739 return 0;
1742 /***********************************************************************
1743 * ImmGetRegisterWordStyleW (IMM32.@)
1745 UINT WINAPI ImmGetRegisterWordStyleW(
1746 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1748 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1749 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1750 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1752 if (is_kbd_ime_unicode(immHkl))
1753 return immHkl->pImeGetRegisterWordStyle(nItem,lpStyleBuf);
1754 else
1756 STYLEBUFA sba;
1757 UINT rc;
1759 rc = immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)&sba);
1760 MultiByteToWideChar(CP_ACP, 0, sba.szDescription, -1,
1761 lpStyleBuf->szDescription, 32);
1762 lpStyleBuf->dwStyle = sba.dwStyle;
1763 return rc;
1766 else
1767 return 0;
1770 /***********************************************************************
1771 * ImmGetStatusWindowPos (IMM32.@)
1773 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1775 InputContextData *data = hIMC;
1777 TRACE("(%p, %p)\n", hIMC, lpptPos);
1779 if (!data || !lpptPos)
1780 return FALSE;
1782 *lpptPos = data->IMC.ptStatusWndPos;
1784 return TRUE;
1787 /***********************************************************************
1788 * ImmGetVirtualKey (IMM32.@)
1790 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1792 OSVERSIONINFOA version;
1793 InputContextData *data = ImmGetContext( hWnd );
1794 TRACE("%p\n", hWnd);
1796 if ( data )
1797 return data->lastVK;
1799 version.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
1800 GetVersionExA( &version );
1801 switch(version.dwPlatformId)
1803 case VER_PLATFORM_WIN32_WINDOWS:
1804 return VK_PROCESSKEY;
1805 case VER_PLATFORM_WIN32_NT:
1806 return 0;
1807 default:
1808 FIXME("%d not supported\n",version.dwPlatformId);
1809 return VK_PROCESSKEY;
1813 /***********************************************************************
1814 * ImmInstallIMEA (IMM32.@)
1816 HKL WINAPI ImmInstallIMEA(
1817 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1819 LPWSTR lpszwIMEFileName;
1820 LPWSTR lpszwLayoutText;
1821 HKL hkl;
1823 TRACE ("(%s, %s)\n", debugstr_a(lpszIMEFileName),
1824 debugstr_a(lpszLayoutText));
1826 lpszwIMEFileName = strdupAtoW(lpszIMEFileName);
1827 lpszwLayoutText = strdupAtoW(lpszLayoutText);
1829 hkl = ImmInstallIMEW(lpszwIMEFileName, lpszwLayoutText);
1831 HeapFree(GetProcessHeap(),0,lpszwIMEFileName);
1832 HeapFree(GetProcessHeap(),0,lpszwLayoutText);
1833 return hkl;
1836 /***********************************************************************
1837 * ImmInstallIMEW (IMM32.@)
1839 HKL WINAPI ImmInstallIMEW(
1840 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1842 INT lcid = GetUserDefaultLCID();
1843 INT count;
1844 HKL hkl;
1845 DWORD rc;
1846 HKEY hkey;
1847 WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
1849 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName),
1850 debugstr_w(lpszLayoutText));
1852 /* Start with 2. e001 will be blank and so default to the wine internal IME */
1853 count = 2;
1855 while (count < 0xfff)
1857 DWORD disposition = 0;
1859 hkl = (HKL)MAKELPARAM( lcid, 0xe000 | count );
1860 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hkl);
1862 rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &disposition);
1863 if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
1864 break;
1865 else if (rc == ERROR_SUCCESS)
1866 RegCloseKey(hkey);
1868 count++;
1871 if (count == 0xfff)
1873 WARN("Unable to find slot to install IME\n");
1874 return 0;
1877 if (rc == ERROR_SUCCESS)
1879 rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (const BYTE*)lpszIMEFileName,
1880 (lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR));
1881 if (rc == ERROR_SUCCESS)
1882 rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (const BYTE*)lpszLayoutText,
1883 (lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR));
1884 RegCloseKey(hkey);
1885 return hkl;
1887 else
1889 WARN("Unable to set IME registry values\n");
1890 return 0;
1894 /***********************************************************************
1895 * ImmIsIME (IMM32.@)
1897 BOOL WINAPI ImmIsIME(HKL hKL)
1899 ImmHkl *ptr;
1900 TRACE("(%p):\n", hKL);
1901 ptr = IMM_GetImmHkl(hKL);
1902 return (ptr && ptr->hIME);
1905 /***********************************************************************
1906 * ImmIsUIMessageA (IMM32.@)
1908 BOOL WINAPI ImmIsUIMessageA(
1909 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1911 BOOL rc = FALSE;
1913 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1914 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1915 (msg == WM_IME_SETCONTEXT) ||
1916 (msg == WM_IME_NOTIFY) ||
1917 (msg == WM_IME_COMPOSITIONFULL) ||
1918 (msg == WM_IME_SELECT) ||
1919 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */) ||
1920 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1921 (msg == WM_MSIME_MOUSE) ||
1922 (msg == WM_MSIME_RECONVERTREQUEST) ||
1923 (msg == WM_MSIME_RECONVERT) ||
1924 (msg == WM_MSIME_QUERYPOSITION) ||
1925 (msg == WM_MSIME_DOCUMENTFEED))
1927 if (hWndIME)
1928 SendMessageA(hWndIME, msg, wParam, lParam);
1930 rc = TRUE;
1932 return rc;
1935 /***********************************************************************
1936 * ImmIsUIMessageW (IMM32.@)
1938 BOOL WINAPI ImmIsUIMessageW(
1939 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1941 BOOL rc = FALSE;
1943 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1944 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1945 (msg == WM_IME_SETCONTEXT) ||
1946 (msg == WM_IME_NOTIFY) ||
1947 (msg == WM_IME_COMPOSITIONFULL) ||
1948 (msg == WM_IME_SELECT) ||
1949 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */) ||
1950 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1951 (msg == WM_MSIME_MOUSE) ||
1952 (msg == WM_MSIME_RECONVERTREQUEST) ||
1953 (msg == WM_MSIME_RECONVERT) ||
1954 (msg == WM_MSIME_QUERYPOSITION) ||
1955 (msg == WM_MSIME_DOCUMENTFEED))
1957 if (hWndIME)
1958 SendMessageW(hWndIME, msg, wParam, lParam);
1960 rc = TRUE;
1962 return rc;
1965 /***********************************************************************
1966 * ImmNotifyIME (IMM32.@)
1968 BOOL WINAPI ImmNotifyIME(
1969 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
1971 InputContextData *data = hIMC;
1973 TRACE("(%p, %d, %d, %d)\n",
1974 hIMC, dwAction, dwIndex, dwValue);
1976 if (!data || ! data->immKbd->pNotifyIME)
1977 return FALSE;
1979 return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue);
1982 /***********************************************************************
1983 * ImmRegisterWordA (IMM32.@)
1985 BOOL WINAPI ImmRegisterWordA(
1986 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
1988 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1989 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
1990 debugstr_a(lpszRegister));
1991 if (immHkl->hIME && immHkl->pImeRegisterWord)
1993 if (!is_kbd_ime_unicode(immHkl))
1994 return immHkl->pImeRegisterWord((LPCWSTR)lpszReading,dwStyle,
1995 (LPCWSTR)lpszRegister);
1996 else
1998 LPWSTR lpszwReading = strdupAtoW(lpszReading);
1999 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
2000 BOOL rc;
2002 rc = immHkl->pImeRegisterWord(lpszwReading,dwStyle,lpszwRegister);
2003 HeapFree(GetProcessHeap(),0,lpszwReading);
2004 HeapFree(GetProcessHeap(),0,lpszwRegister);
2005 return rc;
2008 else
2009 return FALSE;
2012 /***********************************************************************
2013 * ImmRegisterWordW (IMM32.@)
2015 BOOL WINAPI ImmRegisterWordW(
2016 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
2018 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2019 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2020 debugstr_w(lpszRegister));
2021 if (immHkl->hIME && immHkl->pImeRegisterWord)
2023 if (is_kbd_ime_unicode(immHkl))
2024 return immHkl->pImeRegisterWord(lpszReading,dwStyle,lpszRegister);
2025 else
2027 LPSTR lpszaReading = strdupWtoA(lpszReading);
2028 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
2029 BOOL rc;
2031 rc = immHkl->pImeRegisterWord((LPCWSTR)lpszaReading,dwStyle,
2032 (LPCWSTR)lpszaRegister);
2033 HeapFree(GetProcessHeap(),0,lpszaReading);
2034 HeapFree(GetProcessHeap(),0,lpszaRegister);
2035 return rc;
2038 else
2039 return FALSE;
2042 /***********************************************************************
2043 * ImmReleaseContext (IMM32.@)
2045 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
2047 static int shown = 0;
2049 if (!shown) {
2050 FIXME("(%p, %p): stub\n", hWnd, hIMC);
2051 shown = 1;
2053 return TRUE;
2056 /***********************************************************************
2057 * ImmRequestMessageA(IMM32.@)
2059 LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2061 InputContextData *data = hIMC;
2063 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2065 if (data && IsWindow(data->IMC.hWnd))
2066 return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2068 return 0;
2071 /***********************************************************************
2072 * ImmRequestMessageW(IMM32.@)
2074 LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2076 InputContextData *data = hIMC;
2078 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2080 if (data && IsWindow(data->IMC.hWnd))
2081 return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2083 return 0;
2086 /***********************************************************************
2087 * ImmSetCandidateWindow (IMM32.@)
2089 BOOL WINAPI ImmSetCandidateWindow(
2090 HIMC hIMC, LPCANDIDATEFORM lpCandidate)
2092 InputContextData *data = hIMC;
2094 TRACE("(%p, %p)\n", hIMC, lpCandidate);
2096 if (!data || !lpCandidate)
2097 return FALSE;
2099 TRACE("\t%x, %x, (%i,%i), (%i,%i - %i,%i)\n",
2100 lpCandidate->dwIndex, lpCandidate->dwStyle,
2101 lpCandidate->ptCurrentPos.x, lpCandidate->ptCurrentPos.y,
2102 lpCandidate->rcArea.top, lpCandidate->rcArea.left,
2103 lpCandidate->rcArea.bottom, lpCandidate->rcArea.right);
2105 if ( lpCandidate->dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
2106 return FALSE;
2108 data->IMC.cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
2109 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS);
2110 ImmInternalSendIMENotify(data, IMN_SETCANDIDATEPOS, 1 << lpCandidate->dwIndex);
2112 return TRUE;
2115 /***********************************************************************
2116 * ImmSetCompositionFontA (IMM32.@)
2118 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
2120 InputContextData *data = hIMC;
2121 TRACE("(%p, %p)\n", hIMC, lplf);
2123 if (!data || !lplf)
2124 return FALSE;
2126 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
2127 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
2128 LF_FACESIZE);
2129 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2130 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2132 return TRUE;
2135 /***********************************************************************
2136 * ImmSetCompositionFontW (IMM32.@)
2138 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
2140 InputContextData *data = hIMC;
2141 TRACE("(%p, %p)\n", hIMC, lplf);
2143 if (!data || !lplf)
2144 return FALSE;
2146 data->IMC.lfFont.W = *lplf;
2147 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2148 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2150 return TRUE;
2153 /***********************************************************************
2154 * ImmSetCompositionStringA (IMM32.@)
2156 BOOL WINAPI ImmSetCompositionStringA(
2157 HIMC hIMC, DWORD dwIndex,
2158 LPCVOID lpComp, DWORD dwCompLen,
2159 LPCVOID lpRead, DWORD dwReadLen)
2161 DWORD comp_len;
2162 DWORD read_len;
2163 WCHAR *CompBuffer = NULL;
2164 WCHAR *ReadBuffer = NULL;
2165 BOOL rc;
2166 InputContextData *data = hIMC;
2168 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2169 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2171 if (!data)
2172 return FALSE;
2174 if (!(dwIndex == SCS_SETSTR ||
2175 dwIndex == SCS_CHANGEATTR ||
2176 dwIndex == SCS_CHANGECLAUSE ||
2177 dwIndex == SCS_SETRECONVERTSTRING ||
2178 dwIndex == SCS_QUERYRECONVERTSTRING))
2179 return FALSE;
2181 if (!is_himc_ime_unicode(data))
2182 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2183 dwCompLen, lpRead, dwReadLen);
2185 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
2186 if (comp_len)
2188 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
2189 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
2192 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
2193 if (read_len)
2195 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
2196 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
2199 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
2200 ReadBuffer, read_len);
2202 HeapFree(GetProcessHeap(), 0, CompBuffer);
2203 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2205 return rc;
2208 /***********************************************************************
2209 * ImmSetCompositionStringW (IMM32.@)
2211 BOOL WINAPI ImmSetCompositionStringW(
2212 HIMC hIMC, DWORD dwIndex,
2213 LPCVOID lpComp, DWORD dwCompLen,
2214 LPCVOID lpRead, DWORD dwReadLen)
2216 DWORD comp_len;
2217 DWORD read_len;
2218 CHAR *CompBuffer = NULL;
2219 CHAR *ReadBuffer = NULL;
2220 BOOL rc;
2221 InputContextData *data = hIMC;
2223 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2224 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2226 if (!data)
2227 return FALSE;
2229 if (!(dwIndex == SCS_SETSTR ||
2230 dwIndex == SCS_CHANGEATTR ||
2231 dwIndex == SCS_CHANGECLAUSE ||
2232 dwIndex == SCS_SETRECONVERTSTRING ||
2233 dwIndex == SCS_QUERYRECONVERTSTRING))
2234 return FALSE;
2236 if (is_himc_ime_unicode(data))
2237 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2238 dwCompLen, lpRead, dwReadLen);
2240 comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL,
2241 NULL);
2242 if (comp_len)
2244 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len);
2245 WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len,
2246 NULL, NULL);
2249 read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL,
2250 NULL);
2251 if (read_len)
2253 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len);
2254 WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len,
2255 NULL, NULL);
2258 rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len,
2259 ReadBuffer, read_len);
2261 HeapFree(GetProcessHeap(), 0, CompBuffer);
2262 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2264 return rc;
2267 /***********************************************************************
2268 * ImmSetCompositionWindow (IMM32.@)
2270 BOOL WINAPI ImmSetCompositionWindow(
2271 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
2273 BOOL reshow = FALSE;
2274 InputContextData *data = hIMC;
2276 TRACE("(%p, %p)\n", hIMC, lpCompForm);
2277 TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
2278 lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
2279 lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
2281 if (!data)
2282 return FALSE;
2284 data->IMC.cfCompForm = *lpCompForm;
2286 if (IsWindowVisible(data->immKbd->UIWnd))
2288 reshow = TRUE;
2289 ShowWindow(data->immKbd->UIWnd,SW_HIDE);
2292 /* FIXME: this is a partial stub */
2294 if (reshow)
2295 ShowWindow(data->immKbd->UIWnd,SW_SHOWNOACTIVATE);
2297 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0);
2298 return TRUE;
2301 /***********************************************************************
2302 * ImmSetConversionStatus (IMM32.@)
2304 BOOL WINAPI ImmSetConversionStatus(
2305 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
2307 DWORD oldConversion, oldSentence;
2308 InputContextData *data = hIMC;
2310 TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence);
2312 if (!data)
2313 return FALSE;
2315 if ( fdwConversion != data->IMC.fdwConversion )
2317 oldConversion = data->IMC.fdwConversion;
2318 data->IMC.fdwConversion = fdwConversion;
2319 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldConversion, IMC_SETCONVERSIONMODE);
2320 ImmInternalSendIMENotify(data, IMN_SETCONVERSIONMODE, 0);
2322 if ( fdwSentence != data->IMC.fdwSentence )
2324 oldSentence = data->IMC.fdwSentence;
2325 data->IMC.fdwSentence = fdwSentence;
2326 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldSentence, IMC_SETSENTENCEMODE);
2327 ImmInternalSendIMENotify(data, IMN_SETSENTENCEMODE, 0);
2330 return TRUE;
2333 /***********************************************************************
2334 * ImmSetOpenStatus (IMM32.@)
2336 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
2338 InputContextData *data = hIMC;
2340 TRACE("%p %d\n", hIMC, fOpen);
2342 if (!data)
2343 return FALSE;
2345 if (data->immKbd->UIWnd == NULL)
2347 /* create the ime window */
2348 data->immKbd->UIWnd = CreateWindowExW( WS_EX_TOOLWINDOW,
2349 data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0,
2350 0, data->immKbd->hIME, 0);
2351 SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
2354 if (!fOpen != !data->IMC.fOpen)
2356 data->IMC.fOpen = fOpen;
2357 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS);
2358 ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0);
2361 return TRUE;
2364 /***********************************************************************
2365 * ImmSetStatusWindowPos (IMM32.@)
2367 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
2369 InputContextData *data = hIMC;
2371 TRACE("(%p, %p)\n", hIMC, lpptPos);
2373 if (!data || !lpptPos)
2374 return FALSE;
2376 TRACE("\t(%i,%i)\n", lpptPos->x, lpptPos->y);
2378 data->IMC.ptStatusWndPos = *lpptPos;
2379 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETSTATUSWINDOWPOS);
2380 ImmInternalSendIMENotify(data, IMN_SETSTATUSWINDOWPOS, 0);
2382 return TRUE;
2385 /***********************************************************************
2386 * ImmCreateSoftKeyboard(IMM32.@)
2388 HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y)
2390 FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y);
2391 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2392 return 0;
2395 /***********************************************************************
2396 * ImmDestroySoftKeyboard(IMM32.@)
2398 BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd)
2400 FIXME("(%p): stub\n", hSoftWnd);
2401 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2402 return FALSE;
2405 /***********************************************************************
2406 * ImmShowSoftKeyboard(IMM32.@)
2408 BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow)
2410 FIXME("(%p, %d): stub\n", hSoftWnd, nCmdShow);
2411 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2412 return FALSE;
2415 /***********************************************************************
2416 * ImmSimulateHotKey (IMM32.@)
2418 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
2420 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
2421 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2422 return FALSE;
2425 /***********************************************************************
2426 * ImmUnregisterWordA (IMM32.@)
2428 BOOL WINAPI ImmUnregisterWordA(
2429 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
2431 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2432 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2433 debugstr_a(lpszUnregister));
2434 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2436 if (!is_kbd_ime_unicode(immHkl))
2437 return immHkl->pImeUnregisterWord((LPCWSTR)lpszReading,dwStyle,
2438 (LPCWSTR)lpszUnregister);
2439 else
2441 LPWSTR lpszwReading = strdupAtoW(lpszReading);
2442 LPWSTR lpszwUnregister = strdupAtoW(lpszUnregister);
2443 BOOL rc;
2445 rc = immHkl->pImeUnregisterWord(lpszwReading,dwStyle,lpszwUnregister);
2446 HeapFree(GetProcessHeap(),0,lpszwReading);
2447 HeapFree(GetProcessHeap(),0,lpszwUnregister);
2448 return rc;
2451 else
2452 return FALSE;
2455 /***********************************************************************
2456 * ImmUnregisterWordW (IMM32.@)
2458 BOOL WINAPI ImmUnregisterWordW(
2459 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
2461 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2462 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2463 debugstr_w(lpszUnregister));
2464 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2466 if (is_kbd_ime_unicode(immHkl))
2467 return immHkl->pImeUnregisterWord(lpszReading,dwStyle,lpszUnregister);
2468 else
2470 LPSTR lpszaReading = strdupWtoA(lpszReading);
2471 LPSTR lpszaUnregister = strdupWtoA(lpszUnregister);
2472 BOOL rc;
2474 rc = immHkl->pImeUnregisterWord((LPCWSTR)lpszaReading,dwStyle,
2475 (LPCWSTR)lpszaUnregister);
2476 HeapFree(GetProcessHeap(),0,lpszaReading);
2477 HeapFree(GetProcessHeap(),0,lpszaUnregister);
2478 return rc;
2481 else
2482 return FALSE;
2485 /***********************************************************************
2486 * ImmGetImeMenuItemsA (IMM32.@)
2488 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2489 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
2490 DWORD dwSize)
2492 InputContextData *data = hIMC;
2493 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2494 lpImeParentMenu, lpImeMenu, dwSize);
2495 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2497 if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2498 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2499 (IMEMENUITEMINFOW*)lpImeParentMenu,
2500 (IMEMENUITEMINFOW*)lpImeMenu, dwSize);
2501 else
2503 IMEMENUITEMINFOW lpImeParentMenuW;
2504 IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL;
2505 DWORD rc;
2507 if (lpImeParentMenu)
2508 parent = &lpImeParentMenuW;
2509 if (lpImeMenu)
2511 int count = dwSize / sizeof(LPIMEMENUITEMINFOA);
2512 dwSize = count * sizeof(IMEMENUITEMINFOW);
2513 lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize);
2515 else
2516 lpImeMenuW = NULL;
2518 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2519 parent, lpImeMenuW, dwSize);
2521 if (lpImeParentMenu)
2523 memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA));
2524 lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem;
2525 WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString,
2526 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE,
2527 NULL, NULL);
2529 if (lpImeMenu && rc)
2531 unsigned int i;
2532 for (i = 0; i < rc; i++)
2534 memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA));
2535 lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem;
2536 WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString,
2537 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE,
2538 NULL, NULL);
2541 HeapFree(GetProcessHeap(),0,lpImeMenuW);
2542 return rc;
2545 else
2546 return 0;
2549 /***********************************************************************
2550 * ImmGetImeMenuItemsW (IMM32.@)
2552 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2553 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
2554 DWORD dwSize)
2556 InputContextData *data = hIMC;
2557 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2558 lpImeParentMenu, lpImeMenu, dwSize);
2559 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2561 if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2562 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2563 lpImeParentMenu, lpImeMenu, dwSize);
2564 else
2566 IMEMENUITEMINFOA lpImeParentMenuA;
2567 IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL;
2568 DWORD rc;
2570 if (lpImeParentMenu)
2571 parent = &lpImeParentMenuA;
2572 if (lpImeMenu)
2574 int count = dwSize / sizeof(LPIMEMENUITEMINFOW);
2575 dwSize = count * sizeof(IMEMENUITEMINFOA);
2576 lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize);
2578 else
2579 lpImeMenuA = NULL;
2581 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2582 (IMEMENUITEMINFOW*)parent,
2583 (IMEMENUITEMINFOW*)lpImeMenuA, dwSize);
2585 if (lpImeParentMenu)
2587 memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA));
2588 lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem;
2589 MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString,
2590 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE);
2592 if (lpImeMenu && rc)
2594 unsigned int i;
2595 for (i = 0; i < rc; i++)
2597 memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA));
2598 lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem;
2599 MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString,
2600 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE);
2603 HeapFree(GetProcessHeap(),0,lpImeMenuA);
2604 return rc;
2607 else
2608 return 0;
2611 /***********************************************************************
2612 * ImmLockIMC(IMM32.@)
2614 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
2616 InputContextData *data = hIMC;
2618 if (!data)
2619 return NULL;
2620 data->dwLock++;
2621 return &data->IMC;
2624 /***********************************************************************
2625 * ImmUnlockIMC(IMM32.@)
2627 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
2629 InputContextData *data = hIMC;
2630 data->dwLock--;
2631 return (data->dwLock!=0);
2634 /***********************************************************************
2635 * ImmGetIMCLockCount(IMM32.@)
2637 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
2639 InputContextData *data = hIMC;
2640 return data->dwLock;
2643 /***********************************************************************
2644 * ImmCreateIMCC(IMM32.@)
2646 HIMCC WINAPI ImmCreateIMCC(DWORD size)
2648 IMCCInternal *internal;
2649 int real_size = size + sizeof(IMCCInternal);
2651 internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size);
2652 if (internal == NULL)
2653 return NULL;
2655 internal->dwSize = size;
2656 return internal;
2659 /***********************************************************************
2660 * ImmDestroyIMCC(IMM32.@)
2662 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
2664 HeapFree(GetProcessHeap(),0,block);
2665 return NULL;
2668 /***********************************************************************
2669 * ImmLockIMCC(IMM32.@)
2671 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
2673 IMCCInternal *internal;
2674 internal = imcc;
2676 internal->dwLock ++;
2677 return internal + 1;
2680 /***********************************************************************
2681 * ImmUnlockIMCC(IMM32.@)
2683 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
2685 IMCCInternal *internal;
2686 internal = imcc;
2688 internal->dwLock --;
2689 return (internal->dwLock!=0);
2692 /***********************************************************************
2693 * ImmGetIMCCLockCount(IMM32.@)
2695 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
2697 IMCCInternal *internal;
2698 internal = imcc;
2700 return internal->dwLock;
2703 /***********************************************************************
2704 * ImmReSizeIMCC(IMM32.@)
2706 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
2708 IMCCInternal *internal,*newone;
2709 int real_size = size + sizeof(IMCCInternal);
2711 internal = imcc;
2713 newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size);
2714 newone->dwSize = size;
2716 return newone;
2719 /***********************************************************************
2720 * ImmGetIMCCSize(IMM32.@)
2722 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2724 IMCCInternal *internal;
2725 internal = imcc;
2727 return internal->dwSize;
2730 /***********************************************************************
2731 * ImmGenerateMessage(IMM32.@)
2733 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2735 InputContextData *data = hIMC;
2737 TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
2738 if (data->IMC.dwNumMsgBuf > 0)
2740 LPTRANSMSG lpTransMsg;
2741 DWORD i;
2743 lpTransMsg = ImmLockIMCC(data->IMC.hMsgBuf);
2744 for (i = 0; i < data->IMC.dwNumMsgBuf; i++)
2745 ImmInternalPostIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
2747 ImmUnlockIMCC(data->IMC.hMsgBuf);
2749 data->IMC.dwNumMsgBuf = 0;
2752 return TRUE;
2755 /***********************************************************************
2756 * ImmTranslateMessage(IMM32.@)
2757 * ( Undocumented, call internally and from user32.dll )
2759 BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData)
2761 InputContextData *data;
2762 HIMC imc = ImmGetContext(hwnd);
2763 BYTE state[256];
2764 UINT scancode;
2765 LPVOID list = 0;
2766 UINT msg_count;
2767 UINT uVirtKey;
2768 static const DWORD list_count = 10;
2770 TRACE("%p %x %x %x\n",hwnd, msg, (UINT)wParam, (UINT)lKeyData);
2772 if (imc)
2773 data = imc;
2774 else
2775 return FALSE;
2777 if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx)
2778 return FALSE;
2780 GetKeyboardState(state);
2781 scancode = lKeyData >> 0x10 & 0xff;
2783 list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list_count * sizeof(TRANSMSG) + sizeof(DWORD));
2784 ((DWORD*)list)[0] = list_count;
2786 if (data->immKbd->imeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST)
2788 WCHAR chr;
2790 if (!is_himc_ime_unicode(data))
2791 ToAscii(data->lastVK, scancode, state, &chr, 0);
2792 else
2793 ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0, GetKeyboardLayout(0));
2794 uVirtKey = MAKELONG(data->lastVK,chr);
2796 else
2797 uVirtKey = data->lastVK;
2799 msg_count = data->immKbd->pImeToAsciiEx(uVirtKey, scancode, state, list, 0, imc);
2800 TRACE("%i messages generated\n",msg_count);
2801 if (msg_count && msg_count <= list_count)
2803 UINT i;
2804 LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD));
2806 for (i = 0; i < msg_count; i++)
2807 ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam);
2809 else if (msg_count > list_count)
2810 ImmGenerateMessage(imc);
2812 HeapFree(GetProcessHeap(),0,list);
2814 data->lastVK = VK_PROCESSKEY;
2816 return (msg_count > 0);
2819 /***********************************************************************
2820 * ImmProcessKey(IMM32.@)
2821 * ( Undocumented, called from user32.dll )
2823 BOOL WINAPI ImmProcessKey(HWND hwnd, HKL hKL, UINT vKey, LPARAM lKeyData, DWORD unknown)
2825 InputContextData *data;
2826 HIMC imc = ImmGetContext(hwnd);
2827 BYTE state[256];
2829 TRACE("%p %p %x %x %x\n",hwnd, hKL, vKey, (UINT)lKeyData, unknown);
2831 if (imc)
2832 data = imc;
2833 else
2834 return FALSE;
2836 if (!data->immKbd->hIME || !data->immKbd->pImeProcessKey)
2837 return FALSE;
2839 GetKeyboardState(state);
2840 if (data->immKbd->pImeProcessKey(imc, vKey, lKeyData, state))
2842 data->lastVK = vKey;
2843 return TRUE;
2846 data->lastVK = VK_PROCESSKEY;
2847 return FALSE;
2850 /***********************************************************************
2851 * ImmDisableTextFrameService(IMM32.@)
2853 BOOL WINAPI ImmDisableTextFrameService(DWORD idThread)
2855 FIXME("Stub\n");
2856 return FALSE;
2859 /***********************************************************************
2860 * ImmEnumInputContext(IMM32.@)
2863 BOOL WINAPI ImmEnumInputContext(DWORD idThread, IMCENUMPROC lpfn, LPARAM lParam)
2865 FIXME("Stub\n");
2866 return FALSE;
2869 /***********************************************************************
2870 * ImmGetHotKey(IMM32.@)
2873 BOOL WINAPI ImmGetHotKey(DWORD hotkey, UINT *modifiers, UINT *key, HKL hkl)
2875 FIXME("%x, %p, %p, %p: stub\n", hotkey, modifiers, key, hkl);
2876 return FALSE;
2881 * Window Proc for the Default IME window class
2883 static LRESULT WINAPI DefIME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
2884 LPARAM lParam)
2886 switch (uMsg)
2888 case WM_CREATE:
2889 case WM_NCCREATE:
2890 return TRUE;
2891 case WM_IME_COMPOSITION:
2892 case WM_IME_STARTCOMPOSITION:
2893 case WM_IME_ENDCOMPOSITION:
2894 case WM_IME_SELECT:
2895 case WM_IME_CONTROL:
2896 case WM_IME_NOTIFY:
2898 ImmHkl *immHkl = IMM_GetImmHkl(GetKeyboardLayout(0));
2899 if (immHkl->UIWnd)
2900 PostMessageW(immHkl->UIWnd,uMsg,wParam,lParam);
2901 return TRUE;
2903 default:
2904 if ((uMsg == WM_MSIME_RECONVERTOPTIONS) ||
2905 (uMsg ==WM_MSIME_SERVICE) ||
2906 (uMsg == WM_MSIME_MOUSE) ||
2907 (uMsg == WM_MSIME_RECONVERTREQUEST) ||
2908 (uMsg == WM_MSIME_RECONVERT) ||
2909 (uMsg == WM_MSIME_QUERYPOSITION) ||
2910 (uMsg == WM_MSIME_DOCUMENTFEED))
2912 ImmHkl *immHkl = IMM_GetImmHkl(GetKeyboardLayout(0));
2913 if (immHkl->UIWnd)
2914 PostMessageW(immHkl->UIWnd,uMsg,wParam,lParam);
2915 return TRUE;
2917 return DefWindowProcW(hwnd, uMsg, wParam, lParam);