imm work

Aric Stewart aric at codeweavers.com
Wed Jan 7 11:24:18 CST 2004


Notes:
   I fear this may violate dll separation between Imm32 and X11drv. I 
have a very long and bad history of doing that... alot.. so i need to 
get better about it.

   I have extensively tested this with crossover, but have only given it 
a good once though with winecvs. but if things come up i am happy to 
work with people to figure it out.

I am also including my 2 test applications:
  HALFIME.EXE is a half ime application. relies on wine/the ime to do 
the composition but still is ime aware. Grabs the composition string via 
apis instead of relying on the WM_IME_CHAR messages.

  FULLIME.EXE is a full ime application. does its own display of 
composition characters and integrates close with the ime itself.

   if you want to test a fully ime unaware application those are easy to 
find.


Changelog:
extensive changing to xim and imm. uses X11 xim callbacks to enable full 
ime support. corrects some timing issues with xim input.
starts to provide the framework for the MSIME messages

liscencing:
  this patch is LGPL. the test apps are ones i downloaded from the web 
so i am unsure, but that is less important.
-------------- next part --------------
Index: dlls/x11drv/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/Makefile.in,v
retrieving revision 1.38
diff -u -w -r1.38 Makefile.in
--- dlls/x11drv/Makefile.in	5 Dec 2003 00:20:28 -0000	1.38
+++ dlls/x11drv/Makefile.in	7 Jan 2004 17:11:20 -0000
@@ -38,6 +38,7 @@
 	x11drv_main.c \
 	xdnd.c \
 	xfont.c \
+	xim.c \
 	xrandr.c \
 	xrender.c \
 	xvidmode.c
Index: dlls/x11drv/event.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/event.c,v
retrieving revision 1.30
diff -u -w -r1.30 event.c
--- dlls/x11drv/event.c	5 Dec 2003 04:45:50 -0000	1.30
+++ dlls/x11drv/event.c	7 Jan 2004 17:11:21 -0000
@@ -54,6 +54,8 @@
 /* X context to associate a hwnd to an X window */
 extern XContext winContext;
 
+extern BOOL ximInComposeMode;
+
 #define DndNotDnd       -1    /* OffiX drag&drop */
 #define DndUnknown      0
 #define DndRawData      1
@@ -523,6 +525,8 @@
     TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
 
     if (event->detail == NotifyPointer) return;
+    if (ximInComposeMode) return;
+
     x11drv_thread_data()->last_focus = hwnd;
     if ((xic = X11DRV_get_ic( hwnd )))
     {
Index: dlls/x11drv/keyboard.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/keyboard.c,v
retrieving revision 1.44
diff -u -w -r1.44 keyboard.c
--- dlls/x11drv/keyboard.c	30 Dec 2003 19:14:59 -0000	1.44
+++ dlls/x11drv/keyboard.c	7 Jan 2004 17:11:22 -0000
@@ -47,6 +47,8 @@
 #include "wine/winuser16.h"
 #include "winnls.h"
 #include "win.h"
+#include "imm.h"
+#include "xim.h"
 #include "x11drv.h"
 #include "wine/unicode.h"
 #include "wine/debug.h"
@@ -55,6 +57,8 @@
 WINE_DECLARE_DEBUG_CHANNEL(key);
 WINE_DECLARE_DEBUG_CHANNEL(dinput);
 
+extern HIMC root_context;
+
 static int min_keycode, max_keycode, keysyms_per_keycode;
 static WORD keyc2vkey[256], keyc2scan[256];
 
@@ -1113,7 +1117,29 @@
         return;
     }
 
