imm32: Correct offset of text in default IME window when using not default window...
[wine/hacks.git] / dlls / imm32 / imm.c
blob436c126d76c8906be7d9c3ba92a06408fcfa43ed
1 /*
2 * IMM32 library
4 * Copyright 1998 Patrik Stridvall
5 * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "winerror.h"
29 #include "wine/debug.h"
30 #include "imm.h"
31 #include "ddk/imm.h"
32 #include "winnls.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(imm);
36 #define FROM_IME 0xcafe1337
38 static void (*pX11DRV_ForceXIMReset)(HWND);
40 typedef struct tagIMCCInternal
42 DWORD dwLock;
43 DWORD dwSize;
44 } IMCCInternal;
46 typedef struct tagInputContextData
48 BOOL bInternalState;
49 BOOL bRead;
50 BOOL bInComposition;
51 HFONT textfont;
53 DWORD dwLock;
54 INPUTCONTEXT IMC;
55 } InputContextData;
57 typedef struct _tagTRANSMSG {
58 UINT message;
59 WPARAM wParam;
60 LPARAM lParam;
61 } TRANSMSG, *LPTRANSMSG;
63 static InputContextData *root_context = NULL;
64 static HWND hwndDefault = NULL;
65 static HANDLE hImeInst;
66 static const WCHAR WC_IMECLASSNAME[] = {'I','M','E',0};
67 static ATOM atIMEClass = 0;
69 /* MSIME messages */
70 static UINT WM_MSIME_SERVICE;
71 static UINT WM_MSIME_RECONVERTOPTIONS;
72 static UINT WM_MSIME_MOUSE;
73 static UINT WM_MSIME_RECONVERTREQUEST;
74 static UINT WM_MSIME_RECONVERT;
75 static UINT WM_MSIME_QUERYPOSITION;
76 static UINT WM_MSIME_DOCUMENTFEED;
79 * prototypes
81 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
82 LPARAM lParam);
83 static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable);
84 static void ImmInternalPostIMEMessage(UINT, WPARAM, LPARAM);
85 static void ImmInternalSetOpenStatus(BOOL fOpen);
86 static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len);
88 static VOID IMM_PostResult(InputContextData *data)
90 unsigned int i;
91 LPCOMPOSITIONSTRING compstr;
92 LPBYTE compdata;
93 LPWSTR ResultStr;
94 HIMCC newCompStr;
96 TRACE("Posting result as IME_CHAR\n");
97 compdata = ImmLockIMCC(root_context->IMC.hCompStr);
98 compstr = (LPCOMPOSITIONSTRING)compdata;
99 ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
101 for (i = 0; i < compstr->dwResultStrLen; i++)
102 ImmInternalPostIMEMessage (WM_IME_CHAR, ResultStr[i], 1);
104 ImmUnlockIMCC(root_context->IMC.hCompStr);
106 /* clear the buffer */
107 newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0);
108 ImmDestroyIMCC(root_context->IMC.hCompStr);
109 root_context->IMC.hCompStr = newCompStr;
112 static void IMM_Register(void)
114 WNDCLASSW wndClass;
115 ZeroMemory(&wndClass, sizeof(WNDCLASSW));
116 wndClass.style = CS_GLOBALCLASS | CS_IME | CS_HREDRAW | CS_VREDRAW;
117 wndClass.lpfnWndProc = (WNDPROC) IME_WindowProc;
118 wndClass.cbClsExtra = 0;
119 wndClass.cbWndExtra = 0;
120 wndClass.hInstance = hImeInst;
121 wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
122 wndClass.hIcon = NULL;
123 wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW +1);
124 wndClass.lpszMenuName = 0;
125 wndClass.lpszClassName = WC_IMECLASSNAME;
126 atIMEClass = RegisterClassW(&wndClass);
129 static void IMM_Unregister(void)
131 if (atIMEClass) {
132 UnregisterClassW(WC_IMECLASSNAME, NULL);
136 static void IMM_RegisterMessages(void)
138 WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");
139 WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions");
140 WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
141 WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
142 WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
143 WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
144 WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
148 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
150 HMODULE x11drv;
152 TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
153 switch (fdwReason)
155 case DLL_PROCESS_ATTACH:
156 DisableThreadLibraryCalls(hInstDLL);
157 hImeInst = hInstDLL;
158 IMM_RegisterMessages();
159 x11drv = GetModuleHandleA("winex11.drv");
160 if (x11drv) pX11DRV_ForceXIMReset = (void *)GetProcAddress( x11drv, "ForceXIMReset");
161 break;
162 case DLL_PROCESS_DETACH:
163 if (hwndDefault)
165 DestroyWindow(hwndDefault);
166 hwndDefault = 0;
168 IMM_Unregister();
169 break;
171 return TRUE;
174 /* for posting messages as the IME */
175 static void ImmInternalPostIMEMessage(UINT msg, WPARAM wParam, LPARAM lParam)
177 HWND target = GetFocus();
178 if (!target)
179 PostMessageW(root_context->IMC.hWnd,msg,wParam,lParam);
180 else
181 PostMessageW(target, msg, wParam, lParam);
184 static LRESULT ImmInternalSendIMENotify(WPARAM notify, LPARAM lParam)
186 HWND target;
188 target = root_context->IMC.hWnd;
189 if (!target) target = GetFocus();
191 if (target)
192 return SendMessageW(target, WM_IME_NOTIFY, notify, lParam);
194 return 0;
197 static HIMCC ImmCreateBlankCompStr(void)
199 HIMCC rc;
200 LPCOMPOSITIONSTRING ptr;
201 rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
202 ptr = (LPCOMPOSITIONSTRING)ImmLockIMCC(rc);
203 memset(ptr,0,sizeof(COMPOSITIONSTRING));
204 ptr->dwSize = sizeof(COMPOSITIONSTRING);
205 ImmUnlockIMCC(rc);
206 return rc;
209 static void ImmInternalSetOpenStatus(BOOL fOpen)
211 TRACE("Setting internal state to %s\n",(fOpen)?"OPEN":"CLOSED");
213 if (root_context->IMC.fOpen && fOpen == FALSE)
215 ShowWindow(hwndDefault,SW_HIDE);
216 ImmDestroyIMCC(root_context->IMC.hCompStr);
217 root_context->IMC.hCompStr = ImmCreateBlankCompStr();
220 root_context->IMC.fOpen = fOpen;
221 root_context->bInternalState = fOpen;
223 ImmInternalSendIMENotify(IMN_SETOPENSTATUS, 0);
226 static int updateField(DWORD origLen, DWORD origOffset, DWORD currentOffset,
227 LPBYTE target, LPBYTE source, DWORD* lenParam,
228 DWORD* offsetParam, BOOL wchars )
230 if (origLen > 0 && origOffset > 0)
232 int truelen = origLen;
233 if (wchars)
234 truelen *= sizeof(WCHAR);
236 memcpy(&target[currentOffset], &source[origOffset], truelen);
238 *lenParam = origLen;
239 *offsetParam = currentOffset;
240 currentOffset += truelen;
242 return currentOffset;
245 static HIMCC updateCompStr(HIMCC old, LPWSTR compstr, DWORD len)
247 /* we need to make sure the CompStr, CompClaus and CompAttr fields are all
248 * set and correct */
249 int needed_size;
250 HIMCC rc;
251 LPBYTE newdata = NULL;
252 LPBYTE olddata = NULL;
253 LPCOMPOSITIONSTRING new_one;
254 LPCOMPOSITIONSTRING lpcs = NULL;
255 INT current_offset = 0;
257 TRACE("%s, %i\n",debugstr_wn(compstr,len),len);
259 if (old == NULL && compstr == NULL && len == 0)
260 return NULL;
262 if (old != NULL)
264 olddata = ImmLockIMCC(old);
265 lpcs = (LPCOMPOSITIONSTRING)olddata;
268 needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
269 len + sizeof(DWORD) * 2;
271 if (lpcs != NULL)
273 needed_size += lpcs->dwCompReadAttrLen;
274 needed_size += lpcs->dwCompReadClauseLen;
275 needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
276 needed_size += lpcs->dwResultReadClauseLen;
277 needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
278 needed_size += lpcs->dwResultClauseLen;
279 needed_size += lpcs->dwResultStrLen * sizeof(DWORD);
280 needed_size += lpcs->dwPrivateSize;
282 rc = ImmCreateIMCC(needed_size);
283 newdata = ImmLockIMCC(rc);
284 new_one = (LPCOMPOSITIONSTRING)newdata;
286 new_one->dwSize = needed_size;
287 current_offset = sizeof(COMPOSITIONSTRING);
288 if (lpcs != NULL)
290 current_offset = updateField(lpcs->dwCompReadAttrLen,
291 lpcs->dwCompReadAttrOffset,
292 current_offset, newdata, olddata,
293 &new_one->dwCompReadAttrLen,
294 &new_one->dwCompReadAttrOffset, FALSE);
296 current_offset = updateField(lpcs->dwCompReadClauseLen,
297 lpcs->dwCompReadClauseOffset,
298 current_offset, newdata, olddata,
299 &new_one->dwCompReadClauseLen,
300 &new_one->dwCompReadClauseOffset, FALSE);
302 current_offset = updateField(lpcs->dwCompReadStrLen,
303 lpcs->dwCompReadStrOffset,
304 current_offset, newdata, olddata,
305 &new_one->dwCompReadStrLen,
306 &new_one->dwCompReadStrOffset, TRUE);
308 /* new CompAttr, CompClause, CompStr, dwCursorPos */
309 new_one->dwDeltaStart = 0;
311 current_offset = updateField(lpcs->dwResultReadClauseLen,
312 lpcs->dwResultReadClauseOffset,
313 current_offset, newdata, olddata,
314 &new_one->dwResultReadClauseLen,
315 &new_one->dwResultReadClauseOffset, FALSE);
317 current_offset = updateField(lpcs->dwResultReadStrLen,
318 lpcs->dwResultReadStrOffset,
319 current_offset, newdata, olddata,
320 &new_one->dwResultReadStrLen,
321 &new_one->dwResultReadStrOffset, TRUE);
323 current_offset = updateField(lpcs->dwResultClauseLen,
324 lpcs->dwResultClauseOffset,
325 current_offset, newdata, olddata,
326 &new_one->dwResultClauseLen,
327 &new_one->dwResultClauseOffset, FALSE);
329 current_offset = updateField(lpcs->dwResultStrLen,
330 lpcs->dwResultStrOffset,
331 current_offset, newdata, olddata,
332 &new_one->dwResultStrLen,
333 &new_one->dwResultStrOffset, TRUE);
335 current_offset = updateField(lpcs->dwPrivateSize,
336 lpcs->dwPrivateOffset,
337 current_offset, newdata, olddata,
338 &new_one->dwPrivateSize,
339 &new_one->dwPrivateOffset, FALSE);
342 /* set new data */
343 /* CompAttr */
344 new_one->dwCompAttrLen = len;
345 if (len > 0)
347 new_one->dwCompAttrOffset = current_offset;
348 memset(&newdata[current_offset],ATTR_INPUT,len);
349 current_offset += len;
352 /* CompClause */
353 if (len > 0)
355 new_one->dwCompClauseLen = sizeof(DWORD) * 2;
356 new_one->dwCompClauseOffset = current_offset;
357 *(DWORD*)(&newdata[current_offset]) = 0;
358 current_offset += sizeof(DWORD);
359 *(DWORD*)(&newdata[current_offset]) = len;
360 current_offset += sizeof(DWORD);
363 /* CompStr */
364 new_one->dwCompStrLen = len;
365 if (len > 0)
367 new_one->dwCompStrOffset = current_offset;
368 memcpy(&newdata[current_offset],compstr,len*sizeof(WCHAR));
371 /* CursorPos */
372 new_one->dwCursorPos = len;
374 ImmUnlockIMCC(rc);
375 if (lpcs)
376 ImmUnlockIMCC(old);
378 return rc;
381 static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len)
383 /* we need to make sure the ResultStr and ResultClause fields are all
384 * set and correct */
385 int needed_size;
386 HIMCC rc;
387 LPBYTE newdata = NULL;
388 LPBYTE olddata = NULL;
389 LPCOMPOSITIONSTRING new_one;
390 LPCOMPOSITIONSTRING lpcs = NULL;
391 INT current_offset = 0;
393 TRACE("%s, %i\n",debugstr_wn(resultstr,len),len);
395 if (old == NULL && resultstr == NULL && len == 0)
396 return NULL;
398 if (old != NULL)
400 olddata = ImmLockIMCC(old);
401 lpcs = (LPCOMPOSITIONSTRING)olddata;
404 needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
405 sizeof(DWORD) * 2;
407 if (lpcs != NULL)
409 needed_size += lpcs->dwCompReadAttrLen;
410 needed_size += lpcs->dwCompReadClauseLen;
411 needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
412 needed_size += lpcs->dwCompAttrLen;
413 needed_size += lpcs->dwCompClauseLen;
414 needed_size += lpcs->dwCompStrLen * sizeof(DWORD);
415 needed_size += lpcs->dwResultReadClauseLen;
416 needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
417 needed_size += lpcs->dwPrivateSize;
419 rc = ImmCreateIMCC(needed_size);
420 newdata = ImmLockIMCC(rc);
421 new_one = (LPCOMPOSITIONSTRING)newdata;
423 new_one->dwSize = needed_size;
424 current_offset = sizeof(COMPOSITIONSTRING);
425 if (lpcs != NULL)
427 current_offset = updateField(lpcs->dwCompReadAttrLen,
428 lpcs->dwCompReadAttrOffset,
429 current_offset, newdata, olddata,
430 &new_one->dwCompReadAttrLen,
431 &new_one->dwCompReadAttrOffset, FALSE);
433 current_offset = updateField(lpcs->dwCompReadClauseLen,
434 lpcs->dwCompReadClauseOffset,
435 current_offset, newdata, olddata,
436 &new_one->dwCompReadClauseLen,
437 &new_one->dwCompReadClauseOffset, FALSE);
439 current_offset = updateField(lpcs->dwCompReadStrLen,
440 lpcs->dwCompReadStrOffset,
441 current_offset, newdata, olddata,
442 &new_one->dwCompReadStrLen,
443 &new_one->dwCompReadStrOffset, TRUE);
445 current_offset = updateField(lpcs->dwCompAttrLen,
446 lpcs->dwCompAttrOffset,
447 current_offset, newdata, olddata,
448 &new_one->dwCompAttrLen,
449 &new_one->dwCompAttrOffset, FALSE);
451 current_offset = updateField(lpcs->dwCompClauseLen,
452 lpcs->dwCompClauseOffset,
453 current_offset, newdata, olddata,
454 &new_one->dwCompClauseLen,
455 &new_one->dwCompClauseOffset, FALSE);
457 current_offset = updateField(lpcs->dwCompStrLen,
458 lpcs->dwCompStrOffset,
459 current_offset, newdata, olddata,
460 &new_one->dwCompStrLen,
461 &new_one->dwCompStrOffset, TRUE);
463 new_one->dwCursorPos = lpcs->dwCursorPos;
464 new_one->dwDeltaStart = 0;
466 current_offset = updateField(lpcs->dwResultReadClauseLen,
467 lpcs->dwResultReadClauseOffset,
468 current_offset, newdata, olddata,
469 &new_one->dwResultReadClauseLen,
470 &new_one->dwResultReadClauseOffset, FALSE);
472 current_offset = updateField(lpcs->dwResultReadStrLen,
473 lpcs->dwResultReadStrOffset,
474 current_offset, newdata, olddata,
475 &new_one->dwResultReadStrLen,
476 &new_one->dwResultReadStrOffset, TRUE);
478 /* new ResultClause , ResultStr */
480 current_offset = updateField(lpcs->dwPrivateSize,
481 lpcs->dwPrivateOffset,
482 current_offset, newdata, olddata,
483 &new_one->dwPrivateSize,
484 &new_one->dwPrivateOffset, FALSE);
487 /* set new data */
488 /* ResultClause */
489 if (len > 0)
491 new_one->dwResultClauseLen = sizeof(DWORD) * 2;
492 new_one->dwResultClauseOffset = current_offset;
493 *(DWORD*)(&newdata[current_offset]) = 0;
494 current_offset += sizeof(DWORD);
495 *(DWORD*)(&newdata[current_offset]) = len;
496 current_offset += sizeof(DWORD);
499 /* ResultStr */
500 new_one->dwResultStrLen = len;
501 if (len > 0)
503 new_one->dwResultStrOffset = current_offset;
504 memcpy(&newdata[current_offset],resultstr,len*sizeof(WCHAR));
506 ImmUnlockIMCC(rc);
507 if (lpcs)
508 ImmUnlockIMCC(old);
510 return rc;
515 /***********************************************************************
516 * ImmAssociateContext (IMM32.@)
518 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
520 InputContextData *data = (InputContextData*)hIMC;
522 WARN("(%p, %p): semi-stub\n", hWnd, hIMC);
524 if (!hIMC)
525 return NULL;
528 * WINE SPECIFIC! MAY CONFLICT
529 * associate the root context we have an XIM created
531 if (hWnd == 0x000)
533 root_context = (InputContextData*)hIMC;
537 * If already associated just return
539 if (data->IMC.hWnd == hWnd)
540 return hIMC;
542 if (IsWindow(data->IMC.hWnd))
545 * Post a message that your context is switching
547 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
550 data->IMC.hWnd = hWnd;
552 if (IsWindow(data->IMC.hWnd))
555 * Post a message that your context is switching
557 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
561 * TODO: We need to keep track of the old context associated
562 * with a window and return it for now we will return NULL;
564 return NULL;
567 /***********************************************************************
568 * ImmAssociateContextEx (IMM32.@)
570 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
572 FIXME("(%p, %p, %d): stub\n", hWnd, hIMC, dwFlags);
573 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
574 return FALSE;
577 /***********************************************************************
578 * ImmConfigureIMEA (IMM32.@)
580 BOOL WINAPI ImmConfigureIMEA(
581 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
583 FIXME("(%p, %p, %d, %p): stub\n",
584 hKL, hWnd, dwMode, lpData
586 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
587 return FALSE;
590 /***********************************************************************
591 * ImmConfigureIMEW (IMM32.@)
593 BOOL WINAPI ImmConfigureIMEW(
594 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
596 FIXME("(%p, %p, %d, %p): stub\n",
597 hKL, hWnd, dwMode, lpData
599 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
600 return FALSE;
603 /***********************************************************************
604 * ImmCreateContext (IMM32.@)
606 HIMC WINAPI ImmCreateContext(void)
608 InputContextData *new_context;
610 new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
612 /* hCompStr is never NULL */
613 new_context->IMC.hCompStr = ImmCreateBlankCompStr();
615 return (HIMC)new_context;
618 /***********************************************************************
619 * ImmDestroyContext (IMM32.@)
621 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
623 InputContextData *data = (InputContextData*)hIMC;
625 TRACE("Destroying %p\n",hIMC);
627 if (hIMC)
629 ImmDestroyIMCC(data->IMC.hCompStr);
630 ImmDestroyIMCC(data->IMC.hCandInfo);
631 ImmDestroyIMCC(data->IMC.hGuideLine);
632 ImmDestroyIMCC(data->IMC.hPrivate);
633 ImmDestroyIMCC(data->IMC.hMsgBuf);
635 if (data->textfont)
637 DeleteObject(data->textfont);
638 data->textfont = NULL;
641 HeapFree(GetProcessHeap(),0,data);
643 return TRUE;
646 /***********************************************************************
647 * ImmDisableIME (IMM32.@)
649 BOOL WINAPI ImmDisableIME(DWORD idThread)
651 FIXME("(%d): stub\n", idThread);
652 return TRUE;
655 /***********************************************************************
656 * ImmEnumRegisterWordA (IMM32.@)
658 UINT WINAPI ImmEnumRegisterWordA(
659 HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
660 LPCSTR lpszReading, DWORD dwStyle,
661 LPCSTR lpszRegister, LPVOID lpData)
663 FIXME("(%p, %p, %s, %d, %s, %p): stub\n",
664 hKL, lpfnEnumProc,
665 debugstr_a(lpszReading), dwStyle,
666 debugstr_a(lpszRegister), lpData
668 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
669 return 0;
672 /***********************************************************************
673 * ImmEnumRegisterWordW (IMM32.@)
675 UINT WINAPI ImmEnumRegisterWordW(
676 HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
677 LPCWSTR lpszReading, DWORD dwStyle,
678 LPCWSTR lpszRegister, LPVOID lpData)
680 FIXME("(%p, %p, %s, %d, %s, %p): stub\n",
681 hKL, lpfnEnumProc,
682 debugstr_w(lpszReading), dwStyle,
683 debugstr_w(lpszRegister), lpData
685 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
686 return 0;
689 /***********************************************************************
690 * ImmEscapeA (IMM32.@)
692 LRESULT WINAPI ImmEscapeA(
693 HKL hKL, HIMC hIMC,
694 UINT uEscape, LPVOID lpData)
696 FIXME("(%p, %p, %d, %p): stub\n",
697 hKL, hIMC, uEscape, lpData
699 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
700 return 0;
703 /***********************************************************************
704 * ImmEscapeW (IMM32.@)
706 LRESULT WINAPI ImmEscapeW(
707 HKL hKL, HIMC hIMC,
708 UINT uEscape, LPVOID lpData)
710 FIXME("(%p, %p, %d, %p): stub\n",
711 hKL, hIMC, uEscape, lpData
713 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
714 return 0;
717 /***********************************************************************
718 * ImmGetCandidateListA (IMM32.@)
720 DWORD WINAPI ImmGetCandidateListA(
721 HIMC hIMC, DWORD deIndex,
722 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
724 FIXME("(%p, %d, %p, %d): stub\n",
725 hIMC, deIndex,
726 lpCandList, dwBufLen
728 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
729 return 0;
732 /***********************************************************************
733 * ImmGetCandidateListCountA (IMM32.@)
735 DWORD WINAPI ImmGetCandidateListCountA(
736 HIMC hIMC, LPDWORD lpdwListCount)
738 FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
739 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
740 return 0;
743 /***********************************************************************
744 * ImmGetCandidateListCountW (IMM32.@)
746 DWORD WINAPI ImmGetCandidateListCountW(
747 HIMC hIMC, LPDWORD lpdwListCount)
749 FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
750 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
751 return 0;
754 /***********************************************************************
755 * ImmGetCandidateListW (IMM32.@)
757 DWORD WINAPI ImmGetCandidateListW(
758 HIMC hIMC, DWORD deIndex,
759 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
761 FIXME("(%p, %d, %p, %d): stub\n",
762 hIMC, deIndex,
763 lpCandList, dwBufLen
765 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
766 return 0;
769 /***********************************************************************
770 * ImmGetCandidateWindow (IMM32.@)
772 BOOL WINAPI ImmGetCandidateWindow(
773 HIMC hIMC, DWORD dwBufLen, LPCANDIDATEFORM lpCandidate)
775 FIXME("(%p, %d, %p): stub\n", hIMC, dwBufLen, lpCandidate);
776 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
777 return FALSE;
780 /***********************************************************************
781 * ImmGetCompositionFontA (IMM32.@)
783 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
785 FIXME("(%p, %p): stub\n", hIMC, lplf);
786 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
787 return FALSE;
790 /***********************************************************************
791 * ImmGetCompositionFontW (IMM32.@)
793 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
795 FIXME("(%p, %p): stub\n", hIMC, lplf);
796 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
797 return FALSE;
800 /***********************************************************************
801 * ImmGetCompositionStringA (IMM32.@)
803 LONG WINAPI ImmGetCompositionStringA(
804 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
806 CHAR *buf;
807 LONG rc = 0;
808 InputContextData *data = (InputContextData*)hIMC;
809 LPCOMPOSITIONSTRING compstr;
810 LPBYTE compdata;
812 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
814 if (!data)
815 return FALSE;
817 if (!data->IMC.hCompStr)
818 return FALSE;
820 compdata = ImmLockIMCC(data->IMC.hCompStr);
821 compstr = (LPCOMPOSITIONSTRING)compdata;
823 if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 &&
824 compstr->dwResultStrOffset > 0)
826 LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
828 TRACE("GSC_RESULTSTR %p %i\n",ResultStr,
829 compstr->dwResultStrLen);
831 buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwResultStrLen * 3 );
832 rc = WideCharToMultiByte(CP_ACP, 0, ResultStr,
833 compstr->dwResultStrLen , buf,
834 compstr->dwResultStrLen * 3, NULL, NULL);
835 if (dwBufLen >= rc)
836 memcpy(lpBuf,buf,rc);
838 data->bRead = TRUE;
839 HeapFree( GetProcessHeap(), 0, buf );
841 else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 &&
842 compstr->dwCompStrOffset > 0)
844 LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
846 TRACE("GSC_COMPSTR %p %i\n", CompString, compstr->dwCompStrLen);
848 buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwCompStrLen * 3 );
849 rc = WideCharToMultiByte(CP_ACP, 0, CompString,
850 compstr->dwCompStrLen, buf,
851 compstr->dwCompStrLen * 3, NULL, NULL);
852 if (dwBufLen >= rc)
853 memcpy(lpBuf,buf,rc);
854 HeapFree( GetProcessHeap(), 0, buf );
856 else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 &&
857 compstr->dwCompAttrOffset > 0)
859 LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset);
860 TRACE("GSC_COMPATTR %p %i\n", Compattr , compstr->dwCompAttrLen);
862 rc = compstr->dwCompAttrLen;
863 if (dwBufLen >= rc)
864 memcpy(lpBuf,Compattr,rc);
866 else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 &&
867 compstr->dwCompClauseOffset > 0)
869 LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset);
870 TRACE("GSC_COMPCLAUSE %p %i\n", Compclause, compstr->dwCompClauseLen);
872 rc = compstr->dwCompClauseLen;
873 if (dwBufLen >= compstr->dwCompClauseLen)
874 memcpy(lpBuf,Compclause,rc);
876 else if (dwIndex == GCS_RESULTCLAUSE && compstr->dwResultClauseLen > 0 &&
877 compstr->dwResultClauseOffset > 0)
879 LPWSTR Resultclause = (LPWSTR)(compdata + compstr->dwResultClauseOffset);
880 TRACE("GSC_RESULTCLAUSE %p %i\n", Resultclause, compstr->dwResultClauseLen);
882 rc = compstr->dwResultClauseLen;
883 if (dwBufLen >= compstr->dwResultClauseLen)
884 memcpy(lpBuf,Resultclause,rc);
886 else if (dwIndex == GCS_CURSORPOS)
888 TRACE("GSC_CURSORPOS\n");
889 rc = compstr->dwCursorPos;
891 else if (dwIndex == GCS_DELTASTART)
893 TRACE("GCS_DELTASTART\n");
894 rc = compstr->dwDeltaStart;
896 else
898 FIXME("Unhandled index 0x%x\n",dwIndex);
901 ImmUnlockIMCC(data->IMC.hCompStr);
903 return rc;
906 /***********************************************************************
907 * ImmGetCompositionStringW (IMM32.@)
909 LONG WINAPI ImmGetCompositionStringW(
910 HIMC hIMC, DWORD dwIndex,
911 LPVOID lpBuf, DWORD dwBufLen)
913 LONG rc = 0;
914 InputContextData *data = (InputContextData*)hIMC;
915 LPCOMPOSITIONSTRING compstr;
916 LPBYTE compdata;
918 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
920 if (!data)
921 return FALSE;
923 if (!data->IMC.hCompStr)
924 return FALSE;
926 compdata = ImmLockIMCC(data->IMC.hCompStr);
927 compstr = (LPCOMPOSITIONSTRING)compdata;
929 if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 &&
930 compstr->dwResultStrOffset > 0)
932 LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
933 data->bRead = TRUE;
934 rc = compstr->dwResultStrLen * sizeof(WCHAR);
936 if (dwBufLen >= rc)
937 memcpy(lpBuf,ResultStr,rc);
939 else if (dwIndex == GCS_RESULTREADSTR && compstr->dwResultReadStrLen > 0 &&
940 compstr->dwResultReadStrOffset > 0)
942 LPWSTR ResultReadString = (LPWSTR)(compdata + compstr->dwResultReadStrOffset);
944 rc = compstr->dwResultReadStrLen * sizeof(WCHAR);
945 if (dwBufLen >= rc)
946 memcpy(lpBuf,ResultReadString,rc);
948 else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 &&
949 compstr->dwCompStrOffset > 0)
951 LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
952 rc = compstr->dwCompStrLen * sizeof(WCHAR);
953 if (dwBufLen >= rc)
954 memcpy(lpBuf,CompString,rc);
956 else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 &&
957 compstr->dwCompAttrOffset > 0)
960 LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset);
962 rc = compstr->dwCompAttrLen;
963 if (dwBufLen >= rc)
964 memcpy(lpBuf,Compattr,rc);
966 else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 &&
967 compstr->dwCompClauseOffset > 0)
969 LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset);
971 rc = compstr->dwCompClauseLen;
972 if (dwBufLen >= compstr->dwCompClauseLen)
973 memcpy(lpBuf,Compclause,rc);
975 else if (dwIndex == GCS_COMPREADSTR && compstr->dwCompReadStrLen > 0 &&
976 compstr->dwCompReadStrOffset > 0)
978 LPWSTR CompReadString = (LPWSTR)(compdata + compstr->dwCompReadStrOffset);
980 rc = compstr->dwCompReadStrLen * sizeof(WCHAR);
982 if (dwBufLen >= rc)
983 memcpy(lpBuf,CompReadString,rc);
985 else if (dwIndex == GCS_CURSORPOS)
987 TRACE("GSC_CURSORPOS\n");
988 rc = compstr->dwCursorPos;
990 else if (dwIndex == GCS_DELTASTART)
992 TRACE("GCS_DELTASTART\n");
993 rc = compstr->dwDeltaStart;
995 else
997 FIXME("Unhandled index 0x%x\n",dwIndex);
1000 ImmUnlockIMCC(data->IMC.hCompStr);
1002 return rc;
1005 /***********************************************************************
1006 * ImmGetCompositionWindow (IMM32.@)
1008 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1010 InputContextData *data = (InputContextData*)hIMC;
1012 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1014 if (!data)
1015 return FALSE;
1017 memcpy(lpCompForm,&(data->IMC.cfCompForm),sizeof(COMPOSITIONFORM));
1018 return 1;
1021 /***********************************************************************
1022 * ImmGetContext (IMM32.@)
1025 HIMC WINAPI ImmGetContext(HWND hWnd)
1027 TRACE("%p\n", hWnd);
1029 if (!root_context)
1030 return NULL;
1032 root_context->IMC.hWnd = hWnd;
1033 return (HIMC)root_context;
1036 /***********************************************************************
1037 * ImmGetConversionListA (IMM32.@)
1039 DWORD WINAPI ImmGetConversionListA(
1040 HKL hKL, HIMC hIMC,
1041 LPCSTR pSrc, LPCANDIDATELIST lpDst,
1042 DWORD dwBufLen, UINT uFlag)
1044 FIXME("(%p, %p, %s, %p, %d, %d): stub\n",
1045 hKL, hIMC, debugstr_a(pSrc), lpDst, dwBufLen, uFlag
1047 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1048 return 0;
1051 /***********************************************************************
1052 * ImmGetConversionListW (IMM32.@)
1054 DWORD WINAPI ImmGetConversionListW(
1055 HKL hKL, HIMC hIMC,
1056 LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1057 DWORD dwBufLen, UINT uFlag)
1059 FIXME("(%p, %p, %s, %p, %d, %d): stub\n",
1060 hKL, hIMC, debugstr_w(pSrc), lpDst, dwBufLen, uFlag
1062 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1063 return 0;
1066 /***********************************************************************
1067 * ImmGetConversionStatus (IMM32.@)
1069 BOOL WINAPI ImmGetConversionStatus(
1070 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1072 TRACE("(%p, %p, %p): best guess\n", hIMC, lpfdwConversion, lpfdwSentence);
1073 if (lpfdwConversion)
1074 *lpfdwConversion = IME_CMODE_NATIVE;
1075 if (lpfdwSentence)
1076 *lpfdwSentence = IME_SMODE_NONE;
1077 return TRUE;
1080 /***********************************************************************
1081 * ImmGetDefaultIMEWnd (IMM32.@)
1083 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1085 static int shown = 0;
1087 if (!shown) {
1088 FIXME("(%p - %p %p ): semi-stub\n", hWnd,hwndDefault, root_context);
1089 shown = 1;
1092 if (hwndDefault == NULL)
1094 static const WCHAR the_name[] = {'I','M','E','\0'};
1096 IMM_Register();
1097 hwndDefault = CreateWindowExW( WS_EX_TOOLWINDOW, WC_IMECLASSNAME,
1098 the_name, WS_POPUP, 0, 0, 1, 1, 0, 0,
1099 hImeInst, 0);
1101 TRACE("Default created (%p)\n",hwndDefault);
1104 return hwndDefault;
1107 /***********************************************************************
1108 * ImmGetDescriptionA (IMM32.@)
1110 UINT WINAPI ImmGetDescriptionA(
1111 HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1113 WCHAR *buf;
1114 DWORD len;
1116 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1118 /* find out how many characters in the unicode buffer */
1119 len = ImmGetDescriptionW( hKL, NULL, 0 );
1121 /* allocate a buffer of that size */
1122 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1123 if( !buf )
1124 return 0;
1126 /* fetch the unicode buffer */
1127 len = ImmGetDescriptionW( hKL, buf, len + 1 );
1129 /* convert it back to ASCII */
1130 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1131 lpszDescription, uBufLen, NULL, NULL );
1133 HeapFree( GetProcessHeap(), 0, buf );
1135 return len;
1138 /***********************************************************************
1139 * ImmGetDescriptionW (IMM32.@)
1141 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1143 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1145 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1147 if (!uBufLen) return lstrlenW( name );
1148 lstrcpynW( lpszDescription, name, uBufLen );
1149 return lstrlenW( lpszDescription );
1152 /***********************************************************************
1153 * ImmGetGuideLineA (IMM32.@)
1155 DWORD WINAPI ImmGetGuideLineA(
1156 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1158 FIXME("(%p, %d, %s, %d): stub\n",
1159 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1161 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1162 return 0;
1165 /***********************************************************************
1166 * ImmGetGuideLineW (IMM32.@)
1168 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1170 FIXME("(%p, %d, %s, %d): stub\n",
1171 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1173 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1174 return 0;
1177 /***********************************************************************
1178 * ImmGetIMEFileNameA (IMM32.@)
1180 UINT WINAPI ImmGetIMEFileNameA(
1181 HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1183 FIXME("(%p, %p, %d): stub\n", hKL, lpszFileName, uBufLen);
1184 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1185 return 0;
1188 /***********************************************************************
1189 * ImmGetIMEFileNameW (IMM32.@)
1191 UINT WINAPI ImmGetIMEFileNameW(
1192 HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1194 FIXME("(%p, %p, %d): stub\n", hKL, lpszFileName, uBufLen);
1195 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1196 return 0;
1199 /***********************************************************************
1200 * ImmGetOpenStatus (IMM32.@)
1202 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1204 InputContextData *data = (InputContextData*)hIMC;
1206 if (!data)
1207 return FALSE;
1208 FIXME("(%p): semi-stub\n", hIMC);
1210 return data->IMC.fOpen;
1213 /***********************************************************************
1214 * ImmGetProperty (IMM32.@)
1216 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1218 DWORD rc = 0;
1219 TRACE("(%p, %d)\n", hKL, fdwIndex);
1221 switch (fdwIndex)
1223 case IGP_PROPERTY:
1224 TRACE("(%s)\n", "IGP_PROPERTY");
1225 rc = IME_PROP_UNICODE | IME_PROP_AT_CARET;
1226 break;
1227 case IGP_CONVERSION:
1228 FIXME("(%s)\n", "IGP_CONVERSION");
1229 rc = IME_CMODE_NATIVE;
1230 break;
1231 case IGP_SENTENCE:
1232 FIXME("%s)\n", "IGP_SENTENCE");
1233 rc = IME_SMODE_AUTOMATIC;
1234 break;
1235 case IGP_SETCOMPSTR:
1236 TRACE("(%s)\n", "IGP_SETCOMPSTR");
1237 rc = 0;
1238 break;
1239 case IGP_SELECT:
1240 TRACE("(%s)\n", "IGP_SELECT");
1241 rc = SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE;
1242 break;
1243 case IGP_GETIMEVERSION:
1244 TRACE("(%s)\n", "IGP_GETIMEVERSION");
1245 rc = IMEVER_0400;
1246 break;
1247 case IGP_UI:
1248 TRACE("(%s)\n", "IGP_UI");
1249 rc = 0;
1250 break;
1251 default:
1252 rc = 0;
1254 return rc;
1257 /***********************************************************************
1258 * ImmGetRegisterWordStyleA (IMM32.@)
1260 UINT WINAPI ImmGetRegisterWordStyleA(
1261 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1263 FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
1264 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1265 return 0;
1268 /***********************************************************************
1269 * ImmGetRegisterWordStyleW (IMM32.@)
1271 UINT WINAPI ImmGetRegisterWordStyleW(
1272 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1274 FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
1275 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1276 return 0;
1279 /***********************************************************************
1280 * ImmGetStatusWindowPos (IMM32.@)
1282 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1284 FIXME("(%p, %p): stub\n", hIMC, lpptPos);
1285 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1286 return FALSE;
1289 /***********************************************************************
1290 * ImmGetVirtualKey (IMM32.@)
1292 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1294 OSVERSIONINFOA version;
1295 FIXME("(%p): stub\n", hWnd);
1296 GetVersionExA( &version );
1297 switch(version.dwPlatformId)
1299 case VER_PLATFORM_WIN32_WINDOWS:
1300 return VK_PROCESSKEY;
1301 case VER_PLATFORM_WIN32_NT:
1302 return 0;
1303 default:
1304 FIXME("%d not supported\n",version.dwPlatformId);
1305 return VK_PROCESSKEY;
1309 /***********************************************************************
1310 * ImmInstallIMEA (IMM32.@)
1312 HKL WINAPI ImmInstallIMEA(
1313 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1315 FIXME("(%s, %s): stub\n",
1316 debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText)
1318 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1319 return NULL;
1322 /***********************************************************************
1323 * ImmInstallIMEW (IMM32.@)
1325 HKL WINAPI ImmInstallIMEW(
1326 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1328 FIXME("(%s, %s): stub\n",
1329 debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText)
1331 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1332 return NULL;
1335 /***********************************************************************
1336 * ImmIsIME (IMM32.@)
1338 BOOL WINAPI ImmIsIME(HKL hKL)
1340 TRACE("(%p): semi-stub\n", hKL);
1342 * FIXME: Dead key locales will return TRUE here when they should not
1343 * There is probably a more proper way to check this.
1345 return (root_context != NULL);
1348 /***********************************************************************
1349 * ImmIsUIMessageA (IMM32.@)
1351 BOOL WINAPI ImmIsUIMessageA(
1352 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1354 BOOL rc = FALSE;
1356 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1357 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1358 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1359 (msg == WM_MSIME_SERVICE) ||
1360 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1361 (msg == WM_MSIME_MOUSE) ||
1362 (msg == WM_MSIME_RECONVERTREQUEST) ||
1363 (msg == WM_MSIME_RECONVERT) ||
1364 (msg == WM_MSIME_QUERYPOSITION) ||
1365 (msg == WM_MSIME_DOCUMENTFEED))
1368 if (!hwndDefault)
1369 ImmGetDefaultIMEWnd(NULL);
1371 if (hWndIME == NULL)
1372 PostMessageA(hwndDefault, msg, wParam, lParam);
1374 rc = TRUE;
1376 return rc;
1379 /***********************************************************************
1380 * ImmIsUIMessageW (IMM32.@)
1382 BOOL WINAPI ImmIsUIMessageW(
1383 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1385 BOOL rc = FALSE;
1386 TRACE("(%p, %d, %ld, %ld): stub\n", hWndIME, msg, wParam, lParam);
1387 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1388 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1389 (msg == WM_MSIME_SERVICE) ||
1390 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1391 (msg == WM_MSIME_MOUSE) ||
1392 (msg == WM_MSIME_RECONVERTREQUEST) ||
1393 (msg == WM_MSIME_RECONVERT) ||
1394 (msg == WM_MSIME_QUERYPOSITION) ||
1395 (msg == WM_MSIME_DOCUMENTFEED))
1396 rc = TRUE;
1397 return rc;
1400 /***********************************************************************
1401 * ImmNotifyIME (IMM32.@)
1403 BOOL WINAPI ImmNotifyIME(
1404 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
1406 BOOL rc = FALSE;
1408 TRACE("(%p, %d, %d, %d)\n",
1409 hIMC, dwAction, dwIndex, dwValue);
1411 if (!root_context)
1412 return rc;
1414 switch(dwAction)
1416 case NI_CHANGECANDIDATELIST:
1417 FIXME("%s\n","NI_CHANGECANDIDATELIST");
1418 break;
1419 case NI_CLOSECANDIDATE:
1420 FIXME("%s\n","NI_CLOSECANDIDATE");
1421 break;
1422 case NI_COMPOSITIONSTR:
1423 switch (dwIndex)
1425 case CPS_CANCEL:
1426 TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_CANCEL");
1428 BOOL send;
1429 LPCOMPOSITIONSTRING lpCompStr;
1431 if (pX11DRV_ForceXIMReset)
1432 pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
1434 lpCompStr = ImmLockIMCC(root_context->IMC.hCompStr);
1435 send = (lpCompStr->dwCompStrLen != 0);
1436 ImmUnlockIMCC(root_context->IMC.hCompStr);
1438 ImmDestroyIMCC(root_context->IMC.hCompStr);
1439 root_context->IMC.hCompStr = ImmCreateBlankCompStr();
1441 if (send)
1442 ImmInternalPostIMEMessage(WM_IME_COMPOSITION, 0,
1443 GCS_COMPSTR);
1444 rc = TRUE;
1446 break;
1447 case CPS_COMPLETE:
1448 TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_COMPLETE");
1449 if (hIMC != (HIMC)FROM_IME && pX11DRV_ForceXIMReset)
1450 pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
1452 HIMCC newCompStr;
1453 DWORD cplen = 0;
1454 LPWSTR cpstr;
1455 LPCOMPOSITIONSTRING cs = NULL;
1456 LPBYTE cdata = NULL;
1458 /* clear existing result */
1459 newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0);
1460 ImmDestroyIMCC(root_context->IMC.hCompStr);
1461 root_context->IMC.hCompStr = newCompStr;
1463 if (root_context->IMC.hCompStr)
1465 cdata = ImmLockIMCC(root_context->IMC.hCompStr);
1466 cs = (LPCOMPOSITIONSTRING)cdata;
1467 cplen = cs->dwCompStrLen;
1468 cpstr = (LPWSTR)&(cdata[cs->dwCompStrOffset]);
1469 ImmUnlockIMCC(root_context->IMC.hCompStr);
1471 if (cplen > 0)
1473 WCHAR param = cpstr[0];
1474 newCompStr = updateResultStr(root_context->IMC.hCompStr, cpstr, cplen);
1475 ImmDestroyIMCC(root_context->IMC.hCompStr);
1476 root_context->IMC.hCompStr = newCompStr;
1477 newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
1478 ImmDestroyIMCC(root_context->IMC.hCompStr);
1479 root_context->IMC.hCompStr = newCompStr;
1481 root_context->bRead = FALSE;
1483 ImmInternalPostIMEMessage(WM_IME_COMPOSITION, 0,
1484 GCS_COMPSTR);
1486 ImmInternalPostIMEMessage(WM_IME_COMPOSITION,
1487 param,
1488 GCS_RESULTSTR|GCS_RESULTCLAUSE);
1491 ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION, 0, 0);
1492 root_context->bInComposition = FALSE;
1494 break;
1495 case CPS_CONVERT:
1496 FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_CONVERT");
1497 break;
1498 case CPS_REVERT:
1499 FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_REVERT");
1500 break;
1501 default:
1502 ERR("%s - %s (%i)\n","NI_COMPOSITIONSTR","UNKNOWN",dwIndex);
1503 break;
1505 break;
1506 case NI_IMEMENUSELECTED:
1507 FIXME("%s\n", "NI_IMEMENUSELECTED");
1508 break;
1509 case NI_OPENCANDIDATE:
1510 FIXME("%s\n", "NI_OPENCANDIDATE");
1511 break;
1512 case NI_SELECTCANDIDATESTR:
1513 FIXME("%s\n", "NI_SELECTCANDIDATESTR");
1514 break;
1515 case NI_SETCANDIDATE_PAGESIZE:
1516 FIXME("%s\n", "NI_SETCANDIDATE_PAGESIZE");
1517 break;
1518 case NI_SETCANDIDATE_PAGESTART:
1519 FIXME("%s\n", "NI_SETCANDIDATE_PAGESTART");
1520 break;
1521 default:
1522 ERR("Unknown\n");
1525 return rc;
1528 /***********************************************************************
1529 * ImmRegisterWordA (IMM32.@)
1531 BOOL WINAPI ImmRegisterWordA(
1532 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
1534 FIXME("(%p, %s, %d, %s): stub\n",
1535 hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister)
1537 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1538 return FALSE;
1541 /***********************************************************************
1542 * ImmRegisterWordW (IMM32.@)
1544 BOOL WINAPI ImmRegisterWordW(
1545 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
1547 FIXME("(%p, %s, %d, %s): stub\n",
1548 hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister)
1550 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1551 return FALSE;
1554 /***********************************************************************
1555 * ImmReleaseContext (IMM32.@)
1557 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
1559 static int shown = 0;
1561 if (!shown) {
1562 FIXME("(%p, %p): stub\n", hWnd, hIMC);
1563 shown = 1;
1565 return TRUE;
1568 /***********************************************************************
1569 * ImmSetCandidateWindow (IMM32.@)
1571 BOOL WINAPI ImmSetCandidateWindow(
1572 HIMC hIMC, LPCANDIDATEFORM lpCandidate)
1574 FIXME("(%p, %p): stub\n", hIMC, lpCandidate);
1575 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1576 return FALSE;
1579 /***********************************************************************
1580 * ImmSetCompositionFontA (IMM32.@)
1582 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1584 InputContextData *data = (InputContextData*)hIMC;
1585 TRACE("(%p, %p)\n", hIMC, lplf);
1587 if (!data)
1588 return FALSE;
1590 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
1591 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
1592 LF_FACESIZE);
1594 ImmInternalSendIMENotify(IMN_SETCOMPOSITIONFONT, 0);
1596 if (data->textfont)
1598 DeleteObject(data->textfont);
1599 data->textfont = NULL;
1602 data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
1603 return TRUE;
1606 /***********************************************************************
1607 * ImmSetCompositionFontW (IMM32.@)
1609 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1611 InputContextData *data = (InputContextData*)hIMC;
1612 TRACE("(%p, %p)\n", hIMC, lplf);
1614 if (!data)
1615 return FALSE;
1617 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTW));
1618 ImmInternalSendIMENotify(IMN_SETCOMPOSITIONFONT, 0);
1620 if (data->textfont)
1622 DeleteObject(data->textfont);
1623 data->textfont = NULL;
1625 data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
1626 return TRUE;
1629 /***********************************************************************
1630 * ImmSetCompositionStringA (IMM32.@)
1632 BOOL WINAPI ImmSetCompositionStringA(
1633 HIMC hIMC, DWORD dwIndex,
1634 LPCVOID lpComp, DWORD dwCompLen,
1635 LPCVOID lpRead, DWORD dwReadLen)
1637 DWORD comp_len;
1638 DWORD read_len;
1639 WCHAR *CompBuffer = NULL;
1640 WCHAR *ReadBuffer = NULL;
1641 BOOL rc;
1643 TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
1644 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
1646 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
1647 if (comp_len)
1649 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
1650 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
1653 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
1654 if (read_len)
1656 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
1657 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
1660 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
1661 ReadBuffer, read_len);
1663 HeapFree(GetProcessHeap(), 0, CompBuffer);
1664 HeapFree(GetProcessHeap(), 0, ReadBuffer);
1666 return rc;
1669 /***********************************************************************
1670 * ImmSetCompositionStringW (IMM32.@)
1672 BOOL WINAPI ImmSetCompositionStringW(
1673 HIMC hIMC, DWORD dwIndex,
1674 LPCVOID lpComp, DWORD dwCompLen,
1675 LPCVOID lpRead, DWORD dwReadLen)
1677 DWORD flags = 0;
1678 WCHAR wParam = 0;
1680 TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
1681 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
1684 if (hIMC != (HIMC)FROM_IME)
1685 FIXME("PROBLEM: This only sets the wine level string\n");
1688 * Explanation:
1689 * this sets the composition string in the imm32.dll level
1690 * of the composition buffer. we cannot manipulate the xim level
1691 * buffer, which means that once the xim level buffer changes again
1692 * any call to this function from the application will be lost
1695 if (lpRead && dwReadLen)
1696 FIXME("Reading string unimplemented\n");
1699 * app operating this api to also receive the message from xim
1702 if (dwIndex == SCS_SETSTR)
1704 HIMCC newCompStr;
1705 if (!root_context->bInComposition)
1707 ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION, 0, 0);
1708 root_context->bInComposition = TRUE;
1711 flags = GCS_COMPSTR;
1713 if (dwCompLen && lpComp)
1715 newCompStr = updateCompStr(root_context->IMC.hCompStr, (LPWSTR)lpComp, dwCompLen / sizeof(WCHAR));
1716 ImmDestroyIMCC(root_context->IMC.hCompStr);
1717 root_context->IMC.hCompStr = newCompStr;
1719 wParam = ((const WCHAR*)lpComp)[0];
1720 flags |= GCS_COMPCLAUSE | GCS_COMPATTR | GCS_DELTASTART;
1722 else
1724 newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
1725 ImmDestroyIMCC(root_context->IMC.hCompStr);
1726 root_context->IMC.hCompStr = newCompStr;
1730 UpdateDataInDefaultIMEWindow(hwndDefault,FALSE);
1732 ImmInternalPostIMEMessage(WM_IME_COMPOSITION, wParam, flags);
1734 return TRUE;
1737 /***********************************************************************
1738 * ImmSetCompositionWindow (IMM32.@)
1740 BOOL WINAPI ImmSetCompositionWindow(
1741 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1743 BOOL reshow = FALSE;
1744 InputContextData *data = (InputContextData*)hIMC;
1746 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1747 TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
1748 lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
1749 lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
1751 if (!data)
1752 return FALSE;
1754 memcpy(&data->IMC.cfCompForm,lpCompForm,sizeof(COMPOSITIONFORM));
1756 if (IsWindowVisible(hwndDefault))
1758 reshow = TRUE;
1759 ShowWindow(hwndDefault,SW_HIDE);
1762 /* FIXME: this is a partial stub */
1764 if (reshow)
1765 ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
1767 ImmInternalSendIMENotify(IMN_SETCOMPOSITIONWINDOW, 0);
1768 return TRUE;
1771 /***********************************************************************
1772 * ImmSetConversionStatus (IMM32.@)
1774 BOOL WINAPI ImmSetConversionStatus(
1775 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
1777 static int shown = 0;
1779 if (!shown) {
1780 FIXME("(%p, %d, %d): stub\n",
1781 hIMC, fdwConversion, fdwSentence
1783 shown = 1;
1785 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1786 return FALSE;
1789 /***********************************************************************
1790 * ImmSetOpenStatus (IMM32.@)
1792 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
1794 InputContextData *data = (InputContextData*)hIMC;
1796 TRACE("%p %d\n", hIMC, fOpen);
1798 if (hIMC == (HIMC)FROM_IME)
1800 ImmInternalSetOpenStatus(fOpen);
1801 ImmInternalSendIMENotify(IMN_SETOPENSTATUS, 0);
1802 return TRUE;
1805 if (!data)
1806 return FALSE;
1808 if (fOpen != data->bInternalState)
1810 if (fOpen == FALSE && pX11DRV_ForceXIMReset)
1811 pX11DRV_ForceXIMReset(data->IMC.hWnd);
1813 if (fOpen == FALSE)
1814 ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0);
1815 else
1816 ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0);
1818 ImmInternalSetOpenStatus(fOpen);
1819 ImmInternalSetOpenStatus(!fOpen);
1821 if (data->IMC.fOpen == FALSE)
1822 ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0);
1823 else
1824 ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0);
1826 return FALSE;
1828 return TRUE;
1831 /***********************************************************************
1832 * ImmSetStatusWindowPos (IMM32.@)
1834 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1836 FIXME("(%p, %p): stub\n", hIMC, lpptPos);
1837 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1838 return FALSE;
1841 /***********************************************************************
1842 * ImmSimulateHotKey (IMM32.@)
1844 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
1846 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
1847 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1848 return FALSE;
1851 /***********************************************************************
1852 * ImmUnregisterWordA (IMM32.@)
1854 BOOL WINAPI ImmUnregisterWordA(
1855 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
1857 FIXME("(%p, %s, %d, %s): stub\n",
1858 hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszUnregister)
1860 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1861 return FALSE;
1864 /***********************************************************************
1865 * ImmUnregisterWordW (IMM32.@)
1867 BOOL WINAPI ImmUnregisterWordW(
1868 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
1870 FIXME("(%p, %s, %d, %s): stub\n",
1871 hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszUnregister)
1873 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1874 return FALSE;
1877 /***********************************************************************
1878 * ImmGetImeMenuItemsA (IMM32.@)
1880 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
1881 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
1882 DWORD dwSize)
1884 FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType,
1885 lpImeParentMenu, lpImeMenu, dwSize);
1886 return 0;
1889 /***********************************************************************
1890 * ImmGetImeMenuItemsW (IMM32.@)
1892 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
1893 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
1894 DWORD dwSize)
1896 FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType,
1897 lpImeParentMenu, lpImeMenu, dwSize);
1898 return 0;
1901 /***********************************************************************
1902 * ImmLockIMC(IMM32.@)
1904 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
1906 InputContextData *data = (InputContextData*)hIMC;
1908 if (!data)
1909 return NULL;
1910 data->dwLock++;
1911 return &data->IMC;
1914 /***********************************************************************
1915 * ImmUnlockIMC(IMM32.@)
1917 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
1919 InputContextData *data = (InputContextData*)hIMC;
1920 data->dwLock--;
1921 return (data->dwLock!=0);
1924 /***********************************************************************
1925 * ImmGetIMCLockCount(IMM32.@)
1927 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
1929 InputContextData *data = (InputContextData*)hIMC;
1930 return data->dwLock;
1933 /***********************************************************************
1934 * ImmCreateIMCC(IMM32.@)
1936 HIMCC WINAPI ImmCreateIMCC(DWORD size)
1938 IMCCInternal *internal;
1939 int real_size = size + sizeof(IMCCInternal);
1941 internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size);
1942 if (internal == NULL)
1943 return NULL;
1945 internal->dwSize = size;
1946 return (HIMCC)internal;
1949 /***********************************************************************
1950 * ImmDestroyIMCC(IMM32.@)
1952 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
1954 HeapFree(GetProcessHeap(),0,block);
1955 return NULL;
1958 /***********************************************************************
1959 * ImmLockIMCC(IMM32.@)
1961 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
1963 IMCCInternal *internal;
1964 internal = (IMCCInternal*) imcc;
1966 internal->dwLock ++;
1967 return internal + 1;
1970 /***********************************************************************
1971 * ImmUnlockIMCC(IMM32.@)
1973 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
1975 IMCCInternal *internal;
1976 internal = (IMCCInternal*) imcc;
1978 internal->dwLock --;
1979 return (internal->dwLock!=0);
1982 /***********************************************************************
1983 * ImmGetIMCCLockCount(IMM32.@)
1985 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
1987 IMCCInternal *internal;
1988 internal = (IMCCInternal*) imcc;
1990 return internal->dwLock;
1993 /***********************************************************************
1994 * ImmReSizeIMCC(IMM32.@)
1996 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
1998 IMCCInternal *internal,*newone;
1999 int real_size = size + sizeof(IMCCInternal);
2001 internal = (IMCCInternal*) imcc;
2003 newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size);
2004 newone->dwSize = size;
2006 return newone;
2009 /***********************************************************************
2010 * ImmGetIMCCSize(IMM32.@)
2012 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2014 IMCCInternal *internal;
2015 internal = (IMCCInternal*) imcc;
2017 return internal->dwSize;
2020 /***********************************************************************
2021 * ImmGenerateMessage(IMM32.@)
2023 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2025 InputContextData *data = (InputContextData*)hIMC;
2027 TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
2028 if (data->IMC.dwNumMsgBuf > 0)
2030 LPTRANSMSG lpTransMsg;
2031 INT i;
2033 lpTransMsg = (LPTRANSMSG)ImmLockIMCC(data->IMC.hMsgBuf);
2034 for (i = 0; i < data->IMC.dwNumMsgBuf; i++)
2035 ImmInternalPostIMEMessage(lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
2037 ImmUnlockIMCC(data->IMC.hMsgBuf);
2038 ImmDestroyIMCC(data->IMC.hMsgBuf);
2040 data->IMC.dwNumMsgBuf = 0;
2041 data->IMC.hMsgBuf = NULL;
2044 return TRUE;
2047 /*****
2048 * Internal functions to help with IME window management
2050 static void PaintDefaultIMEWnd(HWND hwnd)
2052 PAINTSTRUCT ps;
2053 RECT rect;
2054 HDC hdc = BeginPaint(hwnd,&ps);
2055 LPCOMPOSITIONSTRING compstr;
2056 LPBYTE compdata = NULL;
2057 HMONITOR monitor;
2058 MONITORINFO mon_info;
2059 INT offX=0, offY=0;
2061 GetClientRect(hwnd,&rect);
2062 FillRect(hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1));
2064 compdata = ImmLockIMCC(root_context->IMC.hCompStr);
2065 compstr = (LPCOMPOSITIONSTRING)compdata;
2067 if (compstr->dwCompStrLen && compstr->dwCompStrOffset)
2069 SIZE size;
2070 POINT pt;
2071 HFONT oldfont = NULL;
2072 LPWSTR CompString;
2074 CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
2075 if (root_context->textfont)
2076 oldfont = SelectObject(hdc,root_context->textfont);
2079 GetTextExtentPoint32W(hdc, CompString, compstr->dwCompStrLen, &size);
2080 pt.x = size.cx;
2081 pt.y = size.cy;
2082 LPtoDP(hdc,&pt,1);
2085 * How this works based on tests on windows:
2086 * CFS_POINT: then we start our window at the point and grow it as large
2087 * as it needs to be for the string.
2088 * CFS_RECT: we still use the ptCurrentPos as a starting point and our
2089 * window is only as large as we need for the string, but we do not
2090 * grow such that our window exceeds the given rect. Wrapping if
2091 * needed and possible. If our ptCurrentPos is outside of our rect
2092 * then no window is displayed.
2093 * CFS_FORCE_POSITION: appears to behave just like CFS_POINT
2094 * maybe becase the default MSIME does not do any IME adjusting.
2096 if (root_context->IMC.cfCompForm.dwStyle != CFS_DEFAULT)
2098 POINT cpt = root_context->IMC.cfCompForm.ptCurrentPos;
2099 ClientToScreen(root_context->IMC.hWnd,&cpt);
2100 rect.left = cpt.x;
2101 rect.top = cpt.y;
2102 rect.right = rect.left + pt.x;
2103 rect.bottom = rect.top + pt.y;
2104 monitor = MonitorFromPoint(cpt, MONITOR_DEFAULTTOPRIMARY);
2106 else /* CFS_DEFAULT */
2108 /* Windows places the default IME window in the bottom left */
2109 HWND target = root_context->IMC.hWnd;
2110 if (!target) target = GetFocus();
2112 GetWindowRect(target,&rect);
2113 rect.top = rect.bottom;
2114 rect.right = rect.left + pt.x + 20;
2115 rect.bottom = rect.top + pt.y + 20;
2116 offX=offY=10;
2117 monitor = MonitorFromWindow(target, MONITOR_DEFAULTTOPRIMARY);
2120 if (root_context->IMC.cfCompForm.dwStyle == CFS_RECT)
2122 RECT client;
2123 client =root_context->IMC.cfCompForm.rcArea;
2124 MapWindowPoints( root_context->IMC.hWnd, 0, (POINT *)&client, 2 );
2125 IntersectRect(&rect,&rect,&client);
2126 /* TODO: Wrap the input if needed */
2129 if (root_context->IMC.cfCompForm.dwStyle == CFS_DEFAULT)
2131 /* make sure we are on the desktop */
2132 mon_info.cbSize = sizeof(mon_info);
2133 GetMonitorInfoW(monitor, &mon_info);
2135 if (rect.bottom > mon_info.rcWork.bottom)
2137 int shift = rect.bottom - mon_info.rcWork.bottom;
2138 rect.top -= shift;
2139 rect.bottom -= shift;
2141 if (rect.left < 0)
2143 rect.right -= rect.left;
2144 rect.left = 0;
2146 if (rect.right > mon_info.rcWork.right)
2148 int shift = rect.right - mon_info.rcWork.right;
2149 rect.left -= shift;
2150 rect.right -= shift;
2154 SetWindowPos(hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE);
2156 TextOutW(hdc, offX,offY, CompString, compstr->dwCompStrLen);
2158 if (oldfont)
2159 SelectObject(hdc,oldfont);
2162 ImmUnlockIMCC(root_context->IMC.hCompStr);
2164 EndPaint(hwnd,&ps);
2167 static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable)
2169 LPCOMPOSITIONSTRING compstr;
2171 if (root_context->IMC.hCompStr)
2172 compstr = ImmLockIMCC(root_context->IMC.hCompStr);
2173 else
2174 compstr = NULL;
2176 if (compstr == NULL || compstr->dwCompStrLen == 0)
2177 ShowWindow(hwndDefault,SW_HIDE);
2178 else if (showable)
2179 ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
2181 RedrawWindow(hwnd,NULL,NULL,RDW_ERASENOW|RDW_INVALIDATE);
2183 if (compstr != NULL)
2184 ImmUnlockIMCC(root_context->IMC.hCompStr);
2188 * The window proc for the default IME window
2190 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam,
2191 LPARAM lParam)
2193 LRESULT rc = 0;
2195 TRACE("Incoming Message 0x%x (0x%08x, 0x%08x)\n", msg, (UINT)wParam,
2196 (UINT)lParam);
2198 switch(msg)
2200 case WM_PAINT:
2201 PaintDefaultIMEWnd(hwnd);
2202 return FALSE;
2204 case WM_NCCREATE:
2205 return TRUE;
2207 case WM_CREATE:
2208 SetWindowTextA(hwnd,"Wine Ime Active");
2209 return TRUE;
2211 case WM_SETFOCUS:
2212 if (wParam)
2213 SetFocus((HWND)wParam);
2214 else
2215 FIXME("Received focus, should never have focus\n");
2216 break;
2217 case WM_IME_COMPOSITION:
2218 TRACE("IME message %s, 0x%x, 0x%x (%i)\n",
2219 "WM_IME_COMPOSITION", (UINT)wParam, (UINT)lParam,
2220 root_context->bRead);
2221 if (lParam & GCS_RESULTSTR)
2222 IMM_PostResult(root_context);
2223 else
2224 UpdateDataInDefaultIMEWindow(hwnd,TRUE);
2225 break;
2226 case WM_IME_STARTCOMPOSITION:
2227 TRACE("IME message %s, 0x%x, 0x%x\n",
2228 "WM_IME_STARTCOMPOSITION", (UINT)wParam, (UINT)lParam);
2229 root_context->IMC.hWnd = GetFocus();
2230 ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
2231 break;
2232 case WM_IME_ENDCOMPOSITION:
2233 TRACE("IME message %s, 0x%x, 0x%x\n",
2234 "WM_IME_ENDCOMPOSITION", (UINT)wParam, (UINT)lParam);
2235 ShowWindow(hwndDefault,SW_HIDE);
2236 break;
2237 case WM_IME_SELECT:
2238 TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_SELECT",
2239 (UINT)wParam, (UINT)lParam);
2240 break;
2241 case WM_IME_CONTROL:
2242 TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_CONTROL",
2243 (UINT)wParam, (UINT)lParam);
2244 rc = 1;
2245 break;
2246 case WM_IME_NOTIFY:
2247 TRACE("!! IME NOTIFY\n");
2248 break;
2249 default:
2250 TRACE("Non-standard message 0x%x\n",msg);
2252 /* check the MSIME messages */
2253 if (msg == WM_MSIME_SERVICE)
2255 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_SERVICE",
2256 (UINT)wParam, (UINT)lParam);
2257 rc = FALSE;
2259 else if (msg == WM_MSIME_RECONVERTOPTIONS)
2261 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTOPTIONS",
2262 (UINT)wParam, (UINT)lParam);
2264 else if (msg == WM_MSIME_MOUSE)
2266 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_MOUSE",
2267 (UINT)wParam, (UINT)lParam);
2269 else if (msg == WM_MSIME_RECONVERTREQUEST)
2271 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTREQUEST",
2272 (UINT)wParam, (UINT)lParam);
2274 else if (msg == WM_MSIME_RECONVERT)
2276 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERT",
2277 (UINT)wParam, (UINT)lParam);
2279 else if (msg == WM_MSIME_QUERYPOSITION)
2281 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_QUERYPOSITION",
2282 (UINT)wParam, (UINT)lParam);
2284 else if (msg == WM_MSIME_DOCUMENTFEED)
2286 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_DOCUMENTFEED",
2287 (UINT)wParam, (UINT)lParam);
2289 /* DefWndProc if not an IME message */
2290 else if (!rc && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2291 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP)))
2292 rc = DefWindowProcW(hwnd,msg,wParam,lParam);
2294 return rc;