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 implimenetaion.
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
,
90 static void UpdateDataInDefaultIMEWindow(HIMC hHIMC
, HWND hwnd
, BOOL showable
);
92 static HIMC
RealIMC(HIMC hIMC
)
97 HWND wnd
= GetFocus();
98 HIMC winHimc
= ImmGetContext(wnd
);
99 for (i
= 0; i
< hSelectedCount
; i
++)
100 if (winHimc
== hSelectedFrom
[i
])
108 static LPINPUTCONTEXT
LockRealIMC(HIMC hIMC
)
110 HIMC real_imc
= RealIMC(hIMC
);
112 return ImmLockIMC(real_imc
);
117 static BOOL
UnlockRealIMC(HIMC hIMC
)
119 HIMC real_imc
= RealIMC(hIMC
);
121 return ImmUnlockIMC(real_imc
);
126 static void IME_RegisterClasses(void)
134 ZeroMemory(&wndClass
, sizeof(WNDCLASSW
));
135 wndClass
.style
= CS_GLOBALCLASS
| CS_IME
| CS_HREDRAW
| CS_VREDRAW
;
136 wndClass
.lpfnWndProc
= IME_WindowProc
;
137 wndClass
.cbClsExtra
= 0;
138 wndClass
.cbWndExtra
= 2 * sizeof(LONG_PTR
);
139 wndClass
.hInstance
= x11drv_module
;
140 wndClass
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
141 wndClass
.hIcon
= LoadIconW(NULL
, (LPWSTR
)IDI_APPLICATION
);
142 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
143 wndClass
.lpszMenuName
= 0;
144 wndClass
.lpszClassName
= UI_CLASS_NAME
;
146 RegisterClassW(&wndClass
);
148 WM_MSIME_SERVICE
= RegisterWindowMessageA("MSIMEService");
149 WM_MSIME_RECONVERTOPTIONS
= RegisterWindowMessageA("MSIMEReconvertOptions");
150 WM_MSIME_MOUSE
= RegisterWindowMessageA("MSIMEMouseOperation");
151 WM_MSIME_RECONVERTREQUEST
= RegisterWindowMessageA("MSIMEReconvertRequest");
152 WM_MSIME_RECONVERT
= RegisterWindowMessageA("MSIMEReconvert");
153 WM_MSIME_QUERYPOSITION
= RegisterWindowMessageA("MSIMEQueryPosition");
154 WM_MSIME_DOCUMENTFEED
= RegisterWindowMessageA("MSIMEDocumentFeed");
157 void IME_UnregisterClasses(void)
159 UnregisterClassW(UI_CLASS_NAME
, x11drv_module
);
162 static HIMCC
ImeCreateBlankCompStr(void)
165 LPCOMPOSITIONSTRING ptr
;
166 rc
= ImmCreateIMCC(sizeof(COMPOSITIONSTRING
));
167 ptr
= ImmLockIMCC(rc
);
168 memset(ptr
,0,sizeof(COMPOSITIONSTRING
));
169 ptr
->dwSize
= sizeof(COMPOSITIONSTRING
);
174 static int updateField(DWORD origLen
, DWORD origOffset
, DWORD currentOffset
,
175 LPBYTE target
, LPBYTE source
, DWORD
* lenParam
,
176 DWORD
* offsetParam
, BOOL wchars
)
178 if (origLen
> 0 && origOffset
> 0)
180 int truelen
= origLen
;
182 truelen
*= sizeof(WCHAR
);
184 memcpy(&target
[currentOffset
], &source
[origOffset
], truelen
);
187 *offsetParam
= currentOffset
;
188 currentOffset
+= truelen
;
190 return currentOffset
;
193 static HIMCC
updateCompStr(HIMCC old
, LPWSTR compstr
, DWORD len
)
195 /* we need to make sure the CompStr, CompClaus and CompAttr fields are all
199 LPBYTE newdata
= NULL
;
200 LPBYTE olddata
= NULL
;
201 LPCOMPOSITIONSTRING new_one
;
202 LPCOMPOSITIONSTRING lpcs
= NULL
;
203 INT current_offset
= 0;
205 TRACE("%s, %i\n",debugstr_wn(compstr
,len
),len
);
207 if (old
== NULL
&& compstr
== NULL
&& len
== 0)
210 if (compstr
== NULL
&& len
!= 0)
212 ERR("compstr is NULL however we have a len! Please report\n");
218 olddata
= ImmLockIMCC(old
);
219 lpcs
= (LPCOMPOSITIONSTRING
)olddata
;
222 needed_size
= sizeof(COMPOSITIONSTRING
) + len
* sizeof(WCHAR
) +
223 len
+ sizeof(DWORD
) * 2;
227 needed_size
+= lpcs
->dwCompReadAttrLen
;
228 needed_size
+= lpcs
->dwCompReadClauseLen
;
229 needed_size
+= lpcs
->dwCompReadStrLen
* sizeof(DWORD
);
230 needed_size
+= lpcs
->dwResultReadClauseLen
;
231 needed_size
+= lpcs
->dwResultReadStrLen
* sizeof(DWORD
);
232 needed_size
+= lpcs
->dwResultClauseLen
;
233 needed_size
+= lpcs
->dwResultStrLen
* sizeof(DWORD
);
234 needed_size
+= lpcs
->dwPrivateSize
;
236 rc
= ImmCreateIMCC(needed_size
);
237 newdata
= ImmLockIMCC(rc
);
238 new_one
= (LPCOMPOSITIONSTRING
)newdata
;
240 new_one
->dwSize
= needed_size
;
241 current_offset
= sizeof(COMPOSITIONSTRING
);
244 current_offset
= updateField(lpcs
->dwCompReadAttrLen
,
245 lpcs
->dwCompReadAttrOffset
,
246 current_offset
, newdata
, olddata
,
247 &new_one
->dwCompReadAttrLen
,
248 &new_one
->dwCompReadAttrOffset
, FALSE
);
250 current_offset
= updateField(lpcs
->dwCompReadClauseLen
,
251 lpcs
->dwCompReadClauseOffset
,
252 current_offset
, newdata
, olddata
,
253 &new_one
->dwCompReadClauseLen
,
254 &new_one
->dwCompReadClauseOffset
, FALSE
);
256 current_offset
= updateField(lpcs
->dwCompReadStrLen
,
257 lpcs
->dwCompReadStrOffset
,
258 current_offset
, newdata
, olddata
,
259 &new_one
->dwCompReadStrLen
,
260 &new_one
->dwCompReadStrOffset
, TRUE
);
262 /* new CompAttr, CompClause, CompStr, dwCursorPos */
263 new_one
->dwDeltaStart
= 0;
265 current_offset
= updateField(lpcs
->dwResultReadClauseLen
,
266 lpcs
->dwResultReadClauseOffset
,
267 current_offset
, newdata
, olddata
,
268 &new_one
->dwResultReadClauseLen
,
269 &new_one
->dwResultReadClauseOffset
, FALSE
);
271 current_offset
= updateField(lpcs
->dwResultReadStrLen
,
272 lpcs
->dwResultReadStrOffset
,
273 current_offset
, newdata
, olddata
,
274 &new_one
->dwResultReadStrLen
,
275 &new_one
->dwResultReadStrOffset
, TRUE
);
277 current_offset
= updateField(lpcs
->dwResultClauseLen
,
278 lpcs
->dwResultClauseOffset
,
279 current_offset
, newdata
, olddata
,
280 &new_one
->dwResultClauseLen
,
281 &new_one
->dwResultClauseOffset
, FALSE
);
283 current_offset
= updateField(lpcs
->dwResultStrLen
,
284 lpcs
->dwResultStrOffset
,
285 current_offset
, newdata
, olddata
,
286 &new_one
->dwResultStrLen
,
287 &new_one
->dwResultStrOffset
, TRUE
);
289 current_offset
= updateField(lpcs
->dwPrivateSize
,
290 lpcs
->dwPrivateOffset
,
291 current_offset
, newdata
, olddata
,
292 &new_one
->dwPrivateSize
,
293 &new_one
->dwPrivateOffset
, FALSE
);
298 new_one
->dwCompAttrLen
= len
;
301 new_one
->dwCompAttrOffset
= current_offset
;
302 memset(&newdata
[current_offset
],ATTR_INPUT
,len
);
303 current_offset
+= len
;
309 new_one
->dwCompClauseLen
= sizeof(DWORD
) * 2;
310 new_one
->dwCompClauseOffset
= current_offset
;
311 *(DWORD
*)(&newdata
[current_offset
]) = 0;
312 current_offset
+= sizeof(DWORD
);
313 *(DWORD
*)(&newdata
[current_offset
]) = len
;
314 current_offset
+= sizeof(DWORD
);
318 new_one
->dwCompStrLen
= len
;
321 new_one
->dwCompStrOffset
= current_offset
;
322 memcpy(&newdata
[current_offset
],compstr
,len
*sizeof(WCHAR
));
326 new_one
->dwCursorPos
= len
;
335 static HIMCC
updateResultStr(HIMCC old
, LPWSTR resultstr
, DWORD len
)
337 /* we need to make sure the ResultStr and ResultClause fields are all
341 LPBYTE newdata
= NULL
;
342 LPBYTE olddata
= NULL
;
343 LPCOMPOSITIONSTRING new_one
;
344 LPCOMPOSITIONSTRING lpcs
= NULL
;
345 INT current_offset
= 0;
347 TRACE("%s, %i\n",debugstr_wn(resultstr
,len
),len
);
349 if (old
== NULL
&& resultstr
== NULL
&& len
== 0)
352 if (resultstr
== NULL
&& len
!= 0)
354 ERR("resultstr is NULL however we have a len! Please report\n");
360 olddata
= ImmLockIMCC(old
);
361 lpcs
= (LPCOMPOSITIONSTRING
)olddata
;
364 needed_size
= sizeof(COMPOSITIONSTRING
) + len
* sizeof(WCHAR
) +
369 needed_size
+= lpcs
->dwCompReadAttrLen
;
370 needed_size
+= lpcs
->dwCompReadClauseLen
;
371 needed_size
+= lpcs
->dwCompReadStrLen
* sizeof(DWORD
);
372 needed_size
+= lpcs
->dwCompAttrLen
;
373 needed_size
+= lpcs
->dwCompClauseLen
;
374 needed_size
+= lpcs
->dwCompStrLen
* sizeof(DWORD
);
375 needed_size
+= lpcs
->dwResultReadClauseLen
;
376 needed_size
+= lpcs
->dwResultReadStrLen
* sizeof(DWORD
);
377 needed_size
+= lpcs
->dwPrivateSize
;
379 rc
= ImmCreateIMCC(needed_size
);
380 newdata
= ImmLockIMCC(rc
);
381 new_one
= (LPCOMPOSITIONSTRING
)newdata
;
383 new_one
->dwSize
= needed_size
;
384 current_offset
= sizeof(COMPOSITIONSTRING
);
387 current_offset
= updateField(lpcs
->dwCompReadAttrLen
,
388 lpcs
->dwCompReadAttrOffset
,
389 current_offset
, newdata
, olddata
,
390 &new_one
->dwCompReadAttrLen
,
391 &new_one
->dwCompReadAttrOffset
, FALSE
);
393 current_offset
= updateField(lpcs
->dwCompReadClauseLen
,
394 lpcs
->dwCompReadClauseOffset
,
395 current_offset
, newdata
, olddata
,
396 &new_one
->dwCompReadClauseLen
,
397 &new_one
->dwCompReadClauseOffset
, FALSE
);
399 current_offset
= updateField(lpcs
->dwCompReadStrLen
,
400 lpcs
->dwCompReadStrOffset
,
401 current_offset
, newdata
, olddata
,
402 &new_one
->dwCompReadStrLen
,
403 &new_one
->dwCompReadStrOffset
, TRUE
);
405 current_offset
= updateField(lpcs
->dwCompAttrLen
,
406 lpcs
->dwCompAttrOffset
,
407 current_offset
, newdata
, olddata
,
408 &new_one
->dwCompAttrLen
,
409 &new_one
->dwCompAttrOffset
, FALSE
);
411 current_offset
= updateField(lpcs
->dwCompClauseLen
,
412 lpcs
->dwCompClauseOffset
,
413 current_offset
, newdata
, olddata
,
414 &new_one
->dwCompClauseLen
,
415 &new_one
->dwCompClauseOffset
, FALSE
);
417 current_offset
= updateField(lpcs
->dwCompStrLen
,
418 lpcs
->dwCompStrOffset
,
419 current_offset
, newdata
, olddata
,
420 &new_one
->dwCompStrLen
,
421 &new_one
->dwCompStrOffset
, TRUE
);
423 new_one
->dwCursorPos
= lpcs
->dwCursorPos
;
424 new_one
->dwDeltaStart
= 0;
426 current_offset
= updateField(lpcs
->dwResultReadClauseLen
,
427 lpcs
->dwResultReadClauseOffset
,
428 current_offset
, newdata
, olddata
,
429 &new_one
->dwResultReadClauseLen
,
430 &new_one
->dwResultReadClauseOffset
, FALSE
);
432 current_offset
= updateField(lpcs
->dwResultReadStrLen
,
433 lpcs
->dwResultReadStrOffset
,
434 current_offset
, newdata
, olddata
,
435 &new_one
->dwResultReadStrLen
,
436 &new_one
->dwResultReadStrOffset
, TRUE
);
438 /* new ResultClause , ResultStr */
440 current_offset
= updateField(lpcs
->dwPrivateSize
,
441 lpcs
->dwPrivateOffset
,
442 current_offset
, newdata
, olddata
,
443 &new_one
->dwPrivateSize
,
444 &new_one
->dwPrivateOffset
, FALSE
);
451 new_one
->dwResultClauseLen
= sizeof(DWORD
) * 2;
452 new_one
->dwResultClauseOffset
= current_offset
;
453 *(DWORD
*)(&newdata
[current_offset
]) = 0;
454 current_offset
+= sizeof(DWORD
);
455 *(DWORD
*)(&newdata
[current_offset
]) = len
;
456 current_offset
+= sizeof(DWORD
);
460 new_one
->dwResultStrLen
= len
;
463 new_one
->dwResultStrOffset
= current_offset
;
464 memcpy(&newdata
[current_offset
],resultstr
,len
*sizeof(WCHAR
));
473 static void GenerateIMEMessage(HIMC hIMC
, UINT msg
, WPARAM wParam
,
476 LPINPUTCONTEXT lpIMC
;
477 LPTRANSMSG lpTransMsg
;
479 lpIMC
= LockRealIMC(hIMC
);
483 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
, (lpIMC
->dwNumMsgBuf
+ 1) *
488 lpTransMsg
= ImmLockIMCC(lpIMC
->hMsgBuf
);
492 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
493 lpTransMsg
->message
= msg
;
494 lpTransMsg
->wParam
= wParam
;
495 lpTransMsg
->lParam
= lParam
;
497 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
498 lpIMC
->dwNumMsgBuf
++;
500 ImmGenerateMessage(RealIMC(hIMC
));
504 static void GenerateIMECHARMessages(HIMC hIMC
, LPWSTR String
, DWORD length
)
506 LPINPUTCONTEXT lpIMC
;
507 LPTRANSMSG lpTransMsg
;
513 lpIMC
= LockRealIMC(hIMC
);
517 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
,
518 (lpIMC
->dwNumMsgBuf
+ length
) *
523 lpTransMsg
= ImmLockIMCC(lpIMC
->hMsgBuf
);
527 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
528 for (i
= 0; i
< length
; i
++)
530 lpTransMsg
->message
= WM_IME_CHAR
;
531 lpTransMsg
->wParam
= String
[i
];
532 lpTransMsg
->lParam
= 1;
536 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
537 lpIMC
->dwNumMsgBuf
+=length
;
539 ImmGenerateMessage(RealIMC(hIMC
));
543 static BOOL
IME_RemoveFromSelected(HIMC hIMC
)
546 for (i
= 0; i
< hSelectedCount
; i
++)
547 if (hSelectedFrom
[i
] == hIMC
)
549 if (i
< hSelectedCount
- 1)
550 memmove(&hSelectedFrom
[i
], &hSelectedFrom
[i
+1], (hSelectedCount
- i
- 1)*sizeof(HIMC
));
557 static void IME_AddToSelected(HIMC hIMC
)
561 hSelectedFrom
= HeapReAlloc(GetProcessHeap(), 0, hSelectedFrom
, hSelectedCount
*sizeof(HIMC
));
563 hSelectedFrom
= HeapAlloc(GetProcessHeap(), 0, sizeof(HIMC
));
564 hSelectedFrom
[hSelectedCount
-1] = hIMC
;
567 BOOL WINAPI
ImeInquire(LPIMEINFO lpIMEInfo
, LPWSTR lpszUIClass
,
571 IME_RegisterClasses();
572 lpIMEInfo
->dwPrivateDataSize
= sizeof (IMEPRIVATE
);
573 lpIMEInfo
->fdwProperty
= IME_PROP_UNICODE
| IME_PROP_AT_CARET
;
574 lpIMEInfo
->fdwConversionCaps
= IME_CMODE_NATIVE
;
575 lpIMEInfo
->fdwSentenceCaps
= IME_SMODE_AUTOMATIC
;
576 lpIMEInfo
->fdwUICaps
= UI_CAP_2700
;
577 /* Tell App we cannot accept ImeSetCompositionString calls */
578 lpIMEInfo
->fdwSCSCaps
= 0;
579 lpIMEInfo
->fdwSelectCaps
= SELECT_CAP_CONVERSION
;
581 lstrcpyW(lpszUIClass
,UI_CLASS_NAME
);
586 BOOL WINAPI
ImeConfigure(HKL hKL
,HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
588 FIXME("(%p, %p, %d, %p): stub\n", hKL
, hWnd
, dwMode
, lpData
);
589 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
593 DWORD WINAPI
ImeConversionList(HIMC hIMC
, LPCWSTR lpSource
,
594 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
, UINT uFlag
)
597 FIXME("(%p, %s, %p, %d, %d): stub\n", hIMC
, debugstr_w(lpSource
),
598 lpCandList
, dwBufLen
, uFlag
);
599 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
603 BOOL WINAPI
ImeDestroy(UINT uForce
)
606 HeapFree(GetProcessHeap(),0,hSelectedFrom
);
607 hSelectedFrom
= NULL
;
612 LRESULT WINAPI
ImeEscape(HIMC hIMC
, UINT uSubFunc
, LPVOID lpData
)
614 FIXME("(%p, %d, %p): stub\n", hIMC
, uSubFunc
, lpData
);
615 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
619 BOOL WINAPI
ImeProcessKey(HIMC hIMC
, UINT vKey
, LPARAM lKeyData
,
620 CONST LPBYTE lpbKeyState
)
622 /* See the comment at the head of this file */
623 TRACE("We do no processing via this route\n");
627 BOOL WINAPI
ImeSelect(HIMC hIMC
, BOOL fSelect
)
629 LPINPUTCONTEXT lpIMC
;
630 TRACE("%p %s\n",hIMC
,(fSelect
)?"TRUE":"FALSE");
632 if (hIMC
== FROM_X11
)
634 ERR("ImeSelect should never be called from X11\n");
643 return IME_RemoveFromSelected(hIMC
);
645 IME_AddToSelected(hIMC
);
647 /* Initialize our structures */
648 lpIMC
= LockRealIMC(hIMC
);
651 LPIMEPRIVATE myPrivate
;
652 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
653 myPrivate
->bInComposition
= FALSE
;
654 myPrivate
->bInternalState
= FALSE
;
655 myPrivate
->textfont
= NULL
;
656 myPrivate
->hwndDefault
= NULL
;
657 ImmUnlockIMCC(lpIMC
->hPrivate
);
664 BOOL WINAPI
ImeSetActiveContext(HIMC hIMC
,BOOL fFlag
)
666 FIXME("(%p, %x): stub\n", hIMC
, fFlag
);
670 UINT WINAPI
ImeToAsciiEx (UINT uVKey
, UINT uScanCode
,
671 CONST LPBYTE lpbKeyState
, LPDWORD lpdwTransKey
,
672 UINT fuState
, HIMC hIMC
)
674 /* See the comment at the head of this file */
675 TRACE("We do no processing via this route\n");
679 BOOL WINAPI
NotifyIME(HIMC hIMC
, DWORD dwAction
, DWORD dwIndex
, DWORD dwValue
)
682 LPINPUTCONTEXT lpIMC
;
684 TRACE("%p %i %i %i\n",hIMC
,dwAction
,dwIndex
,dwValue
);
686 lpIMC
= LockRealIMC(hIMC
);
692 case NI_OPENCANDIDATE
: FIXME("NI_OPENCANDIDATE\n"); break;
693 case NI_CLOSECANDIDATE
: FIXME("NI_CLOSECANDIDATE\n"); break;
694 case NI_SELECTCANDIDATESTR
: FIXME("NI_SELECTCANDIDATESTR\n"); break;
695 case NI_CHANGECANDIDATELIST
: FIXME("NI_CHANGECANDIDATELIST\n"); break;
696 case NI_SETCANDIDATE_PAGESTART
: FIXME("NI_SETCANDIDATE_PAGESTART\n"); break;
697 case NI_SETCANDIDATE_PAGESIZE
: FIXME("NI_SETCANDIDATE_PAGESIZE\n"); break;
698 case NI_CONTEXTUPDATED
:
701 case IMC_SETCOMPOSITIONWINDOW
: FIXME("IMC_SETCOMPOSITIONWINDOW\n"); break;
702 case IMC_SETCONVERSIONMODE
: FIXME("IMC_SETCONVERSIONMODE\n"); break;
703 case IMC_SETSENTENCEMODE
: FIXME("IMC_SETSENTENCEMODE\n"); break;
704 case IMC_SETCANDIDATEPOS
: FIXME("IMC_SETCANDIDATEPOS\n"); break;
705 case IMC_SETCOMPOSITIONFONT
:
707 LPIMEPRIVATE myPrivate
;
708 TRACE("IMC_SETCOMPOSITIONFONT\n");
710 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
711 if (myPrivate
->textfont
)
713 DeleteObject(myPrivate
->textfont
);
714 myPrivate
->textfont
= NULL
;
716 myPrivate
->textfont
= CreateFontIndirectW(&lpIMC
->lfFont
.W
);
717 ImmUnlockIMCC(lpIMC
->hPrivate
);
720 case IMC_SETOPENSTATUS
:
722 LPIMEPRIVATE myPrivate
;
723 TRACE("IMC_SETOPENSTATUS\n");
725 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
726 if (lpIMC
->fOpen
!= myPrivate
->bInternalState
&&
727 myPrivate
->bInComposition
)
729 if(lpIMC
->fOpen
== FALSE
)
731 X11DRV_ForceXIMReset(lpIMC
->hWnd
);
732 GenerateIMEMessage(hIMC
,WM_IME_ENDCOMPOSITION
,0,0);
733 myPrivate
->bInComposition
= FALSE
;
737 GenerateIMEMessage(hIMC
,WM_IME_STARTCOMPOSITION
,0,0);
738 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, 0, 0);
741 myPrivate
->bInternalState
= lpIMC
->fOpen
;
745 default: FIXME("Unknown\n"); break;
748 case NI_COMPOSITIONSTR
:
756 LPCOMPOSITIONSTRING cs
= NULL
;
758 LPIMEPRIVATE myPrivate
;
760 TRACE("CPS_COMPLETE\n");
762 /* clear existing result */
763 newCompStr
= updateResultStr(lpIMC
->hCompStr
, NULL
, 0);
765 ImmDestroyIMCC(lpIMC
->hCompStr
);
766 lpIMC
->hCompStr
= newCompStr
;
770 cdata
= ImmLockIMCC(lpIMC
->hCompStr
);
771 cs
= (LPCOMPOSITIONSTRING
)cdata
;
772 cplen
= cs
->dwCompStrLen
;
773 cpstr
= (LPWSTR
)&(cdata
[cs
->dwCompStrOffset
]);
774 ImmUnlockIMCC(lpIMC
->hCompStr
);
778 WCHAR param
= cpstr
[0];
780 newCompStr
= updateResultStr(lpIMC
->hCompStr
, cpstr
, cplen
);
781 ImmDestroyIMCC(lpIMC
->hCompStr
);
782 lpIMC
->hCompStr
= newCompStr
;
783 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
784 ImmDestroyIMCC(lpIMC
->hCompStr
);
785 lpIMC
->hCompStr
= newCompStr
;
787 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, 0,
790 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, param
,
791 GCS_RESULTSTR
|GCS_RESULTCLAUSE
);
794 GenerateIMEMessage(hIMC
,WM_IME_ENDCOMPOSITION
, 0, 0);
796 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
797 myPrivate
->bInComposition
= FALSE
;
798 ImmUnlockIMCC(lpIMC
->hPrivate
);
803 case CPS_CONVERT
: FIXME("CPS_CONVERT\n"); break;
804 case CPS_REVERT
: FIXME("CPS_REVERT\n"); break;
807 LPIMEPRIVATE myPrivate
;
809 TRACE("CPS_CANCEL\n");
811 X11DRV_ForceXIMReset(lpIMC
->hWnd
);
814 ImmDestroyIMCC(lpIMC
->hCompStr
);
815 lpIMC
->hCompStr
= ImeCreateBlankCompStr();
817 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
818 if (myPrivate
->bInComposition
)
820 GenerateIMEMessage(hIMC
, WM_IME_ENDCOMPOSITION
, 0, 0);
821 myPrivate
->bInComposition
= FALSE
;
823 ImmUnlockIMCC(lpIMC
->hPrivate
);
827 default: FIXME("Unknown\n"); break;
830 default: FIXME("Unknown Message\n"); break;
837 BOOL WINAPI
ImeRegisterWord(LPCWSTR lpszReading
, DWORD dwStyle
,
838 LPCWSTR lpszRegister
)
840 FIXME("(%s, %d, %s): stub\n", debugstr_w(lpszReading
), dwStyle
,
841 debugstr_w(lpszRegister
));
842 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
846 BOOL WINAPI
ImeUnregisterWord(LPCWSTR lpszReading
, DWORD dwStyle
,
847 LPCWSTR lpszUnregister
)
849 FIXME("(%s, %d, %s): stub\n", debugstr_w(lpszReading
), dwStyle
,
850 debugstr_w(lpszUnregister
));
851 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
855 UINT WINAPI
ImeGetRegisterWordStyle(UINT nItem
, LPSTYLEBUFW lpStyleBuf
)
857 FIXME("(%d, %p): stub\n", nItem
, lpStyleBuf
);
858 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
862 UINT WINAPI
ImeEnumRegisterWord(REGISTERWORDENUMPROCW lpfnEnumProc
,
863 LPCWSTR lpszReading
, DWORD dwStyle
,
864 LPCWSTR lpszRegister
, LPVOID lpData
)
866 FIXME("(%p, %s, %d, %s, %p): stub\n", lpfnEnumProc
,
867 debugstr_w(lpszReading
), dwStyle
, debugstr_w(lpszRegister
),
869 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
873 BOOL WINAPI
ImeSetCompositionString(HIMC hIMC
, DWORD dwIndex
, LPCVOID lpComp
,
874 DWORD dwCompLen
, LPCVOID lpRead
,
877 LPINPUTCONTEXT lpIMC
;
880 LPIMEPRIVATE myPrivate
;
882 TRACE("(%p, %d, %p, %d, %p, %d):\n",
883 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
886 if (hIMC
!= FROM_X11
)
887 FIXME("PROBLEM: This only sets the wine level string\n");
891 * this sets the composition string in the imm32.dll level
892 * of the composition buffer. we cannot manipulate the xim level
893 * buffer, which means that once the xim level buffer changes again
894 * any call to this function from the application will be lost
897 if (lpRead
&& dwReadLen
)
898 FIXME("Reading string unimplemented\n");
900 lpIMC
= LockRealIMC(hIMC
);
905 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
907 if (dwIndex
== SCS_SETSTR
)
911 if (!myPrivate
->bInComposition
)
913 GenerateIMEMessage(hIMC
, WM_IME_STARTCOMPOSITION
, 0, 0);
914 myPrivate
->bInComposition
= TRUE
;
919 if (dwCompLen
&& lpComp
)
921 newCompStr
= updateCompStr(lpIMC
->hCompStr
, (LPWSTR
)lpComp
, dwCompLen
/ sizeof(WCHAR
));
922 ImmDestroyIMCC(lpIMC
->hCompStr
);
923 lpIMC
->hCompStr
= newCompStr
;
925 wParam
= ((const WCHAR
*)lpComp
)[0];
926 flags
|= GCS_COMPCLAUSE
| GCS_COMPATTR
| GCS_DELTASTART
;
930 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
931 ImmDestroyIMCC(lpIMC
->hCompStr
);
932 lpIMC
->hCompStr
= newCompStr
;
936 UpdateDataInDefaultIMEWindow(hIMC
, myPrivate
->hwndDefault
,FALSE
);
938 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, wParam
, flags
);
939 ImmUnlockIMCC(lpIMC
->hPrivate
);
945 DWORD WINAPI
ImeGetImeMenuItems(HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
946 LPIMEMENUITEMINFOW lpImeParentMenu
, LPIMEMENUITEMINFOW lpImeMenu
,
949 FIXME("(%p, %x %x %p %p %x): stub\n", hIMC
, dwFlags
, dwType
,
950 lpImeParentMenu
, lpImeMenu
, dwSize
);
951 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
955 /* Interfaces to XIM and other parts of winex11drv */
957 void IME_SetOpenStatus(BOOL fOpen
)
959 LPINPUTCONTEXT lpIMC
;
960 LPIMEPRIVATE myPrivate
;
962 lpIMC
= LockRealIMC(FROM_X11
);
966 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
968 if (myPrivate
->bInternalState
&& fOpen
== FALSE
)
970 ShowWindow(myPrivate
->hwndDefault
, SW_HIDE
);
971 ImmDestroyIMCC(lpIMC
->hCompStr
);
972 lpIMC
->hCompStr
= ImeCreateBlankCompStr();
975 ImmUnlockIMCC(lpIMC
->hPrivate
);
976 UnlockRealIMC(FROM_X11
);
978 if (myPrivate
->bInComposition
&& fOpen
== FALSE
)
980 GenerateIMEMessage(FROM_X11
, WM_IME_ENDCOMPOSITION
, 0, 0);
981 myPrivate
->bInComposition
= FALSE
;
984 if (!myPrivate
->bInternalState
&& fOpen
== TRUE
)
985 ImmSetOpenStatus(RealIMC(FROM_X11
), fOpen
);
988 INT
IME_GetCursorPos(void)
990 LPINPUTCONTEXT lpIMC
;
992 LPCOMPOSITIONSTRING compstr
;
997 lpIMC
= LockRealIMC(FROM_X11
);
1000 compstr
= ImmLockIMCC(lpIMC
->hCompStr
);
1001 rc
= compstr
->dwCursorPos
;
1002 ImmUnlockIMCC(lpIMC
->hCompStr
);
1004 UnlockRealIMC(FROM_X11
);
1008 void IME_SetCursorPos(DWORD pos
)
1010 LPINPUTCONTEXT lpIMC
;
1011 LPCOMPOSITIONSTRING compstr
;
1016 lpIMC
= LockRealIMC(FROM_X11
);
1020 compstr
= ImmLockIMCC(lpIMC
->hCompStr
);
1023 UnlockRealIMC(FROM_X11
);
1027 compstr
->dwCursorPos
= pos
;
1028 ImmUnlockIMCC(lpIMC
->hCompStr
);
1029 UnlockRealIMC(FROM_X11
);
1030 GenerateIMEMessage(FROM_X11
, WM_IME_COMPOSITION
, pos
, GCS_CURSORPOS
);
1034 void IME_UpdateAssociation(HWND focus
)
1036 ImmGetContext(focus
);
1038 if (!focus
|| !hSelectedFrom
)
1041 ImmAssociateContext(focus
,RealIMC(FROM_X11
));
1045 BOOL
IME_SetCompositionString(DWORD dwIndex
, LPCVOID lpComp
, DWORD dwCompLen
,
1046 LPCVOID lpRead
, DWORD dwReadLen
)
1048 return ImeSetCompositionString(FROM_X11
, dwIndex
, lpComp
, dwCompLen
,
1052 BOOL
IME_NotifyIME(DWORD dwAction
, DWORD dwIndex
, DWORD dwValue
)
1054 return NotifyIME(FROM_X11
, dwAction
, dwIndex
, dwValue
);
1058 * Internal functions to help with IME window management
1060 static void PaintDefaultIMEWnd(HIMC hIMC
, HWND hwnd
)
1065 LPCOMPOSITIONSTRING compstr
;
1066 LPBYTE compdata
= NULL
;
1068 MONITORINFO mon_info
;
1070 LPINPUTCONTEXT lpIMC
;
1072 lpIMC
= LockRealIMC(hIMC
);
1076 hdc
= BeginPaint(hwnd
,&ps
);
1078 GetClientRect(hwnd
,&rect
);
1079 FillRect(hdc
, &rect
, (HBRUSH
)(COLOR_WINDOW
+ 1));
1081 compdata
= ImmLockIMCC(lpIMC
->hCompStr
);
1082 compstr
= (LPCOMPOSITIONSTRING
)compdata
;
1084 if (compstr
->dwCompStrLen
&& compstr
->dwCompStrOffset
)
1088 HFONT oldfont
= NULL
;
1090 LPIMEPRIVATE myPrivate
;
1092 CompString
= (LPWSTR
)(compdata
+ compstr
->dwCompStrOffset
);
1093 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
1095 if (myPrivate
->textfont
)
1096 oldfont
= SelectObject(hdc
,myPrivate
->textfont
);
1098 ImmUnlockIMCC(lpIMC
->hPrivate
);
1100 GetTextExtentPoint32W(hdc
, CompString
, compstr
->dwCompStrLen
, &size
);
1106 * How this works based on tests on windows:
1107 * CFS_POINT: then we start our window at the point and grow it as large
1108 * as it needs to be for the string.
1109 * CFS_RECT: we still use the ptCurrentPos as a starting point and our
1110 * window is only as large as we need for the string, but we do not
1111 * grow such that our window exceeds the given rect. Wrapping if
1112 * needed and possible. If our ptCurrentPos is outside of our rect
1113 * then no window is displayed.
1114 * CFS_FORCE_POSITION: appears to behave just like CFS_POINT
1115 * maybe becase the default MSIME does not do any IME adjusting.
1117 if (lpIMC
->cfCompForm
.dwStyle
!= CFS_DEFAULT
)
1119 POINT cpt
= lpIMC
->cfCompForm
.ptCurrentPos
;
1120 ClientToScreen(lpIMC
->hWnd
,&cpt
);
1123 rect
.right
= rect
.left
+ pt
.x
;
1124 rect
.bottom
= rect
.top
+ pt
.y
;
1125 monitor
= MonitorFromPoint(cpt
, MONITOR_DEFAULTTOPRIMARY
);
1127 else /* CFS_DEFAULT */
1129 /* Windows places the default IME window in the bottom left */
1130 HWND target
= lpIMC
->hWnd
;
1131 if (!target
) target
= GetFocus();
1133 GetWindowRect(target
,&rect
);
1134 rect
.top
= rect
.bottom
;
1135 rect
.right
= rect
.left
+ pt
.x
+ 20;
1136 rect
.bottom
= rect
.top
+ pt
.y
+ 20;
1138 monitor
= MonitorFromWindow(target
, MONITOR_DEFAULTTOPRIMARY
);
1141 if (lpIMC
->cfCompForm
.dwStyle
== CFS_RECT
)
1144 client
=lpIMC
->cfCompForm
.rcArea
;
1145 MapWindowPoints( lpIMC
->hWnd
, 0, (POINT
*)&client
, 2 );
1146 IntersectRect(&rect
,&rect
,&client
);
1147 /* TODO: Wrap the input if needed */
1150 if (lpIMC
->cfCompForm
.dwStyle
== CFS_DEFAULT
)
1152 /* make sure we are on the desktop */
1153 mon_info
.cbSize
= sizeof(mon_info
);
1154 GetMonitorInfoW(monitor
, &mon_info
);
1156 if (rect
.bottom
> mon_info
.rcWork
.bottom
)
1158 int shift
= rect
.bottom
- mon_info
.rcWork
.bottom
;
1160 rect
.bottom
-= shift
;
1164 rect
.right
-= rect
.left
;
1167 if (rect
.right
> mon_info
.rcWork
.right
)
1169 int shift
= rect
.right
- mon_info
.rcWork
.right
;
1171 rect
.right
-= shift
;
1175 SetWindowPos(hwnd
, HWND_TOPMOST
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, SWP_NOACTIVATE
);
1177 TextOutW(hdc
, offX
,offY
, CompString
, compstr
->dwCompStrLen
);
1180 SelectObject(hdc
,oldfont
);
1183 ImmUnlockIMCC(lpIMC
->hCompStr
);
1186 UnlockRealIMC(hIMC
);
1189 static void UpdateDataInDefaultIMEWindow(HIMC hIMC
, HWND hwnd
, BOOL showable
)
1191 LPCOMPOSITIONSTRING compstr
;
1192 LPINPUTCONTEXT lpIMC
;
1194 lpIMC
= LockRealIMC(hIMC
);
1198 if (lpIMC
->hCompStr
)
1199 compstr
= ImmLockIMCC(lpIMC
->hCompStr
);
1203 if (compstr
== NULL
|| compstr
->dwCompStrLen
== 0)
1204 ShowWindow(hwnd
,SW_HIDE
);
1206 ShowWindow(hwnd
,SW_SHOWNOACTIVATE
);
1208 RedrawWindow(hwnd
,NULL
,NULL
,RDW_ERASENOW
|RDW_INVALIDATE
);
1210 if (compstr
!= NULL
)
1211 ImmUnlockIMCC(lpIMC
->hCompStr
);
1213 UnlockRealIMC(hIMC
);
1216 static void DefaultIMEComposition(HIMC hIMC
, HWND hwnd
, LPARAM lParam
)
1218 TRACE("IME message WM_IME_COMPOSITION 0x%lx\n", lParam
);
1219 if (lParam
& GCS_RESULTSTR
)
1221 LPCOMPOSITIONSTRING compstr
;
1225 LPINPUTCONTEXT lpIMC
;
1227 lpIMC
= LockRealIMC(hIMC
);
1231 TRACE("Posting result as IME_CHAR\n");
1232 compdata
= ImmLockIMCC(lpIMC
->hCompStr
);
1233 compstr
= (LPCOMPOSITIONSTRING
)compdata
;
1234 ResultStr
= (LPWSTR
)(compdata
+ compstr
->dwResultStrOffset
);
1235 GenerateIMECHARMessages(hIMC
, ResultStr
, compstr
->dwResultStrLen
);
1236 ImmUnlockIMCC(lpIMC
->hCompStr
);
1238 /* clear the buffer */
1239 newCompStr
= updateResultStr(lpIMC
->hCompStr
, NULL
, 0);
1240 ImmDestroyIMCC(lpIMC
->hCompStr
);
1241 lpIMC
->hCompStr
= newCompStr
;
1242 UnlockRealIMC(hIMC
);
1245 UpdateDataInDefaultIMEWindow(hIMC
,hwnd
,TRUE
);
1248 static void DefaultIMEStartComposition(HIMC hIMC
, HWND hwnd
)
1250 LPINPUTCONTEXT lpIMC
;
1252 lpIMC
= LockRealIMC(hIMC
);
1256 TRACE("IME message WM_IME_STARTCOMPOSITION\n");
1257 lpIMC
->hWnd
= GetFocus();
1258 ShowWindow(hwnd
,SW_SHOWNOACTIVATE
);
1259 UnlockRealIMC(hIMC
);
1262 static LRESULT
ImeHandleNotify(HIMC hIMC
, HWND hwnd
, UINT msg
, WPARAM wParam
,
1267 case IMN_OPENSTATUSWINDOW
:
1268 FIXME("WM_IME_NOTIFY:IMN_OPENSTATUSWINDOW\n");
1270 case IMN_CLOSESTATUSWINDOW
:
1271 FIXME("WM_IME_NOTIFY:IMN_CLOSESTATUSWINDOW\n");
1273 case IMN_OPENCANDIDATE
:
1274 FIXME("WM_IME_NOTIFY:IMN_OPENCANDIDATE\n");
1276 case IMN_CHANGECANDIDATE
:
1277 FIXME("WM_IME_NOTIFY:IMN_CHANGECANDIDATE\n");
1279 case IMN_CLOSECANDIDATE
:
1280 FIXME("WM_IME_NOTIFY:IMN_CLOSECANDIDATE\n");
1282 case IMN_SETCONVERSIONMODE
:
1283 FIXME("WM_IME_NOTIFY:IMN_SETCONVERSIONMODE\n");
1285 case IMN_SETSENTENCEMODE
:
1286 FIXME("WM_IME_NOTIFY:IMN_SETSENTENCEMODE\n");
1288 case IMN_SETOPENSTATUS
:
1289 FIXME("WM_IME_NOTIFY:IMN_SETOPENSTATUS\n");
1291 case IMN_SETCANDIDATEPOS
:
1292 FIXME("WM_IME_NOTIFY:IMN_SETCANDIDATEPOS\n");
1294 case IMN_SETCOMPOSITIONFONT
:
1295 FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONFONT\n");
1297 case IMN_SETCOMPOSITIONWINDOW
:
1298 FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONWINDOW\n");
1301 FIXME("WM_IME_NOTIFY:IMN_GUIDELINE\n");
1303 case IMN_SETSTATUSWINDOWPOS
:
1304 FIXME("WM_IME_NOTIFY:IMN_SETSTATUSWINDOWPOS\n");
1307 FIXME("WM_IME_NOTIFY:<Unknown 0x%lx>\n",wParam
);
1313 static LRESULT WINAPI
IME_WindowProc(HWND hwnd
, UINT msg
, WPARAM wParam
,
1319 TRACE("Incoming Message 0x%x (0x%08lx, 0x%08lx)\n", msg
, wParam
, lParam
);
1322 * Each UI window contains the current Input Context.
1323 * This Input Context can be obtained by calling GetWindowLong
1324 * with IMMGWL_IMC when the UI window receives a WM_IME_xxx message.
1325 * The UI window can refer to this Input Context and handles the
1329 hIMC
= (HIMC
)GetWindowLongPtrW(hwnd
,IMMGWL_IMC
);
1331 hIMC
= RealIMC(FROM_X11
);
1333 /* if we have no hIMC there are many messages we cannot process */
1337 case WM_IME_STARTCOMPOSITION
:
1338 case WM_IME_ENDCOMPOSITION
:
1339 case WM_IME_COMPOSITION
:
1341 case WM_IME_CONTROL
:
1342 case WM_IME_COMPOSITIONFULL
:
1355 LPIMEPRIVATE myPrivate
;
1356 LPINPUTCONTEXT lpIMC
;
1358 SetWindowTextA(hwnd
,"Wine Ime Active");
1360 lpIMC
= LockRealIMC(hIMC
);
1363 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
1364 myPrivate
->hwndDefault
= hwnd
;
1365 ImmUnlockIMCC(lpIMC
->hPrivate
);
1367 UnlockRealIMC(hIMC
);
1372 PaintDefaultIMEWnd(hIMC
, hwnd
);
1380 SetFocus((HWND
)wParam
);
1382 FIXME("Received focus, should never have focus\n");
1384 case WM_IME_COMPOSITION
:
1385 DefaultIMEComposition(hIMC
, hwnd
, lParam
);
1387 case WM_IME_STARTCOMPOSITION
:
1388 DefaultIMEStartComposition(hIMC
, hwnd
);
1390 case WM_IME_ENDCOMPOSITION
:
1391 TRACE("IME message %s, 0x%lx, 0x%lx\n",
1392 "WM_IME_ENDCOMPOSITION", wParam
, lParam
);
1393 ShowWindow(hwnd
,SW_HIDE
);
1396 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_IME_SELECT", wParam
, lParam
);
1398 case WM_IME_CONTROL
:
1399 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_IME_CONTROL", wParam
, lParam
);
1403 rc
= ImeHandleNotify(hIMC
,hwnd
,msg
,wParam
,lParam
);
1406 TRACE("Non-standard message 0x%x\n",msg
);
1408 /* check the MSIME messages */
1409 if (msg
== WM_MSIME_SERVICE
)
1411 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_SERVICE", wParam
, lParam
);
1414 else if (msg
== WM_MSIME_RECONVERTOPTIONS
)
1416 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_RECONVERTOPTIONS", wParam
, lParam
);
1418 else if (msg
== WM_MSIME_MOUSE
)
1420 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_MOUSE", wParam
, lParam
);
1422 else if (msg
== WM_MSIME_RECONVERTREQUEST
)
1424 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_RECONVERTREQUEST", wParam
, lParam
);
1426 else if (msg
== WM_MSIME_RECONVERT
)
1428 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_RECONVERT", wParam
, lParam
);
1430 else if (msg
== WM_MSIME_QUERYPOSITION
)
1432 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_QUERYPOSITION", wParam
, lParam
);
1434 else if (msg
== WM_MSIME_DOCUMENTFEED
)
1436 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_DOCUMENTFEED", wParam
, lParam
);
1438 /* DefWndProc if not an IME message */
1439 if (!rc
&& !((msg
>= WM_IME_STARTCOMPOSITION
&& msg
<= WM_IME_KEYLAST
) ||
1440 (msg
>= WM_IME_SETCONTEXT
&& msg
<= WM_IME_KEYUP
)))
1441 rc
= DefWindowProcW(hwnd
,msg
,wParam
,lParam
);