-    TRACE_(key)("state = %X\n", event->state);
+    TRACE_(key)("state = %X nbyte = %d, status 0x%x\n", event->state, ascii_chars, status);
+
+    if (status == XBufferOverflow)
+        ERR("Buffer Overflow need %i!\n",ascii_chars);
+
+    if (status == XLookupChars)
+    {
+            DWORD dwOutput;
+            WCHAR wcOutput[64];
+            HWND focus;
+
+            TRACE_(key)("XIM: XLookupChars\n");
+
+            dwOutput = MultiByteToWideChar(CP_UNIXCP,
+                    0, Str, ascii_chars, wcOutput, sizeof(wcOutput));
+
+            if ((focus = GetFocus()))
+                X11DRV_ImmAssociateContext(focus,root_context);
+
+            X11DRV_ImmSetInternalString(GCS_RESULTSTR,0,0,wcOutput,dwOutput);
+    }
+    else
+    {
 
     /* If XKB extensions are used, the state mask for AltGr will use the group
        index instead of the modifier mask. The group index is set in bits
@@ -1191,6 +1217,7 @@
         send_keyboard_input( vkey & 0xff, bScan, dwFlags, event_time );
     }
    }
+}
 }
 
 /**********************************************************************
Index: dlls/x11drv/window.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/window.c,v
retrieving revision 1.68
diff -u -w -r1.68 window.c
--- dlls/x11drv/window.c	31 Dec 2003 23:51:52 -0000	1.68
+++ dlls/x11drv/window.c	7 Jan 2004 17:11:22 -0000
@@ -791,12 +791,9 @@
 
     if (is_top_level)
     {
+        extern XIC x11drv_CreateIC(XIM xim, Display *display, Window win);
         XIM xim = x11drv_thread_data()->xim;
-        if (xim) data->xic = XCreateIC( xim,
-                                        XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
-                                        XNClientWindow, data->whole_window,
-                                        XNFocusWindow, data->whole_window,
-                                        0 );
+        if (xim) data->xic = x11drv_CreateIC( xim, display, data->whole_window );
     }
 
     /* non-maximized child must be at bottom of Z order */
Index: dlls/x11drv/x11drv.spec
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/x11drv.spec,v
retrieving revision 1.50
diff -u -w -r1.50 x11drv.spec
--- dlls/x11drv/x11drv.spec	26 Nov 2003 22:03:34 -0000	1.50
+++ dlls/x11drv/x11drv.spec	7 Jan 2004 17:11:22 -0000
@@ -114,3 +114,6 @@
 # X11 locks
 @ cdecl -norelay wine_tsx11_lock()
 @ cdecl -norelay wine_tsx11_unlock()
+
+# XIM
+@ cdecl X11DRV_ForceXIMReset(long)
Index: dlls/x11drv/x11drv_main.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/x11drv_main.c,v
retrieving revision 1.83
diff -u -w -r1.83 x11drv_main.c
--- dlls/x11drv/x11drv_main.c	5 Dec 2003 00:11:48 -0000	1.83
+++ dlls/x11drv/x11drv_main.c	7 Jan 2004 17:11:22 -0000
@@ -62,7 +62,10 @@
 #include "xvidmode.h"
 #include "xrandr.h"
 #include "dga2.h"
+#include "imm.h"
+#include "xim.h"
 #include "wine/server.h"
+#include "wine/unicode.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
@@ -106,11 +109,16 @@
 static unsigned long err_serial;             /* serial number of first request */
 static int (*old_error_handler)( Display *, XErrorEvent * );
 
+extern char input_style[100];
+extern BOOL ximDisable;
+
 #define IS_OPTION_TRUE(ch) \
     ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
 #define IS_OPTION_FALSE(ch) \
     ((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
 
+XIM x11drv_SetupXIM(struct x11drv_thread_data *data);
+
 /***********************************************************************
  *		ignore_error
  *
@@ -309,6 +317,11 @@
     if (!get_config_key( hkey, appkey, "DesktopDoubleBuffered", buffer, sizeof(buffer) ))
         desktop_dbl_buf = IS_OPTION_TRUE( buffer[0] );
 
+    if (!get_config_key( hkey, appkey, "NoXIM", buffer, sizeof(buffer) ))
+        ximDisable = IS_OPTION_TRUE( buffer[0] );
+
+    get_config_key( hkey, appkey, "InputStyle", input_style, sizeof(input_style) );
+
     if (appkey) RegCloseKey( appkey );
     RegCloseKey( hkey );
 }
@@ -463,15 +476,8 @@
         MESSAGE( "x11drv: Can't open display: %s\n", XDisplayName(NULL) );
         ExitProcess(1);
     }
-    fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
 
-    if ((data->xim = XOpenIM( data->display, NULL, NULL, NULL )))
-    {
-        TRACE("X display of IM = %p\n", XDisplayOfIM(data->xim));
-        TRACE("Using %s locale of Input Method\n", XLocaleOfIM(data->xim));
-    }
-    else
-        WARN("Can't open input method\n");
+    fcntl( ConnectionNumber(data->display), F_SETFD, 1 ); /* set close on exec flag */
 
 #ifdef HAVE_XKB
     if (use_xkb)
@@ -483,6 +489,9 @@
 
     if (synchronous) XSynchronize( data->display, True );
     wine_tsx11_unlock();
+
+    if (!(data->xim = x11drv_SetupXIM(data))) WARN("Input Method is not available\n");
+
     if (wine_server_fd_to_handle( ConnectionNumber(data->display), GENERIC_READ | SYNCHRONIZE,
                                   FALSE, &data->display_fd ))
     {
--- /dev/null	Thu Aug 30 15:30:55 2001
+++ dlls/x11drv/xim.c	Wed Jan  7 09:15:23 2004
@@ -0,0 +1,473 @@
+/*
+ * Functions for further XIM control
+ *
+ * Copyright 2003 CodeWeavers, Aric Stewart
+ *
+ * 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
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "wingdi.h"
+#include "winnls.h"
+#include "x11drv.h"
+#include "imm.h"
+#include "../dlls/imm32/imm_internal.h"
+#include "xim.h"
+#include "wine/debug.h"
+
+HIMC root_context;
+char input_style[100];
+BOOL ximDisable;
+BOOL ximInComposeMode=FALSE;
+static XIMStyle ximStyle = 0;
+static XIMStyle ximStyleRoot = 0;
+
+static HMODULE hImmDll = NULL;
+typedef HIMC (WINAPI *tfImmAssociateContext)(HWND,HIMC);
+typedef HIMC (WINAPI *tfCreateContext)();
+typedef VOID (WINAPI *tfImmInternalPostIMEMessage)(UINT, WPARAM, LPARAM);
+typedef BOOL (WINAPI *tfImmSetInternalString)(DWORD, DWORD, DWORD, LPWSTR,
+                                             DWORD);
+typedef VOID (WINAPI *tfImmInternalSetOpenStatus)(BOOL);
+
+static tfImmAssociateContext       pImmAssociateContext = NULL;
+static tfCreateContext             pImmCreateContext = NULL;
+static tfImmInternalPostIMEMessage pImmInternalPostIMEMessage = NULL;
+static tfImmSetInternalString      pImmSetInternalString = NULL;
+static tfImmInternalSetOpenStatus  pImmInternalSetOpenStatus = NULL;
+
+#define STYLE_OFFTHESPOT (XIMPreeditArea | XIMStatusArea)
+#define STYLE_OVERTHESPOT (XIMPreeditPosition | XIMStatusNothing)
+#define STYLE_ROOT (XIMPreeditNothing | XIMStatusNothing)
+/* this uses all the callbacks to utilize full IME support */
+#define STYLE_CALLBACK (XIMPreeditCallbacks | XIMStatusNothing)
+/* inorder to enable deadkey support */
+#define STYLE_NONE (XIMPreeditNothing | XIMStatusNothing)
+
+WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
+
+/*
+ * here are the functions that sort of marshall calls into IMM32.DLL
+ */
+static void X11DRV_LoadImmDll()
+{
+    hImmDll = LoadLibraryA("imm32.dll");    
+
+    pImmAssociateContext = (tfImmAssociateContext)GetProcAddress(hImmDll,
+                                              "ImmAssociateContext");
+    if (!pImmAssociateContext)
+        WARN("IMM: pImmAssociateContext not found in DLL\n");
+
+    pImmCreateContext = (tfCreateContext)GetProcAddress(hImmDll,
+                                                "ImmCreateContext");
+    if (!pImmCreateContext)
+        WARN("IMM: pImmCreateContext not found in DLL\n");
+
+    pImmInternalPostIMEMessage = (tfImmInternalPostIMEMessage)GetProcAddress(
+                                        hImmDll, "ImmInternalPostIMEMessage");
+    if (!pImmInternalPostIMEMessage)
+        WARN("IMM: pImmInternalPostIMEMessage not found in DLL\n");
+
+    pImmSetInternalString = (tfImmSetInternalString)GetProcAddress(hImmDll,
+                                                    "ImmSetInternalString");
+    if (!pImmSetInternalString)
+        WARN("IMM: pImmSetInternalString not found in DLL\n");
+
+    pImmInternalSetOpenStatus = (tfImmInternalSetOpenStatus)GetProcAddress(
+                                        hImmDll, "ImmInternalSetOpenStatus");
+    if (!pImmInternalSetOpenStatus)
+        WARN("IMM: pImmInternalSetOpenStatus not found in DLL\n");
+}
+
+HIMC WINAPI X11DRV_ImmAssociateContext(HWND hWnd, HIMC hIMC)
+{
+    if (pImmAssociateContext)
+        return pImmAssociateContext(hWnd,hIMC);
+    else
+        return NULL;
+}
+
+BOOL WINAPI X11DRV_ImmSetInternalString(DWORD dwIndex, DWORD dwOffset, DWORD
+                                    selLength, LPWSTR lpComp, DWORD dwCompLen)
+{
+    if (pImmSetInternalString)
+        return pImmSetInternalString(dwIndex, dwOffset, selLength, lpComp,
+                                     dwCompLen);
+    else
+        return FALSE;
+}
+
+int XIMPreEditStartCallback(XIC ic, XPointer client_data, XPointer call_data)
+{
+    TRACE("PreEditStartCallback %p\n",ic);
+    if (pImmInternalSetOpenStatus)
+        pImmInternalSetOpenStatus(TRUE);
+    ximInComposeMode = TRUE;
+    if (pImmInternalPostIMEMessage)
+        pImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0);
+    return -1;
+}
+
+void XIMPreEditDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
+{
+    TRACE("PreeditDoneCallback %p\n",ic);
+    if (pImmInternalPostIMEMessage)
+        pImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0);
+    ximInComposeMode = FALSE;
+    if (pImmInternalSetOpenStatus)
+        pImmInternalSetOpenStatus(FALSE);
+}
+
+void XIMPreEditDrawCallback(XIM ic, XPointer client_data,
+                           XIMPreeditDrawCallbackStruct *P_DR)
+{
+    DWORD dwOutput;
+    WCHAR wcOutput[64];
+
+    TRACE("PreEditDrawCallback %p\n",ic);
+
+    if (P_DR)
+    {
+        int sel = P_DR->chg_first;
+        int len = P_DR->chg_length;
+        if (P_DR->text)
+        {
+            if (! P_DR->text->encoding_is_wchar)
+            {
+                TRACE("multibyte\n");
+                dwOutput = MultiByteToWideChar(CP_UNIXCP, 0,
+                           P_DR->text->string.multi_byte, -1,
+                           wcOutput, 64);
+
+                /* ignore null */
+                dwOutput --;
+
+                if (pImmSetInternalString)
+                    pImmSetInternalString(GCS_COMPSTR, sel, len, wcOutput,
+                                          dwOutput);
+            }
+            else
+            {
+                FIXME("wchar PROBIBILY WRONG\n");
+                if (pImmSetInternalString)
+                    pImmSetInternalString(GCS_COMPSTR, sel, len,
+                            (LPWSTR)P_DR->text->string.wide_char,
+                            P_DR->text->length);
+            }
+        }
+        else
+            if (pImmSetInternalString)
+                pImmSetInternalString(GCS_COMPSTR, sel, len, NULL, 0);
+    }
+    TRACE("Finished\n");
+}
+
+void XIMPreEditCaretCallback(XIC ic, XPointer client_data,
+                            XIMPreeditCaretCallbackStruct *P_C)
+{
+    FIXME("PreeditCaretCalback %p\n",ic);
+}
+
+void WINAPI X11DRV_ForceXIMReset(HWND hwnd)
+{
+    XIC ic = X11DRV_get_ic(hwnd);
+    if (ic)
+    {
+        char* leftover;
+        TRACE("Forcing Reset %p\n",ic);
+        wine_tsx11_lock();
+        leftover = XmbResetIC(ic);
+        XFree(leftover);
+        wine_tsx11_unlock();
+    }
+}
+
+/***********************************************************************
+*           X11DRV Ime creation
+*/
+
+XIM x11drv_SetupXIM(struct x11drv_thread_data *data)
+{
+    XIMStyle ximStyleRequest, ximStyleCallback, ximStyleNone;
+    XIMStyles *ximStyles = NULL;
+    INT i;
+    XIM xim;
+
+    if(ximDisable)
+    {
+        WARN("Disabled input method.\n");
+        return FALSE;
+    }
+
+    ximStyleRequest = STYLE_CALLBACK;
+
+    if (!strcasecmp(input_style, "offthespot"))
+        ximStyleRequest = STYLE_OFFTHESPOT;
+    else if (!strcasecmp(input_style, "overthespot"))
+        ximStyleRequest = STYLE_OVERTHESPOT;
+    else if (!strcasecmp(input_style, "root"))
+        ximStyleRequest = STYLE_ROOT;
+
+    wine_tsx11_lock();
+
+    if(!XSupportsLocale())
+    {
+        WARN("X does not support locale.\n");
+        goto err;
+    }
+    if(XSetLocaleModifiers("") == NULL)
+    {
+        WARN("Could not set locale modifiers.\n");
+        goto err;
+    }
+
+    xim = XOpenIM(data->display, NULL, NULL, NULL);
+    if (xim == NULL)
+    {
+        WARN("Could not open input method.\n");
+        goto err;
+    }
+
+    TRACE("X display of IM = %p\n", XDisplayOfIM(xim));
+    TRACE("Using %s locale of Input Method\n", XLocaleOfIM(xim));
+
+    XGetIMValues(xim, XNQueryInputStyle, &ximStyles, NULL);
+    if (ximStyles == 0)
+    {
+        WARN("Could not find supported input style.\n");
+    }
+    else
+    {
+        TRACE("ximStyles->count_styles = %d\n", ximStyles->count_styles);
+
+        ximStyleRoot = 0;
+        ximStyleNone = 0;
+        ximStyleCallback = 0;
+
+        for (i = 0; i < ximStyles->count_styles; ++i)
+        {
+            int style = ximStyles->supported_styles[i];
+            TRACE("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 (!ximStyle && (ximStyles->supported_styles[i] ==
+                                ximStyleRequest))
+            {
+                ximStyle = ximStyleRequest;
+                TRACE("Setting Style: ximStyle = ximStyleRequest\n");
+            }
+            else if (!ximStyleRoot &&(ximStyles->supported_styles[i] ==
+                     STYLE_ROOT))
+            {
+                ximStyleRoot = STYLE_ROOT;
+                TRACE("Setting Style: ximStyleRoot = STYLE_ROOT\n");
+            }
+            else if (!ximStyleCallback &&(ximStyles->supported_styles[i] ==
+                     STYLE_CALLBACK))
+            {
+                ximStyleCallback = STYLE_CALLBACK;
+                TRACE("Setting Style: ximStyleCallback = STYLE_CALLBACK\n");
+            }
+            else if (!ximStyleNone && (ximStyles->supported_styles[i] ==
+                     STYLE_NONE))
+            {
+                TRACE("Setting Style: ximStyleNone = STYLE_NONE\n");
+                ximStyleNone = STYLE_NONE;
+            }
+        }
+        XFree(ximStyles);
+
+        if (ximStyle == 0)
+            ximStyle = ximStyleRoot;
+
+        if (ximStyle == 0)
+            ximStyle = ximStyleNone;
+
+        if (ximStyleCallback == 0)
+        {
+            TRACE("No callback style avalable\n");
+            ximStyleCallback = ximStyle;
+        }
+
+        }
+
+    wine_tsx11_unlock();
+
+    X11DRV_LoadImmDll();
+
+    if (pImmCreateContext)
+    {
+        root_context = pImmCreateContext();
+        if (pImmAssociateContext)
+            pImmAssociateContext(0,root_context);
+    }
+
+    return xim;
+
+err:
+    wine_tsx11_unlock();
+    return NULL;
+}
+
+
+XIC x11drv_CreateIC(XIM xim, Display *display, Window win)
+{
+    XFontSet fontSet;
+    char **list;
+    int count;
+    XPoint spot = {0};
+    XVaNestedList preedit = NULL;
+    XVaNestedList status = NULL;
+    XIC xic;
+    XIMCallback P_StartCB;
+    XIMCallback P_DoneCB;
+    XIMCallback P_DrawCB;
+    XIMCallback P_CaretCB;
+    LANGID langid = PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale()));
+
+    wine_tsx11_lock();
+
+    /* use complex and slow XIC initialization method only for CJK */
+    if (langid != LANG_CHINESE &&
+        langid != LANG_JAPANESE &&
+        langid != LANG_KOREAN)
+    {
+        xic = XCreateIC(xim,
+                        XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
+                        XNClientWindow, win,
+                        XNFocusWindow, win,
+                        0);
+        wine_tsx11_unlock();
+        return xic;
+    }
+
+    fontSet = XCreateFontSet(display,
+                      "*", /*FIXME*/
+                      &list, &count, NULL);
+
+    TRACE("ximFontSet = 0x%x\n", (unsigned int) fontSet);
+    TRACE("list = 0x%x, count = %d\n", (unsigned int) list, count);
+
+    if (list != NULL)
+    {
+        int i;
+
+        for (i = 0; i < count; ++i)
+        {
+            TRACE("list[%d] = %s\n", i, list[i]);
+        }
+        XFreeStringList(list);
+    }
+
+    /* create callbacks */
+    P_StartCB.client_data = NULL;
+    P_StartCB.callback = (XIMProc)XIMPreEditStartCallback;
+    P_DoneCB.client_data = NULL;
+    P_DoneCB.callback = (XIMProc)XIMPreEditDoneCallback;
+    P_DrawCB.client_data = NULL;
+    P_DrawCB.callback = (XIMProc)XIMPreEditDrawCallback;
+    P_CaretCB.client_data = NULL;
+    P_CaretCB.callback = (XIMProc)XIMPreEditCaretCallback;
+
+    if ((ximStyle & (XIMPreeditNothing | XIMPreeditNone)) == 0)
+    {
+        preedit = XVaCreateNestedList(0,
+                        XNFontSet, fontSet,
+                        XNSpotLocation, &spot,
+                        XNPreeditStartCallback, &P_StartCB,
+                        XNPreeditDoneCallback, &P_DoneCB,
+                        XNPreeditDrawCallback, &P_DrawCB,
+                        XNPreeditCaretCallback, &P_CaretCB,
+                        NULL);
+        TRACE("preedit = 0x%x\n", (unsigned int) preedit);
+    }
+    else
+    {
+        preedit = XVaCreateNestedList(0,
+                        XNPreeditStartCallback, &P_StartCB,
+                        XNPreeditDoneCallback, &P_DoneCB,
+                        XNPreeditDrawCallback, &P_DrawCB,
+                        XNPreeditCaretCallback, &P_CaretCB,
+                        NULL);
+
+        TRACE("preedit = 0x%x\n", (unsigned int) preedit);
+    }
+
+    if ((ximStyle & (XIMStatusNothing | XIMStatusNone)) == 0)
+    {
+        status = XVaCreateNestedList(0,
+            XNFontSet, fontSet,
+            NULL);
+        TRACE("status = 0x%x\n", (unsigned int) status);
+     }
+
+    if (preedit != NULL && status != NULL)
+    {
+        xic = XCreateIC(xim,
+              XNInputStyle, ximStyle,
+              XNPreeditAttributes, preedit,
+              XNStatusAttributes, status,
+              XNClientWindow, win,
+              XNFocusWindow, win,
+              NULL);
+     }
+    else if (preedit != NULL)
+    {
+        xic = XCreateIC(xim,
+              XNInputStyle, ximStyle,
+              XNPreeditAttributes, preedit,
+              XNClientWindow, win,
+              XNFocusWindow, win,
+              NULL);
+    }
+    else if (status != NULL)
+    {
+        xic = XCreateIC(xim,
+              XNInputStyle, ximStyle,
+              XNStatusAttributes, status,
+              XNClientWindow, win,
+              XNFocusWindow, win,
+              NULL);
+    }
+    else
+    {
+        xic = XCreateIC(xim,
+              XNInputStyle, ximStyle,
+              XNClientWindow, win,
+              XNFocusWindow, win,
+              NULL);
+    }
+
+    TRACE("xic = 0x%x\n", (unsigned int) xic);
+
+    if (preedit != NULL)
+        XFree(preedit);
+    if (status != NULL)
+        XFree(status);
+
+    wine_tsx11_unlock();
+
+    return xic;
+}
--- /dev/null	Thu Aug 30 15:30:55 2001
+++ dlls/x11drv/xim.h	Wed Jan  7 09:15:23 2004
@@ -0,0 +1,39 @@
+/*
+ * Functions for further XIM control
+ *
+ * Copyright 2003 CodeWeavers, Aric Stewart
+ *
+ * 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
+ */
+
+#include <X11/Xlib.h>
+
+void XIMStatusStartCallback(XIC ic, XPointer client_data, XPointer S_S);
+void XIMStatusDoneCallback(XIC ic, XPointer client_data, XPointer S_S);
+void XIMStatusDrawCallback(XIC ic, XPointer client_data,
+                          XIMStatusDrawCallbackStruct *call_data);
+int XIMPreEditStartCallback(XIC ic, XPointer client_data, XPointer call_data);
+void XIMPreEditDoneCallback(XIC ic, XPointer client_data, XPointer call_data);
+void XIMPreEditDrawCallback(XIM ic, XPointer client_data,
+                           XIMPreeditDrawCallbackStruct *P_DR);
+void XIMPreEditCaretCallback(XIC ic, XPointer client_data,
+                            XIMPreeditCaretCallbackStruct *P_C);
+
+/* Prototypes for functions to be called in Imm32.dll */
+
+HIMC WINAPI X11DRV_ImmAssociateContext(HWND hWnd, HIMC hIMC);
+BOOL WINAPI X11DRV_ImmSetInternalString(DWORD dwIndex, DWORD dwOffset, DWORD 
+                                    selLength, LPWSTR lpComp, DWORD dwCompLen);
+
? dlls/imm32/imm_internal.h
Index: dlls/imm32/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/imm32/Makefile.in,v
retrieving revision 1.21
diff -u -w -r1.21 Makefile.in
--- dlls/imm32/Makefile.in	11 Oct 2003 01:09:19 -0000	1.21
+++ dlls/imm32/Makefile.in	7 Jan 2004 17:13:14 -0000
@@ -3,7 +3,7 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = imm32.dll
-IMPORTS   = user32 kernel32
+IMPORTS   = user32 x11drv gdi32 kernel32
 ALTNAMES  = imm.dll
 
 SPEC_SRCS16 = $(ALTNAMES:.dll=.spec)
