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.
43 #include "x11drv_dll.h"
44 #include "wine/debug.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(imm
);
50 #define FROM_X11 ((HIMC)0xcafe1337)
52 typedef struct _IMEPRIVATE
{
57 } IMEPRIVATE
, *LPIMEPRIVATE
;
59 typedef struct _tagTRANSMSG
{
63 } TRANSMSG
, *LPTRANSMSG
;
65 static const WCHAR UI_CLASS_NAME
[] = {'W','i','n','e','X','1','1','I','M','E',0};
67 static HIMC
*hSelectedFrom
= NULL
;
68 static INT hSelectedCount
= 0;
71 static UINT WM_MSIME_SERVICE
;
72 static UINT WM_MSIME_RECONVERTOPTIONS
;
73 static UINT WM_MSIME_MOUSE
;
74 static UINT WM_MSIME_RECONVERTREQUEST
;
75 static UINT WM_MSIME_RECONVERT
;
76 static UINT WM_MSIME_QUERYPOSITION
;
77 static UINT WM_MSIME_DOCUMENTFEED
;
79 static LRESULT WINAPI
IME_WindowProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
,
82 static HIMC
RealIMC(HIMC hIMC
)
87 HWND wnd
= GetFocus();
88 HIMC winHimc
= ImmGetContext(wnd
);
89 for (i
= 0; i
< hSelectedCount
; i
++)
90 if (winHimc
== hSelectedFrom
[i
])
98 static LPINPUTCONTEXT
LockRealIMC(HIMC hIMC
)
100 HIMC real_imc
= RealIMC(hIMC
);
102 return ImmLockIMC(real_imc
);
107 static BOOL
UnlockRealIMC(HIMC hIMC
)
109 HIMC real_imc
= RealIMC(hIMC
);
111 return ImmUnlockIMC(real_imc
);
116 static BOOL WINAPI
register_classes( INIT_ONCE
*once
, void *param
, void **context
)
120 ZeroMemory(&wndClass
, sizeof(WNDCLASSW
));
121 wndClass
.style
= CS_GLOBALCLASS
| CS_IME
| CS_HREDRAW
| CS_VREDRAW
;
122 wndClass
.lpfnWndProc
= IME_WindowProc
;
123 wndClass
.cbClsExtra
= 0;
124 wndClass
.cbWndExtra
= 2 * sizeof(LONG_PTR
);
125 wndClass
.hInstance
= x11drv_module
;
126 wndClass
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
127 wndClass
.hIcon
= LoadIconW(NULL
, (LPWSTR
)IDI_APPLICATION
);
128 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
129 wndClass
.lpszMenuName
= 0;
130 wndClass
.lpszClassName
= UI_CLASS_NAME
;
132 RegisterClassW(&wndClass
);
134 WM_MSIME_SERVICE
= RegisterWindowMessageA("MSIMEService");
135 WM_MSIME_RECONVERTOPTIONS
= RegisterWindowMessageA("MSIMEReconvertOptions");
136 WM_MSIME_MOUSE
= RegisterWindowMessageA("MSIMEMouseOperation");
137 WM_MSIME_RECONVERTREQUEST
= RegisterWindowMessageA("MSIMEReconvertRequest");
138 WM_MSIME_RECONVERT
= RegisterWindowMessageA("MSIMEReconvert");
139 WM_MSIME_QUERYPOSITION
= RegisterWindowMessageA("MSIMEQueryPosition");
140 WM_MSIME_DOCUMENTFEED
= RegisterWindowMessageA("MSIMEDocumentFeed");
144 static HIMCC
ImeCreateBlankCompStr(void)
147 LPCOMPOSITIONSTRING ptr
;
148 rc
= ImmCreateIMCC(sizeof(COMPOSITIONSTRING
));
149 ptr
= ImmLockIMCC(rc
);
150 memset(ptr
,0,sizeof(COMPOSITIONSTRING
));
151 ptr
->dwSize
= sizeof(COMPOSITIONSTRING
);
156 static int updateField(DWORD origLen
, DWORD origOffset
, DWORD currentOffset
,
157 LPBYTE target
, LPBYTE source
, DWORD
* lenParam
,
158 DWORD
* offsetParam
, BOOL wchars
)
160 if (origLen
> 0 && origOffset
> 0)
162 int truelen
= origLen
;
164 truelen
*= sizeof(WCHAR
);
166 memcpy(&target
[currentOffset
], &source
[origOffset
], truelen
);
169 *offsetParam
= currentOffset
;
170 currentOffset
+= truelen
;
172 return currentOffset
;
175 static HIMCC
updateCompStr(HIMCC old
, LPCWSTR compstr
, DWORD len
)
177 /* We need to make sure the CompStr, CompClause and CompAttr fields are all
178 * set and correct. */
181 LPBYTE newdata
= NULL
;
182 LPBYTE olddata
= NULL
;
183 LPCOMPOSITIONSTRING new_one
;
184 LPCOMPOSITIONSTRING lpcs
= NULL
;
185 INT current_offset
= 0;
187 TRACE("%s, %li\n",debugstr_wn(compstr
,len
),len
);
189 if (old
== NULL
&& compstr
== NULL
&& len
== 0)
192 if (compstr
== NULL
&& len
!= 0)
194 ERR("compstr is NULL however we have a len! Please report\n");
200 olddata
= ImmLockIMCC(old
);
201 lpcs
= (LPCOMPOSITIONSTRING
)olddata
;
204 needed_size
= sizeof(COMPOSITIONSTRING
) + len
* sizeof(WCHAR
) +
205 len
+ sizeof(DWORD
) * 2;
209 needed_size
+= lpcs
->dwCompReadAttrLen
;
210 needed_size
+= lpcs
->dwCompReadClauseLen
;
211 needed_size
+= lpcs
->dwCompReadStrLen
* sizeof(WCHAR
);
212 needed_size
+= lpcs
->dwResultReadClauseLen
;
213 needed_size
+= lpcs
->dwResultReadStrLen
* sizeof(WCHAR
);
214 needed_size
+= lpcs
->dwResultClauseLen
;
215 needed_size
+= lpcs
->dwResultStrLen
* sizeof(WCHAR
);
216 needed_size
+= lpcs
->dwPrivateSize
;
218 rc
= ImmCreateIMCC(needed_size
);
219 newdata
= ImmLockIMCC(rc
);
220 new_one
= (LPCOMPOSITIONSTRING
)newdata
;
222 new_one
->dwSize
= needed_size
;
223 current_offset
= sizeof(COMPOSITIONSTRING
);
226 current_offset
= updateField(lpcs
->dwCompReadAttrLen
,
227 lpcs
->dwCompReadAttrOffset
,
228 current_offset
, newdata
, olddata
,
229 &new_one
->dwCompReadAttrLen
,
230 &new_one
->dwCompReadAttrOffset
, FALSE
);
232 current_offset
= updateField(lpcs
->dwCompReadClauseLen
,
233 lpcs
->dwCompReadClauseOffset
,
234 current_offset
, newdata
, olddata
,
235 &new_one
->dwCompReadClauseLen
,
236 &new_one
->dwCompReadClauseOffset
, FALSE
);
238 current_offset
= updateField(lpcs
->dwCompReadStrLen
,
239 lpcs
->dwCompReadStrOffset
,
240 current_offset
, newdata
, olddata
,
241 &new_one
->dwCompReadStrLen
,
242 &new_one
->dwCompReadStrOffset
, TRUE
);
244 /* new CompAttr, CompClause, CompStr, dwCursorPos */
245 new_one
->dwDeltaStart
= 0;
247 current_offset
= updateField(lpcs
->dwResultReadClauseLen
,
248 lpcs
->dwResultReadClauseOffset
,
249 current_offset
, newdata
, olddata
,
250 &new_one
->dwResultReadClauseLen
,
251 &new_one
->dwResultReadClauseOffset
, FALSE
);
253 current_offset
= updateField(lpcs
->dwResultReadStrLen
,
254 lpcs
->dwResultReadStrOffset
,
255 current_offset
, newdata
, olddata
,
256 &new_one
->dwResultReadStrLen
,
257 &new_one
->dwResultReadStrOffset
, TRUE
);
259 current_offset
= updateField(lpcs
->dwResultClauseLen
,
260 lpcs
->dwResultClauseOffset
,
261 current_offset
, newdata
, olddata
,
262 &new_one
->dwResultClauseLen
,
263 &new_one
->dwResultClauseOffset
, FALSE
);
265 current_offset
= updateField(lpcs
->dwResultStrLen
,
266 lpcs
->dwResultStrOffset
,
267 current_offset
, newdata
, olddata
,
268 &new_one
->dwResultStrLen
,
269 &new_one
->dwResultStrOffset
, TRUE
);
271 current_offset
= updateField(lpcs
->dwPrivateSize
,
272 lpcs
->dwPrivateOffset
,
273 current_offset
, newdata
, olddata
,
274 &new_one
->dwPrivateSize
,
275 &new_one
->dwPrivateOffset
, FALSE
);
280 new_one
->dwCompAttrLen
= len
;
283 new_one
->dwCompAttrOffset
= current_offset
;
284 memset(&newdata
[current_offset
],ATTR_INPUT
,len
);
285 current_offset
+= len
;
291 new_one
->dwCompClauseLen
= sizeof(DWORD
) * 2;
292 new_one
->dwCompClauseOffset
= current_offset
;
293 *(DWORD
*)(&newdata
[current_offset
]) = 0;
294 current_offset
+= sizeof(DWORD
);
295 *(DWORD
*)(&newdata
[current_offset
]) = len
;
296 current_offset
+= sizeof(DWORD
);
299 new_one
->dwCompClauseLen
= 0;
302 new_one
->dwCompStrLen
= len
;
305 new_one
->dwCompStrOffset
= current_offset
;
306 memcpy(&newdata
[current_offset
],compstr
,len
*sizeof(WCHAR
));
310 new_one
->dwCursorPos
= len
;
319 static HIMCC
updateResultStr(HIMCC old
, LPWSTR resultstr
, DWORD len
)
321 /* we need to make sure the ResultStr and ResultClause fields are all
325 LPBYTE newdata
= NULL
;
326 LPBYTE olddata
= NULL
;
327 LPCOMPOSITIONSTRING new_one
;
328 LPCOMPOSITIONSTRING lpcs
= NULL
;
329 INT current_offset
= 0;
331 TRACE("%s, %li\n",debugstr_wn(resultstr
,len
),len
);
333 if (old
== NULL
&& resultstr
== NULL
&& len
== 0)
336 if (resultstr
== NULL
&& len
!= 0)
338 ERR("resultstr is NULL however we have a len! Please report\n");
344 olddata
= ImmLockIMCC(old
);
345 lpcs
= (LPCOMPOSITIONSTRING
)olddata
;
348 needed_size
= sizeof(COMPOSITIONSTRING
) + len
* sizeof(WCHAR
) +
353 needed_size
+= lpcs
->dwCompReadAttrLen
;
354 needed_size
+= lpcs
->dwCompReadClauseLen
;
355 needed_size
+= lpcs
->dwCompReadStrLen
* sizeof(WCHAR
);
356 needed_size
+= lpcs
->dwCompAttrLen
;
357 needed_size
+= lpcs
->dwCompClauseLen
;
358 needed_size
+= lpcs
->dwCompStrLen
* sizeof(WCHAR
);
359 needed_size
+= lpcs
->dwResultReadClauseLen
;
360 needed_size
+= lpcs
->dwResultReadStrLen
* sizeof(WCHAR
);
361 needed_size
+= lpcs
->dwPrivateSize
;
363 rc
= ImmCreateIMCC(needed_size
);
364 newdata
= ImmLockIMCC(rc
);
365 new_one
= (LPCOMPOSITIONSTRING
)newdata
;
367 new_one
->dwSize
= needed_size
;
368 current_offset
= sizeof(COMPOSITIONSTRING
);
371 current_offset
= updateField(lpcs
->dwCompReadAttrLen
,
372 lpcs
->dwCompReadAttrOffset
,
373 current_offset
, newdata
, olddata
,
374 &new_one
->dwCompReadAttrLen
,
375 &new_one
->dwCompReadAttrOffset
, FALSE
);
377 current_offset
= updateField(lpcs
->dwCompReadClauseLen
,
378 lpcs
->dwCompReadClauseOffset
,
379 current_offset
, newdata
, olddata
,
380 &new_one
->dwCompReadClauseLen
,
381 &new_one
->dwCompReadClauseOffset
, FALSE
);
383 current_offset
= updateField(lpcs
->dwCompReadStrLen
,
384 lpcs
->dwCompReadStrOffset
,
385 current_offset
, newdata
, olddata
,
386 &new_one
->dwCompReadStrLen
,
387 &new_one
->dwCompReadStrOffset
, TRUE
);
389 current_offset
= updateField(lpcs
->dwCompAttrLen
,
390 lpcs
->dwCompAttrOffset
,
391 current_offset
, newdata
, olddata
,
392 &new_one
->dwCompAttrLen
,
393 &new_one
->dwCompAttrOffset
, FALSE
);
395 current_offset
= updateField(lpcs
->dwCompClauseLen
,
396 lpcs
->dwCompClauseOffset
,
397 current_offset
, newdata
, olddata
,
398 &new_one
->dwCompClauseLen
,
399 &new_one
->dwCompClauseOffset
, FALSE
);
401 current_offset
= updateField(lpcs
->dwCompStrLen
,
402 lpcs
->dwCompStrOffset
,
403 current_offset
, newdata
, olddata
,
404 &new_one
->dwCompStrLen
,
405 &new_one
->dwCompStrOffset
, TRUE
);
407 new_one
->dwCursorPos
= lpcs
->dwCursorPos
;
408 new_one
->dwDeltaStart
= 0;
410 current_offset
= updateField(lpcs
->dwResultReadClauseLen
,
411 lpcs
->dwResultReadClauseOffset
,
412 current_offset
, newdata
, olddata
,
413 &new_one
->dwResultReadClauseLen
,
414 &new_one
->dwResultReadClauseOffset
, FALSE
);
416 current_offset
= updateField(lpcs
->dwResultReadStrLen
,
417 lpcs
->dwResultReadStrOffset
,
418 current_offset
, newdata
, olddata
,
419 &new_one
->dwResultReadStrLen
,
420 &new_one
->dwResultReadStrOffset
, TRUE
);
422 /* new ResultClause , ResultStr */
424 current_offset
= updateField(lpcs
->dwPrivateSize
,
425 lpcs
->dwPrivateOffset
,
426 current_offset
, newdata
, olddata
,
427 &new_one
->dwPrivateSize
,
428 &new_one
->dwPrivateOffset
, FALSE
);
435 new_one
->dwResultClauseLen
= sizeof(DWORD
) * 2;
436 new_one
->dwResultClauseOffset
= current_offset
;
437 *(DWORD
*)(&newdata
[current_offset
]) = 0;
438 current_offset
+= sizeof(DWORD
);
439 *(DWORD
*)(&newdata
[current_offset
]) = len
;
440 current_offset
+= sizeof(DWORD
);
443 new_one
->dwResultClauseLen
= 0;
446 new_one
->dwResultStrLen
= len
;
449 new_one
->dwResultStrOffset
= current_offset
;
450 memcpy(&newdata
[current_offset
],resultstr
,len
*sizeof(WCHAR
));
459 static void GenerateIMEMessage(HIMC hIMC
, UINT msg
, WPARAM wParam
,
462 LPINPUTCONTEXT lpIMC
;
463 LPTRANSMSG lpTransMsg
;
465 lpIMC
= LockRealIMC(hIMC
);
469 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
, (lpIMC
->dwNumMsgBuf
+ 1) *
474 lpTransMsg
= ImmLockIMCC(lpIMC
->hMsgBuf
);
478 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
479 lpTransMsg
->message
= msg
;
480 lpTransMsg
->wParam
= wParam
;
481 lpTransMsg
->lParam
= lParam
;
483 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
484 lpIMC
->dwNumMsgBuf
++;
486 ImmGenerateMessage(RealIMC(hIMC
));
490 static BOOL
IME_RemoveFromSelected(HIMC hIMC
)
493 for (i
= 0; i
< hSelectedCount
; i
++)
494 if (hSelectedFrom
[i
] == hIMC
)
496 if (i
< hSelectedCount
- 1)
497 memmove(&hSelectedFrom
[i
], &hSelectedFrom
[i
+1], (hSelectedCount
- i
- 1)*sizeof(HIMC
));
504 static void IME_AddToSelected(HIMC hIMC
)
508 hSelectedFrom
= HeapReAlloc(GetProcessHeap(), 0, hSelectedFrom
, hSelectedCount
*sizeof(HIMC
));
510 hSelectedFrom
= HeapAlloc(GetProcessHeap(), 0, sizeof(HIMC
));
511 hSelectedFrom
[hSelectedCount
-1] = hIMC
;
514 BOOL WINAPI
ImeInquire(LPIMEINFO lpIMEInfo
, LPWSTR lpszUIClass
,
517 static INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
520 InitOnceExecuteOnce( &init_once
, register_classes
, NULL
, NULL
);
521 lpIMEInfo
->dwPrivateDataSize
= sizeof (IMEPRIVATE
);
522 lpIMEInfo
->fdwProperty
= IME_PROP_UNICODE
| IME_PROP_AT_CARET
;
523 lpIMEInfo
->fdwConversionCaps
= IME_CMODE_NATIVE
| IME_CMODE_FULLSHAPE
;
524 lpIMEInfo
->fdwSentenceCaps
= IME_SMODE_AUTOMATIC
;
525 lpIMEInfo
->fdwUICaps
= UI_CAP_2700
;
526 /* Tell App we cannot accept ImeSetCompositionString calls */
527 lpIMEInfo
->fdwSCSCaps
= 0;
528 lpIMEInfo
->fdwSelectCaps
= SELECT_CAP_CONVERSION
;
530 lstrcpyW(lpszUIClass
,UI_CLASS_NAME
);
535 BOOL WINAPI
ImeConfigure(HKL hKL
,HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
537 FIXME("(%p, %p, %ld, %p): stub\n", hKL
, hWnd
, dwMode
, lpData
);
538 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
542 DWORD WINAPI
ImeConversionList(HIMC hIMC
, LPCWSTR lpSource
,
543 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
, UINT uFlag
)
546 FIXME("(%p, %s, %p, %ld, %d): stub\n", hIMC
, debugstr_w(lpSource
),
547 lpCandList
, dwBufLen
, uFlag
);
548 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
552 BOOL WINAPI
ImeDestroy(UINT uForce
)
555 HeapFree(GetProcessHeap(),0,hSelectedFrom
);
556 hSelectedFrom
= NULL
;
561 LRESULT WINAPI
ImeEscape(HIMC hIMC
, UINT uSubFunc
, LPVOID lpData
)
563 FIXME("(%p, %d, %p): stub\n", hIMC
, uSubFunc
, lpData
);
564 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
568 BOOL WINAPI
ImeProcessKey(HIMC hIMC
, UINT vKey
, LPARAM lKeyData
, const LPBYTE lpbKeyState
)
570 /* See the comment at the head of this file */
571 TRACE("We do no processing via this route\n");
575 BOOL WINAPI
ImeSelect(HIMC hIMC
, BOOL fSelect
)
577 LPINPUTCONTEXT lpIMC
;
578 TRACE("%p %s\n",hIMC
,(fSelect
)?"TRUE":"FALSE");
580 if (hIMC
== FROM_X11
)
582 ERR("ImeSelect should never be called from X11\n");
591 return IME_RemoveFromSelected(hIMC
);
593 IME_AddToSelected(hIMC
);
595 /* Initialize our structures */
596 lpIMC
= LockRealIMC(hIMC
);
599 LPIMEPRIVATE myPrivate
;
600 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
601 myPrivate
->bInComposition
= FALSE
;
602 myPrivate
->bInternalState
= FALSE
;
603 myPrivate
->textfont
= NULL
;
604 myPrivate
->hwndDefault
= NULL
;
605 ImmUnlockIMCC(lpIMC
->hPrivate
);
612 BOOL WINAPI
ImeSetActiveContext(HIMC hIMC
,BOOL fFlag
)
617 FIXME("(%p, %x): stub\n", hIMC
, fFlag
);
621 UINT WINAPI
ImeToAsciiEx (UINT uVKey
, UINT uScanCode
, const LPBYTE lpbKeyState
,
622 LPDWORD lpdwTransKey
, UINT fuState
, HIMC hIMC
)
624 /* See the comment at the head of this file */
625 TRACE("We do no processing via this route\n");
629 BOOL WINAPI
NotifyIME(HIMC hIMC
, DWORD dwAction
, DWORD dwIndex
, DWORD dwValue
)
631 struct xim_preedit_state_params preedit_params
;
633 LPINPUTCONTEXT lpIMC
;
635 TRACE("%p %li %li %li\n",hIMC
,dwAction
,dwIndex
,dwValue
);
637 lpIMC
= LockRealIMC(hIMC
);
643 case NI_OPENCANDIDATE
: FIXME("NI_OPENCANDIDATE\n"); break;
644 case NI_CLOSECANDIDATE
: FIXME("NI_CLOSECANDIDATE\n"); break;
645 case NI_SELECTCANDIDATESTR
: FIXME("NI_SELECTCANDIDATESTR\n"); break;
646 case NI_CHANGECANDIDATELIST
: FIXME("NI_CHANGECANDIDATELIST\n"); break;
647 case NI_SETCANDIDATE_PAGESTART
: FIXME("NI_SETCANDIDATE_PAGESTART\n"); break;
648 case NI_SETCANDIDATE_PAGESIZE
: FIXME("NI_SETCANDIDATE_PAGESIZE\n"); break;
649 case NI_CONTEXTUPDATED
:
652 case IMC_SETCOMPOSITIONWINDOW
: FIXME("IMC_SETCOMPOSITIONWINDOW\n"); break;
653 case IMC_SETCONVERSIONMODE
: FIXME("IMC_SETCONVERSIONMODE\n"); break;
654 case IMC_SETSENTENCEMODE
: FIXME("IMC_SETSENTENCEMODE\n"); break;
655 case IMC_SETCANDIDATEPOS
: FIXME("IMC_SETCANDIDATEPOS\n"); break;
656 case IMC_SETCOMPOSITIONFONT
:
658 LPIMEPRIVATE myPrivate
;
659 TRACE("IMC_SETCOMPOSITIONFONT\n");
661 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
662 if (myPrivate
->textfont
)
664 DeleteObject(myPrivate
->textfont
);
665 myPrivate
->textfont
= NULL
;
667 myPrivate
->textfont
= CreateFontIndirectW(&lpIMC
->lfFont
.W
);
668 ImmUnlockIMCC(lpIMC
->hPrivate
);
671 case IMC_SETOPENSTATUS
:
672 TRACE("IMC_SETOPENSTATUS\n");
675 preedit_params
.hwnd
= lpIMC
->hWnd
;
676 preedit_params
.open
= lpIMC
->fOpen
;
677 X11DRV_CALL( xim_preedit_state
, &preedit_params
);
680 LPIMEPRIVATE myPrivate
;
682 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
683 if (myPrivate
->bInComposition
)
685 X11DRV_CALL( xim_reset
, lpIMC
->hWnd
);
686 GenerateIMEMessage(hIMC
, WM_IME_ENDCOMPOSITION
, 0, 0);
687 myPrivate
->bInComposition
= FALSE
;
689 ImmUnlockIMCC(lpIMC
->hPrivate
);
693 default: FIXME("Unknown\n"); break;
696 case NI_COMPOSITIONSTR
:
704 LPCOMPOSITIONSTRING cs
= NULL
;
706 LPIMEPRIVATE myPrivate
;
708 TRACE("CPS_COMPLETE\n");
710 /* clear existing result */
711 newCompStr
= updateResultStr(lpIMC
->hCompStr
, NULL
, 0);
713 ImmDestroyIMCC(lpIMC
->hCompStr
);
714 lpIMC
->hCompStr
= newCompStr
;
718 cdata
= ImmLockIMCC(lpIMC
->hCompStr
);
719 cs
= (LPCOMPOSITIONSTRING
)cdata
;
720 cplen
= cs
->dwCompStrLen
;
721 cpstr
= (LPWSTR
)&(cdata
[cs
->dwCompStrOffset
]);
722 ImmUnlockIMCC(lpIMC
->hCompStr
);
724 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
727 WCHAR param
= cpstr
[0];
729 newCompStr
= updateResultStr(lpIMC
->hCompStr
, cpstr
, cplen
);
730 ImmDestroyIMCC(lpIMC
->hCompStr
);
731 lpIMC
->hCompStr
= newCompStr
;
732 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
733 ImmDestroyIMCC(lpIMC
->hCompStr
);
734 lpIMC
->hCompStr
= newCompStr
;
736 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, 0,
739 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, param
,
740 GCS_RESULTSTR
|GCS_RESULTCLAUSE
);
742 GenerateIMEMessage(hIMC
,WM_IME_ENDCOMPOSITION
, 0, 0);
744 else if (myPrivate
->bInComposition
)
745 GenerateIMEMessage(hIMC
,WM_IME_ENDCOMPOSITION
, 0, 0);
747 myPrivate
->bInComposition
= FALSE
;
748 ImmUnlockIMCC(lpIMC
->hPrivate
);
753 case CPS_CONVERT
: FIXME("CPS_CONVERT\n"); break;
754 case CPS_REVERT
: FIXME("CPS_REVERT\n"); break;
757 LPIMEPRIVATE myPrivate
;
759 TRACE("CPS_CANCEL\n");
761 X11DRV_CALL( xim_reset
, lpIMC
->hWnd
);
764 ImmDestroyIMCC(lpIMC
->hCompStr
);
765 lpIMC
->hCompStr
= ImeCreateBlankCompStr();
767 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
768 if (myPrivate
->bInComposition
)
770 GenerateIMEMessage(hIMC
, WM_IME_ENDCOMPOSITION
, 0, 0);
771 myPrivate
->bInComposition
= FALSE
;
773 ImmUnlockIMCC(lpIMC
->hPrivate
);
777 default: FIXME("Unknown\n"); break;
780 default: FIXME("Unknown Message\n"); break;
787 BOOL WINAPI
ImeRegisterWord(LPCWSTR lpszReading
, DWORD dwStyle
,
788 LPCWSTR lpszRegister
)
790 FIXME("(%s, %ld, %s): stub\n", debugstr_w(lpszReading
), dwStyle
,
791 debugstr_w(lpszRegister
));
792 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
796 BOOL WINAPI
ImeUnregisterWord(LPCWSTR lpszReading
, DWORD dwStyle
,
797 LPCWSTR lpszUnregister
)
799 FIXME("(%s, %ld, %s): stub\n", debugstr_w(lpszReading
), dwStyle
,
800 debugstr_w(lpszUnregister
));
801 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
805 UINT WINAPI
ImeGetRegisterWordStyle(UINT nItem
, LPSTYLEBUFW lpStyleBuf
)
807 FIXME("(%d, %p): stub\n", nItem
, lpStyleBuf
);
808 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
812 UINT WINAPI
ImeEnumRegisterWord(REGISTERWORDENUMPROCW lpfnEnumProc
,
813 LPCWSTR lpszReading
, DWORD dwStyle
,
814 LPCWSTR lpszRegister
, LPVOID lpData
)
816 FIXME("(%p, %s, %ld, %s, %p): stub\n", lpfnEnumProc
,
817 debugstr_w(lpszReading
), dwStyle
, debugstr_w(lpszRegister
),
819 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
823 BOOL WINAPI
ImeSetCompositionString(HIMC hIMC
, DWORD dwIndex
, LPCVOID lpComp
,
824 DWORD dwCompLen
, LPCVOID lpRead
,
827 LPINPUTCONTEXT lpIMC
;
830 LPIMEPRIVATE myPrivate
;
832 TRACE("(%p, %ld, %p, %ld, %p, %ld):\n",
833 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
836 if (hIMC
!= FROM_X11
)
837 FIXME("PROBLEM: This only sets the wine level string\n");
841 * this sets the composition string in the imm32.dll level
842 * of the composition buffer. we cannot manipulate the xim level
843 * buffer, which means that once the xim level buffer changes again
844 * any call to this function from the application will be lost
847 if (lpRead
&& dwReadLen
)
848 FIXME("Reading string unimplemented\n");
850 lpIMC
= LockRealIMC(hIMC
);
855 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
857 if (dwIndex
== SCS_SETSTR
)
861 if (!myPrivate
->bInComposition
)
863 GenerateIMEMessage(hIMC
, WM_IME_STARTCOMPOSITION
, 0, 0);
864 myPrivate
->bInComposition
= TRUE
;
867 /* clear existing result */
868 newCompStr
= updateResultStr(lpIMC
->hCompStr
, NULL
, 0);
869 ImmDestroyIMCC(lpIMC
->hCompStr
);
870 lpIMC
->hCompStr
= newCompStr
;
874 if (dwCompLen
&& lpComp
)
876 newCompStr
= updateCompStr(lpIMC
->hCompStr
, (LPCWSTR
)lpComp
, dwCompLen
/ sizeof(WCHAR
));
877 ImmDestroyIMCC(lpIMC
->hCompStr
);
878 lpIMC
->hCompStr
= newCompStr
;
880 wParam
= ((const WCHAR
*)lpComp
)[0];
881 flags
|= GCS_COMPCLAUSE
| GCS_COMPATTR
| GCS_DELTASTART
;
885 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
886 ImmDestroyIMCC(lpIMC
->hCompStr
);
887 lpIMC
->hCompStr
= newCompStr
;
891 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, wParam
, flags
);
892 ImmUnlockIMCC(lpIMC
->hPrivate
);
898 DWORD WINAPI
ImeGetImeMenuItems(HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
899 LPIMEMENUITEMINFOW lpImeParentMenu
, LPIMEMENUITEMINFOW lpImeMenu
,
902 FIXME("(%p, %lx %lx %p %p %lx): stub\n", hIMC
, dwFlags
, dwType
,
903 lpImeParentMenu
, lpImeMenu
, dwSize
);
904 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
908 /* Interfaces to XIM and other parts of winex11drv */
910 NTSTATUS
x11drv_ime_set_open_status( UINT open
)
914 imc
= RealIMC(FROM_X11
);
915 ImmSetOpenStatus(imc
, open
);
919 NTSTATUS
x11drv_ime_set_composition_status( UINT open
)
922 LPINPUTCONTEXT lpIMC
;
923 LPIMEPRIVATE myPrivate
;
925 imc
= RealIMC(FROM_X11
);
926 lpIMC
= ImmLockIMC(imc
);
930 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
932 if (open
&& !myPrivate
->bInComposition
)
934 GenerateIMEMessage(imc
, WM_IME_STARTCOMPOSITION
, 0, 0);
936 else if (!open
&& myPrivate
->bInComposition
)
938 ShowWindow(myPrivate
->hwndDefault
, SW_HIDE
);
939 ImmDestroyIMCC(lpIMC
->hCompStr
);
940 lpIMC
->hCompStr
= ImeCreateBlankCompStr();
941 GenerateIMEMessage(imc
, WM_IME_ENDCOMPOSITION
, 0, 0);
943 myPrivate
->bInComposition
= open
;
945 ImmUnlockIMCC(lpIMC
->hPrivate
);
950 NTSTATUS
x11drv_ime_get_cursor_pos( UINT arg
)
952 LPINPUTCONTEXT lpIMC
;
954 LPCOMPOSITIONSTRING compstr
;
959 lpIMC
= LockRealIMC(FROM_X11
);
962 compstr
= ImmLockIMCC(lpIMC
->hCompStr
);
963 rc
= compstr
->dwCursorPos
;
964 ImmUnlockIMCC(lpIMC
->hCompStr
);
966 UnlockRealIMC(FROM_X11
);
970 NTSTATUS
x11drv_ime_set_cursor_pos( UINT pos
)
972 LPINPUTCONTEXT lpIMC
;
973 LPCOMPOSITIONSTRING compstr
;
978 lpIMC
= LockRealIMC(FROM_X11
);
982 compstr
= ImmLockIMCC(lpIMC
->hCompStr
);
985 UnlockRealIMC(FROM_X11
);
989 compstr
->dwCursorPos
= pos
;
990 ImmUnlockIMCC(lpIMC
->hCompStr
);
991 UnlockRealIMC(FROM_X11
);
992 GenerateIMEMessage(FROM_X11
, WM_IME_COMPOSITION
, pos
, GCS_CURSORPOS
);
996 NTSTATUS
x11drv_ime_update_association( UINT arg
)
998 HWND focus
= UlongToHandle( arg
);
1000 ImmGetContext(focus
);
1002 if (focus
&& hSelectedFrom
)
1003 ImmAssociateContext(focus
,RealIMC(FROM_X11
));
1008 NTSTATUS WINAPI
x11drv_ime_set_composition_string( void *param
, ULONG size
)
1010 return ImeSetCompositionString(FROM_X11
, SCS_SETSTR
, param
, size
, NULL
, 0);
1013 NTSTATUS WINAPI
x11drv_ime_set_result( void *params
, ULONG len
)
1015 WCHAR
*lpResult
= params
;
1017 LPINPUTCONTEXT lpIMC
;
1019 LPIMEPRIVATE myPrivate
;
1023 len
/= sizeof(WCHAR
);
1024 if ((focus
= GetFocus()))
1025 x11drv_ime_update_association( HandleToUlong( focus
));
1027 imc
= RealIMC(FROM_X11
);
1028 lpIMC
= ImmLockIMC(imc
);
1032 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
1033 ImmDestroyIMCC(lpIMC
->hCompStr
);
1034 lpIMC
->hCompStr
= newCompStr
;
1036 newCompStr
= updateResultStr(lpIMC
->hCompStr
, lpResult
, len
);
1037 ImmDestroyIMCC(lpIMC
->hCompStr
);
1038 lpIMC
->hCompStr
= newCompStr
;
1040 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
1041 inComp
= myPrivate
->bInComposition
;
1042 ImmUnlockIMCC(lpIMC
->hPrivate
);
1046 ImmSetOpenStatus(imc
, TRUE
);
1047 GenerateIMEMessage(imc
, WM_IME_STARTCOMPOSITION
, 0, 0);
1050 GenerateIMEMessage(imc
, WM_IME_COMPOSITION
, 0, GCS_COMPSTR
);
1051 GenerateIMEMessage(imc
, WM_IME_COMPOSITION
, lpResult
[0], GCS_RESULTSTR
|GCS_RESULTCLAUSE
);
1052 GenerateIMEMessage(imc
, WM_IME_ENDCOMPOSITION
, 0, 0);
1055 ImmSetOpenStatus(imc
, FALSE
);
1062 * Internal functions to help with IME window management
1064 static void PaintDefaultIMEWnd(HIMC hIMC
, HWND hwnd
)
1069 LPCOMPOSITIONSTRING compstr
;
1070 LPBYTE compdata
= NULL
;
1072 MONITORINFO mon_info
;
1074 LPINPUTCONTEXT lpIMC
;
1076 lpIMC
= LockRealIMC(hIMC
);
1080 hdc
= BeginPaint(hwnd
,&ps
);
1082 GetClientRect(hwnd
,&rect
);
1083 FillRect(hdc
, &rect
, (HBRUSH
)(COLOR_WINDOW
+ 1));
1085 compdata
= ImmLockIMCC(lpIMC
->hCompStr
);
1086 compstr
= (LPCOMPOSITIONSTRING
)compdata
;
1088 if (compstr
->dwCompStrLen
&& compstr
->dwCompStrOffset
)
1092 HFONT oldfont
= NULL
;
1094 LPIMEPRIVATE myPrivate
;
1096 CompString
= (LPWSTR
)(compdata
+ compstr
->dwCompStrOffset
);
1097 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
1099 if (myPrivate
->textfont
)
1100 oldfont
= SelectObject(hdc
,myPrivate
->textfont
);
1102 ImmUnlockIMCC(lpIMC
->hPrivate
);
1104 GetTextExtentPoint32W(hdc
, CompString
, compstr
->dwCompStrLen
, &size
);
1110 * How this works based on tests on windows:
1111 * CFS_POINT: then we start our window at the point and grow it as large
1112 * as it needs to be for the string.
1113 * CFS_RECT: we still use the ptCurrentPos as a starting point and our
1114 * window is only as large as we need for the string, but we do not
1115 * grow such that our window exceeds the given rect. Wrapping if
1116 * needed and possible. If our ptCurrentPos is outside of our rect
1117 * then no window is displayed.
1118 * CFS_FORCE_POSITION: appears to behave just like CFS_POINT
1119 * maybe because the default MSIME does not do any IME adjusting.
1121 if (lpIMC
->cfCompForm
.dwStyle
!= CFS_DEFAULT
)
1123 POINT cpt
= lpIMC
->cfCompForm
.ptCurrentPos
;
1124 ClientToScreen(lpIMC
->hWnd
,&cpt
);
1127 rect
.right
= rect
.left
+ pt
.x
;
1128 rect
.bottom
= rect
.top
+ pt
.y
;
1129 monitor
= MonitorFromPoint(cpt
, MONITOR_DEFAULTTOPRIMARY
);
1131 else /* CFS_DEFAULT */
1133 /* Windows places the default IME window in the bottom left */
1134 HWND target
= lpIMC
->hWnd
;
1135 if (!target
) target
= GetFocus();
1137 GetWindowRect(target
,&rect
);
1138 rect
.top
= rect
.bottom
;
1139 rect
.right
= rect
.left
+ pt
.x
+ 20;
1140 rect
.bottom
= rect
.top
+ pt
.y
+ 20;
1142 monitor
= MonitorFromWindow(target
, MONITOR_DEFAULTTOPRIMARY
);
1145 if (lpIMC
->cfCompForm
.dwStyle
== CFS_RECT
)
1148 client
=lpIMC
->cfCompForm
.rcArea
;
1149 MapWindowPoints( lpIMC
->hWnd
, 0, (POINT
*)&client
, 2 );
1150 IntersectRect(&rect
,&rect
,&client
);
1151 /* TODO: Wrap the input if needed */
1154 if (lpIMC
->cfCompForm
.dwStyle
== CFS_DEFAULT
)
1156 /* make sure we are on the desktop */
1157 mon_info
.cbSize
= sizeof(mon_info
);
1158 GetMonitorInfoW(monitor
, &mon_info
);
1160 if (rect
.bottom
> mon_info
.rcWork
.bottom
)
1162 int shift
= rect
.bottom
- mon_info
.rcWork
.bottom
;
1164 rect
.bottom
-= shift
;
1168 rect
.right
-= rect
.left
;
1171 if (rect
.right
> mon_info
.rcWork
.right
)
1173 int shift
= rect
.right
- mon_info
.rcWork
.right
;
1175 rect
.right
-= shift
;
1179 SetWindowPos(hwnd
, HWND_TOPMOST
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, SWP_NOACTIVATE
);
1181 TextOutW(hdc
, offX
,offY
, CompString
, compstr
->dwCompStrLen
);
1184 SelectObject(hdc
,oldfont
);
1187 ImmUnlockIMCC(lpIMC
->hCompStr
);
1190 UnlockRealIMC(hIMC
);
1193 static void UpdateDefaultIMEWindow(HIMC hIMC
, HWND hwnd
)
1195 LPCOMPOSITIONSTRING compstr
;
1196 LPINPUTCONTEXT lpIMC
;
1198 lpIMC
= LockRealIMC(hIMC
);
1202 if (lpIMC
->hCompStr
)
1203 compstr
= ImmLockIMCC(lpIMC
->hCompStr
);
1207 if (compstr
== NULL
|| compstr
->dwCompStrLen
== 0)
1208 ShowWindow(hwnd
,SW_HIDE
);
1211 ShowWindow(hwnd
,SW_SHOWNOACTIVATE
);
1212 RedrawWindow(hwnd
, NULL
, NULL
, RDW_ERASENOW
| RDW_INVALIDATE
);
1215 if (compstr
!= NULL
)
1216 ImmUnlockIMCC(lpIMC
->hCompStr
);
1218 lpIMC
->hWnd
= GetFocus();
1219 UnlockRealIMC(hIMC
);
1222 static void DefaultIMEComposition(HIMC hIMC
, HWND hwnd
, LPARAM lParam
)
1224 TRACE("IME message WM_IME_COMPOSITION 0x%Ix\n", lParam
);
1225 if (!(lParam
& GCS_RESULTSTR
))
1226 UpdateDefaultIMEWindow(hIMC
, hwnd
);
1229 static void DefaultIMEStartComposition(HIMC hIMC
, HWND hwnd
)
1231 TRACE("IME message WM_IME_STARTCOMPOSITION\n");
1232 UpdateDefaultIMEWindow(hIMC
, hwnd
);
1235 static LRESULT
ImeHandleNotify(HIMC hIMC
, HWND hwnd
, UINT msg
, WPARAM wParam
,
1240 case IMN_OPENSTATUSWINDOW
:
1241 FIXME("WM_IME_NOTIFY:IMN_OPENSTATUSWINDOW\n");
1243 case IMN_CLOSESTATUSWINDOW
:
1244 FIXME("WM_IME_NOTIFY:IMN_CLOSESTATUSWINDOW\n");
1246 case IMN_OPENCANDIDATE
:
1247 FIXME("WM_IME_NOTIFY:IMN_OPENCANDIDATE\n");
1249 case IMN_CHANGECANDIDATE
:
1250 FIXME("WM_IME_NOTIFY:IMN_CHANGECANDIDATE\n");
1252 case IMN_CLOSECANDIDATE
:
1253 FIXME("WM_IME_NOTIFY:IMN_CLOSECANDIDATE\n");
1255 case IMN_SETCONVERSIONMODE
:
1256 FIXME("WM_IME_NOTIFY:IMN_SETCONVERSIONMODE\n");
1258 case IMN_SETSENTENCEMODE
:
1259 FIXME("WM_IME_NOTIFY:IMN_SETSENTENCEMODE\n");
1261 case IMN_SETOPENSTATUS
:
1262 TRACE("WM_IME_NOTIFY:IMN_SETOPENSTATUS\n");
1264 case IMN_SETCANDIDATEPOS
:
1265 FIXME("WM_IME_NOTIFY:IMN_SETCANDIDATEPOS\n");
1267 case IMN_SETCOMPOSITIONFONT
:
1268 FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONFONT\n");
1270 case IMN_SETCOMPOSITIONWINDOW
:
1271 FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONWINDOW\n");
1274 FIXME("WM_IME_NOTIFY:IMN_GUIDELINE\n");
1276 case IMN_SETSTATUSWINDOWPOS
:
1277 FIXME("WM_IME_NOTIFY:IMN_SETSTATUSWINDOWPOS\n");
1280 FIXME("WM_IME_NOTIFY:<Unknown 0x%Ix>\n",wParam
);
1286 static LRESULT WINAPI
IME_WindowProc(HWND hwnd
, UINT msg
, WPARAM wParam
,
1292 TRACE("Incoming Message 0x%x (0x%08Ix, 0x%08Ix)\n", msg
, wParam
, lParam
);
1295 * Each UI window contains the current Input Context.
1296 * This Input Context can be obtained by calling GetWindowLong
1297 * with IMMGWL_IMC when the UI window receives a WM_IME_xxx message.
1298 * The UI window can refer to this Input Context and handles the
1302 hIMC
= (HIMC
)GetWindowLongPtrW(hwnd
,IMMGWL_IMC
);
1304 hIMC
= RealIMC(FROM_X11
);
1306 /* if we have no hIMC there are many messages we cannot process */
1310 case WM_IME_STARTCOMPOSITION
:
1311 case WM_IME_ENDCOMPOSITION
:
1312 case WM_IME_COMPOSITION
:
1314 case WM_IME_CONTROL
:
1315 case WM_IME_COMPOSITIONFULL
:
1328 LPIMEPRIVATE myPrivate
;
1329 LPINPUTCONTEXT lpIMC
;
1331 SetWindowTextA(hwnd
,"Wine Ime Active");
1333 lpIMC
= LockRealIMC(hIMC
);
1336 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
1337 myPrivate
->hwndDefault
= hwnd
;
1338 ImmUnlockIMCC(lpIMC
->hPrivate
);
1340 UnlockRealIMC(hIMC
);
1345 PaintDefaultIMEWnd(hIMC
, hwnd
);
1353 SetFocus((HWND
)wParam
);
1355 FIXME("Received focus, should never have focus\n");
1357 case WM_IME_COMPOSITION
:
1358 DefaultIMEComposition(hIMC
, hwnd
, lParam
);
1360 case WM_IME_STARTCOMPOSITION
:
1361 DefaultIMEStartComposition(hIMC
, hwnd
);
1363 case WM_IME_ENDCOMPOSITION
:
1364 TRACE("IME message %s, 0x%Ix, 0x%Ix\n",
1365 "WM_IME_ENDCOMPOSITION", wParam
, lParam
);
1366 ShowWindow(hwnd
,SW_HIDE
);
1369 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_IME_SELECT", wParam
, lParam
);
1371 case WM_IME_CONTROL
:
1372 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_IME_CONTROL", wParam
, lParam
);
1376 rc
= ImeHandleNotify(hIMC
,hwnd
,msg
,wParam
,lParam
);
1379 TRACE("Non-standard message 0x%x\n",msg
);
1381 /* check the MSIME messages */
1382 if (msg
== WM_MSIME_SERVICE
)
1384 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_SERVICE", wParam
, lParam
);
1387 else if (msg
== WM_MSIME_RECONVERTOPTIONS
)
1389 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_RECONVERTOPTIONS", wParam
, lParam
);
1391 else if (msg
== WM_MSIME_MOUSE
)
1393 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_MOUSE", wParam
, lParam
);
1395 else if (msg
== WM_MSIME_RECONVERTREQUEST
)
1397 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_RECONVERTREQUEST", wParam
, lParam
);
1399 else if (msg
== WM_MSIME_RECONVERT
)
1401 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_RECONVERT", wParam
, lParam
);
1403 else if (msg
== WM_MSIME_QUERYPOSITION
)
1405 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_QUERYPOSITION", wParam
, lParam
);
1407 else if (msg
== WM_MSIME_DOCUMENTFEED
)
1409 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_DOCUMENTFEED", wParam
, lParam
);
1411 /* DefWndProc if not an IME message */
1412 if (!rc
&& !((msg
>= WM_IME_STARTCOMPOSITION
&& msg
<= WM_IME_KEYLAST
) ||
1413 (msg
>= WM_IME_SETCONTEXT
&& msg
<= WM_IME_KEYUP
)))
1414 rc
= DefWindowProcW(hwnd
,msg
,wParam
,lParam
);