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;
78 static BOOL hXIMPresent
= FALSE
;
81 static UINT WM_MSIME_SERVICE
;
82 static UINT WM_MSIME_RECONVERTOPTIONS
;
83 static UINT WM_MSIME_MOUSE
;
84 static UINT WM_MSIME_RECONVERTREQUEST
;
85 static UINT WM_MSIME_RECONVERT
;
86 static UINT WM_MSIME_QUERYPOSITION
;
87 static UINT WM_MSIME_DOCUMENTFEED
;
89 static LRESULT WINAPI
IME_WindowProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
,
91 static void UpdateDataInDefaultIMEWindow(HIMC hHIMC
, HWND hwnd
, BOOL showable
);
93 static HIMC
RealIMC(HIMC hIMC
)
98 HWND wnd
= GetFocus();
99 HIMC winHimc
= ImmGetContext(wnd
);
100 for (i
= 0; i
< hSelectedCount
; i
++)
101 if (winHimc
== hSelectedFrom
[i
])
109 static LPINPUTCONTEXT
LockRealIMC(HIMC hIMC
)
111 HIMC real_imc
= RealIMC(hIMC
);
113 return (LPINPUTCONTEXT
)ImmLockIMC(real_imc
);
118 static BOOL
UnlockRealIMC(HIMC hIMC
)
120 HIMC real_imc
= RealIMC(hIMC
);
122 return ImmUnlockIMC(real_imc
);
127 static HIMCC
ImeCreateBlankCompStr(void)
130 LPCOMPOSITIONSTRING ptr
;
131 rc
= ImmCreateIMCC(sizeof(COMPOSITIONSTRING
));
132 ptr
= (LPCOMPOSITIONSTRING
)ImmLockIMCC(rc
);
133 memset(ptr
,0,sizeof(COMPOSITIONSTRING
));
134 ptr
->dwSize
= sizeof(COMPOSITIONSTRING
);
139 static int updateField(DWORD origLen
, DWORD origOffset
, DWORD currentOffset
,
140 LPBYTE target
, LPBYTE source
, DWORD
* lenParam
,
141 DWORD
* offsetParam
, BOOL wchars
)
143 if (origLen
> 0 && origOffset
> 0)
145 int truelen
= origLen
;
147 truelen
*= sizeof(WCHAR
);
149 memcpy(&target
[currentOffset
], &source
[origOffset
], truelen
);
152 *offsetParam
= currentOffset
;
153 currentOffset
+= truelen
;
155 return currentOffset
;
158 static HIMCC
updateCompStr(HIMCC old
, LPWSTR compstr
, DWORD len
)
160 /* we need to make sure the CompStr, CompClaus and CompAttr fields are all
164 LPBYTE newdata
= NULL
;
165 LPBYTE olddata
= NULL
;
166 LPCOMPOSITIONSTRING new_one
;
167 LPCOMPOSITIONSTRING lpcs
= NULL
;
168 INT current_offset
= 0;
170 TRACE("%s, %i\n",debugstr_wn(compstr
,len
),len
);
172 if (old
== NULL
&& compstr
== NULL
&& len
== 0)
177 olddata
= ImmLockIMCC(old
);
178 lpcs
= (LPCOMPOSITIONSTRING
)olddata
;
181 needed_size
= sizeof(COMPOSITIONSTRING
) + len
* sizeof(WCHAR
) +
182 len
+ sizeof(DWORD
) * 2;
186 needed_size
+= lpcs
->dwCompReadAttrLen
;
187 needed_size
+= lpcs
->dwCompReadClauseLen
;
188 needed_size
+= lpcs
->dwCompReadStrLen
* sizeof(DWORD
);
189 needed_size
+= lpcs
->dwResultReadClauseLen
;
190 needed_size
+= lpcs
->dwResultReadStrLen
* sizeof(DWORD
);
191 needed_size
+= lpcs
->dwResultClauseLen
;
192 needed_size
+= lpcs
->dwResultStrLen
* sizeof(DWORD
);
193 needed_size
+= lpcs
->dwPrivateSize
;
195 rc
= ImmCreateIMCC(needed_size
);
196 newdata
= ImmLockIMCC(rc
);
197 new_one
= (LPCOMPOSITIONSTRING
)newdata
;
199 new_one
->dwSize
= needed_size
;
200 current_offset
= sizeof(COMPOSITIONSTRING
);
203 current_offset
= updateField(lpcs
->dwCompReadAttrLen
,
204 lpcs
->dwCompReadAttrOffset
,
205 current_offset
, newdata
, olddata
,
206 &new_one
->dwCompReadAttrLen
,
207 &new_one
->dwCompReadAttrOffset
, FALSE
);
209 current_offset
= updateField(lpcs
->dwCompReadClauseLen
,
210 lpcs
->dwCompReadClauseOffset
,
211 current_offset
, newdata
, olddata
,
212 &new_one
->dwCompReadClauseLen
,
213 &new_one
->dwCompReadClauseOffset
, FALSE
);
215 current_offset
= updateField(lpcs
->dwCompReadStrLen
,
216 lpcs
->dwCompReadStrOffset
,
217 current_offset
, newdata
, olddata
,
218 &new_one
->dwCompReadStrLen
,
219 &new_one
->dwCompReadStrOffset
, TRUE
);
221 /* new CompAttr, CompClause, CompStr, dwCursorPos */
222 new_one
->dwDeltaStart
= 0;
224 current_offset
= updateField(lpcs
->dwResultReadClauseLen
,
225 lpcs
->dwResultReadClauseOffset
,
226 current_offset
, newdata
, olddata
,
227 &new_one
->dwResultReadClauseLen
,
228 &new_one
->dwResultReadClauseOffset
, FALSE
);
230 current_offset
= updateField(lpcs
->dwResultReadStrLen
,
231 lpcs
->dwResultReadStrOffset
,
232 current_offset
, newdata
, olddata
,
233 &new_one
->dwResultReadStrLen
,
234 &new_one
->dwResultReadStrOffset
, TRUE
);
236 current_offset
= updateField(lpcs
->dwResultClauseLen
,
237 lpcs
->dwResultClauseOffset
,
238 current_offset
, newdata
, olddata
,
239 &new_one
->dwResultClauseLen
,
240 &new_one
->dwResultClauseOffset
, FALSE
);
242 current_offset
= updateField(lpcs
->dwResultStrLen
,
243 lpcs
->dwResultStrOffset
,
244 current_offset
, newdata
, olddata
,
245 &new_one
->dwResultStrLen
,
246 &new_one
->dwResultStrOffset
, TRUE
);
248 current_offset
= updateField(lpcs
->dwPrivateSize
,
249 lpcs
->dwPrivateOffset
,
250 current_offset
, newdata
, olddata
,
251 &new_one
->dwPrivateSize
,
252 &new_one
->dwPrivateOffset
, FALSE
);
257 new_one
->dwCompAttrLen
= len
;
260 new_one
->dwCompAttrOffset
= current_offset
;
261 memset(&newdata
[current_offset
],ATTR_INPUT
,len
);
262 current_offset
+= len
;
268 new_one
->dwCompClauseLen
= sizeof(DWORD
) * 2;
269 new_one
->dwCompClauseOffset
= current_offset
;
270 *(DWORD
*)(&newdata
[current_offset
]) = 0;
271 current_offset
+= sizeof(DWORD
);
272 *(DWORD
*)(&newdata
[current_offset
]) = len
;
273 current_offset
+= sizeof(DWORD
);
277 new_one
->dwCompStrLen
= len
;
280 new_one
->dwCompStrOffset
= current_offset
;
281 memcpy(&newdata
[current_offset
],compstr
,len
*sizeof(WCHAR
));
285 new_one
->dwCursorPos
= len
;
294 static HIMCC
updateResultStr(HIMCC old
, LPWSTR resultstr
, DWORD len
)
296 /* we need to make sure the ResultStr and ResultClause fields are all
300 LPBYTE newdata
= NULL
;
301 LPBYTE olddata
= NULL
;
302 LPCOMPOSITIONSTRING new_one
;
303 LPCOMPOSITIONSTRING lpcs
= NULL
;
304 INT current_offset
= 0;
306 TRACE("%s, %i\n",debugstr_wn(resultstr
,len
),len
);
308 if (old
== NULL
&& resultstr
== NULL
&& len
== 0)
313 olddata
= ImmLockIMCC(old
);
314 lpcs
= (LPCOMPOSITIONSTRING
)olddata
;
317 needed_size
= sizeof(COMPOSITIONSTRING
) + len
* sizeof(WCHAR
) +
322 needed_size
+= lpcs
->dwCompReadAttrLen
;
323 needed_size
+= lpcs
->dwCompReadClauseLen
;
324 needed_size
+= lpcs
->dwCompReadStrLen
* sizeof(DWORD
);
325 needed_size
+= lpcs
->dwCompAttrLen
;
326 needed_size
+= lpcs
->dwCompClauseLen
;
327 needed_size
+= lpcs
->dwCompStrLen
* sizeof(DWORD
);
328 needed_size
+= lpcs
->dwResultReadClauseLen
;
329 needed_size
+= lpcs
->dwResultReadStrLen
* sizeof(DWORD
);
330 needed_size
+= lpcs
->dwPrivateSize
;
332 rc
= ImmCreateIMCC(needed_size
);
333 newdata
= ImmLockIMCC(rc
);
334 new_one
= (LPCOMPOSITIONSTRING
)newdata
;
336 new_one
->dwSize
= needed_size
;
337 current_offset
= sizeof(COMPOSITIONSTRING
);
340 current_offset
= updateField(lpcs
->dwCompReadAttrLen
,
341 lpcs
->dwCompReadAttrOffset
,
342 current_offset
, newdata
, olddata
,
343 &new_one
->dwCompReadAttrLen
,
344 &new_one
->dwCompReadAttrOffset
, FALSE
);
346 current_offset
= updateField(lpcs
->dwCompReadClauseLen
,
347 lpcs
->dwCompReadClauseOffset
,
348 current_offset
, newdata
, olddata
,
349 &new_one
->dwCompReadClauseLen
,
350 &new_one
->dwCompReadClauseOffset
, FALSE
);
352 current_offset
= updateField(lpcs
->dwCompReadStrLen
,
353 lpcs
->dwCompReadStrOffset
,
354 current_offset
, newdata
, olddata
,
355 &new_one
->dwCompReadStrLen
,
356 &new_one
->dwCompReadStrOffset
, TRUE
);
358 current_offset
= updateField(lpcs
->dwCompAttrLen
,
359 lpcs
->dwCompAttrOffset
,
360 current_offset
, newdata
, olddata
,
361 &new_one
->dwCompAttrLen
,
362 &new_one
->dwCompAttrOffset
, FALSE
);
364 current_offset
= updateField(lpcs
->dwCompClauseLen
,
365 lpcs
->dwCompClauseOffset
,
366 current_offset
, newdata
, olddata
,
367 &new_one
->dwCompClauseLen
,
368 &new_one
->dwCompClauseOffset
, FALSE
);
370 current_offset
= updateField(lpcs
->dwCompStrLen
,
371 lpcs
->dwCompStrOffset
,
372 current_offset
, newdata
, olddata
,
373 &new_one
->dwCompStrLen
,
374 &new_one
->dwCompStrOffset
, TRUE
);
376 new_one
->dwCursorPos
= lpcs
->dwCursorPos
;
377 new_one
->dwDeltaStart
= 0;
379 current_offset
= updateField(lpcs
->dwResultReadClauseLen
,
380 lpcs
->dwResultReadClauseOffset
,
381 current_offset
, newdata
, olddata
,
382 &new_one
->dwResultReadClauseLen
,
383 &new_one
->dwResultReadClauseOffset
, FALSE
);
385 current_offset
= updateField(lpcs
->dwResultReadStrLen
,
386 lpcs
->dwResultReadStrOffset
,
387 current_offset
, newdata
, olddata
,
388 &new_one
->dwResultReadStrLen
,
389 &new_one
->dwResultReadStrOffset
, TRUE
);
391 /* new ResultClause , ResultStr */
393 current_offset
= updateField(lpcs
->dwPrivateSize
,
394 lpcs
->dwPrivateOffset
,
395 current_offset
, newdata
, olddata
,
396 &new_one
->dwPrivateSize
,
397 &new_one
->dwPrivateOffset
, FALSE
);
404 new_one
->dwResultClauseLen
= sizeof(DWORD
) * 2;
405 new_one
->dwResultClauseOffset
= current_offset
;
406 *(DWORD
*)(&newdata
[current_offset
]) = 0;
407 current_offset
+= sizeof(DWORD
);
408 *(DWORD
*)(&newdata
[current_offset
]) = len
;
409 current_offset
+= sizeof(DWORD
);
413 new_one
->dwResultStrLen
= len
;
416 new_one
->dwResultStrOffset
= current_offset
;
417 memcpy(&newdata
[current_offset
],resultstr
,len
*sizeof(WCHAR
));
426 static void GenerateIMEMessage(HIMC hIMC
, UINT msg
, WPARAM wParam
,
429 LPINPUTCONTEXT lpIMC
;
430 LPTRANSMSG lpTransMsg
;
432 lpIMC
= LockRealIMC(hIMC
);
436 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
, (lpIMC
->dwNumMsgBuf
+ 1) *
441 lpTransMsg
= (LPTRANSMSG
)ImmLockIMCC(lpIMC
->hMsgBuf
);
445 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
446 lpTransMsg
->message
= msg
;
447 lpTransMsg
->wParam
= wParam
;
448 lpTransMsg
->lParam
= lParam
;
450 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
451 lpIMC
->dwNumMsgBuf
++;
453 ImmGenerateMessage(RealIMC(hIMC
));
457 static void GenerateIMECHARMessages(HIMC hIMC
, LPWSTR String
, DWORD length
)
459 LPINPUTCONTEXT lpIMC
;
460 LPTRANSMSG lpTransMsg
;
466 lpIMC
= LockRealIMC(hIMC
);
470 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
,
471 (lpIMC
->dwNumMsgBuf
+ length
) *
476 lpTransMsg
= (LPTRANSMSG
)ImmLockIMCC(lpIMC
->hMsgBuf
);
480 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
481 for (i
= 0; i
< length
; i
++)
483 lpTransMsg
->message
= WM_IME_CHAR
;
484 lpTransMsg
->wParam
= String
[i
];
485 lpTransMsg
->lParam
= 1;
489 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
490 lpIMC
->dwNumMsgBuf
+=length
;
492 ImmGenerateMessage(RealIMC(hIMC
));
496 static BOOL
IME_RemoveFromSelected(HIMC hIMC
)
499 for (i
= 0; i
< hSelectedCount
; i
++)
500 if (hSelectedFrom
[i
] == hIMC
)
502 if (i
< hSelectedCount
- 1)
503 memcpy(&hSelectedFrom
[i
], &hSelectedFrom
[i
+1], (hSelectedCount
- i
- 1)*sizeof(HIMC
));
510 static void IME_AddToSelected(HIMC hIMC
)
514 hSelectedFrom
= HeapReAlloc(GetProcessHeap(), 0, hSelectedFrom
, hSelectedCount
*sizeof(HIMC
));
516 hSelectedFrom
= HeapAlloc(GetProcessHeap(), 0, sizeof(HIMC
));
517 hSelectedFrom
[hSelectedCount
-1] = hIMC
;
520 BOOL WINAPI
ImeInquire(LPIMEINFO lpIMEInfo
, LPWSTR lpszUIClass
,
526 ERR("No XIM in the back end\n");
529 lpIMEInfo
->dwPrivateDataSize
= sizeof (IMEPRIVATE
);
530 lpIMEInfo
->fdwProperty
= IME_PROP_UNICODE
| IME_PROP_AT_CARET
;
531 lpIMEInfo
->fdwConversionCaps
= IME_CMODE_NATIVE
;
532 lpIMEInfo
->fdwSentenceCaps
= IME_SMODE_AUTOMATIC
;
533 lpIMEInfo
->fdwUICaps
= UI_CAP_2700
;
534 /* Tell App we cannot accept ImeSetCompositionString calls */
535 lpIMEInfo
->fdwSCSCaps
= 0;
536 lpIMEInfo
->fdwSelectCaps
= SELECT_CAP_CONVERSION
;
538 lstrcpyW(lpszUIClass
,UI_CLASS_NAME
);
543 BOOL WINAPI
ImeConfigure(HKL hKL
,HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
545 FIXME("(%p, %p, %d, %p): stub\n", hKL
, hWnd
, dwMode
, lpData
);
546 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
550 DWORD WINAPI
ImeConversionList(HIMC hIMC
, LPCWSTR lpSource
,
551 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
, UINT uFlag
)
554 FIXME("(%p, %s, %p, %d, %d): stub\n", hIMC
, debugstr_w(lpSource
),
555 lpCandList
, dwBufLen
, uFlag
);
556 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
560 BOOL WINAPI
ImeDestroy(UINT uForce
)
563 HeapFree(GetProcessHeap(),0,hSelectedFrom
);
564 hSelectedFrom
= NULL
;
569 LRESULT WINAPI
ImeEscape(HIMC hIMC
, UINT uSubFunc
, LPVOID lpData
)
571 FIXME("(%p, %d, %p): stub\n", hIMC
, uSubFunc
, lpData
);
572 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
576 BOOL WINAPI
ImeProcessKey(HIMC hIMC
, UINT vKey
, LPARAM lKeyData
,
577 CONST LPBYTE lpbKeyState
)
579 /* See the comment at the head of this file */
580 TRACE("We do no processing via this route\n");
584 BOOL WINAPI
ImeSelect(HIMC hIMC
, BOOL fSelect
)
586 LPINPUTCONTEXT lpIMC
;
587 TRACE("%p %s\n",hIMC
,(fSelect
)?"TRUE":"FALSE");
589 if (hIMC
== FROM_X11
)
591 ERR("ImeSelect should never be called from X11\n");
597 ERR("No XIM in the back end\n");
606 return IME_RemoveFromSelected(hIMC
);
608 IME_AddToSelected(hIMC
);
610 /* Initialize our structures */
611 lpIMC
= LockRealIMC(hIMC
);
614 LPIMEPRIVATE myPrivate
;
615 myPrivate
= (LPIMEPRIVATE
)ImmLockIMCC(lpIMC
->hPrivate
);
616 myPrivate
->bInComposition
= FALSE
;
617 myPrivate
->bInternalState
= FALSE
;
618 myPrivate
->textfont
= NULL
;
619 myPrivate
->hwndDefault
= NULL
;
620 ImmUnlockIMCC(lpIMC
->hPrivate
);
627 BOOL WINAPI
ImeSetActiveContext(HIMC hIMC
,BOOL fFlag
)
633 UINT WINAPI
ImeToAsciiEx (UINT uVKey
, UINT uScanCode
,
634 CONST LPBYTE lpbKeyState
, LPDWORD lpdwTransKey
,
635 UINT fuState
, HIMC hIMC
)
637 /* See the comment at the head of this file */
638 TRACE("We do no processing via this route\n");
642 BOOL WINAPI
NotifyIME(HIMC hIMC
, DWORD dwAction
, DWORD dwIndex
, DWORD dwValue
)
645 LPINPUTCONTEXT lpIMC
;
647 TRACE("%p %i %i %i\n",hIMC
,dwAction
,dwIndex
,dwValue
);
649 lpIMC
= LockRealIMC(hIMC
);
655 case NI_OPENCANDIDATE
: FIXME("NI_OPENCANDIDATE\n"); break;
656 case NI_CLOSECANDIDATE
: FIXME("NI_CLOSECANDIDATE\n"); break;
657 case NI_SELECTCANDIDATESTR
: FIXME("NI_SELECTCANDIDATESTR\n"); break;
658 case NI_CHANGECANDIDATELIST
: FIXME("NI_CHANGECANDIDATELIST\n"); break;
659 case NI_SETCANDIDATE_PAGESTART
: FIXME("NI_SETCANDIDATE_PAGESTART\n"); break;
660 case NI_SETCANDIDATE_PAGESIZE
: FIXME("NI_SETCANDIDATE_PAGESIZE\n"); break;
661 case NI_CONTEXTUPDATED
:
662 FIXME("NI_CONTEXTUPDATED:");
665 case IMC_SETCOMPOSITIONWINDOW
: FIXME("IMC_SETCOMPOSITIONWINDOW\n"); break;
666 case IMC_SETCONVERSIONMODE
: FIXME("IMC_SETCONVERSIONMODE\n"); break;
667 case IMC_SETSENTENCEMODE
: FIXME("IMC_SETSENTENCEMODE\n"); break;
668 case IMC_SETCANDIDATEPOS
: FIXME("IMC_SETCANDIDATEPOS\n"); break;
669 case IMC_SETCOMPOSITIONFONT
:
671 LPIMEPRIVATE myPrivate
;
672 TRACE("IMC_SETCOMPOSITIONFONT\n");
674 myPrivate
= (LPIMEPRIVATE
)ImmLockIMCC(lpIMC
->hPrivate
);
675 if (myPrivate
->textfont
)
677 DeleteObject(myPrivate
->textfont
);
678 myPrivate
->textfont
= NULL
;
680 myPrivate
->textfont
= CreateFontIndirectW(&lpIMC
->lfFont
.W
);
681 ImmUnlockIMCC(lpIMC
->hPrivate
);
684 case IMC_SETOPENSTATUS
:
686 LPIMEPRIVATE myPrivate
;
687 TRACE("IMC_SETOPENSTATUS\n");
689 myPrivate
= (LPIMEPRIVATE
)ImmLockIMCC(lpIMC
->hPrivate
);
690 if (lpIMC
->fOpen
!= myPrivate
->bInternalState
&&
691 myPrivate
->bInComposition
)
693 if(lpIMC
->fOpen
== FALSE
)
695 X11DRV_ForceXIMReset(lpIMC
->hWnd
);
696 GenerateIMEMessage(hIMC
,WM_IME_ENDCOMPOSITION
,0,0);
697 myPrivate
->bInComposition
= FALSE
;
701 GenerateIMEMessage(hIMC
,WM_IME_STARTCOMPOSITION
,0,0);
702 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, 0, 0);
705 myPrivate
->bInternalState
= lpIMC
->fOpen
;
709 default: FIXME("Unknown\n"); break;
712 case NI_COMPOSITIONSTR
:
713 TRACE("NI_COMPOSITIONSTR:");
721 LPCOMPOSITIONSTRING cs
= NULL
;
723 LPIMEPRIVATE myPrivate
;
725 TRACE("CPS_COMPLETE\n");
727 /* clear existing result */
728 newCompStr
= updateResultStr(lpIMC
->hCompStr
, NULL
, 0);
730 ImmDestroyIMCC(lpIMC
->hCompStr
);
731 lpIMC
->hCompStr
= newCompStr
;
735 cdata
= ImmLockIMCC(lpIMC
->hCompStr
);
736 cs
= (LPCOMPOSITIONSTRING
)cdata
;
737 cplen
= cs
->dwCompStrLen
;
738 cpstr
= (LPWSTR
)&(cdata
[cs
->dwCompStrOffset
]);
739 ImmUnlockIMCC(lpIMC
->hCompStr
);
743 WCHAR param
= cpstr
[0];
745 newCompStr
= updateResultStr(lpIMC
->hCompStr
, cpstr
, cplen
);
746 ImmDestroyIMCC(lpIMC
->hCompStr
);
747 lpIMC
->hCompStr
= newCompStr
;
748 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
749 ImmDestroyIMCC(lpIMC
->hCompStr
);
750 lpIMC
->hCompStr
= newCompStr
;
752 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, 0,
755 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, param
,
756 GCS_RESULTSTR
|GCS_RESULTCLAUSE
);
759 GenerateIMEMessage(hIMC
,WM_IME_ENDCOMPOSITION
, 0, 0);
761 myPrivate
= (LPIMEPRIVATE
)ImmLockIMCC(lpIMC
->hPrivate
);
762 myPrivate
->bInComposition
= FALSE
;
763 ImmUnlockIMCC(lpIMC
->hPrivate
);
768 case CPS_CONVERT
: FIXME("CPS_CONVERT\n"); break;
769 case CPS_REVERT
: FIXME("CPS_REVERT\n"); break;
773 LPCOMPOSITIONSTRING lpCompStr
;
775 TRACE("CPS_CANCEL\n");
777 X11DRV_ForceXIMReset(lpIMC
->hWnd
);
779 lpCompStr
= ImmLockIMCC(lpIMC
->hCompStr
);
780 send
= (lpCompStr
->dwCompStrLen
!= 0);
781 ImmUnlockIMCC(lpIMC
->hCompStr
);
786 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
787 ImmDestroyIMCC(lpIMC
->hCompStr
);
788 lpIMC
->hCompStr
= newCompStr
;
789 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, 0, GCS_COMPSTR
);
794 default: FIXME("Unknown\n"); break;
797 default: FIXME("Unknown Message\n"); break;
804 BOOL WINAPI
ImeRegisterWord(LPCWSTR lpszReading
, DWORD dwStyle
,
805 LPCWSTR lpszRegister
)
807 FIXME("(%s, %d, %s): stub\n", debugstr_w(lpszReading
), dwStyle
,
808 debugstr_w(lpszRegister
));
809 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
813 BOOL WINAPI
ImeUnregisterWord(LPCWSTR lpszReading
, DWORD dwStyle
,
814 LPCWSTR lpszUnregister
)
816 FIXME("(%s, %d, %s): stub\n", debugstr_w(lpszReading
), dwStyle
,
817 debugstr_w(lpszUnregister
));
818 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
822 UINT WINAPI
ImeGetRegisterWordStyle(UINT nItem
, LPSTYLEBUFW lpStyleBuf
)
824 FIXME("(%d, %p): stub\n", nItem
, lpStyleBuf
);
825 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
829 UINT WINAPI
ImeEnumRegisterWord(REGISTERWORDENUMPROCW lpfnEnumProc
,
830 LPCWSTR lpszReading
, DWORD dwStyle
,
831 LPCWSTR lpszRegister
, LPVOID lpData
)
833 FIXME("(%p, %s, %d, %s, %p): stub\n", lpfnEnumProc
,
834 debugstr_w(lpszReading
), dwStyle
, debugstr_w(lpszRegister
),
836 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
840 BOOL WINAPI
ImeSetCompositionString(HIMC hIMC
, DWORD dwIndex
, LPCVOID lpComp
,
841 DWORD dwCompLen
, LPCVOID lpRead
,
844 LPINPUTCONTEXT lpIMC
;
847 LPIMEPRIVATE myPrivate
;
849 TRACE("(%p, %d, %p, %d, %p, %d):\n",
850 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
853 if (hIMC
!= FROM_X11
)
854 FIXME("PROBLEM: This only sets the wine level string\n");
858 * this sets the composition string in the imm32.dll level
859 * of the composition buffer. we cannot manipulate the xim level
860 * buffer, which means that once the xim level buffer changes again
861 * any call to this function from the application will be lost
864 if (lpRead
&& dwReadLen
)
865 FIXME("Reading string unimplemented\n");
867 lpIMC
= LockRealIMC(hIMC
);
872 myPrivate
= (LPIMEPRIVATE
)ImmLockIMCC(lpIMC
->hPrivate
);
874 if (dwIndex
== SCS_SETSTR
)
878 if (!myPrivate
->bInComposition
)
880 GenerateIMEMessage(hIMC
, WM_IME_STARTCOMPOSITION
, 0, 0);
881 myPrivate
->bInComposition
= TRUE
;
886 if (dwCompLen
&& lpComp
)
888 newCompStr
= updateCompStr(lpIMC
->hCompStr
, (LPWSTR
)lpComp
, dwCompLen
/ sizeof(WCHAR
));
889 ImmDestroyIMCC(lpIMC
->hCompStr
);
890 lpIMC
->hCompStr
= newCompStr
;
892 wParam
= ((const WCHAR
*)lpComp
)[0];
893 flags
|= GCS_COMPCLAUSE
| GCS_COMPATTR
| GCS_DELTASTART
;
897 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
898 ImmDestroyIMCC(lpIMC
->hCompStr
);
899 lpIMC
->hCompStr
= newCompStr
;
903 UpdateDataInDefaultIMEWindow(hIMC
, myPrivate
->hwndDefault
,FALSE
);
905 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, wParam
, flags
);
906 ImmUnlockIMCC(lpIMC
->hPrivate
);
912 DWORD WINAPI
ImeGetImeMenuItems(HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
913 LPIMEMENUITEMINFOW lpImeParentMenu
, LPIMEMENUITEMINFOW lpImeMenu
,
916 FIXME("(%p, %x %x %p %p %x): stub\n", hIMC
, dwFlags
, dwType
,
917 lpImeParentMenu
, lpImeMenu
, dwSize
);
918 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
922 /* Interfaces to XIM and other parts of winex11drv */
924 void IME_RegisterClasses(HINSTANCE hImeInst
)
927 ZeroMemory(&wndClass
, sizeof(WNDCLASSW
));
928 wndClass
.style
= CS_GLOBALCLASS
| CS_IME
| CS_HREDRAW
| CS_VREDRAW
;
929 wndClass
.lpfnWndProc
= (WNDPROC
) IME_WindowProc
;
930 wndClass
.cbClsExtra
= 0;
931 wndClass
.cbWndExtra
= 2 * sizeof(LONG
);
932 wndClass
.hInstance
= hImeInst
;
933 wndClass
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
934 wndClass
.hIcon
= LoadIconW(NULL
, (LPWSTR
)IDI_APPLICATION
);
935 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
936 wndClass
.lpszMenuName
= 0;
937 wndClass
.lpszClassName
= UI_CLASS_NAME
;
939 RegisterClassW(&wndClass
);
941 WM_MSIME_SERVICE
= RegisterWindowMessageA("MSIMEService");
942 WM_MSIME_RECONVERTOPTIONS
= RegisterWindowMessageA("MSIMEReconvertOptions");
943 WM_MSIME_MOUSE
= RegisterWindowMessageA("MSIMEMouseOperation");
944 WM_MSIME_RECONVERTREQUEST
= RegisterWindowMessageA("MSIMEReconvertRequest");
945 WM_MSIME_RECONVERT
= RegisterWindowMessageA("MSIMEReconvert");
946 WM_MSIME_QUERYPOSITION
= RegisterWindowMessageA("MSIMEQueryPosition");
947 WM_MSIME_DOCUMENTFEED
= RegisterWindowMessageA("MSIMEDocumentFeed");
950 void IME_UnregisterClasses(HINSTANCE hImeInst
)
952 UnregisterClassW(UI_CLASS_NAME
, hImeInst
);
955 void IME_SetOpenStatus(BOOL fOpen
)
957 LPINPUTCONTEXT lpIMC
;
958 LPIMEPRIVATE myPrivate
;
960 lpIMC
= LockRealIMC(FROM_X11
);
964 myPrivate
= (LPIMEPRIVATE
)ImmLockIMCC(lpIMC
->hPrivate
);
966 if (myPrivate
->bInternalState
&& fOpen
== FALSE
)
968 ShowWindow(myPrivate
->hwndDefault
, SW_HIDE
);
969 ImmDestroyIMCC(lpIMC
->hCompStr
);
970 lpIMC
->hCompStr
= ImeCreateBlankCompStr();
973 ImmUnlockIMCC(lpIMC
->hPrivate
);
974 UnlockRealIMC(FROM_X11
);
976 if (myPrivate
->bInComposition
&& fOpen
== FALSE
)
978 GenerateIMEMessage(FROM_X11
, WM_IME_ENDCOMPOSITION
, 0, 0);
979 myPrivate
->bInComposition
= FALSE
;
982 if (!myPrivate
->bInternalState
&& fOpen
== TRUE
)
983 ImmSetOpenStatus(RealIMC(FROM_X11
), fOpen
);
986 void IME_XIMPresent(BOOL present
)
988 hXIMPresent
= present
;
991 LRESULT
IME_SendMessageToSelectedHWND(UINT msg
, WPARAM wParam
, LPARAM lParam
)
993 LPINPUTCONTEXT lpIMC
;
999 lpIMC
= LockRealIMC(FROM_X11
);
1001 rc
= SendMessageW(lpIMC
->hWnd
,msg
,wParam
,lParam
);
1003 UnlockRealIMC(FROM_X11
);
1007 INT
IME_GetCursorPos()
1009 LPINPUTCONTEXT lpIMC
;
1011 LPCOMPOSITIONSTRING compstr
;
1016 lpIMC
= LockRealIMC(FROM_X11
);
1019 compstr
= (LPCOMPOSITIONSTRING
)ImmLockIMCC(lpIMC
->hCompStr
);
1020 rc
= compstr
->dwCursorPos
;
1021 ImmUnlockIMCC(lpIMC
->hCompStr
);
1023 UnlockRealIMC(FROM_X11
);
1027 void IME_SetCursorPos(DWORD pos
)
1029 LPINPUTCONTEXT lpIMC
;
1030 LPCOMPOSITIONSTRING compstr
;
1035 lpIMC
= LockRealIMC(FROM_X11
);
1039 compstr
= (LPCOMPOSITIONSTRING
)ImmLockIMCC(lpIMC
->hCompStr
);
1042 UnlockRealIMC(FROM_X11
);
1046 compstr
->dwCursorPos
= pos
;
1047 ImmUnlockIMCC(lpIMC
->hCompStr
);
1048 UnlockRealIMC(FROM_X11
);
1049 GenerateIMEMessage(FROM_X11
, WM_IME_COMPOSITION
, pos
, GCS_CURSORPOS
);
1053 void IME_UpdateAssociation(HWND focus
)
1055 ImmGetContext(focus
);
1057 if (!focus
|| !hSelectedFrom
)
1060 ImmAssociateContext(focus
,RealIMC(FROM_X11
));
1064 BOOL
IME_SetCompositionString(DWORD dwIndex
, LPCVOID lpComp
, DWORD dwCompLen
,
1065 LPCVOID lpRead
, DWORD dwReadLen
)
1067 return ImeSetCompositionString(FROM_X11
, dwIndex
, lpComp
, dwCompLen
,
1071 BOOL
IME_NotifyIME(DWORD dwAction
, DWORD dwIndex
, DWORD dwValue
)
1073 return NotifyIME(FROM_X11
, dwAction
, dwIndex
, dwValue
);
1077 * Internal functions to help with IME window management
1079 static void PaintDefaultIMEWnd(HIMC hIMC
, HWND hwnd
)
1084 LPCOMPOSITIONSTRING compstr
;
1085 LPBYTE compdata
= NULL
;
1087 MONITORINFO mon_info
;
1089 LPINPUTCONTEXT lpIMC
;
1091 lpIMC
= LockRealIMC(hIMC
);
1095 hdc
= BeginPaint(hwnd
,&ps
);
1097 GetClientRect(hwnd
,&rect
);
1098 FillRect(hdc
, &rect
, (HBRUSH
)(COLOR_WINDOW
+ 1));
1100 compdata
= ImmLockIMCC(lpIMC
->hCompStr
);
1101 compstr
= (LPCOMPOSITIONSTRING
)compdata
;
1103 if (compstr
->dwCompStrLen
&& compstr
->dwCompStrOffset
)
1107 HFONT oldfont
= NULL
;
1109 LPIMEPRIVATE myPrivate
;
1111 CompString
= (LPWSTR
)(compdata
+ compstr
->dwCompStrOffset
);
1112 myPrivate
= (LPIMEPRIVATE
)ImmLockIMCC(lpIMC
->hPrivate
);
1114 if (myPrivate
->textfont
)
1115 oldfont
= SelectObject(hdc
,myPrivate
->textfont
);
1117 ImmUnlockIMCC(lpIMC
->hPrivate
);
1119 GetTextExtentPoint32W(hdc
, CompString
, compstr
->dwCompStrLen
, &size
);
1125 * How this works based on tests on windows:
1126 * CFS_POINT: then we start our window at the point and grow it as large
1127 * as it needs to be for the string.
1128 * CFS_RECT: we still use the ptCurrentPos as a starting point and our
1129 * window is only as large as we need for the string, but we do not
1130 * grow such that our window exceeds the given rect. Wrapping if
1131 * needed and possible. If our ptCurrentPos is outside of our rect
1132 * then no window is displayed.
1133 * CFS_FORCE_POSITION: appears to behave just like CFS_POINT
1134 * maybe becase the default MSIME does not do any IME adjusting.
1136 if (lpIMC
->cfCompForm
.dwStyle
!= CFS_DEFAULT
)
1138 POINT cpt
= lpIMC
->cfCompForm
.ptCurrentPos
;
1139 ClientToScreen(lpIMC
->hWnd
,&cpt
);
1142 rect
.right
= rect
.left
+ pt
.x
;
1143 rect
.bottom
= rect
.top
+ pt
.y
;
1144 monitor
= MonitorFromPoint(cpt
, MONITOR_DEFAULTTOPRIMARY
);
1146 else /* CFS_DEFAULT */
1148 /* Windows places the default IME window in the bottom left */
1149 HWND target
= lpIMC
->hWnd
;
1150 if (!target
) target
= GetFocus();
1152 GetWindowRect(target
,&rect
);
1153 rect
.top
= rect
.bottom
;
1154 rect
.right
= rect
.left
+ pt
.x
+ 20;
1155 rect
.bottom
= rect
.top
+ pt
.y
+ 20;
1157 monitor
= MonitorFromWindow(target
, MONITOR_DEFAULTTOPRIMARY
);
1160 if (lpIMC
->cfCompForm
.dwStyle
== CFS_RECT
)
1163 client
=lpIMC
->cfCompForm
.rcArea
;
1164 MapWindowPoints( lpIMC
->hWnd
, 0, (POINT
*)&client
, 2 );
1165 IntersectRect(&rect
,&rect
,&client
);
1166 /* TODO: Wrap the input if needed */
1169 if (lpIMC
->cfCompForm
.dwStyle
== CFS_DEFAULT
)
1171 /* make sure we are on the desktop */
1172 mon_info
.cbSize
= sizeof(mon_info
);
1173 GetMonitorInfoW(monitor
, &mon_info
);
1175 if (rect
.bottom
> mon_info
.rcWork
.bottom
)
1177 int shift
= rect
.bottom
- mon_info
.rcWork
.bottom
;
1179 rect
.bottom
-= shift
;
1183 rect
.right
-= rect
.left
;
1186 if (rect
.right
> mon_info
.rcWork
.right
)
1188 int shift
= rect
.right
- mon_info
.rcWork
.right
;
1190 rect
.right
-= shift
;
1194 SetWindowPos(hwnd
, HWND_TOPMOST
, rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, SWP_NOACTIVATE
);
1196 TextOutW(hdc
, offX
,offY
, CompString
, compstr
->dwCompStrLen
);
1199 SelectObject(hdc
,oldfont
);
1202 ImmUnlockIMCC(lpIMC
->hCompStr
);
1205 UnlockRealIMC(hIMC
);
1208 static void UpdateDataInDefaultIMEWindow(HIMC hIMC
, HWND hwnd
, BOOL showable
)
1210 LPCOMPOSITIONSTRING compstr
;
1211 LPINPUTCONTEXT lpIMC
;
1213 lpIMC
= LockRealIMC(hIMC
);
1217 if (lpIMC
->hCompStr
)
1218 compstr
= ImmLockIMCC(lpIMC
->hCompStr
);
1222 if (compstr
== NULL
|| compstr
->dwCompStrLen
== 0)
1223 ShowWindow(hwnd
,SW_HIDE
);
1225 ShowWindow(hwnd
,SW_SHOWNOACTIVATE
);
1227 RedrawWindow(hwnd
,NULL
,NULL
,RDW_ERASENOW
|RDW_INVALIDATE
);
1229 if (compstr
!= NULL
)
1230 ImmUnlockIMCC(lpIMC
->hCompStr
);
1232 UnlockRealIMC(hIMC
);
1235 static void DefaultIMEComposition(HIMC hIMC
, HWND hwnd
, LPARAM lParam
)
1237 TRACE("IME message WM_IME_COMPOSITION 0x%lx\n", lParam
);
1238 if (lParam
& GCS_RESULTSTR
)
1240 LPCOMPOSITIONSTRING compstr
;
1244 LPINPUTCONTEXT lpIMC
;
1246 lpIMC
= LockRealIMC(hIMC
);
1250 TRACE("Posting result as IME_CHAR\n");
1251 compdata
= ImmLockIMCC(lpIMC
->hCompStr
);
1252 compstr
= (LPCOMPOSITIONSTRING
)compdata
;
1253 ResultStr
= (LPWSTR
)(compdata
+ compstr
->dwResultStrOffset
);
1254 GenerateIMECHARMessages(hIMC
, ResultStr
, compstr
->dwResultStrLen
);
1255 ImmUnlockIMCC(lpIMC
->hCompStr
);
1257 /* clear the buffer */
1258 newCompStr
= updateResultStr(lpIMC
->hCompStr
, NULL
, 0);
1259 ImmDestroyIMCC(lpIMC
->hCompStr
);
1260 lpIMC
->hCompStr
= newCompStr
;
1261 UnlockRealIMC(hIMC
);
1264 UpdateDataInDefaultIMEWindow(hIMC
,hwnd
,TRUE
);
1267 static void DefaultIMEStartComposition(HIMC hIMC
, HWND hwnd
)
1269 LPINPUTCONTEXT lpIMC
;
1271 lpIMC
= LockRealIMC(hIMC
);
1275 TRACE("IME message WM_IME_STARTCOMPOSITION\n");
1276 lpIMC
->hWnd
= GetFocus();
1277 ShowWindow(hwnd
,SW_SHOWNOACTIVATE
);
1278 UnlockRealIMC(hIMC
);
1281 static LRESULT
ImeHandleNotify(HIMC hIMC
, HWND hwnd
, UINT msg
, WPARAM wParam
,
1286 case IMN_OPENSTATUSWINDOW
:
1287 FIXME("WM_IME_NOTIFY:IMN_OPENSTATUSWINDOW\n");
1289 case IMN_CLOSESTATUSWINDOW
:
1290 FIXME("WM_IME_NOTIFY:IMN_CLOSESTATUSWINDOW\n");
1292 case IMN_OPENCANDIDATE
:
1293 FIXME("WM_IME_NOTIFY:IMN_OPENCANDIDATE\n");
1295 case IMN_CHANGECANDIDATE
:
1296 FIXME("WM_IME_NOTIFY:IMN_CHANGECANDIDATE\n");
1298 case IMN_CLOSECANDIDATE
:
1299 FIXME("WM_IME_NOTIFY:IMN_CLOSECANDIDATE\n");
1301 case IMN_SETCONVERSIONMODE
:
1302 FIXME("WM_IME_NOTIFY:IMN_SETCONVERSIONMODE\n");
1304 case IMN_SETSENTENCEMODE
:
1305 FIXME("WM_IME_NOTIFY:IMN_SETSENTENCEMODE\n");
1307 case IMN_SETOPENSTATUS
:
1308 FIXME("WM_IME_NOTIFY:IMN_SETOPENSTATUS\n");
1310 case IMN_SETCANDIDATEPOS
:
1311 FIXME("WM_IME_NOTIFY:IMN_SETCANDIDATEPOS\n");
1313 case IMN_SETCOMPOSITIONFONT
:
1314 FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONFONT\n");
1316 case IMN_SETCOMPOSITIONWINDOW
:
1317 FIXME("WM_IME_NOTIFY:IMN_SETCOMPOSITIONWINDOW\n");
1320 FIXME("WM_IME_NOTIFY:IMN_GUIDELINE\n");
1322 case IMN_SETSTATUSWINDOWPOS
:
1323 FIXME("WM_IME_NOTIFY:IMN_SETSTATUSWINDOWPOS\n");
1326 FIXME("WM_IME_NOTIFY:<Unknown 0x%lx>\n",wParam
);
1332 static LRESULT WINAPI
IME_WindowProc(HWND hwnd
, UINT msg
, WPARAM wParam
,
1338 TRACE("Incoming Message 0x%x (0x%08lx, 0x%08lx)\n", msg
, wParam
, lParam
);
1341 * Each UI window contains the current Input Context.
1342 * This Input Context can be obtained by calling GetWindowLong
1343 * with IMMGWL_IMC when the UI window receives a WM_IME_xxx message.
1344 * The UI window can refer to this Input Context and handles the
1348 hIMC
= (HIMC
)GetWindowLongW(hwnd
,IMMGWL_IMC
);
1350 hIMC
= RealIMC(FROM_X11
);
1352 /* if we have no hIMC there are many messages we cannot process */
1356 case WM_IME_STARTCOMPOSITION
:
1357 case WM_IME_ENDCOMPOSITION
:
1358 case WM_IME_COMPOSITION
:
1360 case WM_IME_CONTROL
:
1361 case WM_IME_COMPOSITIONFULL
:
1374 LPIMEPRIVATE myPrivate
;
1375 LPINPUTCONTEXT lpIMC
;
1377 SetWindowTextA(hwnd
,"Wine Ime Active");
1379 lpIMC
= LockRealIMC(hIMC
);
1382 myPrivate
= (LPIMEPRIVATE
)ImmLockIMCC(lpIMC
->hPrivate
);
1383 myPrivate
->hwndDefault
= hwnd
;
1384 ImmUnlockIMCC(lpIMC
->hPrivate
);
1386 UnlockRealIMC(hIMC
);
1391 PaintDefaultIMEWnd(hIMC
, hwnd
);
1399 SetFocus((HWND
)wParam
);
1401 FIXME("Received focus, should never have focus\n");
1403 case WM_IME_COMPOSITION
:
1404 DefaultIMEComposition(hIMC
, hwnd
, lParam
);
1406 case WM_IME_STARTCOMPOSITION
:
1407 DefaultIMEStartComposition(hIMC
, hwnd
);
1409 case WM_IME_ENDCOMPOSITION
:
1410 TRACE("IME message %s, 0x%lx, 0x%lx\n",
1411 "WM_IME_ENDCOMPOSITION", wParam
, lParam
);
1412 ShowWindow(hwnd
,SW_HIDE
);
1415 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_IME_SELECT", wParam
, lParam
);
1417 case WM_IME_CONTROL
:
1418 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_IME_CONTROL", wParam
, lParam
);
1422 rc
= ImeHandleNotify(hIMC
,hwnd
,msg
,wParam
,lParam
);
1425 TRACE("Non-standard message 0x%x\n",msg
);
1427 /* check the MSIME messages */
1428 if (msg
== WM_MSIME_SERVICE
)
1430 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_SERVICE", wParam
, lParam
);
1433 else if (msg
== WM_MSIME_RECONVERTOPTIONS
)
1435 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_RECONVERTOPTIONS", wParam
, lParam
);
1437 else if (msg
== WM_MSIME_MOUSE
)
1439 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_MOUSE", wParam
, lParam
);
1441 else if (msg
== WM_MSIME_RECONVERTREQUEST
)
1443 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_RECONVERTREQUEST", wParam
, lParam
);
1445 else if (msg
== WM_MSIME_RECONVERT
)
1447 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_RECONVERT", wParam
, lParam
);
1449 else if (msg
== WM_MSIME_QUERYPOSITION
)
1451 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_QUERYPOSITION", wParam
, lParam
);
1453 else if (msg
== WM_MSIME_DOCUMENTFEED
)
1455 TRACE("IME message %s, 0x%lx, 0x%lx\n","WM_MSIME_DOCUMENTFEED", wParam
, lParam
);
1457 /* DefWndProc if not an IME message */
1458 if (!rc
&& !((msg
>= WM_IME_STARTCOMPOSITION
&& msg
<= WM_IME_KEYLAST
) ||
1459 (msg
>= WM_IME_SETCONTEXT
&& msg
<= WM_IME_KEYUP
)))
1460 rc
= DefWindowProcW(hwnd
,msg
,wParam
,lParam
);