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 static HIMC
*hSelectedFrom
= NULL
;
53 static INT hSelectedCount
= 0;
55 static void input_context_reset_comp_str( INPUTCONTEXT
*ctx
)
57 COMPOSITIONSTRING
*compstr
;
59 if (!(compstr
= ImmLockIMCC( ctx
->hCompStr
)))
60 WARN( "Failed to lock input context composition string\n" );
63 memset( compstr
, 0, sizeof(*compstr
) );
64 compstr
->dwSize
= sizeof(*compstr
);
65 ImmUnlockIMCC( ctx
->hCompStr
);
69 static HIMC
RealIMC(HIMC hIMC
)
74 HWND wnd
= GetFocus();
75 HIMC winHimc
= ImmGetContext(wnd
);
76 for (i
= 0; i
< hSelectedCount
; i
++)
77 if (winHimc
== hSelectedFrom
[i
])
85 static LPINPUTCONTEXT
LockRealIMC(HIMC hIMC
)
87 HIMC real_imc
= RealIMC(hIMC
);
89 return ImmLockIMC(real_imc
);
94 static BOOL
UnlockRealIMC(HIMC hIMC
)
96 HIMC real_imc
= RealIMC(hIMC
);
98 return ImmUnlockIMC(real_imc
);
103 static int updateField(DWORD origLen
, DWORD origOffset
, DWORD currentOffset
,
104 LPBYTE target
, LPBYTE source
, DWORD
* lenParam
,
105 DWORD
* offsetParam
, BOOL wchars
)
107 if (origLen
> 0 && origOffset
> 0)
109 int truelen
= origLen
;
111 truelen
*= sizeof(WCHAR
);
113 memcpy(&target
[currentOffset
], &source
[origOffset
], truelen
);
116 *offsetParam
= currentOffset
;
117 currentOffset
+= truelen
;
119 return currentOffset
;
122 static HIMCC
updateCompStr(HIMCC old
, LPCWSTR compstr
, DWORD len
)
124 /* We need to make sure the CompStr, CompClause and CompAttr fields are all
125 * set and correct. */
128 LPBYTE newdata
= NULL
;
129 LPBYTE olddata
= NULL
;
130 LPCOMPOSITIONSTRING new_one
;
131 LPCOMPOSITIONSTRING lpcs
= NULL
;
132 INT current_offset
= 0;
134 TRACE("%s, %li\n",debugstr_wn(compstr
,len
),len
);
136 if (old
== NULL
&& compstr
== NULL
&& len
== 0)
139 if (compstr
== NULL
&& len
!= 0)
141 ERR("compstr is NULL however we have a len! Please report\n");
147 olddata
= ImmLockIMCC(old
);
148 lpcs
= (LPCOMPOSITIONSTRING
)olddata
;
151 needed_size
= sizeof(COMPOSITIONSTRING
) + len
* sizeof(WCHAR
) +
152 len
+ sizeof(DWORD
) * 2;
156 needed_size
+= lpcs
->dwCompReadAttrLen
;
157 needed_size
+= lpcs
->dwCompReadClauseLen
;
158 needed_size
+= lpcs
->dwCompReadStrLen
* sizeof(WCHAR
);
159 needed_size
+= lpcs
->dwResultReadClauseLen
;
160 needed_size
+= lpcs
->dwResultReadStrLen
* sizeof(WCHAR
);
161 needed_size
+= lpcs
->dwResultClauseLen
;
162 needed_size
+= lpcs
->dwResultStrLen
* sizeof(WCHAR
);
163 needed_size
+= lpcs
->dwPrivateSize
;
165 rc
= ImmCreateIMCC(needed_size
);
166 newdata
= ImmLockIMCC(rc
);
167 new_one
= (LPCOMPOSITIONSTRING
)newdata
;
169 new_one
->dwSize
= needed_size
;
170 current_offset
= sizeof(COMPOSITIONSTRING
);
173 current_offset
= updateField(lpcs
->dwCompReadAttrLen
,
174 lpcs
->dwCompReadAttrOffset
,
175 current_offset
, newdata
, olddata
,
176 &new_one
->dwCompReadAttrLen
,
177 &new_one
->dwCompReadAttrOffset
, FALSE
);
179 current_offset
= updateField(lpcs
->dwCompReadClauseLen
,
180 lpcs
->dwCompReadClauseOffset
,
181 current_offset
, newdata
, olddata
,
182 &new_one
->dwCompReadClauseLen
,
183 &new_one
->dwCompReadClauseOffset
, FALSE
);
185 current_offset
= updateField(lpcs
->dwCompReadStrLen
,
186 lpcs
->dwCompReadStrOffset
,
187 current_offset
, newdata
, olddata
,
188 &new_one
->dwCompReadStrLen
,
189 &new_one
->dwCompReadStrOffset
, TRUE
);
191 /* new CompAttr, CompClause, CompStr, dwCursorPos */
192 new_one
->dwDeltaStart
= 0;
194 current_offset
= updateField(lpcs
->dwResultReadClauseLen
,
195 lpcs
->dwResultReadClauseOffset
,
196 current_offset
, newdata
, olddata
,
197 &new_one
->dwResultReadClauseLen
,
198 &new_one
->dwResultReadClauseOffset
, FALSE
);
200 current_offset
= updateField(lpcs
->dwResultReadStrLen
,
201 lpcs
->dwResultReadStrOffset
,
202 current_offset
, newdata
, olddata
,
203 &new_one
->dwResultReadStrLen
,
204 &new_one
->dwResultReadStrOffset
, TRUE
);
206 current_offset
= updateField(lpcs
->dwResultClauseLen
,
207 lpcs
->dwResultClauseOffset
,
208 current_offset
, newdata
, olddata
,
209 &new_one
->dwResultClauseLen
,
210 &new_one
->dwResultClauseOffset
, FALSE
);
212 current_offset
= updateField(lpcs
->dwResultStrLen
,
213 lpcs
->dwResultStrOffset
,
214 current_offset
, newdata
, olddata
,
215 &new_one
->dwResultStrLen
,
216 &new_one
->dwResultStrOffset
, TRUE
);
218 current_offset
= updateField(lpcs
->dwPrivateSize
,
219 lpcs
->dwPrivateOffset
,
220 current_offset
, newdata
, olddata
,
221 &new_one
->dwPrivateSize
,
222 &new_one
->dwPrivateOffset
, FALSE
);
227 new_one
->dwCompAttrLen
= len
;
230 new_one
->dwCompAttrOffset
= current_offset
;
231 memset(&newdata
[current_offset
],ATTR_INPUT
,len
);
232 current_offset
+= len
;
238 new_one
->dwCompClauseLen
= sizeof(DWORD
) * 2;
239 new_one
->dwCompClauseOffset
= current_offset
;
240 *(DWORD
*)(&newdata
[current_offset
]) = 0;
241 current_offset
+= sizeof(DWORD
);
242 *(DWORD
*)(&newdata
[current_offset
]) = len
;
243 current_offset
+= sizeof(DWORD
);
246 new_one
->dwCompClauseLen
= 0;
249 new_one
->dwCompStrLen
= len
;
252 new_one
->dwCompStrOffset
= current_offset
;
253 memcpy(&newdata
[current_offset
],compstr
,len
*sizeof(WCHAR
));
257 new_one
->dwCursorPos
= len
;
266 static HIMCC
updateResultStr(HIMCC old
, LPWSTR resultstr
, DWORD len
)
268 /* we need to make sure the ResultStr and ResultClause fields are all
272 LPBYTE newdata
= NULL
;
273 LPBYTE olddata
= NULL
;
274 LPCOMPOSITIONSTRING new_one
;
275 LPCOMPOSITIONSTRING lpcs
= NULL
;
276 INT current_offset
= 0;
278 TRACE("%s, %li\n",debugstr_wn(resultstr
,len
),len
);
280 if (old
== NULL
&& resultstr
== NULL
&& len
== 0)
283 if (resultstr
== NULL
&& len
!= 0)
285 ERR("resultstr is NULL however we have a len! Please report\n");
291 olddata
= ImmLockIMCC(old
);
292 lpcs
= (LPCOMPOSITIONSTRING
)olddata
;
295 needed_size
= sizeof(COMPOSITIONSTRING
) + len
* sizeof(WCHAR
) +
300 needed_size
+= lpcs
->dwCompReadAttrLen
;
301 needed_size
+= lpcs
->dwCompReadClauseLen
;
302 needed_size
+= lpcs
->dwCompReadStrLen
* sizeof(WCHAR
);
303 needed_size
+= lpcs
->dwCompAttrLen
;
304 needed_size
+= lpcs
->dwCompClauseLen
;
305 needed_size
+= lpcs
->dwCompStrLen
* sizeof(WCHAR
);
306 needed_size
+= lpcs
->dwResultReadClauseLen
;
307 needed_size
+= lpcs
->dwResultReadStrLen
* sizeof(WCHAR
);
308 needed_size
+= lpcs
->dwPrivateSize
;
310 rc
= ImmCreateIMCC(needed_size
);
311 newdata
= ImmLockIMCC(rc
);
312 new_one
= (LPCOMPOSITIONSTRING
)newdata
;
314 new_one
->dwSize
= needed_size
;
315 current_offset
= sizeof(COMPOSITIONSTRING
);
318 current_offset
= updateField(lpcs
->dwCompReadAttrLen
,
319 lpcs
->dwCompReadAttrOffset
,
320 current_offset
, newdata
, olddata
,
321 &new_one
->dwCompReadAttrLen
,
322 &new_one
->dwCompReadAttrOffset
, FALSE
);
324 current_offset
= updateField(lpcs
->dwCompReadClauseLen
,
325 lpcs
->dwCompReadClauseOffset
,
326 current_offset
, newdata
, olddata
,
327 &new_one
->dwCompReadClauseLen
,
328 &new_one
->dwCompReadClauseOffset
, FALSE
);
330 current_offset
= updateField(lpcs
->dwCompReadStrLen
,
331 lpcs
->dwCompReadStrOffset
,
332 current_offset
, newdata
, olddata
,
333 &new_one
->dwCompReadStrLen
,
334 &new_one
->dwCompReadStrOffset
, TRUE
);
336 current_offset
= updateField(lpcs
->dwCompAttrLen
,
337 lpcs
->dwCompAttrOffset
,
338 current_offset
, newdata
, olddata
,
339 &new_one
->dwCompAttrLen
,
340 &new_one
->dwCompAttrOffset
, FALSE
);
342 current_offset
= updateField(lpcs
->dwCompClauseLen
,
343 lpcs
->dwCompClauseOffset
,
344 current_offset
, newdata
, olddata
,
345 &new_one
->dwCompClauseLen
,
346 &new_one
->dwCompClauseOffset
, FALSE
);
348 current_offset
= updateField(lpcs
->dwCompStrLen
,
349 lpcs
->dwCompStrOffset
,
350 current_offset
, newdata
, olddata
,
351 &new_one
->dwCompStrLen
,
352 &new_one
->dwCompStrOffset
, TRUE
);
354 new_one
->dwCursorPos
= lpcs
->dwCursorPos
;
355 new_one
->dwDeltaStart
= 0;
357 current_offset
= updateField(lpcs
->dwResultReadClauseLen
,
358 lpcs
->dwResultReadClauseOffset
,
359 current_offset
, newdata
, olddata
,
360 &new_one
->dwResultReadClauseLen
,
361 &new_one
->dwResultReadClauseOffset
, FALSE
);
363 current_offset
= updateField(lpcs
->dwResultReadStrLen
,
364 lpcs
->dwResultReadStrOffset
,
365 current_offset
, newdata
, olddata
,
366 &new_one
->dwResultReadStrLen
,
367 &new_one
->dwResultReadStrOffset
, TRUE
);
369 /* new ResultClause , ResultStr */
371 current_offset
= updateField(lpcs
->dwPrivateSize
,
372 lpcs
->dwPrivateOffset
,
373 current_offset
, newdata
, olddata
,
374 &new_one
->dwPrivateSize
,
375 &new_one
->dwPrivateOffset
, FALSE
);
382 new_one
->dwResultClauseLen
= sizeof(DWORD
) * 2;
383 new_one
->dwResultClauseOffset
= current_offset
;
384 *(DWORD
*)(&newdata
[current_offset
]) = 0;
385 current_offset
+= sizeof(DWORD
);
386 *(DWORD
*)(&newdata
[current_offset
]) = len
;
387 current_offset
+= sizeof(DWORD
);
390 new_one
->dwResultClauseLen
= 0;
393 new_one
->dwResultStrLen
= len
;
396 new_one
->dwResultStrOffset
= current_offset
;
397 memcpy(&newdata
[current_offset
],resultstr
,len
*sizeof(WCHAR
));
406 static void GenerateIMEMessage(HIMC hIMC
, UINT msg
, WPARAM wParam
,
409 LPINPUTCONTEXT lpIMC
;
410 LPTRANSMSG lpTransMsg
;
412 lpIMC
= LockRealIMC(hIMC
);
416 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
, (lpIMC
->dwNumMsgBuf
+ 1) *
421 lpTransMsg
= ImmLockIMCC(lpIMC
->hMsgBuf
);
425 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
426 lpTransMsg
->message
= msg
;
427 lpTransMsg
->wParam
= wParam
;
428 lpTransMsg
->lParam
= lParam
;
430 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
431 lpIMC
->dwNumMsgBuf
++;
433 ImmGenerateMessage(RealIMC(hIMC
));
437 static void ime_set_composition_status( HIMC himc
, BOOL composition
)
439 struct ime_private
*priv
;
443 if (!(ctx
= ImmLockIMC( himc
))) return;
444 if ((priv
= ImmLockIMCC( ctx
->hPrivate
)))
446 if (!priv
->bInComposition
&& composition
) msg
= WM_IME_STARTCOMPOSITION
;
447 else if (priv
->bInComposition
&& !composition
) msg
= WM_IME_ENDCOMPOSITION
;
448 priv
->bInComposition
= composition
;
449 ImmUnlockIMCC( ctx
->hPrivate
);
451 ImmUnlockIMC( himc
);
453 if (msg
) GenerateIMEMessage( himc
, msg
, 0, 0 );
456 static BOOL
IME_RemoveFromSelected(HIMC hIMC
)
459 for (i
= 0; i
< hSelectedCount
; i
++)
460 if (hSelectedFrom
[i
] == hIMC
)
462 if (i
< hSelectedCount
- 1)
463 memmove(&hSelectedFrom
[i
], &hSelectedFrom
[i
+1], (hSelectedCount
- i
- 1)*sizeof(HIMC
));
470 static void IME_AddToSelected(HIMC hIMC
)
474 hSelectedFrom
= HeapReAlloc(GetProcessHeap(), 0, hSelectedFrom
, hSelectedCount
*sizeof(HIMC
));
476 hSelectedFrom
= HeapAlloc(GetProcessHeap(), 0, sizeof(HIMC
));
477 hSelectedFrom
[hSelectedCount
-1] = hIMC
;
480 BOOL WINAPI
ImeProcessKey(HIMC hIMC
, UINT vKey
, LPARAM lKeyData
, const LPBYTE lpbKeyState
)
482 /* See the comment at the head of this file */
483 TRACE("We do no processing via this route\n");
487 BOOL WINAPI
ImeSelect(HIMC hIMC
, BOOL fSelect
)
489 LPINPUTCONTEXT lpIMC
;
490 TRACE("%p %s\n",hIMC
,(fSelect
)?"TRUE":"FALSE");
492 if (hIMC
== FROM_X11
)
494 ERR("ImeSelect should never be called from X11\n");
503 return IME_RemoveFromSelected(hIMC
);
505 IME_AddToSelected(hIMC
);
507 /* Initialize our structures */
508 lpIMC
= LockRealIMC(hIMC
);
511 LPIMEPRIVATE myPrivate
;
512 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
513 myPrivate
->bInComposition
= FALSE
;
514 myPrivate
->bInternalState
= FALSE
;
515 myPrivate
->textfont
= NULL
;
516 myPrivate
->hwndDefault
= NULL
;
517 ImmUnlockIMCC(lpIMC
->hPrivate
);
524 UINT WINAPI
ImeToAsciiEx (UINT uVKey
, UINT uScanCode
, const LPBYTE lpbKeyState
,
525 TRANSMSGLIST
*lpdwTransKey
, UINT fuState
, HIMC hIMC
)
527 /* See the comment at the head of this file */
528 TRACE("We do no processing via this route\n");
532 BOOL WINAPI
NotifyIME(HIMC hIMC
, DWORD dwAction
, DWORD dwIndex
, DWORD dwValue
)
534 struct xim_preedit_state_params preedit_params
;
536 LPINPUTCONTEXT lpIMC
;
538 TRACE("%p %li %li %li\n",hIMC
,dwAction
,dwIndex
,dwValue
);
540 lpIMC
= LockRealIMC(hIMC
);
546 case NI_OPENCANDIDATE
: FIXME("NI_OPENCANDIDATE\n"); break;
547 case NI_CLOSECANDIDATE
: FIXME("NI_CLOSECANDIDATE\n"); break;
548 case NI_SELECTCANDIDATESTR
: FIXME("NI_SELECTCANDIDATESTR\n"); break;
549 case NI_CHANGECANDIDATELIST
: FIXME("NI_CHANGECANDIDATELIST\n"); break;
550 case NI_SETCANDIDATE_PAGESTART
: FIXME("NI_SETCANDIDATE_PAGESTART\n"); break;
551 case NI_SETCANDIDATE_PAGESIZE
: FIXME("NI_SETCANDIDATE_PAGESIZE\n"); break;
552 case NI_CONTEXTUPDATED
:
555 case IMC_SETCOMPOSITIONWINDOW
: FIXME("IMC_SETCOMPOSITIONWINDOW\n"); break;
556 case IMC_SETCONVERSIONMODE
: FIXME("IMC_SETCONVERSIONMODE\n"); break;
557 case IMC_SETSENTENCEMODE
: FIXME("IMC_SETSENTENCEMODE\n"); break;
558 case IMC_SETCANDIDATEPOS
: FIXME("IMC_SETCANDIDATEPOS\n"); break;
559 case IMC_SETCOMPOSITIONFONT
:
561 LPIMEPRIVATE myPrivate
;
562 TRACE("IMC_SETCOMPOSITIONFONT\n");
564 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
565 if (myPrivate
->textfont
)
567 DeleteObject(myPrivate
->textfont
);
568 myPrivate
->textfont
= NULL
;
570 myPrivate
->textfont
= CreateFontIndirectW(&lpIMC
->lfFont
.W
);
571 ImmUnlockIMCC(lpIMC
->hPrivate
);
574 case IMC_SETOPENSTATUS
:
576 preedit_params
.hwnd
= lpIMC
->hWnd
;
577 preedit_params
.open
= lpIMC
->fOpen
;
578 X11DRV_CALL( xim_preedit_state
, &preedit_params
);
581 X11DRV_CALL( xim_reset
, lpIMC
->hWnd
);
582 input_context_reset_comp_str( lpIMC
);
583 ime_set_composition_status( hIMC
, FALSE
);
586 default: FIXME("Unknown\n"); break;
589 case NI_COMPOSITIONSTR
:
594 COMPOSITIONSTRING
*compstr
;
596 if (!(compstr
= ImmLockIMCC( lpIMC
->hCompStr
)))
597 WARN( "Failed to lock input context composition string\n" );
600 WCHAR wchr
= *(WCHAR
*)((BYTE
*)compstr
+ compstr
->dwCompStrOffset
);
601 COMPOSITIONSTRING tmp
= *compstr
;
604 memset( compstr
, 0, sizeof(*compstr
) );
605 compstr
->dwSize
= tmp
.dwSize
;
606 compstr
->dwResultStrLen
= tmp
.dwCompStrLen
;
607 compstr
->dwResultStrOffset
= tmp
.dwCompStrOffset
;
608 compstr
->dwResultClauseLen
= tmp
.dwCompClauseLen
;
609 compstr
->dwResultClauseOffset
= tmp
.dwCompClauseOffset
;
610 ImmUnlockIMCC( lpIMC
->hCompStr
);
612 if (tmp
.dwCompStrLen
) flags
|= GCS_RESULTSTR
;
613 if (tmp
.dwCompClauseLen
) flags
|= GCS_RESULTCLAUSE
;
614 if (flags
) GenerateIMEMessage( hIMC
, WM_IME_COMPOSITION
, wchr
, flags
);
617 ImmSetOpenStatus( hIMC
, FALSE
);
621 case CPS_CONVERT
: FIXME("CPS_CONVERT\n"); break;
622 case CPS_REVERT
: FIXME("CPS_REVERT\n"); break;
624 input_context_reset_comp_str( lpIMC
);
625 ime_set_composition_status( hIMC
, FALSE
);
628 default: FIXME("Unknown\n"); break;
631 default: FIXME("Unknown Message\n"); break;
638 BOOL WINAPI
ImeSetCompositionString(HIMC hIMC
, DWORD dwIndex
, LPCVOID lpComp
,
639 DWORD dwCompLen
, LPCVOID lpRead
,
642 LPINPUTCONTEXT lpIMC
;
646 TRACE("(%p, %ld, %p, %ld, %p, %ld):\n",
647 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
650 if (hIMC
!= FROM_X11
)
651 FIXME("PROBLEM: This only sets the wine level string\n");
655 * this sets the composition string in the imm32.dll level
656 * of the composition buffer. we cannot manipulate the xim level
657 * buffer, which means that once the xim level buffer changes again
658 * any call to this function from the application will be lost
661 if (lpRead
&& dwReadLen
)
662 FIXME("Reading string unimplemented\n");
664 lpIMC
= LockRealIMC(hIMC
);
669 if (dwIndex
== SCS_SETSTR
)
673 ime_set_composition_status( hIMC
, TRUE
);
675 /* clear existing result */
676 newCompStr
= updateResultStr(lpIMC
->hCompStr
, NULL
, 0);
677 ImmDestroyIMCC(lpIMC
->hCompStr
);
678 lpIMC
->hCompStr
= newCompStr
;
682 if (dwCompLen
&& lpComp
)
684 newCompStr
= updateCompStr(lpIMC
->hCompStr
, (LPCWSTR
)lpComp
, dwCompLen
/ sizeof(WCHAR
));
685 ImmDestroyIMCC(lpIMC
->hCompStr
);
686 lpIMC
->hCompStr
= newCompStr
;
688 wParam
= ((const WCHAR
*)lpComp
)[0];
689 flags
|= GCS_COMPCLAUSE
| GCS_COMPATTR
| GCS_DELTASTART
;
693 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
694 ImmDestroyIMCC(lpIMC
->hCompStr
);
695 lpIMC
->hCompStr
= newCompStr
;
699 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, wParam
, flags
);
700 ImmUnlockIMCC(lpIMC
->hPrivate
);
706 /* Interfaces to XIM and other parts of winex11drv */
708 NTSTATUS
x11drv_ime_set_open_status( UINT open
)
712 imc
= RealIMC(FROM_X11
);
713 ImmSetOpenStatus(imc
, open
);
717 NTSTATUS
x11drv_ime_set_composition_status( UINT open
)
720 LPINPUTCONTEXT lpIMC
;
722 imc
= RealIMC(FROM_X11
);
723 lpIMC
= ImmLockIMC(imc
);
729 struct ime_private
*myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
730 ShowWindow(myPrivate
->hwndDefault
, SW_HIDE
);
731 input_context_reset_comp_str( lpIMC
);
732 ImmUnlockIMCC(lpIMC
->hPrivate
);
737 ime_set_composition_status( imc
, open
);
742 NTSTATUS
x11drv_ime_get_cursor_pos( UINT arg
)
744 LPINPUTCONTEXT lpIMC
;
746 LPCOMPOSITIONSTRING compstr
;
751 lpIMC
= LockRealIMC(FROM_X11
);
754 compstr
= ImmLockIMCC(lpIMC
->hCompStr
);
755 rc
= compstr
->dwCursorPos
;
756 ImmUnlockIMCC(lpIMC
->hCompStr
);
758 UnlockRealIMC(FROM_X11
);
762 NTSTATUS
x11drv_ime_set_cursor_pos( UINT pos
)
764 LPINPUTCONTEXT lpIMC
;
765 LPCOMPOSITIONSTRING compstr
;
770 lpIMC
= LockRealIMC(FROM_X11
);
774 compstr
= ImmLockIMCC(lpIMC
->hCompStr
);
777 UnlockRealIMC(FROM_X11
);
781 compstr
->dwCursorPos
= pos
;
782 ImmUnlockIMCC(lpIMC
->hCompStr
);
783 UnlockRealIMC(FROM_X11
);
784 GenerateIMEMessage(FROM_X11
, WM_IME_COMPOSITION
, pos
, GCS_CURSORPOS
);
788 NTSTATUS
x11drv_ime_update_association( UINT arg
)
790 HWND focus
= UlongToHandle( arg
);
792 ImmGetContext(focus
);
794 if (focus
&& hSelectedFrom
)
795 ImmAssociateContext(focus
,RealIMC(FROM_X11
));
800 NTSTATUS WINAPI
x11drv_ime_set_composition_string( void *param
, ULONG size
)
802 return ImeSetCompositionString(FROM_X11
, SCS_SETSTR
, param
, size
, NULL
, 0);
805 NTSTATUS WINAPI
x11drv_ime_set_result( void *params
, ULONG len
)
807 WCHAR
*lpResult
= params
;
809 LPINPUTCONTEXT lpIMC
;
811 LPIMEPRIVATE myPrivate
;
815 len
/= sizeof(WCHAR
);
816 if ((focus
= GetFocus()))
817 x11drv_ime_update_association( HandleToUlong( focus
));
819 imc
= RealIMC(FROM_X11
);
820 lpIMC
= ImmLockIMC(imc
);
824 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
825 ImmDestroyIMCC(lpIMC
->hCompStr
);
826 lpIMC
->hCompStr
= newCompStr
;
828 newCompStr
= updateResultStr(lpIMC
->hCompStr
, lpResult
, len
);
829 ImmDestroyIMCC(lpIMC
->hCompStr
);
830 lpIMC
->hCompStr
= newCompStr
;
832 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
833 inComp
= myPrivate
->bInComposition
;
834 ImmUnlockIMCC(lpIMC
->hPrivate
);
838 ImmSetOpenStatus(imc
, TRUE
);
839 GenerateIMEMessage(imc
, WM_IME_STARTCOMPOSITION
, 0, 0);
842 GenerateIMEMessage(imc
, WM_IME_COMPOSITION
, 0, GCS_COMPSTR
);
843 GenerateIMEMessage(imc
, WM_IME_COMPOSITION
, lpResult
[0], GCS_RESULTSTR
|GCS_RESULTCLAUSE
);
844 GenerateIMEMessage(imc
, WM_IME_ENDCOMPOSITION
, 0, 0);
847 ImmSetOpenStatus(imc
, FALSE
);