Index: dlls/imm32/imm.c
===================================================================
RCS file: /home/wine/wine/dlls/imm32/imm.c,v
retrieving revision 1.27
diff -u -w -r1.27 imm.c
--- dlls/imm32/imm.c	29 Sep 2003 20:20:53 -0000	1.27
+++ dlls/imm32/imm.c	7 Jan 2004 17:13:15 -0000
@@ -2,7 +2,7 @@
  * IMM32 library
  *
  * Copyright 1998 Patrik Stridvall
- * Copyright 2002 CodeWeavers, Aric Stewart
+ * Copyright 2002, 2003 CodeWeavers, Aric Stewart
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -28,6 +28,7 @@
 #include "winerror.h"
 #include "wine/debug.h"
 #include "imm.h"
+#include "imm_internal.h"
 #include "winnls.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(imm);
@@ -38,49 +39,87 @@
         LPBYTE  CompositionReadingString;
         LPBYTE  ResultString;
         LPBYTE  ResultReadingString;
-        DWORD   dwCompStringSize;
+        DWORD           dwCompStringSize;   /* buffer size */
+        DWORD           dwCompStringLength; /* string length (in bytes) */
         DWORD   dwCompReadStringSize;
         DWORD   dwResultStringSize;
         DWORD   dwResultReadStringSize;
         HWND    hwnd;
         BOOL    bOpen;
