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
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.
51 #include "wine/debug.h"
57 WINE_DEFAULT_DEBUG_CHANNEL(imm
);
59 #define FROM_X11 ((HIMC)0xcafe1337)
61 typedef struct _IMEPRIVATE
{
66 } IMEPRIVATE
, *LPIMEPRIVATE
;
68 typedef struct _tagTRANSMSG
{
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;
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
,
91 static HIMC
RealIMC(HIMC hIMC
)
96 HWND wnd
= GetFocus();
97 HIMC winHimc
= ImmGetContext(wnd
);
98 for (i
= 0; i
< hSelectedCount
; i
++)
99 if (winHimc
== hSelectedFrom
[i
])
107 static LPINPUTCONTEXT
LockRealIMC(HIMC hIMC
)
109 HIMC real_imc
= RealIMC(hIMC
);
111 return ImmLockIMC(real_imc
);
116 static BOOL
UnlockRealIMC(HIMC hIMC
)
118 HIMC real_imc
= RealIMC(hIMC
);
120 return ImmUnlockIMC(real_imc
);
125 static BOOL WINAPI
register_classes( INIT_ONCE
*once
, void *param
, void **context
)
129 ZeroMemory(&wndClass
, sizeof(WNDCLASSW
));
130 wndClass
.style
= CS_GLOBALCLASS
| CS_IME
| CS_HREDRAW
| CS_VREDRAW
;
131 wndClass
.lpfnWndProc
= IME_WindowProc
;
132 wndClass
.cbClsExtra
= 0;
133 wndClass
.cbWndExtra
= 2 * sizeof(LONG_PTR
);
134 wndClass
.hInstance
= x11drv_module
;
135 wndClass
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
136 wndClass
.hIcon
= LoadIconW(NULL
, (LPWSTR
)IDI_APPLICATION
);
137 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
138 wndClass
.lpszMenuName
= 0;
139 wndClass
.lpszClassName
= UI_CLASS_NAME
;
141 RegisterClassW(&wndClass
);
143 WM_MSIME_SERVICE
= RegisterWindowMessageA("MSIMEService");
144 WM_MSIME_RECONVERTOPTIONS
= RegisterWindowMessageA("MSIMEReconvertOptions");
145 WM_MSIME_MOUSE
= RegisterWindowMessageA("MSIMEMouseOperation");
146 WM_MSIME_RECONVERTREQUEST
= RegisterWindowMessageA("MSIMEReconvertRequest");
147 WM_MSIME_RECONVERT
= RegisterWindowMessageA("MSIMEReconvert");
148 WM_MSIME_QUERYPOSITION
= RegisterWindowMessageA("MSIMEQueryPosition");
149 WM_MSIME_DOCUMENTFEED
= RegisterWindowMessageA("MSIMEDocumentFeed");
153 static HIMCC
ImeCreateBlankCompStr(void)
156 LPCOMPOSITIONSTRING ptr
;
157 rc
= ImmCreateIMCC(sizeof(COMPOSITIONSTRING
));
158 ptr
= ImmLockIMCC(rc
);
159 memset(ptr
,0,sizeof(COMPOSITIONSTRING
));
160 ptr
->dwSize
= sizeof(COMPOSITIONSTRING
);
165 static int updateField(DWORD origLen
, DWORD origOffset
, DWORD currentOffset
,
166 LPBYTE target
, LPBYTE source
, DWORD
* lenParam
,
167 DWORD
* offsetParam
, BOOL wchars
)
169 if (origLen
> 0 && origOffset
> 0)
171 int truelen
= origLen
;
173 truelen
*= sizeof(WCHAR
);
175 memcpy(&target
[currentOffset
], &source
[origOffset
], truelen
);
178 *offsetParam
= currentOffset
;
179 currentOffset
+= truelen
;
181 return currentOffset
;
184 static HIMCC
updateCompStr(HIMCC old
, LPCWSTR compstr
, DWORD len
)
186 /* We need to make sure the CompStr, CompClause and CompAttr fields are all
187 * set and correct. */
190 LPBYTE newdata
= NULL
;
191 LPBYTE olddata
= NULL
;
192 LPCOMPOSITIONSTRING new_one
;
193 LPCOMPOSITIONSTRING lpcs
= NULL
;
194 INT current_offset
= 0;
196 TRACE("%s, %i\n",debugstr_wn(compstr
,len
),len
);
198 if (old
== NULL
&& compstr
== NULL
&& len
== 0)
201 if (compstr
== NULL
&& len
!= 0)
203 ERR("compstr is NULL however we have a len! Please report\n");
209 olddata
= ImmLockIMCC(old
);
210 lpcs
= (LPCOMPOSITIONSTRING
)olddata
;
213 needed_size
= sizeof(COMPOSITIONSTRING
) + len
* sizeof(WCHAR
) +
214 len
+ sizeof(DWORD
) * 2;
218 needed_size
+= lpcs
->dwCompReadAttrLen
;
219 needed_size
+= lpcs
->dwCompReadClauseLen
;
220 needed_size
+= lpcs
->dwCompReadStrLen
* sizeof(WCHAR
);
221 needed_size
+= lpcs
->dwResultReadClauseLen
;
222 needed_size
+= lpcs
->dwResultReadStrLen
* sizeof(WCHAR
);
223 needed_size
+= lpcs
->dwResultClauseLen
;
224 needed_size
+= lpcs
->dwResultStrLen
* sizeof(WCHAR
);
225 needed_size
+= lpcs
->dwPrivateSize
;
227 rc
= ImmCreateIMCC(needed_size
);
228 newdata
= ImmLockIMCC(rc
);
229 new_one
= (LPCOMPOSITIONSTRING
)newdata
;
231 new_one
->dwSize
= needed_size
;
232 current_offset
= sizeof(COMPOSITIONSTRING
);
235 current_offset
= updateField(lpcs
->dwCompReadAttrLen
,
236 lpcs
->dwCompReadAttrOffset
,
237 current_offset
, newdata
, olddata
,
238 &new_one
->dwCompReadAttrLen
,
239 &new_one
->dwCompReadAttrOffset
, FALSE
);
241 current_offset
= updateField(lpcs
->dwCompReadClauseLen
,
242 lpcs
->dwCompReadClauseOffset
,
243 current_offset
, newdata
, olddata
,
244 &new_one
->dwCompReadClauseLen
,
245 &new_one
->dwCompReadClauseOffset
, FALSE
);
247 current_offset
= updateField(lpcs
->dwCompReadStrLen
,
248 lpcs
->dwCompReadStrOffset
,
249 current_offset
, newdata
, olddata
,
250 &new_one
->dwCompReadStrLen
,
251 &new_one
->dwCompReadStrOffset
, TRUE
);
253 /* new CompAttr, CompClause, CompStr, dwCursorPos */
254 new_one
->dwDeltaStart
= 0;
256 current_offset
= updateField(lpcs
->dwResultReadClauseLen
,
257 lpcs
->dwResultReadClauseOffset
,
258 current_offset
, newdata
, olddata
,
259 &new_one
->dwResultReadClauseLen
,
260 &new_one
->dwResultReadClauseOffset
, FALSE
);
262 current_offset
= updateField(lpcs
->dwResultReadStrLen
,
263 lpcs
->dwResultReadStrOffset
,
264 current_offset
, newdata
, olddata
,
265 &new_one
->dwResultReadStrLen
,
266 &new_one
->dwResultReadStrOffset
, TRUE
);
268 current_offset
= updateField(lpcs
->dwResultClauseLen
,
269 lpcs
->dwResultClauseOffset
,
270 current_offset
, newdata
, olddata
,
271 &new_one
->dwResultClauseLen
,
272 &new_one
->dwResultClauseOffset
, FALSE
);
274 current_offset
= updateField(lpcs
->dwResultStrLen
,
275 lpcs
->dwResultStrOffset
,
276 current_offset
, newdata
, olddata
,
277 &new_one
->dwResultStrLen
,
278 &new_one
->dwResultStrOffset
, TRUE
);
280 current_offset
= updateField(lpcs
->dwPrivateSize
,
281 lpcs
->dwPrivateOffset
,
282 current_offset
, newdata
, olddata
,
283 &new_one
->dwPrivateSize
,
284 &new_one
->dwPrivateOffset
, FALSE
);
289 new_one
->dwCompAttrLen
= len
;
292 new_one
->dwCompAttrOffset
= current_offset
;
293 memset(&newdata
[current_offset
],ATTR_INPUT
,len
);
294 current_offset
+= len
;
300 new_one
->dwCompClauseLen
= sizeof(DWORD
) * 2;
301 new_one
->dwCompClauseOffset
= current_offset
;
302 *(DWORD
*)(&newdata
[current_offset
]) = 0;
303 current_offset
+= sizeof(DWORD
);
304 *(DWORD
*)(&newdata
[current_offset
]) = len
;
305 current_offset
+= sizeof(DWORD
);
308 new_one
->dwCompClauseLen
= 0;
311 new_one
->dwCompStrLen
= len
;
314 new_one
->dwCompStrOffset
= current_offset
;
315 memcpy(&newdata
[current_offset
],compstr
,len
*sizeof(WCHAR
));
319 new_one
->dwCursorPos
= len
;
328 static HIMCC
updateResultStr(HIMCC old
, LPWSTR resultstr
, DWORD len
)
330 /* we need to make sure the ResultStr and ResultClause fields are all
334 LPBYTE newdata
= NULL
;
335 LPBYTE olddata
= NULL
;
336 LPCOMPOSITIONSTRING new_one
;
337 LPCOMPOSITIONSTRING lpcs
= NULL
;
338 INT current_offset
= 0;
340 TRACE("%s, %i\n",debugstr_wn(resultstr
,len
),len
);
342 if (old
== NULL
&& resultstr
== NULL
&& len
== 0)
345 if (resultstr
== NULL
&& len
!= 0)
347 ERR("resultstr is NULL however we have a len! Please report\n");
353 olddata
= ImmLockIMCC(old
);
354 lpcs
= (LPCOMPOSITIONSTRING
)olddata
;
357 needed_size
= sizeof(COMPOSITIONSTRING
) + len
* sizeof(WCHAR
) +
362 needed_size
+= lpcs
->dwCompReadAttrLen
;
363 needed_size
+= lpcs
->dwCompReadClauseLen
;
364 needed_size
+= lpcs
->dwCompReadStrLen
* sizeof(WCHAR
);
365 needed_size
+= lpcs
->dwCompAttrLen
;
366 needed_size
+= lpcs
->dwCompClauseLen
;
367 needed_size
+= lpcs
->dwCompStrLen
* sizeof(WCHAR
);
368 needed_size
+= lpcs
->dwResultReadClauseLen
;
369 needed_size
+= lpcs
->dwResultReadStrLen
* sizeof(WCHAR
);
370 needed_size
+= lpcs
->dwPrivateSize
;
372 rc
= ImmCreateIMCC(needed_size
);
373 newdata
= ImmLockIMCC(rc
);
374 new_one
= (LPCOMPOSITIONSTRING
)newdata
;
376 new_one
->dwSize
= needed_size
;
377 current_offset
= sizeof(COMPOSITIONSTRING
);
380 current_offset
= updateField(lpcs
->dwCompReadAttrLen
,
381 lpcs
->dwCompReadAttrOffset
,
382 current_offset
, newdata
, olddata
,
383 &new_one
->dwCompReadAttrLen
,
384 &new_one
->dwCompReadAttrOffset
, FALSE
);
386 current_offset
= updateField(lpcs
->dwCompReadClauseLen
,
387 lpcs
->dwCompReadClauseOffset
,
388 current_offset
, newdata
, olddata
,
389 &new_one
->dwCompReadClauseLen
,
390 &new_one
->dwCompReadClauseOffset
, FALSE
);
392 current_offset
= updateField(lpcs
->dwCompReadStrLen
,
393 lpcs
->dwCompReadStrOffset
,
394 current_offset
, newdata
, olddata
,
395 &new_one
->dwCompReadStrLen
,
396 &new_one
->dwCompReadStrOffset
, TRUE
);
398 current_offset
= updateField(lpcs
->dwCompAttrLen
,
399 lpcs
->dwCompAttrOffset
,
400 current_offset
, newdata
, olddata
,
401 &new_one
->dwCompAttrLen
,
402 &new_one
->dwCompAttrOffset
, FALSE
);
404 current_offset
= updateField(lpcs
->dwCompClauseLen
,
405 lpcs
->dwCompClauseOffset
,
406 current_offset
, newdata
, olddata
,
407 &new_one
->dwCompClauseLen
,
408 &new_one
->dwCompClauseOffset
, FALSE
);
410 current_offset
= updateField(lpcs
->dwCompStrLen
,
411 lpcs
->dwCompStrOffset
,
412 current_offset
, newdata
, olddata
,
413 &new_one
->dwCompStrLen
,
414 &new_one
->dwCompStrOffset
, TRUE
);
416 new_one
->dwCursorPos
= lpcs
->dwCursorPos
;
417 new_one
->dwDeltaStart
= 0;
419 current_offset
= updateField(lpcs
->dwResultReadClauseLen
,
420 lpcs
->dwResultReadClauseOffset
,
421 current_offset
, newdata
, olddata
,
422 &new_one
->dwResultReadClauseLen
,
423 &new_one
->dwResultReadClauseOffset
, FALSE
);
425 current_offset
= updateField(lpcs
->dwResultReadStrLen
,
426 lpcs
->dwResultReadStrOffset
,
427 current_offset
, newdata
, olddata
,
428 &new_one
->dwResultReadStrLen
,
429 &new_one
->dwResultReadStrOffset
, TRUE
);
431 /* new ResultClause , ResultStr */
433 current_offset
= updateField(lpcs
->dwPrivateSize
,
434 lpcs
->dwPrivateOffset
,
435 current_offset
, newdata
, olddata
,
436 &new_one
->dwPrivateSize
,
437 &new_one
->dwPrivateOffset
, FALSE
);
444 new_one
->dwResultClauseLen
= sizeof(DWORD
) * 2;
445 new_one
->dwResultClauseOffset
= current_offset
;
446 *(DWORD
*)(&newdata
[current_offset
]) = 0;
447 current_offset
+= sizeof(DWORD
);
448 *(DWORD
*)(&newdata
[current_offset
]) = len
;
449 current_offset
+= sizeof(DWORD
);
452 new_one
->dwResultClauseLen
= 0;
455 new_one
->dwResultStrLen
= len
;
458 new_one
->dwResultStrOffset
= current_offset
;
459 memcpy(&newdata
[current_offset
],resultstr
,len
*sizeof(WCHAR
));
468 static void GenerateIMEMessage(HIMC hIMC
, UINT msg
, WPARAM wParam
,
471 LPINPUTCONTEXT lpIMC
;
472 LPTRANSMSG lpTransMsg
;
474 lpIMC
= LockRealIMC(hIMC
);
478 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
, (lpIMC
->dwNumMsgBuf
+ 1) *
483 lpTransMsg
= ImmLockIMCC(lpIMC
->hMsgBuf
);
487 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
488 lpTransMsg
->message
= msg
;
489 lpTransMsg
->wParam
= wParam
;
490 lpTransMsg
->lParam
= lParam
;
492 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
493 lpIMC
->dwNumMsgBuf
++;
495 ImmGenerateMessage(RealIMC(hIMC
));
499 static BOOL
IME_RemoveFromSelected(HIMC hIMC
)
502 for (i
= 0; i
< hSelectedCount
; i
++)
503 if (hSelectedFrom
[i
] == hIMC
)
505 if (i
< hSelectedCount
- 1)
506 memmove(&hSelectedFrom
[i
], &hSelectedFrom
[i
+1], (hSelectedCount
- i
- 1)*sizeof(HIMC
));
513 static void IME_AddToSelected(HIMC hIMC
)
517 hSelectedFrom
= HeapReAlloc(GetProcessHeap(), 0, hSelectedFrom
, hSelectedCount
*sizeof(HIMC
));
519 hSelectedFrom
= HeapAlloc(GetProcessHeap(), 0, sizeof(HIMC
));
520 hSelectedFrom
[hSelectedCount
-1] = hIMC
;
523 BOOL WINAPI
ImeInquire(LPIMEINFO lpIMEInfo
, LPWSTR lpszUIClass
,
526 static INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
529 InitOnceExecuteOnce( &init_once
, register_classes
, NULL
, NULL
);
530 lpIMEInfo
->dwPrivateDataSize
= sizeof (IMEPRIVATE
);
531 lpIMEInfo
->fdwProperty
= IME_PROP_UNICODE
| IME_PROP_AT_CARET
;
532 lpIMEInfo
->fdwConversionCaps
= IME_CMODE_NATIVE
| IME_CMODE_FULLSHAPE
;
533 lpIMEInfo
->fdwSentenceCaps
= IME_SMODE_AUTOMATIC
;
534 lpIMEInfo
->fdwUICaps
= UI_CAP_2700
;
535 /* Tell App we cannot accept ImeSetCompositionString calls */
536 lpIMEInfo
->fdwSCSCaps
= 0;
537 lpIMEInfo
->fdwSelectCaps
= SELECT_CAP_CONVERSION
;
539 lstrcpyW(lpszUIClass
,UI_CLASS_NAME
);
544 BOOL WINAPI
ImeConfigure(HKL hKL
,HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
546 FIXME("(%p, %p, %d, %p): stub\n", hKL
, hWnd
, dwMode
, lpData
);
547 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
551 DWORD WINAPI
ImeConversionList(HIMC hIMC
, LPCWSTR lpSource
,
552 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
, UINT uFlag
)
555 FIXME("(%p, %s, %p, %d, %d): stub\n", hIMC
, debugstr_w(lpSource
),
556 lpCandList
, dwBufLen
, uFlag
);
557 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
561 BOOL WINAPI
ImeDestroy(UINT uForce
)
564 HeapFree(GetProcessHeap(),0,hSelectedFrom
);
565 hSelectedFrom
= NULL
;
570 LRESULT WINAPI
ImeEscape(HIMC hIMC
, UINT uSubFunc
, LPVOID lpData
)
572 FIXME("(%p, %d, %p): stub\n", hIMC
, uSubFunc
, lpData
);
573 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
577 BOOL WINAPI
ImeProcessKey(HIMC hIMC
, UINT vKey
, LPARAM lKeyData
, const LPBYTE lpbKeyState
)
579 /* See the comment at the head of this file */
580 TRACE("We do no processing via this route\n");
584 BOOL WINAPI
ImeSelect(HIMC hIMC
, BOOL fSelect
)
586 LPINPUTCONTEXT lpIMC
;
587 TRACE("%p %s\n",hIMC
,(fSelect
)?"TRUE":"FALSE");
589 if (hIMC
== FROM_X11
)
591 ERR("ImeSelect should never be called from X11\n");
600 return IME_RemoveFromSelected(hIMC
);
602 IME_AddToSelected(hIMC
);
604 /* Initialize our structures */
605 lpIMC
= LockRealIMC(hIMC
);
608 LPIMEPRIVATE myPrivate
;
609 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
610 myPrivate
->bInComposition
= FALSE
;
611 myPrivate
->bInternalState
= FALSE
;
612 myPrivate
->textfont
= NULL
;
613 myPrivate
->hwndDefault
= NULL
;
614 ImmUnlockIMCC(lpIMC
->hPrivate
);
621 BOOL WINAPI
ImeSetActiveContext(HIMC hIMC
,BOOL fFlag
)
626 FIXME("(%p, %x): stub\n", hIMC
, fFlag
);
630 UINT WINAPI
ImeToAsciiEx (UINT uVKey
, UINT uScanCode
, const LPBYTE lpbKeyState
,
631 LPDWORD lpdwTransKey
, UINT fuState
, HIMC hIMC
)
633 /* See the comment at the head of this file */
634 TRACE("We do no processing via this route\n");
638 BOOL WINAPI
NotifyIME(HIMC hIMC
, DWORD dwAction
, DWORD dwIndex
, DWORD dwValue
)
641 LPINPUTCONTEXT lpIMC
;
643 TRACE("%p %i %i %i\n",hIMC
,dwAction
,dwIndex
,dwValue
);
645 lpIMC
= LockRealIMC(hIMC
);
651 case NI_OPENCANDIDATE
: FIXME("NI_OPENCANDIDATE\n"); break;
652 case NI_CLOSECANDIDATE
: FIXME("NI_CLOSECANDIDATE\n"); break;
653 case NI_SELECTCANDIDATESTR
: FIXME("NI_SELECTCANDIDATESTR\n"); break;
654 case NI_CHANGECANDIDATELIST
: FIXME("NI_CHANGECANDIDATELIST\n"); break;
655 case NI_SETCANDIDATE_PAGESTART
: FIXME("NI_SETCANDIDATE_PAGESTART\n"); break;
656 case NI_SETCANDIDATE_PAGESIZE
: FIXME("NI_SETCANDIDATE_PAGESIZE\n"); break;
657 case NI_CONTEXTUPDATED
:
660 case IMC_SETCOMPOSITIONWINDOW
: FIXME("IMC_SETCOMPOSITIONWINDOW\n"); break;
661 case IMC_SETCONVERSIONMODE
: FIXME("IMC_SETCONVERSIONMODE\n"); break;
662 case IMC_SETSENTENCEMODE
: FIXME("IMC_SETSENTENCEMODE\n"); break;
663 case IMC_SETCANDIDATEPOS
: FIXME("IMC_SETCANDIDATEPOS\n"); break;
664 case IMC_SETCOMPOSITIONFONT
:
666 LPIMEPRIVATE myPrivate
;
667 TRACE("IMC_SETCOMPOSITIONFONT\n");
669 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
670 if (myPrivate
->textfont
)
672 DeleteObject(myPrivate
->textfont
);
673 myPrivate
->textfont
= NULL
;
675 myPrivate
->textfont
= CreateFontIndirectW(&lpIMC
->lfFont
.W
);
676 ImmUnlockIMCC(lpIMC
->hPrivate
);
679 case IMC_SETOPENSTATUS
:
680 TRACE("IMC_SETOPENSTATUS\n");
683 X11DRV_SetPreeditState(lpIMC
->hWnd
, lpIMC
->fOpen
);
686 LPIMEPRIVATE myPrivate
;
688 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
689 if (myPrivate
->bInComposition
)
691 X11DRV_ForceXIMReset(lpIMC
->hWnd
);
692 GenerateIMEMessage(hIMC
, WM_IME_ENDCOMPOSITION
, 0, 0);
693 myPrivate
->bInComposition
= FALSE
;
695 ImmUnlockIMCC(lpIMC
->hPrivate
);
699 default: FIXME("Unknown\n"); break;
702 case NI_COMPOSITIONSTR
:
710 LPCOMPOSITIONSTRING cs
= NULL
;
712 LPIMEPRIVATE myPrivate
;
714 TRACE("CPS_COMPLETE\n");
716 /* clear existing result */
717 newCompStr
= updateResultStr(lpIMC
->hCompStr
, NULL
, 0);
719 ImmDestroyIMCC(lpIMC
->hCompStr
);
720 lpIMC
->hCompStr
= newCompStr
;
724 cdata
= ImmLockIMCC(lpIMC
->hCompStr
);
725 cs
= (LPCOMPOSITIONSTRING
)cdata
;
726 cplen
= cs
->dwCompStrLen
;
727 cpstr
= (LPWSTR
)&(cdata
[cs
->dwCompStrOffset
]);
728 ImmUnlockIMCC(lpIMC
->hCompStr
);
730 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
733 WCHAR param
= cpstr
[0];
735 newCompStr
= updateResultStr(lpIMC
->hCompStr
, cpstr
, cplen
);
736 ImmDestroyIMCC(lpIMC
->hCompStr
);
737 lpIMC
->hCompStr
= newCompStr
;
738 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
739 ImmDestroyIMCC(lpIMC
->hCompStr
);
740 lpIMC
->hCompStr
= newCompStr
;
742 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, 0,
745 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, param
,
746 GCS_RESULTSTR
|GCS_RESULTCLAUSE
);
748 GenerateIMEMessage(hIMC
,WM_IME_ENDCOMPOSITION
, 0, 0);
750 else if (myPrivate
->bInComposition
)
751 GenerateIMEMessage(hIMC
,WM_IME_ENDCOMPOSITION
, 0, 0);
753 myPrivate
->bInComposition
= FALSE
;
754 ImmUnlockIMCC(lpIMC
->hPrivate
);
759 case CPS_CONVERT
: FIXME("CPS_CONVERT\n"); break;
760 case CPS_REVERT
: FIXME("CPS_REVERT\n"); break;
763 LPIMEPRIVATE myPrivate
;
765 TRACE("CPS_CANCEL\n");
767 X11DRV_ForceXIMReset(lpIMC
->hWnd
);
770 ImmDestroyIMCC(lpIMC
->hCompStr
);
771 lpIMC
->hCompStr
= ImeCreateBlankCompStr();
773 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
774 if (myPrivate
->bInComposition
)
776 GenerateIMEMessage(hIMC
, WM_IME_ENDCOMPOSITION
, 0, 0);
777 myPrivate
->bInComposition
= FALSE
;
779 ImmUnlockIMCC(lpIMC
->hPrivate
);
783 default: FIXME("Unknown\n"); break;
786 default: FIXME("Unknown Message\n"); break;
793 BOOL WINAPI
ImeRegisterWord(LPCWSTR lpszReading
, DWORD dwStyle
,
794 LPCWSTR lpszRegister
)
796 FIXME("(%s, %d, %s): stub\n", debugstr_w(lpszReading
), dwStyle
,
797 debugstr_w(lpszRegister
));
798 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
802 BOOL WINAPI
ImeUnregisterWord(LPCWSTR lpszReading
, DWORD dwStyle
,
803 LPCWSTR lpszUnregister
)
805 FIXME("(%s, %d, %s): stub\n", debugstr_w(lpszReading
), dwStyle
,
806 debugstr_w(lpszUnregister
));
807 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
811 UINT WINAPI
ImeGetRegisterWordStyle(UINT nItem
, LPSTYLEBUFW lpStyleBuf
)
813 FIXME("(%d, %p): stub\n", nItem
, lpStyleBuf
);
814 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
818 UINT WINAPI
ImeEnumRegisterWord(REGISTERWORDENUMPROCW lpfnEnumProc
,
819 LPCWSTR lpszReading
, DWORD dwStyle
,
820 LPCWSTR lpszRegister
, LPVOID lpData
)
822 FIXME("(%p, %s, %d, %s, %p): stub\n", lpfnEnumProc
,
823 debugstr_w(lpszReading
), dwStyle
, debugstr_w(lpszRegister
),
825 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
829 BOOL WINAPI
ImeSetCompositionString(HIMC hIMC
, DWORD dwIndex
, LPCVOID lpComp
,
830 DWORD dwCompLen
, LPCVOID lpRead
,
833 LPINPUTCONTEXT lpIMC
;
836 LPIMEPRIVATE myPrivate
;
838 TRACE("(%p, %d, %p, %d, %p, %d):\n",
839 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
842 if (hIMC
!= FROM_X11
)
843 FIXME("PROBLEM: This only sets the wine level string\n");
847 * this sets the composition string in the imm32.dll level
848 * of the composition buffer. we cannot manipulate the xim level
849 * buffer, which means that once the xim level buffer changes again
850 * any call to this function from the application will be lost
853 if (lpRead
&& dwReadLen
)
854 FIXME("Reading string unimplemented\n");
856 lpIMC
= LockRealIMC(hIMC
);
861 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
863 if (dwIndex
== SCS_SETSTR
)
867 if (!myPrivate
->bInComposition
)
869 GenerateIMEMessage(hIMC
, WM_IME_STARTCOMPOSITION
, 0, 0);
870 myPrivate
->bInComposition
= TRUE
;
873 /* clear existing result */
874 newCompStr
= updateResultStr(lpIMC
->hCompStr
, NULL
, 0);
875 ImmDestroyIMCC(lpIMC
->hCompStr
);
876 lpIMC
->hCompStr
= newCompStr
;
880 if (dwCompLen
&& lpComp
)
882 newCompStr
= updateCompStr(lpIMC
->hCompStr
, (LPCWSTR
)lpComp
, dwCompLen
/ sizeof(WCHAR
));
883 ImmDestroyIMCC(lpIMC
->hCompStr
);
884 lpIMC
->hCompStr
= newCompStr
;
886 wParam
= ((const WCHAR
*)lpComp
)[0];
887 flags
|= GCS_COMPCLAUSE
| GCS_COMPATTR
| GCS_DELTASTART
;
891 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
892 ImmDestroyIMCC(lpIMC
->hCompStr
);
893 lpIMC
->hCompStr
= newCompStr
;
897 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, wParam
, flags
);
898 ImmUnlockIMCC(lpIMC
->hPrivate
);
904 DWORD WINAPI
ImeGetImeMenuItems(HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
905 LPIMEMENUITEMINFOW lpImeParentMenu
, LPIMEMENUITEMINFOW lpImeMenu
,
908 FIXME("(%p, %x %x %p %p %x): stub\n", hIMC
, dwFlags
, dwType
,
909 lpImeParentMenu
, lpImeMenu
, dwSize
);
910 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
914 /* Interfaces to XIM and other parts of winex11drv */
916 void IME_SetOpenStatus(BOOL fOpen
)
920 imc
= RealIMC(FROM_X11
);
921 ImmSetOpenStatus(imc
, fOpen
);
924 void IME_SetCompositionStatus(BOOL fOpen
)
927 LPINPUTCONTEXT lpIMC
;
928 LPIMEPRIVATE myPrivate
;
930 imc
= RealIMC(FROM_X11
);
931 lpIMC
= ImmLockIMC(imc
);
935 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
937 if (fOpen
&& !myPrivate
->bInComposition
)
939 GenerateIMEMessage(imc
, WM_IME_STARTCOMPOSITION
, 0, 0);
941 else if (!fOpen
&& myPrivate
->bInComposition
)
943 ShowWindow(myPrivate
->hwndDefault
, SW_HIDE
);
944 ImmDestroyIMCC(lpIMC
->hCompStr
);
945 lpIMC
->hCompStr
= ImeCreateBlankCompStr();
946 GenerateIMEMessage(imc
, WM_IME_ENDCOMPOSITION
, 0, 0);
948 myPrivate
->bInComposition
= fOpen
;
950 ImmUnlockIMCC(lpIMC
->hPrivate
);
954 INT
IME_GetCursorPos(void)
956 LPINPUTCONTEXT lpIMC
;
958 LPCOMPOSITIONSTRING compstr
;
963 lpIMC
= LockRealIMC(FROM_X11
);
966 compstr
= ImmLockIMCC(lpIMC
->hCompStr
);
967 rc
= compstr
->dwCursorPos
;
968 ImmUnlockIMCC(lpIMC
->hCompStr
);
970 UnlockRealIMC(FROM_X11
);
974 void IME_SetCursorPos(DWORD pos
)
976 LPINPUTCONTEXT lpIMC
;
977 LPCOMPOSITIONSTRING compstr
;
982 lpIMC
= LockRealIMC(FROM_X11
);
986 compstr
= ImmLockIMCC(lpIMC
->hCompStr
);
989 UnlockRealIMC(FROM_X11
);
993 compstr
->dwCursorPos
= pos
;
994 ImmUnlockIMCC(lpIMC
->hCompStr
);
995 UnlockRealIMC(FROM_X11
);
996 GenerateIMEMessage(FROM_X11
, WM_IME_COMPOSITION
, pos
, GCS_CURSORPOS
);
1000 void IME_UpdateAssociation(HWND focus
)
1002 ImmGetContext(focus
);
1004 if (!focus
|| !hSelectedFrom
)
1007 ImmAssociateContext(focus
,RealIMC(FROM_X11
));
1011 BOOL
IME_SetCompositionString(DWORD dwIndex
, LPCVOID lpComp
, DWORD dwCompLen
,
1012 LPCVOID lpRead
, DWORD dwReadLen
)
1014 return ImeSetCompositionString(FROM_X11
, dwIndex
, lpComp
, dwCompLen
,
1018 void IME_SetResultString(LPWSTR lpResult
, DWORD dwResultLen
)
1021 LPINPUTCONTEXT lpIMC
;
1023 LPIMEPRIVATE myPrivate
;
1026 imc
= RealIMC(FROM_X11
);
1027 lpIMC
= ImmLockIMC(imc
);
1031 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
1032 ImmDestroyIMCC(lpIMC
->hCompStr
);
1033 lpIMC
->hCompStr
= newCompStr
;
1035 newCompStr
= updateResultStr(lpIMC
->hCompStr
, lpResult
, dwResultLen
);
1036 ImmDestroyIMCC(lpIMC
->hCompStr
);
1037 lpIMC
->hCompStr
= newCompStr
;
1039 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
1040 inComp
= myPrivate
->bInComposition
;
1041 ImmUnlockIMCC(lpIMC
->hPrivate
);
1045 ImmSetOpenStatus(imc
, TRUE
);
1046 GenerateIMEMessage(imc
, WM_IME_STARTCOMPOSITION
, 0, 0);
1049 GenerateIMEMessage(imc
, WM_IME_COMPOSITION
, 0, GCS_COMPSTR
);
1050 GenerateIMEMessage(imc
, WM_IME_COMPOSITION
, lpResult
[0], GCS_RESULTSTR
|GCS_RESULTCLAUSE
);
1051 GenerateIMEMessage(imc
, WM_IME_ENDCOMPOSITION
, 0, 0);
1054 ImmSetOpenStatus(imc
, FALSE
);
1060 * Internal functions to help with IME window management
1062 static void PaintDefaultIMEWnd(HIMC hIMC
, HWND hwnd
)
1067 LPCOMPOSITIONSTRING compstr
;
1068 LPBYTE compdata
= NULL
;
1070 MONITORINFO mon_info
;
1072 LPINPUTCONTEXT lpIMC
;
1074 lpIMC
= LockRealIMC(hIMC
);
1078 hdc
= BeginPaint(hwnd
,&ps
);
1080 GetClientRect(hwnd
,&rect
);
1081 FillRect(hdc
, &rect
, (HBRUSH
)(COLOR_WINDOW
+ 1));
1083 compdata
= ImmLockIMCC(lpIMC
->hCompStr
);
1084 compstr
= (LPCOMPOSITIONSTRING
)compdata
;
1086 if (compstr
->dwCompStrLen
&& compstr
->dwCompStrOffset
)
1090 HFONT oldfont
= NULL
;
1092 LPIMEPRIVATE myPrivate
;
1094 CompString
= (LPWSTR
)(compdata
+ compstr
->dwCompStrOffset
);
1095 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
1097 if (myPrivate
->textfont
)
1098 oldfont
= SelectObject(hdc
,myPrivate
->textfont
);
1100 ImmUnlockIMCC(lpIMC
->hPrivate
);
1102 GetTextExtentPoint32W(hdc
, CompString
, compstr
->dwCompStrLen
, &size
);
1108 * How this works based on tests on windows:
1109 * CFS_POINT: then we start our window at the point and grow it as large
1110 * as it needs to be for the string.
1111 * CFS_RECT: we still use the ptCurrentPos as a starting point and our
1112 * window is only as large as we need for the string, but we do not
1113 * grow such that our window exceeds the given rect. Wrapping if
1114 * needed and possible. If our ptCurrentPos is outside of our rect
1115 * then no window is displayed.
1116 * CFS_FORCE_POSITION: appears to behave just like CFS_POINT
1117 * maybe because the default MSIME does not do any IME adjusting.
1119 if (lpIMC
->cfCompForm
.dwStyle
!= CFS_DEFAULT
)
1121 POINT cpt
= lpIMC
->cfCompForm
.ptCurrentPos
;
1122 ClientToScreen(lpIMC
->hWnd
,&cpt
);
1125 rect
.right
= rect
.left
+ pt
.x
;
1126 rect
.bottom
= rect
.top
+ pt
.y
;
1127 monitor
= MonitorFromPoint(cpt
, MONITOR_DEFAULTTOPRIMARY
);
1129 else /* CFS_DEFAULT */
1131 /* Windows places the default IME window in the bottom left */
1132 HWND target
= lpIMC
->hWnd
;
1133 if (!target
) target
= GetFocus();
1135 GetWindowRect(target
,&rect
);
1136 rect
.top
= rect
.bottom
;
1137 rect
.right
= rect
.left
+ pt
.x
+ 20;
1138 rect
.bottom
= rect
.top
+ pt
.y
+ 20;
1140 monitor
= MonitorFromWindow(target
, MONITOR_DEFAULTTOPRIMARY
);
1143 if (lpIMC
->cfCompForm
.dwStyle
== CFS_RECT
)
1146 client
=lpIMC
->cfCompForm
.rcArea
;
1147 MapWindowPoints( lpIMC
->hWnd
, 0, (POINT
*)&client
, 2 );
1148 IntersectRect(&rect
,&rect
,&client
);
1149 /* TODO: Wrap the input if needed */
1152 if (lpIMC
->cfCompForm
.dwStyle
== CFS_DEFAULT
)
1154 /* make sure we are on the desktop */
1155 mon_info
.cbSize
= sizeof(mon_info
);
1156 GetMonitorInfoW(monitor
, &mon_info
);
1158 if (rect
.bottom
> mon_info
.rcWork
.bottom
)
1160 int shift
= rect
.bottom
- mon_info
.rcWork
.bottom
;
1162 rect
.bottom
-= shift
;
1166 rect
.right
-= rect
.left
;
1169 if (rect
.right
> mon_info
.rcWork
.right
)
1171 int shift
= rect
.right
- mon_info
.rcWork
.right
;
1173 rect
.right
-= shift
;
1177 SetWindowPos(hwnd
, HWND_TOPMOST
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, SWP_NOACTIVATE
);
1179 TextOutW(hdc
, offX
,offY
, CompString
, compstr
->dwCompStrLen
);
1182 SelectObject(hdc
,oldfont
);
1185 ImmUnlockIMCC(lpIMC
->hCompStr
);
1188 UnlockRealIMC(hIMC
);
1191 static void UpdateDefaultIMEWindow(HIMC hIMC
, HWND hwnd
)
1193 LPCOMPOSITIONSTRING compstr
;
1194 LPINPUTCONTEXT lpIMC
;
1196 lpIMC
= LockRealIMC(hIMC
);
1200 if (lpIMC
->hCompStr
)
1201 compstr
= ImmLockIMCC(lpIMC
->hCompStr
);
1205 if (compstr
== NULL
|| compstr
->dwCompStrLen
== 0)
1206 ShowWindow(hwnd
,SW_HIDE
);
1209 ShowWindow(hwnd
,SW_SHOWNOACTIVATE
);
1210 RedrawWindow(hwnd
, NULL
, NULL
, RDW_ERASENOW
| RDW_INVALIDATE
);
1213 if (compstr
!= NULL
)
1214 ImmUnlockIMCC(lpIMC
->hCompStr
);
1216 lpIMC
->hWnd
= GetFocus();
1217 UnlockRealIMC(hIMC
);
1220 static void DefaultIMEComposition(HIMC hIMC
, HWND hwnd
, LPARAM lParam
)
1222 TRACE("IME message WM_IME_COMPOSITION 0x%lx\n", lParam
);
1223 if (!(lParam
& GCS_RESULTSTR
))
1224 UpdateDefaultIMEWindow(hIMC
, hwnd
);
1227 static void DefaultIMEStartComposition(HIMC hIMC
, HWND hwnd
)
1229 TRACE("IME message WM_IME_STARTCOMPOSITION\n");
1230 UpdateDefaultIMEWindow(hIMC
, hwnd
);
1233 static LRESULT
ImeHandleNotify(HIMC hIMC
, HWND hwnd
, UINT msg
, WPARAM wParam
,
1238 case IMN_OPENSTATUSWINDOW
:
1239 FIXME("WM_IME_NOTIFY:IMN_OPENSTATUSWINDOW\n");
1241 case IMN_CLOSESTATUSWINDOW
:
1242 FIXME("WM_IME_NOTIFY:IMN_CLOSESTATUSWINDOW\n");
1244 case IMN_OPENCANDIDATE
:
1245 FIXME("WM_IME_NOTIFY:IMN_OPENCANDIDATE\n");
1247 case IMN_CHANGECANDIDATE
:
1248 FIXME("WM_IME_NOTIFY:IMN_CHANGECANDIDATE\n");
1250 case IMN_CLOSECANDIDATE
:
1251 FIXME("WM_IME_NOTIFY:IMN_CLOSECANDIDATE\n");
1253 case IMN_SETCONVERSIONMODE
:
1254 FIXME("WM_IME_NOTIFY:IMN_SETCONVERSIONMODE\n");
1256 case IMN_SETSENTENCEMODE
:
1257 FIXME("WM_IME_NOTIFY:IMN_SETSENTENCEMODE\n");
1259 case IMN_SETOPENSTATUS
:
1260 TRACE("WM_IME_NOTIFY:IMN_SETOPENSTATUS\n");
1262 case IMN_SETCANDIDATEPOS
:
1263 FIXME("WM_IME_NOTIFY:IMN_SETCANDIDATEPOS\n");
1265 case IMN_SETCOMPOSITIONFONT
:
1266 FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONFONT\n");
1268 case IMN_SETCOMPOSITIONWINDOW
:
1269 FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONWINDOW\n");
1272 FIXME("WM_IME_NOTIFY:IMN_GUIDELINE\n");
1274 case IMN_SETSTATUSWINDOWPOS
:
1275 FIXME("WM_IME_NOTIFY:IMN_SETSTATUSWINDOWPOS\n");
1278 FIXME("WM_IME_NOTIFY:<Unknown 0x%lx>\n",wParam
);
1284 static LRESULT WINAPI
IME_WindowProc(HWND hwnd
, UINT msg
, WPARAM wParam
,
1290 TRACE("Incoming Message 0x%x (0x%08lx, 0x%08lx)\n", msg
, wParam
, lParam
);
1293 * Each UI window contains the current Input Context.
1294 * This Input Context can be obtained by calling GetWindowLong
1295 * with IMMGWL_IMC when the UI window receives a WM_IME_xxx message.
1296 * The UI window can refer to this Input Context and handles the
1300 hIMC
= (HIMC
)GetWindowLongPtrW(hwnd
,IMMGWL_IMC
);
1302 hIMC
= RealIMC(FROM_X11
);
1304 /* if we have no hIMC there are many messages we cannot process */
1308 case WM_IME_STARTCOMPOSITION
:
1309 case WM_IME_ENDCOMPOSITION
:
1310 case WM_IME_COMPOSITION
:
1312 case WM_IME_CONTROL
:
1313 case WM_IME_COMPOSITIONFULL
:
1326 LPIMEPRIVATE myPrivate
;
1327 LPINPUTCONTEXT lpIMC
;
1329 SetWindowTextA(hwnd
,"Wine Ime Active");
1331 lpIMC
= LockRealIMC(hIMC
);
1334 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
1335 myPrivate
->hwndDefault
= hwnd
;
1336 ImmUnlockIMCC(lpIMC
->hPrivate
);
1338 UnlockRealIMC(hIMC
);
1343 PaintDefaultIMEWnd(hIMC
, hwnd
);
1351 SetFocus((HWND
)wParam
);
1353 FIXME("Received focus, should never have focus\n");
1355 case WM_IME_COMPOSITION
:
1356 DefaultIMEComposition(hIMC
, hwnd
, lParam
);
1358 case WM_IME_STARTCOMPOSITION
:
1359 DefaultIMEStartComposition(hIMC
, hwnd
);
1361 case WM_IME_ENDCOMPOSITION
:
1362 TRACE("IME message %s, 0x%lx, 0x%lx\n",
1363 "WM_IME_ENDCOMPOSITION", wParam
, lParam
);
1364 ShowWindow(hwnd
,SW_HIDE
);
1367 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_IME_SELECT", wParam
, lParam
);
1369 case WM_IME_CONTROL
:
1370 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_IME_CONTROL", wParam
, lParam
);
1374 rc
= ImeHandleNotify(hIMC
,hwnd
,msg
,wParam
,lParam
);
1377 TRACE("Non-standard message 0x%x\n",msg
);
1379 /* check the MSIME messages */
1380 if (msg
== WM_MSIME_SERVICE
)
1382 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_SERVICE", wParam
, lParam
);
1385 else if (msg
== WM_MSIME_RECONVERTOPTIONS
)
1387 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_RECONVERTOPTIONS", wParam
, lParam
);
1389 else if (msg
== WM_MSIME_MOUSE
)
1391 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_MOUSE", wParam
, lParam
);
1393 else if (msg
== WM_MSIME_RECONVERTREQUEST
)
1395 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_RECONVERTREQUEST", wParam
, lParam
);
1397 else if (msg
== WM_MSIME_RECONVERT
)
1399 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_RECONVERT", wParam
, lParam
);
1401 else if (msg
== WM_MSIME_QUERYPOSITION
)
1403 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_QUERYPOSITION", wParam
, lParam
);
1405 else if (msg
== WM_MSIME_DOCUMENTFEED
)
1407 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_DOCUMENTFEED", wParam
, lParam
);
1409 /* DefWndProc if not an IME message */
1410 if (!rc
&& !((msg
>= WM_IME_STARTCOMPOSITION
&& msg
<= WM_IME_KEYLAST
) ||
1411 (msg
>= WM_IME_SETCONTEXT
&& msg
<= WM_IME_KEYUP
)))
1412 rc
= DefWindowProcW(hwnd
,msg
,wParam
,lParam
);