< prev index next >

src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c

Print this page
rev 50172 : 8201429: Support AIX Input Method Editor (IME) for AWT Input Method Framework (IMF)

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -21,99 +21,111 @@
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
 
-#ifdef HEADLESS
-    #error This file should not be included in headless library
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <X11/Xlib.h>
-#include <X11/keysym.h>
-#include <sys/time.h>
-
 #include "awt.h"
 #include "awt_p.h"
 
+#include <sun_awt_X11InputMethodBase.h>
 #include <sun_awt_X11InputMethod.h>
 #include <sun_awt_X11_XInputMethod.h>
 
+#include <langinfo.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <wchar.h>
+#include <wctype.h>
+#include <X11/Intrinsic.h>
+#include <X11/keysym.h>
+#include <X11/Xlib.h>
+
+#ifdef HEADLESS
+    #error This file should not be included in headless library
+#endif
+
 #define THROW_OUT_OF_MEMORY_ERROR() \
         JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL)
 
 struct X11InputMethodIDs {
   jfieldID pData;
 } x11InputMethodIDs;
 
-static void PreeditStartCallback(XIC, XPointer, XPointer);
+static int PreeditStartCallback(XIC, XPointer, XPointer);
 static void PreeditDoneCallback(XIC, XPointer, XPointer);
 static void PreeditDrawCallback(XIC, XPointer,
                                 XIMPreeditDrawCallbackStruct *);
 static void PreeditCaretCallback(XIC, XPointer,
                                  XIMPreeditCaretCallbackStruct *);
-#if defined(__linux__) || defined(MACOSX)
 static void StatusStartCallback(XIC, XPointer, XPointer);
 static void StatusDoneCallback(XIC, XPointer, XPointer);
 static void StatusDrawCallback(XIC, XPointer,
                                XIMStatusDrawCallbackStruct *);
-#endif
 
 #define ROOT_WINDOW_STYLES      (XIMPreeditNothing | XIMStatusNothing)
 #define NO_STYLES               (XIMPreeditNone | XIMStatusNone)
+/* added style to allow for in-place composition, such as "dead" keys for accents */
+#define IN_PLACE_STYLES         (XIMPreeditNothing | XIMStatusNone)
 
 #define PreeditStartIndex       0
 #define PreeditDoneIndex        1
 #define PreeditDrawIndex        2
 #define PreeditCaretIndex       3
-#if defined(__linux__) || defined(MACOSX)
 #define StatusStartIndex        4
 #define StatusDoneIndex         5
 #define StatusDrawIndex         6
 #define NCALLBACKS              7
-#else
-#define NCALLBACKS              4
-#endif
+
+#define STATUS_BORDER 2         /* Status Border width */
+#define CARET_OFFSET 1          /* Offset of caret position (pixel) */
+#define BORDER_MARGIN 3         /* BORDER MARGIN width */
+#define STATUS_MARGIN 7         /* Margin between the status window and its parent window */
+#define PREEDIT_ATTR_MASK (XIMReverse|XIMUnderline)
+          /* Preedit attribute which host adapter can handle */
 
 /*
  * Callback function pointers: the order has to match the *Index
  * values above.
  */
 static XIMProc callback_funcs[NCALLBACKS] = {
     (XIMProc)PreeditStartCallback,
     (XIMProc)PreeditDoneCallback,
     (XIMProc)PreeditDrawCallback,
     (XIMProc)PreeditCaretCallback,
-#if defined(__linux__) || defined(MACOSX)
     (XIMProc)StatusStartCallback,
     (XIMProc)StatusDoneCallback,
     (XIMProc)StatusDrawCallback,
-#endif
 };
 
-#if defined(__linux__) || defined(MACOSX)
 #define MAX_STATUS_LEN  100
 typedef struct {
     Window   w;                /*status window id        */
     Window   root;             /*the root window id      */
     Window   parent;           /*parent shell window     */
+    Window   grandParent;      /*window has WM frame     */
     int      x, y;             /*parent's upperleft position */
     int      width, height;    /*parent's width, height  */
     GC       lightGC;          /*gc for light border     */
     GC       dimGC;            /*gc for dim border       */
     GC       bgGC;             /*normal painting         */
     GC       fgGC;             /*normal painting         */
     int      statusW, statusH; /*status window's w, h    */
     int      rootW, rootH;     /*root window's w, h    */
     int      bWidth;           /*border width            */
-    char     status[MAX_STATUS_LEN]; /*status text       */
+    wchar_t  status[MAX_STATUS_LEN + 1]; /*status text       */
     XFontSet fontset;           /*fontset for drawing    */
     int      off_x, off_y;
     Bool     on;                /*if the status window on*/
+    int      fOff;              /* font base line(in pixel) from top */
+    int      fBot;              /* font bottom line(in pixel) from top */
+    int      peTextW;           /* Composition text width in pixel */
+    wchar_t* peText;            /* Composed string (wide char.) */
+    XIMFeedback* peAttr;        /* Composed text attribute */
+    int      peCaret;           /* Caret position in number of character */
+    Bool     status_ready;      /* Not draw Status at XCreateIC */
 } StatusWindow;
-#endif
 
 /*
  * X11InputMethodData keeps per X11InputMethod instance information. A pointer
  * to this data structure is kept in an X11InputMethod object (pData).
  */

@@ -122,37 +134,16 @@
     XIC         ic_active;      /* X Input Context for active clients */
     XIC         ic_passive;     /* X Input Context for passive clients */
     XIMCallback *callbacks;     /* callback parameters */
     jobject     x11inputmethod; /* global ref to X11InputMethod instance */
                                 /* associated with the XIC */
-#if defined(__linux__) || defined(MACOSX)
     StatusWindow *statusWindow; /* our own status window  */
-#endif
-    char        *lookup_buf;    /* buffer used for XmbLookupString */
-    int         lookup_buf_len; /* lookup buffer size in bytes */
+    Bool        passiveStatusWindow;/* Passive Client uses StatusWindow */
+    Bool        isActiveClient;     /* True:clinet is active */
+    Bool        forceReset;     /* True: call resetXIC before UnsetICFocus */
 } X11InputMethodData;
 
-/*
- * When XIC is created, a global reference is created for
- * sun.awt.X11InputMethod object so that it could be used by the XIM callback
- * functions. This could be a dangerous thing to do when the original
- * X11InputMethod object is garbage collected and as a result,
- * destroyX11InputMethodData is called to delete the global reference.
- * If any XIM callback function still holds and uses the "already deleted"
- * global reference, disaster is going to happen. So we have to maintain
- * a list for these global references which is consulted first when the
- * callback functions or any function tries to use "currentX11InputMethodObject"
- * which always refers to the global reference try to use it.
- *
- */
-typedef struct _X11InputMethodGRefNode {
-    jobject inputMethodGRef;
-    struct _X11InputMethodGRefNode* next;
-} X11InputMethodGRefNode;
-
-X11InputMethodGRefNode *x11InputMethodGRefListHead = NULL;
-
 /* reference to the current X11InputMethod instance, it is always
    point to the global reference to the X11InputMethodObject since
    it could be referenced by different threads. */
 jobject currentX11InputMethodInstance = NULL;
 

@@ -163,29 +154,45 @@
 static XIM X11im = NULL;
 Display * dpy = NULL;
 
 #define GetJNIEnv() (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2)
 
-static void DestroyXIMCallback(XIM, XPointer, XPointer);
-static void OpenXIMCallback(Display *, XPointer, XPointer);
-/* Solaris XIM Extention */
-#define XNCommitStringCallback "commitStringCallback"
-static void CommitStringCallback(XIC, XPointer, XPointer);
-
 static X11InputMethodData * getX11InputMethodData(JNIEnv *, jobject);
 static void setX11InputMethodData(JNIEnv *, jobject, X11InputMethodData *);
 static void destroyX11InputMethodData(JNIEnv *, X11InputMethodData *);
 static void freeX11InputMethodData(JNIEnv *, X11InputMethodData *);
 
-#ifdef __solaris__
-/* Prototype for this function is missing in Solaris X11R6 Xlib.h */
+/* Prototype for this function is missing in AIX Xlib.h */
 extern char *XSetIMValues(
 #if NeedVarargsPrototypes
     XIM /* im */, ...
 #endif
 );
-#endif
+
+static int st_wcslen(wchar_t *string);
+static Bool isPreeditStateActive(XIC ic);
+static void * buf_insert(void * src, void * insert, int size,
+                         int src_len, int ins_len, int offset);
+static void * handle_buffer(void * source, void * insert,
+                            int size, int src_len, int ins_len,
+                            int del_len, int offset);
+static void preedit_draw_passive(X11InputMethodData *pX11IMData,
+                                 XIMPreeditDrawCallbackStruct *pre_draw);
+static void resetPassivePreeditText(StatusWindow *statusWindow);
+static void draw_caret(StatusWindow *statusWindow, GC gc, int pos);
+static int  get_next_attr(int len, unsigned long *attr);
+static void draw_preedit(StatusWindow *statusWindow);
+static void align_status(StatusWindow *statusWindow);
+static void shrink_status(StatusWindow *statusWindow);
+static GC create_gc(Window win, Bool isReverse);
+static XFontSet create_fontset(void);
+static Bool is_text_available(XIMText * text);
+static Bool isNativeIm();
+static Window getGrandParent(Window parent);
+static void moveStatusWindow(StatusWindow *statusWindow);
+static void arrange_window_stack(StatusWindow* statusWindow);
+static Window get_current_focus(XIC ic);
 
 /*
  * This function is stolen from /src/solaris/hpi/src/system_md.c
  * It is used in setting the time in Java-level InputEvents
  */

@@ -227,91 +234,10 @@
     }
 
     return mbs;
 }
 