+        BOOL            bInternalState;
         BOOL    bRead;
+        LOGFONTW        font;
+        HFONT           textfont; 
+        COMPOSITIONFORM CompForm;
 } InputContextData; 
 
 static InputContextData *root_context = NULL;
 static HWND hwndDefault = NULL;
 static HANDLE hImeInst;
-static const WCHAR WC_IMECLASSNAME[] = {'W','i','n','e','I','M','E','C','l','a','s','s',0};
+static const WCHAR WC_IMECLASSNAME[] = {'I','M','E',0};
 
-static LRESULT CALLBACK IME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+/* MSIME messages */
+static UINT WM_MSIME_SERVICE;
+static UINT WM_MSIME_RECONVERTOPTIONS;
+static UINT WM_MSIME_MOUSE;
+static UINT WM_MSIME_RECONVERTREQUEST;
+static UINT WM_MSIME_RECONVERT;
+static UINT WM_MSIME_QUERYPOSITION;
+static UINT WM_MSIME_DOCUMENTFEED;
+
+static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
+                                          LPARAM lParam);
+void UpdateDataInDefaultIMEWindow(HWND hwnd);
 
 static VOID IMM_PostResult(InputContextData *data)
 {
     int i;
+    TRACE("Posting result as IME_CHAR\n");
 
     for (i = 0; i < data->dwResultStringSize / sizeof (WCHAR); i++)
-        SendMessageW(data->hwnd, WM_IME_CHAR, ((WCHAR*)data->ResultString)[i], 1);
+        ImmInternalPostIMEMessage (WM_IME_CHAR, ((WCHAR*)data->ResultString)[i],
+                     1);
+
+    /* clear the buffer */
+    if (data->dwResultStringSize)
+        HeapFree(GetProcessHeap(),0,data->ResultString);
+    data->dwResultStringSize = 0;
+    data->ResultString = NULL;
 }
 
-static void IMM_Register(void)
+static VOID IMM_Register()
 {
     WNDCLASSW wndClass;
     ZeroMemory(&wndClass, sizeof(WNDCLASSW));
-    wndClass.style = CS_GLOBALCLASS | CS_IME;
-    wndClass.lpfnWndProc = IME_WindowProc;
+    wndClass.style = CS_GLOBALCLASS | CS_IME | CS_HREDRAW | CS_VREDRAW;
+    wndClass.lpfnWndProc = (WNDPROC) IME_WindowProc;
     wndClass.cbClsExtra = 0;
     wndClass.cbWndExtra = 0;
-    wndClass.hCursor = NULL;
+    wndClass.hInstance = hImeInst;
+    wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
+    wndClass.hIcon = NULL;
     wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW +1);
+    wndClass.lpszMenuName   = 0;
     wndClass.lpszClassName = WC_IMECLASSNAME;
     RegisterClassW(&wndClass);
 }
 
-static void IMM_Unregister(void)
+static VOID IMM_Unregister()
 {
     UnregisterClassW(WC_IMECLASSNAME, NULL);
 }
 
+static VOID IMM_RegisterMessages()
+{
+    WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");    
+    WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions");
+    WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
+    WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
+    WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
+    WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
+    WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
+}
+
 
 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
 {
@@ -90,6 +129,7 @@
         case DLL_PROCESS_ATTACH:
             DisableThreadLibraryCalls(hInstDLL);
             hImeInst = hInstDLL;
+            IMM_RegisterMessages();
             break;
         case DLL_PROCESS_DETACH:
             if (hwndDefault)
@@ -103,6 +143,183 @@
     return TRUE;
 }
 
+/* for posting messages as the IME */
+void WINAPI ImmInternalPostIMEMessage(UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    HWND target = GetFocus();
+    if (!target)
+       PostMessageW(root_context->hwnd,msg,wParam,lParam);
+    else 
+       PostMessageW(target, msg, wParam, lParam);
+}
+
+/* for filling the data into the ime structure */
+BOOL WINAPI ImmSetInternalString( DWORD dwIndex, DWORD dwOffset, DWORD
+                                  selLength,  LPWSTR lpComp, DWORD dwCompLen)
+{
+    int byte_length = dwCompLen * sizeof(WCHAR);
+    int byte_offset = dwOffset * sizeof(WCHAR);
+    int byte_selection = selLength * sizeof(WCHAR);
+    DWORD flags = 0;
+    WCHAR wParam  = 0;
+
+    TRACE("( %li, %li, %ld, %p, %ld):\n", dwOffset, selLength, dwIndex, lpComp,
+                                        dwCompLen );
+
+    /* Composition strings are edited in chunks */
+    if (dwIndex == GCS_COMPSTR)
+    {
+        int i,j;  
+        LPBYTE ptr_new;
+        LPBYTE ptr_old;
+
+        if ((dwCompLen == 0) && (selLength == 0))
+        {
+            /* DO Nothing */
+        }
+        /* deletion occurred */
+        else if ((dwCompLen== 0) && (selLength != 0))
+        { 
+            if (root_context->dwCompStringLength)
+            {
+                for (i = 0; i < byte_selection; i++)
+                {
+                    if (byte_offset+byte_selection+i <
+                        root_context->dwCompStringLength)
+                    {
+                        root_context->CompositionString[byte_offset + i] =
+                        root_context->CompositionString[byte_offset +
+                                                    byte_selection + i];
+                    }
+                    else
+                        root_context->CompositionString[byte_offset + i] = 0;
+                }
+                /* clean up the end */
+                root_context->dwCompStringLength -= byte_selection;
+
+                i = root_context->dwCompStringLength;
+                while (i < root_context->dwCompStringSize)
+                {
+                    root_context->CompositionString[i++] = 0;
+                }
+                wParam = root_context->CompositionString[0];
+                flags = GCS_COMPCLAUSE | GCS_COMPATTR;
+            }
+        }
+        else
+        {
+            int byte_expantion = byte_length - byte_selection;
+            if (byte_expantion + root_context->dwCompStringLength >=
+                root_context->dwCompStringSize)
+            {
+                if (root_context->CompositionString)
+                    root_context->CompositionString =
+                        HeapReAlloc(GetProcessHeap(), 0,
+                                    root_context->CompositionString,
+                                    root_context->dwCompStringSize +
+                                    byte_expantion);
+                else
+                    root_context->CompositionString =
+                        HeapAlloc(GetProcessHeap(), 0,
+                                    root_context->dwCompStringSize +
+                                    byte_expantion);
+
+                memset(&(root_context->CompositionString[root_context->
+                     dwCompStringSize]), byte_expantion,0);
+
+                root_context->dwCompStringSize += byte_expantion; 
+            }
+
+            ptr_new =  ((LPBYTE)lpComp);
+            ptr_old = root_context->CompositionString + byte_offset +
+                      byte_selection;
+
+            root_context->dwCompStringLength += byte_expantion;
+
+            wParam = lpComp[0];
+            flags = GCS_COMPCLAUSE | GCS_COMPATTR;
+            if (byte_expantion == 0)
+                flags |= CS_NOMOVECARET;
+
+            for (j=0,i = byte_offset; i < root_context->dwCompStringSize; i++)
+            {
+                if (j < byte_length)
+                {
+                    root_context->CompositionString[i] = ptr_new[j++];
+                }
+                else
+                {
+                    if (ptr_old < root_context->CompositionString +
+                        root_context->dwCompStringSize)
+                    {
+                        root_context->CompositionString[i] = *ptr_old;
+                        ptr_old++;
+                            }
+                    else
+                        root_context->CompositionString[i] = 0; 
+                }
+            }
+        }
+    }
+
+    /* result string only gets set as a block. */
+    if ((dwIndex == GCS_RESULTSTR) && (lpComp) && (dwCompLen))
+    {
+        flags = GCS_RESULTCLAUSE;
+        if (root_context->dwResultStringSize)
+            HeapFree(GetProcessHeap(),0,root_context->ResultString);
+        root_context->dwResultStringSize= byte_length;
+        root_context->ResultString= HeapAlloc(GetProcessHeap(),0,byte_length); 
+        memcpy(root_context->ResultString,lpComp,byte_length);
+        wParam = lpComp[0];
+        root_context->bRead = FALSE;
+    }
+
+    UpdateDataInDefaultIMEWindow(hwndDefault);
+
+    ImmInternalPostIMEMessage (WM_IME_COMPOSITION, wParam, dwIndex|flags);
+    
+    return TRUE;
+}
+
+void WINAPI ImmInternalSetOpenStatus(BOOL fOpen)
+{
+    TRACE("Setting interal state to %s\n",(fOpen)?"OPEN":"CLOSED");
+
+   root_context->bOpen = fOpen;
+   root_context->bInternalState = fOpen;
+    
+
+   if (fOpen == FALSE)
+   {
+        ShowWindow(hwndDefault,SW_HIDE);
+
+        if (root_context->dwCompStringSize)
+            HeapFree(GetProcessHeap(),0,root_context->CompositionString);
+        if (root_context->dwCompReadStringSize)
+            HeapFree(GetProcessHeap(),0,root_context->CompositionReadingString);
+        if (root_context->dwResultStringSize)
+            HeapFree(GetProcessHeap(),0,root_context->ResultString);
+        if (root_context->dwResultReadStringSize)
+            HeapFree(GetProcessHeap(),0,root_context->ResultReadingString);
+        root_context->dwCompStringSize = 0;
+        root_context->dwCompStringLength = 0;
+        root_context->CompositionString = NULL;
+        root_context->dwCompReadStringSize = 0;
+        root_context->CompositionReadingString = NULL;
+        root_context->dwResultStringSize = 0;
+        root_context->ResultString = NULL;
+        root_context->dwResultReadStringSize = 0;
+        root_context->ResultReadingString = NULL;
+    }
+    else
+    {
+        ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
+    }
+
+   SendMessageW(root_context->hwnd, WM_IME_NOTIFY, IMN_SETOPENSTATUS, 0);
+}
+
 
 /***********************************************************************
  *		ImmAssociateContext (IMM32.@)
@@ -215,6 +432,12 @@
         if (data->dwResultReadStringSize)
             HeapFree(GetProcessHeap(),0,data->ResultReadingString);
 
+        if (data->textfont)
+        {
+            DeleteObject(data->textfont);
+            data->textfont = NULL;
+        }
+
         HeapFree(GetProcessHeap(),0,data);
     }
     return TRUE;
@@ -283,6 +506,23 @@
 }
 
 /***********************************************************************
+ *		ImmGetCandidateList 
+ * Yes no A or W... The test from the platform sdk calls it like this
+DWORD WINAPI ImmGetCandidateList(
+  HIMC hIMC, DWORD deIndex,
+  LPCANDIDATELIST lpCandList, DWORD dwBufLen)
+{
+  FIXME("(%p, %ld, %p, %ld): stub\n",
+    hIMC, deIndex,
+    lpCandList, dwBufLen
+  );
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return 0;
+}
+ */
+
+
+/***********************************************************************
  *		ImmGetCandidateListA (IMM32.@)
  */
 DWORD WINAPI ImmGetCandidateListA(
@@ -371,29 +611,68 @@
 LONG WINAPI ImmGetCompositionStringA(
   HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
 {
-    LONG rc; 
-    LPBYTE wcstring=NULL;
+    LONG rc = 0; 
+    InputContextData *data = (InputContextData*)hIMC;
 
-    FIXME("(%p, %ld, %p, %ld): stub\n",
-            hIMC, dwIndex, lpBuf, dwBufLen);
+    TRACE("(%p, 0x%lx, %p, %ld)\n", hIMC, dwIndex, lpBuf, dwBufLen);
 
-    if (dwBufLen > 0)
-        wcstring = HeapAlloc(GetProcessHeap(),0,dwBufLen * 2); 
+    if (!data)
+       return FALSE;
  
-    rc = ImmGetCompositionStringW(hIMC, dwIndex, wcstring, dwBufLen*2 );
+    if (dwIndex == GCS_RESULTSTR)
+    {
+        CHAR buf[data->dwResultStringSize * 3];
+
+        rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)data->ResultString,
+                                 data->dwResultStringSize / sizeof(WCHAR), buf,
+                                 data->dwResultStringSize * 3, NULL, NULL);
 
-    if ((rc > dwBufLen) || (rc == 0))
+        if (dwBufLen >= rc)
+            memcpy(lpBuf,buf,rc);
+
+        data->bRead = TRUE;
+    }
+    else if (dwIndex == GCS_COMPSTR)
     {
-        if (wcstring)
-            HeapFree(GetProcessHeap(),0,wcstring);
+        CHAR buf[data->dwCompStringLength* 3];
 
-        return rc;
+        rc = WideCharToMultiByte(CP_ACP, 0,(LPWSTR)data->CompositionString,
+                                 data->dwCompStringLength/ sizeof(WCHAR), buf,
+                                 data->dwCompStringLength* 3, NULL, NULL);
+        
+        if (dwBufLen >= rc)
+            memcpy(lpBuf,buf,rc);
     }
+    else if (dwIndex == GCS_COMPATTR)
+    {
+        rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)data->CompositionString,
+                                 data->dwCompStringLength/ sizeof(WCHAR), NULL,
+                                 0, NULL, NULL);
  
