imm32: When updating a NULL HIMCC with NULL just return NULL. Handle the NULL HIMCC...
[wine.git] / dlls / imm32 / imm.c
blob58d0e3edb0177a49c65b411e780bd27ef1403221
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 static InputContextData *root_context = NULL;
58 static HWND hwndDefault = NULL;
59 static HANDLE hImeInst;
60 static const WCHAR WC_IMECLASSNAME[] = {'I','M','E',0};
61 static ATOM atIMEClass = 0;
63 /* MSIME messages */
64 static UINT WM_MSIME_SERVICE;
65 static UINT WM_MSIME_RECONVERTOPTIONS;
66 static UINT WM_MSIME_MOUSE;
67 static UINT WM_MSIME_RECONVERTREQUEST;
68 static UINT WM_MSIME_RECONVERT;
69 static UINT WM_MSIME_QUERYPOSITION;
70 static UINT WM_MSIME_DOCUMENTFEED;
73 * prototypes
75 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
76 LPARAM lParam);
77 static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable);
78 static void ImmInternalPostIMEMessage(UINT, WPARAM, LPARAM);
79 static void ImmInternalSetOpenStatus(BOOL fOpen);
80 static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len);
82 static VOID IMM_PostResult(InputContextData *data)
84 unsigned int i;
85 LPCOMPOSITIONSTRING compstr;
86 LPBYTE compdata;
87 LPWSTR ResultStr;
88 HIMCC newCompStr;
90 TRACE("Posting result as IME_CHAR\n");
91 compdata = ImmLockIMCC(root_context->IMC.hCompStr);
92 compstr = (LPCOMPOSITIONSTRING)compdata;
93 ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
95 for (i = 0; i < compstr->dwResultStrLen; i++)
96 ImmInternalPostIMEMessage (WM_IME_CHAR, ResultStr[i], 1);
98 ImmUnlockIMCC(root_context->IMC.hCompStr);
100 /* clear the buffer */
101 newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0);
102 ImmDestroyIMCC(root_context->IMC.hCompStr);
103 root_context->IMC.hCompStr = newCompStr;
106 static void IMM_Register(void)
108 WNDCLASSW wndClass;
109 ZeroMemory(&wndClass, sizeof(WNDCLASSW));
110 wndClass.style = CS_GLOBALCLASS | CS_IME | CS_HREDRAW | CS_VREDRAW;
111 wndClass.lpfnWndProc = (WNDPROC) IME_WindowProc;
112 wndClass.cbClsExtra = 0;
113 wndClass.cbWndExtra = 0;
114 wndClass.hInstance = hImeInst;
115 wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
116 wndClass.hIcon = NULL;
117 wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW +1);
118 wndClass.lpszMenuName = 0;
119 wndClass.lpszClassName = WC_IMECLASSNAME;
120 atIMEClass = RegisterClassW(&wndClass);
123 static void IMM_Unregister(void)
125 if (atIMEClass) {
126 UnregisterClassW(WC_IMECLASSNAME, NULL);
130 static void IMM_RegisterMessages(void)
132 WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");
133 WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions");
134 WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
135 WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
136 WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
137 WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
138 WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
142 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
144 HMODULE x11drv;
146 TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
147 switch (fdwReason)
149 case DLL_PROCESS_ATTACH:
150 DisableThreadLibraryCalls(hInstDLL);
151 hImeInst = hInstDLL;
152 IMM_RegisterMessages();
153 x11drv = GetModuleHandleA("winex11.drv");
154 if (x11drv) pX11DRV_ForceXIMReset = (void *)GetProcAddress( x11drv, "ForceXIMReset");
155 break;
156 case DLL_PROCESS_DETACH:
157 if (hwndDefault)
159 DestroyWindow(hwndDefault);
160 hwndDefault = 0;
162 IMM_Unregister();
163 break;
165 return TRUE;
168 /* for posting messages as the IME */
169 static void ImmInternalPostIMEMessage(UINT msg, WPARAM wParam, LPARAM lParam)
171 HWND target = GetFocus();
172 if (!target)
173 PostMessageW(root_context->IMC.hWnd,msg,wParam,lParam);
174 else
175 PostMessageW(target, msg, wParam, lParam);
178 static LRESULT ImmInternalSendIMENotify(WPARAM notify, LPARAM lParam)
180 HWND target;
182 target = root_context->IMC.hWnd;
183 if (!target) target = GetFocus();
185 if (target)
186 return SendMessageW(target, WM_IME_NOTIFY, notify, lParam);
188 return 0;
191 static void ImmInternalSetOpenStatus(BOOL fOpen)
193 TRACE("Setting internal state to %s\n",(fOpen)?"OPEN":"CLOSED");
195 root_context->IMC.fOpen = fOpen;
196 root_context->bInternalState = fOpen;
198 if (fOpen == FALSE)
200 ShowWindow(hwndDefault,SW_HIDE);
201 ImmDestroyIMCC(root_context->IMC.hCompStr);
202 root_context->IMC.hCompStr = NULL;
204 else
205 ShowWindow(hwndDefault, SW_SHOWNOACTIVATE);
207 ImmInternalSendIMENotify(IMN_SETOPENSTATUS, 0);
210 static int updateField(DWORD origLen, DWORD origOffset, DWORD currentOffset,
211 LPBYTE target, LPBYTE source, DWORD* lenParam,
212 DWORD* offsetParam, BOOL wchars )
214 if (origLen > 0 && origOffset > 0)
216 int truelen = origLen;
217 if (wchars)
218 truelen *= sizeof(WCHAR);
220 memcpy(&target[currentOffset], &source[origOffset], truelen);
222 *lenParam = origLen;
223 *offsetParam = currentOffset;
224 currentOffset += truelen;
226 return currentOffset;
229 static HIMCC updateCompStr(HIMCC old, LPWSTR compstr, DWORD len)
231 /* we need to make sure the CompStr, CompClaus and CompAttr fields are all
232 * set and correct */
233 int needed_size;
234 HIMCC rc;
235 LPBYTE newdata = NULL;
236 LPBYTE olddata = NULL;
237 LPCOMPOSITIONSTRING new_one;
238 LPCOMPOSITIONSTRING lpcs = NULL;
239 INT current_offset = 0;
241 TRACE("%s, %i\n",debugstr_wn(compstr,len),len);
243 if (old == NULL && compstr == NULL && len == 0)
244 return NULL;
246 if (old != NULL)
248 olddata = ImmLockIMCC(old);
249 lpcs = (LPCOMPOSITIONSTRING)olddata;
252 needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
253 len + sizeof(DWORD) * 2;
255 if (lpcs != NULL)
257 needed_size += lpcs->dwCompReadAttrLen;
258 needed_size += lpcs->dwCompReadClauseLen;
259 needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
260 needed_size += lpcs->dwResultReadClauseLen;
261 needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
262 needed_size += lpcs->dwResultClauseLen;
263 needed_size += lpcs->dwResultStrLen * sizeof(DWORD);
264 needed_size += lpcs->dwPrivateSize;
266 rc = ImmCreateIMCC(needed_size);
267 newdata = ImmLockIMCC(rc);
268 new_one = (LPCOMPOSITIONSTRING)newdata;
270 new_one->dwSize = needed_size;
271 current_offset = sizeof(COMPOSITIONSTRING);
272 if (lpcs != NULL)
274 current_offset = updateField(lpcs->dwCompReadAttrLen,
275 lpcs->dwCompReadAttrOffset,
276 current_offset, newdata, olddata,
277 &new_one->dwCompReadAttrLen,
278 &new_one->dwCompReadAttrOffset, FALSE);
280 current_offset = updateField(lpcs->dwCompReadClauseLen,
281 lpcs->dwCompReadClauseOffset,
282 current_offset, newdata, olddata,
283 &new_one->dwCompReadClauseLen,
284 &new_one->dwCompReadClauseOffset, FALSE);
286 current_offset = updateField(lpcs->dwCompReadStrLen,
287 lpcs->dwCompReadStrOffset,
288 current_offset, newdata, olddata,
289 &new_one->dwCompReadStrLen,
290 &new_one->dwCompReadStrOffset, TRUE);
292 /* new CompAttr, CompClause, CompStr, dwCursorPos */
293 new_one->dwDeltaStart = 0;
295 current_offset = updateField(lpcs->dwResultReadClauseLen,
296 lpcs->dwResultReadClauseOffset,
297 current_offset, newdata, olddata,
298 &new_one->dwResultReadClauseLen,
299 &new_one->dwResultReadClauseOffset, FALSE);
301 current_offset = updateField(lpcs->dwResultReadStrLen,
302 lpcs->dwResultReadStrOffset,
303 current_offset, newdata, olddata,
304 &new_one->dwResultReadStrLen,
305 &new_one->dwResultReadStrOffset, TRUE);
307 current_offset = updateField(lpcs->dwResultClauseLen,
308 lpcs->dwResultClauseOffset,
309 current_offset, newdata, olddata,
310 &new_one->dwResultClauseLen,
311 &new_one->dwResultClauseOffset, FALSE);
313 current_offset = updateField(lpcs->dwResultStrLen,
314 lpcs->dwResultStrOffset,
315 current_offset, newdata, olddata,
316 &new_one->dwResultStrLen,
317 &new_one->dwResultStrOffset, TRUE);
319 current_offset = updateField(lpcs->dwPrivateSize,
320 lpcs->dwPrivateOffset,
321 current_offset, newdata, olddata,
322 &new_one->dwPrivateSize,
323 &new_one->dwPrivateOffset, FALSE);
326 /* set new data */
327 /* CompAttr */
328 new_one->dwCompAttrLen = len;
329 if (len > 0)
331 new_one->dwCompAttrOffset = current_offset;
332 memset(&newdata[current_offset],ATTR_INPUT,len);
333 current_offset += len;
336 /* CompClause */
337 if (len > 0)
339 new_one->dwCompClauseLen = sizeof(DWORD) * 2;
340 new_one->dwCompClauseOffset = current_offset;
341 *(DWORD*)(&newdata[current_offset]) = 0;
342 current_offset += sizeof(DWORD);
343 *(DWORD*)(&newdata[current_offset]) = len;
344 current_offset += sizeof(DWORD);
347 /* CompStr */
348 new_one->dwCompStrLen = len;
349 if (len > 0)
351 new_one->dwCompStrOffset = current_offset;
352 memcpy(&newdata[current_offset],compstr,len*sizeof(WCHAR));
355 /* CursorPos */
356 new_one->dwCursorPos = len;
358 ImmUnlockIMCC(rc);
359 if (lpcs)
360 ImmUnlockIMCC(old);
362 return rc;
365 static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len)
367 /* we need to make sure the ResultStr and ResultClause fields are all
368 * set and correct */
369 int needed_size;
370 HIMCC rc;
371 LPBYTE newdata = NULL;
372 LPBYTE olddata = NULL;
373 LPCOMPOSITIONSTRING new_one;
374 LPCOMPOSITIONSTRING lpcs = NULL;
375 INT current_offset = 0;
377 TRACE("%s, %i\n",debugstr_wn(resultstr,len),len);
379 if (old == NULL && resultstr == NULL && len == 0)
380 return NULL;
382 if (old != NULL)
384 olddata = ImmLockIMCC(old);
385 lpcs = (LPCOMPOSITIONSTRING)olddata;
388 needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
389 sizeof(DWORD) * 2;
391 if (lpcs != NULL)
393 needed_size += lpcs->dwCompReadAttrLen;
394 needed_size += lpcs->dwCompReadClauseLen;
395 needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
396 needed_size += lpcs->dwCompAttrLen;
397 needed_size += lpcs->dwCompClauseLen;
398 needed_size += lpcs->dwCompStrLen * sizeof(DWORD);
399 needed_size += lpcs->dwResultReadClauseLen;
400 needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
401 needed_size += lpcs->dwPrivateSize;
403 rc = ImmCreateIMCC(needed_size);
404 newdata = ImmLockIMCC(rc);
405 new_one = (LPCOMPOSITIONSTRING)newdata;
407 new_one->dwSize = needed_size;
408 current_offset = sizeof(COMPOSITIONSTRING);
409 if (lpcs != NULL)
411 current_offset = updateField(lpcs->dwCompReadAttrLen,
412 lpcs->dwCompReadAttrOffset,
413 current_offset, newdata, olddata,
414 &new_one->dwCompReadAttrLen,
415 &new_one->dwCompReadAttrOffset, FALSE);
417 current_offset = updateField(lpcs->dwCompReadClauseLen,
418 lpcs->dwCompReadClauseOffset,
419 current_offset, newdata, olddata,
420 &new_one->dwCompReadClauseLen,
421 &new_one->dwCompReadClauseOffset, FALSE);
423 current_offset = updateField(lpcs->dwCompReadStrLen,
424 lpcs->dwCompReadStrOffset,
425 current_offset, newdata, olddata,
426 &new_one->dwCompReadStrLen,
427 &new_one->dwCompReadStrOffset, TRUE);
429 current_offset = updateField(lpcs->dwCompAttrLen,
430 lpcs->dwCompAttrOffset,
431 current_offset, newdata, olddata,
432 &new_one->dwCompAttrLen,
433 &new_one->dwCompAttrOffset, FALSE);
435 current_offset = updateField(lpcs->dwCompClauseLen,
436 lpcs->dwCompClauseOffset,
437 current_offset, newdata, olddata,
438 &new_one->dwCompClauseLen,
439 &new_one->dwCompClauseOffset, FALSE);
441 current_offset = updateField(lpcs->dwCompStrLen,
442 lpcs->dwCompStrOffset,
443 current_offset, newdata, olddata,
444 &new_one->dwCompStrLen,
445 &new_one->dwCompStrOffset, TRUE);
447 new_one->dwCursorPos = lpcs->dwCursorPos;
448 new_one->dwDeltaStart = 0;
450 current_offset = updateField(lpcs->dwResultReadClauseLen,
451 lpcs->dwResultReadClauseOffset,
452 current_offset, newdata, olddata,
453 &new_one->dwResultReadClauseLen,
454 &new_one->dwResultReadClauseOffset, FALSE);
456 current_offset = updateField(lpcs->dwResultReadStrLen,
457 lpcs->dwResultReadStrOffset,
458 current_offset, newdata, olddata,
459 &new_one->dwResultReadStrLen,
460 &new_one->dwResultReadStrOffset, TRUE);
462 /* new ResultClause , ResultStr */
464 current_offset = updateField(lpcs->dwPrivateSize,
465 lpcs->dwPrivateOffset,
466 current_offset, newdata, olddata,
467 &new_one->dwPrivateSize,
468 &new_one->dwPrivateOffset, FALSE);
471 /* set new data */
472 /* ResultClause */
473 if (len > 0)
475 new_one->dwResultClauseLen = sizeof(DWORD) * 2;
476 new_one->dwResultClauseOffset = current_offset;
477 *(DWORD*)(&newdata[current_offset]) = 0;
478 current_offset += sizeof(DWORD);
479 *(DWORD*)(&newdata[current_offset]) = len;
480 current_offset += sizeof(DWORD);
483 /* ResultStr */
484 new_one->dwResultStrLen = len;
485 if (len > 0)
487 new_one->dwResultStrOffset = current_offset;
488 memcpy(&newdata[current_offset],resultstr,len*sizeof(WCHAR));
490 ImmUnlockIMCC(rc);
491 if (lpcs)
492 ImmUnlockIMCC(old);
494 return rc;
499 /***********************************************************************
500 * ImmAssociateContext (IMM32.@)
502 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
504 InputContextData *data = (InputContextData*)hIMC;
506 WARN("(%p, %p): semi-stub\n", hWnd, hIMC);
508 if (!hIMC)
509 return NULL;
512 * WINE SPECIFIC! MAY CONFLICT
513 * associate the root context we have an XIM created
515 if (hWnd == 0x000)
517 root_context = (InputContextData*)hIMC;
521 * If already associated just return
523 if (data->IMC.hWnd == hWnd)
524 return hIMC;
526 if (IsWindow(data->IMC.hWnd))
529 * Post a message that your context is switching
531 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
534 data->IMC.hWnd = hWnd;
536 if (IsWindow(data->IMC.hWnd))
539 * Post a message that your context is switching
541 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
545 * TODO: We need to keep track of the old context associated
546 * with a window and return it for now we will return NULL;
548 return NULL;
551 /***********************************************************************
552 * ImmAssociateContextEx (IMM32.@)
554 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
556 FIXME("(%p, %p, %d): stub\n", hWnd, hIMC, dwFlags);
557 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
558 return FALSE;
561 /***********************************************************************
562 * ImmConfigureIMEA (IMM32.@)
564 BOOL WINAPI ImmConfigureIMEA(
565 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
567 FIXME("(%p, %p, %d, %p): stub\n",
568 hKL, hWnd, dwMode, lpData
570 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
571 return FALSE;
574 /***********************************************************************
575 * ImmConfigureIMEW (IMM32.@)
577 BOOL WINAPI ImmConfigureIMEW(
578 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
580 FIXME("(%p, %p, %d, %p): stub\n",
581 hKL, hWnd, dwMode, lpData
583 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
584 return FALSE;
587 /***********************************************************************
588 * ImmCreateContext (IMM32.@)
590 HIMC WINAPI ImmCreateContext(void)
592 InputContextData *new_context;
594 new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
596 return (HIMC)new_context;
599 /***********************************************************************
600 * ImmDestroyContext (IMM32.@)
602 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
604 InputContextData *data = (InputContextData*)hIMC;
606 TRACE("Destroying %p\n",hIMC);
608 if (hIMC)
610 ImmDestroyIMCC(root_context->IMC.hCompStr);
611 ImmDestroyIMCC(root_context->IMC.hCandInfo);
612 ImmDestroyIMCC(root_context->IMC.hGuideLine);
613 ImmDestroyIMCC(root_context->IMC.hPrivate);
614 ImmDestroyIMCC(root_context->IMC.hMsgBuf);
616 if (data->textfont)
618 DeleteObject(data->textfont);
619 data->textfont = NULL;
622 HeapFree(GetProcessHeap(),0,data);
624 return TRUE;
627 /***********************************************************************
628 * ImmDisableIME (IMM32.@)
630 BOOL WINAPI ImmDisableIME(DWORD idThread)
632 FIXME("(%d): stub\n", idThread);
633 return TRUE;
636 /***********************************************************************
637 * ImmEnumRegisterWordA (IMM32.@)
639 UINT WINAPI ImmEnumRegisterWordA(
640 HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
641 LPCSTR lpszReading, DWORD dwStyle,
642 LPCSTR lpszRegister, LPVOID lpData)
644 FIXME("(%p, %p, %s, %d, %s, %p): stub\n",
645 hKL, lpfnEnumProc,
646 debugstr_a(lpszReading), dwStyle,
647 debugstr_a(lpszRegister), lpData
649 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
650 return 0;
653 /***********************************************************************
654 * ImmEnumRegisterWordW (IMM32.@)
656 UINT WINAPI ImmEnumRegisterWordW(
657 HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
658 LPCWSTR lpszReading, DWORD dwStyle,
659 LPCWSTR lpszRegister, LPVOID lpData)
661 FIXME("(%p, %p, %s, %d, %s, %p): stub\n",
662 hKL, lpfnEnumProc,
663 debugstr_w(lpszReading), dwStyle,
664 debugstr_w(lpszRegister), lpData
666 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
667 return 0;
670 /***********************************************************************
671 * ImmEscapeA (IMM32.@)
673 LRESULT WINAPI ImmEscapeA(
674 HKL hKL, HIMC hIMC,
675 UINT uEscape, LPVOID lpData)
677 FIXME("(%p, %p, %d, %p): stub\n",
678 hKL, hIMC, uEscape, lpData
680 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
681 return 0;
684 /***********************************************************************
685 * ImmEscapeW (IMM32.@)
687 LRESULT WINAPI ImmEscapeW(
688 HKL hKL, HIMC hIMC,
689 UINT uEscape, LPVOID lpData)
691 FIXME("(%p, %p, %d, %p): stub\n",
692 hKL, hIMC, uEscape, lpData
694 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
695 return 0;
698 /***********************************************************************
699 * ImmGetCandidateListA (IMM32.@)
701 DWORD WINAPI ImmGetCandidateListA(
702 HIMC hIMC, DWORD deIndex,
703 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
705 FIXME("(%p, %d, %p, %d): stub\n",
706 hIMC, deIndex,
707 lpCandList, dwBufLen
709 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
710 return 0;
713 /***********************************************************************
714 * ImmGetCandidateListCountA (IMM32.@)
716 DWORD WINAPI ImmGetCandidateListCountA(
717 HIMC hIMC, LPDWORD lpdwListCount)
719 FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
720 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
721 return 0;
724 /***********************************************************************
725 * ImmGetCandidateListCountW (IMM32.@)
727 DWORD WINAPI ImmGetCandidateListCountW(
728 HIMC hIMC, LPDWORD lpdwListCount)
730 FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
731 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
732 return 0;
735 /***********************************************************************
736 * ImmGetCandidateListW (IMM32.@)
738 DWORD WINAPI ImmGetCandidateListW(
739 HIMC hIMC, DWORD deIndex,
740 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
742 FIXME("(%p, %d, %p, %d): stub\n",
743 hIMC, deIndex,
744 lpCandList, dwBufLen
746 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
747 return 0;
750 /***********************************************************************
751 * ImmGetCandidateWindow (IMM32.@)
753 BOOL WINAPI ImmGetCandidateWindow(
754 HIMC hIMC, DWORD dwBufLen, LPCANDIDATEFORM lpCandidate)
756 FIXME("(%p, %d, %p): stub\n", hIMC, dwBufLen, lpCandidate);
757 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
758 return FALSE;
761 /***********************************************************************
762 * ImmGetCompositionFontA (IMM32.@)
764 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
766 FIXME("(%p, %p): stub\n", hIMC, lplf);
767 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
768 return FALSE;
771 /***********************************************************************
772 * ImmGetCompositionFontW (IMM32.@)
774 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
776 FIXME("(%p, %p): stub\n", hIMC, lplf);
777 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
778 return FALSE;
781 /***********************************************************************
782 * ImmGetCompositionStringA (IMM32.@)
784 LONG WINAPI ImmGetCompositionStringA(
785 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
787 CHAR *buf;
788 LONG rc = 0;
789 InputContextData *data = (InputContextData*)hIMC;
790 LPCOMPOSITIONSTRING compstr;
791 LPBYTE compdata;
793 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
795 if (!data)
796 return FALSE;
798 if (!data->IMC.hCompStr)
799 return FALSE;
801 compdata = ImmLockIMCC(data->IMC.hCompStr);
802 compstr = (LPCOMPOSITIONSTRING)compdata;
804 if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 &&
805 compstr->dwResultStrOffset > 0)
807 LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
809 TRACE("GSC_RESULTSTR %p %i\n",ResultStr,
810 compstr->dwResultStrLen);
812 buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwResultStrLen * 3 );
813 rc = WideCharToMultiByte(CP_ACP, 0, ResultStr,
814 compstr->dwResultStrLen , buf,
815 compstr->dwResultStrLen * 3, NULL, NULL);
816 if (dwBufLen >= rc)
817 memcpy(lpBuf,buf,rc);
819 data->bRead = TRUE;
820 HeapFree( GetProcessHeap(), 0, buf );
822 else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 &&
823 compstr->dwCompStrOffset > 0)
825 LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
827 TRACE("GSC_COMPSTR %p %i\n", CompString, compstr->dwCompStrLen);
829 buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwCompStrLen * 3 );
830 rc = WideCharToMultiByte(CP_ACP, 0, CompString,
831 compstr->dwCompStrLen, buf,
832 compstr->dwCompStrLen * 3, NULL, NULL);
833 if (dwBufLen >= rc)
834 memcpy(lpBuf,buf,rc);
835 HeapFree( GetProcessHeap(), 0, buf );
837 else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 &&
838 compstr->dwCompAttrOffset > 0)
840 LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset);
841 TRACE("GSC_COMPATTR %p %i\n", Compattr , compstr->dwCompAttrLen);
843 rc = compstr->dwCompAttrLen;
844 if (dwBufLen >= rc)
845 memcpy(lpBuf,Compattr,rc);
847 else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 &&
848 compstr->dwCompClauseOffset > 0)
850 LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset);
851 TRACE("GSC_COMPCLAUSE %p %i\n", Compclause, compstr->dwCompClauseLen);
853 rc = compstr->dwCompClauseLen;
854 if (dwBufLen >= compstr->dwCompClauseLen)
855 memcpy(lpBuf,Compclause,rc);
857 else if (dwIndex == GCS_RESULTCLAUSE && compstr->dwResultClauseLen > 0 &&
858 compstr->dwResultClauseOffset > 0)
860 LPWSTR Resultclause = (LPWSTR)(compdata + compstr->dwResultClauseOffset);
861 TRACE("GSC_RESULTCLAUSE %p %i\n", Resultclause, compstr->dwResultClauseLen);
863 rc = compstr->dwResultClauseLen;
864 if (dwBufLen >= compstr->dwResultClauseLen)
865 memcpy(lpBuf,Resultclause,rc);
867 else if (dwIndex == GCS_CURSORPOS)
869 TRACE("GSC_CURSORPOS\n");
870 rc = compstr->dwCursorPos;
872 else if (dwIndex == GCS_DELTASTART)
874 TRACE("GCS_DELTASTART\n");
875 rc = compstr->dwDeltaStart;
877 else
879 FIXME("Unhandled index 0x%x\n",dwIndex);
882 ImmUnlockIMCC(data->IMC.hCompStr);
884 return rc;
887 /***********************************************************************
888 * ImmGetCompositionStringW (IMM32.@)
890 LONG WINAPI ImmGetCompositionStringW(
891 HIMC hIMC, DWORD dwIndex,
892 LPVOID lpBuf, DWORD dwBufLen)
894 LONG rc = 0;
895 InputContextData *data = (InputContextData*)hIMC;
896 LPCOMPOSITIONSTRING compstr;
897 LPBYTE compdata;
899 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
901 if (!data)
902 return FALSE;
904 if (!data->IMC.hCompStr)
905 return FALSE;
907 compdata = ImmLockIMCC(data->IMC.hCompStr);
908 compstr = (LPCOMPOSITIONSTRING)compdata;
910 if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 &&
911 compstr->dwResultStrOffset > 0)
913 LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
914 data->bRead = TRUE;
915 rc = compstr->dwResultStrLen * sizeof(WCHAR);
917 if (dwBufLen >= rc)
918 memcpy(lpBuf,ResultStr,rc);
920 else if (dwIndex == GCS_RESULTREADSTR && compstr->dwResultReadStrLen > 0 &&
921 compstr->dwResultReadStrOffset > 0)
923 LPWSTR ResultReadString = (LPWSTR)(compdata + compstr->dwResultReadStrOffset);
925 rc = compstr->dwResultReadStrLen * sizeof(WCHAR);
926 if (dwBufLen >= rc)
927 memcpy(lpBuf,ResultReadString,rc);
929 else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 &&
930 compstr->dwCompStrOffset > 0)
932 LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
933 rc = compstr->dwCompStrLen * sizeof(WCHAR);
934 if (dwBufLen >= rc)
935 memcpy(lpBuf,CompString,rc);
937 else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 &&
938 compstr->dwCompAttrOffset > 0)
941 LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset);
943 rc = compstr->dwCompAttrLen;
944 if (dwBufLen >= rc)
945 memcpy(lpBuf,Compattr,rc);
947 else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 &&
948 compstr->dwCompClauseOffset > 0)
950 LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset);
952 rc = compstr->dwCompClauseLen;
953 if (dwBufLen >= compstr->dwCompClauseLen)
954 memcpy(lpBuf,Compclause,rc);
956 else if (dwIndex == GCS_COMPREADSTR && compstr->dwCompReadStrLen > 0 &&
957 compstr->dwCompReadStrOffset > 0)
959 LPWSTR CompReadString = (LPWSTR)(compdata + compstr->dwCompReadStrOffset);
961 rc = compstr->dwCompReadStrLen * sizeof(WCHAR);
963 if (dwBufLen >= rc)
964 memcpy(lpBuf,CompReadString,rc);
966 else if (dwIndex == GCS_CURSORPOS)
968 TRACE("GSC_CURSORPOS\n");
969 rc = compstr->dwCursorPos;
971 else if (dwIndex == GCS_DELTASTART)
973 TRACE("GCS_DELTASTART\n");
974 rc = compstr->dwDeltaStart;
976 else
978 FIXME("Unhandled index 0x%x\n",dwIndex);
981 ImmUnlockIMCC(data->IMC.hCompStr);
983 return rc;
986 /***********************************************************************
987 * ImmGetCompositionWindow (IMM32.@)
989 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
991 InputContextData *data = (InputContextData*)hIMC;
993 TRACE("(%p, %p)\n", hIMC, lpCompForm);
995 if (!data)
996 return FALSE;
998 memcpy(lpCompForm,&(data->IMC.cfCompForm),sizeof(COMPOSITIONFORM));
999 return 1;
1002 /***********************************************************************
1003 * ImmGetContext (IMM32.@)
1006 HIMC WINAPI ImmGetContext(HWND hWnd)
1008 TRACE("%p\n", hWnd);
1010 if (!root_context)
1011 return NULL;
1013 root_context->IMC.hWnd = hWnd;
1014 return (HIMC)root_context;
1017 /***********************************************************************
1018 * ImmGetConversionListA (IMM32.@)
1020 DWORD WINAPI ImmGetConversionListA(
1021 HKL hKL, HIMC hIMC,
1022 LPCSTR pSrc, LPCANDIDATELIST lpDst,
1023 DWORD dwBufLen, UINT uFlag)
1025 FIXME("(%p, %p, %s, %p, %d, %d): stub\n",
1026 hKL, hIMC, debugstr_a(pSrc), lpDst, dwBufLen, uFlag
1028 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1029 return 0;
1032 /***********************************************************************
1033 * ImmGetConversionListW (IMM32.@)
1035 DWORD WINAPI ImmGetConversionListW(
1036 HKL hKL, HIMC hIMC,
1037 LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1038 DWORD dwBufLen, UINT uFlag)
1040 FIXME("(%p, %p, %s, %p, %d, %d): stub\n",
1041 hKL, hIMC, debugstr_w(pSrc), lpDst, dwBufLen, uFlag
1043 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1044 return 0;
1047 /***********************************************************************
1048 * ImmGetConversionStatus (IMM32.@)
1050 BOOL WINAPI ImmGetConversionStatus(
1051 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1053 TRACE("(%p, %p, %p): best guess\n", hIMC, lpfdwConversion, lpfdwSentence);
1054 if (lpfdwConversion)
1055 *lpfdwConversion = IME_CMODE_NATIVE;
1056 if (lpfdwSentence)
1057 *lpfdwSentence = IME_SMODE_NONE;
1058 return TRUE;
1061 /***********************************************************************
1062 * ImmGetDefaultIMEWnd (IMM32.@)
1064 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1066 static int shown = 0;
1068 if (!shown) {
1069 FIXME("(%p - %p %p ): semi-stub\n", hWnd,hwndDefault, root_context);
1070 shown = 1;
1073 if (hwndDefault == NULL)
1075 static const WCHAR the_name[] = {'I','M','E','\0'};
1077 IMM_Register();
1078 hwndDefault = CreateWindowExW( WS_EX_TOOLWINDOW, WC_IMECLASSNAME,
1079 the_name, WS_POPUP, 0, 0, 1, 1, 0, 0,
1080 hImeInst, 0);
1082 TRACE("Default created (%p)\n",hwndDefault);
1085 return (HWND)hwndDefault;
1088 /***********************************************************************
1089 * ImmGetDescriptionA (IMM32.@)
1091 UINT WINAPI ImmGetDescriptionA(
1092 HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1094 WCHAR *buf;
1095 DWORD len;
1097 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1099 /* find out how many characters in the unicode buffer */
1100 len = ImmGetDescriptionW( hKL, NULL, 0 );
1102 /* allocate a buffer of that size */
1103 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1104 if( !buf )
1105 return 0;
1107 /* fetch the unicode buffer */
1108 len = ImmGetDescriptionW( hKL, buf, len + 1 );
1110 /* convert it back to ASCII */
1111 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1112 lpszDescription, uBufLen, NULL, NULL );
1114 HeapFree( GetProcessHeap(), 0, buf );
1116 return len;
1119 /***********************************************************************
1120 * ImmGetDescriptionW (IMM32.@)
1122 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1124 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1126 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1128 if (!uBufLen) return lstrlenW( name );
1129 lstrcpynW( lpszDescription, name, uBufLen );
1130 return lstrlenW( lpszDescription );
1133 /***********************************************************************
1134 * ImmGetGuideLineA (IMM32.@)
1136 DWORD WINAPI ImmGetGuideLineA(
1137 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1139 FIXME("(%p, %d, %s, %d): stub\n",
1140 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1142 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1143 return 0;
1146 /***********************************************************************
1147 * ImmGetGuideLineW (IMM32.@)
1149 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1151 FIXME("(%p, %d, %s, %d): stub\n",
1152 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1154 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1155 return 0;
1158 /***********************************************************************
1159 * ImmGetIMEFileNameA (IMM32.@)
1161 UINT WINAPI ImmGetIMEFileNameA(
1162 HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1164 FIXME("(%p, %p, %d): stub\n", hKL, lpszFileName, uBufLen);
1165 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1166 return 0;
1169 /***********************************************************************
1170 * ImmGetIMEFileNameW (IMM32.@)
1172 UINT WINAPI ImmGetIMEFileNameW(
1173 HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1175 FIXME("(%p, %p, %d): stub\n", hKL, lpszFileName, uBufLen);
1176 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1177 return 0;
1180 /***********************************************************************
1181 * ImmGetOpenStatus (IMM32.@)
1183 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1185 InputContextData *data = (InputContextData*)hIMC;
1187 if (!data)
1188 return FALSE;
1189 FIXME("(%p): semi-stub\n", hIMC);
1191 return data->IMC.fOpen;
1194 /***********************************************************************
1195 * ImmGetProperty (IMM32.@)
1197 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1199 DWORD rc = 0;
1200 TRACE("(%p, %d)\n", hKL, fdwIndex);
1202 switch (fdwIndex)
1204 case IGP_PROPERTY:
1205 TRACE("(%s)\n", "IGP_PROPERTY");
1206 rc = IME_PROP_UNICODE | IME_PROP_AT_CARET;
1207 break;
1208 case IGP_CONVERSION:
1209 FIXME("(%s)\n", "IGP_CONVERSION");
1210 rc = IME_CMODE_NATIVE;
1211 break;
1212 case IGP_SENTENCE:
1213 FIXME("%s)\n", "IGP_SENTENCE");
1214 rc = IME_SMODE_AUTOMATIC;
1215 break;
1216 case IGP_SETCOMPSTR:
1217 TRACE("(%s)\n", "IGP_SETCOMPSTR");
1218 rc = 0;
1219 break;
1220 case IGP_SELECT:
1221 TRACE("(%s)\n", "IGP_SELECT");
1222 rc = SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE;
1223 break;
1224 case IGP_GETIMEVERSION:
1225 TRACE("(%s)\n", "IGP_GETIMEVERSION");
1226 rc = IMEVER_0400;
1227 break;
1228 case IGP_UI:
1229 TRACE("(%s)\n", "IGP_UI");
1230 rc = 0;
1231 break;
1232 default:
1233 rc = 0;
1235 return rc;
1238 /***********************************************************************
1239 * ImmGetRegisterWordStyleA (IMM32.@)
1241 UINT WINAPI ImmGetRegisterWordStyleA(
1242 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1244 FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
1245 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1246 return 0;
1249 /***********************************************************************
1250 * ImmGetRegisterWordStyleW (IMM32.@)
1252 UINT WINAPI ImmGetRegisterWordStyleW(
1253 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1255 FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
1256 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1257 return 0;
1260 /***********************************************************************
1261 * ImmGetStatusWindowPos (IMM32.@)
1263 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1265 FIXME("(%p, %p): stub\n", hIMC, lpptPos);
1266 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1267 return FALSE;
1270 /***********************************************************************
1271 * ImmGetVirtualKey (IMM32.@)
1273 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1275 OSVERSIONINFOA version;
1276 FIXME("(%p): stub\n", hWnd);
1277 GetVersionExA( &version );
1278 switch(version.dwPlatformId)
1280 case VER_PLATFORM_WIN32_WINDOWS:
1281 return VK_PROCESSKEY;
1282 case VER_PLATFORM_WIN32_NT:
1283 return 0;
1284 default:
1285 FIXME("%d not supported\n",version.dwPlatformId);
1286 return VK_PROCESSKEY;
1290 /***********************************************************************
1291 * ImmInstallIMEA (IMM32.@)
1293 HKL WINAPI ImmInstallIMEA(
1294 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1296 FIXME("(%s, %s): stub\n",
1297 debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText)
1299 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1300 return NULL;
1303 /***********************************************************************
1304 * ImmInstallIMEW (IMM32.@)
1306 HKL WINAPI ImmInstallIMEW(
1307 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1309 FIXME("(%s, %s): stub\n",
1310 debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText)
1312 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1313 return NULL;
1316 /***********************************************************************
1317 * ImmIsIME (IMM32.@)
1319 BOOL WINAPI ImmIsIME(HKL hKL)
1321 TRACE("(%p): semi-stub\n", hKL);
1323 * FIXME: Dead key locales will return TRUE here when they should not
1324 * There is probably a more proper way to check this.
1326 return (root_context != NULL);
1329 /***********************************************************************
1330 * ImmIsUIMessageA (IMM32.@)
1332 BOOL WINAPI ImmIsUIMessageA(
1333 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1335 BOOL rc = FALSE;
1337 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1338 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1339 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1340 (msg == WM_MSIME_SERVICE) ||
1341 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1342 (msg == WM_MSIME_MOUSE) ||
1343 (msg == WM_MSIME_RECONVERTREQUEST) ||
1344 (msg == WM_MSIME_RECONVERT) ||
1345 (msg == WM_MSIME_QUERYPOSITION) ||
1346 (msg == WM_MSIME_DOCUMENTFEED))
1349 if (!hwndDefault)
1350 ImmGetDefaultIMEWnd(NULL);
1352 if (hWndIME == NULL)
1353 PostMessageA(hwndDefault, msg, wParam, lParam);
1355 rc = TRUE;
1357 return rc;
1360 /***********************************************************************
1361 * ImmIsUIMessageW (IMM32.@)
1363 BOOL WINAPI ImmIsUIMessageW(
1364 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1366 BOOL rc = FALSE;
1367 TRACE("(%p, %d, %ld, %ld): stub\n", hWndIME, msg, wParam, lParam);
1368 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1369 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1370 (msg == WM_MSIME_SERVICE) ||
1371 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1372 (msg == WM_MSIME_MOUSE) ||
1373 (msg == WM_MSIME_RECONVERTREQUEST) ||
1374 (msg == WM_MSIME_RECONVERT) ||
1375 (msg == WM_MSIME_QUERYPOSITION) ||
1376 (msg == WM_MSIME_DOCUMENTFEED))
1377 rc = TRUE;
1378 return rc;
1381 /***********************************************************************
1382 * ImmNotifyIME (IMM32.@)
1384 BOOL WINAPI ImmNotifyIME(
1385 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
1387 BOOL rc = FALSE;
1389 TRACE("(%p, %d, %d, %d)\n",
1390 hIMC, dwAction, dwIndex, dwValue);
1392 if (!root_context)
1393 return rc;
1395 switch(dwAction)
1397 case NI_CHANGECANDIDATELIST:
1398 FIXME("%s\n","NI_CHANGECANDIDATELIST");
1399 break;
1400 case NI_CLOSECANDIDATE:
1401 FIXME("%s\n","NI_CLOSECANDIDATE");
1402 break;
1403 case NI_COMPOSITIONSTR:
1404 switch (dwIndex)
1406 case CPS_CANCEL:
1407 TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_CANCEL");
1409 HIMCC newCompStr;
1410 if (pX11DRV_ForceXIMReset)
1411 pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
1413 newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
1414 ImmDestroyIMCC(root_context->IMC.hCompStr);
1415 root_context->IMC.hCompStr = newCompStr;
1417 ImmInternalPostIMEMessage(WM_IME_COMPOSITION, 0,
1418 GCS_COMPSTR);
1419 rc = TRUE;
1421 break;
1422 case CPS_COMPLETE:
1423 TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_COMPLETE");
1424 if (hIMC != (HIMC)FROM_IME && pX11DRV_ForceXIMReset)
1425 pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
1427 HIMCC newCompStr;
1428 DWORD cplen = 0;
1429 LPWSTR cpstr;
1430 LPCOMPOSITIONSTRING cs = NULL;
1431 LPBYTE cdata = NULL;
1433 /* clear existing result */
1434 newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0);
1435 ImmDestroyIMCC(root_context->IMC.hCompStr);
1436 root_context->IMC.hCompStr = newCompStr;
1438 if (root_context->IMC.hCompStr)
1440 cdata = ImmLockIMCC(root_context->IMC.hCompStr);
1441 cs = (LPCOMPOSITIONSTRING)cdata;
1442 cplen = cs->dwCompStrLen;
1443 cpstr = (LPWSTR)&(cdata[cs->dwCompStrOffset]);
1444 ImmUnlockIMCC(root_context->IMC.hCompStr);
1446 if (cplen > 0)
1448 WCHAR param = cpstr[0];
1449 newCompStr = updateResultStr(root_context->IMC.hCompStr, cpstr, cplen);
1450 ImmDestroyIMCC(root_context->IMC.hCompStr);
1451 root_context->IMC.hCompStr = newCompStr;
1452 newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
1453 ImmDestroyIMCC(root_context->IMC.hCompStr);
1454 root_context->IMC.hCompStr = newCompStr;
1456 root_context->bRead = FALSE;
1458 ImmInternalPostIMEMessage(WM_IME_COMPOSITION, 0,
1459 GCS_COMPSTR);
1461 ImmInternalPostIMEMessage(WM_IME_COMPOSITION,
1462 param,
1463 GCS_RESULTSTR|GCS_RESULTCLAUSE);
1466 ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION, 0, 0);
1467 root_context->bInComposition = FALSE;
1469 break;
1470 case CPS_CONVERT:
1471 FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_CONVERT");
1472 break;
1473 case CPS_REVERT:
1474 FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_REVERT");
1475 break;
1476 default:
1477 ERR("%s - %s (%i)\n","NI_COMPOSITIONSTR","UNKNOWN",dwIndex);
1478 break;
1480 break;
1481 case NI_IMEMENUSELECTED:
1482 FIXME("%s\n", "NI_IMEMENUSELECTED");
1483 break;
1484 case NI_OPENCANDIDATE:
1485 FIXME("%s\n", "NI_OPENCANDIDATE");
1486 break;
1487 case NI_SELECTCANDIDATESTR:
1488 FIXME("%s\n", "NI_SELECTCANDIDATESTR");
1489 break;
1490 case NI_SETCANDIDATE_PAGESIZE:
1491 FIXME("%s\n", "NI_SETCANDIDATE_PAGESIZE");
1492 break;
1493 case NI_SETCANDIDATE_PAGESTART:
1494 FIXME("%s\n", "NI_SETCANDIDATE_PAGESTART");
1495 break;
1496 default:
1497 ERR("Unknown\n");
1500 return rc;
1503 /***********************************************************************
1504 * ImmRegisterWordA (IMM32.@)
1506 BOOL WINAPI ImmRegisterWordA(
1507 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
1509 FIXME("(%p, %s, %d, %s): stub\n",
1510 hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister)
1512 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1513 return FALSE;
1516 /***********************************************************************
1517 * ImmRegisterWordW (IMM32.@)
1519 BOOL WINAPI ImmRegisterWordW(
1520 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
1522 FIXME("(%p, %s, %d, %s): stub\n",
1523 hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister)
1525 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1526 return FALSE;
1529 /***********************************************************************
1530 * ImmReleaseContext (IMM32.@)
1532 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
1534 static int shown = 0;
1536 if (!shown) {
1537 FIXME("(%p, %p): stub\n", hWnd, hIMC);
1538 shown = 1;
1540 return TRUE;
1543 /***********************************************************************
1544 * ImmSetCandidateWindow (IMM32.@)
1546 BOOL WINAPI ImmSetCandidateWindow(
1547 HIMC hIMC, LPCANDIDATEFORM lpCandidate)
1549 FIXME("(%p, %p): stub\n", hIMC, lpCandidate);
1550 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1551 return FALSE;
1554 /***********************************************************************
1555 * ImmSetCompositionFontA (IMM32.@)
1557 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1559 InputContextData *data = (InputContextData*)hIMC;
1560 TRACE("(%p, %p)\n", hIMC, lplf);
1562 if (!data)
1563 return FALSE;
1565 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
1566 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
1567 LF_FACESIZE);
1569 ImmInternalSendIMENotify(IMN_SETCOMPOSITIONFONT, 0);
1571 if (data->textfont)
1573 DeleteObject(data->textfont);
1574 data->textfont = NULL;
1577 data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
1578 return TRUE;
1581 /***********************************************************************
1582 * ImmSetCompositionFontW (IMM32.@)
1584 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1586 InputContextData *data = (InputContextData*)hIMC;
1587 TRACE("(%p, %p)\n", hIMC, lplf);
1589 if (!data)
1590 return FALSE;
1592 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTW));
1593 ImmInternalSendIMENotify(IMN_SETCOMPOSITIONFONT, 0);
1595 if (data->textfont)
1597 DeleteObject(data->textfont);
1598 data->textfont = NULL;
1600 data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
1601 return TRUE;
1604 /***********************************************************************
1605 * ImmSetCompositionStringA (IMM32.@)
1607 BOOL WINAPI ImmSetCompositionStringA(
1608 HIMC hIMC, DWORD dwIndex,
1609 LPCVOID lpComp, DWORD dwCompLen,
1610 LPCVOID lpRead, DWORD dwReadLen)
1612 DWORD comp_len;
1613 DWORD read_len;
1614 WCHAR *CompBuffer = NULL;
1615 WCHAR *ReadBuffer = NULL;
1616 BOOL rc;
1618 TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
1619 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
1621 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
1622 if (comp_len)
1624 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
1625 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
1628 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
1629 if (read_len)
1631 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
1632 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
1635 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
1636 ReadBuffer, read_len);
1638 HeapFree(GetProcessHeap(), 0, CompBuffer);
1639 HeapFree(GetProcessHeap(), 0, ReadBuffer);
1641 return rc;
1644 /***********************************************************************
1645 * ImmSetCompositionStringW (IMM32.@)
1647 BOOL WINAPI ImmSetCompositionStringW(
1648 HIMC hIMC, DWORD dwIndex,
1649 LPCVOID lpComp, DWORD dwCompLen,
1650 LPCVOID lpRead, DWORD dwReadLen)
1652 DWORD flags = 0;
1653 WCHAR wParam = 0;
1655 TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
1656 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
1659 if (hIMC != (HIMC)FROM_IME)
1660 FIXME("PROBLEM: This only sets the wine level string\n");
1663 * Explanation:
1664 * this sets the composition string in the imm32.dll level
1665 * of the composition buffer. we cannot manipulate the xim level
1666 * buffer, which means that once the xim level buffer changes again
1667 * any call to this function from the application will be lost
1670 if (lpRead && dwReadLen)
1671 FIXME("Reading string unimplemented\n");
1674 * app operating this api to also receive the message from xim
1677 if (dwIndex == SCS_SETSTR)
1679 HIMCC newCompStr;
1680 if (!root_context->bInComposition)
1682 ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION, 0, 0);
1683 root_context->bInComposition = TRUE;
1686 flags = GCS_COMPSTR;
1688 if (dwCompLen && lpComp)
1690 newCompStr = updateCompStr(root_context->IMC.hCompStr, (LPWSTR)lpComp, dwCompLen / sizeof(WCHAR));
1691 ImmDestroyIMCC(root_context->IMC.hCompStr);
1692 root_context->IMC.hCompStr = newCompStr;
1694 wParam = ((const WCHAR*)lpComp)[0];
1695 flags |= GCS_COMPCLAUSE | GCS_COMPATTR | GCS_DELTASTART;
1697 else
1699 newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
1700 ImmDestroyIMCC(root_context->IMC.hCompStr);
1701 root_context->IMC.hCompStr = newCompStr;
1705 UpdateDataInDefaultIMEWindow(hwndDefault,FALSE);
1707 ImmInternalPostIMEMessage(WM_IME_COMPOSITION, wParam, flags);
1709 return TRUE;
1712 /***********************************************************************
1713 * ImmSetCompositionWindow (IMM32.@)
1715 BOOL WINAPI ImmSetCompositionWindow(
1716 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1718 BOOL reshow = FALSE;
1719 InputContextData *data = (InputContextData*)hIMC;
1721 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1722 TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
1723 lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
1724 lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
1726 if (!data)
1727 return FALSE;
1729 memcpy(&data->IMC.cfCompForm,lpCompForm,sizeof(COMPOSITIONFORM));
1731 if (IsWindowVisible(hwndDefault))
1733 reshow = TRUE;
1734 ShowWindow(hwndDefault,SW_HIDE);
1737 /* FIXME: this is a partial stub */
1739 if (reshow)
1740 ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
1742 ImmInternalSendIMENotify(IMN_SETCOMPOSITIONWINDOW, 0);
1743 return TRUE;
1746 /***********************************************************************
1747 * ImmSetConversionStatus (IMM32.@)
1749 BOOL WINAPI ImmSetConversionStatus(
1750 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
1752 static int shown = 0;
1754 if (!shown) {
1755 FIXME("(%p, %d, %d): stub\n",
1756 hIMC, fdwConversion, fdwSentence
1758 shown = 1;
1760 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1761 return FALSE;
1764 /***********************************************************************
1765 * ImmSetOpenStatus (IMM32.@)
1767 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
1769 InputContextData *data = (InputContextData*)hIMC;
1771 TRACE("%p %d\n", hIMC, fOpen);
1773 if (hIMC == (HIMC)FROM_IME)
1775 ImmInternalSetOpenStatus(fOpen);
1776 ImmInternalSendIMENotify(IMN_SETOPENSTATUS, 0);
1777 return TRUE;
1780 if (!data)
1781 return FALSE;
1783 if (fOpen != data->bInternalState)
1785 if (fOpen == FALSE && pX11DRV_ForceXIMReset)
1786 pX11DRV_ForceXIMReset(data->IMC.hWnd);
1788 if (fOpen == FALSE)
1789 ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0);
1790 else
1791 ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0);
1793 ImmInternalSetOpenStatus(fOpen);
1794 ImmInternalSetOpenStatus(!fOpen);
1796 if (data->IMC.fOpen == FALSE)
1797 ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0);
1798 else
1799 ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0);
1801 return FALSE;
1803 return TRUE;
1806 /***********************************************************************
1807 * ImmSetStatusWindowPos (IMM32.@)
1809 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1811 FIXME("(%p, %p): stub\n", hIMC, lpptPos);
1812 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1813 return FALSE;
1816 /***********************************************************************
1817 * ImmSimulateHotKey (IMM32.@)
1819 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
1821 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
1822 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1823 return FALSE;
1826 /***********************************************************************
1827 * ImmUnregisterWordA (IMM32.@)
1829 BOOL WINAPI ImmUnregisterWordA(
1830 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
1832 FIXME("(%p, %s, %d, %s): stub\n",
1833 hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszUnregister)
1835 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1836 return FALSE;
1839 /***********************************************************************
1840 * ImmUnregisterWordW (IMM32.@)
1842 BOOL WINAPI ImmUnregisterWordW(
1843 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
1845 FIXME("(%p, %s, %d, %s): stub\n",
1846 hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszUnregister)
1848 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1849 return FALSE;
1852 /***********************************************************************
1853 * ImmGetImeMenuItemsA (IMM32.@)
1855 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
1856 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
1857 DWORD dwSize)
1859 FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType,
1860 lpImeParentMenu, lpImeMenu, dwSize);
1861 return 0;
1864 /***********************************************************************
1865 * ImmGetImeMenuItemsW (IMM32.@)
1867 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
1868 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
1869 DWORD dwSize)
1871 FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType,
1872 lpImeParentMenu, lpImeMenu, dwSize);
1873 return 0;
1876 /***********************************************************************
1877 * ImmLockIMC(IMM32.@)
1879 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
1881 InputContextData *data = (InputContextData*)hIMC;
1883 if (!data)
1884 return NULL;
1885 data->dwLock++;
1886 return &data->IMC;
1889 /***********************************************************************
1890 * ImmUnlockIMC(IMM32.@)
1892 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
1894 InputContextData *data = (InputContextData*)hIMC;
1895 data->dwLock--;
1896 return (data->dwLock!=0);
1899 /***********************************************************************
1900 * ImmGetIMCLockCount(IMM32.@)
1902 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
1904 InputContextData *data = (InputContextData*)hIMC;
1905 return data->dwLock;
1908 /***********************************************************************
1909 * ImmCreateIMCC(IMM32.@)
1911 HIMCC WINAPI ImmCreateIMCC(DWORD size)
1913 IMCCInternal *internal;
1914 int real_size = size + sizeof(IMCCInternal);
1916 internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size);
1917 if (internal == NULL)
1918 return NULL;
1920 internal->dwSize = size;
1921 return (HIMCC)internal;
1924 /***********************************************************************
1925 * ImmDestroyIMCC(IMM32.@)
1927 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
1929 HeapFree(GetProcessHeap(),0,block);
1930 return NULL;
1933 /***********************************************************************
1934 * ImmLockIMCC(IMM32.@)
1936 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
1938 IMCCInternal *internal;
1939 internal = (IMCCInternal*) imcc;
1941 internal->dwLock ++;
1942 return internal + 1;
1945 /***********************************************************************
1946 * ImmUnlockIMCC(IMM32.@)
1948 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
1950 IMCCInternal *internal;
1951 internal = (IMCCInternal*) imcc;
1953 internal->dwLock --;
1954 return (internal->dwLock!=0);
1957 /***********************************************************************
1958 * ImmGetIMCCLockCount(IMM32.@)
1960 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
1962 IMCCInternal *internal;
1963 internal = (IMCCInternal*) imcc;
1965 return internal->dwLock;
1968 /***********************************************************************
1969 * ImmReSizeIMCC(IMM32.@)
1971 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
1973 IMCCInternal *internal,*newone;
1974 int real_size = size + sizeof(IMCCInternal);
1976 internal = (IMCCInternal*) imcc;
1978 newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size);
1979 newone->dwSize = size;
1981 return newone;
1984 /***********************************************************************
1985 * ImmGetIMCCSize(IMM32.@)
1987 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
1989 IMCCInternal *internal;
1990 internal = (IMCCInternal*) imcc;
1992 return internal->dwSize;
1995 /*****
1996 * Internal functions to help with IME window management
1998 static void PaintDefaultIMEWnd(HWND hwnd)
2000 PAINTSTRUCT ps;
2001 RECT rect;
2002 HDC hdc = BeginPaint(hwnd,&ps);
2003 LPCOMPOSITIONSTRING compstr;
2004 LPBYTE compdata = NULL;
2005 HMONITOR monitor;
2006 MONITORINFO mon_info;
2007 INT offX=0, offY=0;
2009 GetClientRect(hwnd,&rect);
2010 FillRect(hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1));
2012 compdata = ImmLockIMCC(root_context->IMC.hCompStr);
2013 compstr = (LPCOMPOSITIONSTRING)compdata;
2015 if (compstr->dwCompStrLen && compstr->dwCompStrOffset)
2017 SIZE size;
2018 POINT pt;
2019 HFONT oldfont = NULL;
2020 LPWSTR CompString;
2022 CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
2023 if (root_context->textfont)
2024 oldfont = SelectObject(hdc,root_context->textfont);
2027 GetTextExtentPoint32W(hdc, CompString, compstr->dwCompStrLen, &size);
2028 pt.x = size.cx;
2029 pt.y = size.cy;
2030 LPtoDP(hdc,&pt,1);
2033 * How this works based on tests on windows:
2034 * CFS_POINT: then we start our window at the point and grow it as large
2035 * as it needs to be for the string.
2036 * CFS_RECT: we still use the ptCurrentPos as a starting point and our
2037 * window is only as large as we need for the string, but we do not
2038 * grow such that our window exceeds the given rect. Wrapping if
2039 * needed and possible. If our ptCurrentPos is outside of our rect
2040 * then no window is displayed.
2041 * CFS_FORCE_POSITION: appears to behave just like CFS_POINT
2042 * maybe becase the default MSIME does not do any IME adjusting.
2044 if (root_context->IMC.cfCompForm.dwStyle != CFS_DEFAULT)
2046 POINT cpt = root_context->IMC.cfCompForm.ptCurrentPos;
2047 ClientToScreen(root_context->IMC.hWnd,&cpt);
2048 rect.left = cpt.x;
2049 rect.top = cpt.y;
2050 rect.right = rect.left + pt.x;
2051 rect.bottom = rect.top + pt.y;
2052 offX=offY=10;
2053 monitor = MonitorFromPoint(cpt, MONITOR_DEFAULTTOPRIMARY);
2055 else /* CFS_DEFAULT */
2057 /* Windows places the default IME window in the bottom left */
2058 HWND target = root_context->IMC.hWnd;
2059 if (!target) target = GetFocus();
2061 GetWindowRect(target,&rect);
2062 rect.top = rect.bottom;
2063 rect.right = rect.left + pt.x + 20;
2064 rect.bottom = rect.top + pt.y + 20;
2065 offX=offY=10;
2066 monitor = MonitorFromWindow(target, MONITOR_DEFAULTTOPRIMARY);
2069 if (root_context->IMC.cfCompForm.dwStyle == CFS_RECT)
2071 RECT client;
2072 client =root_context->IMC.cfCompForm.rcArea;
2073 MapWindowPoints( root_context->IMC.hWnd, 0, (POINT *)&client, 2 );
2074 IntersectRect(&rect,&rect,&client);
2075 /* TODO: Wrap the input if needed */
2078 if (root_context->IMC.cfCompForm.dwStyle == CFS_DEFAULT)
2080 /* make sure we are on the desktop */
2081 mon_info.cbSize = sizeof(mon_info);
2082 GetMonitorInfoW(monitor, &mon_info);
2084 if (rect.bottom > mon_info.rcWork.bottom)
2086 int shift = rect.bottom - mon_info.rcWork.bottom;
2087 rect.top -= shift;
2088 rect.bottom -= shift;
2090 if (rect.left < 0)
2092 rect.right -= rect.left;
2093 rect.left = 0;
2095 if (rect.right > mon_info.rcWork.right)
2097 int shift = rect.right - mon_info.rcWork.right;
2098 rect.left -= shift;
2099 rect.right -= shift;
2103 SetWindowPos(hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE);
2105 TextOutW(hdc, offX,offY, CompString, compstr->dwCompStrLen);
2107 if (oldfont)
2108 SelectObject(hdc,oldfont);
2111 ImmUnlockIMCC(root_context->IMC.hCompStr);
2113 EndPaint(hwnd,&ps);
2116 static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable)
2118 LPCOMPOSITIONSTRING compstr;
2120 if (root_context->IMC.hCompStr)
2121 compstr = ImmLockIMCC(root_context->IMC.hCompStr);
2122 else
2123 compstr = NULL;
2125 if (compstr == NULL || compstr->dwCompStrLen == 0)
2126 ShowWindow(hwndDefault,SW_HIDE);
2127 else if (showable)
2128 ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
2130 RedrawWindow(hwnd,NULL,NULL,RDW_ERASENOW|RDW_INVALIDATE);
2132 if (compstr != NULL)
2133 ImmUnlockIMCC(root_context->IMC.hCompStr);
2137 * The window proc for the default IME window
2139 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam,
2140 LPARAM lParam)
2142 LRESULT rc = 0;
2144 TRACE("Incoming Message 0x%x (0x%08x, 0x%08x)\n", msg, (UINT)wParam,
2145 (UINT)lParam);
2147 switch(msg)
2149 case WM_PAINT:
2150 PaintDefaultIMEWnd(hwnd);
2151 return FALSE;
2153 case WM_NCCREATE:
2154 return TRUE;
2156 case WM_CREATE:
2157 SetWindowTextA(hwnd,"Wine Ime Active");
2158 return TRUE;
2160 case WM_SETFOCUS:
2161 if (wParam)
2162 SetFocus((HWND)wParam);
2163 else
2164 FIXME("Received focus, should never have focus\n");
2165 break;
2166 case WM_IME_COMPOSITION:
2167 TRACE("IME message %s, 0x%x, 0x%x (%i)\n",
2168 "WM_IME_COMPOSITION", (UINT)wParam, (UINT)lParam,
2169 root_context->bRead);
2170 if (lParam & GCS_RESULTSTR)
2171 IMM_PostResult(root_context);
2172 else
2173 UpdateDataInDefaultIMEWindow(hwnd,TRUE);
2174 break;
2175 case WM_IME_STARTCOMPOSITION:
2176 TRACE("IME message %s, 0x%x, 0x%x\n",
2177 "WM_IME_STARTCOMPOSITION", (UINT)wParam, (UINT)lParam);
2178 root_context->IMC.hWnd = GetFocus();
2179 ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
2180 break;
2181 case WM_IME_ENDCOMPOSITION:
2182 TRACE("IME message %s, 0x%x, 0x%x\n",
2183 "WM_IME_ENDCOMPOSITION", (UINT)wParam, (UINT)lParam);
2184 ShowWindow(hwndDefault,SW_HIDE);
2185 break;
2186 case WM_IME_SELECT:
2187 TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_SELECT",
2188 (UINT)wParam, (UINT)lParam);
2189 break;
2190 case WM_IME_CONTROL:
2191 TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_CONTROL",
2192 (UINT)wParam, (UINT)lParam);
2193 rc = 1;
2194 break;
2195 case WM_IME_NOTIFY:
2196 TRACE("!! IME NOTIFY\n");
2197 break;
2198 default:
2199 TRACE("Non-standard message 0x%x\n",msg);
2201 /* check the MSIME messages */
2202 if (msg == WM_MSIME_SERVICE)
2204 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_SERVICE",
2205 (UINT)wParam, (UINT)lParam);
2206 rc = FALSE;
2208 else if (msg == WM_MSIME_RECONVERTOPTIONS)
2210 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTOPTIONS",
2211 (UINT)wParam, (UINT)lParam);
2213 else if (msg == WM_MSIME_MOUSE)
2215 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_MOUSE",
2216 (UINT)wParam, (UINT)lParam);
2218 else if (msg == WM_MSIME_RECONVERTREQUEST)
2220 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTREQUEST",
2221 (UINT)wParam, (UINT)lParam);
2223 else if (msg == WM_MSIME_RECONVERT)
2225 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERT",
2226 (UINT)wParam, (UINT)lParam);
2228 else if (msg == WM_MSIME_QUERYPOSITION)
2230 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_QUERYPOSITION",
2231 (UINT)wParam, (UINT)lParam);
2233 else if (msg == WM_MSIME_DOCUMENTFEED)
2235 TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_DOCUMENTFEED",
2236 (UINT)wParam, (UINT)lParam);
2238 /* DefWndProc if not an IME message */
2239 else if (!rc && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2240 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP)))
2241 rc = DefWindowProcW(hwnd,msg,wParam,lParam);
2243 return rc;