winex11.drv: Use BOOL type where appropriate.
[wine.git] / dlls / winex11.drv / ime.c
blobaa6c7ddf89809bcf3e53d797fc1d636cc83eaad1
1 /*
2 * The IME for interfacing with XIM
4 * Copyright 2008 CodeWeavers, Aric Stewart
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 * Notes:
23 * The normal flow for IMM/IME Processing is as follows.
24 * 1) The Keyboard Driver generates key messages which are first passed to
25 * the IMM and then to IME via ImeProcessKey. If the IME returns 0 then
26 * it does not want the key and the keyboard driver then generates the
27 * WM_KEYUP/WM_KEYDOWN messages. However if the IME is going to process the
28 * key it returns non-zero.
29 * 2) If the IME is going to process the key then the IMM calls ImeToAsciiEx to
30 * process the key. the IME modifies the HIMC structure to reflect the
31 * current state and generates any messages it needs the IMM to process.
32 * 3) IMM checks the messages and send them to the application in question. From
33 * here the IMM level deals with if the application is IME aware or not.
35 * This flow does not work well for the X11 driver and XIM.
36 * (It works fine for Mac)
37 * As such we will have to reroute step 1. Instead the x11drv driver will
38 * generate an XIM events and call directly into this IME implementation.
39 * As such we will have to use the alternative ImmGenerateMessage path to be
40 * generate the messages that we want the IMM layer to send to the application.
43 #include "config.h"
45 #include <stdarg.h>
46 #include "windef.h"
47 #include "winbase.h"
48 #include "wingdi.h"
49 #include "winuser.h"
50 #include "winerror.h"
51 #include "wine/debug.h"
52 #include "imm.h"
53 #include "ddk/imm.h"
54 #include "winnls.h"
55 #include "x11drv.h"
57 WINE_DEFAULT_DEBUG_CHANNEL(imm);
59 #define FROM_X11 ((HIMC)0xcafe1337)
61 typedef struct _IMEPRIVATE {
62 BOOL bInComposition;
63 BOOL bInternalState;
64 HFONT textfont;
65 HWND hwndDefault;
66 } IMEPRIVATE, *LPIMEPRIVATE;
68 typedef struct _tagTRANSMSG {
69 UINT message;
70 WPARAM wParam;
71 LPARAM lParam;
72 } TRANSMSG, *LPTRANSMSG;
74 static const WCHAR UI_CLASS_NAME[] = {'W','i','n','e','X','1','1','I','M','E',0};
76 static HIMC *hSelectedFrom = NULL;
77 static INT hSelectedCount = 0;
79 /* MSIME messages */
80 static UINT WM_MSIME_SERVICE;
81 static UINT WM_MSIME_RECONVERTOPTIONS;
82 static UINT WM_MSIME_MOUSE;
83 static UINT WM_MSIME_RECONVERTREQUEST;
84 static UINT WM_MSIME_RECONVERT;
85 static UINT WM_MSIME_QUERYPOSITION;
86 static UINT WM_MSIME_DOCUMENTFEED;
88 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
89 LPARAM lParam);
91 static HIMC RealIMC(HIMC hIMC)
93 if (hIMC == FROM_X11)
95 INT i;
96 HWND wnd = GetFocus();
97 HIMC winHimc = ImmGetContext(wnd);
98 for (i = 0; i < hSelectedCount; i++)
99 if (winHimc == hSelectedFrom[i])
100 return winHimc;
101 return NULL;
103 else
104 return hIMC;
107 static LPINPUTCONTEXT LockRealIMC(HIMC hIMC)
109 HIMC real_imc = RealIMC(hIMC);
110 if (real_imc)
111 return ImmLockIMC(real_imc);
112 else
113 return NULL;
116 static BOOL UnlockRealIMC(HIMC hIMC)
118 HIMC real_imc = RealIMC(hIMC);
119 if (real_imc)
120 return ImmUnlockIMC(real_imc);
121 else
122 return FALSE;
125 static void IME_RegisterClasses(void)
127 static BOOL done = FALSE;
128 WNDCLASSW wndClass;
130 if (done) return;
131 done = TRUE;
133 ZeroMemory(&wndClass, sizeof(WNDCLASSW));
134 wndClass.style = CS_GLOBALCLASS | CS_IME | CS_HREDRAW | CS_VREDRAW;
135 wndClass.lpfnWndProc = IME_WindowProc;
136 wndClass.cbClsExtra = 0;
137 wndClass.cbWndExtra = 2 * sizeof(LONG_PTR);
138 wndClass.hInstance = x11drv_module;
139 wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
140 wndClass.hIcon = LoadIconW(NULL, (LPWSTR)IDI_APPLICATION);
141 wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW +1);
142 wndClass.lpszMenuName = 0;
143 wndClass.lpszClassName = UI_CLASS_NAME;
145 RegisterClassW(&wndClass);
147 WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");
148 WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions");
149 WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
150 WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
151 WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
152 WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
153 WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
156 static HIMCC ImeCreateBlankCompStr(void)
158 HIMCC rc;
159 LPCOMPOSITIONSTRING ptr;
160 rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
161 ptr = ImmLockIMCC(rc);
162 memset(ptr,0,sizeof(COMPOSITIONSTRING));
163 ptr->dwSize = sizeof(COMPOSITIONSTRING);
164 ImmUnlockIMCC(rc);
165 return rc;
168 static int updateField(DWORD origLen, DWORD origOffset, DWORD currentOffset,
169 LPBYTE target, LPBYTE source, DWORD* lenParam,
170 DWORD* offsetParam, BOOL wchars )
172 if (origLen > 0 && origOffset > 0)
174 int truelen = origLen;
175 if (wchars)
176 truelen *= sizeof(WCHAR);
178 memcpy(&target[currentOffset], &source[origOffset], truelen);
180 *lenParam = origLen;
181 *offsetParam = currentOffset;
182 currentOffset += truelen;
184 return currentOffset;
187 static HIMCC updateCompStr(HIMCC old, LPCWSTR compstr, DWORD len)
189 /* we need to make sure the CompStr, CompClaus and CompAttr fields are all
190 * set and correct */
191 int needed_size;
192 HIMCC rc;
193 LPBYTE newdata = NULL;
194 LPBYTE olddata = NULL;
195 LPCOMPOSITIONSTRING new_one;
196 LPCOMPOSITIONSTRING lpcs = NULL;
197 INT current_offset = 0;
199 TRACE("%s, %i\n",debugstr_wn(compstr,len),len);
201 if (old == NULL && compstr == NULL && len == 0)
202 return NULL;
204 if (compstr == NULL && len != 0)
206 ERR("compstr is NULL however we have a len! Please report\n");
207 len = 0;
210 if (old != NULL)
212 olddata = ImmLockIMCC(old);
213 lpcs = (LPCOMPOSITIONSTRING)olddata;
216 needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
217 len + sizeof(DWORD) * 2;
219 if (lpcs != NULL)
221 needed_size += lpcs->dwCompReadAttrLen;
222 needed_size += lpcs->dwCompReadClauseLen;
223 needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
224 needed_size += lpcs->dwResultReadClauseLen;
225 needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
226 needed_size += lpcs->dwResultClauseLen;
227 needed_size += lpcs->dwResultStrLen * sizeof(DWORD);
228 needed_size += lpcs->dwPrivateSize;
230 rc = ImmCreateIMCC(needed_size);
231 newdata = ImmLockIMCC(rc);
232 new_one = (LPCOMPOSITIONSTRING)newdata;
234 new_one->dwSize = needed_size;
235 current_offset = sizeof(COMPOSITIONSTRING);
236 if (lpcs != NULL)
238 current_offset = updateField(lpcs->dwCompReadAttrLen,
239 lpcs->dwCompReadAttrOffset,
240 current_offset, newdata, olddata,
241 &new_one->dwCompReadAttrLen,
242 &new_one->dwCompReadAttrOffset, FALSE);
244 current_offset = updateField(lpcs->dwCompReadClauseLen,
245 lpcs->dwCompReadClauseOffset,
246 current_offset, newdata, olddata,
247 &new_one->dwCompReadClauseLen,
248 &new_one->dwCompReadClauseOffset, FALSE);
250 current_offset = updateField(lpcs->dwCompReadStrLen,
251 lpcs->dwCompReadStrOffset,
252 current_offset, newdata, olddata,
253 &new_one->dwCompReadStrLen,
254 &new_one->dwCompReadStrOffset, TRUE);
256 /* new CompAttr, CompClause, CompStr, dwCursorPos */
257 new_one->dwDeltaStart = 0;
259 current_offset = updateField(lpcs->dwResultReadClauseLen,
260 lpcs->dwResultReadClauseOffset,
261 current_offset, newdata, olddata,
262 &new_one->dwResultReadClauseLen,
263 &new_one->dwResultReadClauseOffset, FALSE);
265 current_offset = updateField(lpcs->dwResultReadStrLen,
266 lpcs->dwResultReadStrOffset,
267 current_offset, newdata, olddata,
268 &new_one->dwResultReadStrLen,
269 &new_one->dwResultReadStrOffset, TRUE);
271 current_offset = updateField(lpcs->dwResultClauseLen,
272 lpcs->dwResultClauseOffset,
273 current_offset, newdata, olddata,
274 &new_one->dwResultClauseLen,
275 &new_one->dwResultClauseOffset, FALSE);
277 current_offset = updateField(lpcs->dwResultStrLen,
278 lpcs->dwResultStrOffset,
279 current_offset, newdata, olddata,
280 &new_one->dwResultStrLen,
281 &new_one->dwResultStrOffset, TRUE);
283 current_offset = updateField(lpcs->dwPrivateSize,
284 lpcs->dwPrivateOffset,
285 current_offset, newdata, olddata,
286 &new_one->dwPrivateSize,
287 &new_one->dwPrivateOffset, FALSE);
290 /* set new data */
291 /* CompAttr */
292 new_one->dwCompAttrLen = len;
293 if (len > 0)
295 new_one->dwCompAttrOffset = current_offset;
296 memset(&newdata[current_offset],ATTR_INPUT,len);
297 current_offset += len;
300 /* CompClause */
301 if (len > 0)
303 new_one->dwCompClauseLen = sizeof(DWORD) * 2;
304 new_one->dwCompClauseOffset = current_offset;
305 *(DWORD*)(&newdata[current_offset]) = 0;
306 current_offset += sizeof(DWORD);
307 *(DWORD*)(&newdata[current_offset]) = len;
308 current_offset += sizeof(DWORD);
311 /* CompStr */
312 new_one->dwCompStrLen = len;
313 if (len > 0)
315 new_one->dwCompStrOffset = current_offset;
316 memcpy(&newdata[current_offset],compstr,len*sizeof(WCHAR));
319 /* CursorPos */
320 new_one->dwCursorPos = len;
322 ImmUnlockIMCC(rc);
323 if (lpcs)
324 ImmUnlockIMCC(old);
326 return rc;
329 static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len)
331 /* we need to make sure the ResultStr and ResultClause fields are all
332 * set and correct */
333 int needed_size;
334 HIMCC rc;
335 LPBYTE newdata = NULL;
336 LPBYTE olddata = NULL;
337 LPCOMPOSITIONSTRING new_one;
338 LPCOMPOSITIONSTRING lpcs = NULL;
339 INT current_offset = 0;
341 TRACE("%s, %i\n",debugstr_wn(resultstr,len),len);
343 if (old == NULL && resultstr == NULL && len == 0)
344 return NULL;
346 if (resultstr == NULL && len != 0)
348 ERR("resultstr is NULL however we have a len! Please report\n");
349 len = 0;
352 if (old != NULL)
354 olddata = ImmLockIMCC(old);
355 lpcs = (LPCOMPOSITIONSTRING)olddata;
358 needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
359 sizeof(DWORD) * 2;
361 if (lpcs != NULL)
363 needed_size += lpcs->dwCompReadAttrLen;
364 needed_size += lpcs->dwCompReadClauseLen;
365 needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
366 needed_size += lpcs->dwCompAttrLen;
367 needed_size += lpcs->dwCompClauseLen;
368 needed_size += lpcs->dwCompStrLen * sizeof(DWORD);
369 needed_size += lpcs->dwResultReadClauseLen;
370 needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
371 needed_size += lpcs->dwPrivateSize;
373 rc = ImmCreateIMCC(needed_size);
374 newdata = ImmLockIMCC(rc);
375 new_one = (LPCOMPOSITIONSTRING)newdata;
377 new_one->dwSize = needed_size;
378 current_offset = sizeof(COMPOSITIONSTRING);
379 if (lpcs != NULL)
381 current_offset = updateField(lpcs->dwCompReadAttrLen,
382 lpcs->dwCompReadAttrOffset,
383 current_offset, newdata, olddata,
384 &new_one->dwCompReadAttrLen,
385 &new_one->dwCompReadAttrOffset, FALSE);
387 current_offset = updateField(lpcs->dwCompReadClauseLen,
388 lpcs->dwCompReadClauseOffset,
389 current_offset, newdata, olddata,
390 &new_one->dwCompReadClauseLen,
391 &new_one->dwCompReadClauseOffset, FALSE);
393 current_offset = updateField(lpcs->dwCompReadStrLen,
394 lpcs->dwCompReadStrOffset,
395 current_offset, newdata, olddata,
396 &new_one->dwCompReadStrLen,
397 &new_one->dwCompReadStrOffset, TRUE);
399 current_offset = updateField(lpcs->dwCompAttrLen,
400 lpcs->dwCompAttrOffset,
401 current_offset, newdata, olddata,
402 &new_one->dwCompAttrLen,
403 &new_one->dwCompAttrOffset, FALSE);
405 current_offset = updateField(lpcs->dwCompClauseLen,
406 lpcs->dwCompClauseOffset,
407 current_offset, newdata, olddata,
408 &new_one->dwCompClauseLen,
409 &new_one->dwCompClauseOffset, FALSE);
411 current_offset = updateField(lpcs->dwCompStrLen,
412 lpcs->dwCompStrOffset,
413 current_offset, newdata, olddata,
414 &new_one->dwCompStrLen,
415 &new_one->dwCompStrOffset, TRUE);
417 new_one->dwCursorPos = lpcs->dwCursorPos;
418 new_one->dwDeltaStart = 0;
420 current_offset = updateField(lpcs->dwResultReadClauseLen,
421 lpcs->dwResultReadClauseOffset,
422 current_offset, newdata, olddata,
423 &new_one->dwResultReadClauseLen,
424 &new_one->dwResultReadClauseOffset, FALSE);
426 current_offset = updateField(lpcs->dwResultReadStrLen,
427 lpcs->dwResultReadStrOffset,
428 current_offset, newdata, olddata,
429 &new_one->dwResultReadStrLen,
430 &new_one->dwResultReadStrOffset, TRUE);
432 /* new ResultClause , ResultStr */
434 current_offset = updateField(lpcs->dwPrivateSize,
435 lpcs->dwPrivateOffset,
436 current_offset, newdata, olddata,
437 &new_one->dwPrivateSize,
438 &new_one->dwPrivateOffset, FALSE);
441 /* set new data */
442 /* ResultClause */
443 if (len > 0)
445 new_one->dwResultClauseLen = sizeof(DWORD) * 2;
446 new_one->dwResultClauseOffset = current_offset;
447 *(DWORD*)(&newdata[current_offset]) = 0;
448 current_offset += sizeof(DWORD);
449 *(DWORD*)(&newdata[current_offset]) = len;
450 current_offset += sizeof(DWORD);
453 /* ResultStr */
454 new_one->dwResultStrLen = len;
455 if (len > 0)
457 new_one->dwResultStrOffset = current_offset;
458 memcpy(&newdata[current_offset],resultstr,len*sizeof(WCHAR));
460 ImmUnlockIMCC(rc);
461 if (lpcs)
462 ImmUnlockIMCC(old);
464 return rc;
467 static void GenerateIMEMessage(HIMC hIMC, UINT msg, WPARAM wParam,
468 LPARAM lParam)
470 LPINPUTCONTEXT lpIMC;
471 LPTRANSMSG lpTransMsg;
473 lpIMC = LockRealIMC(hIMC);
474 if (lpIMC == NULL)
475 return;
477 lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf, (lpIMC->dwNumMsgBuf + 1) *
478 sizeof(TRANSMSG));
479 if (!lpIMC->hMsgBuf)
480 return;
482 lpTransMsg = ImmLockIMCC(lpIMC->hMsgBuf);
483 if (!lpTransMsg)
484 return;
486 lpTransMsg += lpIMC->dwNumMsgBuf;
487 lpTransMsg->message = msg;
488 lpTransMsg->wParam = wParam;
489 lpTransMsg->lParam = lParam;
491 ImmUnlockIMCC(lpIMC->hMsgBuf);
492 lpIMC->dwNumMsgBuf++;
494 ImmGenerateMessage(RealIMC(hIMC));
495 UnlockRealIMC(hIMC);
498 static void GenerateIMECHARMessages(HIMC hIMC, LPWSTR String, DWORD length)
500 LPINPUTCONTEXT lpIMC;
501 LPTRANSMSG lpTransMsg;
502 DWORD i;
504 if (length <= 0)
505 return;
507 lpIMC = LockRealIMC(hIMC);
508 if (lpIMC == NULL)
509 return;
511 lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf,
512 (lpIMC->dwNumMsgBuf + length) *
513 sizeof(TRANSMSG));
514 if (!lpIMC->hMsgBuf)
515 return;
517 lpTransMsg = ImmLockIMCC(lpIMC->hMsgBuf);
518 if (!lpTransMsg)
519 return;
521 lpTransMsg += lpIMC->dwNumMsgBuf;
522 for (i = 0; i < length; i++)
524 lpTransMsg->message = WM_IME_CHAR;
525 lpTransMsg->wParam = String[i];
526 lpTransMsg->lParam = 1;
527 lpTransMsg ++;
530 ImmUnlockIMCC(lpIMC->hMsgBuf);
531 lpIMC->dwNumMsgBuf+=length;
533 ImmGenerateMessage(RealIMC(hIMC));
534 UnlockRealIMC(hIMC);
537 static BOOL IME_RemoveFromSelected(HIMC hIMC)
539 int i;
540 for (i = 0; i < hSelectedCount; i++)
541 if (hSelectedFrom[i] == hIMC)
543 if (i < hSelectedCount - 1)
544 memmove(&hSelectedFrom[i], &hSelectedFrom[i+1], (hSelectedCount - i - 1)*sizeof(HIMC));
545 hSelectedCount --;
546 return TRUE;
548 return FALSE;
551 static void IME_AddToSelected(HIMC hIMC)
553 hSelectedCount++;
554 if (hSelectedFrom)
555 hSelectedFrom = HeapReAlloc(GetProcessHeap(), 0, hSelectedFrom, hSelectedCount*sizeof(HIMC));
556 else
557 hSelectedFrom = HeapAlloc(GetProcessHeap(), 0, sizeof(HIMC));
558 hSelectedFrom[hSelectedCount-1] = hIMC;
561 BOOL WINAPI ImeInquire(LPIMEINFO lpIMEInfo, LPWSTR lpszUIClass,
562 LPCWSTR lpszOption)
564 TRACE("\n");
565 IME_RegisterClasses();
566 lpIMEInfo->dwPrivateDataSize = sizeof (IMEPRIVATE);
567 lpIMEInfo->fdwProperty = IME_PROP_UNICODE | IME_PROP_AT_CARET;
568 lpIMEInfo->fdwConversionCaps = IME_CMODE_NATIVE;
569 lpIMEInfo->fdwSentenceCaps = IME_SMODE_AUTOMATIC;
570 lpIMEInfo->fdwUICaps = UI_CAP_2700;
571 /* Tell App we cannot accept ImeSetCompositionString calls */
572 lpIMEInfo->fdwSCSCaps = 0;
573 lpIMEInfo->fdwSelectCaps = SELECT_CAP_CONVERSION;
575 lstrcpyW(lpszUIClass,UI_CLASS_NAME);
577 return TRUE;
580 BOOL WINAPI ImeConfigure(HKL hKL,HWND hWnd, DWORD dwMode, LPVOID lpData)
582 FIXME("(%p, %p, %d, %p): stub\n", hKL, hWnd, dwMode, lpData);
583 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
584 return FALSE;
587 DWORD WINAPI ImeConversionList(HIMC hIMC, LPCWSTR lpSource,
588 LPCANDIDATELIST lpCandList, DWORD dwBufLen, UINT uFlag)
591 FIXME("(%p, %s, %p, %d, %d): stub\n", hIMC, debugstr_w(lpSource),
592 lpCandList, dwBufLen, uFlag);
593 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
594 return 0;
597 BOOL WINAPI ImeDestroy(UINT uForce)
599 TRACE("\n");
600 HeapFree(GetProcessHeap(),0,hSelectedFrom);
601 hSelectedFrom = NULL;
602 hSelectedCount = 0;
603 return TRUE;
606 LRESULT WINAPI ImeEscape(HIMC hIMC, UINT uSubFunc, LPVOID lpData)
608 FIXME("(%p, %d, %p): stub\n", hIMC, uSubFunc, lpData);
609 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
610 return 0;
613 BOOL WINAPI ImeProcessKey(HIMC hIMC, UINT vKey, LPARAM lKeyData, const LPBYTE lpbKeyState)
615 /* See the comment at the head of this file */
616 TRACE("We do no processing via this route\n");
617 return FALSE;
620 BOOL WINAPI ImeSelect(HIMC hIMC, BOOL fSelect)
622 LPINPUTCONTEXT lpIMC;
623 TRACE("%p %s\n",hIMC,(fSelect)?"TRUE":"FALSE");
625 if (hIMC == FROM_X11)
627 ERR("ImeSelect should never be called from X11\n");
628 return FALSE;
631 if (!hIMC)
632 return TRUE;
634 /* not selected */
635 if (!fSelect)
636 return IME_RemoveFromSelected(hIMC);
638 IME_AddToSelected(hIMC);
640 /* Initialize our structures */
641 lpIMC = LockRealIMC(hIMC);
642 if (lpIMC != NULL)
644 LPIMEPRIVATE myPrivate;
645 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
646 myPrivate->bInComposition = FALSE;
647 myPrivate->bInternalState = FALSE;
648 myPrivate->textfont = NULL;
649 myPrivate->hwndDefault = NULL;
650 ImmUnlockIMCC(lpIMC->hPrivate);
651 UnlockRealIMC(hIMC);
654 return TRUE;
657 BOOL WINAPI ImeSetActiveContext(HIMC hIMC,BOOL fFlag)
659 FIXME("(%p, %x): stub\n", hIMC, fFlag);
660 return TRUE;
663 UINT WINAPI ImeToAsciiEx (UINT uVKey, UINT uScanCode, const LPBYTE lpbKeyState,
664 LPDWORD lpdwTransKey, UINT fuState, HIMC hIMC)
666 /* See the comment at the head of this file */
667 TRACE("We do no processing via this route\n");
668 return 0;
671 BOOL WINAPI NotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
673 BOOL bRet = FALSE;
674 LPINPUTCONTEXT lpIMC;
676 TRACE("%p %i %i %i\n",hIMC,dwAction,dwIndex,dwValue);
678 lpIMC = LockRealIMC(hIMC);
679 if (lpIMC == NULL)
680 return FALSE;
682 switch (dwAction)
684 case NI_OPENCANDIDATE: FIXME("NI_OPENCANDIDATE\n"); break;
685 case NI_CLOSECANDIDATE: FIXME("NI_CLOSECANDIDATE\n"); break;
686 case NI_SELECTCANDIDATESTR: FIXME("NI_SELECTCANDIDATESTR\n"); break;
687 case NI_CHANGECANDIDATELIST: FIXME("NI_CHANGECANDIDATELIST\n"); break;
688 case NI_SETCANDIDATE_PAGESTART: FIXME("NI_SETCANDIDATE_PAGESTART\n"); break;
689 case NI_SETCANDIDATE_PAGESIZE: FIXME("NI_SETCANDIDATE_PAGESIZE\n"); break;
690 case NI_CONTEXTUPDATED:
691 switch (dwValue)
693 case IMC_SETCOMPOSITIONWINDOW: FIXME("IMC_SETCOMPOSITIONWINDOW\n"); break;
694 case IMC_SETCONVERSIONMODE: FIXME("IMC_SETCONVERSIONMODE\n"); break;
695 case IMC_SETSENTENCEMODE: FIXME("IMC_SETSENTENCEMODE\n"); break;
696 case IMC_SETCANDIDATEPOS: FIXME("IMC_SETCANDIDATEPOS\n"); break;
697 case IMC_SETCOMPOSITIONFONT:
699 LPIMEPRIVATE myPrivate;
700 TRACE("IMC_SETCOMPOSITIONFONT\n");
702 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
703 if (myPrivate->textfont)
705 DeleteObject(myPrivate->textfont);
706 myPrivate->textfont = NULL;
708 myPrivate->textfont = CreateFontIndirectW(&lpIMC->lfFont.W);
709 ImmUnlockIMCC(lpIMC->hPrivate);
711 break;
712 case IMC_SETOPENSTATUS:
713 TRACE("IMC_SETOPENSTATUS\n");
715 bRet = TRUE;
716 X11DRV_SetPreeditState(lpIMC->hWnd, lpIMC->fOpen);
717 if (!lpIMC->fOpen)
719 LPIMEPRIVATE myPrivate;
721 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
722 if (myPrivate->bInComposition)
724 X11DRV_ForceXIMReset(lpIMC->hWnd);
725 GenerateIMEMessage(hIMC, WM_IME_ENDCOMPOSITION, 0, 0);
726 myPrivate->bInComposition = FALSE;
728 ImmUnlockIMCC(lpIMC->hPrivate);
731 break;
732 default: FIXME("Unknown\n"); break;
734 break;
735 case NI_COMPOSITIONSTR:
736 switch (dwIndex)
738 case CPS_COMPLETE:
740 HIMCC newCompStr;
741 DWORD cplen = 0;
742 LPWSTR cpstr;
743 LPCOMPOSITIONSTRING cs = NULL;
744 LPBYTE cdata = NULL;
745 LPIMEPRIVATE myPrivate;
747 TRACE("CPS_COMPLETE\n");
749 /* clear existing result */
750 newCompStr = updateResultStr(lpIMC->hCompStr, NULL, 0);
752 ImmDestroyIMCC(lpIMC->hCompStr);
753 lpIMC->hCompStr = newCompStr;
755 if (lpIMC->hCompStr)
757 cdata = ImmLockIMCC(lpIMC->hCompStr);
758 cs = (LPCOMPOSITIONSTRING)cdata;
759 cplen = cs->dwCompStrLen;
760 cpstr = (LPWSTR)&(cdata[cs->dwCompStrOffset]);
761 ImmUnlockIMCC(lpIMC->hCompStr);
763 if (cplen > 0)
765 WCHAR param = cpstr[0];
767 newCompStr = updateResultStr(lpIMC->hCompStr, cpstr, cplen);
768 ImmDestroyIMCC(lpIMC->hCompStr);
769 lpIMC->hCompStr = newCompStr;
770 newCompStr = updateCompStr(lpIMC->hCompStr, NULL, 0);
771 ImmDestroyIMCC(lpIMC->hCompStr);
772 lpIMC->hCompStr = newCompStr;
774 GenerateIMEMessage(hIMC, WM_IME_COMPOSITION, 0,
775 GCS_COMPSTR);
777 GenerateIMEMessage(hIMC, WM_IME_COMPOSITION, param,
778 GCS_RESULTSTR|GCS_RESULTCLAUSE);
781 GenerateIMEMessage(hIMC,WM_IME_ENDCOMPOSITION, 0, 0);
783 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
784 myPrivate->bInComposition = FALSE;
785 ImmUnlockIMCC(lpIMC->hPrivate);
787 bRet = TRUE;
789 break;
790 case CPS_CONVERT: FIXME("CPS_CONVERT\n"); break;
791 case CPS_REVERT: FIXME("CPS_REVERT\n"); break;
792 case CPS_CANCEL:
794 LPIMEPRIVATE myPrivate;
796 TRACE("CPS_CANCEL\n");
798 X11DRV_ForceXIMReset(lpIMC->hWnd);
800 if (lpIMC->hCompStr)
801 ImmDestroyIMCC(lpIMC->hCompStr);
802 lpIMC->hCompStr = ImeCreateBlankCompStr();
804 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
805 if (myPrivate->bInComposition)
807 GenerateIMEMessage(hIMC, WM_IME_ENDCOMPOSITION, 0, 0);
808 myPrivate->bInComposition = FALSE;
810 ImmUnlockIMCC(lpIMC->hPrivate);
811 bRet = TRUE;
813 break;
814 default: FIXME("Unknown\n"); break;
816 break;
817 default: FIXME("Unknown Message\n"); break;
820 UnlockRealIMC(hIMC);
821 return bRet;
824 BOOL WINAPI ImeRegisterWord(LPCWSTR lpszReading, DWORD dwStyle,
825 LPCWSTR lpszRegister)
827 FIXME("(%s, %d, %s): stub\n", debugstr_w(lpszReading), dwStyle,
828 debugstr_w(lpszRegister));
829 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
830 return FALSE;
833 BOOL WINAPI ImeUnregisterWord(LPCWSTR lpszReading, DWORD dwStyle,
834 LPCWSTR lpszUnregister)
836 FIXME("(%s, %d, %s): stub\n", debugstr_w(lpszReading), dwStyle,
837 debugstr_w(lpszUnregister));
838 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
839 return FALSE;
842 UINT WINAPI ImeGetRegisterWordStyle(UINT nItem, LPSTYLEBUFW lpStyleBuf)
844 FIXME("(%d, %p): stub\n", nItem, lpStyleBuf);
845 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
846 return 0;
849 UINT WINAPI ImeEnumRegisterWord(REGISTERWORDENUMPROCW lpfnEnumProc,
850 LPCWSTR lpszReading, DWORD dwStyle,
851 LPCWSTR lpszRegister, LPVOID lpData)
853 FIXME("(%p, %s, %d, %s, %p): stub\n", lpfnEnumProc,
854 debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister),
855 lpData);
856 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
857 return 0;
860 BOOL WINAPI ImeSetCompositionString(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp,
861 DWORD dwCompLen, LPCVOID lpRead,
862 DWORD dwReadLen)
864 LPINPUTCONTEXT lpIMC;
865 DWORD flags = 0;
866 WCHAR wParam = 0;
867 LPIMEPRIVATE myPrivate;
869 TRACE("(%p, %d, %p, %d, %p, %d):\n",
870 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
873 if (hIMC != FROM_X11)
874 FIXME("PROBLEM: This only sets the wine level string\n");
877 * Explanation:
878 * this sets the composition string in the imm32.dll level
879 * of the composition buffer. we cannot manipulate the xim level
880 * buffer, which means that once the xim level buffer changes again
881 * any call to this function from the application will be lost
884 if (lpRead && dwReadLen)
885 FIXME("Reading string unimplemented\n");
887 lpIMC = LockRealIMC(hIMC);
889 if (lpIMC == NULL)
890 return FALSE;
892 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
894 if (dwIndex == SCS_SETSTR)
896 HIMCC newCompStr;
898 if (!myPrivate->bInComposition)
900 GenerateIMEMessage(hIMC, WM_IME_STARTCOMPOSITION, 0, 0);
901 myPrivate->bInComposition = TRUE;
904 flags = GCS_COMPSTR;
906 if (dwCompLen && lpComp)
908 newCompStr = updateCompStr(lpIMC->hCompStr, (LPCWSTR)lpComp, dwCompLen / sizeof(WCHAR));
909 ImmDestroyIMCC(lpIMC->hCompStr);
910 lpIMC->hCompStr = newCompStr;
912 wParam = ((const WCHAR*)lpComp)[0];
913 flags |= GCS_COMPCLAUSE | GCS_COMPATTR | GCS_DELTASTART;
915 else
917 newCompStr = updateCompStr(lpIMC->hCompStr, NULL, 0);
918 ImmDestroyIMCC(lpIMC->hCompStr);
919 lpIMC->hCompStr = newCompStr;
923 GenerateIMEMessage(hIMC, WM_IME_COMPOSITION, wParam, flags);
924 ImmUnlockIMCC(lpIMC->hPrivate);
925 UnlockRealIMC(hIMC);
927 return TRUE;
930 DWORD WINAPI ImeGetImeMenuItems(HIMC hIMC, DWORD dwFlags, DWORD dwType,
931 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
932 DWORD dwSize)
934 FIXME("(%p, %x %x %p %p %x): stub\n", hIMC, dwFlags, dwType,
935 lpImeParentMenu, lpImeMenu, dwSize);
936 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
937 return 0;
940 /* Interfaces to XIM and other parts of winex11drv */
942 void IME_SetOpenStatus(BOOL fOpen)
944 HIMC imc;
946 imc = RealIMC(FROM_X11);
947 ImmSetOpenStatus(imc, fOpen);
950 void IME_SetCompositionStatus(BOOL fOpen)
952 HIMC imc;
953 LPINPUTCONTEXT lpIMC;
954 LPIMEPRIVATE myPrivate;
956 imc = RealIMC(FROM_X11);
957 lpIMC = ImmLockIMC(imc);
958 if (lpIMC == NULL)
959 return;
961 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
963 if (fOpen && !myPrivate->bInComposition)
965 GenerateIMEMessage(imc, WM_IME_STARTCOMPOSITION, 0, 0);
967 else if (!fOpen && myPrivate->bInComposition)
969 ShowWindow(myPrivate->hwndDefault, SW_HIDE);
970 ImmDestroyIMCC(lpIMC->hCompStr);
971 lpIMC->hCompStr = ImeCreateBlankCompStr();
972 GenerateIMEMessage(imc, WM_IME_ENDCOMPOSITION, 0, 0);
974 myPrivate->bInComposition = fOpen;
976 ImmUnlockIMCC(lpIMC->hPrivate);
977 ImmUnlockIMC(imc);
980 INT IME_GetCursorPos(void)
982 LPINPUTCONTEXT lpIMC;
983 INT rc = 0;
984 LPCOMPOSITIONSTRING compstr;
986 if (!hSelectedFrom)
987 return rc;
989 lpIMC = LockRealIMC(FROM_X11);
990 if (lpIMC)
992 compstr = ImmLockIMCC(lpIMC->hCompStr);
993 rc = compstr->dwCursorPos;
994 ImmUnlockIMCC(lpIMC->hCompStr);
996 UnlockRealIMC(FROM_X11);
997 return rc;
1000 void IME_SetCursorPos(DWORD pos)
1002 LPINPUTCONTEXT lpIMC;
1003 LPCOMPOSITIONSTRING compstr;
1005 if (!hSelectedFrom)
1006 return;
1008 lpIMC = LockRealIMC(FROM_X11);
1009 if (!lpIMC)
1010 return;
1012 compstr = ImmLockIMCC(lpIMC->hCompStr);
1013 if (!compstr)
1015 UnlockRealIMC(FROM_X11);
1016 return;
1019 compstr->dwCursorPos = pos;
1020 ImmUnlockIMCC(lpIMC->hCompStr);
1021 UnlockRealIMC(FROM_X11);
1022 GenerateIMEMessage(FROM_X11, WM_IME_COMPOSITION, pos, GCS_CURSORPOS);
1023 return;
1026 void IME_UpdateAssociation(HWND focus)
1028 ImmGetContext(focus);
1030 if (!focus || !hSelectedFrom)
1031 return;
1033 ImmAssociateContext(focus,RealIMC(FROM_X11));
1037 BOOL IME_SetCompositionString(DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen,
1038 LPCVOID lpRead, DWORD dwReadLen)
1040 return ImeSetCompositionString(FROM_X11, dwIndex, lpComp, dwCompLen,
1041 lpRead, dwReadLen);
1044 void IME_SetResultString(LPWSTR lpResult, DWORD dwResultLen)
1046 HIMC imc;
1047 LPINPUTCONTEXT lpIMC;
1048 HIMCC newCompStr;
1049 LPIMEPRIVATE myPrivate;
1051 imc = RealIMC(FROM_X11);
1052 lpIMC = ImmLockIMC(imc);
1053 if (lpIMC == NULL)
1054 return;
1056 newCompStr = updateResultStr(lpIMC->hCompStr, lpResult, dwResultLen);
1057 ImmDestroyIMCC(lpIMC->hCompStr);
1058 lpIMC->hCompStr = newCompStr;
1060 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
1061 if (!myPrivate->bInComposition)
1062 GenerateIMEMessage(imc, WM_IME_STARTCOMPOSITION, 0, 0);
1063 GenerateIMEMessage(imc, WM_IME_COMPOSITION, 0, GCS_RESULTSTR);
1064 if (!myPrivate->bInComposition)
1065 GenerateIMEMessage(imc, WM_IME_ENDCOMPOSITION, 0, 0);
1066 ImmUnlockIMCC(lpIMC->hPrivate);
1068 ImmUnlockIMC(imc);
1071 /*****
1072 * Internal functions to help with IME window management
1074 static void PaintDefaultIMEWnd(HIMC hIMC, HWND hwnd)
1076 PAINTSTRUCT ps;
1077 RECT rect;
1078 HDC hdc;
1079 LPCOMPOSITIONSTRING compstr;
1080 LPBYTE compdata = NULL;
1081 HMONITOR monitor;
1082 MONITORINFO mon_info;
1083 INT offX=0, offY=0;
1084 LPINPUTCONTEXT lpIMC;
1086 lpIMC = LockRealIMC(hIMC);
1087 if (lpIMC == NULL)
1088 return;
1090 hdc = BeginPaint(hwnd,&ps);
1092 GetClientRect(hwnd,&rect);
1093 FillRect(hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1));
1095 compdata = ImmLockIMCC(lpIMC->hCompStr);
1096 compstr = (LPCOMPOSITIONSTRING)compdata;
1098 if (compstr->dwCompStrLen && compstr->dwCompStrOffset)
1100 SIZE size;
1101 POINT pt;
1102 HFONT oldfont = NULL;
1103 LPWSTR CompString;
1104 LPIMEPRIVATE myPrivate;
1106 CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
1107 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
1109 if (myPrivate->textfont)
1110 oldfont = SelectObject(hdc,myPrivate->textfont);
1112 ImmUnlockIMCC(lpIMC->hPrivate);
1114 GetTextExtentPoint32W(hdc, CompString, compstr->dwCompStrLen, &size);
1115 pt.x = size.cx;
1116 pt.y = size.cy;
1117 LPtoDP(hdc,&pt,1);
1120 * How this works based on tests on windows:
1121 * CFS_POINT: then we start our window at the point and grow it as large
1122 * as it needs to be for the string.
1123 * CFS_RECT: we still use the ptCurrentPos as a starting point and our
1124 * window is only as large as we need for the string, but we do not
1125 * grow such that our window exceeds the given rect. Wrapping if
1126 * needed and possible. If our ptCurrentPos is outside of our rect
1127 * then no window is displayed.
1128 * CFS_FORCE_POSITION: appears to behave just like CFS_POINT
1129 * maybe because the default MSIME does not do any IME adjusting.
1131 if (lpIMC->cfCompForm.dwStyle != CFS_DEFAULT)
1133 POINT cpt = lpIMC->cfCompForm.ptCurrentPos;
1134 ClientToScreen(lpIMC->hWnd,&cpt);
1135 rect.left = cpt.x;
1136 rect.top = cpt.y;
1137 rect.right = rect.left + pt.x;
1138 rect.bottom = rect.top + pt.y;
1139 monitor = MonitorFromPoint(cpt, MONITOR_DEFAULTTOPRIMARY);
1141 else /* CFS_DEFAULT */
1143 /* Windows places the default IME window in the bottom left */
1144 HWND target = lpIMC->hWnd;
1145 if (!target) target = GetFocus();
1147 GetWindowRect(target,&rect);
1148 rect.top = rect.bottom;
1149 rect.right = rect.left + pt.x + 20;
1150 rect.bottom = rect.top + pt.y + 20;
1151 offX=offY=10;
1152 monitor = MonitorFromWindow(target, MONITOR_DEFAULTTOPRIMARY);
1155 if (lpIMC->cfCompForm.dwStyle == CFS_RECT)
1157 RECT client;
1158 client =lpIMC->cfCompForm.rcArea;
1159 MapWindowPoints( lpIMC->hWnd, 0, (POINT *)&client, 2 );
1160 IntersectRect(&rect,&rect,&client);
1161 /* TODO: Wrap the input if needed */
1164 if (lpIMC->cfCompForm.dwStyle == CFS_DEFAULT)
1166 /* make sure we are on the desktop */
1167 mon_info.cbSize = sizeof(mon_info);
1168 GetMonitorInfoW(monitor, &mon_info);
1170 if (rect.bottom > mon_info.rcWork.bottom)
1172 int shift = rect.bottom - mon_info.rcWork.bottom;
1173 rect.top -= shift;
1174 rect.bottom -= shift;
1176 if (rect.left < 0)
1178 rect.right -= rect.left;
1179 rect.left = 0;
1181 if (rect.right > mon_info.rcWork.right)
1183 int shift = rect.right - mon_info.rcWork.right;
1184 rect.left -= shift;
1185 rect.right -= shift;
1189 SetWindowPos(hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE);
1191 TextOutW(hdc, offX,offY, CompString, compstr->dwCompStrLen);
1193 if (oldfont)
1194 SelectObject(hdc,oldfont);
1197 ImmUnlockIMCC(lpIMC->hCompStr);
1199 EndPaint(hwnd,&ps);
1200 UnlockRealIMC(hIMC);
1203 static void UpdateDefaultIMEWindow(HIMC hIMC, HWND hwnd)
1205 LPCOMPOSITIONSTRING compstr;
1206 LPINPUTCONTEXT lpIMC;
1208 lpIMC = LockRealIMC(hIMC);
1209 if (lpIMC == NULL)
1210 return;
1212 if (lpIMC->hCompStr)
1213 compstr = ImmLockIMCC(lpIMC->hCompStr);
1214 else
1215 compstr = NULL;
1217 if (compstr == NULL || compstr->dwCompStrLen == 0)
1218 ShowWindow(hwnd,SW_HIDE);
1219 else
1221 ShowWindow(hwnd,SW_SHOWNOACTIVATE);
1222 RedrawWindow(hwnd, NULL, NULL, RDW_ERASENOW | RDW_INVALIDATE);
1225 if (compstr != NULL)
1226 ImmUnlockIMCC(lpIMC->hCompStr);
1228 lpIMC->hWnd = GetFocus();
1229 UnlockRealIMC(hIMC);
1232 static void DefaultIMEComposition(HIMC hIMC, HWND hwnd, LPARAM lParam)
1234 TRACE("IME message WM_IME_COMPOSITION 0x%lx\n", lParam);
1235 if (lParam & GCS_RESULTSTR)
1237 LPCOMPOSITIONSTRING compstr;
1238 LPBYTE compdata;
1239 LPWSTR ResultStr;
1240 HIMCC newCompStr;
1241 LPINPUTCONTEXT lpIMC;
1243 lpIMC = LockRealIMC(hIMC);
1244 if (lpIMC == NULL)
1245 return;
1247 TRACE("Posting result as IME_CHAR\n");
1248 compdata = ImmLockIMCC(lpIMC->hCompStr);
1249 compstr = (LPCOMPOSITIONSTRING)compdata;
1250 ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
1251 GenerateIMECHARMessages(hIMC, ResultStr, compstr->dwResultStrLen);
1252 ImmUnlockIMCC(lpIMC->hCompStr);
1254 /* clear the buffer */
1255 newCompStr = updateResultStr(lpIMC->hCompStr, NULL, 0);
1256 ImmDestroyIMCC(lpIMC->hCompStr);
1257 lpIMC->hCompStr = newCompStr;
1258 UnlockRealIMC(hIMC);
1260 else
1261 UpdateDefaultIMEWindow(hIMC, hwnd);
1264 static void DefaultIMEStartComposition(HIMC hIMC, HWND hwnd )
1266 TRACE("IME message WM_IME_STARTCOMPOSITION\n");
1267 UpdateDefaultIMEWindow(hIMC, hwnd);
1270 static LRESULT ImeHandleNotify(HIMC hIMC, HWND hwnd, UINT msg, WPARAM wParam,
1271 LPARAM lParam)
1273 switch (wParam)
1275 case IMN_OPENSTATUSWINDOW:
1276 FIXME("WM_IME_NOTIFY:IMN_OPENSTATUSWINDOW\n");
1277 break;
1278 case IMN_CLOSESTATUSWINDOW:
1279 FIXME("WM_IME_NOTIFY:IMN_CLOSESTATUSWINDOW\n");
1280 break;
1281 case IMN_OPENCANDIDATE:
1282 FIXME("WM_IME_NOTIFY:IMN_OPENCANDIDATE\n");
1283 break;
1284 case IMN_CHANGECANDIDATE:
1285 FIXME("WM_IME_NOTIFY:IMN_CHANGECANDIDATE\n");
1286 break;
1287 case IMN_CLOSECANDIDATE:
1288 FIXME("WM_IME_NOTIFY:IMN_CLOSECANDIDATE\n");
1289 break;
1290 case IMN_SETCONVERSIONMODE:
1291 FIXME("WM_IME_NOTIFY:IMN_SETCONVERSIONMODE\n");
1292 break;
1293 case IMN_SETSENTENCEMODE:
1294 FIXME("WM_IME_NOTIFY:IMN_SETSENTENCEMODE\n");
1295 break;
1296 case IMN_SETOPENSTATUS:
1297 TRACE("WM_IME_NOTIFY:IMN_SETOPENSTATUS\n");
1298 break;
1299 case IMN_SETCANDIDATEPOS:
1300 FIXME("WM_IME_NOTIFY:IMN_SETCANDIDATEPOS\n");
1301 break;
1302 case IMN_SETCOMPOSITIONFONT:
1303 FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONFONT\n");
1304 break;
1305 case IMN_SETCOMPOSITIONWINDOW:
1306 FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONWINDOW\n");
1307 break;
1308 case IMN_GUIDELINE:
1309 FIXME("WM_IME_NOTIFY:IMN_GUIDELINE\n");
1310 break;
1311 case IMN_SETSTATUSWINDOWPOS:
1312 FIXME("WM_IME_NOTIFY:IMN_SETSTATUSWINDOWPOS\n");
1313 break;
1314 default:
1315 FIXME("WM_IME_NOTIFY:<Unknown 0x%lx>\n",wParam);
1316 break;
1318 return 0;
1321 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam,
1322 LPARAM lParam)
1324 LRESULT rc = 0;
1325 HIMC hIMC;
1327 TRACE("Incoming Message 0x%x (0x%08lx, 0x%08lx)\n", msg, wParam, lParam);
1330 * Each UI window contains the current Input Context.
1331 * This Input Context can be obtained by calling GetWindowLong
1332 * with IMMGWL_IMC when the UI window receives a WM_IME_xxx message.
1333 * The UI window can refer to this Input Context and handles the
1334 * messages.
1337 hIMC = (HIMC)GetWindowLongPtrW(hwnd,IMMGWL_IMC);
1338 if (!hIMC)
1339 hIMC = RealIMC(FROM_X11);
1341 /* if we have no hIMC there are many messages we cannot process */
1342 if (hIMC == NULL)
1344 switch (msg) {
1345 case WM_IME_STARTCOMPOSITION:
1346 case WM_IME_ENDCOMPOSITION:
1347 case WM_IME_COMPOSITION:
1348 case WM_IME_NOTIFY:
1349 case WM_IME_CONTROL:
1350 case WM_IME_COMPOSITIONFULL:
1351 case WM_IME_SELECT:
1352 case WM_IME_CHAR:
1353 return 0L;
1354 default:
1355 break;
1359 switch(msg)
1361 case WM_CREATE:
1363 LPIMEPRIVATE myPrivate;
1364 LPINPUTCONTEXT lpIMC;
1366 SetWindowTextA(hwnd,"Wine Ime Active");
1368 lpIMC = LockRealIMC(hIMC);
1369 if (lpIMC)
1371 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
1372 myPrivate->hwndDefault = hwnd;
1373 ImmUnlockIMCC(lpIMC->hPrivate);
1375 UnlockRealIMC(hIMC);
1377 return TRUE;
1379 case WM_PAINT:
1380 PaintDefaultIMEWnd(hIMC, hwnd);
1381 return FALSE;
1383 case WM_NCCREATE:
1384 return TRUE;
1386 case WM_SETFOCUS:
1387 if (wParam)
1388 SetFocus((HWND)wParam);
1389 else
1390 FIXME("Received focus, should never have focus\n");
1391 break;
1392 case WM_IME_COMPOSITION:
1393 DefaultIMEComposition(hIMC, hwnd, lParam);
1394 break;
1395 case WM_IME_STARTCOMPOSITION:
1396 DefaultIMEStartComposition(hIMC, hwnd);
1397 break;
1398 case WM_IME_ENDCOMPOSITION:
1399 TRACE("IME message %s, 0x%lx, 0x%lx\n",
1400 "WM_IME_ENDCOMPOSITION", wParam, lParam);
1401 ShowWindow(hwnd,SW_HIDE);
1402 break;
1403 case WM_IME_SELECT:
1404 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_IME_SELECT", wParam, lParam);
1405 break;
1406 case WM_IME_CONTROL:
1407 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_IME_CONTROL", wParam, lParam);
1408 rc = 1;
1409 break;
1410 case WM_IME_NOTIFY:
1411 rc = ImeHandleNotify(hIMC,hwnd,msg,wParam,lParam);
1412 break;
1413 default:
1414 TRACE("Non-standard message 0x%x\n",msg);
1416 /* check the MSIME messages */
1417 if (msg == WM_MSIME_SERVICE)
1419 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_SERVICE", wParam, lParam);
1420 rc = FALSE;
1422 else if (msg == WM_MSIME_RECONVERTOPTIONS)
1424 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_RECONVERTOPTIONS", wParam, lParam);
1426 else if (msg == WM_MSIME_MOUSE)
1428 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_MOUSE", wParam, lParam);
1430 else if (msg == WM_MSIME_RECONVERTREQUEST)
1432 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_RECONVERTREQUEST", wParam, lParam);
1434 else if (msg == WM_MSIME_RECONVERT)
1436 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_RECONVERT", wParam, lParam);
1438 else if (msg == WM_MSIME_QUERYPOSITION)
1440 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_QUERYPOSITION", wParam, lParam);
1442 else if (msg == WM_MSIME_DOCUMENTFEED)
1444 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_DOCUMENTFEED", wParam, lParam);
1446 /* DefWndProc if not an IME message */
1447 if (!rc && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1448 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP)))
1449 rc = DefWindowProcW(hwnd,msg,wParam,lParam);
1451 return rc;