-    rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)wcstring, (rc / sizeof(WCHAR)),
-                             lpBuf, dwBufLen, NULL, NULL);
+        if (dwBufLen >= rc)
+        {
+            int i=0;
+            for (i = 0;  i < rc; i++)
+                ((LPBYTE)lpBuf)[i] = ATTR_INPUT;
+        }
+    }
+    else if (dwIndex == GCS_COMPCLAUSE)
+    {
+        rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)data->CompositionString,
+                                 data->dwCompStringLength/ sizeof(WCHAR), NULL,
+                                 0, NULL, NULL);
 
-    HeapFree(GetProcessHeap(),0,wcstring);
+        if (dwBufLen >= sizeof(DWORD)*2)
+        {
+            ((LPDWORD)lpBuf)[0] = 0;
+            ((LPDWORD)lpBuf)[1] = rc;
+        }
+        rc = sizeof(DWORD)*2;
+    }
+    else
+    {
+        FIXME("Unhandled index 0x%lx\n",dwIndex);
+    }
 
     return rc;
 }
@@ -405,9 +684,10 @@
   HIMC hIMC, DWORD dwIndex,
   LPVOID lpBuf, DWORD dwBufLen)
 {
+  LONG rc = 0;
   InputContextData *data = (InputContextData*)hIMC;
 
-  FIXME("(%p, 0x%lx, %p, %ld): stub\n",
+  TRACE("(%p, 0x%lx, %p, %ld)\n",
     hIMC, dwIndex, lpBuf, dwBufLen
   );
 
@@ -421,54 +701,98 @@
         if (dwBufLen >= data->dwResultStringSize)
             memcpy(lpBuf,data->ResultString,data->dwResultStringSize);
         
-        return data->dwResultStringSize;
+        rc =  data->dwResultStringSize;
     }
-
-    if (dwIndex == GCS_RESULTREADSTR)
+    else if (dwIndex == GCS_RESULTREADSTR)
     {
         if (dwBufLen >= data->dwResultReadStringSize)
             memcpy(lpBuf,data->ResultReadingString,
                     data->dwResultReadStringSize);
         
-        return data->dwResultReadStringSize;
+        rc = data->dwResultReadStringSize;
     }   
+    else if (dwIndex == GCS_COMPSTR)
+    {
+        if (dwBufLen >= data->dwCompStringLength)
+            memcpy(lpBuf,data->CompositionString,data->dwCompStringLength);
 
-    if (dwIndex == GCS_COMPSTR)
+        rc = data->dwCompStringLength;
+    }
+    else if (dwIndex == GCS_COMPATTR)
     {
-        if (dwBufLen >= data->dwCompStringSize)
-            memcpy(lpBuf,data->CompositionString,data->dwCompStringSize);
+        int len = data->dwCompStringLength;
         
-        return data->dwCompStringSize;
+        if (dwBufLen >= len)
+        {
+            int i=0;
+            for (i = 0;  i < len; i++)
+                ((LPBYTE)lpBuf)[i] = ATTR_INPUT;
     }
 
-    if (dwIndex == GCS_COMPREADSTR)
+        rc = len;
+    }
+    else if (dwIndex == GCS_COMPCLAUSE)
+    {
+        if (dwBufLen >= sizeof(DWORD)*2)
+        {
+            ((LPDWORD)lpBuf)[0] = 0;
+            ((LPDWORD)lpBuf)[1] = data->dwCompStringLength/sizeof(WCHAR);
+        }
+        rc = sizeof(DWORD)*2;
+    }
+    else if (dwIndex == GCS_COMPREADSTR)
     {
         if (dwBufLen >= data->dwCompReadStringSize)
             memcpy(lpBuf,data->CompositionReadingString,
                     data->dwCompReadStringSize);
         
-        return data->dwCompReadStringSize;
+        rc = data->dwCompReadStringSize;
+    }   
+    else
+    {
+        FIXME("Unhandled index 0x%lx\n",dwIndex);
     }   
 
-    return 0;
+    return rc;
+}
+
+/*
+ * Yes no A or W... The test from the platform sdk calls it like this
+LONG WINAPI ImmGetCompositionString( HIMC hIMC, DWORD dwIndex,
+  LPVOID lpBuf, DWORD dwBufLen)
+{
+    return ImmGetCompositionStringA(hIMC,dwIndex,lpBuf,dwBufLen);
 }
+ */
 
 /***********************************************************************
  *		ImmGetCompositionWindow (IMM32.@)
  */
 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
 {
-  FIXME("(%p, %p): stub\n", hIMC, lpCompForm);
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return 0;
+    InputContextData *data = (InputContextData*)hIMC;
+
+    TRACE("(%p, %p)\n", hIMC, lpCompForm);
+
+    if (!data)
+        return FALSE;
+
+    memcpy(lpCompForm,&(data->CompForm),sizeof(COMPOSITIONFORM));
+    return 1;
 }
 
 /***********************************************************************
  *		ImmGetContext (IMM32.@)
+ *
  */
 HIMC WINAPI ImmGetContext(HWND hWnd)
 {
     FIXME("(%p): stub\n", hWnd);
+
+    if (!root_context)
+        return NULL;
+
+    root_context->hwnd = hWnd;
     return (HIMC)root_context;
 }
 
