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 WCHAR
*input_context_get_comp_str( INPUTCONTEXT
*ctx
, BOOL result
, UINT
*length
)
57 COMPOSITIONSTRING
*string
;
61 if (!(string
= ImmLockIMCC( ctx
->hCompStr
))) return NULL
;
62 len
= result
? string
->dwResultStrLen
: string
->dwCompStrLen
;
63 off
= result
? string
->dwResultStrOffset
: string
->dwCompStrOffset
;
65 if (len
&& off
&& (text
= malloc( (len
+ 1) * sizeof(WCHAR
) )))
67 memcpy( text
, (BYTE
*)string
+ off
, len
* sizeof(WCHAR
) );
72 ImmUnlockIMCC( ctx
->hCompStr
);
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 HIMCC
ImeCreateBlankCompStr(void)
113 LPCOMPOSITIONSTRING ptr
;
114 rc
= ImmCreateIMCC(sizeof(COMPOSITIONSTRING
));
115 ptr
= ImmLockIMCC(rc
);
116 memset(ptr
,0,sizeof(COMPOSITIONSTRING
));
117 ptr
->dwSize
= sizeof(COMPOSITIONSTRING
);
122 static int updateField(DWORD origLen
, DWORD origOffset
, DWORD currentOffset
,
123 LPBYTE target
, LPBYTE source
, DWORD
* lenParam
,
124 DWORD
* offsetParam
, BOOL wchars
)
126 if (origLen
> 0 && origOffset
> 0)
128 int truelen
= origLen
;
130 truelen
*= sizeof(WCHAR
);
132 memcpy(&target
[currentOffset
], &source
[origOffset
], truelen
);
135 *offsetParam
= currentOffset
;
136 currentOffset
+= truelen
;
138 return currentOffset
;
141 static HIMCC
updateCompStr(HIMCC old
, LPCWSTR compstr
, DWORD len
)
143 /* We need to make sure the CompStr, CompClause and CompAttr fields are all
144 * set and correct. */
147 LPBYTE newdata
= NULL
;
148 LPBYTE olddata
= NULL
;
149 LPCOMPOSITIONSTRING new_one
;
150 LPCOMPOSITIONSTRING lpcs
= NULL
;
151 INT current_offset
= 0;
153 TRACE("%s, %li\n",debugstr_wn(compstr
,len
),len
);
155 if (old
== NULL
&& compstr
== NULL
&& len
== 0)
158 if (compstr
== NULL
&& len
!= 0)
160 ERR("compstr is NULL however we have a len! Please report\n");
166 olddata
= ImmLockIMCC(old
);
167 lpcs
= (LPCOMPOSITIONSTRING
)olddata
;
170 needed_size
= sizeof(COMPOSITIONSTRING
) + len
* sizeof(WCHAR
) +
171 len
+ sizeof(DWORD
) * 2;
175 needed_size
+= lpcs
->dwCompReadAttrLen
;
176 needed_size
+= lpcs
->dwCompReadClauseLen
;
177 needed_size
+= lpcs
->dwCompReadStrLen
* sizeof(WCHAR
);
178 needed_size
+= lpcs
->dwResultReadClauseLen
;
179 needed_size
+= lpcs
->dwResultReadStrLen
* sizeof(WCHAR
);
180 needed_size
+= lpcs
->dwResultClauseLen
;
181 needed_size
+= lpcs
->dwResultStrLen
* sizeof(WCHAR
);
182 needed_size
+= lpcs
->dwPrivateSize
;
184 rc
= ImmCreateIMCC(needed_size
);
185 newdata
= ImmLockIMCC(rc
);
186 new_one
= (LPCOMPOSITIONSTRING
)newdata
;
188 new_one
->dwSize
= needed_size
;
189 current_offset
= sizeof(COMPOSITIONSTRING
);
192 current_offset
= updateField(lpcs
->dwCompReadAttrLen
,
193 lpcs
->dwCompReadAttrOffset
,
194 current_offset
, newdata
, olddata
,
195 &new_one
->dwCompReadAttrLen
,
196 &new_one
->dwCompReadAttrOffset
, FALSE
);
198 current_offset
= updateField(lpcs
->dwCompReadClauseLen
,
199 lpcs
->dwCompReadClauseOffset
,
200 current_offset
, newdata
, olddata
,
201 &new_one
->dwCompReadClauseLen
,
202 &new_one
->dwCompReadClauseOffset
, FALSE
);
204 current_offset
= updateField(lpcs
->dwCompReadStrLen
,
205 lpcs
->dwCompReadStrOffset
,
206 current_offset
, newdata
, olddata
,
207 &new_one
->dwCompReadStrLen
,
208 &new_one
->dwCompReadStrOffset
, TRUE
);
210 /* new CompAttr, CompClause, CompStr, dwCursorPos */
211 new_one
->dwDeltaStart
= 0;
213 current_offset
= updateField(lpcs
->dwResultReadClauseLen
,
214 lpcs
->dwResultReadClauseOffset
,
215 current_offset
, newdata
, olddata
,
216 &new_one
->dwResultReadClauseLen
,
217 &new_one
->dwResultReadClauseOffset
, FALSE
);
219 current_offset
= updateField(lpcs
->dwResultReadStrLen
,
220 lpcs
->dwResultReadStrOffset
,
221 current_offset
, newdata
, olddata
,
222 &new_one
->dwResultReadStrLen
,
223 &new_one
->dwResultReadStrOffset
, TRUE
);
225 current_offset
= updateField(lpcs
->dwResultClauseLen
,
226 lpcs
->dwResultClauseOffset
,
227 current_offset
, newdata
, olddata
,
228 &new_one
->dwResultClauseLen
,
229 &new_one
->dwResultClauseOffset
, FALSE
);
231 current_offset
= updateField(lpcs
->dwResultStrLen
,
232 lpcs
->dwResultStrOffset
,
233 current_offset
, newdata
, olddata
,
234 &new_one
->dwResultStrLen
,
235 &new_one
->dwResultStrOffset
, TRUE
);
237 current_offset
= updateField(lpcs
->dwPrivateSize
,
238 lpcs
->dwPrivateOffset
,
239 current_offset
, newdata
, olddata
,
240 &new_one
->dwPrivateSize
,
241 &new_one
->dwPrivateOffset
, FALSE
);
246 new_one
->dwCompAttrLen
= len
;
249 new_one
->dwCompAttrOffset
= current_offset
;
250 memset(&newdata
[current_offset
],ATTR_INPUT
,len
);
251 current_offset
+= len
;
257 new_one
->dwCompClauseLen
= sizeof(DWORD
) * 2;
258 new_one
->dwCompClauseOffset
= current_offset
;
259 *(DWORD
*)(&newdata
[current_offset
]) = 0;
260 current_offset
+= sizeof(DWORD
);
261 *(DWORD
*)(&newdata
[current_offset
]) = len
;
262 current_offset
+= sizeof(DWORD
);
265 new_one
->dwCompClauseLen
= 0;
268 new_one
->dwCompStrLen
= len
;
271 new_one
->dwCompStrOffset
= current_offset
;
272 memcpy(&newdata
[current_offset
],compstr
,len
*sizeof(WCHAR
));
276 new_one
->dwCursorPos
= len
;
285 static HIMCC
updateResultStr(HIMCC old
, LPWSTR resultstr
, DWORD len
)
287 /* we need to make sure the ResultStr and ResultClause fields are all
291 LPBYTE newdata
= NULL
;
292 LPBYTE olddata
= NULL
;
293 LPCOMPOSITIONSTRING new_one
;
294 LPCOMPOSITIONSTRING lpcs
= NULL
;
295 INT current_offset
= 0;
297 TRACE("%s, %li\n",debugstr_wn(resultstr
,len
),len
);
299 if (old
== NULL
&& resultstr
== NULL
&& len
== 0)
302 if (resultstr
== NULL
&& len
!= 0)
304 ERR("resultstr is NULL however we have a len! Please report\n");
310 olddata
= ImmLockIMCC(old
);
311 lpcs
= (LPCOMPOSITIONSTRING
)olddata
;
314 needed_size
= sizeof(COMPOSITIONSTRING
) + len
* sizeof(WCHAR
) +
319 needed_size
+= lpcs
->dwCompReadAttrLen
;
320 needed_size
+= lpcs
->dwCompReadClauseLen
;
321 needed_size
+= lpcs
->dwCompReadStrLen
* sizeof(WCHAR
);
322 needed_size
+= lpcs
->dwCompAttrLen
;
323 needed_size
+= lpcs
->dwCompClauseLen
;
324 needed_size
+= lpcs
->dwCompStrLen
* sizeof(WCHAR
);
325 needed_size
+= lpcs
->dwResultReadClauseLen
;
326 needed_size
+= lpcs
->dwResultReadStrLen
* sizeof(WCHAR
);
327 needed_size
+= lpcs
->dwPrivateSize
;
329 rc
= ImmCreateIMCC(needed_size
);
330 newdata
= ImmLockIMCC(rc
);
331 new_one
= (LPCOMPOSITIONSTRING
)newdata
;
333 new_one
->dwSize
= needed_size
;
334 current_offset
= sizeof(COMPOSITIONSTRING
);
337 current_offset
= updateField(lpcs
->dwCompReadAttrLen
,
338 lpcs
->dwCompReadAttrOffset
,
339 current_offset
, newdata
, olddata
,
340 &new_one
->dwCompReadAttrLen
,
341 &new_one
->dwCompReadAttrOffset
, FALSE
);
343 current_offset
= updateField(lpcs
->dwCompReadClauseLen
,
344 lpcs
->dwCompReadClauseOffset
,
345 current_offset
, newdata
, olddata
,
346 &new_one
->dwCompReadClauseLen
,
347 &new_one
->dwCompReadClauseOffset
, FALSE
);
349 current_offset
= updateField(lpcs
->dwCompReadStrLen
,
350 lpcs
->dwCompReadStrOffset
,
351 current_offset
, newdata
, olddata
,
352 &new_one
->dwCompReadStrLen
,
353 &new_one
->dwCompReadStrOffset
, TRUE
);
355 current_offset
= updateField(lpcs
->dwCompAttrLen
,
356 lpcs
->dwCompAttrOffset
,
357 current_offset
, newdata
, olddata
,
358 &new_one
->dwCompAttrLen
,
359 &new_one
->dwCompAttrOffset
, FALSE
);
361 current_offset
= updateField(lpcs
->dwCompClauseLen
,
362 lpcs
->dwCompClauseOffset
,
363 current_offset
, newdata
, olddata
,
364 &new_one
->dwCompClauseLen
,
365 &new_one
->dwCompClauseOffset
, FALSE
);
367 current_offset
= updateField(lpcs
->dwCompStrLen
,
368 lpcs
->dwCompStrOffset
,
369 current_offset
, newdata
, olddata
,
370 &new_one
->dwCompStrLen
,
371 &new_one
->dwCompStrOffset
, TRUE
);
373 new_one
->dwCursorPos
= lpcs
->dwCursorPos
;
374 new_one
->dwDeltaStart
= 0;
376 current_offset
= updateField(lpcs
->dwResultReadClauseLen
,
377 lpcs
->dwResultReadClauseOffset
,
378 current_offset
, newdata
, olddata
,
379 &new_one
->dwResultReadClauseLen
,
380 &new_one
->dwResultReadClauseOffset
, FALSE
);
382 current_offset
= updateField(lpcs
->dwResultReadStrLen
,
383 lpcs
->dwResultReadStrOffset
,
384 current_offset
, newdata
, olddata
,
385 &new_one
->dwResultReadStrLen
,
386 &new_one
->dwResultReadStrOffset
, TRUE
);
388 /* new ResultClause , ResultStr */
390 current_offset
= updateField(lpcs
->dwPrivateSize
,
391 lpcs
->dwPrivateOffset
,
392 current_offset
, newdata
, olddata
,
393 &new_one
->dwPrivateSize
,
394 &new_one
->dwPrivateOffset
, FALSE
);
401 new_one
->dwResultClauseLen
= sizeof(DWORD
) * 2;
402 new_one
->dwResultClauseOffset
= current_offset
;
403 *(DWORD
*)(&newdata
[current_offset
]) = 0;
404 current_offset
+= sizeof(DWORD
);
405 *(DWORD
*)(&newdata
[current_offset
]) = len
;
406 current_offset
+= sizeof(DWORD
);
409 new_one
->dwResultClauseLen
= 0;
412 new_one
->dwResultStrLen
= len
;
415 new_one
->dwResultStrOffset
= current_offset
;
416 memcpy(&newdata
[current_offset
],resultstr
,len
*sizeof(WCHAR
));
425 static void GenerateIMEMessage(HIMC hIMC
, UINT msg
, WPARAM wParam
,
428 LPINPUTCONTEXT lpIMC
;
429 LPTRANSMSG lpTransMsg
;
431 lpIMC
= LockRealIMC(hIMC
);
435 lpIMC
->hMsgBuf
= ImmReSizeIMCC(lpIMC
->hMsgBuf
, (lpIMC
->dwNumMsgBuf
+ 1) *
440 lpTransMsg
= ImmLockIMCC(lpIMC
->hMsgBuf
);
444 lpTransMsg
+= lpIMC
->dwNumMsgBuf
;
445 lpTransMsg
->message
= msg
;
446 lpTransMsg
->wParam
= wParam
;
447 lpTransMsg
->lParam
= lParam
;
449 ImmUnlockIMCC(lpIMC
->hMsgBuf
);
450 lpIMC
->dwNumMsgBuf
++;
452 ImmGenerateMessage(RealIMC(hIMC
));
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
:
575 TRACE("IMC_SETOPENSTATUS\n");
578 preedit_params
.hwnd
= lpIMC
->hWnd
;
579 preedit_params
.open
= lpIMC
->fOpen
;
580 X11DRV_CALL( xim_preedit_state
, &preedit_params
);
583 LPIMEPRIVATE myPrivate
;
585 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
586 if (myPrivate
->bInComposition
)
588 X11DRV_CALL( xim_reset
, lpIMC
->hWnd
);
589 GenerateIMEMessage(hIMC
, WM_IME_ENDCOMPOSITION
, 0, 0);
590 myPrivate
->bInComposition
= FALSE
;
592 ImmUnlockIMCC(lpIMC
->hPrivate
);
596 default: FIXME("Unknown\n"); break;
599 case NI_COMPOSITIONSTR
:
605 LPIMEPRIVATE myPrivate
;
609 TRACE("CPS_COMPLETE\n");
611 /* clear existing result */
612 newCompStr
= updateResultStr(lpIMC
->hCompStr
, NULL
, 0);
614 ImmDestroyIMCC(lpIMC
->hCompStr
);
615 lpIMC
->hCompStr
= newCompStr
;
617 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
618 if ((str
= input_context_get_comp_str( lpIMC
, FALSE
, &len
)))
620 WCHAR param
= str
[0];
622 newCompStr
= updateResultStr( lpIMC
->hCompStr
, str
, len
);
623 ImmDestroyIMCC(lpIMC
->hCompStr
);
624 lpIMC
->hCompStr
= newCompStr
;
625 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
626 ImmDestroyIMCC(lpIMC
->hCompStr
);
627 lpIMC
->hCompStr
= newCompStr
;
629 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, 0,
632 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, param
,
633 GCS_RESULTSTR
|GCS_RESULTCLAUSE
);
635 GenerateIMEMessage(hIMC
,WM_IME_ENDCOMPOSITION
, 0, 0);
638 else if (myPrivate
->bInComposition
)
639 GenerateIMEMessage(hIMC
,WM_IME_ENDCOMPOSITION
, 0, 0);
641 myPrivate
->bInComposition
= FALSE
;
642 ImmUnlockIMCC(lpIMC
->hPrivate
);
647 case CPS_CONVERT
: FIXME("CPS_CONVERT\n"); break;
648 case CPS_REVERT
: FIXME("CPS_REVERT\n"); break;
651 LPIMEPRIVATE myPrivate
;
653 TRACE("CPS_CANCEL\n");
655 X11DRV_CALL( xim_reset
, lpIMC
->hWnd
);
658 ImmDestroyIMCC(lpIMC
->hCompStr
);
659 lpIMC
->hCompStr
= ImeCreateBlankCompStr();
661 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
662 if (myPrivate
->bInComposition
)
664 GenerateIMEMessage(hIMC
, WM_IME_ENDCOMPOSITION
, 0, 0);
665 myPrivate
->bInComposition
= FALSE
;
667 ImmUnlockIMCC(lpIMC
->hPrivate
);
671 default: FIXME("Unknown\n"); break;
674 default: FIXME("Unknown Message\n"); break;
681 BOOL WINAPI
ImeSetCompositionString(HIMC hIMC
, DWORD dwIndex
, LPCVOID lpComp
,
682 DWORD dwCompLen
, LPCVOID lpRead
,
685 LPINPUTCONTEXT lpIMC
;
688 LPIMEPRIVATE myPrivate
;
690 TRACE("(%p, %ld, %p, %ld, %p, %ld):\n",
691 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
694 if (hIMC
!= FROM_X11
)
695 FIXME("PROBLEM: This only sets the wine level string\n");
699 * this sets the composition string in the imm32.dll level
700 * of the composition buffer. we cannot manipulate the xim level
701 * buffer, which means that once the xim level buffer changes again
702 * any call to this function from the application will be lost
705 if (lpRead
&& dwReadLen
)
706 FIXME("Reading string unimplemented\n");
708 lpIMC
= LockRealIMC(hIMC
);
713 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
715 if (dwIndex
== SCS_SETSTR
)
719 if (!myPrivate
->bInComposition
)
721 GenerateIMEMessage(hIMC
, WM_IME_STARTCOMPOSITION
, 0, 0);
722 myPrivate
->bInComposition
= TRUE
;
725 /* clear existing result */
726 newCompStr
= updateResultStr(lpIMC
->hCompStr
, NULL
, 0);
727 ImmDestroyIMCC(lpIMC
->hCompStr
);
728 lpIMC
->hCompStr
= newCompStr
;
732 if (dwCompLen
&& lpComp
)
734 newCompStr
= updateCompStr(lpIMC
->hCompStr
, (LPCWSTR
)lpComp
, dwCompLen
/ sizeof(WCHAR
));
735 ImmDestroyIMCC(lpIMC
->hCompStr
);
736 lpIMC
->hCompStr
= newCompStr
;
738 wParam
= ((const WCHAR
*)lpComp
)[0];
739 flags
|= GCS_COMPCLAUSE
| GCS_COMPATTR
| GCS_DELTASTART
;
743 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
744 ImmDestroyIMCC(lpIMC
->hCompStr
);
745 lpIMC
->hCompStr
= newCompStr
;
749 GenerateIMEMessage(hIMC
, WM_IME_COMPOSITION
, wParam
, flags
);
750 ImmUnlockIMCC(lpIMC
->hPrivate
);
756 /* Interfaces to XIM and other parts of winex11drv */
758 NTSTATUS
x11drv_ime_set_open_status( UINT open
)
762 imc
= RealIMC(FROM_X11
);
763 ImmSetOpenStatus(imc
, open
);
767 NTSTATUS
x11drv_ime_set_composition_status( UINT open
)
770 LPINPUTCONTEXT lpIMC
;
771 LPIMEPRIVATE myPrivate
;
773 imc
= RealIMC(FROM_X11
);
774 lpIMC
= ImmLockIMC(imc
);
778 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
780 if (open
&& !myPrivate
->bInComposition
)
782 GenerateIMEMessage(imc
, WM_IME_STARTCOMPOSITION
, 0, 0);
784 else if (!open
&& myPrivate
->bInComposition
)
786 ShowWindow(myPrivate
->hwndDefault
, SW_HIDE
);
787 ImmDestroyIMCC(lpIMC
->hCompStr
);
788 lpIMC
->hCompStr
= ImeCreateBlankCompStr();
789 GenerateIMEMessage(imc
, WM_IME_ENDCOMPOSITION
, 0, 0);
791 myPrivate
->bInComposition
= open
;
793 ImmUnlockIMCC(lpIMC
->hPrivate
);
798 NTSTATUS
x11drv_ime_get_cursor_pos( UINT arg
)
800 LPINPUTCONTEXT lpIMC
;
802 LPCOMPOSITIONSTRING compstr
;
807 lpIMC
= LockRealIMC(FROM_X11
);
810 compstr
= ImmLockIMCC(lpIMC
->hCompStr
);
811 rc
= compstr
->dwCursorPos
;
812 ImmUnlockIMCC(lpIMC
->hCompStr
);
814 UnlockRealIMC(FROM_X11
);
818 NTSTATUS
x11drv_ime_set_cursor_pos( UINT pos
)
820 LPINPUTCONTEXT lpIMC
;
821 LPCOMPOSITIONSTRING compstr
;
826 lpIMC
= LockRealIMC(FROM_X11
);
830 compstr
= ImmLockIMCC(lpIMC
->hCompStr
);
833 UnlockRealIMC(FROM_X11
);
837 compstr
->dwCursorPos
= pos
;
838 ImmUnlockIMCC(lpIMC
->hCompStr
);
839 UnlockRealIMC(FROM_X11
);
840 GenerateIMEMessage(FROM_X11
, WM_IME_COMPOSITION
, pos
, GCS_CURSORPOS
);
844 NTSTATUS
x11drv_ime_update_association( UINT arg
)
846 HWND focus
= UlongToHandle( arg
);
848 ImmGetContext(focus
);
850 if (focus
&& hSelectedFrom
)
851 ImmAssociateContext(focus
,RealIMC(FROM_X11
));
856 NTSTATUS WINAPI
x11drv_ime_set_composition_string( void *param
, ULONG size
)
858 return ImeSetCompositionString(FROM_X11
, SCS_SETSTR
, param
, size
, NULL
, 0);
861 NTSTATUS WINAPI
x11drv_ime_set_result( void *params
, ULONG len
)
863 WCHAR
*lpResult
= params
;
865 LPINPUTCONTEXT lpIMC
;
867 LPIMEPRIVATE myPrivate
;
871 len
/= sizeof(WCHAR
);
872 if ((focus
= GetFocus()))
873 x11drv_ime_update_association( HandleToUlong( focus
));
875 imc
= RealIMC(FROM_X11
);
876 lpIMC
= ImmLockIMC(imc
);
880 newCompStr
= updateCompStr(lpIMC
->hCompStr
, NULL
, 0);
881 ImmDestroyIMCC(lpIMC
->hCompStr
);
882 lpIMC
->hCompStr
= newCompStr
;
884 newCompStr
= updateResultStr(lpIMC
->hCompStr
, lpResult
, len
);
885 ImmDestroyIMCC(lpIMC
->hCompStr
);
886 lpIMC
->hCompStr
= newCompStr
;
888 myPrivate
= ImmLockIMCC(lpIMC
->hPrivate
);
889 inComp
= myPrivate
->bInComposition
;
890 ImmUnlockIMCC(lpIMC
->hPrivate
);
894 ImmSetOpenStatus(imc
, TRUE
);
895 GenerateIMEMessage(imc
, WM_IME_STARTCOMPOSITION
, 0, 0);
898 GenerateIMEMessage(imc
, WM_IME_COMPOSITION
, 0, GCS_COMPSTR
);
899 GenerateIMEMessage(imc
, WM_IME_COMPOSITION
, lpResult
[0], GCS_RESULTSTR
|GCS_RESULTCLAUSE
);
900 GenerateIMEMessage(imc
, WM_IME_ENDCOMPOSITION
, 0, 0);
903 ImmSetOpenStatus(imc
, FALSE
);