-/*
- * Returns True if the global reference is still in the list,
- * otherwise False.
- */
-static Bool isX11InputMethodGRefInList(jobject imGRef) {
-    X11InputMethodGRefNode *pX11InputMethodGRef = x11InputMethodGRefListHead;
-
-    if (imGRef == NULL) {
-        return False;
-    }
-
-    while (pX11InputMethodGRef != NULL) {
-        if (pX11InputMethodGRef->inputMethodGRef == imGRef) {
-            return True;
-        }
-        pX11InputMethodGRef = pX11InputMethodGRef->next;
-    }
-
-    return False;
-}
-
-/*
- * Add the new created global reference to the list.
- */
-static void addToX11InputMethodGRefList(jobject newX11InputMethodGRef) {
-    X11InputMethodGRefNode *newNode = NULL;
-
-    if (newX11InputMethodGRef == NULL ||
-        isX11InputMethodGRefInList(newX11InputMethodGRef)) {
-        return;
-    }
-
-    newNode = (X11InputMethodGRefNode *)malloc(sizeof(X11InputMethodGRefNode));
-
-    if (newNode == NULL) {
-        return;
-    } else {
-        newNode->inputMethodGRef = newX11InputMethodGRef;
-        newNode->next = x11InputMethodGRefListHead;
-        x11InputMethodGRefListHead = newNode;
-    }
-}
-
-/*
- * Remove the global reference from the list.
- */
-static void removeX11InputMethodGRefFromList(jobject x11InputMethodGRef) {
-     X11InputMethodGRefNode *pX11InputMethodGRef = NULL;
-     X11InputMethodGRefNode *cX11InputMethodGRef = x11InputMethodGRefListHead;
-
-     if (x11InputMethodGRefListHead == NULL ||
-         x11InputMethodGRef == NULL) {
-         return;
-     }
-
-     /* cX11InputMethodGRef always refers to the current node while
-        pX11InputMethodGRef refers to the previous node.
-     */
-     while (cX11InputMethodGRef != NULL) {
-         if (cX11InputMethodGRef->inputMethodGRef == x11InputMethodGRef) {
-             break;
-         }
-         pX11InputMethodGRef = cX11InputMethodGRef;
-         cX11InputMethodGRef = cX11InputMethodGRef->next;
-     }
-
-     if (cX11InputMethodGRef == NULL) {
-         return; /* Not found. */
-     }
-
-     if (cX11InputMethodGRef == x11InputMethodGRefListHead) {
-         x11InputMethodGRefListHead = x11InputMethodGRefListHead->next;
-     } else {
-         pX11InputMethodGRef->next = cX11InputMethodGRef->next;
-     }
-     free(cX11InputMethodGRef);
-
-     return;
-}
-
-
 static X11InputMethodData * getX11InputMethodData(JNIEnv * env, jobject imInstance) {
     X11InputMethodData *pX11IMData =
         (X11InputMethodData *)JNU_GetLongFieldAsPtr(env, imInstance, x11InputMethodIDs.pData);
 
     /*

@@ -370,40 +296,38 @@
 }
 
 static void
 freeX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData)
 {
-#if defined(__linux__) || defined(MACOSX)
     if (pX11IMData->statusWindow != NULL){
         StatusWindow *sw = pX11IMData->statusWindow;
         XFreeGC(awt_display, sw->lightGC);
         XFreeGC(awt_display, sw->dimGC);
         XFreeGC(awt_display, sw->bgGC);
         XFreeGC(awt_display, sw->fgGC);
         if (sw->fontset != NULL) {
             XFreeFontSet(awt_display, sw->fontset);
         }
         XDestroyWindow(awt_display, sw->w);
+        if (pX11IMData->statusWindow->peText){
+            free((void *)pX11IMData->statusWindow->peText);
+            pX11IMData->statusWindow->peText = NULL;
+        }
+        if (pX11IMData->statusWindow->peAttr){
+            free((void *)pX11IMData->statusWindow->peAttr);
+            pX11IMData->statusWindow->peAttr = NULL;
+        }
         free((void*)sw);
     }
-#endif
 
     if (pX11IMData->callbacks)
         free((void *)pX11IMData->callbacks);
 
     if (env) {
-        /* Remove the global reference from the list, so that
-           the callback function or whoever refers to it could know.
-        */
-        removeX11InputMethodGRefFromList(pX11IMData->x11inputmethod);
         (*env)->DeleteGlobalRef(env, pX11IMData->x11inputmethod);
     }
 
-    if (pX11IMData->lookup_buf) {
-        free((void *)pX11IMData->lookup_buf);
-    }
-
     free((void *)pX11IMData);
 }
 
 /*
  * Sets or unsets the focus to the given XIC.

@@ -453,10 +377,13 @@
 Boolean
 awt_x11inputmethod_lookupString(XKeyPressedEvent *event, KeySym *keysymp)
 {
     JNIEnv *env = GetJNIEnv();
     X11InputMethodData *pX11IMData = NULL;
+    int buf_len = INITIAL_LOOKUP_BUF_SIZE;
+    char mbbuf[INITIAL_LOOKUP_BUF_SIZE];
+    char *buf;
     KeySym keysym = NoSymbol;
     Status status;
     int mblen;
     jstring javastr;
     XIC ic;

@@ -465,63 +392,38 @@
 
     /*
       printf("lookupString: entering...\n");
      */
 
-    if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) {
-        currentX11InputMethodInstance = NULL;
-        return False;
-    }
-
     pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance);
 
     if (pX11IMData == NULL) {
-#if defined(__linux__) || defined(MACOSX)
         return False;
-#else
-        return result;
-#endif
     }
 
     if ((ic = pX11IMData->current_ic) == (XIC)0){
-#if defined(__linux__) || defined(MACOSX)
         return False;
-#else
-        return result;
-#endif
-    }
-
-    /* allocate the lookup buffer at the first invocation */
-    if (pX11IMData->lookup_buf_len == 0) {
-        pX11IMData->lookup_buf = (char *)malloc(INITIAL_LOOKUP_BUF_SIZE);
-        if (pX11IMData->lookup_buf == NULL) {
-            THROW_OUT_OF_MEMORY_ERROR();
-            return result;
-        }
-        pX11IMData->lookup_buf_len = INITIAL_LOOKUP_BUF_SIZE;
     }
 
-    mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf,
-                            pX11IMData->lookup_buf_len - 1, &keysym, &status);
+    buf = mbbuf;
+    mblen = XmbLookupString(ic, event, buf,
+                            buf_len - 1, &keysym, &status);
 
     /*
      * In case of overflow, a buffer is allocated and it retries
      * XmbLookupString().
      */
     if (status == XBufferOverflow) {
-        free((void *)pX11IMData->lookup_buf);
-        pX11IMData->lookup_buf_len = 0;
-        pX11IMData->lookup_buf = (char *)malloc(mblen + 1);
-        if (pX11IMData->lookup_buf == NULL) {
+        buf_len = mblen + 1;
+        buf = (char *)malloc(buf_len);
+        if (buf == NULL) {
             THROW_OUT_OF_MEMORY_ERROR();
             return result;
         }
-        pX11IMData->lookup_buf_len = mblen + 1;
-        mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf,
-                            pX11IMData->lookup_buf_len - 1, &keysym, &status);
+        mblen = XmbLookupString(ic, event, buf, buf_len, &keysym, &status);
     }
-    pX11IMData->lookup_buf[mblen] = 0;
+    buf[mblen] = 0;
 
     /* Get keysym without taking modifiers into account first to map
      * to AWT keyCode table.
      */
     switch (status) {

@@ -534,52 +436,57 @@
             }
         }
         composing = False;
         /*FALLTHRU*/
     case XLookupChars:
-    /*
-     printf("lookupString: status=XLookupChars, type=%d, state=%x, keycode=%x, keysym=%x\n",
-       event->type, event->state, event->keycode, keysym);
-    */
-        javastr = JNU_NewStringPlatform(env, (const char *)pX11IMData->lookup_buf);
+        /*
+        printf("lookupString: status=XLookupChars, type=%d, state=%x, keycode=%x, keysym=%x\n",
+               event->type, event->state, event->keycode, keysym);
+        */
+        javastr = JNU_NewStringPlatform(env, (const char *)buf);
         if (javastr != NULL) {
             JNU_CallMethodByName(env, NULL,
                                  currentX11InputMethodInstance,
                                  "dispatchCommittedText",
                                  "(Ljava/lang/String;J)V",
                                  javastr,
                                  event->time);
+            if ((*env)->ExceptionOccurred(env)) {
+                (*env)->ExceptionDescribe(env);
+                (*env)->ExceptionClear(env);
+            }
         }
         break;
 
     case XLookupKeySym:
-    /*
-     printf("lookupString: status=XLookupKeySym, type=%d, state=%x, keycode=%x, keysym=%x\n",
-       event->type, event->state, event->keycode, keysym);
-    */
+        /*
+        printf("lookupString: status=XLookupKeySym, type=%d, state=%x, keycode=%x, keysym=%x\n",
+               event->type, event->state, event->keycode, keysym);
+        */
         if (keysym == XK_Multi_key)
             composing = True;
         if (! composing) {
             *keysymp = keysym;
             result = False;
         }
         break;
 
     case XLookupNone:
-    /*
-     printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n",
-        event->type, event->state, event->keycode, keysym);
-    */
+        /*
+        printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n",
+               event->type, event->state, event->keycode, keysym);
+        */
         break;
     }
 
+    if (buf != mbbuf) {
+        free(buf);
+    }
     return result;
 }
 