@@ -508,11 +832,12 @@
 BOOL WINAPI ImmGetConversionStatus(
   HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
 {
-  FIXME("(%p, %p, %p): stub\n",
-    hIMC, lpfdwConversion, lpfdwSentence
-  );
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return FALSE;
+    TRACE("(%p, %p, %p): best guess\n", hIMC, lpfdwConversion, lpfdwSentence);
+    if (lpfdwConversion)
+        *lpfdwConversion = IME_CMODE_NATIVE;
+    if (lpfdwSentence)
+        *lpfdwSentence = IME_SMODE_NONE;
+    return TRUE;
 }
 
 /***********************************************************************
@@ -520,15 +845,18 @@
  */
 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
 {
-  FIXME("(%p): semi-stub\n", hWnd);
+  FIXME("(%p - %p %p ): semi-stub\n", hWnd,hwndDefault, root_context);
 
   if ((!hwndDefault) && (root_context))
   {
-        static const WCHAR name[] = {'I','M','E',0};
+        static const WCHAR the_name[] = {'I','M','E','\0'};
+
         IMM_Register();
+        hwndDefault = CreateWindowExW( WS_EX_CLIENTEDGE, WC_IMECLASSNAME,
+                the_name, WS_POPUPWINDOW|WS_CAPTION, 0, 0, 120, 55, 0, 0,
+                hImeInst, 0);
 
-        hwndDefault = CreateWindowW( WC_IMECLASSNAME,
-                       name,WS_POPUPWINDOW,0,0,0,0,0,0,hImeInst,0);
+        TRACE("Default created (0x%x)\n",(INT)hwndDefault);
   }
 
   return (HWND)hwndDefault;
@@ -540,11 +868,29 @@
 UINT WINAPI ImmGetDescriptionA(
   HKL hKL, LPSTR lpszDescription, UINT uBufLen)
 {
-  FIXME("(%p, %s, %d): stub\n",
-    hKL, debugstr_a(lpszDescription), uBufLen
-  );
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  WCHAR *buf;
+  DWORD len;
+
+  TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
+
+  /* find out how many characters in the unicode buffer */
+  len = ImmGetDescriptionW( hKL, NULL, 0 );
+
+  /* allocate a buffer of that size */
+  buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
+  if( !buf )
   return 0;
+
+  /* fetch the unicode buffer */
+  len = ImmGetDescriptionW( hKL, buf, len );
+
+  /* convert it back to ASCII */
+  len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
+                             lpszDescription, uBufLen, NULL, NULL );
+
+  HeapFree( GetProcessHeap(), 0, buf );
+
+  return len;
 }
 
 /***********************************************************************
@@ -552,11 +898,23 @@
  */
 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
 {
-  FIXME("(%p, %s, %d): stub\n",
-    hKL, debugstr_w(lpszDescription), uBufLen
-  );
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return 0;
+  const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
+  int len;
+
+  FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
+
+  len = lstrlenW( name );
+  if( !uBufLen )
+     return len;
+
+  if( uBufLen < len )
+     len = uBufLen;
+
+  lstrcpynW( lpszDescription, name, len );
+
+  FIXME("\n");
+
+  return len;
 }
 
 /***********************************************************************
@@ -590,9 +948,7 @@
 UINT WINAPI ImmGetIMEFileNameA(
   HKL hKL, LPSTR lpszFileName, UINT uBufLen)
 {
-  FIXME("(%p, %s, %d): stub\n",
-    hKL, debugstr_a(lpszFileName), uBufLen
-  );
+  FIXME("(%p, %p, %d): stub\n", hKL, lpszFileName, uBufLen);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -603,9 +959,7 @@
 UINT WINAPI ImmGetIMEFileNameW(
   HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
 {
-  FIXME("(%p, %s, %d): stub\n",
-    hKL, debugstr_w(lpszFileName), uBufLen
-  );
+  FIXME("(%p, %p, %d): stub\n", hKL, lpszFileName, uBufLen);
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return 0;
 }
@@ -617,10 +971,10 @@
 {
   InputContextData *data = (InputContextData*)hIMC;
 
+    if (!data)
+        return FALSE;
   FIXME("(%p): semi-stub\n", hIMC);
 
-  if (!data) return FALSE;
-
   return data->bOpen;
 }
 
@@ -630,23 +984,38 @@
 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
 {
     DWORD rc = 0;
-    FIXME("(%p, %ld): semi-stub\n", hKL, fdwIndex);
+    TRACE("(%p, %ld)\n", hKL, fdwIndex);
 
     switch (fdwIndex)
     {
         case IGP_PROPERTY:
-            rc = IME_PROP_UNICODE | IME_PROP_SPECIAL_UI;
+            TRACE("(%s)\n", "IGP_PROPERTY");
+            rc = IME_PROP_UNICODE | IME_PROP_AT_CARET;
+            break;
+        case IGP_CONVERSION:
+            FIXME("(%s)\n", "IGP_CONVERSION");
+            rc = IME_CMODE_NATIVE;
+            break;
+        case IGP_SENTENCE:
+            FIXME("%s)\n", "IGP_SENTENCE");
+            rc = IME_SMODE_AUTOMATIC;
             break;
         case IGP_SETCOMPSTR:
-            rc = SCS_CAP_COMPSTR;
+            TRACE("(%s)\n", "IGP_SETCOMPSTR");
+            rc = 0;
             break;
         case IGP_SELECT:
+            TRACE("(%s)\n", "IGP_SELECT");
             rc = SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE;
             break;
         case IGP_GETIMEVERSION:
+            TRACE("(%s)\n", "IGP_GETIMEVERSION");
             rc = IMEVER_0400;
             break;
         case IGP_UI:
+            TRACE("(%s)\n", "IGP_UI");
+            rc = 0;
+            break;
         default:
             rc = 0;
     }
@@ -751,11 +1120,20 @@
 BOOL WINAPI ImmIsUIMessageA(
   HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
 {
-  FIXME("(%p, %d, %d, %ld): stub\n",
-    hWndIME, msg, wParam, lParam
-  );
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return FALSE;
+    BOOL rc = FALSE;
+    TRACE("(%p, %x, %d, %ld)\n", hWndIME, msg, wParam, lParam);
+    if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || 
+        (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
+        (msg >= WM_MSIME_SERVICE && msg <= WM_MSIME_DOCUMENTFEED))
+    {
+        if (hWndIME == NULL)
+        {
+            ImmGetDefaultIMEWnd(NULL);
+            PostMessageA(hwndDefault, msg, wParam, lParam);
+        }
+        rc = TRUE;
+    }
+    return rc;
 }
 
 /***********************************************************************
@@ -764,11 +1142,13 @@
 BOOL WINAPI ImmIsUIMessageW(
   HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
 {
-  FIXME("(%p, %d, %d, %ld): stub\n",
-    hWndIME, msg, wParam, lParam
-  );
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return FALSE;
+    BOOL rc = FALSE;
+    TRACE("(%p, %d, %d, %ld): stub\n", hWndIME, msg, wParam, lParam);
+    if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || 
+        (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
+        (msg >= WM_MSIME_SERVICE && msg <= WM_MSIME_DOCUMENTFEED))
+        rc = TRUE;
+    return rc;
 }
 
 /***********************************************************************
@@ -777,11 +1157,98 @@
 BOOL WINAPI ImmNotifyIME(
   HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
 {
+    BOOL rc = FALSE;
   FIXME("(%p, %ld, %ld, %ld): stub\n",
-    hIMC, dwAction, dwIndex, dwValue
-  );
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return FALSE;
+        hIMC, dwAction, dwIndex, dwValue);
+
+    switch(dwAction)
+    {
+        case NI_CHANGECANDIDATELIST:
+            FIXME("%s\n","NI_CHANGECANDIDATELIST");
+            break;
+        case NI_CLOSECANDIDATE:
+            FIXME("%s\n","NI_CLOSECANDIDATE");
+            break;
+        case NI_COMPOSITIONSTR:
+            switch (dwIndex)
+            {
+                case CPS_CANCEL:
+                    TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_CANCEL");
+                    X11DRV_ForceXIMReset(root_context->hwnd);
+                    if (root_context->dwCompStringSize)
+                    {
+                        HeapFree(GetProcessHeap(),0,
+                                 root_context->CompositionString);
+                        root_context->dwCompStringSize = 0;
+                        root_context->dwCompStringLength = 0;
+                        root_context->CompositionString = NULL;
+                        ImmInternalPostIMEMessage(WM_IME_COMPOSITION, 0,
+                                                  GCS_COMPSTR);
+                    }
+                    rc = TRUE;
+                    break;
+                case CPS_COMPLETE:
+                    TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_COMPLETE");
+                    X11DRV_ForceXIMReset(root_context->hwnd);
+                    if (root_context->dwResultStringSize)
+                    {
+                        HeapFree(GetProcessHeap(),0,root_context->ResultString);
+                        root_context->dwResultStringSize = 0;
+                        root_context->ResultString = NULL;
+                    }
+                    if (root_context->dwCompStringLength)
+                    {
+                        root_context->ResultString = HeapAlloc(
+                        GetProcessHeap(), 0, root_context->dwCompStringLength);
+                        root_context->dwResultStringSize =
+                                        root_context->dwCompStringLength;
+
+                        memcpy(root_context->ResultString,
+                               root_context->CompositionString,
+                               root_context->dwCompStringLength);
+
+                        HeapFree(GetProcessHeap(),0,
+                                 root_context->CompositionString);
+                        root_context->dwCompStringSize = 0;
+                        root_context->dwCompStringLength = 0;
+                        root_context->CompositionString = NULL;
+                        ImmInternalPostIMEMessage(WM_IME_COMPOSITION, 0,
+                                                  GCS_COMPSTR);
+                        ImmInternalPostIMEMessage(WM_IME_COMPOSITION, 0,
+                                                  GCS_RESULTSTR);
+                    }
+                    break;
+                case CPS_CONVERT:
+                    FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_CONVERT");
+                    break;
+                case CPS_REVERT:
+                    FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_REVERT");
+                    break;
+                default:
+                    ERR("%s - %s (%li)\n","NI_COMPOSITIONSTR","UNKNOWN",dwIndex);
+                    break;
+            }
+            break;
+        case NI_IMEMENUSELECTED:
+            FIXME("%s\n", "NI_IMEMENUSELECTED");
+            break;
+        case NI_OPENCANDIDATE:
+            FIXME("%s\n", "NI_OPENCANDIDATE");
+            break;
+        case NI_SELECTCANDIDATESTR:
+            FIXME("%s\n", "NI_SELECTCANDIDATESTR");
+            break;
+        case NI_SETCANDIDATE_PAGESIZE:
+            FIXME("%s\n", "NI_SETCANDIDATE_PAGESIZE");
+            break;
+        case NI_SETCANDIDATE_PAGESTART:
+            FIXME("%s\n", "NI_SETCANDIDATE_PAGESTART");
+            break;
+        default:
+            ERR("Unknown\n");
+    }
+  
+    return rc;
 }
 
 /***********************************************************************
@@ -816,8 +1283,8 @@
 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
 {
   FIXME("(%p, %p): stub\n", hWnd, hIMC);
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return FALSE;
+
+    return TRUE;
 }
 
 /***********************************************************************
@@ -836,9 +1303,26 @@
  */
 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
 {
-  FIXME("(%p, %p): stub\n", hIMC, lplf);
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    InputContextData *data = (InputContextData*)hIMC;
+    TRACE("(%p, %p)\n", hIMC, lplf);
+
+    if (!data)
   return FALSE;
+
+    memcpy(&data->font,lplf,sizeof(LOGFONTA));
+    MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->font.lfFaceName,
+                        LF_FACESIZE);
+
+    SendMessageW(root_context->hwnd, WM_IME_NOTIFY, IMN_SETCOMPOSITIONFONT, 0);
+
+    if (data->textfont)
+    {
+        DeleteObject(data->textfont);
+        data->textfont = NULL;
+    }
+
+    data->textfont = CreateFontIndirectW(&data->font); 
+    return TRUE;
 }
 
 /***********************************************************************
@@ -846,9 +1330,22 @@
  */
 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
 {
-  FIXME("(%p, %p): stub\n", hIMC, lplf);
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    InputContextData *data = (InputContextData*)hIMC;
+    TRACE("(%p, %p)\n", hIMC, lplf);
+
+    if (!data)
   return FALSE;
+
+    memcpy(&data->font,lplf,sizeof(LOGFONTW));
+    SendMessageW(root_context->hwnd, WM_IME_NOTIFY, IMN_SETCOMPOSITIONFONT, 0);
+
+    if (data->textfont)
+    {
+        DeleteObject(data->textfont);
+        data->textfont = NULL;
+    }
+    data->textfont = CreateFontIndirectW(&data->font); 
+    return TRUE;
 }
 
 /***********************************************************************
@@ -860,8 +1357,8 @@
   LPCVOID lpRead, DWORD dwReadLen)
 {
   FIXME("(%p, %ld, %p, %ld, %p, %ld): stub\n",
-    hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen
-  );
+    hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
+
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
   return FALSE;
 }
@@ -874,72 +1371,46 @@
 	LPCVOID lpComp, DWORD dwCompLen,
 	LPCVOID lpRead, DWORD dwReadLen)
 {
-    InputContextData *data = (InputContextData*)hIMC;
-
-    FIXME("(%p, %ld, %p, %ld, %p, %ld): semi-stub\n",
-        hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen
-        );
+    FIXME("(%p, %ld, %p, %ld, %p, %ld): stub\n",
+        hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
 
-    if (!data)
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
         return FALSE;
+}
 
-    if ((dwIndex == SCS_SETSTR)&&(dwCompLen || dwReadLen))
-        SendMessageW(data->hwnd, WM_IME_STARTCOMPOSITION, 0, 0);
-
-    if (dwIndex == SCS_SETSTR)
+/***********************************************************************
+ *		ImmSetCompositionWindow (IMM32.@)
+ */
+BOOL WINAPI ImmSetCompositionWindow(
+  HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
     {
-        INT send_comp = 0;
+    BOOL reshow = FALSE;
+    InputContextData *data = (InputContextData*)hIMC;
 
+    TRACE("(%p, %p)\n", hIMC, lpCompForm);
+    TRACE("\t%lx, (%li,%li), (%li,%li - %li,%li)\n",lpCompForm->dwStyle,
+lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
+lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
 
-        if (lpComp && dwCompLen)
-        {
-/*            if (data->dwCompStringSize)
-                HeapFree(GetProcessHeap(),0,data->CompositionString);
-            data->dwCompStringSize = dwCompLen;
-            data->CompositionString = HeapAlloc(GetProcessHeap(),0,dwCompLen); 
-            memcpy(data->CompositionString,lpComp,dwCompLen);
-            send_comp |= GCS_COMPSTR;
-*/
-            data->bRead = FALSE;
+    if (!data)
+        return FALSE;
 
-            if (data->dwResultStringSize)
-                HeapFree(GetProcessHeap(),0,data->ResultString);
-            data->dwResultStringSize= dwCompLen;
-            data->ResultString= HeapAlloc(GetProcessHeap(),0,dwCompLen); 
-            memcpy(data->ResultString,lpComp,dwCompLen);
-            send_comp |= GCS_RESULTSTR;
-        }
+    memcpy(&data->CompForm,lpCompForm,sizeof(COMPOSITIONFORM));
 
-        if (lpRead && dwReadLen)
+    if (IsWindowVisible(hwndDefault))
         {
-            if (data->dwCompReadStringSize)
-                HeapFree(GetProcessHeap(),0,data->CompositionReadingString);
-            data->dwCompReadStringSize= dwReadLen;
-            data->CompositionReadingString = HeapAlloc(GetProcessHeap(), 0,
-                                                        dwReadLen);
-            memcpy(data->CompositionReadingString,lpRead,dwReadLen);
-            send_comp |= GCS_COMPREADSTR;
+        reshow = TRUE;
+        ShowWindow(hwndDefault,SW_HIDE);
         }
 
-        if (send_comp)
-            SendMessageW(data->hwnd, WM_IME_COMPOSITION, 0, send_comp);
+    FIXME("STUB\n");   
 
-        SendMessageW(data->hwnd, WM_IME_ENDCOMPOSITION, 0, 0);
+    if (reshow)
+        ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
 
+    SendMessageW(root_context->hwnd, WM_IME_NOTIFY,IMN_SETCOMPOSITIONWINDOW, 0);
         return TRUE;
-    }
-    return FALSE;
-}
 
-/***********************************************************************
- *		ImmSetCompositionWindow (IMM32.@)
- */
-BOOL WINAPI ImmSetCompositionWindow(
-  HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
-{
-  FIXME("(%p, %p): stub\n", hIMC, lpCompForm);
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return FALSE;
 }
 
 /***********************************************************************
@@ -962,16 +1433,34 @@
 {
     InputContextData *data = (InputContextData*)hIMC;
     FIXME("Semi-Stub\n");
-    if (data)
+
+    if (!data)
+        return FALSE;
+
+    if (fOpen != data->bInternalState)
     {
-        data->bOpen = fOpen;
-        SendMessageW(data->hwnd, WM_IME_NOTIFY, IMN_SETOPENSTATUS, 0);
-        return TRUE;
-    }
+        if (fOpen == FALSE)
+            X11DRV_ForceXIMReset(data->hwnd);
+
+        if (fOpen == FALSE)
+            ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0);
+        else
+            ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0);
+
+        ImmInternalSetOpenStatus(fOpen);
+        ImmInternalSetOpenStatus(!fOpen);
+
+        if (data->bOpen == FALSE)
+            ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0);
     else
+            ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0);
+
         return FALSE;
 }
 
+    return TRUE;
+}
+
 /***********************************************************************
  *		ImmSetStatusWindowPos (IMM32.@)
  */
@@ -1018,42 +1507,157 @@
   return FALSE;
 }
 
+
+/*****
+ * Internal functions to help with IME window management
+ */
+void PaintDefaultIMEWnd(HWND hwnd)
+{
+    PAINTSTRUCT ps;
+    RECT rect;
+    HDC hdc = BeginPaint(hwnd,&ps);
+    GetClientRect(hwnd,&rect);
+
+    if (root_context->dwCompStringLength && root_context->CompositionString)
+    {
+        SIZE size;
+        POINT pt;
+        HFONT oldfont = NULL;
+
+        if (root_context->textfont)
+            oldfont = SelectObject(hdc,root_context->textfont);
+
+        TextOutW(hdc, 0,0,(LPWSTR)root_context->CompositionString,
+                 root_context->dwCompStringLength / sizeof(WCHAR));
+
+        GetTextExtentPoint32W(hdc, (LPWSTR)root_context->CompositionString,
+                              root_context->dwCompStringLength / sizeof(WCHAR),
+                              &size);
+        pt.x = size.cx;
+        pt.y = size.cy;
+        LPtoDP(hdc,&pt,1);
+        rect.left = pt.x;
+
+        if (oldfont)
+            SelectObject(hdc,oldfont);
+    }
+    FillRect(hdc,&rect, (HBRUSH) (COLOR_WINDOW+1));
+    EndPaint(hwnd,&ps);
+}
+
+void UpdateDataInDefaultIMEWindow(HWND hwnd)
+{
+    RedrawWindow(hwnd,NULL,NULL,RDW_ERASENOW|RDW_INVALIDATE);
+}
+
 /*
  * The window proc for the default IME window
  */
-static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
+static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam,
                                           LPARAM lParam)
 {
-    TRACE("Incoming Message 0x%x  (0x%08x, 0x%08x)\n", uMsg, (UINT)wParam,
+    LRESULT rc = 0;
+
+    TRACE("Incoming Message 0x%x  (0x%08x, 0x%08x)\n", msg, (UINT)wParam,
            (UINT)lParam);
 
-    switch(uMsg)
+    switch(msg)
     {
+        case WM_PAINT:
+            PaintDefaultIMEWnd(hwnd);
+            return FALSE;
+
         case WM_NCCREATE:
             return TRUE;
 
+        case WM_CREATE:
+            SetWindowTextA(hwnd,"Wine Ime Active");
+            return TRUE;
+
+        case WM_SETFOCUS:
+            if (wParam)
+                SetFocus((HWND)wParam);
+            else
+                FIXME("Received focus, should never have focus\n");
+
         case WM_IME_COMPOSITION:
-            TRACE("IME message %s, 0x%x, 0x%x\n",
-                    "WM_IME_COMPOSITION", (UINT)wParam, (UINT)lParam);
+            TRACE("IME message %s, 0x%x, 0x%x (%i)\n",
+                    "WM_IME_COMPOSITION", (UINT)wParam, (UINT)lParam,
+                     root_context->bRead);
+            if ((lParam & GCS_RESULTSTR) && (!root_context->bRead))
+                    IMM_PostResult(root_context);
+            else
+                 UpdateDataInDefaultIMEWindow(hwnd);
             break;
         case WM_IME_STARTCOMPOSITION:
             TRACE("IME message %s, 0x%x, 0x%x\n",
                     "WM_IME_STARTCOMPOSITION", (UINT)wParam, (UINT)lParam);
+            root_context->hwnd = GetFocus();
+            ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
             break;
         case WM_IME_ENDCOMPOSITION:
             TRACE("IME message %s, 0x%x, 0x%x\n",
                     "WM_IME_ENDCOMPOSITION", (UINT)wParam, (UINT)lParam);
-            /* 
-             *   if the string has not been read, then send it as
-             *   WM_IME_CHAR messages
-             */
-            if (!root_context->bRead)
-                IMM_PostResult(root_context);
+            ShowWindow(hwndDefault,SW_HIDE);
             break;
         case WM_IME_SELECT:
             TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_SELECT",
                 (UINT)wParam, (UINT)lParam);
             break;
+        case WM_IME_CONTROL:
+            TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_CONTROL",
+                (UINT)wParam, (UINT)lParam);
+            rc = 1; 
+            break;
+        case WM_IME_NOTIFY:
+            TRACE("!! IME NOTIFY\n");
+            break;
+       default:
+            TRACE("Non-standard message 0x%x\n",msg);
     }
