XIM support patch

liu spider liuspider at yahoo.com
Fri Dec 13 08:58:27 CST 2002


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 at 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



More information about the wine-patches mailing list