msvcp90: Return last index in string::find_last_not_of_cstr_substr if input is empty.
[wine/multimedia.git] / dlls / imm32 / imm.c
blob35c16f09255c9cd46d04699aae97652ed50e5ee2
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"
36 #include "wine/unicode.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(imm);
40 #define MAKE_FUNCPTR(f) typeof(f) * p##f
41 typedef struct _tagImmHkl{
42 struct list entry;
43 HKL hkl;
44 HMODULE hIME;
45 IMEINFO imeInfo;
46 WCHAR imeClassName[17]; /* 16 character max */
47 ULONG uSelected;
48 HWND UIWnd;
50 /* Function Pointers */
51 MAKE_FUNCPTR(ImeInquire);
52 MAKE_FUNCPTR(ImeConfigure);
53 MAKE_FUNCPTR(ImeDestroy);
54 MAKE_FUNCPTR(ImeEscape);
55 MAKE_FUNCPTR(ImeSelect);
56 MAKE_FUNCPTR(ImeSetActiveContext);
57 MAKE_FUNCPTR(ImeToAsciiEx);
58 MAKE_FUNCPTR(NotifyIME);
59 MAKE_FUNCPTR(ImeRegisterWord);
60 MAKE_FUNCPTR(ImeUnregisterWord);
61 MAKE_FUNCPTR(ImeEnumRegisterWord);
62 MAKE_FUNCPTR(ImeSetCompositionString);
63 MAKE_FUNCPTR(ImeConversionList);
64 MAKE_FUNCPTR(ImeProcessKey);
65 MAKE_FUNCPTR(ImeGetRegisterWordStyle);
66 MAKE_FUNCPTR(ImeGetImeMenuItems);
67 } ImmHkl;
68 #undef MAKE_FUNCPTR
70 typedef struct tagInputContextData
72 DWORD dwLock;
73 INPUTCONTEXT IMC;
75 ImmHkl *immKbd;
76 UINT lastVK;
77 DWORD magic;
78 } InputContextData;
80 #define WINE_IMC_VALID_MAGIC 0x56434D49
82 typedef struct _tagTRANSMSG {
83 UINT message;
84 WPARAM wParam;
85 LPARAM lParam;
86 } TRANSMSG, *LPTRANSMSG;
88 typedef struct _tagIMMThreadData {
89 HIMC defaultContext;
90 HWND hwndDefault;
91 } IMMThreadData;
93 static DWORD tlsIndex = 0;
94 static struct list ImmHklList = LIST_INIT(ImmHklList);
96 /* MSIME messages */
97 static UINT WM_MSIME_SERVICE;
98 static UINT WM_MSIME_RECONVERTOPTIONS;
99 static UINT WM_MSIME_MOUSE;
100 static UINT WM_MSIME_RECONVERTREQUEST;
101 static UINT WM_MSIME_RECONVERT;
102 static UINT WM_MSIME_QUERYPOSITION;
103 static UINT WM_MSIME_DOCUMENTFEED;
105 static const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
107 static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
108 static const WCHAR szLayoutTextW[] = {'L','a','y','o','u','t',' ','T','e','x','t',0};
109 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};
111 static const WCHAR szwIME[] = {'I','M','E',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 load_graphics_driver(void)
250 static const WCHAR display_device_guid_propW[] = {
251 '_','_','w','i','n','e','_','d','i','s','p','l','a','y','_',
252 'd','e','v','i','c','e','_','g','u','i','d',0 };
253 static const WCHAR key_pathW[] = {
254 'S','y','s','t','e','m','\\',
255 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
256 'C','o','n','t','r','o','l','\\',
257 'V','i','d','e','o','\\','{',0};
258 static const WCHAR displayW[] = {'}','\\','0','0','0','0',0};
259 static const WCHAR driverW[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0};
261 HMODULE ret = 0;
262 HKEY hkey;
263 DWORD size;
264 WCHAR path[MAX_PATH];
265 WCHAR key[(sizeof(key_pathW) + sizeof(displayW)) / sizeof(WCHAR) + 40];
266 UINT guid_atom = HandleToULong( GetPropW( GetDesktopWindow(), display_device_guid_propW ));
268 if (!guid_atom) return 0;
269 memcpy( key, key_pathW, sizeof(key_pathW) );
270 if (!GlobalGetAtomNameW( guid_atom, key + strlenW(key), 40 )) return 0;
271 strcatW( key, displayW );
272 if (RegOpenKeyW( HKEY_LOCAL_MACHINE, key, &hkey )) return 0;
273 size = sizeof(path);
274 if (!RegQueryValueExW( hkey, driverW, NULL, NULL, (BYTE *)path, &size )) ret = LoadLibraryW( path );
275 RegCloseKey( hkey );
276 TRACE( "%s %p\n", debugstr_w(path), ret );
277 return ret;
280 /* ImmHkl loading and freeing */
281 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
282 static ImmHkl *IMM_GetImmHkl(HKL hkl)
284 ImmHkl *ptr;
285 WCHAR filename[MAX_PATH];
287 TRACE("Seeking ime for keyboard %p\n",hkl);
289 LIST_FOR_EACH_ENTRY(ptr, &ImmHklList, ImmHkl, entry)
291 if (ptr->hkl == hkl)
292 return ptr;
294 /* not found... create it */
296 ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ImmHkl));
298 ptr->hkl = hkl;
299 if (ImmGetIMEFileNameW(hkl, filename, MAX_PATH)) ptr->hIME = LoadLibraryW(filename);
300 if (!ptr->hIME) ptr->hIME = load_graphics_driver();
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(void)
381 WNDCLASSW wndClass;
383 ZeroMemory(&wndClass, sizeof(WNDCLASSW));
385 wndClass.style = CS_GLOBALCLASS;
386 wndClass.lpfnWndProc = (WNDPROC) DefIME_WindowProc;
387 wndClass.cbWndExtra = 2 * sizeof(LONG_PTR);
388 wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
389 wndClass.lpszClassName = szwIME;
391 RegisterClassW(&wndClass);
394 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
396 TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
397 switch (fdwReason)
399 case DLL_PROCESS_ATTACH:
400 IMM_RegisterMessages();
401 tlsIndex = TlsAlloc();
402 if (tlsIndex == TLS_OUT_OF_INDEXES)
403 return FALSE;
404 IMM_RegisterIMEClass();
405 break;
406 case DLL_THREAD_ATTACH:
407 break;
408 case DLL_THREAD_DETACH:
409 IMM_FreeThreadData();
410 break;
411 case DLL_PROCESS_DETACH:
412 if (lpReserved) break;
413 IMM_FreeThreadData();
414 IMM_FreeAllImmHkl();
415 TlsFree(tlsIndex);
416 UnregisterClassW(szwIME, NULL);
417 break;
419 return TRUE;
422 /* for posting messages as the IME */
423 static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
425 HWND target = GetFocus();
426 if (!target)
427 PostMessageW(data->IMC.hWnd,msg,wParam,lParam);
428 else
429 PostMessageW(target, msg, wParam, lParam);
432 static LRESULT ImmInternalSendIMENotify(InputContextData *data, WPARAM notify, LPARAM lParam)
434 HWND target;
436 target = data->IMC.hWnd;
437 if (!target) target = GetFocus();
439 if (target)
440 return SendMessageW(target, WM_IME_NOTIFY, notify, lParam);
442 return 0;
445 static HIMCC ImmCreateBlankCompStr(void)
447 HIMCC rc;
448 LPCOMPOSITIONSTRING ptr;
449 rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
450 ptr = ImmLockIMCC(rc);
451 memset(ptr,0,sizeof(COMPOSITIONSTRING));
452 ptr->dwSize = sizeof(COMPOSITIONSTRING);
453 ImmUnlockIMCC(rc);
454 return rc;
457 static InputContextData* get_imc_data(HIMC hIMC)
459 InputContextData *data = hIMC;
461 if (hIMC == NULL)
462 return NULL;
464 if(IsBadReadPtr(data, sizeof(InputContextData)) || data->magic != WINE_IMC_VALID_MAGIC)
466 SetLastError(ERROR_INVALID_HANDLE);
467 return NULL;
469 return data;
472 /***********************************************************************
473 * ImmAssociateContext (IMM32.@)
475 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
477 HIMC old = NULL;
478 InputContextData *data = get_imc_data(hIMC);
480 TRACE("(%p, %p):\n", hWnd, hIMC);
482 if(hIMC && !data)
483 return NULL;
485 if (!IMM_GetThreadData()->defaultContext)
486 IMM_GetThreadData()->defaultContext = ImmCreateContext();
489 * If already associated just return
491 if (hIMC && data->IMC.hWnd == hWnd)
492 return hIMC;
494 if (hWnd)
496 old = RemovePropW(hWnd,szwWineIMCProperty);
498 if (old == NULL)
499 old = IMM_GetThreadData()->defaultContext;
500 else if (old == (HIMC)-1)
501 old = NULL;
503 if (hIMC != IMM_GetThreadData()->defaultContext)
505 if (hIMC == NULL) /* Meaning disable imm for that window*/
506 SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1);
507 else
508 SetPropW(hWnd,szwWineIMCProperty,hIMC);
511 if (old)
513 InputContextData *old_data = old;
514 if (old_data->IMC.hWnd == hWnd)
515 old_data->IMC.hWnd = NULL;
519 if (!hIMC)
520 return old;
522 if (IsWindow(data->IMC.hWnd))
525 * Post a message that your context is switching
527 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
530 data->IMC.hWnd = hWnd;
532 if (IsWindow(data->IMC.hWnd))
535 * Post a message that your context is switching
537 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
540 return old;
545 * Helper function for ImmAssociateContextEx
547 static BOOL CALLBACK _ImmAssociateContextExEnumProc(HWND hwnd, LPARAM lParam)
549 HIMC hImc = (HIMC)lParam;
550 ImmAssociateContext(hwnd,hImc);
551 return TRUE;
554 /***********************************************************************
555 * ImmAssociateContextEx (IMM32.@)
557 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
559 TRACE("(%p, %p, 0x%x):\n", hWnd, hIMC, dwFlags);
561 if (!IMM_GetThreadData()->defaultContext)
562 IMM_GetThreadData()->defaultContext = ImmCreateContext();
564 if (!hWnd) return FALSE;
566 switch (dwFlags)
568 case 0:
569 ImmAssociateContext(hWnd,hIMC);
570 return TRUE;
571 case IACE_DEFAULT:
572 ImmAssociateContext(hWnd,IMM_GetThreadData()->defaultContext);
573 return TRUE;
574 case IACE_IGNORENOCONTEXT:
575 if (GetPropW(hWnd,szwWineIMCProperty))
576 ImmAssociateContext(hWnd,hIMC);
577 return TRUE;
578 case IACE_CHILDREN:
579 EnumChildWindows(hWnd,_ImmAssociateContextExEnumProc,(LPARAM)hIMC);
580 return TRUE;
581 default:
582 FIXME("Unknown dwFlags 0x%x\n",dwFlags);
583 return FALSE;
587 /***********************************************************************
588 * ImmConfigureIMEA (IMM32.@)
590 BOOL WINAPI ImmConfigureIMEA(
591 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
593 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
595 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
597 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
598 return FALSE;
600 if (immHkl->hIME && immHkl->pImeConfigure)
602 if (dwMode != IME_CONFIG_REGISTERWORD || !is_kbd_ime_unicode(immHkl))
603 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
604 else
606 REGISTERWORDW rww;
607 REGISTERWORDA *rwa = lpData;
608 BOOL rc;
610 rww.lpReading = strdupAtoW(rwa->lpReading);
611 rww.lpWord = strdupAtoW(rwa->lpWord);
612 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rww);
613 HeapFree(GetProcessHeap(),0,rww.lpReading);
614 HeapFree(GetProcessHeap(),0,rww.lpWord);
615 return rc;
618 else
619 return FALSE;
622 /***********************************************************************
623 * ImmConfigureIMEW (IMM32.@)
625 BOOL WINAPI ImmConfigureIMEW(
626 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
628 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
630 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
632 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
633 return FALSE;
635 if (immHkl->hIME && immHkl->pImeConfigure)
637 if (dwMode != IME_CONFIG_REGISTERWORD || is_kbd_ime_unicode(immHkl))
638 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
639 else
641 REGISTERWORDW *rww = lpData;
642 REGISTERWORDA rwa;
643 BOOL rc;
645 rwa.lpReading = strdupWtoA(rww->lpReading);
646 rwa.lpWord = strdupWtoA(rww->lpWord);
647 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rwa);
648 HeapFree(GetProcessHeap(),0,rwa.lpReading);
649 HeapFree(GetProcessHeap(),0,rwa.lpWord);
650 return rc;
653 else
654 return FALSE;
657 /***********************************************************************
658 * ImmCreateContext (IMM32.@)
660 HIMC WINAPI ImmCreateContext(void)
662 InputContextData *new_context;
663 LPGUIDELINE gl;
664 LPCANDIDATEINFO ci;
665 int i;
667 new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
669 /* Load the IME */
670 new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0));
672 if (!new_context->immKbd->hIME)
674 TRACE("IME dll could not be loaded\n");
675 HeapFree(GetProcessHeap(),0,new_context);
676 return 0;
679 /* the HIMCCs are never NULL */
680 new_context->IMC.hCompStr = ImmCreateBlankCompStr();
681 new_context->IMC.hMsgBuf = ImmCreateIMCC(0);
682 new_context->IMC.hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
683 ci = ImmLockIMCC(new_context->IMC.hCandInfo);
684 memset(ci,0,sizeof(CANDIDATEINFO));
685 ci->dwSize = sizeof(CANDIDATEINFO);
686 ImmUnlockIMCC(new_context->IMC.hCandInfo);
687 new_context->IMC.hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
688 gl = ImmLockIMCC(new_context->IMC.hGuideLine);
689 memset(gl,0,sizeof(GUIDELINE));
690 gl->dwSize = sizeof(GUIDELINE);
691 ImmUnlockIMCC(new_context->IMC.hGuideLine);
693 for (i = 0; i < sizeof(new_context->IMC.cfCandForm) / sizeof(CANDIDATEFORM); i++)
694 new_context->IMC.cfCandForm[i].dwIndex = ~0u;
696 /* Initialize the IME Private */
697 new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
699 if (!new_context->immKbd->pImeSelect(new_context, TRUE))
701 TRACE("Selection of IME failed\n");
702 IMM_DestroyContext(new_context);
703 return 0;
705 SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)GetKeyboardLayout(0));
707 new_context->immKbd->uSelected++;
708 TRACE("Created context %p\n",new_context);
710 new_context->magic = WINE_IMC_VALID_MAGIC;
711 return new_context;
714 static BOOL IMM_DestroyContext(HIMC hIMC)
716 InputContextData *data = get_imc_data(hIMC);
718 TRACE("Destroying %p\n",hIMC);
720 if (!data)
721 return FALSE;
723 data->immKbd->uSelected --;
724 data->immKbd->pImeSelect(hIMC, FALSE);
725 SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)GetKeyboardLayout(0));
727 ImmDestroyIMCC(data->IMC.hCompStr);
728 ImmDestroyIMCC(data->IMC.hCandInfo);
729 ImmDestroyIMCC(data->IMC.hGuideLine);
730 ImmDestroyIMCC(data->IMC.hPrivate);
731 ImmDestroyIMCC(data->IMC.hMsgBuf);
733 data->magic = 0;
734 HeapFree(GetProcessHeap(),0,data);
736 return TRUE;
739 /***********************************************************************
740 * ImmDestroyContext (IMM32.@)
742 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
744 if (hIMC != IMM_GetThreadData()->defaultContext)
745 return IMM_DestroyContext(hIMC);
746 else
747 return FALSE;
750 /***********************************************************************
751 * ImmDisableIME (IMM32.@)
753 BOOL WINAPI ImmDisableIME(DWORD idThread)
755 FIXME("(%d): stub\n", idThread);
756 return TRUE;
759 /***********************************************************************
760 * ImmEnumRegisterWordA (IMM32.@)
762 UINT WINAPI ImmEnumRegisterWordA(
763 HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
764 LPCSTR lpszReading, DWORD dwStyle,
765 LPCSTR lpszRegister, LPVOID lpData)
767 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
768 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
769 debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister), lpData);
770 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
772 if (!is_kbd_ime_unicode(immHkl))
773 return immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
774 (LPCWSTR)lpszReading, dwStyle, (LPCWSTR)lpszRegister, lpData);
775 else
777 LPWSTR lpszwReading = strdupAtoW(lpszReading);
778 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
779 BOOL rc;
781 rc = immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
782 lpszwReading, dwStyle, lpszwRegister,
783 lpData);
785 HeapFree(GetProcessHeap(),0,lpszwReading);
786 HeapFree(GetProcessHeap(),0,lpszwRegister);
787 return rc;
790 else
791 return 0;
794 /***********************************************************************
795 * ImmEnumRegisterWordW (IMM32.@)
797 UINT WINAPI ImmEnumRegisterWordW(
798 HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
799 LPCWSTR lpszReading, DWORD dwStyle,
800 LPCWSTR lpszRegister, LPVOID lpData)
802 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
803 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
804 debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister), lpData);
805 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
807 if (is_kbd_ime_unicode(immHkl))
808 return immHkl->pImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
809 lpszRegister, lpData);
810 else
812 LPSTR lpszaReading = strdupWtoA(lpszReading);
813 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
814 BOOL rc;
816 rc = immHkl->pImeEnumRegisterWord(lpfnEnumProc, (LPCWSTR)lpszaReading,
817 dwStyle, (LPCWSTR)lpszaRegister, lpData);
819 HeapFree(GetProcessHeap(),0,lpszaReading);
820 HeapFree(GetProcessHeap(),0,lpszaRegister);
821 return rc;
824 else
825 return 0;
828 static inline BOOL EscapeRequiresWA(UINT uEscape)
830 if (uEscape == IME_ESC_GET_EUDC_DICTIONARY ||
831 uEscape == IME_ESC_SET_EUDC_DICTIONARY ||
832 uEscape == IME_ESC_IME_NAME ||
833 uEscape == IME_ESC_GETHELPFILENAME)
834 return TRUE;
835 return FALSE;
838 /***********************************************************************
839 * ImmEscapeA (IMM32.@)
841 LRESULT WINAPI ImmEscapeA(
842 HKL hKL, HIMC hIMC,
843 UINT uEscape, LPVOID lpData)
845 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
846 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
848 if (immHkl->hIME && immHkl->pImeEscape)
850 if (!EscapeRequiresWA(uEscape) || !is_kbd_ime_unicode(immHkl))
851 return immHkl->pImeEscape(hIMC,uEscape,lpData);
852 else
854 WCHAR buffer[81]; /* largest required buffer should be 80 */
855 LRESULT rc;
856 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
858 MultiByteToWideChar(CP_ACP,0,lpData,-1,buffer,81);
859 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
861 else
863 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
864 WideCharToMultiByte(CP_ACP,0,buffer,-1,lpData,80, NULL, NULL);
866 return rc;
869 else
870 return 0;
873 /***********************************************************************
874 * ImmEscapeW (IMM32.@)
876 LRESULT WINAPI ImmEscapeW(
877 HKL hKL, HIMC hIMC,
878 UINT uEscape, LPVOID lpData)
880 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
881 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
883 if (immHkl->hIME && immHkl->pImeEscape)
885 if (!EscapeRequiresWA(uEscape) || is_kbd_ime_unicode(immHkl))
886 return immHkl->pImeEscape(hIMC,uEscape,lpData);
887 else
889 CHAR buffer[81]; /* largest required buffer should be 80 */
890 LRESULT rc;
891 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
893 WideCharToMultiByte(CP_ACP,0,lpData,-1,buffer,81, NULL, NULL);
894 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
896 else
898 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
899 MultiByteToWideChar(CP_ACP,0,buffer,-1,lpData,80);
901 return rc;
904 else
905 return 0;
908 /***********************************************************************
909 * ImmGetCandidateListA (IMM32.@)
911 DWORD WINAPI ImmGetCandidateListA(
912 HIMC hIMC, DWORD dwIndex,
913 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
915 InputContextData *data = get_imc_data(hIMC);
916 LPCANDIDATEINFO candinfo;
917 LPCANDIDATELIST candlist;
918 DWORD ret = 0;
920 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
922 if (!data || !data->IMC.hCandInfo)
923 return 0;
925 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
926 if ( dwIndex >= candinfo->dwCount ||
927 dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
928 goto done;
930 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
931 if ( !candlist->dwSize || !candlist->dwCount )
932 goto done;
934 if ( !is_himc_ime_unicode(data) )
936 ret = candlist->dwSize;
937 if ( lpCandList && dwBufLen >= ret )
938 memcpy(lpCandList, candlist, ret);
940 else
941 ret = convert_candidatelist_WtoA( candlist, lpCandList, dwBufLen);
943 done:
944 ImmUnlockIMCC(data->IMC.hCandInfo);
945 return ret;
948 /***********************************************************************
949 * ImmGetCandidateListCountA (IMM32.@)
951 DWORD WINAPI ImmGetCandidateListCountA(
952 HIMC hIMC, LPDWORD lpdwListCount)
954 InputContextData *data = get_imc_data(hIMC);
955 LPCANDIDATEINFO candinfo;
956 DWORD ret, count;
958 TRACE("%p, %p\n", hIMC, lpdwListCount);
960 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
961 return 0;
963 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
965 *lpdwListCount = count = candinfo->dwCount;
967 if ( !is_himc_ime_unicode(data) )
968 ret = candinfo->dwSize;
969 else
971 ret = sizeof(CANDIDATEINFO);
972 while ( count-- )
973 ret += ImmGetCandidateListA(hIMC, count, NULL, 0);
976 ImmUnlockIMCC(data->IMC.hCandInfo);
977 return ret;
980 /***********************************************************************
981 * ImmGetCandidateListCountW (IMM32.@)
983 DWORD WINAPI ImmGetCandidateListCountW(
984 HIMC hIMC, LPDWORD lpdwListCount)
986 InputContextData *data = get_imc_data(hIMC);
987 LPCANDIDATEINFO candinfo;
988 DWORD ret, count;
990 TRACE("%p, %p\n", hIMC, lpdwListCount);
992 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
993 return 0;
995 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
997 *lpdwListCount = count = candinfo->dwCount;
999 if ( is_himc_ime_unicode(data) )
1000 ret = candinfo->dwSize;
1001 else
1003 ret = sizeof(CANDIDATEINFO);
1004 while ( count-- )
1005 ret += ImmGetCandidateListW(hIMC, count, NULL, 0);
1008 ImmUnlockIMCC(data->IMC.hCandInfo);
1009 return ret;
1012 /***********************************************************************
1013 * ImmGetCandidateListW (IMM32.@)
1015 DWORD WINAPI ImmGetCandidateListW(
1016 HIMC hIMC, DWORD dwIndex,
1017 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
1019 InputContextData *data = get_imc_data(hIMC);
1020 LPCANDIDATEINFO candinfo;
1021 LPCANDIDATELIST candlist;
1022 DWORD ret = 0;
1024 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
1026 if (!data || !data->IMC.hCandInfo)
1027 return 0;
1029 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
1030 if ( dwIndex >= candinfo->dwCount ||
1031 dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
1032 goto done;
1034 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
1035 if ( !candlist->dwSize || !candlist->dwCount )
1036 goto done;
1038 if ( is_himc_ime_unicode(data) )
1040 ret = candlist->dwSize;
1041 if ( lpCandList && dwBufLen >= ret )
1042 memcpy(lpCandList, candlist, ret);
1044 else
1045 ret = convert_candidatelist_AtoW( candlist, lpCandList, dwBufLen);
1047 done:
1048 ImmUnlockIMCC(data->IMC.hCandInfo);
1049 return ret;
1052 /***********************************************************************
1053 * ImmGetCandidateWindow (IMM32.@)
1055 BOOL WINAPI ImmGetCandidateWindow(
1056 HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
1058 InputContextData *data = get_imc_data(hIMC);
1060 TRACE("%p, %d, %p\n", hIMC, dwIndex, lpCandidate);
1062 if (!data || !lpCandidate)
1063 return FALSE;
1065 if ( dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
1066 return FALSE;
1068 if (data->IMC.cfCandForm[dwIndex].dwIndex != dwIndex)
1069 return FALSE;
1071 *lpCandidate = data->IMC.cfCandForm[dwIndex];
1073 return TRUE;
1076 /***********************************************************************
1077 * ImmGetCompositionFontA (IMM32.@)
1079 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1081 LOGFONTW lfW;
1082 BOOL rc;
1084 TRACE("(%p, %p):\n", hIMC, lplf);
1086 rc = ImmGetCompositionFontW(hIMC,&lfW);
1087 if (!rc || !lplf)
1088 return FALSE;
1090 memcpy(lplf,&lfW,sizeof(LOGFONTA));
1091 WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName,
1092 LF_FACESIZE, NULL, NULL);
1093 return TRUE;
1096 /***********************************************************************
1097 * ImmGetCompositionFontW (IMM32.@)
1099 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1101 InputContextData *data = get_imc_data(hIMC);
1103 TRACE("(%p, %p):\n", hIMC, lplf);
1105 if (!data || !lplf)
1106 return FALSE;
1108 *lplf = data->IMC.lfFont.W;
1110 return TRUE;
1114 /* Helpers for the GetCompositionString functions */
1116 static INT CopyCompStringIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE target, INT tlen,
1117 BOOL unicode )
1119 INT rc;
1121 if (is_himc_ime_unicode(data) && !unicode)
1122 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)source, slen, (LPSTR)target, tlen, NULL, NULL);
1123 else if (!is_himc_ime_unicode(data) && unicode)
1124 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)source, slen, (LPWSTR)target, tlen) * sizeof(WCHAR);
1125 else
1127 int dlen = (unicode)?sizeof(WCHAR):sizeof(CHAR);
1128 memcpy( target, source, min(slen,tlen)*dlen);
1129 rc = slen*dlen;
1132 return rc;
1135 static INT CopyCompAttrIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen,
1136 LPBYTE target, INT tlen, BOOL unicode )
1138 INT rc;
1140 if (is_himc_ime_unicode(data) && !unicode)
1142 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, sslen, NULL, 0, NULL, NULL);
1143 if (tlen)
1145 const BYTE *src = source;
1146 LPBYTE dst = target;
1147 int i, j = 0, k = 0;
1149 if (rc < tlen)
1150 tlen = rc;
1151 for (i = 0; i < sslen; ++i)
1153 int len;
1155 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)ssource + i, 1,
1156 NULL, 0, NULL, NULL);
1157 for (; len > 0; --len)
1159 dst[j++] = src[k];
1161 if (j >= tlen)
1162 goto end;
1164 ++k;
1166 end:
1167 rc = j;
1170 else if (!is_himc_ime_unicode(data) && unicode)
1172 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, sslen, NULL, 0);
1173 if (tlen)
1175 const BYTE *src = source;
1176 LPBYTE dst = target;
1177 int i, j = 0;
1179 if (rc < tlen)
1180 tlen = rc;
1181 for (i = 0; i < sslen; ++i)
1183 if (IsDBCSLeadByte(((LPSTR)ssource)[i]))
1184 continue;
1186 dst[j++] = src[i];
1188 if (j >= tlen)
1189 break;
1191 rc = j;
1194 else
1196 memcpy( target, source, min(slen,tlen));
1197 rc = slen;
1200 return rc;
1203 static INT CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource,
1204 LPBYTE target, INT tlen, BOOL unicode )
1206 INT rc;
1208 if (is_himc_ime_unicode(data) && !unicode)
1210 if (tlen)
1212 int i;
1214 if (slen < tlen)
1215 tlen = slen;
1216 tlen /= sizeof (DWORD);
1217 for (i = 0; i < tlen; ++i)
1219 ((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource,
1220 ((DWORD *)source)[i],
1221 NULL, 0,
1222 NULL, NULL);
1224 rc = sizeof (DWORD) * i;
1226 else
1227 rc = slen;
1229 else if (!is_himc_ime_unicode(data) && unicode)
1231 if (tlen)
1233 int i;
1235 if (slen < tlen)
1236 tlen = slen;
1237 tlen /= sizeof (DWORD);
1238 for (i = 0; i < tlen; ++i)
1240 ((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource,
1241 ((DWORD *)source)[i],
1242 NULL, 0);
1244 rc = sizeof (DWORD) * i;
1246 else
1247 rc = slen;
1249 else
1251 memcpy( target, source, min(slen,tlen));
1252 rc = slen;
1255 return rc;
1258 static INT CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE ssource, BOOL unicode)
1260 int rc;
1262 if (is_himc_ime_unicode(data) && !unicode)
1264 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, NULL, NULL);
1266 else if (!is_himc_ime_unicode(data) && unicode)
1268 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0);
1270 else
1271 rc = offset;
1273 return rc;
1276 static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf,
1277 DWORD dwBufLen, BOOL unicode)
1279 LONG rc = 0;
1280 InputContextData *data = get_imc_data(hIMC);
1281 LPCOMPOSITIONSTRING compstr;
1282 LPBYTE compdata;
1284 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
1286 if (!data)
1287 return FALSE;
1289 if (!data->IMC.hCompStr)
1290 return FALSE;
1292 compdata = ImmLockIMCC(data->IMC.hCompStr);
1293 compstr = (LPCOMPOSITIONSTRING)compdata;
1295 switch (dwIndex)
1297 case GCS_RESULTSTR:
1298 TRACE("GCS_RESULTSTR\n");
1299 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, lpBuf, dwBufLen, unicode);
1300 break;
1301 case GCS_COMPSTR:
1302 TRACE("GCS_COMPSTR\n");
1303 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, lpBuf, dwBufLen, unicode);
1304 break;
1305 case GCS_COMPATTR:
1306 TRACE("GCS_COMPATTR\n");
1307 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompAttrOffset, compstr->dwCompAttrLen,
1308 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1309 lpBuf, dwBufLen, unicode);
1310 break;
1311 case GCS_COMPCLAUSE:
1312 TRACE("GCS_COMPCLAUSE\n");
1313 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompClauseOffset,compstr->dwCompClauseLen,
1314 compdata + compstr->dwCompStrOffset,
1315 lpBuf, dwBufLen, unicode);
1316 break;
1317 case GCS_RESULTCLAUSE:
1318 TRACE("GCS_RESULTCLAUSE\n");
1319 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen,
1320 compdata + compstr->dwResultStrOffset,
1321 lpBuf, dwBufLen, unicode);
1322 break;
1323 case GCS_RESULTREADSTR:
1324 TRACE("GCS_RESULTREADSTR\n");
1325 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultReadStrOffset, compstr->dwResultReadStrLen, lpBuf, dwBufLen, unicode);
1326 break;
1327 case GCS_RESULTREADCLAUSE:
1328 TRACE("GCS_RESULTREADCLAUSE\n");
1329 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultReadClauseOffset,compstr->dwResultReadClauseLen,
1330 compdata + compstr->dwResultStrOffset,
1331 lpBuf, dwBufLen, unicode);
1332 break;
1333 case GCS_COMPREADSTR:
1334 TRACE("GCS_COMPREADSTR\n");
1335 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, lpBuf, dwBufLen, unicode);
1336 break;
1337 case GCS_COMPREADATTR:
1338 TRACE("GCS_COMPREADATTR\n");
1339 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompReadAttrOffset, compstr->dwCompReadAttrLen,
1340 compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen,
1341 lpBuf, dwBufLen, unicode);
1342 break;
1343 case GCS_COMPREADCLAUSE:
1344 TRACE("GCS_COMPREADCLAUSE\n");
1345 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompReadClauseOffset,compstr->dwCompReadClauseLen,
1346 compdata + compstr->dwCompStrOffset,
1347 lpBuf, dwBufLen, unicode);
1348 break;
1349 case GCS_CURSORPOS:
1350 TRACE("GCS_CURSORPOS\n");
1351 rc = CopyCompOffsetIMEtoClient(data, compstr->dwCursorPos, compdata + compstr->dwCompStrOffset, unicode);
1352 break;
1353 case GCS_DELTASTART:
1354 TRACE("GCS_DELTASTART\n");
1355 rc = CopyCompOffsetIMEtoClient(data, compstr->dwDeltaStart, compdata + compstr->dwCompStrOffset, unicode);
1356 break;
1357 default:
1358 FIXME("Unhandled index 0x%x\n",dwIndex);
1359 break;
1362 ImmUnlockIMCC(data->IMC.hCompStr);
1364 return rc;
1367 /***********************************************************************
1368 * ImmGetCompositionStringA (IMM32.@)
1370 LONG WINAPI ImmGetCompositionStringA(
1371 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
1373 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
1377 /***********************************************************************
1378 * ImmGetCompositionStringW (IMM32.@)
1380 LONG WINAPI ImmGetCompositionStringW(
1381 HIMC hIMC, DWORD dwIndex,
1382 LPVOID lpBuf, DWORD dwBufLen)
1384 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
1387 /***********************************************************************
1388 * ImmGetCompositionWindow (IMM32.@)
1390 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1392 InputContextData *data = get_imc_data(hIMC);
1394 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1396 if (!data)
1397 return FALSE;
1399 *lpCompForm = data->IMC.cfCompForm;
1400 return 1;
1403 /***********************************************************************
1404 * ImmGetContext (IMM32.@)
1407 HIMC WINAPI ImmGetContext(HWND hWnd)
1409 HIMC rc;
1411 TRACE("%p\n", hWnd);
1413 if (!IsWindow(hWnd))
1415 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
1416 return NULL;
1418 if (!IMM_GetThreadData()->defaultContext)
1419 IMM_GetThreadData()->defaultContext = ImmCreateContext();
1421 rc = GetPropW(hWnd,szwWineIMCProperty);
1422 if (rc == (HIMC)-1)
1423 rc = NULL;
1424 else if (rc == NULL)
1425 rc = IMM_GetThreadData()->defaultContext;
1427 if (rc)
1429 InputContextData *data = rc;
1430 data->IMC.hWnd = hWnd;
1432 TRACE("returning %p\n", rc);
1434 return rc;
1437 /***********************************************************************
1438 * ImmGetConversionListA (IMM32.@)
1440 DWORD WINAPI ImmGetConversionListA(
1441 HKL hKL, HIMC hIMC,
1442 LPCSTR pSrc, LPCANDIDATELIST lpDst,
1443 DWORD dwBufLen, UINT uFlag)
1445 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1446 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_a(pSrc), lpDst,
1447 dwBufLen, uFlag);
1448 if (immHkl->hIME && immHkl->pImeConversionList)
1450 if (!is_kbd_ime_unicode(immHkl))
1451 return immHkl->pImeConversionList(hIMC,(LPCWSTR)pSrc,lpDst,dwBufLen,uFlag);
1452 else
1454 LPCANDIDATELIST lpwDst;
1455 DWORD ret = 0, len;
1456 LPWSTR pwSrc = strdupAtoW(pSrc);
1458 len = immHkl->pImeConversionList(hIMC, pwSrc, NULL, 0, uFlag);
1459 lpwDst = HeapAlloc(GetProcessHeap(), 0, len);
1460 if ( lpwDst )
1462 immHkl->pImeConversionList(hIMC, pwSrc, lpwDst, len, uFlag);
1463 ret = convert_candidatelist_WtoA( lpwDst, lpDst, dwBufLen);
1464 HeapFree(GetProcessHeap(), 0, lpwDst);
1466 HeapFree(GetProcessHeap(), 0, pwSrc);
1468 return ret;
1471 else
1472 return 0;
1475 /***********************************************************************
1476 * ImmGetConversionListW (IMM32.@)
1478 DWORD WINAPI ImmGetConversionListW(
1479 HKL hKL, HIMC hIMC,
1480 LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1481 DWORD dwBufLen, UINT uFlag)
1483 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1484 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_w(pSrc), lpDst,
1485 dwBufLen, uFlag);
1486 if (immHkl->hIME && immHkl->pImeConversionList)
1488 if (is_kbd_ime_unicode(immHkl))
1489 return immHkl->pImeConversionList(hIMC,pSrc,lpDst,dwBufLen,uFlag);
1490 else
1492 LPCANDIDATELIST lpaDst;
1493 DWORD ret = 0, len;
1494 LPSTR paSrc = strdupWtoA(pSrc);
1496 len = immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, NULL, 0, uFlag);
1497 lpaDst = HeapAlloc(GetProcessHeap(), 0, len);
1498 if ( lpaDst )
1500 immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, lpaDst, len, uFlag);
1501 ret = convert_candidatelist_AtoW( lpaDst, lpDst, dwBufLen);
1502 HeapFree(GetProcessHeap(), 0, lpaDst);
1504 HeapFree(GetProcessHeap(), 0, paSrc);
1506 return ret;
1509 else
1510 return 0;
1513 /***********************************************************************
1514 * ImmGetConversionStatus (IMM32.@)
1516 BOOL WINAPI ImmGetConversionStatus(
1517 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1519 InputContextData *data = get_imc_data(hIMC);
1521 TRACE("%p %p %p\n", hIMC, lpfdwConversion, lpfdwSentence);
1523 if (!data)
1524 return FALSE;
1526 if (lpfdwConversion)
1527 *lpfdwConversion = data->IMC.fdwConversion;
1528 if (lpfdwSentence)
1529 *lpfdwSentence = data->IMC.fdwSentence;
1531 return TRUE;
1534 /***********************************************************************
1535 * ImmGetDefaultIMEWnd (IMM32.@)
1537 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1539 if (IMM_GetThreadData()->hwndDefault == NULL)
1540 IMM_GetThreadData()->hwndDefault = CreateWindowExW( WS_EX_TOOLWINDOW,
1541 szwIME, NULL, WS_POPUP, 0, 0, 1, 1, 0, 0, 0, 0);
1542 TRACE("Default is %p\n",IMM_GetThreadData()->hwndDefault);
1543 return IMM_GetThreadData()->hwndDefault;
1546 /***********************************************************************
1547 * ImmGetDescriptionA (IMM32.@)
1549 UINT WINAPI ImmGetDescriptionA(
1550 HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1552 WCHAR *buf;
1553 DWORD len;
1555 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1557 /* find out how many characters in the unicode buffer */
1558 len = ImmGetDescriptionW( hKL, NULL, 0 );
1559 if (!len)
1560 return 0;
1562 /* allocate a buffer of that size */
1563 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1564 if( !buf )
1565 return 0;
1567 /* fetch the unicode buffer */
1568 len = ImmGetDescriptionW( hKL, buf, len + 1 );
1570 /* convert it back to ASCII */
1571 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1572 lpszDescription, uBufLen, NULL, NULL );
1574 HeapFree( GetProcessHeap(), 0, buf );
1576 if (len == 0)
1577 return 0;
1579 return len - 1;
1582 /***********************************************************************
1583 * ImmGetDescriptionW (IMM32.@)
1585 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1587 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1589 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1591 if (!hKL) return 0;
1592 if (!uBufLen) return lstrlenW( name );
1593 lstrcpynW( lpszDescription, name, uBufLen );
1594 return lstrlenW( lpszDescription );
1597 /***********************************************************************
1598 * ImmGetGuideLineA (IMM32.@)
1600 DWORD WINAPI ImmGetGuideLineA(
1601 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1603 FIXME("(%p, %d, %s, %d): stub\n",
1604 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1606 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1607 return 0;
1610 /***********************************************************************
1611 * ImmGetGuideLineW (IMM32.@)
1613 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1615 FIXME("(%p, %d, %s, %d): stub\n",
1616 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1618 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1619 return 0;
1622 /***********************************************************************
1623 * ImmGetIMEFileNameA (IMM32.@)
1625 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1627 LPWSTR bufW = NULL;
1628 UINT wBufLen = uBufLen;
1629 UINT rc;
1631 if (uBufLen && lpszFileName)
1632 bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR));
1633 else /* We need this to get the number of byte required */
1635 bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR));
1636 wBufLen = MAX_PATH;
1639 rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen);
1641 if (rc > 0)
1643 if (uBufLen && lpszFileName)
1644 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName,
1645 uBufLen, NULL, NULL);
1646 else /* get the length */
1647 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL,
1648 NULL);
1651 HeapFree(GetProcessHeap(),0,bufW);
1652 return rc;
1655 /***********************************************************************
1656 * ImmGetIMEFileNameW (IMM32.@)
1658 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1660 HKEY hkey;
1661 DWORD length;
1662 DWORD rc;
1663 WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
1665 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hKL );
1666 rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey);
1667 if (rc != ERROR_SUCCESS)
1669 SetLastError(rc);
1670 return 0;
1673 length = 0;
1674 rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length);
1676 if (rc != ERROR_SUCCESS)
1678 RegCloseKey(hkey);
1679 SetLastError(rc);
1680 return 0;
1682 if (length > uBufLen * sizeof(WCHAR) || !lpszFileName)
1684 RegCloseKey(hkey);
1685 if (lpszFileName)
1687 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1688 return 0;
1690 else
1691 return length / sizeof(WCHAR);
1694 RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length);
1696 RegCloseKey(hkey);
1698 return length / sizeof(WCHAR);
1701 /***********************************************************************
1702 * ImmGetOpenStatus (IMM32.@)
1704 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1706 InputContextData *data = get_imc_data(hIMC);
1707 static int i;
1709 if (!data)
1710 return FALSE;
1712 TRACE("(%p): semi-stub\n", hIMC);
1714 if (!i++)
1715 FIXME("(%p): semi-stub\n", hIMC);
1717 return data->IMC.fOpen;
1720 /***********************************************************************
1721 * ImmGetProperty (IMM32.@)
1723 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1725 DWORD rc = 0;
1726 ImmHkl *kbd;
1728 TRACE("(%p, %d)\n", hKL, fdwIndex);
1729 kbd = IMM_GetImmHkl(hKL);
1731 if (kbd && kbd->hIME)
1733 switch (fdwIndex)
1735 case IGP_PROPERTY: rc = kbd->imeInfo.fdwProperty; break;
1736 case IGP_CONVERSION: rc = kbd->imeInfo.fdwConversionCaps; break;
1737 case IGP_SENTENCE: rc = kbd->imeInfo.fdwSentenceCaps; break;
1738 case IGP_SETCOMPSTR: rc = kbd->imeInfo.fdwSCSCaps; break;
1739 case IGP_SELECT: rc = kbd->imeInfo.fdwSelectCaps; break;
1740 case IGP_GETIMEVERSION: rc = IMEVER_0400; break;
1741 case IGP_UI: rc = 0; break;
1742 default: rc = 0;
1745 return rc;
1748 /***********************************************************************
1749 * ImmGetRegisterWordStyleA (IMM32.@)
1751 UINT WINAPI ImmGetRegisterWordStyleA(
1752 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1754 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1755 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1756 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1758 if (!is_kbd_ime_unicode(immHkl))
1759 return immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)lpStyleBuf);
1760 else
1762 STYLEBUFW sbw;
1763 UINT rc;
1765 rc = immHkl->pImeGetRegisterWordStyle(nItem,&sbw);
1766 WideCharToMultiByte(CP_ACP, 0, sbw.szDescription, -1,
1767 lpStyleBuf->szDescription, 32, NULL, NULL);
1768 lpStyleBuf->dwStyle = sbw.dwStyle;
1769 return rc;
1772 else
1773 return 0;
1776 /***********************************************************************
1777 * ImmGetRegisterWordStyleW (IMM32.@)
1779 UINT WINAPI ImmGetRegisterWordStyleW(
1780 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1782 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1783 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1784 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1786 if (is_kbd_ime_unicode(immHkl))
1787 return immHkl->pImeGetRegisterWordStyle(nItem,lpStyleBuf);
1788 else
1790 STYLEBUFA sba;
1791 UINT rc;
1793 rc = immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)&sba);
1794 MultiByteToWideChar(CP_ACP, 0, sba.szDescription, -1,
1795 lpStyleBuf->szDescription, 32);
1796 lpStyleBuf->dwStyle = sba.dwStyle;
1797 return rc;
1800 else
1801 return 0;
1804 /***********************************************************************
1805 * ImmGetStatusWindowPos (IMM32.@)
1807 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1809 InputContextData *data = get_imc_data(hIMC);
1811 TRACE("(%p, %p)\n", hIMC, lpptPos);
1813 if (!data || !lpptPos)
1814 return FALSE;
1816 *lpptPos = data->IMC.ptStatusWndPos;
1818 return TRUE;
1821 /***********************************************************************
1822 * ImmGetVirtualKey (IMM32.@)
1824 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1826 OSVERSIONINFOA version;
1827 InputContextData *data = ImmGetContext( hWnd );
1828 TRACE("%p\n", hWnd);
1830 if ( data )
1831 return data->lastVK;
1833 version.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
1834 GetVersionExA( &version );
1835 switch(version.dwPlatformId)
1837 case VER_PLATFORM_WIN32_WINDOWS:
1838 return VK_PROCESSKEY;
1839 case VER_PLATFORM_WIN32_NT:
1840 return 0;
1841 default:
1842 FIXME("%d not supported\n",version.dwPlatformId);
1843 return VK_PROCESSKEY;
1847 /***********************************************************************
1848 * ImmInstallIMEA (IMM32.@)
1850 HKL WINAPI ImmInstallIMEA(
1851 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1853 LPWSTR lpszwIMEFileName;
1854 LPWSTR lpszwLayoutText;
1855 HKL hkl;
1857 TRACE ("(%s, %s)\n", debugstr_a(lpszIMEFileName),
1858 debugstr_a(lpszLayoutText));
1860 lpszwIMEFileName = strdupAtoW(lpszIMEFileName);
1861 lpszwLayoutText = strdupAtoW(lpszLayoutText);
1863 hkl = ImmInstallIMEW(lpszwIMEFileName, lpszwLayoutText);
1865 HeapFree(GetProcessHeap(),0,lpszwIMEFileName);
1866 HeapFree(GetProcessHeap(),0,lpszwLayoutText);
1867 return hkl;
1870 /***********************************************************************
1871 * ImmInstallIMEW (IMM32.@)
1873 HKL WINAPI ImmInstallIMEW(
1874 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1876 INT lcid = GetUserDefaultLCID();
1877 INT count;
1878 HKL hkl;
1879 DWORD rc;
1880 HKEY hkey;
1881 WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
1883 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName),
1884 debugstr_w(lpszLayoutText));
1886 /* Start with 2. e001 will be blank and so default to the wine internal IME */
1887 count = 2;
1889 while (count < 0xfff)
1891 DWORD disposition = 0;
1893 hkl = (HKL)MAKELPARAM( lcid, 0xe000 | count );
1894 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hkl);
1896 rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &disposition);
1897 if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
1898 break;
1899 else if (rc == ERROR_SUCCESS)
1900 RegCloseKey(hkey);
1902 count++;
1905 if (count == 0xfff)
1907 WARN("Unable to find slot to install IME\n");
1908 return 0;
1911 if (rc == ERROR_SUCCESS)
1913 rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (const BYTE*)lpszIMEFileName,
1914 (lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR));
1915 if (rc == ERROR_SUCCESS)
1916 rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (const BYTE*)lpszLayoutText,
1917 (lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR));
1918 RegCloseKey(hkey);
1919 return hkl;
1921 else
1923 WARN("Unable to set IME registry values\n");
1924 return 0;
1928 /***********************************************************************
1929 * ImmIsIME (IMM32.@)
1931 BOOL WINAPI ImmIsIME(HKL hKL)
1933 ImmHkl *ptr;
1934 TRACE("(%p):\n", hKL);
1935 ptr = IMM_GetImmHkl(hKL);
1936 return (ptr && ptr->hIME);
1939 /***********************************************************************
1940 * ImmIsUIMessageA (IMM32.@)
1942 BOOL WINAPI ImmIsUIMessageA(
1943 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1945 BOOL rc = FALSE;
1947 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1948 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1949 (msg == WM_IME_SETCONTEXT) ||
1950 (msg == WM_IME_NOTIFY) ||
1951 (msg == WM_IME_COMPOSITIONFULL) ||
1952 (msg == WM_IME_SELECT) ||
1953 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */) ||
1954 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1955 (msg == WM_MSIME_MOUSE) ||
1956 (msg == WM_MSIME_RECONVERTREQUEST) ||
1957 (msg == WM_MSIME_RECONVERT) ||
1958 (msg == WM_MSIME_QUERYPOSITION) ||
1959 (msg == WM_MSIME_DOCUMENTFEED))
1961 if (hWndIME)
1962 SendMessageA(hWndIME, msg, wParam, lParam);
1964 rc = TRUE;
1966 return rc;
1969 /***********************************************************************
1970 * ImmIsUIMessageW (IMM32.@)
1972 BOOL WINAPI ImmIsUIMessageW(
1973 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1975 BOOL rc = FALSE;
1977 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1978 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1979 (msg == WM_IME_SETCONTEXT) ||
1980 (msg == WM_IME_NOTIFY) ||
1981 (msg == WM_IME_COMPOSITIONFULL) ||
1982 (msg == WM_IME_SELECT) ||
1983 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */) ||
1984 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1985 (msg == WM_MSIME_MOUSE) ||
1986 (msg == WM_MSIME_RECONVERTREQUEST) ||
1987 (msg == WM_MSIME_RECONVERT) ||
1988 (msg == WM_MSIME_QUERYPOSITION) ||
1989 (msg == WM_MSIME_DOCUMENTFEED))
1991 if (hWndIME)
1992 SendMessageW(hWndIME, msg, wParam, lParam);
1994 rc = TRUE;
1996 return rc;
1999 /***********************************************************************
2000 * ImmNotifyIME (IMM32.@)
2002 BOOL WINAPI ImmNotifyIME(
2003 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
2005 InputContextData *data = get_imc_data(hIMC);
2007 TRACE("(%p, %d, %d, %d)\n",
2008 hIMC, dwAction, dwIndex, dwValue);
2010 if (hIMC == NULL)
2012 SetLastError(ERROR_SUCCESS);
2013 return FALSE;
2016 if (!data || ! data->immKbd->pNotifyIME)
2018 return FALSE;
2021 return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue);
2024 /***********************************************************************
2025 * ImmRegisterWordA (IMM32.@)
2027 BOOL WINAPI ImmRegisterWordA(
2028 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
2030 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2031 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2032 debugstr_a(lpszRegister));
2033 if (immHkl->hIME && immHkl->pImeRegisterWord)
2035 if (!is_kbd_ime_unicode(immHkl))
2036 return immHkl->pImeRegisterWord((LPCWSTR)lpszReading,dwStyle,
2037 (LPCWSTR)lpszRegister);
2038 else
2040 LPWSTR lpszwReading = strdupAtoW(lpszReading);
2041 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
2042 BOOL rc;
2044 rc = immHkl->pImeRegisterWord(lpszwReading,dwStyle,lpszwRegister);
2045 HeapFree(GetProcessHeap(),0,lpszwReading);
2046 HeapFree(GetProcessHeap(),0,lpszwRegister);
2047 return rc;
2050 else
2051 return FALSE;
2054 /***********************************************************************
2055 * ImmRegisterWordW (IMM32.@)
2057 BOOL WINAPI ImmRegisterWordW(
2058 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
2060 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2061 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2062 debugstr_w(lpszRegister));
2063 if (immHkl->hIME && immHkl->pImeRegisterWord)
2065 if (is_kbd_ime_unicode(immHkl))
2066 return immHkl->pImeRegisterWord(lpszReading,dwStyle,lpszRegister);
2067 else
2069 LPSTR lpszaReading = strdupWtoA(lpszReading);
2070 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
2071 BOOL rc;
2073 rc = immHkl->pImeRegisterWord((LPCWSTR)lpszaReading,dwStyle,
2074 (LPCWSTR)lpszaRegister);
2075 HeapFree(GetProcessHeap(),0,lpszaReading);
2076 HeapFree(GetProcessHeap(),0,lpszaRegister);
2077 return rc;
2080 else
2081 return FALSE;
2084 /***********************************************************************
2085 * ImmReleaseContext (IMM32.@)
2087 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
2089 static int shown = 0;
2091 if (!shown) {
2092 FIXME("(%p, %p): stub\n", hWnd, hIMC);
2093 shown = 1;
2095 return TRUE;
2098 /***********************************************************************
2099 * ImmRequestMessageA(IMM32.@)
2101 LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2103 InputContextData *data = get_imc_data(hIMC);
2105 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2106 if (!data)
2107 SetLastError(ERROR_INVALID_HANDLE);
2109 if (data && IsWindow(data->IMC.hWnd))
2110 return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2112 return 0;
2115 /***********************************************************************
2116 * ImmRequestMessageW(IMM32.@)
2118 LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2120 InputContextData *data = get_imc_data(hIMC);
2122 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2124 if (!data)
2125 SetLastError(ERROR_INVALID_HANDLE);
2127 if (data && IsWindow(data->IMC.hWnd))
2128 return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2130 return 0;
2133 /***********************************************************************
2134 * ImmSetCandidateWindow (IMM32.@)
2136 BOOL WINAPI ImmSetCandidateWindow(
2137 HIMC hIMC, LPCANDIDATEFORM lpCandidate)
2139 InputContextData *data = get_imc_data(hIMC);
2141 TRACE("(%p, %p)\n", hIMC, lpCandidate);
2143 if (!data || !lpCandidate)
2144 return FALSE;
2146 TRACE("\t%x, %x, (%i,%i), (%i,%i - %i,%i)\n",
2147 lpCandidate->dwIndex, lpCandidate->dwStyle,
2148 lpCandidate->ptCurrentPos.x, lpCandidate->ptCurrentPos.y,
2149 lpCandidate->rcArea.top, lpCandidate->rcArea.left,
2150 lpCandidate->rcArea.bottom, lpCandidate->rcArea.right);
2152 if ( lpCandidate->dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
2153 return FALSE;
2155 data->IMC.cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
2156 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS);
2157 ImmInternalSendIMENotify(data, IMN_SETCANDIDATEPOS, 1 << lpCandidate->dwIndex);
2159 return TRUE;
2162 /***********************************************************************
2163 * ImmSetCompositionFontA (IMM32.@)
2165 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
2167 InputContextData *data = get_imc_data(hIMC);
2168 TRACE("(%p, %p)\n", hIMC, lplf);
2170 if (!data || !lplf)
2172 SetLastError(ERROR_INVALID_HANDLE);
2173 return FALSE;
2176 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
2177 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
2178 LF_FACESIZE);
2179 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2180 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2182 return TRUE;
2185 /***********************************************************************
2186 * ImmSetCompositionFontW (IMM32.@)
2188 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
2190 InputContextData *data = get_imc_data(hIMC);
2191 TRACE("(%p, %p)\n", hIMC, lplf);
2193 if (!data || !lplf)
2195 SetLastError(ERROR_INVALID_HANDLE);
2196 return FALSE;
2199 data->IMC.lfFont.W = *lplf;
2200 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2201 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2203 return TRUE;
2206 /***********************************************************************
2207 * ImmSetCompositionStringA (IMM32.@)
2209 BOOL WINAPI ImmSetCompositionStringA(
2210 HIMC hIMC, DWORD dwIndex,
2211 LPCVOID lpComp, DWORD dwCompLen,
2212 LPCVOID lpRead, DWORD dwReadLen)
2214 DWORD comp_len;
2215 DWORD read_len;
2216 WCHAR *CompBuffer = NULL;
2217 WCHAR *ReadBuffer = NULL;
2218 BOOL rc;
2219 InputContextData *data = get_imc_data(hIMC);
2221 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2222 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2224 if (!data)
2225 return FALSE;
2227 if (!(dwIndex == SCS_SETSTR ||
2228 dwIndex == SCS_CHANGEATTR ||
2229 dwIndex == SCS_CHANGECLAUSE ||
2230 dwIndex == SCS_SETRECONVERTSTRING ||
2231 dwIndex == SCS_QUERYRECONVERTSTRING))
2232 return FALSE;
2234 if (!is_himc_ime_unicode(data))
2235 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2236 dwCompLen, lpRead, dwReadLen);
2238 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
2239 if (comp_len)
2241 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
2242 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
2245 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
2246 if (read_len)
2248 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
2249 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
2252 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
2253 ReadBuffer, read_len);
2255 HeapFree(GetProcessHeap(), 0, CompBuffer);
2256 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2258 return rc;
2261 /***********************************************************************
2262 * ImmSetCompositionStringW (IMM32.@)
2264 BOOL WINAPI ImmSetCompositionStringW(
2265 HIMC hIMC, DWORD dwIndex,
2266 LPCVOID lpComp, DWORD dwCompLen,
2267 LPCVOID lpRead, DWORD dwReadLen)
2269 DWORD comp_len;
2270 DWORD read_len;
2271 CHAR *CompBuffer = NULL;
2272 CHAR *ReadBuffer = NULL;
2273 BOOL rc;
2274 InputContextData *data = get_imc_data(hIMC);
2276 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2277 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2279 if (!data)
2280 return FALSE;
2282 if (!(dwIndex == SCS_SETSTR ||
2283 dwIndex == SCS_CHANGEATTR ||
2284 dwIndex == SCS_CHANGECLAUSE ||
2285 dwIndex == SCS_SETRECONVERTSTRING ||
2286 dwIndex == SCS_QUERYRECONVERTSTRING))
2287 return FALSE;
2289 if (is_himc_ime_unicode(data))
2290 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2291 dwCompLen, lpRead, dwReadLen);
2293 comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL,
2294 NULL);
2295 if (comp_len)
2297 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len);
2298 WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len,
2299 NULL, NULL);
2302 read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL,
2303 NULL);
2304 if (read_len)
2306 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len);
2307 WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len,
2308 NULL, NULL);
2311 rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len,
2312 ReadBuffer, read_len);
2314 HeapFree(GetProcessHeap(), 0, CompBuffer);
2315 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2317 return rc;
2320 /***********************************************************************
2321 * ImmSetCompositionWindow (IMM32.@)
2323 BOOL WINAPI ImmSetCompositionWindow(
2324 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
2326 BOOL reshow = FALSE;
2327 InputContextData *data = get_imc_data(hIMC);
2329 TRACE("(%p, %p)\n", hIMC, lpCompForm);
2330 TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
2331 lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
2332 lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
2334 if (!data)
2336 SetLastError(ERROR_INVALID_HANDLE);
2337 return FALSE;
2340 data->IMC.cfCompForm = *lpCompForm;
2342 if (IsWindowVisible(data->immKbd->UIWnd))
2344 reshow = TRUE;
2345 ShowWindow(data->immKbd->UIWnd,SW_HIDE);
2348 /* FIXME: this is a partial stub */
2350 if (reshow)
2351 ShowWindow(data->immKbd->UIWnd,SW_SHOWNOACTIVATE);
2353 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0);
2354 return TRUE;
2357 /***********************************************************************
2358 * ImmSetConversionStatus (IMM32.@)
2360 BOOL WINAPI ImmSetConversionStatus(
2361 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
2363 DWORD oldConversion, oldSentence;
2364 InputContextData *data = get_imc_data(hIMC);
2366 TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence);
2368 if (!data)
2370 SetLastError(ERROR_INVALID_HANDLE);
2371 return FALSE;
2374 if ( fdwConversion != data->IMC.fdwConversion )
2376 oldConversion = data->IMC.fdwConversion;
2377 data->IMC.fdwConversion = fdwConversion;
2378 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldConversion, IMC_SETCONVERSIONMODE);
2379 ImmInternalSendIMENotify(data, IMN_SETCONVERSIONMODE, 0);
2381 if ( fdwSentence != data->IMC.fdwSentence )
2383 oldSentence = data->IMC.fdwSentence;
2384 data->IMC.fdwSentence = fdwSentence;
2385 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldSentence, IMC_SETSENTENCEMODE);
2386 ImmInternalSendIMENotify(data, IMN_SETSENTENCEMODE, 0);
2389 return TRUE;
2392 /***********************************************************************
2393 * ImmSetOpenStatus (IMM32.@)
2395 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
2397 InputContextData *data = get_imc_data(hIMC);
2399 TRACE("%p %d\n", hIMC, fOpen);
2401 if (!data)
2403 SetLastError(ERROR_INVALID_HANDLE);
2404 return FALSE;
2407 if (data->immKbd->UIWnd == NULL)
2409 /* create the ime window */
2410 data->immKbd->UIWnd = CreateWindowExW( WS_EX_TOOLWINDOW,
2411 data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0,
2412 0, data->immKbd->hIME, 0);
2413 SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
2415 else if (fOpen)
2416 SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
2418 if (!fOpen != !data->IMC.fOpen)
2420 data->IMC.fOpen = fOpen;
2421 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS);
2422 ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0);
2425 return TRUE;
2428 /***********************************************************************
2429 * ImmSetStatusWindowPos (IMM32.@)
2431 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
2433 InputContextData *data = get_imc_data(hIMC);
2435 TRACE("(%p, %p)\n", hIMC, lpptPos);
2437 if (!data || !lpptPos)
2439 SetLastError(ERROR_INVALID_HANDLE);
2440 return FALSE;
2443 TRACE("\t(%i,%i)\n", lpptPos->x, lpptPos->y);
2445 data->IMC.ptStatusWndPos = *lpptPos;
2446 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETSTATUSWINDOWPOS);
2447 ImmInternalSendIMENotify(data, IMN_SETSTATUSWINDOWPOS, 0);
2449 return TRUE;
2452 /***********************************************************************
2453 * ImmCreateSoftKeyboard(IMM32.@)
2455 HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y)
2457 FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y);
2458 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2459 return 0;
2462 /***********************************************************************
2463 * ImmDestroySoftKeyboard(IMM32.@)
2465 BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd)
2467 FIXME("(%p): stub\n", hSoftWnd);
2468 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2469 return FALSE;
2472 /***********************************************************************
2473 * ImmShowSoftKeyboard(IMM32.@)
2475 BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow)
2477 FIXME("(%p, %d): stub\n", hSoftWnd, nCmdShow);
2478 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2479 return FALSE;
2482 /***********************************************************************
2483 * ImmSimulateHotKey (IMM32.@)
2485 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
2487 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
2488 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2489 return FALSE;
2492 /***********************************************************************
2493 * ImmUnregisterWordA (IMM32.@)
2495 BOOL WINAPI ImmUnregisterWordA(
2496 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
2498 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2499 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2500 debugstr_a(lpszUnregister));
2501 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2503 if (!is_kbd_ime_unicode(immHkl))
2504 return immHkl->pImeUnregisterWord((LPCWSTR)lpszReading,dwStyle,
2505 (LPCWSTR)lpszUnregister);
2506 else
2508 LPWSTR lpszwReading = strdupAtoW(lpszReading);
2509 LPWSTR lpszwUnregister = strdupAtoW(lpszUnregister);
2510 BOOL rc;
2512 rc = immHkl->pImeUnregisterWord(lpszwReading,dwStyle,lpszwUnregister);
2513 HeapFree(GetProcessHeap(),0,lpszwReading);
2514 HeapFree(GetProcessHeap(),0,lpszwUnregister);
2515 return rc;
2518 else
2519 return FALSE;
2522 /***********************************************************************
2523 * ImmUnregisterWordW (IMM32.@)
2525 BOOL WINAPI ImmUnregisterWordW(
2526 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
2528 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2529 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2530 debugstr_w(lpszUnregister));
2531 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2533 if (is_kbd_ime_unicode(immHkl))
2534 return immHkl->pImeUnregisterWord(lpszReading,dwStyle,lpszUnregister);
2535 else
2537 LPSTR lpszaReading = strdupWtoA(lpszReading);
2538 LPSTR lpszaUnregister = strdupWtoA(lpszUnregister);
2539 BOOL rc;
2541 rc = immHkl->pImeUnregisterWord((LPCWSTR)lpszaReading,dwStyle,
2542 (LPCWSTR)lpszaUnregister);
2543 HeapFree(GetProcessHeap(),0,lpszaReading);
2544 HeapFree(GetProcessHeap(),0,lpszaUnregister);
2545 return rc;
2548 else
2549 return FALSE;
2552 /***********************************************************************
2553 * ImmGetImeMenuItemsA (IMM32.@)
2555 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2556 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
2557 DWORD dwSize)
2559 InputContextData *data = get_imc_data(hIMC);
2560 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2561 lpImeParentMenu, lpImeMenu, dwSize);
2563 if (!data)
2565 SetLastError(ERROR_INVALID_HANDLE);
2566 return 0;
2569 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2571 if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2572 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2573 (IMEMENUITEMINFOW*)lpImeParentMenu,
2574 (IMEMENUITEMINFOW*)lpImeMenu, dwSize);
2575 else
2577 IMEMENUITEMINFOW lpImeParentMenuW;
2578 IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL;
2579 DWORD rc;
2581 if (lpImeParentMenu)
2582 parent = &lpImeParentMenuW;
2583 if (lpImeMenu)
2585 int count = dwSize / sizeof(LPIMEMENUITEMINFOA);
2586 dwSize = count * sizeof(IMEMENUITEMINFOW);
2587 lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize);
2589 else
2590 lpImeMenuW = NULL;
2592 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2593 parent, lpImeMenuW, dwSize);
2595 if (lpImeParentMenu)
2597 memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA));
2598 lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem;
2599 WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString,
2600 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE,
2601 NULL, NULL);
2603 if (lpImeMenu && rc)
2605 unsigned int i;
2606 for (i = 0; i < rc; i++)
2608 memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA));
2609 lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem;
2610 WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString,
2611 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE,
2612 NULL, NULL);
2615 HeapFree(GetProcessHeap(),0,lpImeMenuW);
2616 return rc;
2619 else
2620 return 0;
2623 /***********************************************************************
2624 * ImmGetImeMenuItemsW (IMM32.@)
2626 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2627 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
2628 DWORD dwSize)
2630 InputContextData *data = get_imc_data(hIMC);
2631 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2632 lpImeParentMenu, lpImeMenu, dwSize);
2634 if (!data)
2636 SetLastError(ERROR_INVALID_HANDLE);
2637 return 0;
2640 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2642 if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2643 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2644 lpImeParentMenu, lpImeMenu, dwSize);
2645 else
2647 IMEMENUITEMINFOA lpImeParentMenuA;
2648 IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL;
2649 DWORD rc;
2651 if (lpImeParentMenu)
2652 parent = &lpImeParentMenuA;
2653 if (lpImeMenu)
2655 int count = dwSize / sizeof(LPIMEMENUITEMINFOW);
2656 dwSize = count * sizeof(IMEMENUITEMINFOA);
2657 lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize);
2659 else
2660 lpImeMenuA = NULL;
2662 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2663 (IMEMENUITEMINFOW*)parent,
2664 (IMEMENUITEMINFOW*)lpImeMenuA, dwSize);
2666 if (lpImeParentMenu)
2668 memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA));
2669 lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem;
2670 MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString,
2671 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE);
2673 if (lpImeMenu && rc)
2675 unsigned int i;
2676 for (i = 0; i < rc; i++)
2678 memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA));
2679 lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem;
2680 MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString,
2681 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE);
2684 HeapFree(GetProcessHeap(),0,lpImeMenuA);
2685 return rc;
2688 else
2689 return 0;
2692 /***********************************************************************
2693 * ImmLockIMC(IMM32.@)
2695 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
2697 InputContextData *data = get_imc_data(hIMC);
2699 if (!data)
2700 return NULL;
2701 data->dwLock++;
2702 return &data->IMC;
2705 /***********************************************************************
2706 * ImmUnlockIMC(IMM32.@)
2708 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
2710 InputContextData *data = get_imc_data(hIMC);
2712 if (!data)
2713 return FALSE;
2714 if (data->dwLock)
2715 data->dwLock--;
2716 return TRUE;
2719 /***********************************************************************
2720 * ImmGetIMCLockCount(IMM32.@)
2722 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
2724 InputContextData *data = get_imc_data(hIMC);
2725 if (!data)
2726 return 0;
2727 return data->dwLock;
2730 /***********************************************************************
2731 * ImmCreateIMCC(IMM32.@)
2733 HIMCC WINAPI ImmCreateIMCC(DWORD size)
2735 return GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE, size);
2738 /***********************************************************************
2739 * ImmDestroyIMCC(IMM32.@)
2741 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
2743 return GlobalFree(block);
2746 /***********************************************************************
2747 * ImmLockIMCC(IMM32.@)
2749 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
2751 return GlobalLock(imcc);
2754 /***********************************************************************
2755 * ImmUnlockIMCC(IMM32.@)
2757 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
2759 return GlobalUnlock(imcc);
2762 /***********************************************************************
2763 * ImmGetIMCCLockCount(IMM32.@)
2765 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
2767 return GlobalFlags(imcc) & GMEM_LOCKCOUNT;
2770 /***********************************************************************
2771 * ImmReSizeIMCC(IMM32.@)
2773 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
2775 return GlobalReAlloc(imcc, size, GMEM_ZEROINIT | GMEM_MOVEABLE);
2778 /***********************************************************************
2779 * ImmGetIMCCSize(IMM32.@)
2781 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2783 return GlobalSize(imcc);
2786 /***********************************************************************
2787 * ImmGenerateMessage(IMM32.@)
2789 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2791 InputContextData *data = get_imc_data(hIMC);
2793 if (!data)
2795 SetLastError(ERROR_INVALID_HANDLE);
2796 return FALSE;
2799 TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
2800 if (data->IMC.dwNumMsgBuf > 0)
2802 LPTRANSMSG lpTransMsg;
2803 DWORD i;
2805 lpTransMsg = ImmLockIMCC(data->IMC.hMsgBuf);
2806 for (i = 0; i < data->IMC.dwNumMsgBuf; i++)
2807 ImmInternalPostIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
2809 ImmUnlockIMCC(data->IMC.hMsgBuf);
2811 data->IMC.dwNumMsgBuf = 0;
2814 return TRUE;
2817 /***********************************************************************
2818 * ImmTranslateMessage(IMM32.@)
2819 * ( Undocumented, call internally and from user32.dll )
2821 BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData)
2823 InputContextData *data;
2824 HIMC imc = ImmGetContext(hwnd);
2825 BYTE state[256];
2826 UINT scancode;
2827 LPVOID list = 0;
2828 UINT msg_count;
2829 UINT uVirtKey;
2830 static const DWORD list_count = 10;
2832 TRACE("%p %x %x %x\n",hwnd, msg, (UINT)wParam, (UINT)lKeyData);
2834 if (imc)
2835 data = imc;
2836 else
2837 return FALSE;
2839 if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx)
2840 return FALSE;
2842 GetKeyboardState(state);
2843 scancode = lKeyData >> 0x10 & 0xff;
2845 list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list_count * sizeof(TRANSMSG) + sizeof(DWORD));
2846 ((DWORD*)list)[0] = list_count;
2848 if (data->immKbd->imeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST)
2850 WCHAR chr;
2852 if (!is_himc_ime_unicode(data))
2853 ToAscii(data->lastVK, scancode, state, &chr, 0);
2854 else
2855 ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0, GetKeyboardLayout(0));
2856 uVirtKey = MAKELONG(data->lastVK,chr);
2858 else
2859 uVirtKey = data->lastVK;
2861 msg_count = data->immKbd->pImeToAsciiEx(uVirtKey, scancode, state, list, 0, imc);
2862 TRACE("%i messages generated\n",msg_count);
2863 if (msg_count && msg_count <= list_count)
2865 UINT i;
2866 LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD));
2868 for (i = 0; i < msg_count; i++)
2869 ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam);
2871 else if (msg_count > list_count)
2872 ImmGenerateMessage(imc);
2874 HeapFree(GetProcessHeap(),0,list);
2876 data->lastVK = VK_PROCESSKEY;
2878 return (msg_count > 0);
2881 /***********************************************************************
2882 * ImmProcessKey(IMM32.@)
2883 * ( Undocumented, called from user32.dll )
2885 BOOL WINAPI ImmProcessKey(HWND hwnd, HKL hKL, UINT vKey, LPARAM lKeyData, DWORD unknown)
2887 InputContextData *data;
2888 HIMC imc = ImmGetContext(hwnd);
2889 BYTE state[256];
2891 TRACE("%p %p %x %x %x\n",hwnd, hKL, vKey, (UINT)lKeyData, unknown);
2893 if (imc)
2894 data = imc;
2895 else
2896 return FALSE;
2898 if (!data->immKbd->hIME || !data->immKbd->pImeProcessKey)
2899 return FALSE;
2901 GetKeyboardState(state);
2902 if (data->immKbd->pImeProcessKey(imc, vKey, lKeyData, state))
2904 data->lastVK = vKey;
2905 return TRUE;
2908 data->lastVK = VK_PROCESSKEY;
2909 return FALSE;
2912 /***********************************************************************
2913 * ImmDisableTextFrameService(IMM32.@)
2915 BOOL WINAPI ImmDisableTextFrameService(DWORD idThread)
2917 FIXME("Stub\n");
2918 return FALSE;
2921 /***********************************************************************
2922 * ImmEnumInputContext(IMM32.@)
2925 BOOL WINAPI ImmEnumInputContext(DWORD idThread, IMCENUMPROC lpfn, LPARAM lParam)
2927 FIXME("Stub\n");
2928 return FALSE;
2931 /***********************************************************************
2932 * ImmGetHotKey(IMM32.@)
2935 BOOL WINAPI ImmGetHotKey(DWORD hotkey, UINT *modifiers, UINT *key, HKL hkl)
2937 FIXME("%x, %p, %p, %p: stub\n", hotkey, modifiers, key, hkl);
2938 return FALSE;
2943 * Window Proc for the Default IME window class
2945 static LRESULT WINAPI DefIME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
2946 LPARAM lParam)
2948 switch (uMsg)
2950 case WM_CREATE:
2951 case WM_NCCREATE:
2952 return TRUE;
2953 case WM_IME_STARTCOMPOSITION:
2954 case WM_IME_ENDCOMPOSITION:
2955 case WM_IME_COMPOSITION:
2956 case WM_IME_SETCONTEXT:
2957 case WM_IME_NOTIFY:
2958 case WM_IME_CONTROL:
2959 case WM_IME_COMPOSITIONFULL:
2960 case WM_IME_SELECT:
2961 case WM_IME_CHAR:
2962 case WM_IME_REQUEST:
2963 case WM_IME_KEYDOWN:
2964 case WM_IME_KEYUP:
2966 ImmHkl *immHkl = IMM_GetImmHkl(GetKeyboardLayout(0));
2967 if (immHkl->UIWnd)
2968 return SendMessageW(immHkl->UIWnd,uMsg,wParam,lParam);
2969 else
2970 return FALSE;
2972 default:
2973 if ((uMsg == WM_MSIME_RECONVERTOPTIONS) ||
2974 (uMsg == WM_MSIME_SERVICE) ||
2975 (uMsg == WM_MSIME_MOUSE) ||
2976 (uMsg == WM_MSIME_RECONVERTREQUEST) ||
2977 (uMsg == WM_MSIME_RECONVERT) ||
2978 (uMsg == WM_MSIME_QUERYPOSITION) ||
2979 (uMsg == WM_MSIME_DOCUMENTFEED))
2981 ImmHkl *immHkl = IMM_GetImmHkl(GetKeyboardLayout(0));
2982 if (immHkl->UIWnd)
2983 return SendMessageW(immHkl->UIWnd,uMsg,wParam,lParam);
2984 else
2985 return FALSE;
2987 return DefWindowProcW(hwnd, uMsg, wParam, lParam);