-    return 0;
+    /* check the MSIME messages */
+    if (msg == WM_MSIME_SERVICE)
+    {
+            TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_SERVICE",
+                (UINT)wParam, (UINT)lParam);
+            rc = FALSE;
+    }
+    else if (msg == WM_MSIME_RECONVERTOPTIONS)
+    {
+            TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTOPTIONS",
+                (UINT)wParam, (UINT)lParam);
+    }
+    else if (msg == WM_MSIME_MOUSE)
+    {
+            TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_MOUSE",
+                (UINT)wParam, (UINT)lParam);
+    }
+    else if (msg == WM_MSIME_RECONVERTREQUEST)
+    {
+            TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTREQUEST",
+                (UINT)wParam, (UINT)lParam);
+    }
+    else if (msg == WM_MSIME_RECONVERT)
+    {
+            TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERT",
+                (UINT)wParam, (UINT)lParam);
+    }
+    else if (msg == WM_MSIME_QUERYPOSITION)
+    {
+            TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_QUERYPOSITION",
+                (UINT)wParam, (UINT)lParam);
+    }
+    else if (msg == WM_MSIME_DOCUMENTFEED)
+    {
+            TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_DOCUMENTFEED",
+                (UINT)wParam, (UINT)lParam);
+    }
+
+    /* DefWndProc if not an IME message */
+    if (!rc && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || 
+        (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
+        (msg >= WM_MSIME_SERVICE && msg <= WM_MSIME_DOCUMENTFEED)))
+            return DefWindowProcW(hwnd,msg,wParam,lParam);
+    else
+        return rc;
 }
