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 static const WCHAR UI_CLASS_NAME
[] = {'W','i','n','e','X','1','1','I','M','E',0};
61 static HIMC
*hSelectedFrom
= NULL
;
62 static INT hSelectedCount
= 0;
65 static UINT WM_MSIME_SERVICE
;
66 static UINT WM_MSIME_RECONVERTOPTIONS
;
67 static UINT WM_MSIME_MOUSE
;
68 static UINT WM_MSIME_RECONVERTREQUEST
;
69 static UINT WM_MSIME_RECONVERT
;
70 static UINT WM_MSIME_QUERYPOSITION
;
71 static UINT WM_MSIME_DOCUMENTFEED
;
73 static LRESULT WINAPI
IME_WindowProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
,
76 static HIMC
RealIMC(HIMC hIMC
)
81 HWND wnd
= GetFocus();
82 HIMC winHimc
= ImmGetContext(wnd
);
83 for (i
= 0; i
< hSelectedCount
; i
++)
84 if (winHimc
== hSelectedFrom
[i
])
92 static LPINPUTCONTEXT
LockRealIMC(HIMC hIMC
)
94 HIMC real_imc
= RealIMC(hIMC
);
96 return ImmLockIMC(real_imc
);
101 static BOOL
UnlockRealIMC(HIMC hIMC
)
103 HIMC real_imc
= RealIMC(hIMC
);
105 return ImmUnlockIMC(real_imc
);
110 static BOOL WINAPI
register_classes( INIT_ONCE
*once
, void *param
, void **context
)
114 ZeroMemory(&wndClass
, sizeof(WNDCLASSW
));
115 wndClass
.style
= CS_GLOBALCLASS
| CS_IME
| CS_HREDRAW
| CS_VREDRAW
;
116 wndClass
.lpfnWndProc
= IME_WindowProc
;
117 wndClass
.cbClsExtra
= 0;
118 wndClass
.cbWndExtra
= 2 * sizeof(LONG_PTR
);
119 wndClass
.hInstance
= x11drv_module
;
120 wndClass
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
121 wndClass
.hIcon
= LoadIconW(NULL
, (LPWSTR
)IDI_APPLICATION
);
122 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
123 wndClass
.lpszMenuName
= 0;
124 wndClass
.lpszClassName
= UI_CLASS_NAME
;
126 RegisterClassW(&wndClass
);
128 WM_MSIME_SERVICE
= RegisterWindowMessageA("MSIMEService");
129 WM_MSIME_RECONVERTOPTIONS
= RegisterWindowMessageA("MSIMEReconvertOptions");
130 WM_MSIME_MOUSE
= RegisterWindowMessageA("MSIMEMouseOperation");
131 WM_MSIME_RECONVERTREQUEST
= RegisterWindowMessageA("MSIMEReconvertRequest");
132 WM_MSIME_RECONVERT
= RegisterWindowMessageA("MSIMEReconvert");
133 WM_MSIME_QUERYPOSITION
= RegisterWindowMessageA("MSIMEQueryPosition");
134 WM_MSIME_DOCUMENTFEED
= RegisterWindowMessageA("MSIMEDocumentFeed");
138 static HIMCC
ImeCreateBlankCompStr(void)
141 LPCOMPOSITIONSTRING ptr
;
142 rc
= ImmCreateIMCC(sizeof(COMPOSITIONSTRING
));
143 ptr
= ImmLockIMCC(rc
);
144 memset(ptr
,0,sizeof(COMPOSITIONSTRING
));
145 ptr
->dwSize
= sizeof(COMPOSITIONSTRING
);
150 static int updateField(DWORD origLen
, DWORD origOffset
, DWORD currentOffset
,
151 LPBYTE target
, LPBYTE source
, DWORD
* lenParam
,
152 DWORD
* offsetParam
, BOOL wchars
)
154 if (origLen
> 0 && origOffset
> 0)
156 int truelen
= origLen
;
158 truelen
*= sizeof(WCHAR
);
160 memcpy(&target
[currentOffset
], &source
[origOffset
], truelen
);
163 *offsetParam
= currentOffset
;
164 currentOffset
+= truelen
;
166 return currentOffset
;
169 static HIMCC
updateCompStr(HIMCC old
, LPCWSTR compstr
, DWORD len
)
171 /* We need to make sure the CompStr, CompClause and CompAttr fields are all
172 * set and correct. */
175 LPBYTE newdata
= NULL
;
176 LPBYTE olddata
= NULL
;
177 LPCOMPOSITIONSTRING new_one
;
178 LPCOMPOSITIONSTRING lpcs
= NULL
;
179 INT current_offset
= 0;
181 TRACE("%s, %li\n",debugstr_wn(compstr
,len
),len
);
183 if (old
== NULL
&& compstr
== NULL
&& len
== 0)
186 if (compstr
== NULL
&& len
!= 0)
188 ERR("compstr is NULL however we have a len! Please report\n");
194 olddata
= ImmLockIMCC(old
);
195 lpcs
= (LPCOMPOSITIONSTRING
)olddata
;
198 needed_size
= sizeof(COMPOSITIONSTRING
) + len
* sizeof(WCHAR
) +
199 len
+ sizeof(DWORD
) * 2;
203 needed_size
+= lpcs
->dwCompReadAttrLen
;
204 needed_size
+= lpcs
->dwCompReadClauseLen
;
205 needed_size
+= lpcs
->dwCompReadStrLen
* sizeof(WCHAR
);
206 needed_size
+= lpcs
->dwResultReadClauseLen
;
207 needed_size
+= lpcs
->dwResultReadStrLen
* sizeof(WCHAR
);
208 needed_size
+= lpcs
->dwResultClauseLen
;
209 needed_size
+= lpcs
->dwResultStrLen
* sizeof(WCHAR
);
210 needed_size
+= lpcs
->dwPrivateSize
;
212 rc
= ImmCreateIMCC(needed_size
);
213 newdata
= ImmLockIMCC(rc
);
214 new_one
= (LPCOMPOSITIONSTRING
)newdata
;
216 new_one
->dwSize
= needed_size
;
217 current_offset
= sizeof(COMPOSITIONSTRING
);
220 current_offset
= updateField(lpcs
->dwCompReadAttrLen
,
221 lpcs
->dwCompReadAttrOffset
,
222 current_offset
, newdata
, olddata
,
223 &new_one
->dwCompReadAttrLen
,
224 &new_one
->dwCompReadAttrOffset
, FALSE
);
226 current_offset
= updateField(lpcs
->dwCompReadClauseLen
,
227 lpcs
->dwCompReadClauseOffset
,
228 current_offset
, newdata
, olddata
,
229 &new_one
->dwCompReadClauseLen
,
230 &new_one
->dwCompReadClauseOffset
, FALSE
);
232 current_offset
= updateField(lpcs
->dwCompReadStrLen
,
233 lpcs
->dwCompReadStrOffset
,
234 current_offset
, newdata
, olddata
,
235 &new_one
->dwCompReadStrLen
,
236 &new_one
->dwCompReadStrOffset
, TRUE
);
238 /* new CompAttr, CompClause, CompStr, dwCursorPos */
239 new_one
->dwDeltaStart
= 0;
241 current_offset
= updateField(lpcs
->dwResultReadClauseLen
,
242 lpcs
->dwResultReadClauseOffset
,
243 current_offset
, newdata
, olddata
,
244 &new_one
->dwResultReadClauseLen
,
245 &new_one
->dwResultReadClauseOffset
, FALSE
);
247 current_offset
= updateField(lpcs
->dwResultReadStrLen
,
248 lpcs
->dwResultReadStrOffset
,
249 current_offset
, newdata
, olddata
,
250 &new_one
->dwResultReadStrLen
,
251 &new_one
->dwResultReadStrOffset
, TRUE
);
253 current_offset
= updateField(lpcs
->dwResultClauseLen
,
254 lpcs
->dwResultClauseOffset
,
255 current_offset
, newdata
, olddata
,
256 &new_one
->dwResultClauseLen
,
257 &new_one
->dwResultClauseOffset
, FALSE
);
259 current_offset
= updateField(lpcs
->dwResultStrLen
,
260 lpcs
->dwResultStrOffset
,
261 current_offset
, newdata
, olddata
,
262 &new_one
->dwResultStrLen
,
263 &new_one
->dwResultStrOffset
, TRUE
);
265 current_offset
= updateField(lpcs
->dwPrivateSize
,
266 lpcs
->dwPrivateOffset
,
267 current_offset
, newdata
, olddata
,
268 &new_one
->dwPrivateSize
,
269 &new_one
->dwPrivateOffset
, FALSE
);
274 new_one
->dwCompAttrLen
= len
;
277 new_one
->dwCompAttrOffset
= current_offset
;
278 memset(&newdata
[current_offset
],ATTR_INPUT
,len
);
279 current_offset
+= len
;
285 new_one
->dwCompClauseLen
= sizeof(DWORD
) * 2;
286 new_one
->dwCompClauseOffset
= current_offset
;
287 *(DWORD
*)(&newdata
[current_offset
]) = 0;
288 current_offset
+= sizeof(DWORD
);
289 *(DWORD
*)(&newdata
[current_offset
]) = len
;
290 current_offset
+= sizeof(DWORD
);
293 new_one
->dwCompClauseLen
= 0;
296 new_one
->dwCompStrLen
= len
;
299 new_one
->dwCompStrOffset
= current_offset
;
300 memcpy(&newdata
[current_offset
],compstr
,len
*sizeof(WCHAR
));
304 new_one
->dwCursorPos
= len
;
313 static HIMCC
updateResultStr(HIMCC old
, LPWSTR resultstr
, DWORD len
)
315 /* we need to make sure the ResultStr and ResultClause fields are all
319 LPBYTE newdata
= NULL
;
320 LPBYTE olddata
= NULL
;
321 LPCOMPOSITIONSTRING new_one
;
322 LPCOMPOSITIONSTRING lpcs
= NULL
;
323 INT current_offset
= 0;
325 TRACE("%s, %li\n",debugstr_wn(resultstr
,len
),len
);
327 if (old
== NULL
&& resultstr
== NULL
&& len
== 0)
330 if (resultstr
== NULL
&& len
!= 0)
332 ERR("resultstr is NULL however we have a len! Please report\n");
338 olddata
= ImmLockIMCC(old
);
339 lpcs
= (LPCOMPOSITIONSTRING
)olddata
;
342 needed_size
= sizeof(COMPOSITIONSTRING
) + len
* sizeof(WCHAR
) +
347 needed_size
+= lpcs
->dwCompReadAttrLen
;
348 needed_size
+= lpcs
->dwCompReadClauseLen
;
349 needed_size
+= lpcs
->dwCompReadStrLen
* sizeof(WCHAR
);
350 needed_size
+= lpcs
->dwCompAttrLen
;
351 needed_size
+= lpcs
->dwCompClauseLen
;
352 needed_size
+= lpcs
->dwCompStrLen
* sizeof(WCHAR
);
353 needed_size
+= lpcs
->dwResultReadClauseLen
;
354 needed_size
+= lpcs
->dwResultReadStrLen
* sizeof(WCHAR
);
355 needed_size
+= lpcs
->dwPrivateSize
;
357 rc
= ImmCreateIMCC(needed_size
);
358 newdata
= ImmLockIMCC(rc
);
359 new_one
= (LPCOMPOSITIONSTRING
)newdata
;
361 new_one
->dwSize
= needed_size
;
362 current_offset
= sizeof(COMPOSITIONSTRING
);
365 current_offset
= updateField(lpcs
->dwCompReadAttrLen
,
366 lpcs
->dwCompReadAttrOffset
,
367 current_offset
, newdata
, olddata
,
368 &new_one
->dwCompReadAttrLen
,
369 &new_one
->dwCompReadAttrOffset
, FALSE
);
371 current_offset
= updateField(lpcs
->dwCompReadClauseLen
,
372 lpcs
->dwCompReadClauseOffset
,
373 current_offset
, newdata
, olddata
,
374 &new_one
->dwCompReadClauseLen
,
375 &new_one
->dwCompReadClauseOffset
, FALSE
);
377 current_offset
= updateField(lpcs
->dwCompReadStrLen
,
378 lpcs
->dwCompReadStrOffset
,
379 current_offset
, newdata
, olddata
,
380 &new_one
->dwCompReadStrLen
,
381 &new_one
->dwCompReadStrOffset
, TRUE
);
383 current_offset
= updateField(lpcs
->dwCompAttrLen
,
384 lpcs
->dwCompAttrOffset
,
385 current_offset
, newdata
, olddata
,
386 &new_one
->dwCompAttrLen
,
387 &new_one
->dwCompAttrOffset
, FALSE
);
389 current_offset
= updateField(lpcs
->dwCompClauseLen
,
390 lpcs
->dwCompClauseOffset
,
391 current_offset
, newdata
, olddata
,
392 &new_one
->dwCompClauseLen
,
393 &new_one
->dwCompClauseOffset
, FALSE
);
395 current_offset
= updateField(lpcs
->dwCompStrLen
,
396 lpcs
->dwCompStrOffset
,
397 current_offset
, newdata
, olddata
,
398 &new_one
->dwCompStrLen
,
399 &new_one
->dwCompStrOffset
, TRUE
);
401 new_one
->dwCursorPos
= lpcs
->dwCursorPos
;
402 new_one
->dwDeltaStart
= 0;
404 current_offset
= updateField(lpcs
->dwResultReadClauseLen
,
405 lpcs
->dwResultReadClauseOffset
,
406 current_offset
, newdata
, olddata
,
407 &new_one
->dwResultReadClauseLen
,
408 &new_one
->dwResultReadClauseOffset
, FALSE
);
410 current_offset
= updateField(lpcs
->dwResultReadStrLen
,
411 lpcs
->dwResultReadStrOffset
,
412 current_offset
, newdata
, olddata
,
413 &new_one
->dwResultReadStrLen
,
414 &new_one
->dwResultReadStrOffset
, TRUE
);
416 /* new ResultClause , ResultStr */
418 current_offset
= updateField(lpcs
->dwPrivateSize
,
419 lpcs
->dwPrivateOffset
,
420 current_offset
, newdata
, olddata
,
421 &new_one
->dwPrivateSize
,
422 &new_one
->dwPrivateOffset
, FALSE
);
429 new_one
->dwResultClauseLen
= sizeof(DWORD
) * 2;
430 new_one
->dwResultClauseOffset
= current_offset
;
431 *(DWORD
*)(&newdata
[current_offset
]) = 0;
432 current_offset
+= sizeof(DWORD
);
433 *(DWORD
*)(&newdata
[current_offset
]) = len
;
434 current_offset
+= sizeof(DWORD
);
437 new_one
->dwResultClauseLen
= 0;
440 new_one
->dwResultStrLen
= len
;
443 new_one
->dwResultStrOffset
= current_offset
;
444 memcpy(&newdata
[current_offset
],resultstr
,len
*sizeof(WCHAR
));
453 static void GenerateIMEMessage(HIMC hIMC
, UINT msg
, WPARAM wParam
,
456 LPINPUTCONTEXT lpIMC
;
457 LPTRANSMSG lpTransMsg
;
459 lpIMC
= LockRealIMC(hIMC
);
463 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
, (lpIMC
->dwNumMsgBuf
+ 1) *
468 lpTransMsg
= ImmLockIMCC(lpIMC
->hMsgBuf
);
472 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
473 lpTransMsg
->message
= msg
;
474 lpTransMsg
->wParam
= wParam
;
475 lpTransMsg
->lParam
= lParam
;
477 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
478 lpIMC
->dwNumMsgBuf
++;
480 ImmGenerateMessage(RealIMC(hIMC
));
484 static BOOL
IME_RemoveFromSelected(HIMC hIMC
)
487 for (i
= 0; i
< hSelectedCount
; i
++)
488 if (hSelectedFrom
[i
] == hIMC
)
490 if (i
< hSelectedCount
- 1)
491 memmove(&hSelectedFrom
[i
], &hSelectedFrom
[i
+1], (hSelectedCount
- i
- 1)*sizeof(HIMC
));
498 static void IME_AddToSelected(HIMC hIMC
)
502 hSelectedFrom
= HeapReAlloc(GetProcessHeap(), 0, hSelectedFrom
, hSelectedCount
*sizeof(HIMC
));
504 hSelectedFrom
= HeapAlloc(GetProcessHeap(), 0, sizeof(HIMC
));
505 hSelectedFrom
[hSelectedCount
-1] = hIMC
;
508 BOOL WINAPI
ImeInquire(LPIMEINFO lpIMEInfo
, LPWSTR lpszUIClass
, DWORD flags
)
510 static INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
513 InitOnceExecuteOnce( &init_once
, register_classes
, NULL
, NULL
);
514 lpIMEInfo
->dwPrivateDataSize
= sizeof (IMEPRIVATE
);
515 lpIMEInfo
->fdwProperty
= IME_PROP_UNICODE
| IME_PROP_AT_CARET
;
516 lpIMEInfo
->fdwConversionCaps
= IME_CMODE_NATIVE
| IME_CMODE_FULLSHAPE
;
517 lpIMEInfo
->fdwSentenceCaps
= IME_SMODE_AUTOMATIC
;
518 lpIMEInfo
->fdwUICaps
= UI_CAP_2700
;
519 /* Tell App we cannot accept ImeSetCompositionString calls */
520 lpIMEInfo
->fdwSCSCaps
= 0;
521 lpIMEInfo
->fdwSelectCaps
= SELECT_CAP_CONVERSION
;
523 lstrcpyW(lpszUIClass
,UI_CLASS_NAME
);
528 BOOL WINAPI
ImeConfigure(HKL hKL
,HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
530 FIXME("(%p, %p, %ld, %p): stub\n", hKL
, hWnd
, dwMode
, lpData
);
531 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
535 DWORD WINAPI
ImeConversionList(HIMC hIMC
, LPCWSTR lpSource
,
536 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
, UINT uFlag
)
539 FIXME("(%p, %s, %p, %ld, %d): stub\n", hIMC
, debugstr_w(lpSource
),
540 lpCandList
, dwBufLen
, uFlag
);
541 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
545 BOOL WINAPI
ImeDestroy(UINT uForce
)
548 HeapFree(GetProcessHeap(),0,hSelectedFrom
);
549 hSelectedFrom
= NULL
;
554 LRESULT WINAPI
ImeEscape(HIMC hIMC
, UINT uSubFunc
, LPVOID lpData
)
556 FIXME("(%p, %d, %p): stub\n", hIMC
, uSubFunc
, lpData
);
557 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
561 BOOL WINAPI
ImeProcessKey(HIMC hIMC
, UINT vKey
, LPARAM lKeyData
, const LPBYTE lpbKeyState
)
563 /* See the comment at the head of this file */
564 TRACE("We do no processing via this route\n");
568 BOOL WINAPI
ImeSelect(HIMC hIMC
, BOOL fSelect
)
570 LPINPUTCONTEXT lpIMC
;
571 TRACE("%p %s\n",hIMC
,(fSelect
)?"TRUE":"FALSE");
573 if (hIMC
== FROM_X11
)
575 ERR("ImeSelect should never be called from X11\n");
584 return IME_RemoveFromSelected(hIMC
);
586 IME_AddToSelected(hIMC
);
588 /* Initialize our structures */
589 lpIMC
= LockRealIMC(hIMC
);
592 LPIMEPRIVATE myPrivate
;
593 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
594 myPrivate
->bInComposition
= FALSE
;
595 myPrivate
->bInternalState
= FALSE
;
596 myPrivate
->textfont
= NULL
;
597 myPrivate
->hwndDefault
= NULL
;
598 ImmUnlockIMCC(lpIMC
->hPrivate
);
605 BOOL WINAPI
ImeSetActiveContext(HIMC hIMC
,BOOL fFlag
)
610 FIXME("(%p, %x): stub\n", hIMC
, fFlag
);
614 UINT WINAPI
ImeToAsciiEx (UINT uVKey
, UINT uScanCode
, const LPBYTE lpbKeyState
,
615 TRANSMSGLIST
*lpdwTransKey
, UINT fuState
, HIMC hIMC
)
617 /* See the comment at the head of this file */
618 TRACE("We do no processing via this route\n");
622 BOOL WINAPI
NotifyIME(HIMC hIMC
, DWORD dwAction
, DWORD dwIndex
, DWORD dwValue
)
624 struct xim_preedit_state_params preedit_params
;
626 LPINPUTCONTEXT lpIMC
;
628 TRACE("%p %li %li %li\n",hIMC
,dwAction
,dwIndex
,dwValue
);
630 lpIMC
= LockRealIMC(hIMC
);
636 case NI_OPENCANDIDATE
: FIXME("NI_OPENCANDIDATE\n"); break;
637 case NI_CLOSECANDIDATE
: FIXME("NI_CLOSECANDIDATE\n"); break;
638 case NI_SELECTCANDIDATESTR
: FIXME("NI_SELECTCANDIDATESTR\n"); break;
639 case NI_CHANGECANDIDATELIST
: FIXME("NI_CHANGECANDIDATELIST\n"); break;
640 case NI_SETCANDIDATE_PAGESTART
: FIXME("NI_SETCANDIDATE_PAGESTART\n"); break;
641 case NI_SETCANDIDATE_PAGESIZE
: FIXME("NI_SETCANDIDATE_PAGESIZE\n"); break;
642 case NI_CONTEXTUPDATED
:
645 case IMC_SETCOMPOSITIONWINDOW
: FIXME("IMC_SETCOMPOSITIONWINDOW\n"); break;
646 case IMC_SETCONVERSIONMODE
: FIXME("IMC_SETCONVERSIONMODE\n"); break;
647 case IMC_SETSENTENCEMODE
: FIXME("IMC_SETSENTENCEMODE\n"); break;
648 case IMC_SETCANDIDATEPOS
: FIXME("IMC_SETCANDIDATEPOS\n"); break;
649 case IMC_SETCOMPOSITIONFONT
:
651 LPIMEPRIVATE myPrivate
;
652 TRACE("IMC_SETCOMPOSITIONFONT\n");
654 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
655 if (myPrivate
->textfont
)
657 DeleteObject(myPrivate
->textfont
);
658 myPrivate
->textfont
= NULL
;
660 myPrivate
->textfont
= CreateFontIndirectW(&lpIMC
->lfFont
.W
);
661 ImmUnlockIMCC(lpIMC
->hPrivate
);
664 case IMC_SETOPENSTATUS
:
665 TRACE("IMC_SETOPENSTATUS\n");
668 preedit_params
.hwnd
= lpIMC
->hWnd
;
669 preedit_params
.open
= lpIMC
->fOpen
;
670 X11DRV_CALL( xim_preedit_state
, &preedit_params
);
673 LPIMEPRIVATE myPrivate
;
675 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
676 if (myPrivate
->bInComposition
)
678 X11DRV_CALL( xim_reset
, lpIMC
->hWnd
);
679 GenerateIMEMessage(hIMC
, WM_IME_ENDCOMPOSITION
, 0, 0);
680 myPrivate
->bInComposition
= FALSE
;
682 ImmUnlockIMCC(lpIMC
->hPrivate
);
686 default: FIXME("Unknown\n"); break;
689 case NI_COMPOSITIONSTR
:
697 LPCOMPOSITIONSTRING cs
= NULL
;
699 LPIMEPRIVATE myPrivate
;
701 TRACE("CPS_COMPLETE\n");
703 /* clear existing result */
704 newCompStr
= updateResultStr(lpIMC
->hCompStr
, NULL
, 0);
706 ImmDestroyIMCC(lpIMC
->hCompStr
);
707 lpIMC
->hCompStr
= newCompStr
;
711 cdata
= ImmLockIMCC(lpIMC
->hCompStr
);
712 cs
= (LPCOMPOSITIONSTRING
)cdata
;
713 cplen
= cs
->dwCompStrLen
;
714 cpstr
= (LPWSTR
)&(cdata
[cs
->dwCompStrOffset
]);
715 ImmUnlockIMCC(lpIMC
->hCompStr
);
717 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
720 WCHAR param
= cpstr
[0];
722 newCompStr
= updateResultStr(lpIMC
->hCompStr
, cpstr
, cplen
);
723 ImmDestroyIMCC(lpIMC
->hCompStr
);
724 lpIMC
->hCompStr
= newCompStr
;
725 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
726 ImmDestroyIMCC(lpIMC
->hCompStr
);
727 lpIMC
->hCompStr
= newCompStr
;
729 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, 0,
732 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, param
,
733 GCS_RESULTSTR
|GCS_RESULTCLAUSE
);
735 GenerateIMEMessage(hIMC
,WM_IME_ENDCOMPOSITION
, 0, 0);
737 else if (myPrivate
->bInComposition
)
738 GenerateIMEMessage(hIMC
,WM_IME_ENDCOMPOSITION
, 0, 0);
740 myPrivate
->bInComposition
= FALSE
;
741 ImmUnlockIMCC(lpIMC
->hPrivate
);
746 case CPS_CONVERT
: FIXME("CPS_CONVERT\n"); break;
747 case CPS_REVERT
: FIXME("CPS_REVERT\n"); break;
750 LPIMEPRIVATE myPrivate
;
752 TRACE("CPS_CANCEL\n");
754 X11DRV_CALL( xim_reset
, lpIMC
->hWnd
);
757 ImmDestroyIMCC(lpIMC
->hCompStr
);
758 lpIMC
->hCompStr
= ImeCreateBlankCompStr();
760 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
761 if (myPrivate
->bInComposition
)
763 GenerateIMEMessage(hIMC
, WM_IME_ENDCOMPOSITION
, 0, 0);
764 myPrivate
->bInComposition
= FALSE
;
766 ImmUnlockIMCC(lpIMC
->hPrivate
);
770 default: FIXME("Unknown\n"); break;
773 default: FIXME("Unknown Message\n"); break;
780 BOOL WINAPI
ImeRegisterWord(LPCWSTR lpszReading
, DWORD dwStyle
,
781 LPCWSTR lpszRegister
)
783 FIXME("(%s, %ld, %s): stub\n", debugstr_w(lpszReading
), dwStyle
,
784 debugstr_w(lpszRegister
));
785 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
789 BOOL WINAPI
ImeUnregisterWord(LPCWSTR lpszReading
, DWORD dwStyle
,
790 LPCWSTR lpszUnregister
)
792 FIXME("(%s, %ld, %s): stub\n", debugstr_w(lpszReading
), dwStyle
,
793 debugstr_w(lpszUnregister
));
794 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
798 UINT WINAPI
ImeGetRegisterWordStyle(UINT nItem
, LPSTYLEBUFW lpStyleBuf
)
800 FIXME("(%d, %p): stub\n", nItem
, lpStyleBuf
);
801 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
805 UINT WINAPI
ImeEnumRegisterWord(REGISTERWORDENUMPROCW lpfnEnumProc
,
806 LPCWSTR lpszReading
, DWORD dwStyle
,
807 LPCWSTR lpszRegister
, LPVOID lpData
)
809 FIXME("(%p, %s, %ld, %s, %p): stub\n", lpfnEnumProc
,
810 debugstr_w(lpszReading
), dwStyle
, debugstr_w(lpszRegister
),
812 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
816 BOOL WINAPI
ImeSetCompositionString(HIMC hIMC
, DWORD dwIndex
, LPCVOID lpComp
,
817 DWORD dwCompLen
, LPCVOID lpRead
,
820 LPINPUTCONTEXT lpIMC
;
823 LPIMEPRIVATE myPrivate
;
825 TRACE("(%p, %ld, %p, %ld, %p, %ld):\n",
826 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
829 if (hIMC
!= FROM_X11
)
830 FIXME("PROBLEM: This only sets the wine level string\n");
834 * this sets the composition string in the imm32.dll level
835 * of the composition buffer. we cannot manipulate the xim level
836 * buffer, which means that once the xim level buffer changes again
837 * any call to this function from the application will be lost
840 if (lpRead
&& dwReadLen
)
841 FIXME("Reading string unimplemented\n");
843 lpIMC
= LockRealIMC(hIMC
);
848 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
850 if (dwIndex
== SCS_SETSTR
)
854 if (!myPrivate
->bInComposition
)
856 GenerateIMEMessage(hIMC
, WM_IME_STARTCOMPOSITION
, 0, 0);
857 myPrivate
->bInComposition
= TRUE
;
860 /* clear existing result */
861 newCompStr
= updateResultStr(lpIMC
->hCompStr
, NULL
, 0);
862 ImmDestroyIMCC(lpIMC
->hCompStr
);
863 lpIMC
->hCompStr
= newCompStr
;
867 if (dwCompLen
&& lpComp
)
869 newCompStr
= updateCompStr(lpIMC
->hCompStr
, (LPCWSTR
)lpComp
, dwCompLen
/ sizeof(WCHAR
));
870 ImmDestroyIMCC(lpIMC
->hCompStr
);
871 lpIMC
->hCompStr
= newCompStr
;
873 wParam
= ((const WCHAR
*)lpComp
)[0];
874 flags
|= GCS_COMPCLAUSE
| GCS_COMPATTR
| GCS_DELTASTART
;
878 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
879 ImmDestroyIMCC(lpIMC
->hCompStr
);
880 lpIMC
->hCompStr
= newCompStr
;
884 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, wParam
, flags
);
885 ImmUnlockIMCC(lpIMC
->hPrivate
);
891 DWORD WINAPI
ImeGetImeMenuItems(HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
892 LPIMEMENUITEMINFOW lpImeParentMenu
, LPIMEMENUITEMINFOW lpImeMenu
,
895 FIXME("(%p, %lx %lx %p %p %lx): stub\n", hIMC
, dwFlags
, dwType
,
896 lpImeParentMenu
, lpImeMenu
, dwSize
);
897 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
901 /* Interfaces to XIM and other parts of winex11drv */
903 NTSTATUS
x11drv_ime_set_open_status( UINT open
)
907 imc
= RealIMC(FROM_X11
);
908 ImmSetOpenStatus(imc
, open
);
912 NTSTATUS
x11drv_ime_set_composition_status( UINT open
)
915 LPINPUTCONTEXT lpIMC
;
916 LPIMEPRIVATE myPrivate
;
918 imc
= RealIMC(FROM_X11
);
919 lpIMC
= ImmLockIMC(imc
);
923 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
925 if (open
&& !myPrivate
->bInComposition
)
927 GenerateIMEMessage(imc
, WM_IME_STARTCOMPOSITION
, 0, 0);
929 else if (!open
&& myPrivate
->bInComposition
)
931 ShowWindow(myPrivate
->hwndDefault
, SW_HIDE
);
932 ImmDestroyIMCC(lpIMC
->hCompStr
);
933 lpIMC
->hCompStr
= ImeCreateBlankCompStr();
934 GenerateIMEMessage(imc
, WM_IME_ENDCOMPOSITION
, 0, 0);
936 myPrivate
->bInComposition
= open
;
938 ImmUnlockIMCC(lpIMC
->hPrivate
);
943 NTSTATUS
x11drv_ime_get_cursor_pos( UINT arg
)
945 LPINPUTCONTEXT lpIMC
;
947 LPCOMPOSITIONSTRING compstr
;
952 lpIMC
= LockRealIMC(FROM_X11
);
955 compstr
= ImmLockIMCC(lpIMC
->hCompStr
);
956 rc
= compstr
->dwCursorPos
;
957 ImmUnlockIMCC(lpIMC
->hCompStr
);
959 UnlockRealIMC(FROM_X11
);
963 NTSTATUS
x11drv_ime_set_cursor_pos( UINT pos
)
965 LPINPUTCONTEXT lpIMC
;
966 LPCOMPOSITIONSTRING compstr
;
971 lpIMC
= LockRealIMC(FROM_X11
);
975 compstr
= ImmLockIMCC(lpIMC
->hCompStr
);
978 UnlockRealIMC(FROM_X11
);
982 compstr
->dwCursorPos
= pos
;
983 ImmUnlockIMCC(lpIMC
->hCompStr
);
984 UnlockRealIMC(FROM_X11
);
985 GenerateIMEMessage(FROM_X11
, WM_IME_COMPOSITION
, pos
, GCS_CURSORPOS
);
989 NTSTATUS
x11drv_ime_update_association( UINT arg
)
991 HWND focus
= UlongToHandle( arg
);
993 ImmGetContext(focus
);
995 if (focus
&& hSelectedFrom
)
996 ImmAssociateContext(focus
,RealIMC(FROM_X11
));
1001 NTSTATUS WINAPI
x11drv_ime_set_composition_string( void *param
, ULONG size
)
1003 return ImeSetCompositionString(FROM_X11
, SCS_SETSTR
, param
, size
, NULL
, 0);
1006 NTSTATUS WINAPI
x11drv_ime_set_result( void *params
, ULONG len
)
1008 WCHAR
*lpResult
= params
;
1010 LPINPUTCONTEXT lpIMC
;
1012 LPIMEPRIVATE myPrivate
;
1016 len
/= sizeof(WCHAR
);
1017 if ((focus
= GetFocus()))
1018 x11drv_ime_update_association( HandleToUlong( focus
));
1020 imc
= RealIMC(FROM_X11
);
1021 lpIMC
= ImmLockIMC(imc
);
1025 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
1026 ImmDestroyIMCC(lpIMC
->hCompStr
);
1027 lpIMC
->hCompStr
= newCompStr
;
1029 newCompStr
= updateResultStr(lpIMC
->hCompStr
, lpResult
, len
);
1030 ImmDestroyIMCC(lpIMC
->hCompStr
);
1031 lpIMC
->hCompStr
= newCompStr
;
1033 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
1034 inComp
= myPrivate
->bInComposition
;
1035 ImmUnlockIMCC(lpIMC
->hPrivate
);
1039 ImmSetOpenStatus(imc
, TRUE
);
1040 GenerateIMEMessage(imc
, WM_IME_STARTCOMPOSITION
, 0, 0);
1043 GenerateIMEMessage(imc
, WM_IME_COMPOSITION
, 0, GCS_COMPSTR
);
1044 GenerateIMEMessage(imc
, WM_IME_COMPOSITION
, lpResult
[0], GCS_RESULTSTR
|GCS_RESULTCLAUSE
);
1045 GenerateIMEMessage(imc
, WM_IME_ENDCOMPOSITION
, 0, 0);
1048 ImmSetOpenStatus(imc
, FALSE
);
1055 * Internal functions to help with IME window management
1057 static void PaintDefaultIMEWnd(HIMC hIMC
, HWND hwnd
)
1062 LPCOMPOSITIONSTRING compstr
;
1063 LPBYTE compdata
= NULL
;
1065 MONITORINFO mon_info
;
1067 LPINPUTCONTEXT lpIMC
;
1069 lpIMC
= LockRealIMC(hIMC
);
1073 hdc
= BeginPaint(hwnd
,&ps
);
1075 GetClientRect(hwnd
,&rect
);
1076 FillRect(hdc
, &rect
, (HBRUSH
)(COLOR_WINDOW
+ 1));
1078 compdata
= ImmLockIMCC(lpIMC
->hCompStr
);
1079 compstr
= (LPCOMPOSITIONSTRING
)compdata
;
1081 if (compstr
->dwCompStrLen
&& compstr
->dwCompStrOffset
)
1085 HFONT oldfont
= NULL
;
1087 LPIMEPRIVATE myPrivate
;
1089 CompString
= (LPWSTR
)(compdata
+ compstr
->dwCompStrOffset
);
1090 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
1092 if (myPrivate
->textfont
)
1093 oldfont
= SelectObject(hdc
,myPrivate
->textfont
);
1095 ImmUnlockIMCC(lpIMC
->hPrivate
);
1097 GetTextExtentPoint32W(hdc
, CompString
, compstr
->dwCompStrLen
, &size
);
1103 * How this works based on tests on windows:
1104 * CFS_POINT: then we start our window at the point and grow it as large
1105 * as it needs to be for the string.
1106 * CFS_RECT: we still use the ptCurrentPos as a starting point and our
1107 * window is only as large as we need for the string, but we do not
1108 * grow such that our window exceeds the given rect. Wrapping if
1109 * needed and possible. If our ptCurrentPos is outside of our rect
1110 * then no window is displayed.
1111 * CFS_FORCE_POSITION: appears to behave just like CFS_POINT
1112 * maybe because the default MSIME does not do any IME adjusting.
1114 if (lpIMC
->cfCompForm
.dwStyle
!= CFS_DEFAULT
)
1116 POINT cpt
= lpIMC
->cfCompForm
.ptCurrentPos
;
1117 ClientToScreen(lpIMC
->hWnd
,&cpt
);
1120 rect
.right
= rect
.left
+ pt
.x
;
1121 rect
.bottom
= rect
.top
+ pt
.y
;
1122 monitor
= MonitorFromPoint(cpt
, MONITOR_DEFAULTTOPRIMARY
);
1124 else /* CFS_DEFAULT */
1126 /* Windows places the default IME window in the bottom left */
1127 HWND target
= lpIMC
->hWnd
;
1128 if (!target
) target
= GetFocus();
1130 GetWindowRect(target
,&rect
);
1131 rect
.top
= rect
.bottom
;
1132 rect
.right
= rect
.left
+ pt
.x
+ 20;
1133 rect
.bottom
= rect
.top
+ pt
.y
+ 20;
1135 monitor
= MonitorFromWindow(target
, MONITOR_DEFAULTTOPRIMARY
);
1138 if (lpIMC
->cfCompForm
.dwStyle
== CFS_RECT
)
1141 client
=lpIMC
->cfCompForm
.rcArea
;
1142 MapWindowPoints( lpIMC
->hWnd
, 0, (POINT
*)&client
, 2 );
1143 IntersectRect(&rect
,&rect
,&client
);
1144 /* TODO: Wrap the input if needed */
1147 if (lpIMC
->cfCompForm
.dwStyle
== CFS_DEFAULT
)
1149 /* make sure we are on the desktop */
1150 mon_info
.cbSize
= sizeof(mon_info
);
1151 GetMonitorInfoW(monitor
, &mon_info
);
1153 if (rect
.bottom
> mon_info
.rcWork
.bottom
)
1155 int shift
= rect
.bottom
- mon_info
.rcWork
.bottom
;
1157 rect
.bottom
-= shift
;
1161 rect
.right
-= rect
.left
;
1164 if (rect
.right
> mon_info
.rcWork
.right
)
1166 int shift
= rect
.right
- mon_info
.rcWork
.right
;
1168 rect
.right
-= shift
;
1172 SetWindowPos(hwnd
, HWND_TOPMOST
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, SWP_NOACTIVATE
);
1174 TextOutW(hdc
, offX
,offY
, CompString
, compstr
->dwCompStrLen
);
1177 SelectObject(hdc
,oldfont
);
1180 ImmUnlockIMCC(lpIMC
->hCompStr
);
1183 UnlockRealIMC(hIMC
);
1186 static void UpdateDefaultIMEWindow(HIMC hIMC
, HWND hwnd
)
1188 LPCOMPOSITIONSTRING compstr
;
1189 LPINPUTCONTEXT lpIMC
;
1191 lpIMC
= LockRealIMC(hIMC
);
1195 if (lpIMC
->hCompStr
)
1196 compstr
= ImmLockIMCC(lpIMC
->hCompStr
);
1200 if (compstr
== NULL
|| compstr
->dwCompStrLen
== 0)
1201 ShowWindow(hwnd
,SW_HIDE
);
1204 ShowWindow(hwnd
,SW_SHOWNOACTIVATE
);
1205 RedrawWindow(hwnd
, NULL
, NULL
, RDW_ERASENOW
| RDW_INVALIDATE
);
1208 if (compstr
!= NULL
)
1209 ImmUnlockIMCC(lpIMC
->hCompStr
);
1211 lpIMC
->hWnd
= GetFocus();
1212 UnlockRealIMC(hIMC
);
1215 static void DefaultIMEComposition(HIMC hIMC
, HWND hwnd
, LPARAM lParam
)
1217 TRACE("IME message WM_IME_COMPOSITION 0x%Ix\n", lParam
);
1218 if (!(lParam
& GCS_RESULTSTR
))
1219 UpdateDefaultIMEWindow(hIMC
, hwnd
);
1222 static void DefaultIMEStartComposition(HIMC hIMC
, HWND hwnd
)
1224 TRACE("IME message WM_IME_STARTCOMPOSITION\n");
1225 UpdateDefaultIMEWindow(hIMC
, hwnd
);
1228 static LRESULT
ImeHandleNotify(HIMC hIMC
, HWND hwnd
, UINT msg
, WPARAM wParam
,
1233 case IMN_OPENSTATUSWINDOW
:
1234 FIXME("WM_IME_NOTIFY:IMN_OPENSTATUSWINDOW\n");
1236 case IMN_CLOSESTATUSWINDOW
:
1237 FIXME("WM_IME_NOTIFY:IMN_CLOSESTATUSWINDOW\n");
1239 case IMN_OPENCANDIDATE
:
1240 FIXME("WM_IME_NOTIFY:IMN_OPENCANDIDATE\n");
1242 case IMN_CHANGECANDIDATE
:
1243 FIXME("WM_IME_NOTIFY:IMN_CHANGECANDIDATE\n");
1245 case IMN_CLOSECANDIDATE
:
1246 FIXME("WM_IME_NOTIFY:IMN_CLOSECANDIDATE\n");
1248 case IMN_SETCONVERSIONMODE
:
1249 FIXME("WM_IME_NOTIFY:IMN_SETCONVERSIONMODE\n");
1251 case IMN_SETSENTENCEMODE
:
1252 FIXME("WM_IME_NOTIFY:IMN_SETSENTENCEMODE\n");
1254 case IMN_SETOPENSTATUS
:
1255 TRACE("WM_IME_NOTIFY:IMN_SETOPENSTATUS\n");
1257 case IMN_SETCANDIDATEPOS
:
1258 FIXME("WM_IME_NOTIFY:IMN_SETCANDIDATEPOS\n");
1260 case IMN_SETCOMPOSITIONFONT
:
1261 FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONFONT\n");
1263 case IMN_SETCOMPOSITIONWINDOW
:
1264 FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONWINDOW\n");
1267 FIXME("WM_IME_NOTIFY:IMN_GUIDELINE\n");
1269 case IMN_SETSTATUSWINDOWPOS
:
1270 FIXME("WM_IME_NOTIFY:IMN_SETSTATUSWINDOWPOS\n");
1273 FIXME("WM_IME_NOTIFY:<Unknown 0x%Ix>\n",wParam
);
1279 static LRESULT WINAPI
IME_WindowProc(HWND hwnd
, UINT msg
, WPARAM wParam
,
1285 TRACE("Incoming Message 0x%x (0x%08Ix, 0x%08Ix)\n", msg
, wParam
, lParam
);
1288 * Each UI window contains the current Input Context.
1289 * This Input Context can be obtained by calling GetWindowLong
1290 * with IMMGWL_IMC when the UI window receives a WM_IME_xxx message.
1291 * The UI window can refer to this Input Context and handles the
1295 hIMC
= (HIMC
)GetWindowLongPtrW(hwnd
,IMMGWL_IMC
);
1297 hIMC
= RealIMC(FROM_X11
);
1299 /* if we have no hIMC there are many messages we cannot process */
1303 case WM_IME_STARTCOMPOSITION
:
1304 case WM_IME_ENDCOMPOSITION
:
1305 case WM_IME_COMPOSITION
:
1307 case WM_IME_CONTROL
:
1308 case WM_IME_COMPOSITIONFULL
:
1321 LPIMEPRIVATE myPrivate
;
1322 LPINPUTCONTEXT lpIMC
;
1324 SetWindowTextA(hwnd
,"Wine Ime Active");
1326 lpIMC
= LockRealIMC(hIMC
);
1329 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
1330 myPrivate
->hwndDefault
= hwnd
;
1331 ImmUnlockIMCC(lpIMC
->hPrivate
);
1333 UnlockRealIMC(hIMC
);
1338 PaintDefaultIMEWnd(hIMC
, hwnd
);
1346 SetFocus((HWND
)wParam
);
1348 FIXME("Received focus, should never have focus\n");
1350 case WM_IME_COMPOSITION
:
1351 DefaultIMEComposition(hIMC
, hwnd
, lParam
);
1353 case WM_IME_STARTCOMPOSITION
:
1354 DefaultIMEStartComposition(hIMC
, hwnd
);
1356 case WM_IME_ENDCOMPOSITION
:
1357 TRACE("IME message %s, 0x%Ix, 0x%Ix\n",
1358 "WM_IME_ENDCOMPOSITION", wParam
, lParam
);
1359 ShowWindow(hwnd
,SW_HIDE
);
1362 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_IME_SELECT", wParam
, lParam
);
1364 case WM_IME_CONTROL
:
1365 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_IME_CONTROL", wParam
, lParam
);
1369 rc
= ImeHandleNotify(hIMC
,hwnd
,msg
,wParam
,lParam
);
1372 TRACE("Non-standard message 0x%x\n",msg
);
1374 /* check the MSIME messages */
1375 if (msg
== WM_MSIME_SERVICE
)
1377 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_SERVICE", wParam
, lParam
);
1380 else if (msg
== WM_MSIME_RECONVERTOPTIONS
)
1382 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_RECONVERTOPTIONS", wParam
, lParam
);
1384 else if (msg
== WM_MSIME_MOUSE
)
1386 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_MOUSE", wParam
, lParam
);
1388 else if (msg
== WM_MSIME_RECONVERTREQUEST
)
1390 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_RECONVERTREQUEST", wParam
, lParam
);
1392 else if (msg
== WM_MSIME_RECONVERT
)
1394 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_RECONVERT", wParam
, lParam
);
1396 else if (msg
== WM_MSIME_QUERYPOSITION
)
1398 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_QUERYPOSITION", wParam
, lParam
);
1400 else if (msg
== WM_MSIME_DOCUMENTFEED
)
1402 TRACE("IME message %s, 0x%Ix, 0x%Ix\n","WM_MSIME_DOCUMENTFEED", wParam
, lParam
);
1404 /* DefWndProc if not an IME message */
1405 if (!rc
&& !((msg
>= WM_IME_STARTCOMPOSITION
&& msg
<= WM_IME_KEYLAST
) ||
1406 (msg
>= WM_IME_SETCONTEXT
&& msg
<= WM_IME_KEYUP
)))
1407 rc
= DefWindowProcW(hwnd
,msg
,wParam
,lParam
);