This patch is intended to implement XIM support in wine. I hope it will support Chinese, Japanese and Korean input method. But as I am Chinese I only tested it with Chinese IM. For this patch is based on the patch of Mike McCormack, which is made for Japanese IM, I think mine will work with Japanese too. But I am not sure whether this one can get along with Korean IMs. If u would like to try it, please give me some suggestions or/and bug reports. This patch implemented features include: One thread only create one connection with XIM server and one IC. Support OVER_THE_SPOT and ROOT IM style. Enable/disable XIM support by editing the config file. The font used in the XIM can be specified in the config file. Some other modifications for convenience purpose. Hope this one helps CJK users. ChangeLog: liuspider <liuspider@yahoo.com> * controls/edit.c - add a debug channel xim - add a message type WM_IME_CHAR * dlls/kernel/locale.c - handle charset * dlls/x11drv/X11_calls - add some X11 XIM calls * dlls/x11drv/event.c - add a debug channel xim - check whether keypress has been filter by XIM server - add set XIC focus in EVENT_FocusIn * dlls/x11drv/keyboard.c - add a debug channel xim - add XIM key handler : XIM_KeyEvent - check whether keypress has been filter by XIM server * dlls/x11drv/ts_xlib.c - add some functions used for XIM * dlls/x11drv/ts_xlib.h - add some functions used for XIM * wine/dlls/x11drv/window.c - a new function to get the XIC * wine/dlls/x11drv/x11drv_main.c - setup the connection with XIM server in thread initialisation routine - create XIC in thread initialisation routine - close connection in thread termination routine - destroy XIC in thread termination routine * documentation/samples/config - a new section [InputMethod] * include/winnls.h - add a constant LOCALE_SCHARSETNAMES * include/x11drv.h - add some variables to hold xim attributes NewFile: * dlls/x11drv/xim.h - CONSTANTs used in XIM input style ( sorry for the first bothering email ) Index: controls/edit.c =================================================================== RCS file: /home/wine/wine/controls/edit.c,v retrieving revision 1.108 diff -u -r1.108 edit.c --- controls/edit.c 2 Dec 2002 18:11:00 -0000 1.108 +++ controls/edit.c 13 Dec 2002 14:30:54 -0000 @@ -56,6 +56,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(edit); WINE_DECLARE_DEBUG_CHANNEL(combo); WINE_DECLARE_DEBUG_CHANNEL(relay); +WINE_DECLARE_DEBUG_CHANNEL(xim); #define BUFLIMIT_MULTI 65534 /* maximum buffer size (not including '\0') FIXME: BTW, new specs say 65535 (do you dare ???) */ @@ -760,6 +761,19 @@ } } break; + case WM_IME_CHAR: + { + WCHAR charW = wParam; + if ((charW == VK_RETURN || charW == VK_ESCAPE) && es->hwndListBox) + { + if (SendMessageW(GetParent(hwnd), CB_GETDROPPEDSTATE, 0, 0)) + SendMessageW(GetParent(hwnd), WM_KEYDOWN, charW, 0); + break; + } + TRACE_(xim)("charW:%d\n",charW); + EDIT_WM_Char(es, charW); + break; + } case WM_CHAR: { Index: dlls/kernel/locale.c =================================================================== RCS file: /home/wine/wine/dlls/kernel/locale.c,v retrieving revision 1.5 diff -u -r1.5 locale.c --- dlls/kernel/locale.c 13 Sep 2002 18:52:01 -0000 1.5 +++ dlls/kernel/locale.c 13 Dec 2002 14:30:55 -0000 @@ -49,6 +49,7 @@ typedef struct { char lang[128]; char country[128]; + char charset[128]; LANGID found_lang_id[NLS_MAX_LANGUAGES]; char found_language[NLS_MAX_LANGUAGES][3]; char found_country[NLS_MAX_LANGUAGES][3]; @@ -179,6 +180,7 @@ LCID lcid = MAKELCID(LangID, SORT_DEFAULT); char buf_language[128]; char buf_country[128]; + char buf_charset[128]; char buf_en_language[128]; TRACE("%04X\n", (UINT)LangID); @@ -187,6 +189,7 @@ buf_language[0] = 0; buf_country[0] = 0; + buf_charset[0] = '\0'; GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME|LOCALE_NOUSEROVERRIDE|LOCALE_USE_CP_ACP, buf_language, sizeof(buf_language)); @@ -196,16 +199,63 @@ buf_country, sizeof(buf_country)); TRACE("LOCALE_SISO3166CTRYNAME: %s\n", buf_country); + GetLocaleInfoA(lcid, LOCALE_SCHARSETNAMES | LOCALE_NOUSEROVERRIDE, + buf_charset, sizeof(buf_charset)); + TRACE("LOCALE_SCHARSETNAMES: %s\n", buf_charset); + if(l_data->lang && strlen(l_data->lang) > 0 && !strcasecmp(l_data->lang, buf_language)) { if(l_data->country && strlen(l_data->country) > 0) { if(!strcasecmp(l_data->country, buf_country)) { +#if (0) l_data->found_lang_id[0] = LangID; l_data->n_found = 1; TRACE("Found lang_id %04X for %s_%s\n", LangID, l_data->lang, l_data->country); return FALSE; /* stop enumeration */ +#endif + char *p, *q; + + if (l_data->charset != NULL && strlen(l_data->charset) > 0) { + p = buf_charset; + do { + q = p; + if ((p = strchr(p, ',')) != NULL) { + *p++ = '\0'; + } + TRACE("q = 0x%x, %s\n", q, ((q == NULL) ? "" : q)); + if (q != NULL && strcasecmp(l_data->charset, q) == 0) { + l_data->found_lang_id[0] = LangID; + l_data->n_found = 1; + TRACE("Found lang_id %04X for %s_%s.%s\n", LangID, l_data->lang, l_data->country, l_data->charset); + return FALSE; + } + } while (p != NULL); + } else { + p = buf_charset; + do { + q = p; + if ((p = strchr(p, ',')) != NULL) { + *p++ = '\0'; + } + TRACE("q = 0x%x, %s\n", q, ((q == NULL) ? "" : q)); + if (q == NULL || *q == '\0') { + l_data->found_lang_id[0] = LangID; + l_data->n_found = 1; + TRACE("Found lang_id %04X for %s_%s\n", LangID, l_data->lang, l_data->country); + return FALSE; + } + } while (p != NULL); + } + if (l_data->n_found < NLS_MAX_LANGUAGES) { + l_data->found_lang_id[l_data->n_found] = LangID; + strncpy(l_data->found_country[l_data->n_found], buf_country, 3); + strncpy(l_data->found_language[l_data->n_found], buf_language, 3); + l_data->n_found++; + TRACE("Found lang_id %04X for %s_%s\n", LangID, l_data->lang, l_data->country); + return TRUE; + } } } else /* l_data->country not specified */ @@ -257,14 +307,15 @@ * * RETURNS: * the numeric code of the language used by Windows - * - * FIXME: Charset and Dialect are not handled */ static LANGID get_language_id(LPCSTR Lang, LPCSTR Country, LPCSTR Charset, LPCSTR Dialect) { LANG_FIND_DATA l_data; char lang_string[256]; + TRACE(" Lang(%s) Country(%s) CharSet(%s) Dialect(%s)\n", + Lang, Country, Charset, Dialect); + if(!Lang) { l_data.found_lang_id[0] = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); @@ -277,6 +328,10 @@ if(Country && strlen(Country) > 0) strncpy(l_data.country, Country, sizeof(l_data.country)); + if (Charset != NULL && strlen(Charset) > 0) { + strncpy(l_data.charset, Charset, sizeof(l_data.charset)); + } + EnumResourceLanguagesA(GetModuleHandleA("KERNEL32"), RT_STRINGA, (LPCSTR)LOCALE_ILANGUAGE, find_language_id_proc, (LPARAM)&l_data); @@ -287,6 +342,15 @@ strcat(lang_string, l_data.country); } + if (!l_data.n_found) { + if (l_data.charset != NULL && strlen(l_data.charset) > 0) { + MESSAGE("Warning: Language '%s.%s' was not found, retrying without charset name...\n", lang_string, l_data.charset); + l_data.charset[0] = '\0'; + EnumResourceLanguagesA(GetModuleHandleA("KERNEL32"), RT_STRINGA, + (LPCSTR) LOCALE_ILANGUAGE, find_language_id_proc, (LONG) &l_data); + } + } + if(!l_data.n_found) { if(l_data.country && strlen(l_data.country) > 0) @@ -304,6 +368,11 @@ { strcat(lang_string, "_"); strcat(lang_string, l_data.country); + } + + if (l_data.charset != NULL && strlen(l_data.charset) > 0) { + strcat(lang_string, "."); + strcat(lang_string, l_data.charset); } if(!l_data.n_found) Index: dlls/x11drv/X11_calls =================================================================== RCS file: /home/wine/wine/dlls/x11drv/X11_calls,v retrieving revision 1.1 diff -u -r1.1 X11_calls --- dlls/x11drv/X11_calls 25 Sep 2002 03:29:55 -0000 1.1 +++ dlls/x11drv/X11_calls 13 Dec 2002 14:30:55 -0000 @@ -10,13 +10,16 @@ XChangeGC XChangeProperty XChangeWindowAttributes +XCloseIM XCopyArea XCopyPlane XCreateBitmapFromData XCreateColormap +XCreateFontSet XCreatePixmap XDefineCursor XDeleteProperty +XDestroyIC XDrawArc XDrawLine XDrawLines @@ -26,13 +29,16 @@ XFillArc XFillPolygon XFillRectangle +XFilterEvent XFlush XFree XFreeColormap XFreeColors XFreeFont XFreeFontNames +XFreeFontSet XFreePixmap +XFreeStringList XGetAtomName XGetFontProperty XGetGeometry @@ -66,6 +72,7 @@ XSetForeground XSetFunction XSetGraphicsExposures +XSetICFocus XSetLineAttributes XSetScreenSaver XSetSelectionOwner @@ -78,3 +85,5 @@ XUngrabServer XUninstallColormap XUnmapWindow +XUnsetICFocus +XmbLookupString Index: dlls/x11drv/event.c =================================================================== RCS file: /home/wine/wine/dlls/x11drv/event.c,v retrieving revision 1.15 diff -u -r1.15 event.c --- dlls/x11drv/event.c 3 Dec 2002 23:34:54 -0000 1.15 +++ dlls/x11drv/event.c 13 Dec 2002 14:30:56 -0000 @@ -46,6 +46,7 @@ #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(event); +WINE_DECLARE_DEBUG_CHANNEL(xim); /* X context to associate a hwnd to an X window */ extern XContext winContext; @@ -191,7 +192,13 @@ HWND hWnd; Display *display = event->xany.display; - TRACE( "called.\n" ); + if( event->type != KeyPress && event->type != KeyRelease + && TSXFilterEvent(event, None)) + { + TRACE_(xim)("Filtered event: %s(%d) window %08x\n",event_names[event->type], + event->type, (unsigned int)event->xany.window); + return; + } switch (event->type) { @@ -475,6 +482,11 @@ */ static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event ) { + XIC xic = NULL; + xic = X11DRV_GetXIC(); + if(xic) + TSXSetICFocus(xic); + if (!hwnd) return; TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] ); Index: dlls/x11drv/keyboard.c =================================================================== RCS file: /home/wine/wine/dlls/x11drv/keyboard.c,v retrieving revision 1.15 diff -u -r1.15 keyboard.c --- dlls/x11drv/keyboard.c 5 Dec 2002 19:55:04 -0000 1.15 +++ dlls/x11drv/keyboard.c 13 Dec 2002 14:30:57 -0000 @@ -39,6 +39,7 @@ #include <string.h> #include "windef.h" +#include "heap.h" #include "wingdi.h" #include "wine/winuser16.h" #include "winnls.h" @@ -49,6 +50,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(keyboard); WINE_DECLARE_DEBUG_CHANNEL(key); WINE_DECLARE_DEBUG_CHANNEL(dinput); +WINE_DECLARE_DEBUG_CHANNEL(xim); int min_keycode, max_keycode, keysyms_per_keycode; WORD keyc2vkey[256], keyc2scan[256]; @@ -61,6 +63,7 @@ #endif static char KEYBOARD_MapDeadKeysym(KeySym keysym); +extern Window root_window; /* Keyboard translation tables */ #define MAIN_LEN 48 @@ -939,6 +942,124 @@ KEYBOARD_UpdateOneState( VK_SHIFT, shift, time ); } +#define NALLOC 64 +static BOOL XIM_KeyEvent(HWND hwnd, XKeyEvent *event) +{ + static BOOL updatedXIMPos = 0; + BOOL done = FALSE; + Window orgWindow = event->window; + struct x11drv_thread_data *data = NtCurrentTeb()->driver_data; + + TRACE_(xim)("hwnd %04x root_window(%08lx)\n", (unsigned int) hwnd, root_window); + + event->window = root_window; + if (!data->xim) + done = FALSE; /* No input method defined */ + else if (TSXFilterEvent((XEvent *) event, None)) + { + TRACE_(xim)("Filtered.\n"); + if (!updatedXIMPos){ + XIC xic = X11DRV_GetXIC(); + POINT p; + XVaNestedList preedit_attr; + GetCaretPos(&p); + ClientToScreen(hwnd, &p); + XPoint spot; + spot.x = p.x; + spot.y = p.y; + spot.y += 25; //FIXME: How to get the caret's height + preedit_attr = XVaCreateNestedList(0, + XNSpotLocation, &spot, + NULL); + XSetICValues(xic,XNPreeditAttributes,preedit_attr,NULL); + /* use this variable to check whether we need to update XIM position */ + updatedXIMPos = 1; + } + done = TRUE; + } + else if (event->type == KeyPress) + { + XIC xic; + KeySym keysym; + Status status; + int i, nbyte; + DWORD dwOutput; + WCHAR wcOutput[NALLOC]; + LPSTR bytes; + DWORD nalloc = NALLOC; + Window w = root_window; + + updatedXIMPos = 0; + if ((xic = X11DRV_GetXIC()) == NULL) + { + WARN_(xim)("Unable tp retrieve input context\n"); + return FALSE; + } + + bytes = HeapAlloc(GetProcessHeap(),0,NALLOC); + + nbyte = TSXmbLookupString(xic, event, bytes, nalloc, &keysym, &status); + TRACE_(xim)("nbyte = %d, status = 0x%x\n", nbyte, status); + + if (status == XBufferOverflow) + { + nalloc = nbyte; + bytes = HeapReAlloc(GetProcessHeap(), 0, bytes, nbyte); + nbyte = TSXmbLookupString(xic, event, bytes, nalloc, &keysym, &status); + TRACE_(xim)("nbyte = %d, status = 0x%x\n", nbyte, status); + } + + switch (status) + { + case XLookupBoth: + if (keysym < 128 || (keysym & 0xff00) == 0xff00) + { + TRACE_(xim)("keysym = 0x%x\n", (int)keysym); + break; /* Leave to the default handler */ + } + /* fall through */ + case XLookupChars: + { + INT codepage = GetACP(); + if (codepage == 932) + { + /* + * Japanese is encoded with windows as SJIS (932) however + * Under unix we use EUS (20932) So we need to translate + * the input as 20932... + */ + dwOutput = MultiByteToWideChar(20932, + 0, bytes, nbyte, wcOutput, sizeof(wcOutput)); + } + else + dwOutput = MultiByteToWideChar(codepage, + 0, bytes, nbyte, wcOutput, sizeof(wcOutput)); + + for(i=0; i<dwOutput; i++) + { + TRACE_(xim)("sending wchar %04x\n", wcOutput[i]); + PostMessageW(hwnd, WM_IME_CHAR, wcOutput[i], 1); + } + done = True; + break; + } + + case XLookupKeySym: + TRACE_(xim)("XLookupKeySym\n"); + break; /* Leave to the default handler */ + + case XLookupNone: + TRACE_(xim)("XLookupNone\n"); + done = True; /* No further processing is necessary */ + break; + } + + HeapFree(GetProcessHeap(),0,bytes); + } + event->window = orgWindow; + return done; +} + /*********************************************************************** * X11DRV_KeyEvent * @@ -953,6 +1074,10 @@ int ascii_chars; DWORD event_time = event->time - X11DRV_server_startticks; + + /* forward to XIM */ + if(XIM_KeyEvent(GetFocus(), event) && event->type == KeyPress) + return; /* this allows support for dead keys */ if ((event->keycode >> 8) == 0x10) Index: dlls/x11drv/ts_xlib.c =================================================================== RCS file: /home/wine/wine/dlls/x11drv/ts_xlib.c,v retrieving revision 1.1 diff -u -r1.1 ts_xlib.c --- dlls/x11drv/ts_xlib.c 25 Sep 2002 03:29:55 -0000 1.1 +++ dlls/x11drv/ts_xlib.c 13 Dec 2002 14:30:57 -0000 @@ -9,6 +9,7 @@ #ifdef HAVE_X11_XLIB_H #include <X11/Xlib.h> +#include <X11/Xutil.h> #include "ts_xlib.h" @@ -670,6 +671,22 @@ return r; } +XFontSet TSXCreateFontSet(Display* a0, const char* a1, char*** a2, int* a3, char** a4) +{ + XFontSet r; + wine_tsx11_lock(); + r = XCreateFontSet(a0, a1, a2, a3, a4); + wine_tsx11_unlock(); + return r; +} + +void TSXFreeFontSet(Display* a0, XFontSet a1) +{ + wine_tsx11_lock(); + XFreeFontSet(a0, a1); + wine_tsx11_unlock(); +} + XIM TSXOpenIM(Display* a0, struct _XrmHashBucketRec* a1, char* a2, char* a3) { XIM r; @@ -677,6 +694,34 @@ r = XOpenIM(a0, a1, a2, a3); wine_tsx11_unlock(); return r; +} + + +void TSXSetICFocus(XIC a0) +{ + wine_tsx11_lock(); + XSetICFocus(a0); + wine_tsx11_unlock(); +} + + + +int TSXFilterEvent(XEvent* a0, Window a1) +{ + int r; + wine_tsx11_lock(); + r = XFilterEvent(a0, a1); + wine_tsx11_unlock(); + return r; +} + +int TSXmbLookupString(XIC a0, XKeyPressedEvent* a1, char* a2, int a3, KeySym* a4, int * a5) +{ + int r; + wine_tsx11_lock(); + r = XmbLookupString(a0, a1, a2, a3, a4, a5); + wine_tsx11_unlock(); + return r; } #endif /* defined(HAVE_X11_XLIB_H) */ Index: dlls/x11drv/ts_xlib.h =================================================================== RCS file: /home/wine/wine/dlls/x11drv/ts_xlib.h,v retrieving revision 1.1 diff -u -r1.1 ts_xlib.h --- dlls/x11drv/ts_xlib.h 25 Sep 2002 03:29:55 -0000 1.1 +++ dlls/x11drv/ts_xlib.h 13 Dec 2002 14:30:57 -0000 @@ -92,7 +92,13 @@ extern int TSXUngrabServer(Display*); extern int TSXUninstallColormap(Display*, Colormap); extern int TSXUnmapWindow(Display*, Window); +extern XFontSet TSXCreateFontSet(Display*, const char*, char***, int*, char**); +extern void TSXFreeFontSet(Display*, XFontSet); + extern XIM TSXOpenIM(Display*, struct _XrmHashBucketRec*, char*, char*); +extern void TSXSetICFocus(XIC); +extern int TSXFilterEvent(XEvent*, Window); +extern int TSXmbLookupString(XIC, XKeyPressedEvent*, char*, int, KeySym*, int *); #endif /* defined(HAVE_X11_XLIB_H) */ Index: dlls/x11drv/window.c =================================================================== RCS file: /home/wine/wine/dlls/x11drv/window.c,v retrieving revision 1.46 diff -u -r1.46 window.c --- dlls/x11drv/window.c 3 Dec 2002 23:34:53 -0000 1.46 +++ dlls/x11drv/window.c 13 Dec 2002 14:30:57 -0000 @@ -40,7 +40,10 @@ #include "winpos.h" #include "mwm.h" +#include "xim.h" + WINE_DEFAULT_DEBUG_CHANNEL(x11drv); +WINE_DECLARE_DEBUG_CHANNEL(xim); extern Pixmap X11DRV_BITMAP_Pixmap( HBITMAP ); @@ -50,6 +53,9 @@ /* X context to associate a hwnd to an X window */ XContext winContext = 0; +extern XContext ximContext; + +extern Window root_window; Atom wmProtocols = None; Atom wmDeleteWindow = None; @@ -96,6 +102,19 @@ { struct x11drv_win_data *data = win->pDriverData; return !(win->dwStyle & WS_MINIMIZE) && !IsRectEmpty( &data->client_rect ); +} + +XIC X11DRV_GetXIC() +{ + + XIC xic = NULL; + + if (ximContext != 0 ){ + wine_tsx11_lock(); + XFindContext(thread_display(), root_window , ximContext, (XPointer *) &xic); + wine_tsx11_unlock(); + } + return xic; } Index: dlls/x11drv/x11drv_main.c =================================================================== RCS file: /home/wine/wine/dlls/x11drv/x11drv_main.c,v retrieving revision 1.65 diff -u -r1.65 x11drv_main.c --- dlls/x11drv/x11drv_main.c 15 Nov 2002 04:16:38 -0000 1.65 +++ dlls/x11drv/x11drv_main.c 13 Dec 2002 14:30:57 -0000 @@ -44,10 +44,12 @@ #include "x11drv.h" #include "xvidmode.h" #include "dga2.h" +#include "xim.h" #include "wine/server.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(x11drv); +WINE_DECLARE_DEBUG_CHANNEL(xim); static CRITICAL_SECTION X11DRV_CritSection = CRITICAL_SECTION_INIT("X11DRV_CritSection"); @@ -57,6 +59,8 @@ unsigned int screen_height; unsigned int screen_depth; Window root_window; +XContext ximContext = 0; +static BOOL XIM_DoCreateIC(Window ); int dxgrab, usedga, usexvidmode; int use_take_focus = 1; int managed_mode = 1; @@ -83,6 +87,9 @@ #define IS_OPTION_FALSE(ch) \ ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0') +XIMStyle ximStyle = 0; +XFontSet ximFontSet; + /*********************************************************************** * X11DRV_expect_error * @@ -276,6 +283,170 @@ RegCloseKey( hkey ); } +static BOOL X11DRV_SetupXIM(struct x11drv_thread_data *data) +{ + BOOL ximDisable; + XIMStyle ximStyleRequest, ximStyleRoot, ximStyleNone; + XIMStyles *ximStyles = NULL; + char buf[100]; + int i; + + char **list; //FIXME + int count; + char * FontSet; + + HKEY hkey, appkey = 0; + + if (RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\InputMethod", 0, NULL, + REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL )) + { + ERR("Cannot create config registry key\n" ); + ExitProcess(1); + } + + /* open the app-specific key */ + + if (GetModuleFileNameA( 0, buf, MAX_PATH )) + { + HKEY tmpkey; + char *p, *appname = buf; + if ((p = strrchr( appname, '/' ))) appname = p + 1; + if ((p = strrchr( appname, '\\' ))) appname = p + 1; + strcat( appname, "\\InputMethod" ); + if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\AppDefaults", &tmpkey )) + { + if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0; + RegCloseKey( tmpkey ); + } + } + + if (!get_config_key( hkey, appkey, "UseXIM", buf, sizeof(buf) )) + { + ximDisable = IS_OPTION_FALSE( buf[0] ); + } + else + ximDisable=FALSE; + if(ximDisable) + { + MESSAGE("Disabled input method.\n"); + return FALSE; + } + + if (!get_config_key( hkey, appkey, "XIMFontSet", buf, sizeof(buf) )) + { + FontSet = strdup( buf ); + } + else + FontSet = "-adobe-helvetica-medium-r-normal--16-*-*-*-*-*-*-*,-*-*-medium-r-normal--18-*-*-*-*-*-gb2312.1980-0,*-r-*"; + + ximFontSet = TSXCreateFontSet(data->display, FontSet, &list, &count, NULL); + + TRACE_(xim)("ximFontSet = 0x%x\n", (unsigned int) ximFontSet); + TRACE_(xim)("list = 0x%x, count = %d\n", (unsigned int) list, count); + if (list != NULL) + { + int i; + + for (i = 0; i < count; ++i) + { + TRACE_(xim)("list[%d] = %s\n", i, list[i]); + } + wine_tsx11_lock(); + XFreeStringList(list); + wine_tsx11_unlock(); + } + + if (get_config_key( hkey, appkey, "InputStyle", buf, sizeof(buf) )) + sprintf(buf, "overthespot"); + + ximStyleRequest = STYLE_OVERTHESPOT; + if (strcasecmp(buf, "offthespot") == 0) + ximStyleRequest = STYLE_OFFTHESPOT; + else if (strcasecmp(buf, "overthespot") == 0) + ximStyleRequest = STYLE_OVERTHESPOT; + else if (strcasecmp(buf, "root") == 0) + ximStyleRequest = STYLE_ROOT; + + wine_tsx11_lock(); + + if(!XSupportsLocale()) + { + MESSAGE("X does not support locale.\n"); + goto err; + } + + if(XSetLocaleModifiers("") == NULL) + { + MESSAGE("Could not set locale modifiers.\n"); + goto err; + } + + data->xim = XOpenIM(data->display, NULL, NULL, NULL); + if (data->xim == NULL) + { + MESSAGE("Could not open input method.\n"); + goto err; + } + + XGetIMValues(data->xim, XNQueryInputStyle, &ximStyles, NULL); + if (ximStyles == 0) + { + MESSAGE("Could not find supported input style.\n"); + } + else + { + TRACE_(xim)("ximStyles->count_styles = %d\n", ximStyles->count_styles); + + ximStyleRoot = 0; + ximStyleNone = 0; + + for (i = 0; i < ximStyles->count_styles; ++i) + { + int style = ximStyles->supported_styles[i]; + TRACE_(xim)("ximStyles[%d] = %s%s%s%s%s\n", i, + (style&XIMPreeditArea)?"XIMPreeditArea ":"", + (style&XIMPreeditCallbacks)?"XIMPreeditCallbacks ":"", + (style&XIMPreeditPosition)?"XIMPreeditPosition ":"", + (style&XIMPreeditNothing)?"XIMPreeditNothing ":"", + (style&XIMPreeditNone)?"XIMPreeditNone ":""); + if (ximStyles->supported_styles[i] == ximStyleRequest) + { + ximStyle = ximStyleRequest; + TRACE_(xim)("Setting Style: ximStyleNone = ximStyleRequest\n"); + break; + } + + if (ximStyles->supported_styles[i] == STYLE_ROOT) + { + ximStyleRoot = STYLE_ROOT; + TRACE_(xim)("Setting Style: ximStyleNone = STYLE_ROOT\n"); + break; + } + + if (ximStyles->supported_styles[i] == STYLE_NONE) + { + TRACE_(xim)("Setting Style: ximStyleNone = STYLE_NONE\n"); + ximStyleNone = STYLE_NONE; + break; + } + } + + XFree(ximStyles); + + if (ximStyle == 0) + ximStyle = ximStyleRoot; + + if (ximStyle == 0) + ximStyle = ximStyleNone; + } + + wine_tsx11_unlock(); + return TRUE; + +err: + wine_tsx11_unlock(); + return FALSE; +} /*********************************************************************** * X11DRV process initialisation routine @@ -376,6 +547,18 @@ { CloseHandle( data->display_fd ); wine_tsx11_lock(); + if(data->xim) + { + XIC xic = X11DRV_GetXIC(); + if (xic) + { + XUnsetICFocus(xic); + XDestroyIC(xic); + XDeleteContext(data->display, root_window, ximContext); + ximContext = 0; + } + XCloseIM(data->xim); + } XCloseDisplay( data->display ); wine_tsx11_unlock(); HeapFree( GetProcessHeap(), 0, data ); @@ -441,7 +624,17 @@ data->cursor = None; data->cursor_window = None; data->last_focus = 0; + data->xim = 0; + X11DRV_SetupXIM(data); NtCurrentTeb()->driver_data = data; + if(data->xim) + { + if(ximContext == 0){ + TRACE_(xim)("root_window %08x\n", + (unsigned int)root_window); + XIM_DoCreateIC(root_window); + } + } return data; } @@ -495,4 +688,86 @@ timeout = bActivate ? last_timeout : 0; TSXSetScreenSaver(gdi_display, timeout, interval, prefer_blanking, allow_exposures); +} + +/*********************************************************************** + * XIM IC Functions (X11DRV.@) + * + */ +static BOOL XIM_DoCreateIC(Window w) +{ + XFontSet FSet = ximFontSet; + XPoint spot = {400,400}; + XVaNestedList preedit = NULL; + XVaNestedList status = NULL; + XIC xic = NULL; + struct x11drv_thread_data *data = NtCurrentTeb()->driver_data; + + TRACE_(xim)("xwin %08x, xim %08x, ximContext %d\n", + (unsigned int)w, (unsigned int) data->xim, ximContext); + + if (data->xim == NULL) + return FALSE; + + wine_tsx11_lock(); + if ((ximStyle & (XIMPreeditNothing | XIMPreeditNone)) == 0) + { + preedit = XVaCreateNestedList(0, + XNFontSet, FSet, + XNSpotLocation, &spot, + NULL); + TRACE_(xim)("preedit = 0x%x\n", (unsigned int) preedit); + } + if ((ximStyle & (XIMStatusNothing | XIMStatusNone)) == 0) + { + status = XVaCreateNestedList(0, + XNFontSet, FSet, NULL); + TRACE_(xim)("status = 0x%x\n", (unsigned int) status); + } + if (preedit != NULL && status != NULL) { + xic = XCreateIC(data->xim, + XNClientWindow, w, + XNFocusWindow, w, + XNInputStyle, ximStyle, + XNPreeditAttributes, preedit, + XNStatusAttributes, status, + NULL); + } else if (preedit != NULL) { + xic = XCreateIC(data->xim, + XNClientWindow, w, + XNFocusWindow, w, + XNInputStyle, ximStyle, + XNPreeditAttributes, preedit, + NULL); + } else if (status != NULL) { + xic = XCreateIC(data->xim, + XNClientWindow, w, + XNFocusWindow, w, + XNInputStyle, ximStyle, + XNStatusAttributes, status, + NULL); + } else { + xic = XCreateIC(data->xim, + XNClientWindow, w, + XNFocusWindow, w, + XNInputStyle, ximStyle, + NULL); + } + TRACE_(xim)("xic = 0x%x\n", (unsigned int) xic); + if (preedit != NULL) { + TSXFree(preedit); + } + if (status != NULL) { + TSXFree(status); + } + + if (ximContext == 0) + ximContext = XUniqueContext(); + + XSaveContext(data->display, w, ximContext, (XPointer) xic); + XSetICFocus(xic); + + wine_tsx11_unlock(); + + return TRUE; } Index: documentation/samples/config =================================================================== RCS file: /home/wine/wine/documentation/samples/config,v retrieving revision 1.37 diff -u -r1.37 config --- documentation/samples/config 13 Dec 2002 02:26:18 -0000 1.37 +++ documentation/samples/config 13 Dec 2002 14:30:57 -0000 @@ -177,6 +177,13 @@ ;"dir3" = "/usr/X11R6/lib/X11/fonts/TT" ;"dir4" = "/usr/share/fonts/TT" +[InputMethod] +; Use XIM Input Method +"UseXIM" = "Y" +; XIM Input Style : "overthespot" or "offthespot" or "root" (default). +"InputStyle" = "overthespot" +"XIMFontSet" = "-adobe-helvetica-medium-r-normal--16-*-*-*-*-*-*-*,-*-*-medium-r-normal--18-*-*-*-*-*-gb2312.1980-0,*-r-*" + [serialports] "Com1" = "/dev/ttyS0" "Com2" = "/dev/ttyS1" Index: include/winnls.h =================================================================== RCS file: /home/wine/wine/include/winnls.h,v retrieving revision 1.37 diff -u -r1.37 winnls.h --- include/winnls.h 4 Nov 2002 22:39:45 -0000 1.37 +++ include/winnls.h 13 Dec 2002 14:30:58 -0000 @@ -146,6 +146,8 @@ #define LOCALE_SISO639LANGNAME 0x00000059 #define LOCALE_SISO3166CTRYNAME 0x0000005A +#define LOCALE_SCHARSETNAMES 0x00001015 + #define LOCALE_IDEFAULTEBCDICCODEPAGE 0x00001012 #define LOCALE_IPAPERSIZE 0x0000100A #define LOCALE_SENGCURRNAME 0x00001007 Index: include/x11drv.h =================================================================== RCS file: /home/wine/wine/include/x11drv.h,v retrieving revision 1.118 diff -u -r1.118 x11drv.h --- include/x11drv.h 15 Nov 2002 04:16:38 -0000 1.118 +++ include/x11drv.h 13 Dec 2002 14:30:58 -0000 @@ -99,6 +99,9 @@ XRENDERINFO xrender; } X11DRV_PDEVICE; +extern XIMStyle ximStyle; +extern XFontSet ximFontSet; +extern XIC X11DRV_GetXIC(); /* GCs used for B&W and color bitmap operations */ extern GC BITMAP_monoGC, BITMAP_colorGC; @@ -337,6 +340,7 @@ Cursor cursor; /* current cursor */ Window cursor_window; /* current window that contains the cursor */ HWND last_focus; /* last window that had focus */ + XIM xim; }; extern struct x11drv_thread_data *x11drv_init_thread_data(void); --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ dlls/x11drv/xim.h 2002-12-13 11:40:39.000000000 +0000 @@ -0,0 +1,30 @@ +/* + * xim.h + * define some constant used in XIM + * + * Copyright 2002 liuspider + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#if !defined(__WINE_XIM_H) + +#define __WINE_XIM_H + +#define STYLE_OFFTHESPOT (XIMPreeditArea | XIMStatusArea) +#define STYLE_OVERTHESPOT (XIMPreeditPosition | XIMStatusNothing) +#define STYLE_ROOT (XIMPreeditNothing | XIMStatusNothing) +#define STYLE_NONE (XIMPreeditNone | XIMStatusNone) + +#endif /* !defined(__WINE_XIM_H) */ __________________________________________________ Do you Yahoo!? Yahoo! Mail Plus - Powerful. Affordable. Sign up now. http://mailplus.yahoo.com