Index: dlls/imm32/imm32.spec
===================================================================
RCS file: /home/wine/wine/dlls/imm32/imm32.spec,v
retrieving revision 1.15
diff -u -w -r1.15 imm32.spec
--- dlls/imm32/imm32.spec	20 Mar 2003 03:53:15 -0000	1.15
+++ dlls/imm32/imm32.spec	7 Jan 2004 17:13:15 -0000
@@ -21,22 +21,23 @@
 @ stdcall ImmGetCompositionFontW(long ptr)
 @ stdcall ImmGetCompositionStringA (long long ptr long)
 @ stdcall ImmGetCompositionStringW (long long ptr long)
+@ stdcall ImmGetCompositionString (long long ptr long) ImmGetCompositionStringA
 @ stdcall ImmGetCompositionWindow(long ptr)
 @ stdcall ImmGetContext(long)
 @ stdcall ImmGetConversionListA(long long str ptr long long)
 @ stdcall ImmGetConversionListW(long long wstr ptr long long)
 @ stdcall ImmGetConversionStatus(long ptr ptr)
 @ stdcall ImmGetDefaultIMEWnd(long)
-@ stdcall ImmGetDescriptionA(long str long)
-@ stdcall ImmGetDescriptionW(long wstr long)
-@ stdcall ImmGetGuideLineA(long long str long)
-@ stdcall ImmGetGuideLineW(long long wstr long)
+@ stdcall ImmGetDescriptionA(long ptr long)
+@ stdcall ImmGetDescriptionW(long ptr long)
+@ stdcall ImmGetGuideLineA(long long ptr long)
+@ stdcall ImmGetGuideLineW(long long ptr long)
 @ stub ImmGetHotKey
 @ stub ImmGetIMCCLockCount
 @ stub ImmGetIMCCSize
 @ stub ImmGetIMCLockCount
-@ stdcall ImmGetIMEFileNameA(long str long)
-@ stdcall ImmGetIMEFileNameW(long wstr long)
+@ stdcall ImmGetIMEFileNameA(long ptr long)
+@ stdcall ImmGetIMEFileNameW(long ptr long)
 @ stdcall ImmGetOpenStatus(long)
 @ stdcall ImmGetProperty(long long)
 @ stdcall ImmGetRegisterWordStyleA(long long ptr)
@@ -71,3 +72,8 @@
 @ stub ImmUnlockIMCC
 @ stdcall ImmUnregisterWordA(long str long str)
 @ stdcall ImmUnregisterWordW(long wstr long wstr)
+
+# wine internal
+@ stdcall ImmInternalPostIMEMessage(long long long)
+@ stdcall ImmSetInternalString(long long long ptr long)
+@ stdcall ImmInternalSetOpenStatus(long)
--- /dev/null	Thu Aug 30 15:30:55 2001
+++ dlls/imm32/imm_internal.h	Wed Jan  7 09:14:46 2004
@@ -0,0 +1,24 @@
+/*
+ * IMM32 library
+ *
+ * Copyright 2003 CodeWeavers, Aric Stewart
+ *
+ * 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
+ */
+
+void WINAPI ImmInternalPostIMEMessage(UINT, WPARAM, LPARAM);
+BOOL WINAPI ImmSetInternalString( DWORD, DWORD, DWORD, LPWSTR, DWORD);
+void WINAPI ImmInternalSetOpenStatus(BOOL fOpen);
+void WINAPI X11DRV_ForceXIMReset(HWND hwnd);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: FULLIME.EXE
Type: application/octet-stream
Size: 52224 bytes
Desc: not available
Url : http://www.winehq.org/pipermail/wine-patches/attachments/20040107/7a91a659/FULLIME.obj
-------------- next part --------------
A non-text attachment was scrubbed...
Name: HALFIME.EXE
Type: application/octet-stream
Size: 46080 bytes
Desc: not available
Url : http://www.winehq.org/pipermail/wine-patches/attachments/20040107/7a91a659/HALFIME.obj


More information about the wine-patches mailing list