Changes in crossover-wine-src-6.1.0 except for configure
[wine/hacks.git] / dlls / winex11.drv / xim.c
blob2cb4eef3d4c92be303cda7d26ce525357fa4c67d
1 /*
2 * Functions for further XIM control
4 * Copyright 2003 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
21 #include "config.h"
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "wingdi.h"
30 #include "winnls.h"
31 #include "x11drv.h"
32 #include "imm.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
37 /* this must match with imm32/imm.c */
38 #define FROM_IME 0xcafe1337
40 BOOL ximInComposeMode=FALSE;
42 #ifdef __APPLE__
43 extern void MAC_SetupXIM();
44 #endif
46 static HIMC root_context;
47 static XIMStyle ximStyle = 0;
48 static XIMStyle ximStyleRoot = 0;
50 /* moved here from imm32 for dll separation */
51 static DWORD dwCompStringLength = 0;
52 static LPBYTE CompositionString = NULL;
53 static DWORD dwCompStringSize = 0;
54 static LPBYTE ResultString = NULL;
55 static DWORD dwResultStringSize = 0;
57 static HMODULE hImmDll = NULL;
58 HIMC (WINAPI *pImmAssociateContext)(HWND,HIMC);
59 HIMC (WINAPI *pImmCreateContext)(void);
60 VOID (WINAPI *pImmSetOpenStatus)(HIMC,BOOL);
61 BOOL (WINAPI *pImmSetCompositionString)(HIMC, DWORD, LPWSTR,
62 DWORD, LPWSTR, DWORD);
63 VOID (WINAPI *pImmNotifyIME)(HIMC, DWORD, DWORD, DWORD);
65 /* WINE specific messages from the xim in x11drv level */
67 #define STYLE_OFFTHESPOT (XIMPreeditArea | XIMStatusArea)
68 #define STYLE_OVERTHESPOT (XIMPreeditPosition | XIMStatusNothing)
69 #define STYLE_ROOT (XIMPreeditNothing | XIMStatusNothing)
70 /* this uses all the callbacks to utilize full IME support */
71 #define STYLE_CALLBACK (XIMPreeditCallbacks | XIMStatusNothing)
72 /* inorder to enable deadkey support */
73 #define STYLE_NONE (XIMPreeditNothing | XIMStatusNothing)
76 * here are the functions that sort of marshall calls into IMM32.DLL
78 static void LoadImmDll(void)
80 hImmDll = LoadLibraryA("imm32.dll");
82 pImmAssociateContext = (void *)GetProcAddress(hImmDll, "ImmAssociateContext");
83 if (!pImmAssociateContext)
84 WARN("IMM: pImmAssociateContext not found in DLL\n");
86 pImmCreateContext = (void *)GetProcAddress(hImmDll, "ImmCreateContext");
87 if (!pImmCreateContext)
88 WARN("IMM: pImmCreateContext not found in DLL\n");
90 pImmSetOpenStatus = (void *)GetProcAddress( hImmDll, "ImmSetOpenStatus");
91 if (!pImmSetOpenStatus)
92 WARN("IMM: pImmSetOpenStatus not found in DLL\n");
94 pImmSetCompositionString =(void *)GetProcAddress(hImmDll, "ImmSetCompositionStringW");
96 if (!pImmSetCompositionString)
97 WARN("IMM: pImmSetCompositionStringW not found in DLL\n");
99 pImmNotifyIME = (void *)GetProcAddress( hImmDll, "ImmNotifyIME");
101 if (!pImmNotifyIME)
102 WARN("IMM: pImmNotifyIME not found in DLL\n");
105 static BOOL X11DRV_ImmSetInternalString(DWORD dwIndex, DWORD dwOffset,
106 DWORD selLength, LPWSTR lpComp, DWORD dwCompLen)
108 /* Composition strings are edited in chunks */
109 unsigned int byte_length = dwCompLen * sizeof(WCHAR);
110 unsigned int byte_offset = dwOffset * sizeof(WCHAR);
111 unsigned int byte_selection = selLength * sizeof(WCHAR);
112 BOOL rc = FALSE;
114 TRACE("( %i, %i, %d, %p, %d):\n", dwOffset, selLength, dwIndex, lpComp, dwCompLen );
116 if (dwIndex == GCS_COMPSTR)
118 unsigned int i,j;
119 LPBYTE ptr_new;
120 LPBYTE ptr_old;
122 if ((dwCompLen == 0) && (selLength == 0))
124 /* DO Nothing */
126 /* deletion occurred */
127 else if ((dwCompLen== 0) && (selLength != 0))
129 if (dwCompStringLength)
131 for (i = 0; i < byte_selection; i++)
133 if (byte_offset+byte_selection+i <
134 dwCompStringLength)
136 CompositionString[byte_offset + i] =
137 CompositionString[byte_offset + byte_selection + i];
139 else
140 CompositionString[byte_offset + i] = 0;
142 /* clean up the end */
143 dwCompStringLength -= byte_selection;
145 i = dwCompStringLength;
146 while (i < dwCompStringSize)
148 CompositionString[i++] = 0;
152 else
154 int byte_expansion = byte_length - byte_selection;
156 if (byte_expansion + dwCompStringLength >= dwCompStringSize)
158 if (CompositionString)
159 CompositionString =
160 HeapReAlloc(GetProcessHeap(), 0,
161 CompositionString,
162 dwCompStringSize +
163 byte_expansion);
164 else
165 CompositionString =
166 HeapAlloc(GetProcessHeap(), 0, dwCompStringSize +
167 byte_expansion);
169 memset(&(CompositionString[dwCompStringSize]), 0,
170 byte_expansion);
172 dwCompStringSize += byte_expansion;
175 ptr_new = ((LPBYTE)lpComp);
176 ptr_old = CompositionString + byte_offset + byte_selection;
178 dwCompStringLength += byte_expansion;
180 for (j=0,i = byte_offset; i < dwCompStringSize; i++)
182 if (j < byte_length)
184 CompositionString[i] = ptr_new[j++];
186 else
188 if (ptr_old < CompositionString + dwCompStringSize)
190 CompositionString[i] = *ptr_old;
191 ptr_old++;
193 else
194 CompositionString[i] = 0;
199 if (pImmSetCompositionString)
200 rc = pImmSetCompositionString((HIMC)FROM_IME, SCS_SETSTR,
201 (LPWSTR)CompositionString, dwCompStringLength,
202 NULL, 0);
204 else if ((dwIndex == GCS_RESULTSTR) && (lpComp) && (dwCompLen))
206 if (dwResultStringSize)
207 HeapFree(GetProcessHeap(),0,ResultString);
208 dwResultStringSize= byte_length;
209 ResultString= HeapAlloc(GetProcessHeap(),0,byte_length);
210 memcpy(ResultString,lpComp,byte_length);
212 if (pImmSetCompositionString)
213 rc = pImmSetCompositionString((HIMC)FROM_IME, SCS_SETSTR,
214 (LPWSTR)ResultString, dwResultStringSize,
215 NULL, 0);
217 if (pImmNotifyIME)
218 pImmNotifyIME((HIMC)FROM_IME, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
221 return rc;
224 void X11DRV_XIMLookupChars( const char *str, DWORD count )
226 DWORD dwOutput;
227 WCHAR wcOutput[64];
228 HWND focus;
230 dwOutput = MultiByteToWideChar(CP_UNIXCP, 0, str, count, wcOutput, sizeof(wcOutput)/sizeof(WCHAR));
232 if (pImmAssociateContext && (focus = GetFocus()))
233 pImmAssociateContext(focus,root_context);
235 X11DRV_ImmSetInternalString(GCS_RESULTSTR,0,0,wcOutput,dwOutput);
238 static void X11DRV_ImmSetOpenStatus(BOOL fOpen)
240 if (fOpen == FALSE)
242 if (dwCompStringSize)
243 HeapFree(GetProcessHeap(),0,CompositionString);
245 dwCompStringSize = 0;
246 dwCompStringLength = 0;
247 CompositionString = NULL;
249 if (dwResultStringSize)
250 HeapFree(GetProcessHeap(),0,ResultString);
252 dwResultStringSize = 0;
253 ResultString = NULL;
256 if (pImmSetOpenStatus)
257 pImmSetOpenStatus((HIMC)FROM_IME,fOpen);
260 static int XIMPreEditStartCallback(XIC ic, XPointer client_data, XPointer call_data)
262 TRACE("PreEditStartCallback %p\n",ic);
263 X11DRV_ImmSetOpenStatus(TRUE);
264 ximInComposeMode = TRUE;
265 return -1;
268 static void XIMPreEditDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
270 TRACE("PreeditDoneCallback %p\n",ic);
271 ximInComposeMode = FALSE;
272 X11DRV_ImmSetOpenStatus(FALSE);
275 static void XIMPreEditDrawCallback(XIM ic, XPointer client_data,
276 XIMPreeditDrawCallbackStruct *P_DR)
278 DWORD dwOutput;
279 WCHAR wcOutput[64];
281 TRACE("PreEditDrawCallback %p\n",ic);
283 if (P_DR)
285 int sel = P_DR->chg_first;
286 int len = P_DR->chg_length;
287 if (P_DR->text)
289 if (! P_DR->text->encoding_is_wchar)
291 TRACE("multibyte\n");
292 dwOutput = MultiByteToWideChar(CP_UNIXCP, 0,
293 P_DR->text->string.multi_byte, -1,
294 wcOutput, 64);
296 /* ignore null */
297 dwOutput --;
298 X11DRV_ImmSetInternalString (GCS_COMPSTR, sel, len, wcOutput, dwOutput);
300 else
302 FIXME("wchar PROBIBILY WRONG\n");
303 X11DRV_ImmSetInternalString (GCS_COMPSTR, sel, len,
304 (LPWSTR)P_DR->text->string.wide_char,
305 P_DR->text->length);
308 else
309 X11DRV_ImmSetInternalString (GCS_COMPSTR, sel, len, NULL, 0);
311 TRACE("Finished\n");
314 static void XIMPreEditCaretCallback(XIC ic, XPointer client_data,
315 XIMPreeditCaretCallbackStruct *P_C)
317 FIXME("PreeditCaretCalback %p\n",ic);
320 void X11DRV_ForceXIMReset(HWND hwnd)
322 XIC ic = X11DRV_get_ic(hwnd);
323 if (ic)
325 char* leftover;
326 TRACE("Forcing Reset %p\n",ic);
327 wine_tsx11_lock();
328 leftover = XmbResetIC(ic);
329 XFree(leftover);
330 wine_tsx11_unlock();
334 /***********************************************************************
335 * X11DRV Ime creation
337 XIM X11DRV_SetupXIM(Display *display, const char *input_style)
339 XIMStyle ximStyleRequest, ximStyleCallback, ximStyleNone;
340 XIMStyles *ximStyles = NULL;
341 INT i;
342 XIM xim;
344 ximStyleRequest = STYLE_CALLBACK;
346 #ifdef __APPLE__
347 if(!hImmDll)
349 LoadImmDll();
351 if (pImmCreateContext)
353 root_context = pImmCreateContext();
354 if (pImmAssociateContext)
355 pImmAssociateContext(0,root_context);
359 MAC_SetupXIM();
360 #endif
362 if (!strcasecmp(input_style, "offthespot"))
363 ximStyleRequest = STYLE_OFFTHESPOT;
364 else if (!strcasecmp(input_style, "overthespot"))
365 ximStyleRequest = STYLE_OVERTHESPOT;
366 else if (!strcasecmp(input_style, "root"))
367 ximStyleRequest = STYLE_ROOT;
369 wine_tsx11_lock();
371 if(!XSupportsLocale())
373 WARN("X does not support locale.\n");
374 goto err;
376 if(XSetLocaleModifiers("") == NULL)
378 WARN("Could not set locale modifiers.\n");
379 goto err;
382 xim = XOpenIM(display, NULL, NULL, NULL);
383 if (xim == NULL)
385 WARN("Could not open input method.\n");
386 goto err;
389 TRACE("X display of IM = %p\n", XDisplayOfIM(xim));
390 TRACE("Using %s locale of Input Method\n", XLocaleOfIM(xim));
392 XGetIMValues(xim, XNQueryInputStyle, &ximStyles, NULL);
393 if (ximStyles == 0)
395 WARN("Could not find supported input style.\n");
397 else
399 TRACE("ximStyles->count_styles = %d\n", ximStyles->count_styles);
401 ximStyleRoot = 0;
402 ximStyleNone = 0;
403 ximStyleCallback = 0;
405 for (i = 0; i < ximStyles->count_styles; ++i)
407 int style = ximStyles->supported_styles[i];
408 TRACE("ximStyles[%d] = %s%s%s%s%s\n", i,
409 (style&XIMPreeditArea)?"XIMPreeditArea ":"",
410 (style&XIMPreeditCallbacks)?"XIMPreeditCallbacks ":"",
411 (style&XIMPreeditPosition)?"XIMPreeditPosition ":"",
412 (style&XIMPreeditNothing)?"XIMPreeditNothing ":"",
413 (style&XIMPreeditNone)?"XIMPreeditNone ":"");
414 if (!ximStyle && (ximStyles->supported_styles[i] ==
415 ximStyleRequest))
417 ximStyle = ximStyleRequest;
418 TRACE("Setting Style: ximStyle = ximStyleRequest\n");
420 else if (!ximStyleRoot &&(ximStyles->supported_styles[i] ==
421 STYLE_ROOT))
423 ximStyleRoot = STYLE_ROOT;
424 TRACE("Setting Style: ximStyleRoot = STYLE_ROOT\n");
426 else if (!ximStyleCallback &&(ximStyles->supported_styles[i] ==
427 STYLE_CALLBACK))
429 ximStyleCallback = STYLE_CALLBACK;
430 TRACE("Setting Style: ximStyleCallback = STYLE_CALLBACK\n");
432 else if (!ximStyleNone && (ximStyles->supported_styles[i] ==
433 STYLE_NONE))
435 TRACE("Setting Style: ximStyleNone = STYLE_NONE\n");
436 ximStyleNone = STYLE_NONE;
439 XFree(ximStyles);
441 if (ximStyle == 0)
442 ximStyle = ximStyleRoot;
444 if (ximStyle == 0)
445 ximStyle = ximStyleNone;
447 if (ximStyleCallback == 0)
449 TRACE("No callback style avalable\n");
450 ximStyleCallback = ximStyle;
455 wine_tsx11_unlock();
457 if(!hImmDll)
459 LoadImmDll();
461 if (pImmCreateContext)
463 root_context = pImmCreateContext();
464 if (pImmAssociateContext)
465 pImmAssociateContext(0,root_context);
469 return xim;
471 err:
472 wine_tsx11_unlock();
473 return NULL;
477 XIC X11DRV_CreateIC(XIM xim, Display *display, Window win)
479 XFontSet fontSet = NULL;
480 char **list;
481 int count;
482 XPoint spot = {0};
483 XVaNestedList preedit = NULL;
484 XVaNestedList status = NULL;
485 XIC xic;
486 XIMCallback P_StartCB;
487 XIMCallback P_DoneCB;
488 XIMCallback P_DrawCB;
489 XIMCallback P_CaretCB;
490 LANGID langid = PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale()));
492 wine_tsx11_lock();
494 /* use complex and slow XIC initialization method only for CJK */
495 if (langid != LANG_CHINESE &&
496 langid != LANG_JAPANESE &&
497 langid != LANG_KOREAN)
499 xic = XCreateIC(xim,
500 XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
501 XNClientWindow, win,
502 XNFocusWindow, win,
503 NULL);
504 wine_tsx11_unlock();
505 return xic;
509 if (((ximStyle & (XIMPreeditNothing | XIMPreeditNone)) == 0) ||
510 ((ximStyle & (XIMStatusNothing | XIMStatusNone)) == 0))
512 fontSet = XCreateFontSet(display,
513 "*", /*FIXME*/
514 &list, &count, NULL);
516 TRACE("ximFontSet = %p\n", fontSet);
517 TRACE("list = %p, count = %d\n", list, count);
519 if (list != NULL)
521 int i;
523 for (i = 0; i < count; ++i)
525 TRACE("list[%d] = %s\n", i, list[i]);
527 XFreeStringList(list);
531 /* create callbacks */
532 P_StartCB.client_data = NULL;
533 P_StartCB.callback = (XIMProc)XIMPreEditStartCallback;
534 P_DoneCB.client_data = NULL;
535 P_DoneCB.callback = (XIMProc)XIMPreEditDoneCallback;
536 P_DrawCB.client_data = NULL;
537 P_DrawCB.callback = (XIMProc)XIMPreEditDrawCallback;
538 P_CaretCB.client_data = NULL;
539 P_CaretCB.callback = (XIMProc)XIMPreEditCaretCallback;
541 if ((ximStyle & (XIMPreeditNothing | XIMPreeditNone)) == 0)
543 preedit = XVaCreateNestedList(0,
544 XNFontSet, fontSet,
545 XNSpotLocation, &spot,
546 XNPreeditStartCallback, &P_StartCB,
547 XNPreeditDoneCallback, &P_DoneCB,
548 XNPreeditDrawCallback, &P_DrawCB,
549 XNPreeditCaretCallback, &P_CaretCB,
550 NULL);
551 TRACE("preedit = %p\n", preedit);
553 else
555 preedit = XVaCreateNestedList(0,
556 XNPreeditStartCallback, &P_StartCB,
557 XNPreeditDoneCallback, &P_DoneCB,
558 XNPreeditDrawCallback, &P_DrawCB,
559 XNPreeditCaretCallback, &P_CaretCB,
560 NULL);
562 TRACE("preedit = %p\n", preedit);
565 if ((ximStyle & (XIMStatusNothing | XIMStatusNone)) == 0)
567 status = XVaCreateNestedList(0,
568 XNFontSet, fontSet,
569 NULL);
570 TRACE("status = %p\n", status);
573 if (preedit != NULL && status != NULL)
575 xic = XCreateIC(xim,
576 XNInputStyle, ximStyle,
577 XNPreeditAttributes, preedit,
578 XNStatusAttributes, status,
579 XNClientWindow, win,
580 XNFocusWindow, win,
581 NULL);
583 else if (preedit != NULL)
585 xic = XCreateIC(xim,
586 XNInputStyle, ximStyle,
587 XNPreeditAttributes, preedit,
588 XNClientWindow, win,
589 XNFocusWindow, win,
590 NULL);
592 else if (status != NULL)
594 xic = XCreateIC(xim,
595 XNInputStyle, ximStyle,
596 XNStatusAttributes, status,
597 XNClientWindow, win,
598 XNFocusWindow, win,
599 NULL);
601 else
603 xic = XCreateIC(xim,
604 XNInputStyle, ximStyle,
605 XNClientWindow, win,
606 XNFocusWindow, win,
607 NULL);
610 TRACE("xic = %p\n", xic);
612 if (preedit != NULL)
613 XFree(preedit);
614 if (status != NULL)
615 XFree(status);
617 wine_tsx11_unlock();
619 return xic;