windowscodecs: Implement JpegEncoder_Frame_SetResolution.
[wine/multimedia.git] / dlls / winex11.drv / ime.c
blobb343a647d6e0fa28100fdf6d8f7903a6049ec928
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 int done;
128 WNDCLASSW wndClass;
130 if (done) return;
131 done = 1;
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 void IME_UnregisterClasses(void)
158 UnregisterClassW(UI_CLASS_NAME, x11drv_module);
161 static HIMCC ImeCreateBlankCompStr(void)
163 HIMCC rc;
164 LPCOMPOSITIONSTRING ptr;
165 rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
166 ptr = ImmLockIMCC(rc);
167 memset(ptr,0,sizeof(COMPOSITIONSTRING));
168 ptr->dwSize = sizeof(COMPOSITIONSTRING);
169 ImmUnlockIMCC(rc);
170 return rc;
173 static int updateField(DWORD origLen, DWORD origOffset, DWORD currentOffset,
174 LPBYTE target, LPBYTE source, DWORD* lenParam,
175 DWORD* offsetParam, BOOL wchars )
177 if (origLen > 0 && origOffset > 0)
179 int truelen = origLen;
180 if (wchars)
181 truelen *= sizeof(WCHAR);
183 memcpy(&target[currentOffset], &source[origOffset], truelen);
185 *lenParam = origLen;
186 *offsetParam = currentOffset;
187 currentOffset += truelen;
189 return currentOffset;
192 static HIMCC updateCompStr(HIMCC old, LPCWSTR compstr, DWORD len)
194 /* we need to make sure the CompStr, CompClaus and CompAttr fields are all
195 * set and correct */
196 int needed_size;
197 HIMCC rc;
198 LPBYTE newdata = NULL;
199 LPBYTE olddata = NULL;
200 LPCOMPOSITIONSTRING new_one;
201 LPCOMPOSITIONSTRING lpcs = NULL;
202 INT current_offset = 0;
204 TRACE("%s, %i\n",debugstr_wn(compstr,len),len);
206 if (old == NULL && compstr == NULL && len == 0)
207 return NULL;
209 if (compstr == NULL && len != 0)
211 ERR("compstr is NULL however we have a len! Please report\n");
212 len = 0;
215 if (old != NULL)
217 olddata = ImmLockIMCC(old);
218 lpcs = (LPCOMPOSITIONSTRING)olddata;
221 needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
222 len + sizeof(DWORD) * 2;
224 if (lpcs != NULL)
226 needed_size += lpcs->dwCompReadAttrLen;
227 needed_size += lpcs->dwCompReadClauseLen;
228 needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
229 needed_size += lpcs->dwResultReadClauseLen;
230 needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
231 needed_size += lpcs->dwResultClauseLen;
232 needed_size += lpcs->dwResultStrLen * sizeof(DWORD);
233 needed_size += lpcs->dwPrivateSize;
235 rc = ImmCreateIMCC(needed_size);
236 newdata = ImmLockIMCC(rc);
237 new_one = (LPCOMPOSITIONSTRING)newdata;
239 new_one->dwSize = needed_size;
240 current_offset = sizeof(COMPOSITIONSTRING);
241 if (lpcs != NULL)
243 current_offset = updateField(lpcs->dwCompReadAttrLen,
244 lpcs->dwCompReadAttrOffset,
245 current_offset, newdata, olddata,
246 &new_one->dwCompReadAttrLen,
247 &new_one->dwCompReadAttrOffset, FALSE);
249 current_offset = updateField(lpcs->dwCompReadClauseLen,
250 lpcs->dwCompReadClauseOffset,
251 current_offset, newdata, olddata,
252 &new_one->dwCompReadClauseLen,
253 &new_one->dwCompReadClauseOffset, FALSE);
255 current_offset = updateField(lpcs->dwCompReadStrLen,
256 lpcs->dwCompReadStrOffset,
257 current_offset, newdata, olddata,
258 &new_one->dwCompReadStrLen,
259 &new_one->dwCompReadStrOffset, TRUE);
261 /* new CompAttr, CompClause, CompStr, dwCursorPos */
262 new_one->dwDeltaStart = 0;
264 current_offset = updateField(lpcs->dwResultReadClauseLen,
265 lpcs->dwResultReadClauseOffset,
266 current_offset, newdata, olddata,
267 &new_one->dwResultReadClauseLen,
268 &new_one->dwResultReadClauseOffset, FALSE);
270 current_offset = updateField(lpcs->dwResultReadStrLen,
271 lpcs->dwResultReadStrOffset,
272 current_offset, newdata, olddata,
273 &new_one->dwResultReadStrLen,
274 &new_one->dwResultReadStrOffset, TRUE);
276 current_offset = updateField(lpcs->dwResultClauseLen,
277 lpcs->dwResultClauseOffset,
278 current_offset, newdata, olddata,
279 &new_one->dwResultClauseLen,
280 &new_one->dwResultClauseOffset, FALSE);
282 current_offset = updateField(lpcs->dwResultStrLen,
283 lpcs->dwResultStrOffset,
284 current_offset, newdata, olddata,
285 &new_one->dwResultStrLen,
286 &new_one->dwResultStrOffset, TRUE);
288 current_offset = updateField(lpcs->dwPrivateSize,
289 lpcs->dwPrivateOffset,
290 current_offset, newdata, olddata,
291 &new_one->dwPrivateSize,
292 &new_one->dwPrivateOffset, FALSE);
295 /* set new data */
296 /* CompAttr */
297 new_one->dwCompAttrLen = len;
298 if (len > 0)
300 new_one->dwCompAttrOffset = current_offset;
301 memset(&newdata[current_offset],ATTR_INPUT,len);
302 current_offset += len;
305 /* CompClause */
306 if (len > 0)
308 new_one->dwCompClauseLen = sizeof(DWORD) * 2;
309 new_one->dwCompClauseOffset = current_offset;
310 *(DWORD*)(&newdata[current_offset]) = 0;
311 current_offset += sizeof(DWORD);
312 *(DWORD*)(&newdata[current_offset]) = len;
313 current_offset += sizeof(DWORD);
316 /* CompStr */
317 new_one->dwCompStrLen = len;
318 if (len > 0)
320 new_one->dwCompStrOffset = current_offset;
321 memcpy(&newdata[current_offset],compstr,len*sizeof(WCHAR));
324 /* CursorPos */
325 new_one->dwCursorPos = len;
327 ImmUnlockIMCC(rc);
328 if (lpcs)
329 ImmUnlockIMCC(old);
331 return rc;
334 static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len)
336 /* we need to make sure the ResultStr and ResultClause fields are all
337 * set and correct */
338 int needed_size;
339 HIMCC rc;
340 LPBYTE newdata = NULL;
341 LPBYTE olddata = NULL;
342 LPCOMPOSITIONSTRING new_one;
343 LPCOMPOSITIONSTRING lpcs = NULL;
344 INT current_offset = 0;
346 TRACE("%s, %i\n",debugstr_wn(resultstr,len),len);
348 if (old == NULL && resultstr == NULL && len == 0)
349 return NULL;
351 if (resultstr == NULL && len != 0)
353 ERR("resultstr is NULL however we have a len! Please report\n");
354 len = 0;
357 if (old != NULL)
359 olddata = ImmLockIMCC(old);
360 lpcs = (LPCOMPOSITIONSTRING)olddata;
363 needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
364 sizeof(DWORD) * 2;
366 if (lpcs != NULL)
368 needed_size += lpcs->dwCompReadAttrLen;
369 needed_size += lpcs->dwCompReadClauseLen;
370 needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
371 needed_size += lpcs->dwCompAttrLen;
372 needed_size += lpcs->dwCompClauseLen;
373 needed_size += lpcs->dwCompStrLen * sizeof(DWORD);
374 needed_size += lpcs->dwResultReadClauseLen;
375 needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
376 needed_size += lpcs->dwPrivateSize;
378 rc = ImmCreateIMCC(needed_size);
379 newdata = ImmLockIMCC(rc);
380 new_one = (LPCOMPOSITIONSTRING)newdata;
382 new_one->dwSize = needed_size;
383 current_offset = sizeof(COMPOSITIONSTRING);
384 if (lpcs != NULL)
386 current_offset = updateField(lpcs->dwCompReadAttrLen,
387 lpcs->dwCompReadAttrOffset,
388 current_offset, newdata, olddata,
389 &new_one->dwCompReadAttrLen,
390 &new_one->dwCompReadAttrOffset, FALSE);
392 current_offset = updateField(lpcs->dwCompReadClauseLen,
393 lpcs->dwCompReadClauseOffset,
394 current_offset, newdata, olddata,
395 &new_one->dwCompReadClauseLen,
396 &new_one->dwCompReadClauseOffset, FALSE);
398 current_offset = updateField(lpcs->dwCompReadStrLen,
399 lpcs->dwCompReadStrOffset,
400 current_offset, newdata, olddata,
401 &new_one->dwCompReadStrLen,
402 &new_one->dwCompReadStrOffset, TRUE);
404 current_offset = updateField(lpcs->dwCompAttrLen,
405 lpcs->dwCompAttrOffset,
406 current_offset, newdata, olddata,
407 &new_one->dwCompAttrLen,
408 &new_one->dwCompAttrOffset, FALSE);
410 current_offset = updateField(lpcs->dwCompClauseLen,
411 lpcs->dwCompClauseOffset,
412 current_offset, newdata, olddata,
413 &new_one->dwCompClauseLen,
414 &new_one->dwCompClauseOffset, FALSE);
416 current_offset = updateField(lpcs->dwCompStrLen,
417 lpcs->dwCompStrOffset,
418 current_offset, newdata, olddata,
419 &new_one->dwCompStrLen,
420 &new_one->dwCompStrOffset, TRUE);
422 new_one->dwCursorPos = lpcs->dwCursorPos;
423 new_one->dwDeltaStart = 0;
425 current_offset = updateField(lpcs->dwResultReadClauseLen,
426 lpcs->dwResultReadClauseOffset,
427 current_offset, newdata, olddata,
428 &new_one->dwResultReadClauseLen,
429 &new_one->dwResultReadClauseOffset, FALSE);
431 current_offset = updateField(lpcs->dwResultReadStrLen,
432 lpcs->dwResultReadStrOffset,
433 current_offset, newdata, olddata,
434 &new_one->dwResultReadStrLen,
435 &new_one->dwResultReadStrOffset, TRUE);
437 /* new ResultClause , ResultStr */
439 current_offset = updateField(lpcs->dwPrivateSize,
440 lpcs->dwPrivateOffset,
441 current_offset, newdata, olddata,
442 &new_one->dwPrivateSize,
443 &new_one->dwPrivateOffset, FALSE);
446 /* set new data */
447 /* ResultClause */
448 if (len > 0)
450 new_one->dwResultClauseLen = sizeof(DWORD) * 2;
451 new_one->dwResultClauseOffset = current_offset;
452 *(DWORD*)(&newdata[current_offset]) = 0;
453 current_offset += sizeof(DWORD);
454 *(DWORD*)(&newdata[current_offset]) = len;
455 current_offset += sizeof(DWORD);
458 /* ResultStr */
459 new_one->dwResultStrLen = len;
460 if (len > 0)
462 new_one->dwResultStrOffset = current_offset;
463 memcpy(&newdata[current_offset],resultstr,len*sizeof(WCHAR));
465 ImmUnlockIMCC(rc);
466 if (lpcs)
467 ImmUnlockIMCC(old);
469 return rc;
472 static void GenerateIMEMessage(HIMC hIMC, UINT msg, WPARAM wParam,
473 LPARAM lParam)
475 LPINPUTCONTEXT lpIMC;
476 LPTRANSMSG lpTransMsg;
478 lpIMC = LockRealIMC(hIMC);
479 if (lpIMC == NULL)
480 return;
482 lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf, (lpIMC->dwNumMsgBuf + 1) *
483 sizeof(TRANSMSG));
484 if (!lpIMC->hMsgBuf)
485 return;
487 lpTransMsg = ImmLockIMCC(lpIMC->hMsgBuf);
488 if (!lpTransMsg)
489 return;
491 lpTransMsg += lpIMC->dwNumMsgBuf;
492 lpTransMsg->message = msg;
493 lpTransMsg->wParam = wParam;
494 lpTransMsg->lParam = lParam;
496 ImmUnlockIMCC(lpIMC->hMsgBuf);
497 lpIMC->dwNumMsgBuf++;
499 ImmGenerateMessage(RealIMC(hIMC));
500 UnlockRealIMC(hIMC);
503 static void GenerateIMECHARMessages(HIMC hIMC, LPWSTR String, DWORD length)
505 LPINPUTCONTEXT lpIMC;
506 LPTRANSMSG lpTransMsg;
507 DWORD i;
509 if (length <= 0)
510 return;
512 lpIMC = LockRealIMC(hIMC);
513 if (lpIMC == NULL)
514 return;
516 lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf,
517 (lpIMC->dwNumMsgBuf + length) *
518 sizeof(TRANSMSG));
519 if (!lpIMC->hMsgBuf)
520 return;
522 lpTransMsg = ImmLockIMCC(lpIMC->hMsgBuf);
523 if (!lpTransMsg)
524 return;
526 lpTransMsg += lpIMC->dwNumMsgBuf;
527 for (i = 0; i < length; i++)
529 lpTransMsg->message = WM_IME_CHAR;
530 lpTransMsg->wParam = String[i];
531 lpTransMsg->lParam = 1;
532 lpTransMsg ++;
535 ImmUnlockIMCC(lpIMC->hMsgBuf);
536 lpIMC->dwNumMsgBuf+=length;
538 ImmGenerateMessage(RealIMC(hIMC));
539 UnlockRealIMC(hIMC);
542 static BOOL IME_RemoveFromSelected(HIMC hIMC)
544 int i;
545 for (i = 0; i < hSelectedCount; i++)
546 if (hSelectedFrom[i] == hIMC)
548 if (i < hSelectedCount - 1)
549 memmove(&hSelectedFrom[i], &hSelectedFrom[i+1], (hSelectedCount - i - 1)*sizeof(HIMC));
550 hSelectedCount --;
551 return TRUE;
553 return FALSE;
556 static void IME_AddToSelected(HIMC hIMC)
558 hSelectedCount++;
559 if (hSelectedFrom)
560 hSelectedFrom = HeapReAlloc(GetProcessHeap(), 0, hSelectedFrom, hSelectedCount*sizeof(HIMC));
561 else
562 hSelectedFrom = HeapAlloc(GetProcessHeap(), 0, sizeof(HIMC));
563 hSelectedFrom[hSelectedCount-1] = hIMC;
566 BOOL WINAPI ImeInquire(LPIMEINFO lpIMEInfo, LPWSTR lpszUIClass,
567 LPCWSTR lpszOption)
569 TRACE("\n");
570 IME_RegisterClasses();
571 lpIMEInfo->dwPrivateDataSize = sizeof (IMEPRIVATE);
572 lpIMEInfo->fdwProperty = IME_PROP_UNICODE | IME_PROP_AT_CARET;
573 lpIMEInfo->fdwConversionCaps = IME_CMODE_NATIVE;
574 lpIMEInfo->fdwSentenceCaps = IME_SMODE_AUTOMATIC;
575 lpIMEInfo->fdwUICaps = UI_CAP_2700;
576 /* Tell App we cannot accept ImeSetCompositionString calls */
577 lpIMEInfo->fdwSCSCaps = 0;
578 lpIMEInfo->fdwSelectCaps = SELECT_CAP_CONVERSION;
580 lstrcpyW(lpszUIClass,UI_CLASS_NAME);
582 return TRUE;
585 BOOL WINAPI ImeConfigure(HKL hKL,HWND hWnd, DWORD dwMode, LPVOID lpData)
587 FIXME("(%p, %p, %d, %p): stub\n", hKL, hWnd, dwMode, lpData);
588 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
589 return FALSE;
592 DWORD WINAPI ImeConversionList(HIMC hIMC, LPCWSTR lpSource,
593 LPCANDIDATELIST lpCandList, DWORD dwBufLen, UINT uFlag)
596 FIXME("(%p, %s, %p, %d, %d): stub\n", hIMC, debugstr_w(lpSource),
597 lpCandList, dwBufLen, uFlag);
598 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
599 return 0;
602 BOOL WINAPI ImeDestroy(UINT uForce)
604 TRACE("\n");
605 HeapFree(GetProcessHeap(),0,hSelectedFrom);
606 hSelectedFrom = NULL;
607 hSelectedCount = 0;
608 return TRUE;
611 LRESULT WINAPI ImeEscape(HIMC hIMC, UINT uSubFunc, LPVOID lpData)
613 FIXME("(%p, %d, %p): stub\n", hIMC, uSubFunc, lpData);
614 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
615 return 0;
618 BOOL WINAPI ImeProcessKey(HIMC hIMC, UINT vKey, LPARAM lKeyData,
619 CONST LPBYTE lpbKeyState)
621 /* See the comment at the head of this file */
622 TRACE("We do no processing via this route\n");
623 return FALSE;
626 BOOL WINAPI ImeSelect(HIMC hIMC, BOOL fSelect)
628 LPINPUTCONTEXT lpIMC;
629 TRACE("%p %s\n",hIMC,(fSelect)?"TRUE":"FALSE");
631 if (hIMC == FROM_X11)
633 ERR("ImeSelect should never be called from X11\n");
634 return FALSE;
637 if (!hIMC)
638 return TRUE;
640 /* not selected */
641 if (!fSelect)
642 return IME_RemoveFromSelected(hIMC);
644 IME_AddToSelected(hIMC);
646 /* Initialize our structures */
647 lpIMC = LockRealIMC(hIMC);
648 if (lpIMC != NULL)
650 LPIMEPRIVATE myPrivate;
651 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
652 myPrivate->bInComposition = FALSE;
653 myPrivate->bInternalState = FALSE;
654 myPrivate->textfont = NULL;
655 myPrivate->hwndDefault = NULL;
656 ImmUnlockIMCC(lpIMC->hPrivate);
657 UnlockRealIMC(hIMC);
660 return TRUE;
663 BOOL WINAPI ImeSetActiveContext(HIMC hIMC,BOOL fFlag)
665 FIXME("(%p, %x): stub\n", hIMC, fFlag);
666 return TRUE;
669 UINT WINAPI ImeToAsciiEx (UINT uVKey, UINT uScanCode,
670 CONST LPBYTE lpbKeyState, LPDWORD lpdwTransKey,
671 UINT fuState, HIMC hIMC)
673 /* See the comment at the head of this file */
674 TRACE("We do no processing via this route\n");
675 return 0;
678 BOOL WINAPI NotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
680 BOOL bRet = FALSE;
681 LPINPUTCONTEXT lpIMC;
683 TRACE("%p %i %i %i\n",hIMC,dwAction,dwIndex,dwValue);
685 lpIMC = LockRealIMC(hIMC);
686 if (lpIMC == NULL)
687 return FALSE;
689 switch (dwAction)
691 case NI_OPENCANDIDATE: FIXME("NI_OPENCANDIDATE\n"); break;
692 case NI_CLOSECANDIDATE: FIXME("NI_CLOSECANDIDATE\n"); break;
693 case NI_SELECTCANDIDATESTR: FIXME("NI_SELECTCANDIDATESTR\n"); break;
694 case NI_CHANGECANDIDATELIST: FIXME("NI_CHANGECANDIDATELIST\n"); break;
695 case NI_SETCANDIDATE_PAGESTART: FIXME("NI_SETCANDIDATE_PAGESTART\n"); break;
696 case NI_SETCANDIDATE_PAGESIZE: FIXME("NI_SETCANDIDATE_PAGESIZE\n"); break;
697 case NI_CONTEXTUPDATED:
698 switch (dwValue)
700 case IMC_SETCOMPOSITIONWINDOW: FIXME("IMC_SETCOMPOSITIONWINDOW\n"); break;
701 case IMC_SETCONVERSIONMODE: FIXME("IMC_SETCONVERSIONMODE\n"); break;
702 case IMC_SETSENTENCEMODE: FIXME("IMC_SETSENTENCEMODE\n"); break;
703 case IMC_SETCANDIDATEPOS: FIXME("IMC_SETCANDIDATEPOS\n"); break;
704 case IMC_SETCOMPOSITIONFONT:
706 LPIMEPRIVATE myPrivate;
707 TRACE("IMC_SETCOMPOSITIONFONT\n");
709 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
710 if (myPrivate->textfont)
712 DeleteObject(myPrivate->textfont);
713 myPrivate->textfont = NULL;
715 myPrivate->textfont = CreateFontIndirectW(&lpIMC->lfFont.W);
716 ImmUnlockIMCC(lpIMC->hPrivate);
718 break;
719 case IMC_SETOPENSTATUS:
720 TRACE("IMC_SETOPENSTATUS\n");
722 bRet = TRUE;
723 X11DRV_SetPreeditState(lpIMC->hWnd, lpIMC->fOpen);
724 if (!lpIMC->fOpen)
726 LPIMEPRIVATE myPrivate;
728 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
729 if (myPrivate->bInComposition)
731 X11DRV_ForceXIMReset(lpIMC->hWnd);
732 GenerateIMEMessage(hIMC, WM_IME_ENDCOMPOSITION, 0, 0);
733 myPrivate->bInComposition = FALSE;
735 ImmUnlockIMCC(lpIMC->hPrivate);
738 break;
739 default: FIXME("Unknown\n"); break;
741 break;
742 case NI_COMPOSITIONSTR:
743 switch (dwIndex)
745 case CPS_COMPLETE:
747 HIMCC newCompStr;
748 DWORD cplen = 0;
749 LPWSTR cpstr;
750 LPCOMPOSITIONSTRING cs = NULL;
751 LPBYTE cdata = NULL;
752 LPIMEPRIVATE myPrivate;
754 TRACE("CPS_COMPLETE\n");
756 /* clear existing result */
757 newCompStr = updateResultStr(lpIMC->hCompStr, NULL, 0);
759 ImmDestroyIMCC(lpIMC->hCompStr);
760 lpIMC->hCompStr = newCompStr;
762 if (lpIMC->hCompStr)
764 cdata = ImmLockIMCC(lpIMC->hCompStr);
765 cs = (LPCOMPOSITIONSTRING)cdata;
766 cplen = cs->dwCompStrLen;
767 cpstr = (LPWSTR)&(cdata[cs->dwCompStrOffset]);
768 ImmUnlockIMCC(lpIMC->hCompStr);
770 if (cplen > 0)
772 WCHAR param = cpstr[0];
774 newCompStr = updateResultStr(lpIMC->hCompStr, cpstr, cplen);
775 ImmDestroyIMCC(lpIMC->hCompStr);
776 lpIMC->hCompStr = newCompStr;
777 newCompStr = updateCompStr(lpIMC->hCompStr, NULL, 0);
778 ImmDestroyIMCC(lpIMC->hCompStr);
779 lpIMC->hCompStr = newCompStr;
781 GenerateIMEMessage(hIMC, WM_IME_COMPOSITION, 0,
782 GCS_COMPSTR);
784 GenerateIMEMessage(hIMC, WM_IME_COMPOSITION, param,
785 GCS_RESULTSTR|GCS_RESULTCLAUSE);
788 GenerateIMEMessage(hIMC,WM_IME_ENDCOMPOSITION, 0, 0);
790 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
791 myPrivate->bInComposition = FALSE;
792 ImmUnlockIMCC(lpIMC->hPrivate);
794 bRet = TRUE;
796 break;
797 case CPS_CONVERT: FIXME("CPS_CONVERT\n"); break;
798 case CPS_REVERT: FIXME("CPS_REVERT\n"); break;
799 case CPS_CANCEL:
801 LPIMEPRIVATE myPrivate;
803 TRACE("CPS_CANCEL\n");
805 X11DRV_ForceXIMReset(lpIMC->hWnd);
807 if (lpIMC->hCompStr)
808 ImmDestroyIMCC(lpIMC->hCompStr);
809 lpIMC->hCompStr = ImeCreateBlankCompStr();
811 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
812 if (myPrivate->bInComposition)
814 GenerateIMEMessage(hIMC, WM_IME_ENDCOMPOSITION, 0, 0);
815 myPrivate->bInComposition = FALSE;
817 ImmUnlockIMCC(lpIMC->hPrivate);
818 bRet = TRUE;
820 break;
821 default: FIXME("Unknown\n"); break;
823 break;
824 default: FIXME("Unknown Message\n"); break;
827 UnlockRealIMC(hIMC);
828 return bRet;
831 BOOL WINAPI ImeRegisterWord(LPCWSTR lpszReading, DWORD dwStyle,
832 LPCWSTR lpszRegister)
834 FIXME("(%s, %d, %s): stub\n", debugstr_w(lpszReading), dwStyle,
835 debugstr_w(lpszRegister));
836 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
837 return FALSE;
840 BOOL WINAPI ImeUnregisterWord(LPCWSTR lpszReading, DWORD dwStyle,
841 LPCWSTR lpszUnregister)
843 FIXME("(%s, %d, %s): stub\n", debugstr_w(lpszReading), dwStyle,
844 debugstr_w(lpszUnregister));
845 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
846 return FALSE;
849 UINT WINAPI ImeGetRegisterWordStyle(UINT nItem, LPSTYLEBUFW lpStyleBuf)
851 FIXME("(%d, %p): stub\n", nItem, lpStyleBuf);
852 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
853 return 0;
856 UINT WINAPI ImeEnumRegisterWord(REGISTERWORDENUMPROCW lpfnEnumProc,
857 LPCWSTR lpszReading, DWORD dwStyle,
858 LPCWSTR lpszRegister, LPVOID lpData)
860 FIXME("(%p, %s, %d, %s, %p): stub\n", lpfnEnumProc,
861 debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister),
862 lpData);
863 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
864 return 0;
867 BOOL WINAPI ImeSetCompositionString(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp,
868 DWORD dwCompLen, LPCVOID lpRead,
869 DWORD dwReadLen)
871 LPINPUTCONTEXT lpIMC;
872 DWORD flags = 0;
873 WCHAR wParam = 0;
874 LPIMEPRIVATE myPrivate;
876 TRACE("(%p, %d, %p, %d, %p, %d):\n",
877 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
880 if (hIMC != FROM_X11)
881 FIXME("PROBLEM: This only sets the wine level string\n");
884 * Explanation:
885 * this sets the composition string in the imm32.dll level
886 * of the composition buffer. we cannot manipulate the xim level
887 * buffer, which means that once the xim level buffer changes again
888 * any call to this function from the application will be lost
891 if (lpRead && dwReadLen)
892 FIXME("Reading string unimplemented\n");
894 lpIMC = LockRealIMC(hIMC);
896 if (lpIMC == NULL)
897 return FALSE;
899 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
901 if (dwIndex == SCS_SETSTR)
903 HIMCC newCompStr;
905 if (!myPrivate->bInComposition)
907 GenerateIMEMessage(hIMC, WM_IME_STARTCOMPOSITION, 0, 0);
908 myPrivate->bInComposition = TRUE;
911 flags = GCS_COMPSTR;
913 if (dwCompLen && lpComp)
915 newCompStr = updateCompStr(lpIMC->hCompStr, (LPCWSTR)lpComp, dwCompLen / sizeof(WCHAR));
916 ImmDestroyIMCC(lpIMC->hCompStr);
917 lpIMC->hCompStr = newCompStr;
919 wParam = ((const WCHAR*)lpComp)[0];
920 flags |= GCS_COMPCLAUSE | GCS_COMPATTR | GCS_DELTASTART;
922 else
924 newCompStr = updateCompStr(lpIMC->hCompStr, NULL, 0);
925 ImmDestroyIMCC(lpIMC->hCompStr);
926 lpIMC->hCompStr = newCompStr;
930 GenerateIMEMessage(hIMC, WM_IME_COMPOSITION, wParam, flags);
931 ImmUnlockIMCC(lpIMC->hPrivate);
932 UnlockRealIMC(hIMC);
934 return TRUE;
937 DWORD WINAPI ImeGetImeMenuItems(HIMC hIMC, DWORD dwFlags, DWORD dwType,
938 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
939 DWORD dwSize)
941 FIXME("(%p, %x %x %p %p %x): stub\n", hIMC, dwFlags, dwType,
942 lpImeParentMenu, lpImeMenu, dwSize);
943 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
944 return 0;
947 /* Interfaces to XIM and other parts of winex11drv */
949 void IME_SetOpenStatus(BOOL fOpen)
951 HIMC imc;
953 imc = RealIMC(FROM_X11);
954 ImmSetOpenStatus(imc, fOpen);
957 void IME_SetCompositionStatus(BOOL fOpen)
959 HIMC imc;
960 LPINPUTCONTEXT lpIMC;
961 LPIMEPRIVATE myPrivate;
963 imc = RealIMC(FROM_X11);
964 lpIMC = ImmLockIMC(imc);
965 if (lpIMC == NULL)
966 return;
968 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
970 if (fOpen && !myPrivate->bInComposition)
972 GenerateIMEMessage(imc, WM_IME_STARTCOMPOSITION, 0, 0);
974 else if (!fOpen && myPrivate->bInComposition)
976 ShowWindow(myPrivate->hwndDefault, SW_HIDE);
977 ImmDestroyIMCC(lpIMC->hCompStr);
978 lpIMC->hCompStr = ImeCreateBlankCompStr();
979 GenerateIMEMessage(imc, WM_IME_ENDCOMPOSITION, 0, 0);
981 myPrivate->bInComposition = fOpen;
983 ImmUnlockIMCC(lpIMC->hPrivate);
984 ImmUnlockIMC(imc);
987 INT IME_GetCursorPos(void)
989 LPINPUTCONTEXT lpIMC;
990 INT rc = 0;
991 LPCOMPOSITIONSTRING compstr;
993 if (!hSelectedFrom)
994 return rc;
996 lpIMC = LockRealIMC(FROM_X11);
997 if (lpIMC)
999 compstr = ImmLockIMCC(lpIMC->hCompStr);
1000 rc = compstr->dwCursorPos;
1001 ImmUnlockIMCC(lpIMC->hCompStr);
1003 UnlockRealIMC(FROM_X11);
1004 return rc;
1007 void IME_SetCursorPos(DWORD pos)
1009 LPINPUTCONTEXT lpIMC;
1010 LPCOMPOSITIONSTRING compstr;
1012 if (!hSelectedFrom)
1013 return;
1015 lpIMC = LockRealIMC(FROM_X11);
1016 if (!lpIMC)
1017 return;
1019 compstr = ImmLockIMCC(lpIMC->hCompStr);
1020 if (!compstr)
1022 UnlockRealIMC(FROM_X11);
1023 return;
1026 compstr->dwCursorPos = pos;
1027 ImmUnlockIMCC(lpIMC->hCompStr);
1028 UnlockRealIMC(FROM_X11);
1029 GenerateIMEMessage(FROM_X11, WM_IME_COMPOSITION, pos, GCS_CURSORPOS);
1030 return;
1033 void IME_UpdateAssociation(HWND focus)
1035 ImmGetContext(focus);
1037 if (!focus || !hSelectedFrom)
1038 return;
1040 ImmAssociateContext(focus,RealIMC(FROM_X11));
1044 BOOL IME_SetCompositionString(DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen,
1045 LPCVOID lpRead, DWORD dwReadLen)
1047 return ImeSetCompositionString(FROM_X11, dwIndex, lpComp, dwCompLen,
1048 lpRead, dwReadLen);
1051 void IME_SetResultString(LPWSTR lpResult, DWORD dwResultLen)
1053 HIMC imc;
1054 LPINPUTCONTEXT lpIMC;
1055 HIMCC newCompStr;
1056 LPIMEPRIVATE myPrivate;
1058 imc = RealIMC(FROM_X11);
1059 lpIMC = ImmLockIMC(imc);
1060 if (lpIMC == NULL)
1061 return;
1063 newCompStr = updateResultStr(lpIMC->hCompStr, lpResult, dwResultLen);
1064 ImmDestroyIMCC(lpIMC->hCompStr);
1065 lpIMC->hCompStr = newCompStr;
1067 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
1068 if (!myPrivate->bInComposition)
1069 GenerateIMEMessage(imc, WM_IME_STARTCOMPOSITION, 0, 0);
1070 GenerateIMEMessage(imc, WM_IME_COMPOSITION, 0, GCS_RESULTSTR);
1071 if (!myPrivate->bInComposition)
1072 GenerateIMEMessage(imc, WM_IME_ENDCOMPOSITION, 0, 0);
1073 ImmUnlockIMCC(lpIMC->hPrivate);
1075 ImmUnlockIMC(imc);
1078 /*****
1079 * Internal functions to help with IME window management
1081 static void PaintDefaultIMEWnd(HIMC hIMC, HWND hwnd)
1083 PAINTSTRUCT ps;
1084 RECT rect;
1085 HDC hdc;
1086 LPCOMPOSITIONSTRING compstr;
1087 LPBYTE compdata = NULL;
1088 HMONITOR monitor;
1089 MONITORINFO mon_info;
1090 INT offX=0, offY=0;
1091 LPINPUTCONTEXT lpIMC;
1093 lpIMC = LockRealIMC(hIMC);
1094 if (lpIMC == NULL)
1095 return;
1097 hdc = BeginPaint(hwnd,&ps);
1099 GetClientRect(hwnd,&rect);
1100 FillRect(hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1));
1102 compdata = ImmLockIMCC(lpIMC->hCompStr);
1103 compstr = (LPCOMPOSITIONSTRING)compdata;
1105 if (compstr->dwCompStrLen && compstr->dwCompStrOffset)
1107 SIZE size;
1108 POINT pt;
1109 HFONT oldfont = NULL;
1110 LPWSTR CompString;
1111 LPIMEPRIVATE myPrivate;
1113 CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
1114 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
1116 if (myPrivate->textfont)
1117 oldfont = SelectObject(hdc,myPrivate->textfont);
1119 ImmUnlockIMCC(lpIMC->hPrivate);
1121 GetTextExtentPoint32W(hdc, CompString, compstr->dwCompStrLen, &size);
1122 pt.x = size.cx;
1123 pt.y = size.cy;
1124 LPtoDP(hdc,&pt,1);
1127 * How this works based on tests on windows:
1128 * CFS_POINT: then we start our window at the point and grow it as large
1129 * as it needs to be for the string.
1130 * CFS_RECT: we still use the ptCurrentPos as a starting point and our
1131 * window is only as large as we need for the string, but we do not
1132 * grow such that our window exceeds the given rect. Wrapping if
1133 * needed and possible. If our ptCurrentPos is outside of our rect
1134 * then no window is displayed.
1135 * CFS_FORCE_POSITION: appears to behave just like CFS_POINT
1136 * maybe because the default MSIME does not do any IME adjusting.
1138 if (lpIMC->cfCompForm.dwStyle != CFS_DEFAULT)
1140 POINT cpt = lpIMC->cfCompForm.ptCurrentPos;
1141 ClientToScreen(lpIMC->hWnd,&cpt);
1142 rect.left = cpt.x;
1143 rect.top = cpt.y;
1144 rect.right = rect.left + pt.x;
1145 rect.bottom = rect.top + pt.y;
1146 monitor = MonitorFromPoint(cpt, MONITOR_DEFAULTTOPRIMARY);
1148 else /* CFS_DEFAULT */
1150 /* Windows places the default IME window in the bottom left */
1151 HWND target = lpIMC->hWnd;
1152 if (!target) target = GetFocus();
1154 GetWindowRect(target,&rect);
1155 rect.top = rect.bottom;
1156 rect.right = rect.left + pt.x + 20;
1157 rect.bottom = rect.top + pt.y + 20;
1158 offX=offY=10;
1159 monitor = MonitorFromWindow(target, MONITOR_DEFAULTTOPRIMARY);
1162 if (lpIMC->cfCompForm.dwStyle == CFS_RECT)
1164 RECT client;
1165 client =lpIMC->cfCompForm.rcArea;
1166 MapWindowPoints( lpIMC->hWnd, 0, (POINT *)&client, 2 );
1167 IntersectRect(&rect,&rect,&client);
1168 /* TODO: Wrap the input if needed */
1171 if (lpIMC->cfCompForm.dwStyle == CFS_DEFAULT)
1173 /* make sure we are on the desktop */
1174 mon_info.cbSize = sizeof(mon_info);
1175 GetMonitorInfoW(monitor, &mon_info);
1177 if (rect.bottom > mon_info.rcWork.bottom)
1179 int shift = rect.bottom - mon_info.rcWork.bottom;
1180 rect.top -= shift;
1181 rect.bottom -= shift;
1183 if (rect.left < 0)
1185 rect.right -= rect.left;
1186 rect.left = 0;
1188 if (rect.right > mon_info.rcWork.right)
1190 int shift = rect.right - mon_info.rcWork.right;
1191 rect.left -= shift;
1192 rect.right -= shift;
1196 SetWindowPos(hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE);
1198 TextOutW(hdc, offX,offY, CompString, compstr->dwCompStrLen);
1200 if (oldfont)
1201 SelectObject(hdc,oldfont);
1204 ImmUnlockIMCC(lpIMC->hCompStr);
1206 EndPaint(hwnd,&ps);
1207 UnlockRealIMC(hIMC);
1210 static void UpdateDefaultIMEWindow(HIMC hIMC, HWND hwnd)
1212 LPCOMPOSITIONSTRING compstr;
1213 LPINPUTCONTEXT lpIMC;
1215 lpIMC = LockRealIMC(hIMC);
1216 if (lpIMC == NULL)
1217 return;
1219 if (lpIMC->hCompStr)
1220 compstr = ImmLockIMCC(lpIMC->hCompStr);
1221 else
1222 compstr = NULL;
1224 if (compstr == NULL || compstr->dwCompStrLen == 0)
1225 ShowWindow(hwnd,SW_HIDE);
1226 else
1228 ShowWindow(hwnd,SW_SHOWNOACTIVATE);
1229 RedrawWindow(hwnd, NULL, NULL, RDW_ERASENOW | RDW_INVALIDATE);
1232 if (compstr != NULL)
1233 ImmUnlockIMCC(lpIMC->hCompStr);
1235 lpIMC->hWnd = GetFocus();
1236 UnlockRealIMC(hIMC);
1239 static void DefaultIMEComposition(HIMC hIMC, HWND hwnd, LPARAM lParam)
1241 TRACE("IME message WM_IME_COMPOSITION 0x%lx\n", lParam);
1242 if (lParam & GCS_RESULTSTR)
1244 LPCOMPOSITIONSTRING compstr;
1245 LPBYTE compdata;
1246 LPWSTR ResultStr;
1247 HIMCC newCompStr;
1248 LPINPUTCONTEXT lpIMC;
1250 lpIMC = LockRealIMC(hIMC);
1251 if (lpIMC == NULL)
1252 return;
1254 TRACE("Posting result as IME_CHAR\n");
1255 compdata = ImmLockIMCC(lpIMC->hCompStr);
1256 compstr = (LPCOMPOSITIONSTRING)compdata;
1257 ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
1258 GenerateIMECHARMessages(hIMC, ResultStr, compstr->dwResultStrLen);
1259 ImmUnlockIMCC(lpIMC->hCompStr);
1261 /* clear the buffer */
1262 newCompStr = updateResultStr(lpIMC->hCompStr, NULL, 0);
1263 ImmDestroyIMCC(lpIMC->hCompStr);
1264 lpIMC->hCompStr = newCompStr;
1265 UnlockRealIMC(hIMC);
1267 else
1268 UpdateDefaultIMEWindow(hIMC, hwnd);
1271 static void DefaultIMEStartComposition(HIMC hIMC, HWND hwnd )
1273 TRACE("IME message WM_IME_STARTCOMPOSITION\n");
1274 UpdateDefaultIMEWindow(hIMC, hwnd);
1277 static LRESULT ImeHandleNotify(HIMC hIMC, HWND hwnd, UINT msg, WPARAM wParam,
1278 LPARAM lParam)
1280 switch (wParam)
1282 case IMN_OPENSTATUSWINDOW:
1283 FIXME("WM_IME_NOTIFY:IMN_OPENSTATUSWINDOW\n");
1284 break;
1285 case IMN_CLOSESTATUSWINDOW:
1286 FIXME("WM_IME_NOTIFY:IMN_CLOSESTATUSWINDOW\n");
1287 break;
1288 case IMN_OPENCANDIDATE:
1289 FIXME("WM_IME_NOTIFY:IMN_OPENCANDIDATE\n");
1290 break;
1291 case IMN_CHANGECANDIDATE:
1292 FIXME("WM_IME_NOTIFY:IMN_CHANGECANDIDATE\n");
1293 break;
1294 case IMN_CLOSECANDIDATE:
1295 FIXME("WM_IME_NOTIFY:IMN_CLOSECANDIDATE\n");
1296 break;
1297 case IMN_SETCONVERSIONMODE:
1298 FIXME("WM_IME_NOTIFY:IMN_SETCONVERSIONMODE\n");
1299 break;
1300 case IMN_SETSENTENCEMODE:
1301 FIXME("WM_IME_NOTIFY:IMN_SETSENTENCEMODE\n");
1302 break;
1303 case IMN_SETOPENSTATUS:
1304 TRACE("WM_IME_NOTIFY:IMN_SETOPENSTATUS\n");
1305 break;
1306 case IMN_SETCANDIDATEPOS:
1307 FIXME("WM_IME_NOTIFY:IMN_SETCANDIDATEPOS\n");
1308 break;
1309 case IMN_SETCOMPOSITIONFONT:
1310 FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONFONT\n");
1311 break;
1312 case IMN_SETCOMPOSITIONWINDOW:
1313 FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONWINDOW\n");
1314 break;
1315 case IMN_GUIDELINE:
1316 FIXME("WM_IME_NOTIFY:IMN_GUIDELINE\n");
1317 break;
1318 case IMN_SETSTATUSWINDOWPOS:
1319 FIXME("WM_IME_NOTIFY:IMN_SETSTATUSWINDOWPOS\n");
1320 break;
1321 default:
1322 FIXME("WM_IME_NOTIFY:<Unknown 0x%lx>\n",wParam);
1323 break;
1325 return 0;
1328 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam,
1329 LPARAM lParam)
1331 LRESULT rc = 0;
1332 HIMC hIMC;
1334 TRACE("Incoming Message 0x%x (0x%08lx, 0x%08lx)\n", msg, wParam, lParam);
1337 * Each UI window contains the current Input Context.
1338 * This Input Context can be obtained by calling GetWindowLong
1339 * with IMMGWL_IMC when the UI window receives a WM_IME_xxx message.
1340 * The UI window can refer to this Input Context and handles the
1341 * messages.
1344 hIMC = (HIMC)GetWindowLongPtrW(hwnd,IMMGWL_IMC);
1345 if (!hIMC)
1346 hIMC = RealIMC(FROM_X11);
1348 /* if we have no hIMC there are many messages we cannot process */
1349 if (hIMC == NULL)
1351 switch (msg) {
1352 case WM_IME_STARTCOMPOSITION:
1353 case WM_IME_ENDCOMPOSITION:
1354 case WM_IME_COMPOSITION:
1355 case WM_IME_NOTIFY:
1356 case WM_IME_CONTROL:
1357 case WM_IME_COMPOSITIONFULL:
1358 case WM_IME_SELECT:
1359 case WM_IME_CHAR:
1360 return 0L;
1361 default:
1362 break;
1366 switch(msg)
1368 case WM_CREATE:
1370 LPIMEPRIVATE myPrivate;
1371 LPINPUTCONTEXT lpIMC;
1373 SetWindowTextA(hwnd,"Wine Ime Active");
1375 lpIMC = LockRealIMC(hIMC);
1376 if (lpIMC)
1378 myPrivate = ImmLockIMCC(lpIMC->hPrivate);
1379 myPrivate->hwndDefault = hwnd;
1380 ImmUnlockIMCC(lpIMC->hPrivate);
1382 UnlockRealIMC(hIMC);
1384 return TRUE;
1386 case WM_PAINT:
1387 PaintDefaultIMEWnd(hIMC, hwnd);
1388 return FALSE;
1390 case WM_NCCREATE:
1391 return TRUE;
1393 case WM_SETFOCUS:
1394 if (wParam)
1395 SetFocus((HWND)wParam);
1396 else
1397 FIXME("Received focus, should never have focus\n");
1398 break;
1399 case WM_IME_COMPOSITION:
1400 DefaultIMEComposition(hIMC, hwnd, lParam);
1401 break;
1402 case WM_IME_STARTCOMPOSITION:
1403 DefaultIMEStartComposition(hIMC, hwnd);
1404 break;
1405 case WM_IME_ENDCOMPOSITION:
1406 TRACE("IME message %s, 0x%lx, 0x%lx\n",
1407 "WM_IME_ENDCOMPOSITION", wParam, lParam);
1408 ShowWindow(hwnd,SW_HIDE);
1409 break;
1410 case WM_IME_SELECT:
1411 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_IME_SELECT", wParam, lParam);
1412 break;
1413 case WM_IME_CONTROL:
1414 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_IME_CONTROL", wParam, lParam);
1415 rc = 1;
1416 break;
1417 case WM_IME_NOTIFY:
1418 rc = ImeHandleNotify(hIMC,hwnd,msg,wParam,lParam);
1419 break;
1420 default:
1421 TRACE("Non-standard message 0x%x\n",msg);
1423 /* check the MSIME messages */
1424 if (msg == WM_MSIME_SERVICE)
1426 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_SERVICE", wParam, lParam);
1427 rc = FALSE;
1429 else if (msg == WM_MSIME_RECONVERTOPTIONS)
1431 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_RECONVERTOPTIONS", wParam, lParam);
1433 else if (msg == WM_MSIME_MOUSE)
1435 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_MOUSE", wParam, lParam);
1437 else if (msg == WM_MSIME_RECONVERTREQUEST)
1439 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_RECONVERTREQUEST", wParam, lParam);
1441 else if (msg == WM_MSIME_RECONVERT)
1443 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_RECONVERT", wParam, lParam);
1445 else if (msg == WM_MSIME_QUERYPOSITION)
1447 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_QUERYPOSITION", wParam, lParam);
1449 else if (msg == WM_MSIME_DOCUMENTFEED)
1451 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_DOCUMENTFEED", wParam, lParam);
1453 /* DefWndProc if not an IME message */
1454 if (!rc && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1455 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP)))
1456 rc = DefWindowProcW(hwnd,msg,wParam,lParam);
1458 return rc;