-#if defined(__linux__) || defined(MACOSX)
-static StatusWindow *createStatusWindow(
-                                Window parent) {
+static StatusWindow *createStatusWindow(Window parent) {
     StatusWindow *statusWindow;
     XSetWindowAttributes attrib;
     unsigned long attribmask;
     Window containerWindow;
     Window status;

@@ -598,14 +505,22 @@
     int screen = 0;
     int i;
     AwtGraphicsConfigDataPtr adata;
     extern int awt_numScreens;
     /*hardcode the size right now, should get the size base on font*/
-    int   width=80, height=22;
+    int width=80, height=22;
     Window rootWindow;
     Window *ignoreWindowPtr;
     unsigned int ignoreUnit;
+    Window grandParent;
+    Window target;
+    XFontSet fontset;
+
+    fontset = create_fontset();
+    if (NULL == fontset) {
+        return NULL;
+    }
 
     XGetGeometry(dpy, parent, &rootWindow, &x, &y, &w, &h, &bw, &depth);
 
     attrib.override_redirect = True;
     attribmask = CWOverrideRedirect;

@@ -619,48 +534,77 @@
     bg    = adata->AwtColorMatch(255, 255, 255, adata);
     fg    = adata->AwtColorMatch(0, 0, 0, adata);
     light = adata->AwtColorMatch(195, 195, 195, adata);
     dim   = adata->AwtColorMatch(128, 128, 128, adata);
 
-    XGetWindowAttributes(dpy, parent, &xwa);
+    grandParent = getGrandParent(parent);
+    target = (grandParent == 0) ? parent : grandParent;
+    XGetWindowAttributes(dpy, target, &xwa);
     bw = 2; /*xwa.border_width does not have the correct value*/
 
     /*compare the size difference between parent container
       and shell widget, the diff should be the border frame
       and title bar height (?)*/
 
     XQueryTree( dpy,
-                parent,
+                target,
                 &rootWindow,
                 &containerWindow,
                 &ignoreWindowPtr,
                 &ignoreUnit);
     XGetWindowAttributes(dpy, containerWindow, &xxwa);
 
-    off_x = (xxwa.width - xwa.width) / 2;
-    off_y = xxwa.height - xwa.height - off_x; /*it's magic:-) */
+    XTranslateCoordinates(dpy,
+                          target, xwa.root,
+                          0, 0,
+                          &x, &y, &child);
+
+    if (containerWindow == rootWindow) {
+        off_x = 0; off_y = STATUS_MARGIN;
+    } else {
+        XGetWindowAttributes(dpy, containerWindow, &xxwa);
+        off_x = (xxwa.width - xwa.width) / 2;
+        /* off_y = xxwa.height - xwa.height - off_x;*/ /*it's magic:-) */
+        {
+            int cx, cy;
+            XTranslateCoordinates(dpy,
+                                  containerWindow, xxwa.root,
+                                  0, 0,
+                                  &cx, &cy,
+                                  &child);
+            off_y = (xxwa.height + cy) - (xwa.height + y);
+        }
+    }
 
     /*get the size of root window*/
     XGetWindowAttributes(dpy, rootWindow, &xxwa);
 
     XTranslateCoordinates(dpy,
-                          parent, xwa.root,
+                          target, xwa.root,
                           xwa.x, xwa.y,
                           &x, &y,
                           &child);
     xx = x - off_x;
     yy = y + xwa.height - off_y;
     if (xx < 0 ){
         xx = 0;
     }
-    if (xx + width > xxwa.width){
+    if (xx + width > xxwa.width) {
         xx = xxwa.width - width;
     }
-    if (yy + height > xxwa.height){
+    if (yy + height > xxwa.height) {
         yy = xxwa.height - height;
     }
 
+    if ((DefaultVisual(dpy,screen))->class != adata->awt_visInfo.visual->class &&
+        adata->awt_visInfo.visual->class == TrueColor) {
+        attrib.colormap = XCreateColormap(dpy, xwa.root,
+            adata->awt_visInfo.visual, AllocNone );
+        attrib.border_pixel = BlackPixel(dpy, screen) ;
+        attribmask |= CWColormap | CWBorderPixel;
+    }
+
     status =  XCreateWindow(dpy,
                             xwa.root,
                             xx, yy,
                             width, height,
                             0,

@@ -669,45 +613,50 @@
                             adata->awt_visInfo.visual,
                             attribmask, &attrib);
     XSelectInput(dpy, status,
                  ExposureMask | StructureNotifyMask | EnterWindowMask |
                  LeaveWindowMask | VisibilityChangeMask);
+    if (grandParent != 0){
+        long mask;
+        XGetWindowAttributes(dpy, grandParent, &xwa);
+        mask = xwa.your_event_mask | StructureNotifyMask |
+               VisibilityChangeMask | PropertyChangeMask;
+        XSelectInput(dpy, grandParent,mask);
+    }
+
     statusWindow = (StatusWindow*) calloc(1, sizeof(StatusWindow));
     if (statusWindow == NULL){
         THROW_OUT_OF_MEMORY_ERROR();
         return NULL;
     }
     statusWindow->w = status;
-    //12-point font
-    statusWindow->fontset = XCreateFontSet(dpy,
-                                           "-*-*-medium-r-normal-*-*-120-*-*-*-*",
-                                           &mclr, &mccr, &dsr);
-    /* In case we didn't find the font set, release the list of missing characters */
-    if (mccr > 0) {
-        XFreeStringList(mclr);
-    }
+    statusWindow->fontset = fontset;
     statusWindow->parent = parent;
+    statusWindow->grandParent = grandParent;
     statusWindow->on  = False;
     statusWindow->x = x;
     statusWindow->y = y;
     statusWindow->width = xwa.width;
     statusWindow->height = xwa.height;
     statusWindow->off_x = off_x;
     statusWindow->off_y = off_y;
     statusWindow->bWidth  = bw;
     statusWindow->statusH = height;
     statusWindow->statusW = width;
+    statusWindow->peTextW = 0;
     statusWindow->rootH = xxwa.height;
     statusWindow->rootW = xxwa.width;
     statusWindow->lightGC = XCreateGC(dpy, status, valuemask, &values);
     XSetForeground(dpy, statusWindow->lightGC, light);
     statusWindow->dimGC = XCreateGC(dpy, status, valuemask, &values);
     XSetForeground(dpy, statusWindow->dimGC, dim);
-    statusWindow->fgGC = XCreateGC(dpy, status, valuemask, &values);
+    statusWindow->fgGC = create_gc(status, FALSE);
     XSetForeground(dpy, statusWindow->fgGC, fg);
-    statusWindow->bgGC = XCreateGC(dpy, status, valuemask, &values);
+    statusWindow->bgGC = create_gc(status, TRUE);
     XSetForeground(dpy, statusWindow->bgGC, bg);
+    statusWindow->status_ready = False;
+    wcscpy(statusWindow->status, L"");
     return statusWindow;
 }
 
 /* This method is to turn off or turn on the status window. */
 static void onoffStatusWindow(X11InputMethodData* pX11IMData,

@@ -716,54 +665,40 @@
     XWindowAttributes xwa;
     Window child;
     int x, y;
     StatusWindow *statusWindow = NULL;
 
-    if (NULL == currentX11InputMethodInstance ||
-        NULL == pX11IMData ||
+    if (NULL == pX11IMData ||
         NULL == (statusWindow =  pX11IMData->statusWindow)){
         return;
     }
 
-    if (ON == False){
+    if (ON == False) {
         XUnmapWindow(dpy, statusWindow->w);
-        statusWindow->on = False;
         return;
     }
-    parent = JNU_CallMethodByName(GetJNIEnv(), NULL, pX11IMData->x11inputmethod,
-                                  "getCurrentParentWindow",
-                                  "()J").j;
-    if (statusWindow->parent != parent){
-        statusWindow->parent = parent;
+    if (NULL == currentX11InputMethodInstance){
+        return;
     }
-    XGetWindowAttributes(dpy, parent, &xwa);
-    XTranslateCoordinates(dpy,
-                          parent, xwa.root,
-                          xwa.x, xwa.y,
-                          &x, &y,
-                          &child);
-    if (statusWindow->x != x
-        || statusWindow->y != y
-        || statusWindow->height != xwa.height){
-        statusWindow->x = x;
-        statusWindow->y = y;
-        statusWindow->height = xwa.height;
-        x = statusWindow->x - statusWindow->off_x;
-        y = statusWindow->y + statusWindow->height - statusWindow->off_y;
-        if (x < 0 ){
-            x = 0;
-        }
-        if (x + statusWindow->statusW > statusWindow->rootW){
-            x = statusWindow->rootW - statusWindow->statusW;
-        }
-        if (y + statusWindow->statusH > statusWindow->rootH){
-            y = statusWindow->rootH - statusWindow->statusH;
+    {
+        JNIEnv *env = GetJNIEnv();
+        parent = JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
+                                      "getCurrentParentWindow",
+                                      "()J").j;
+        if ((*env)->ExceptionOccurred(env)) {
+            (*env)->ExceptionDescribe(env);
+            (*env)->ExceptionClear(env);
         }
-        XMoveWindow(dpy, statusWindow->w, x, y);
     }
-    statusWindow->on = True;
-    XMapWindow(dpy, statusWindow->w);
+    if (statusWindow->parent != parent) {
+        statusWindow->parent = parent;
+    }
+    if (st_wcslen(statusWindow->status) > 0 ||
+        (statusWindow->peText != NULL && st_wcslen(statusWindow->peText) > 0 )) {
+        moveStatusWindow(statusWindow);
+        XMapRaised(dpy, statusWindow->w);
+    }
 }
 
 void paintStatusWindow(StatusWindow *statusWindow){
     Window  win  = statusWindow->w;
     GC  lightgc = statusWindow->lightGC;

@@ -772,125 +707,122 @@
     GC  fggc = statusWindow->fgGC;
 
     int width = statusWindow->statusW;
     int height = statusWindow->statusH;
     int bwidth = statusWindow->bWidth;
-    XFillRectangle(dpy, win, bggc, 0, 0, width, height);
-    /* draw border */
-    XDrawLine(dpy, win, fggc, 0, 0, width, 0);
-    XDrawLine(dpy, win, fggc, 0, height-1, width-1, height-1);
-    XDrawLine(dpy, win, fggc, 0, 0, 0, height-1);
-    XDrawLine(dpy, win, fggc, width-1, 0, width-1, height-1);
-
-    XDrawLine(dpy, win, lightgc, 1, 1, width-bwidth, 1);
-    XDrawLine(dpy, win, lightgc, 1, 1, 1, height-2);
-    XDrawLine(dpy, win, lightgc, 1, height-2, width-bwidth, height-2);
-    XDrawLine(dpy, win, lightgc, width-bwidth-1, 1, width-bwidth-1, height-2);
-
-    XDrawLine(dpy, win, dimgc, 2, 2, 2, height-3);
-    XDrawLine(dpy, win, dimgc, 2, height-3, width-bwidth-1, height-3);
-    XDrawLine(dpy, win, dimgc, 2, 2, width-bwidth-2, 2);
-    XDrawLine(dpy, win, dimgc, width-bwidth, 2, width-bwidth, height-3);
-    if (statusWindow->fontset){
-        XmbDrawString(dpy, win, statusWindow->fontset, fggc,
-                      bwidth + 2, height - bwidth - 4,
-                      statusWindow->status,
-                      strlen(statusWindow->status));
+    int len;
+    XRectangle logical, ink;
+
+    if (NULL == statusWindow) return;
+    if ((len = st_wcslen(statusWindow->status)) == 0) {
+        return;
     }
-    else{
+    XwcTextExtents(statusWindow->fontset, statusWindow->status,
+                   len, &ink, &logical);
+    width = logical.width;
+    height = logical.height;
+
+    XFillRectangle(dpy, win, bggc, 0, 0, width+2, height+2);
+
+    XDrawLine(dpy, win, fggc, 0, 0, width+2, 0);
+    XDrawLine(dpy, win, fggc, 0, height+2, width+2, height+2);
+    XDrawLine(dpy, win, fggc, 0, 0, 0, height+2);
+    XDrawLine(dpy, win, fggc, width+2, 0, width+2, height+2);
+
+    if (statusWindow->fontset) {
+        XwcDrawString(dpy, win, statusWindow->fontset, fggc,
+                      -logical.x + 1, -logical.y + 1,
+                      statusWindow->status,
+                      st_wcslen(statusWindow->status));
+    } else {
         /*too bad we failed to create a fontset for this locale*/
         XDrawString(dpy, win, fggc, bwidth + 2, height - bwidth - 4,
                     "[InputMethod ON]", strlen("[InputMethod ON]"));
     }
 }
 
-void statusWindowEventHandler(XEvent event){
+Bool statusWindowEventHandler(XEvent event) {
     JNIEnv *env = GetJNIEnv();
     X11InputMethodData *pX11IMData = NULL;
     StatusWindow *statusWindow;
 
-    if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) {
-        currentX11InputMethodInstance = NULL;
-        return;
-    }
-
-    if (NULL == currentX11InputMethodInstance
-        || NULL == (pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance))
-        || NULL == (statusWindow = pX11IMData->statusWindow)
-        || statusWindow->w != event.xany.window){
-        return;
+    if (NULL == currentX11InputMethodInstance ||
+        NULL == (pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance)) ||
+        NULL == (statusWindow = pX11IMData->statusWindow))
+    {
+        return False;
     }
 
-    switch (event.type){
-    case Expose:
-        paintStatusWindow(statusWindow);
-        break;
-    case MapNotify:
-    case ConfigureNotify:
-        {
-          /*need to reset the stackMode...*/
-            XWindowChanges xwc;
-            int value_make = CWStackMode;
-            xwc.stack_mode = TopIf;
-            XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
-        }
-        break;
+    if (statusWindow->w == event.xany.window) {
+        switch (event.type) {
+        case Expose:
+            paintStatusWindow(statusWindow);
+            if (statusWindow->peText)
+                draw_preedit(statusWindow);
+            arrange_window_stack(statusWindow);
+            break;
+        case ConfigureNotify:
+        case VisibilityNotify:
+            arrange_window_stack(statusWindow);
+            break;
         /*
-    case UnmapNotify:
-    case VisibilityNotify:
-        break;
+        case UnmapNotify:
+        case VisibilityNotify:
+            break;
         */
-    default:
-        break;
-  }
+        default:
+            break;
+        }
+        return True;
+    } else if ((statusWindow->parent == event.xany.window) ||
+               (statusWindow->grandParent && statusWindow->grandParent == event.xany.window)) {
+        switch (event.type) {
+        case MapNotify:
+            if (statusWindow->on) {
+                onoffStatusWindow(pX11IMData, statusWindow->parent, True);
+            }
+            break;
+        case UnmapNotify:
+            onoffStatusWindow(pX11IMData, 0, False);
+            break;
+        case VisibilityNotify:
+            if (statusWindow->on) {
+                arrange_window_stack(statusWindow);
+            }
+            break;
+        case ConfigureNotify:
+            if (statusWindow->grandParent && statusWindow->on) {
+                moveStatusWindow(statusWindow);
+            }
+        case PropertyNotify:
+            if (statusWindow->on) {
+                arrange_window_stack(statusWindow);
+            }
+            break;
+        default:
+            break;
+        }
+    }
+    return False;
 }
 
-static void adjustStatusWindow(Window shell){
+static void adjustStatusWindow(Window shell) {
     JNIEnv *env = GetJNIEnv();
     X11InputMethodData *pX11IMData = NULL;
     StatusWindow *statusWindow;
 
     if (NULL == currentX11InputMethodInstance
-        || !isX11InputMethodGRefInList(currentX11InputMethodInstance)
         || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))
         || NULL == (statusWindow = pX11IMData->statusWindow)
-        || !statusWindow->on) {
-        return;
-    }
+        || !statusWindow->on)
     {
-        XWindowAttributes xwa;
-        int x, y;
-        Window child;
-        XGetWindowAttributes(dpy, shell, &xwa);
-        XTranslateCoordinates(dpy,
-                              shell, xwa.root,
-                              xwa.x, xwa.y,
-                              &x, &y,
-                              &child);
-        if (statusWindow->x != x
-            || statusWindow->y != y
-            || statusWindow->height != xwa.height){
-          statusWindow->x = x;
-          statusWindow->y = y;
-          statusWindow->height = xwa.height;
-
-          x = statusWindow->x - statusWindow->off_x;
-          y = statusWindow->y + statusWindow->height - statusWindow->off_y;
-          if (x < 0 ){
-              x = 0;
-          }
-          if (x + statusWindow->statusW > statusWindow->rootW){
-              x = statusWindow->rootW - statusWindow->statusW;
-          }
-          if (y + statusWindow->statusH > statusWindow->rootH){
-              y = statusWindow->rootH - statusWindow->statusH;
-          }
-          XMoveWindow(dpy, statusWindow->w, x, y);
-        }
+        return;
     }
+
+    moveStatusWindow(statusWindow);
 }
-#endif  /* __linux__ || MACOSX */
+
 /*
  * Creates two XICs, one for active clients and the other for passive
  * clients. All information on those XICs are stored in the
  * X11InputMethodData given by the pX11IMData parameter.
  *

@@ -907,33 +839,43 @@
 createXIC(JNIEnv * env, X11InputMethodData *pX11IMData, Window w)
 {
     XVaNestedList preedit = NULL;
     XVaNestedList status = NULL;
     XIMStyle on_the_spot_styles = XIMPreeditCallbacks,
+             in_place_styles = 0,
              active_styles = 0,
              passive_styles = 0,
              no_styles = 0;
     XIMCallback *callbacks;
     unsigned short i;
     XIMStyles *im_styles;
     char *ret = NULL;
+    Bool passiveStatusWindow = False;
+    pX11IMData->statusWindow = NULL;
 
     if (X11im == NULL) {
         return False;
     }
     if (!w) {
         return False;
     }
 
+    if (getenv("IBMJAVA_PASSIVE") == NULL) {
+        passiveStatusWindow = False;
+    } else {
+        passiveStatusWindow = True;
+    }
+
+    if (isNativeIm()) { passiveStatusWindow = True; }
+
     ret = XGetIMValues(X11im, XNQueryInputStyle, &im_styles, NULL);
 
     if (ret != NULL) {
         jio_fprintf(stderr,"XGetIMValues: %s\n",ret);
         return FALSE ;
     }
 
-#if defined(__linux__) || defined(MACOSX)
     on_the_spot_styles |= XIMStatusNothing;
 
     /*kinput does not support XIMPreeditCallbacks and XIMStatusArea
       at the same time, so use StatusCallback to draw the status
       ourself

@@ -942,47 +884,52 @@
         if (im_styles->supported_styles[i] == (XIMPreeditCallbacks | XIMStatusCallbacks)) {
             on_the_spot_styles = (XIMPreeditCallbacks | XIMStatusCallbacks);
             break;
         }
     }
-#else /*! __linux__ && !MACOSX */
-    on_the_spot_styles |= XIMStatusNothing;
-#endif /* __linux__ || MACOSX */
 
     for (i = 0; i < im_styles->count_styles; i++) {
-        active_styles |= im_styles->supported_styles[i] & on_the_spot_styles;
-        passive_styles |= im_styles->supported_styles[i] & ROOT_WINDOW_STYLES;
-        no_styles |= im_styles->supported_styles[i] & NO_STYLES;
+        if (im_styles->supported_styles[i] == on_the_spot_styles)
+            active_styles = im_styles->supported_styles[i];
+        if (im_styles->supported_styles[i] == ROOT_WINDOW_STYLES)
+            passive_styles = im_styles->supported_styles[i];
+        if (im_styles->supported_styles[i] == IN_PLACE_STYLES) {
+            in_place_styles = im_styles->supported_styles[i];
+        }
+        if (im_styles->supported_styles[i] == NO_STYLES) {
+            no_styles = im_styles->supported_styles[i];
+        }
     }
 
     XFree(im_styles);
 
     if (active_styles != on_the_spot_styles) {
         if (passive_styles == ROOT_WINDOW_STYLES)
             active_styles = passive_styles;
         else {
+          if (in_place_styles == IN_PLACE_STYLES){
+              active_styles = passive_styles = IN_PLACE_STYLES;
+          } else {
             if (no_styles == NO_STYLES)
                 active_styles = passive_styles = NO_STYLES;
             else
                 active_styles = passive_styles = 0;
+          }
         }
     } else {
+      if (!passiveStatusWindow) {
         if (passive_styles != ROOT_WINDOW_STYLES) {
             if (no_styles == NO_STYLES)
                 active_styles = passive_styles = NO_STYLES;
             else
                 active_styles = passive_styles = 0;
         }
+      } else
+          passive_styles = active_styles;
     }
 
     if (active_styles == on_the_spot_styles) {
-        pX11IMData->ic_passive = XCreateIC(X11im,
-                                   XNClientWindow, w,
-                                   XNFocusWindow, w,
-                                   XNInputStyle, passive_styles,
-                                   NULL);
-
         callbacks = (XIMCallback *)malloc(sizeof(XIMCallback) * NCALLBACKS);
         if (callbacks == (XIMCallback *)NULL)
             return False;
         pX11IMData->callbacks = callbacks;
 

@@ -998,93 +945,127 @@
                         XNPreeditDrawCallback,  &callbacks[PreeditDrawIndex],
                         XNPreeditCaretCallback, &callbacks[PreeditCaretIndex],
                         NULL);
         if (preedit == (XVaNestedList)NULL)
             goto err;
-#if defined(__linux__) || defined(MACOSX)
         /*always try XIMStatusCallbacks for active client...*/
         {
+        if (on_the_spot_styles & XIMStatusCallbacks) {
             status = (XVaNestedList)XVaCreateNestedList(0,
                         XNStatusStartCallback, &callbacks[StatusStartIndex],
                         XNStatusDoneCallback,  &callbacks[StatusDoneIndex],
                         XNStatusDrawCallback, &callbacks[StatusDrawIndex],
                         NULL);
 
             if (status == NULL)
                 goto err;
+          }
             pX11IMData->statusWindow = createStatusWindow(w);
             pX11IMData->ic_active = XCreateIC(X11im,
                                               XNClientWindow, w,
                                               XNFocusWindow, w,
                                               XNInputStyle, active_styles,
                                               XNPreeditAttributes, preedit,
                                               XNStatusAttributes, status,
                                               NULL);
+            if (NULL != pX11IMData->statusWindow) {
+                pX11IMData->statusWindow->status_ready = True;
+            }
             XFree((void *)status);
             XFree((void *)preedit);
         }
-#else /* !__linux__ && !MACOSX */
-            pX11IMData->ic_active = XCreateIC(X11im,
-                                              XNClientWindow, w,
-                                              XNFocusWindow, w,
-                                              XNInputStyle, active_styles,
-                                              XNPreeditAttributes, preedit,
-                                              NULL);
-        XFree((void *)preedit);
-#endif /* __linux__ || MACOSX */
+        if (passiveStatusWindow) {
+            pX11IMData->ic_passive = pX11IMData->ic_active;
+        } else {
+            pX11IMData->ic_passive = XCreateIC(X11im,
+                                               XNClientWindow, w,
+                                               XNFocusWindow, w,
+                                               XNInputStyle, passive_styles,
+                                               NULL);
+        }
     } else {
         pX11IMData->ic_active = XCreateIC(X11im,
                                           XNClientWindow, w,
                                           XNFocusWindow, w,
                                           XNInputStyle, active_styles,
                                           NULL);
         pX11IMData->ic_passive = pX11IMData->ic_active;
     }
 
+    // The code set the IC mode that the preedit state is not initialied
+    // at XmbResetIC.  This attribute can be set at XCreateIC.  I separately
+    // set the attribute to avoid the failure of XCreateIC at some platform
+    // which does not support the attribute.
+    if (pX11IMData->ic_active != 0)
+        XSetICValues(pX11IMData->ic_active,
+                        XNResetState, XIMPreserveState, NULL);
+    if (pX11IMData->ic_passive != 0 &&
+        pX11IMData->ic_active != pX11IMData->ic_passive)
+            XSetICValues(pX11IMData->ic_passive,
+             XNResetState, XIMInitialState, NULL);
+
+    pX11IMData->passiveStatusWindow = passiveStatusWindow;
+
     if (pX11IMData->ic_active == (XIC)0
         || pX11IMData->ic_passive == (XIC)0) {
         return False;
     }
 
-    /*
-     * Use commit string call back if possible.
-     * This will ensure the correct order of preedit text and commit text
-     */
-    {
-        XIMCallback cb;
-        cb.client_data = (XPointer) pX11IMData->x11inputmethod;
-        cb.callback = (XIMProc) CommitStringCallback;
-        XSetICValues (pX11IMData->ic_active, XNCommitStringCallback, &cb, NULL);
-        if (pX11IMData->ic_active != pX11IMData->ic_passive) {
-            XSetICValues (pX11IMData->ic_passive, XNCommitStringCallback, &cb, NULL);
-        }
-    }
-
-    /* Add the global reference object to X11InputMethod to the list. */
-    addToX11InputMethodGRefList(pX11IMData->x11inputmethod);
+    /* Unset focus to avoid unexpected IM on */
+    setXICFocus(pX11IMData->ic_active, False);
+    if (pX11IMData->ic_active != pX11IMData->ic_passive)
+        setXICFocus(pX11IMData->ic_passive, False);
 
     return True;
 
  err:
     if (preedit)
         XFree((void *)preedit);
     THROW_OUT_OF_MEMORY_ERROR();
     return False;
 }
 
-static void
+static int
 PreeditStartCallback(XIC ic, XPointer client_data, XPointer call_data)
 {
-    /*ARGSUSED*/
-    /* printf("Native: PreeditCaretCallback\n"); */
+    JNIEnv *env = GetJNIEnv();
+    X11InputMethodData *pX11IMData;
+
+    pX11IMData = getX11InputMethodData(env, (jobject)client_data);
+    if (pX11IMData == NULL || pX11IMData->statusWindow == NULL) {
+        return 0;
+    }
+    resetPassivePreeditText(pX11IMData->statusWindow);
+
+    return -1;  /* unlimited length for preedit text  */
 }
 
 static void
 PreeditDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
 {
-    /*ARGSUSED*/
-    /* printf("Native: StatusStartCallback\n"); */
+    JNIEnv *env = GetJNIEnv();
+    X11InputMethodData *pX11IMData;
+
+    pX11IMData = getX11InputMethodData(env, (jobject)client_data);
+    if (pX11IMData == NULL) {
+        return;
+    }
+
+    if (!pX11IMData->isActiveClient) {
+        resetPassivePreeditText(pX11IMData->statusWindow);
+        shrink_status(pX11IMData->statusWindow);
+    }
+    else{
+            JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
+                                 "clearComposedText",
+                                 "(J)V",
+                                 awt_util_nowMillisUTC());
+            if ((*env)->ExceptionOccurred(env)) {
+                (*env)->ExceptionDescribe(env);
+                (*env)->ExceptionClear(env);
+            }
+    }
 }
 
 /*
  * Translate the preedit draw callback items to Java values and invoke
  * X11InputMethod.dispatchComposedText().

@@ -1106,36 +1087,39 @@
     /* printf("Native: PreeditDrawCallback() \n"); */
     if (pre_draw == NULL) {
         return;
     }
     AWT_LOCK();
-    if (!isX11InputMethodGRefInList((jobject)client_data)) {
-        if ((jobject)client_data == currentX11InputMethodInstance) {
-            currentX11InputMethodInstance = NULL;
-        }
+    if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {
         goto finally;
     }
-    if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {
+
+    if (!pX11IMData->isActiveClient){
+        if (ic == pX11IMData->ic_passive) {
+            preedit_draw_passive(pX11IMData, pre_draw);
+        }
         goto finally;
     }
 
     if ((text = pre_draw->text) != NULL) {
-        if (text->string.multi_byte != NULL) {
-            if (pre_draw->text->encoding_is_wchar == False) {
-                javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte);
-                if (javastr == NULL) {
-                    goto finally;
-                }
-            } else {
-                char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
-                if (mbstr == NULL) {
-                    goto finally;
-                }
-                javastr = JNU_NewStringPlatform(env, (const char *)mbstr);
-                free(mbstr);
-                if (javastr == NULL) {
-                    goto finally;
+        if (is_text_available(text)) {
+            if (text->string.multi_byte != NULL) {
+                if (pre_draw->text->encoding_is_wchar == False) {
+                    javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte);
+                    if (javastr == NULL) {
+                        goto finally;
+                    }
+                } else {
+                    char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
+                    if (mbstr == NULL) {
+                        goto finally;
+                    }
+                    javastr = JNU_NewStringPlatform(env, (const char *)mbstr);
+                    free(mbstr);
+                    if (javastr == NULL) {
+                        goto finally;
+                    }
                 }
             }
         }
         if (text->feedback != NULL) {
             int cnt;

@@ -1174,211 +1158,765 @@
                          style,
                          (jint)pre_draw->chg_first,
                          (jint)pre_draw->chg_length,
                          (jint)pre_draw->caret,
                          awt_util_nowMillisUTC());
+
+    if ((*env)->ExceptionOccurred(env)) {
+        (*env)->ExceptionDescribe(env);
+        (*env)->ExceptionClear(env);
+    }
+
 finally:
     AWT_UNLOCK();
     return;
 }
 
 static void
 PreeditCaretCallback(XIC ic, XPointer client_data,
                      XIMPreeditCaretCallbackStruct *pre_caret)
 {
-    /*ARGSUSED*/
-    /* printf("Native: PreeditCaretCallback\n"); */
+    XIMPreeditDrawCallbackStruct pre_draw;
 
+    if (pre_caret != NULL && pre_caret->direction == XIMAbsolutePosition) {
+        pre_draw.caret = pre_caret->position;
+        pre_draw.chg_first = 0;
+        pre_draw.chg_length = 0;
+        pre_draw.text = NULL;
+        PreeditDrawCallback(ic, client_data, &pre_draw);
+    }
 }
 
-#if defined(__linux__) || defined(MACOSX)
 static void
 StatusStartCallback(XIC ic, XPointer client_data, XPointer call_data)
 {
     /*ARGSUSED*/
     /*printf("StatusStartCallback:\n");  */
-
 }
 
 static void
 StatusDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
 {
     /*ARGSUSED*/
     /*printf("StatusDoneCallback:\n"); */
-
 }
 
-static void
-StatusDrawCallback(XIC ic, XPointer client_data,
-                     XIMStatusDrawCallbackStruct *status_draw)
+static void StatusDrawCallback
+  (XIC ic, XPointer client_data, XIMStatusDrawCallbackStruct *status_draw)
 {
     /*ARGSUSED*/
     /*printf("StatusDrawCallback:\n"); */
     JNIEnv *env = GetJNIEnv();
     X11InputMethodData *pX11IMData = NULL;
     StatusWindow *statusWindow;
+    int value_make = CWX|CWWidth|CWHeight;
+    XRectangle logical, ink;
+    XWindowChanges xwc;
+    int len;
 
     AWT_LOCK();
 
-    if (!isX11InputMethodGRefInList((jobject)client_data)) {
-        if ((jobject)client_data == currentX11InputMethodInstance) {
-            currentX11InputMethodInstance = NULL;
-        }
-        goto finally;
-    }
-
     if (NULL == (pX11IMData = getX11InputMethodData(env, (jobject)client_data))
         || NULL == (statusWindow = pX11IMData->statusWindow)){
         goto finally;
     }
-   currentX11InputMethodInstance = (jobject)client_data;
 
-    if (status_draw->type == XIMTextType){
+    if (status_draw->type == XIMTextType) {
         XIMText *text = (status_draw->data).text;
-        if (text != NULL){
-          if (text->string.multi_byte != NULL) {
-              strncpy(statusWindow->status, text->string.multi_byte, MAX_STATUS_LEN);
-              statusWindow->status[MAX_STATUS_LEN - 1] = '\0';
-          }
-          else {
-              char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
-              strncpy(statusWindow->status, mbstr, MAX_STATUS_LEN);
-              statusWindow->status[MAX_STATUS_LEN - 1] = '\0';
+        if (text != NULL) {
+            if (text->string.multi_byte != NULL) {
+                if(!strcmp(text->string.multi_byte," ")){
+                    wcscpy(statusWindow->status, L"");
+                    onoffStatusWindow(pX11IMData, 0, False);
+                    goto finally;
+                }
+                mbstowcs(statusWindow->status,
+                         (const char *)text->string.multi_byte,
+                         (size_t)MAX_STATUS_LEN);
+            } else {
+                if (0 == st_wcslen(text->string.wide_char)){
+                    wcscpy(statusWindow->status, L"");
+                    onoffStatusWindow(pX11IMData, 0, False);
+                    goto finally;
+                }
+                wcsncpy(statusWindow->status,
+                        text->string.wide_char,
+                        MAX_STATUS_LEN);
+            }
+            XwcTextExtents(statusWindow->fontset, statusWindow->status,
+                           st_wcslen(statusWindow->status), &ink, &logical);
+            statusWindow->statusW = logical.width + BORDER_MARGIN;
+            statusWindow->statusH = logical.height + BORDER_MARGIN;
+            xwc.x = statusWindow->x - statusWindow->off_x;
+            if (xwc.x < 0 ) xwc.x = 0;
+            xwc.width = statusWindow->statusW;
+            xwc.height = statusWindow->statusH;
+            if (xwc.x + xwc.width > statusWindow->rootW){
+                xwc.x = statusWindow->rootW - xwc.width;
+            }
+            XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
+          if (statusWindow->status_ready && statusWindow->on == True){
+            onoffStatusWindow(pX11IMData, statusWindow->parent, True);
           }
-          statusWindow->on = True;
-          onoffStatusWindow(pX11IMData, statusWindow->parent, True);
-          paintStatusWindow(statusWindow);
+            paintStatusWindow(statusWindow);
+            if (statusWindow->peText)
+                draw_preedit(statusWindow);
         }
         else {
-            statusWindow->on = False;
+            wcscpy(statusWindow->status, L"");
             /*just turnoff the status window
             paintStatusWindow(statusWindow);
             */
             onoffStatusWindow(pX11IMData, 0, False);
         }
     }
 
  finally:
     AWT_UNLOCK();
 }
-#endif /* __linux__ || MACOSX */
 
-static void CommitStringCallback(XIC ic, XPointer client_data, XPointer call_data) {
-    JNIEnv *env = GetJNIEnv();
-    XIMText * text = (XIMText *)call_data;
-    X11InputMethodData *pX11IMData = NULL;
-    jstring javastr;
+/* return the string length without trailing spaces    */
+/* work around code for Japanese AIXIM is implemented. */
+static int st_wcslen(wchar_t *string)
+{
+    int len = (int32_t)wcslen(string);
+    if (len == 0)
+        return 0;
+   for (len--;len >= 0; len--) {
+        if (!iswspace((wint_t) string[len])) break;
+    }
+    return len+1;
+}
 
-    AWT_LOCK();
+/*
+ * Checks whether given XIMText contains a string data.
+ */
+static Bool is_text_available(XIMText * text)
+{
+    if (text == NULL || text->length==0)
+        return False;
+    if (text->encoding_is_wchar) {
+        if(text->string.wide_char[0] == L'\0')
+            return False;
+    } else {
+        if (text->string.multi_byte[0] == '\0')
+            return False;
+    }
+    return True;
+}
 
-    if (!isX11InputMethodGRefInList((jobject)client_data)) {
-        if ((jobject)client_data == currentX11InputMethodInstance) {
-            currentX11InputMethodInstance = NULL;
-        }
-        goto finally;
+/*
+ * check if preedit status is active
+*/
+static Bool isPreeditStateActive(XIC ic)
+{
+    XIMPreeditState state = XIMPreeditUnKnown;
+    XVaNestedList pr_atrb;
+    char* nosupportAttr;
+
+    if (ic == NULL) return False;
+
+    pr_atrb = XVaCreateNestedList(0,XNPreeditState,&state,NULL);
+    nosupportAttr=XGetICValues(ic,XNPreeditAttributes,pr_atrb,NULL);
+    XFree(pr_atrb);
+    if (nosupportAttr==NULL && state & XIMPreeditDisable)
+        return False;
+    else
+        return True;
+}
+
+static void * buf_insert(void * src, void * insert, int size,
+                         int src_len, int ins_len, int offset)
+{
+    char *temp;
+
+    temp = realloc(src, size*(src_len+ins_len+1));
+    if (temp == NULL) {
+        THROW_OUT_OF_MEMORY_ERROR();
+        return src;
+    }
+    if (offset != src_len) {
+        memmove(&temp[size*(offset+ins_len)],
+                &((char *)temp)[size*offset],
+                size*(src_len-offset));
     }
+    memcpy(&temp[size*offset], insert, size*ins_len);
 
-    if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {
-        goto finally;
+    return (void *)temp;
+}
+
+static void * handle_buffer(void * source, void * insert,
+                            int size,int src_len, int ins_len,
+                            int del_len, int offset)
+{
+    void * temp = source;
+
+    if (del_len > 0) {
+        if (del_len == ins_len) {
+            memcpy(&((char *)source)[size*offset], insert, size*ins_len);
+            return source;
+        }
+        else if (src_len > offset+del_len) {
+            memmove(&((char *)source)[size*offset],
+                    &((char *)source)[size*(offset+del_len)],
+                    size*(src_len-offset-del_len));
+        }
     }
-    currentX11InputMethodInstance = (jobject)client_data;
+    if (ins_len > 0) {
+        temp = buf_insert(source, insert, size, src_len,
+                          ins_len, offset);
+    }
+    return temp;
+}
+/*
+ * Display the given preedit text to the root window which is ownd by
+ * myself. All of the character is converted to wide char.
+ * this function is used for the passive client.
+ */
+static void preedit_draw_passive(X11InputMethodData *pX11IMData,
+                    XIMPreeditDrawCallbackStruct *pre_draw)
+{
+    XIMText *text;
+    wchar_t *tempbuf = NULL;
+    StatusWindow *statusWindow;
+    wchar_t *cur_text;
+    unsigned long *cur_attr;
+    int     cur_len = 0;
+    int     chg_len = pre_draw->chg_length;
+    int     chg_1st = pre_draw->chg_first;
+
+    if (NULL == (statusWindow = pX11IMData->statusWindow))
+        return;
+    cur_text = statusWindow->peText;
+    cur_attr = statusWindow->peAttr;
+    if (cur_text == NULL && pre_draw->text == NULL)
+        return;
 
-    if (text->encoding_is_wchar == False) {
-        javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte);
+    if (cur_text != NULL)
+        cur_len = (int32_t)wcslen(cur_text);
+    text = pre_draw->text;
+    if (text == NULL) {
+        /* delete only */
+        if (cur_len >  chg_1st+chg_len) {
+            memmove(&cur_text[chg_1st],
+                    &cur_text[chg_1st+chg_len],
+                    sizeof(wchar_t)*(cur_len-chg_1st-chg_len));
+            memmove(&cur_attr[chg_1st],
+                    &cur_attr[chg_1st+chg_len],
+                    sizeof(long)*(cur_len-chg_1st-chg_len));
+        }
+        if ((pre_draw->chg_length <= cur_len ) && (pre_draw->chg_length >0))
+            cur_text[cur_len-pre_draw->chg_length] =L'\0';
     } else {
-        char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
-        if (mbstr == NULL) {
-            goto finally;
+        /* insert or replace */
+        int     ins_len = 0;
+        void *  ins_text = NULL;
+
+        /* if invalid offset is specified, do nothing. */
+        /* this fix is for aixim for eucTW             */
+        if (cur_len < chg_1st)
+            return;
+        if(is_text_available(text)) {
+            /* insert or replace the text */
+            if (text->encoding_is_wchar == False) {
+                /* convert the text to wide chars.
+                   allocate enough size buffer
+                */
+                tempbuf = (wchar_t *)malloc(sizeof(wchar_t)*(text->length+1));
+                if (tempbuf == NULL) {
+                    THROW_OUT_OF_MEMORY_ERROR();
+                    return;
+                }
+                ins_len = (int32_t)mbstowcs(tempbuf, text->string.multi_byte,
+                                   text->length);
+                if (ins_len == -1) {
+                        free(tempbuf);
+                        return;
+                }
+                ins_text = (void *)tempbuf;
+            }
+            else {
+                ins_len = text->length;
+                ins_text = text->string.wide_char;
+            }
+            /* finish prepare the data to be inserted */
+
+            statusWindow->peText =
+                    handle_buffer(cur_text, ins_text, sizeof(wchar_t),
+                                  cur_len, ins_len, chg_len, chg_1st);
+            statusWindow->peAttr =
+                    handle_buffer(cur_attr, text->feedback, sizeof(long),
+                                  cur_len, ins_len, chg_len, chg_1st);
+            statusWindow->peText[cur_len-chg_len+ins_len] =L'\0';
+
+            if (tempbuf != NULL)
+                free(tempbuf);
+        } /* endof insert or replace text */
+        else {
+            /* change attribute only */
+            memcpy(&cur_attr[chg_1st], text->feedback,
+                    sizeof(long)*text->length);
         }
-        javastr = JNU_NewStringPlatform(env, (const char *)mbstr);
-        free(mbstr);
     }
+    statusWindow->peCaret= pre_draw->caret;
+    draw_preedit(statusWindow);
+    if (statusWindow->on && wcslen(statusWindow->peText) > 0)
+        onoffStatusWindow(pX11IMData, statusWindow->parent, True);
+    else if (wcslen(statusWindow->status) == 0)
+        onoffStatusWindow(pX11IMData, 0, False);
+}
 
-    if (javastr != NULL) {
-        JNU_CallMethodByName(env, NULL,
-                                 pX11IMData->x11inputmethod,
-                                 "dispatchCommittedText",
-                                 "(Ljava/lang/String;J)V",
-                                 javastr,
-                                 awt_util_nowMillisUTC());
+/*
+ * reset predit test of passive mode
+ */
+static void
+resetPassivePreeditText(StatusWindow *statusWindow)
+{
+    if (NULL == statusWindow) return;
+    if(statusWindow->peText != NULL) {
+        free(statusWindow->peText);
+        statusWindow->peText = NULL;
     }
- finally:
-    AWT_UNLOCK();
+    if(statusWindow->peAttr != NULL) {
+        free(statusWindow->peAttr);
+        statusWindow->peAttr = NULL;
+    }
+    statusWindow->peCaret= 0;
 }
 
-static void OpenXIMCallback(Display *display, XPointer client_data, XPointer call_data) {
-    XIMCallback ximCallback;
+static void draw_caret(StatusWindow *statusWindow, GC gc, int pos)
+{
+    if (NULL == statusWindow) return;
+    XSetFunction(dpy, gc, GXinvert);
+    XDrawLine(dpy, statusWindow->w,
+              gc, pos, STATUS_BORDER/2,
+              pos, STATUS_BORDER/2+statusWindow->fOff);
+    XSetFunction(dpy, gc, GXcopy);
+}
 
-    X11im = XOpenIM(display, NULL, NULL, NULL);
-    if (X11im == NULL) {
+static int  get_next_attr(int len, unsigned long *attr)
+{
+    int count;
+
+    for (count = 1; count < len; count++)  {
+        if ((attr[count-1] & PREEDIT_ATTR_MASK)
+            != (attr[count] & PREEDIT_ATTR_MASK))
+            break;
+    }
+    return count;
+}
+
+static void draw_preedit(StatusWindow *statusWindow)
+{
+    unsigned long *attr;
+    int x_pos,x_caret;
+    unsigned int  len;
+    int len_disp, pos;
+    wchar_t *str;
+    GC  gc;
+    XRectangle ink, rect, rect_c;
+    Bool caret_done = False;
+
+    if (NULL == statusWindow) return;
+    align_status(statusWindow);
+    XFillRectangle(dpy, statusWindow->w,
+                   statusWindow->bgGC,
+                   statusWindow->statusW,0,
+                   statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN,
+                   statusWindow->fBot+2);
+
+
+    XDrawLine(dpy, statusWindow->w, statusWindow->fgGC,
+              statusWindow->statusW, 0,
+              statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, 0);
+    XDrawLine(dpy, statusWindow->w, statusWindow->fgGC,
+              statusWindow->statusW, statusWindow->fBot+2,
+              statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN,
+              statusWindow->fBot+2);
+    XDrawLine(dpy, statusWindow->w, statusWindow->fgGC,
+              statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, 0,
+              statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN,
+              statusWindow->fBot+2);
+    if (0 == statusWindow->statusW)
+        XDrawLine(dpy, statusWindow->w, statusWindow->fgGC,
+                  0, 0, 0, statusWindow->fBot+2);
+
+    str =  statusWindow->peText;
+
+    if (str != NULL &&  (len = (int32_t)wcslen(str)) != 0) {
+        pos = 0;
+        attr = statusWindow->peAttr;
+        x_pos = x_caret = statusWindow->statusW + STATUS_BORDER;
+        while((int)len-1 >= pos) {
+            len_disp = get_next_attr(len - pos, &attr[pos]);
+            if (attr[pos] & XIMReverse) {
+                gc = statusWindow->bgGC;
+            }
+            else {
+                gc = statusWindow->fgGC;
+            }
+            XwcTextExtents(statusWindow->fontset,
+                           &str[pos],
+                           len_disp, &ink, &rect);
+            XwcDrawImageString(dpy, statusWindow->w,
+                               statusWindow->fontset, gc,
+                               x_pos, statusWindow->fOff+1, &str[pos], len_disp);
+            if (attr[pos] & XIMUnderline) {
+                XDrawLine(dpy, statusWindow->w,
+                          gc, x_pos, statusWindow->fBot,
+                          x_pos+rect.width, statusWindow->fBot);
+            }
+            if (!caret_done) {
+                if( statusWindow->peCaret >= pos &&
+                    statusWindow->peCaret <= pos+len_disp) {
+                    if (statusWindow->peCaret == 0)
+                        x_caret = x_pos;
+                    else if (statusWindow->peCaret == pos+len_disp)
+                        x_caret = x_pos+rect.width;
+                    else {
+                        XwcTextExtents(statusWindow->fontset,
+                                        &str[pos],
+                                        statusWindow->peCaret-pos,
+                                        &ink, &rect_c);
+                        x_caret = x_pos+ rect_c.width;
+                    }
+                    x_caret-=CARET_OFFSET;
+                    caret_done = True;
+                }
+            }
+            pos += len_disp;
+            x_pos += rect.width;
+        }
+        if (caret_done)
+            draw_caret(statusWindow, statusWindow->fgGC, x_caret);
+    }
+}
+
+/* calc required status window size and resize the window */
+static void align_status(StatusWindow *statusWindow)
+{
+    int len_st, len_pe = 0;
+    XRectangle rect_st, rect_pe, ink;
+    Dimension cur_w;
+    int value_make = CWX|CWWidth|CWHeight;
+    XWindowChanges xwc;
+
+    if (NULL == statusWindow) return;
+    if ((len_st = st_wcslen(statusWindow->status)) == 0
+        && (statusWindow->peText == NULL || st_wcslen(statusWindow->peText) == 0 ))
         return;
+
+    rect_pe.x = rect_pe.y = rect_pe.width = rect_pe.height = 0;
+
+    XwcTextExtents(statusWindow->fontset,
+                   statusWindow->status,
+                   len_st, &ink, &rect_st);
+    if (statusWindow->peText != NULL
+        && (len_pe = (int32_t)wcslen(statusWindow->peText)) > 0) {
+        XwcTextExtents(statusWindow->fontset,
+                       statusWindow->peText,
+                       len_pe, &ink, &rect_pe);
+    }
+    statusWindow->fOff = max(-rect_st.y, -rect_pe.y);
+    statusWindow->fBot = max(rect_st.height, rect_pe.height);
+    statusWindow->statusW =rect_st.width;
+    if (rect_st.width > 0) statusWindow->statusW += BORDER_MARGIN;
+    statusWindow->peTextW = rect_pe.width;
+
+    xwc.x = statusWindow->x - statusWindow->off_x;
+    if (xwc.x < 0 ) xwc.x = 0;
+
+    if (len_pe > 0) {
+        xwc.width = statusWindow->statusW
+                    + statusWindow->peTextW + BORDER_MARGIN + 1;
+        xwc.height = statusWindow->fBot + BORDER_MARGIN;
+    } else {
+        xwc.width = statusWindow->statusW;
+        xwc.height = statusWindow->fBot + BORDER_MARGIN;
     }
+    if (xwc.x + xwc.width > statusWindow->rootW){
+      xwc.x = statusWindow->rootW - xwc.width;
+    }
+    XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
+}
+
+static void shrink_status(StatusWindow *statusWindow)
+{
+    int value_make = CWX|CWWidth|CWHeight;
+    XWindowChanges xwc;
 
-    ximCallback.callback = (XIMProc)DestroyXIMCallback;
-    ximCallback.client_data = NULL;
-    XSetIMValues(X11im, XNDestroyCallback, &ximCallback, NULL);
+    if (NULL == statusWindow) return;
+    xwc.width  = statusWindow->statusW;
+    xwc.height = statusWindow->statusH;
+    statusWindow->peTextW = 0;
+    xwc.x = statusWindow->x - statusWindow->off_x;
+    if (xwc.x < 0 ) xwc.x = 0;
+    if (xwc.x + xwc.width > statusWindow->rootW){
+      xwc.x = statusWindow->rootW - xwc.width;
+    }
+    XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
 }
 
-static void DestroyXIMCallback(XIM im, XPointer client_data, XPointer call_data) {
-    /* mark that XIM server was destroyed */
-    X11im = NULL;
-    JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
-    /* free the old pX11IMData and set it to null. this also avoids crashing
-     * the jvm if the XIM server reappears */
-    X11InputMethodData *pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance);
+static GC create_gc(Window win, Bool isReverse)
+{
+    XGCValues xgcv;
+    unsigned long mask;
+    AwtScreenDataPtr defaultScreen;
+
+    defaultScreen = getScreenData(DefaultScreen(dpy));
+
+    mask = (GCForeground | GCBackground );
+    if (isReverse) {
+        xgcv.foreground = defaultScreen->whitepixel;
+        xgcv.background = defaultScreen->blackpixel;
+    } else {
+        xgcv.foreground = defaultScreen->blackpixel;
+        xgcv.background = defaultScreen->whitepixel;
+    }
+    return XCreateGC(dpy, win, mask, &xgcv);
 }
 
-/*
- * Class:     sun_awt_X11InputMethod
- * Method:    initIDs
- * Signature: ()V
- */
+static Bool isNativeIm()
+{
+#define XIMMODIFIER          "@im="
+#define XIM_SERVER_CATEGORY  "@server="
+    char *immodifiers;
+    char *imserver, *imserverPtr;
+    Atom imserverAtom;
+
+    if (!(immodifiers = getenv("XMODIFIERS"))) return True;
+    if (!(imserver = calloc(1,strlen(immodifiers)+strlen(XIM_SERVER_CATEGORY)+1))) return True;
+    if (!(immodifiers = strstr(immodifiers,XIMMODIFIER))) return True;
+    immodifiers += strlen(XIMMODIFIER);
+    strcpy(imserver,XIM_SERVER_CATEGORY);
+    imserverPtr = imserver + strlen(imserver);
+    while(*immodifiers != '@' && *immodifiers != '\0') {
+        *imserverPtr = *immodifiers;
+        imserverPtr++;
+        immodifiers++;
+    }
+    imserverAtom = XInternAtom(awt_display, imserver, True);
+    free(imserver);
+    if (imserverAtom > 0)
+        return False;
+    else
+        return True;
+}
 
-/* This function gets called from the static initializer for
-   X11InputMethod.java
-   to initialize the fieldIDs for fields that may be accessed from C */
-JNIEXPORT void JNICALL
-Java_sun_awt_X11InputMethod_initIDs(JNIEnv *env, jclass cls)
+static Window getGrandParent(Window parent)
 {
-    x11InputMethodIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J");
+    Window containerWindow,rootWindow,tmp;
+    Window *ignoreWindowPtr;
+    unsigned int ignoreUnit;
+    Window grandParent=0;
+    XWindowAttributes xwa;
+    Atom WM_STATE;
+    Atom type = None;
+    int32_t format;
+    unsigned long nitems, after;
+    unsigned char * data;
+
+    if (parent == 0) return grandParent;
+    WM_STATE = XInternAtom(dpy, "WM_STATE", True);
+    if (WM_STATE == None) return grandParent;
+
+    tmp=parent;
+    while(XQueryTree(dpy, tmp,
+                     &rootWindow, &containerWindow,
+                     &ignoreWindowPtr, &ignoreUnit)){
+        XFree(ignoreWindowPtr);
+        if (containerWindow == rootWindow) break;
+        if (XGetWindowProperty(dpy, containerWindow, WM_STATE,
+                    0, 0, False, AnyPropertyType,
+                    &type, &format, &nitems, &after, &data) == Success) {
+            XFree(data);
+            if (type) {
+                XGetWindowAttributes(dpy, containerWindow, &xwa);
+                if (FALSE == xwa.override_redirect){
+                    grandParent=containerWindow;
+                }
+            }
+        }
+        tmp=containerWindow;
+    }
+    return grandParent;
+}
+
+static void moveStatusWindow(StatusWindow *statusWindow)
+{
+    XWindowAttributes xwa;
+    Window child;
+    int x, y, width;
+    Window target;
+
+    if (NULL == statusWindow) return;
+    if (statusWindow->grandParent) {
+        target = statusWindow->grandParent;
+    } else {
+        target = statusWindow->parent;
+    }
+    XGetWindowAttributes(dpy, target, &xwa);
+    XTranslateCoordinates(dpy,
+                          target, xwa.root,
+                          0, 0,
+                          &x, &y,
+                          &child);
+    if (statusWindow->x != x
+        || statusWindow->y != y
+        || statusWindow->width != xwa.width
+        || statusWindow->height != xwa.height){
+        statusWindow->x = x;
+        statusWindow->y = y;
+        statusWindow->height = xwa.height;
+        statusWindow->width = xwa.width;
+        x = statusWindow->x - statusWindow->off_x;
+        y = statusWindow->y + statusWindow->height + statusWindow->off_y;
+        if (x < 0 ){
+            x = 0;
+        }
+        if (statusWindow->peTextW > 0) {
+            width = statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN + 1;
+            if (x + width > statusWindow->rootW){
+                x = statusWindow->rootW - width;
+            }
+        } else {
+            if (x + statusWindow->statusW > statusWindow->rootW){
+                x = statusWindow->rootW - statusWindow->statusW;
+            }
+        }
+        if (y + statusWindow->statusH > statusWindow->rootH){
+            y = statusWindow->rootH - statusWindow->statusH;
+        }
+        XMoveWindow(dpy, statusWindow->w, x, y);
+    }
+}
+
+static void arrange_window_stack(StatusWindow* statusWindow)
+{
+    XWindowChanges xwc;
+    int value_make = CWSibling|CWStackMode;
+    Window root, parent, *children;
+    unsigned int nchildren;
+
+    if (NULL == statusWindow) return;
+    if (XQueryTree(dpy, statusWindow->parent,
+                       &root, &parent, &children, &nchildren)){
+        XFree(children);
+        xwc.sibling = parent;
+        while(XQueryTree(dpy, xwc.sibling, &root, &parent, &children, &nchildren)) {
+            XFree(children);
+            if (root != parent) {
+                xwc.sibling = parent;
+            } else {
+                break;
+            }
+        }
+        xwc.stack_mode = Above;
+        XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
+    }
+}
+
+static int count_missing_fonts(char **charset_list, int charset_count)
+{
+    int i,j;
+    if (charset_count > 0) {
+        j=charset_count;
+        for(i=0; i < charset_count; i++) {
+            if ((strstr(charset_list[i], "IBM-udc")) ||
+                (strstr(charset_list[i], "IBM-sbd")) ||
+                (strstr(charset_list[i], "IBM-ucdTW")))
+                j--;
+        }
+        return j;
+    }
+    else
+        return 0;
+}
+
+static XFontSet create_fontset_name(char * font_name, Bool force)
+{
+    XFontSet fontset = NULL;
+    char **charset_list;
+    int charset_count;
+    char *def_string;
+    int missing_fonts;
+
+    fontset = XCreateFontSet(dpy, font_name,
+                &charset_list, &charset_count, &def_string);
+    if (charset_count > 0) {
+        missing_fonts = count_missing_fonts(charset_list,
+                                            charset_count);
+        XFreeStringList(charset_list);
+        if (fontset && (missing_fonts > 0)) {
+            if (!force) {
+                XFreeFontSet(dpy, fontset);
+                fontset = NULL;
+            }
+        }
+    }
+    return fontset;
 }
 
+static XFontSet create_fontset()
+{
+    XFontSet fontset = NULL;
+    int i;
+    static char * fontlist[] = {
+        "-dt-interface user-medium-r-normal-S*-*-*-*-*-*-*-*-*",
+        "-*-*-medium-r-normal-*-14-*-*-*-c-*-*-*",
+        "-*-*-medium-r-normal-*-14-*-*-*-m-*-*-*",
+        "-*-*-medium-r-normal--14-0-0-0-m-*-*-*",
+        "-monotype-sansmonowt-medium-r-normal--14-*-*-*-m-*-*-*",
+        "-*--14-*",
+        "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*",
+        "-*--16-*",
+        "-*--17-*",
+        "-*--18-*",
+        "-*--19-*",
+        "-*--20-*",
+        "-*--24-*",
+        NULL};
+
+    for (i=0; fontlist[i] != NULL && fontset==NULL; i++)
+        fontset = create_fontset_name(fontlist[i], False);
+
+    if (!fontset)
+        fprintf(stdout, "Cannot load fonts for IMF.\n");
+    return  fontset;
+}
+
+static Window get_current_focus(XIC ic) {
+    Window w = 0;
+    if (ic != NULL)
+        XGetICValues(ic, XNFocusWindow, &w, NULL);
+    return w;
+}
 
 JNIEXPORT jboolean JNICALL
 Java_sun_awt_X11_XInputMethod_openXIMNative(JNIEnv *env,
-                                          jobject this,
-                                          jlong display)
+                                            jobject this,
+                                            jlong display)
 {
     Bool registered;
 
     AWT_LOCK();
 
     dpy = (Display *)jlong_to_ptr(display);
 
-/* Use IMInstantiate call back only on Linux, as there is a bug in Solaris
-   (4768335)
-*/
-#if defined(__linux__) || defined(MACOSX)
-    registered = XRegisterIMInstantiateCallback(dpy, NULL, NULL,
-                     NULL, (XIDProc)OpenXIMCallback, NULL);
-    if (!registered) {
-        /* directly call openXIM callback */
-#endif
-        OpenXIMCallback(dpy, NULL, NULL);
-#if defined(__linux__) || defined(MACOSX)
+    if (X11im == NULL) {
+        X11im = XOpenIM(dpy, NULL, NULL, NULL);
     }
-#endif
 
     AWT_UNLOCK();
 
     return JNI_TRUE;
 }
 
 JNIEXPORT jboolean JNICALL
 Java_sun_awt_X11_XInputMethod_createXICNative(JNIEnv *env,
-                                                  jobject this,
-                                                  jlong window)
+                                              jobject this,
+                                              jlong window)
 {
     X11InputMethodData *pX11IMData;
     jobject globalRef;
     XIC ic;
 

@@ -1397,38 +1935,34 @@
         return JNI_FALSE;
     }
 
     globalRef = (*env)->NewGlobalRef(env, this);
     pX11IMData->x11inputmethod = globalRef;
-#if defined(__linux__) || defined(MACOSX)
     pX11IMData->statusWindow = NULL;
-#endif /* __linux__ || MACOSX */
 
-    pX11IMData->lookup_buf = 0;
-    pX11IMData->lookup_buf_len = 0;
+    setX11InputMethodData(env, this, pX11IMData);
 
     if (createXIC(env, pX11IMData, (Window)window) == False) {
         destroyX11InputMethodData((JNIEnv *) NULL, pX11IMData);
         pX11IMData = (X11InputMethodData *) NULL;
+        setX11InputMethodData(env, this, pX11IMData);
         if ((*env)->ExceptionCheck(env)) {
             goto finally;
         }
     }
 
-    setX11InputMethodData(env, this, pX11IMData);
-
 finally:
     AWT_UNLOCK();
     return (pX11IMData != NULL);
 }
 
 JNIEXPORT void JNICALL
 Java_sun_awt_X11_XInputMethod_setXICFocusNative(JNIEnv *env,
-                                              jobject this,
-                                              jlong w,
-                                              jboolean req,
-                                              jboolean active)
+                                                jobject this,
+                                                jlong w,
+                                                jboolean req,
+                                                jboolean active)
 {
     X11InputMethodData *pX11IMData;
     AWT_LOCK();
     pX11IMData = getX11InputMethodData(env, this);
     if (pX11IMData == NULL) {

@@ -1439,67 +1973,90 @@
     if (req) {
         if (!w) {
             AWT_UNLOCK();
             return;
         }
+        pX11IMData->isActiveClient = active;
         pX11IMData->current_ic = active ?
                         pX11IMData->ic_active : pX11IMData->ic_passive;
         /*
          * On Solaris2.6, setXICWindowFocus() has to be invoked
          * before setting focus.
          */
-        setXICWindowFocus(pX11IMData->current_ic, w);
-        setXICFocus(pX11IMData->current_ic, req);
-        currentX11InputMethodInstance = pX11IMData->x11inputmethod;
-        currentFocusWindow =  w;
-#if defined(__linux__) || defined(MACOSX)
-        if (active && pX11IMData->statusWindow && pX11IMData->statusWindow->on)
+        get_current_focus(pX11IMData->current_ic); /* workaround for kinput2 and SCIM */
+        if (currentFocusWindow != w) {
+            setXICWindowFocus(pX11IMData->current_ic, w);
+            setXICFocus(pX11IMData->current_ic, req);
+            currentX11InputMethodInstance = pX11IMData->x11inputmethod;
+            currentFocusWindow =  w;
+        } else {
+            setXICFocus(pX11IMData->current_ic, req);
+        }
+        if ((active || pX11IMData->passiveStatusWindow)
+            && (pX11IMData->statusWindow && pX11IMData->statusWindow->on))
             onoffStatusWindow(pX11IMData, w, True);
-#endif
     } else {
         currentX11InputMethodInstance = NULL;
         currentFocusWindow = 0;
-#if defined(__linux__) || defined(MACOSX)
         onoffStatusWindow(pX11IMData, 0, False);
         if (pX11IMData->current_ic != NULL)
-#endif
         setXICFocus(pX11IMData->current_ic, req);
 
         pX11IMData->current_ic = (XIC)0;
     }
 
     XFlush(dpy);
     AWT_UNLOCK();
 }
 
-JNIEXPORT void JNICALL
-Java_sun_awt_X11InputMethod_turnoffStatusWindow(JNIEnv *env,
-                                                jobject this)
+/*
+ * Class:     sun_awt_X11InputMethodBase
+ * Method:    initIDs
+ * Signature: ()V
+ * This function gets called from the static initializer for
+ * X11InputMethod.java to initialize the fieldIDs for fields
+ * that may be accessed from C
+ */
+JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_initIDs
+  (JNIEnv *env, jclass cls)
+{
+    x11InputMethodIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J");
+}
+
+/*
+ * Class:     sun_awt_X11InputMethodBase
+ * Method:    turnoffStatusWindow
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_turnoffStatusWindow
+  (JNIEnv *env, jobject this)
 {
-#if defined(__linux__) || defined(MACOSX)
     X11InputMethodData *pX11IMData;
     StatusWindow *statusWindow;
 
     AWT_LOCK();
 
     if (NULL == currentX11InputMethodInstance
-        || !isX11InputMethodGRefInList(currentX11InputMethodInstance)
         || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))
         || NULL == (statusWindow = pX11IMData->statusWindow)
         || !statusWindow->on ){
         AWT_UNLOCK();
         return;
     }
     onoffStatusWindow(pX11IMData, 0, False);
+    statusWindow->on = False;
 
     AWT_UNLOCK();
-#endif
 }
 
-JNIEXPORT void JNICALL
-Java_sun_awt_X11InputMethod_disposeXIC(JNIEnv *env,
-                                             jobject this)
+/*
+ * Class:     sun_awt_X11InputMethodBase
+ * Method:    disposeXIC
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_disposeXIC
+  (JNIEnv *env, jobject this)
 {
     X11InputMethodData *pX11IMData = NULL;
 
     AWT_LOCK();
     pX11IMData = getX11InputMethodData(env, this);

@@ -1516,13 +2073,17 @@
     }
     destroyX11InputMethodData(env, pX11IMData);
     AWT_UNLOCK();
 }
 
-JNIEXPORT jstring JNICALL
-Java_sun_awt_X11InputMethod_resetXIC(JNIEnv *env,
-                                           jobject this)
+/*
+ * Class:     sun_awt_X11InputMethodBase
+ * Method:    resetXIC
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_sun_awt_X11InputMethodBase_resetXIC
+  (JNIEnv *env, jobject this)
 {
     X11InputMethodData *pX11IMData;
     char *xText = NULL;
     jstring jText = (jstring)0;
 

@@ -1531,121 +2092,178 @@
     if (pX11IMData == NULL) {
         AWT_UNLOCK();
         return jText;
     }
 
-    if (pX11IMData->current_ic)
-        xText = XmbResetIC(pX11IMData->current_ic);
-    else {
+    if (pX11IMData->current_ic) {
+        if (!isPreeditStateActive(pX11IMData->current_ic)) {
+            xText = NULL;
+        } else {
+            if (!(pX11IMData->forceReset))
+                setXICFocus(pX11IMData->current_ic, FALSE);
+            xText = XmbResetIC(pX11IMData->current_ic);
+            if (!(pX11IMData->forceReset))
+                setXICFocus(pX11IMData->current_ic, TRUE);
+        }
+    } else {
         /*
          * If there is no reference to the current XIC, try to reset both XICs.
          */
+        if (!isPreeditStateActive(pX11IMData->ic_active))
+            xText = NULL;
+        else
         xText = XmbResetIC(pX11IMData->ic_active);
         /*it may also means that the real client component does
           not have focus -- has been deactivated... its xic should
           not have the focus, bug#4284651 showes reset XIC for htt
           may bring the focus back, so de-focus it again.
         */
         setXICFocus(pX11IMData->ic_active, FALSE);
         if (pX11IMData->ic_active != pX11IMData->ic_passive) {
-            char *tmpText = XmbResetIC(pX11IMData->ic_passive);
+            char *tmpText;
+            if (!isPreeditStateActive(pX11IMData->ic_passive))
+                tmpText = NULL;
+            else
+                tmpText = XmbResetIC(pX11IMData->ic_passive);
             setXICFocus(pX11IMData->ic_passive, FALSE);
             if (xText == (char *)NULL && tmpText)
                 xText = tmpText;
         }
-
     }
     if (xText != NULL) {
         jText = JNU_NewStringPlatform(env, (const char *)xText);
         XFree((void *)xText);
     }
 
+    /* workaround
+     * Some IME do not call PreeditDoneCallback routine even
+     * when XmbResetIC is called. I force to reset the preedit string.
+     */
+    if (!pX11IMData->isActiveClient) {
+        resetPassivePreeditText(pX11IMData->statusWindow);
+        shrink_status(pX11IMData->statusWindow);
+    } else {
+        JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
+                             "clearComposedText",
+                             "()V");
+        if ((*env)->ExceptionOccurred(env)) {
+            (*env)->ExceptionDescribe(env);
+            (*env)->ExceptionClear(env);
+        }
+    }
+
     AWT_UNLOCK();
     return jText;
 }
 
 /*
- * Class:     sun_awt_X11InputMethod
+ * Class:     sun_awt_X11InputMethodBase
  * Method:    setCompositionEnabledNative
- * Signature: (ZJ)V
+ * Signature: (Z)Z
  *
  * This method tries to set the XNPreeditState attribute associated with the current
  * XIC to the passed in 'enable' state.
  *
  * Return JNI_TRUE if XNPreeditState attribute is successfully changed to the
  * 'enable' state; Otherwise, if XSetICValues fails to set this attribute,
  * java.lang.UnsupportedOperationException will be thrown. JNI_FALSE is returned if this
  * method fails due to other reasons.
- *
  */
-JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethod_setCompositionEnabledNative
+JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_setCompositionEnabledNative
   (JNIEnv *env, jobject this, jboolean enable)
 {
     X11InputMethodData *pX11IMData;
     char * ret = NULL;
+    XVaNestedList pr_atrb;
 
     AWT_LOCK();
     pX11IMData = getX11InputMethodData(env, this);
 
     if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {
         AWT_UNLOCK();
         return JNI_FALSE;
     }
 
-    ret = XSetICValues(pX11IMData->current_ic, XNPreeditState,
-                       (enable ? XIMPreeditEnable : XIMPreeditDisable), NULL);
+    pr_atrb = XVaCreateNestedList(0, XNPreeditState,
+                  (enable ? XIMPreeditEnable : XIMPreeditDisable), NULL);
+    ret = XSetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL);
+    XFree((void *)pr_atrb);
     AWT_UNLOCK();
 
-    if ((ret != 0) && (strcmp(ret, XNPreeditState) == 0)) {
+    if ((ret != 0) &&
+        ((strcmp(ret, XNPreeditAttributes) == 0)
+         || (strcmp(ret, XNPreeditState) == 0))) {
         JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
     }
 
     return (jboolean)(ret == 0);
 }
 
 /*
- * Class:     sun_awt_X11InputMethod
+ * Class:     sun_awt_X11InputMethodBase
  * Method:    isCompositionEnabledNative
- * Signature: (J)Z
+ * Signature: ()Z
  *
  * This method tries to get the XNPreeditState attribute associated with the current XIC.
  *
  * Return JNI_TRUE if the XNPreeditState is successfully retrieved. Otherwise, if
  * XGetICValues fails to get this attribute, java.lang.UnsupportedOperationException
  * will be thrown. JNI_FALSE is returned if this method fails due to other reasons.
- *
  */
-JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethod_isCompositionEnabledNative
+JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_isCompositionEnabledNative
   (JNIEnv *env, jobject this)
 {
     X11InputMethodData *pX11IMData = NULL;
     char * ret = NULL;
-    XIMPreeditState state;
+    XIMPreeditState state = XIMPreeditUnKnown;
+    XVaNestedList   pr_atrb;
 
     AWT_LOCK();
     pX11IMData = getX11InputMethodData(env, this);
 
     if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {
         AWT_UNLOCK();
         return JNI_FALSE;
     }
 
-    ret = XGetICValues(pX11IMData->current_ic, XNPreeditState, &state, NULL);
+    pr_atrb = XVaCreateNestedList(0, XNPreeditState, &state, NULL);
+    ret = XGetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL);
+    XFree((void *)pr_atrb);
     AWT_UNLOCK();
 
-    if ((ret != 0) && (strcmp(ret, XNPreeditState) == 0)) {
+    if ((ret != 0) &&
+        ((strcmp(ret, XNPreeditAttributes) == 0)
+         || (strcmp(ret, XNPreeditState) == 0))) {
         JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
         return JNI_FALSE;
     }
 
     return (jboolean)(state == XIMPreeditEnable);
 }
 
 JNIEXPORT void JNICALL Java_sun_awt_X11_XInputMethod_adjustStatusWindow
   (JNIEnv *env, jobject this, jlong window)
 {
-#if defined(__linux__) || defined(MACOSX)
-    AWT_LOCK();
-    adjustStatusWindow(window);
-    AWT_UNLOCK();
-#endif
+
+}
+
+/*
+ * Class:     sun_awt_X11InputMethod
+ * Method:    setStatusAreaVisible
+ * Signature: (ZJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_awt_X11InputMethod_setStatusAreaVisible
+  (JNIEnv *env, jobject this, jboolean value, jlong data)
+{
+    X11InputMethodData *pX11IMData;
+
+    pX11IMData = getX11InputMethodData(env, this);
+    if (NULL == pX11IMData) return;
+    if (NULL == pX11IMData->statusWindow) return;
+
+    if ((int)value){
+        pX11IMData->statusWindow->on = True;
+    }else{
+        pX11IMData->statusWindow->on = False;
+    }
+    return;
 }
< prev index next >