src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c
changeset 47216 71c04702a3d5
parent 42455 a66ed8458668
child 50350 668463f93ec0
child 56230 489867818774
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 #ifdef HEADLESS
       
    27     #error This file should not be included in headless library
       
    28 #endif
       
    29 
       
    30 #include <stdio.h>
       
    31 #include <stdlib.h>
       
    32 #include <X11/Xlib.h>
       
    33 #include <X11/keysym.h>
       
    34 #include <sys/time.h>
       
    35 
       
    36 #include "awt.h"
       
    37 #include "awt_p.h"
       
    38 
       
    39 #include <sun_awt_X11InputMethod.h>
       
    40 #include <sun_awt_X11_XInputMethod.h>
       
    41 
       
    42 #define THROW_OUT_OF_MEMORY_ERROR() \
       
    43         JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL)
       
    44 
       
    45 struct X11InputMethodIDs {
       
    46   jfieldID pData;
       
    47 } x11InputMethodIDs;
       
    48 
       
    49 static void PreeditStartCallback(XIC, XPointer, XPointer);
       
    50 static void PreeditDoneCallback(XIC, XPointer, XPointer);
       
    51 static void PreeditDrawCallback(XIC, XPointer,
       
    52                                 XIMPreeditDrawCallbackStruct *);
       
    53 static void PreeditCaretCallback(XIC, XPointer,
       
    54                                  XIMPreeditCaretCallbackStruct *);
       
    55 #if defined(__linux__) || defined(MACOSX)
       
    56 static void StatusStartCallback(XIC, XPointer, XPointer);
       
    57 static void StatusDoneCallback(XIC, XPointer, XPointer);
       
    58 static void StatusDrawCallback(XIC, XPointer,
       
    59                                XIMStatusDrawCallbackStruct *);
       
    60 #endif
       
    61 
       
    62 #define ROOT_WINDOW_STYLES      (XIMPreeditNothing | XIMStatusNothing)
       
    63 #define NO_STYLES               (XIMPreeditNone | XIMStatusNone)
       
    64 
       
    65 #define PreeditStartIndex       0
       
    66 #define PreeditDoneIndex        1
       
    67 #define PreeditDrawIndex        2
       
    68 #define PreeditCaretIndex       3
       
    69 #if defined(__linux__) || defined(MACOSX)
       
    70 #define StatusStartIndex        4
       
    71 #define StatusDoneIndex         5
       
    72 #define StatusDrawIndex         6
       
    73 #define NCALLBACKS              7
       
    74 #else
       
    75 #define NCALLBACKS              4
       
    76 #endif
       
    77 
       
    78 /*
       
    79  * Callback function pointers: the order has to match the *Index
       
    80  * values above.
       
    81  */
       
    82 static XIMProc callback_funcs[NCALLBACKS] = {
       
    83     (XIMProc)PreeditStartCallback,
       
    84     (XIMProc)PreeditDoneCallback,
       
    85     (XIMProc)PreeditDrawCallback,
       
    86     (XIMProc)PreeditCaretCallback,
       
    87 #if defined(__linux__) || defined(MACOSX)
       
    88     (XIMProc)StatusStartCallback,
       
    89     (XIMProc)StatusDoneCallback,
       
    90     (XIMProc)StatusDrawCallback,
       
    91 #endif
       
    92 };
       
    93 
       
    94 #if defined(__linux__) || defined(MACOSX)
       
    95 #define MAX_STATUS_LEN  100
       
    96 typedef struct {
       
    97     Window   w;                /*status window id        */
       
    98     Window   root;             /*the root window id      */
       
    99     Window   parent;           /*parent shell window     */
       
   100     int      x, y;             /*parent's upperleft position */
       
   101     int      width, height;    /*parent's width, height  */
       
   102     GC       lightGC;          /*gc for light border     */
       
   103     GC       dimGC;            /*gc for dim border       */
       
   104     GC       bgGC;             /*normal painting         */
       
   105     GC       fgGC;             /*normal painting         */
       
   106     int      statusW, statusH; /*status window's w, h    */
       
   107     int      rootW, rootH;     /*root window's w, h    */
       
   108     int      bWidth;           /*border width            */
       
   109     char     status[MAX_STATUS_LEN]; /*status text       */
       
   110     XFontSet fontset;           /*fontset for drawing    */
       
   111     int      off_x, off_y;
       
   112     Bool     on;                /*if the status window on*/
       
   113 } StatusWindow;
       
   114 #endif
       
   115 
       
   116 /*
       
   117  * X11InputMethodData keeps per X11InputMethod instance information. A pointer
       
   118  * to this data structure is kept in an X11InputMethod object (pData).
       
   119  */
       
   120 typedef struct _X11InputMethodData {
       
   121     XIC         current_ic;     /* current X Input Context */
       
   122     XIC         ic_active;      /* X Input Context for active clients */
       
   123     XIC         ic_passive;     /* X Input Context for passive clients */
       
   124     XIMCallback *callbacks;     /* callback parameters */
       
   125     jobject     x11inputmethod; /* global ref to X11InputMethod instance */
       
   126                                 /* associated with the XIC */
       
   127 #if defined(__linux__) || defined(MACOSX)
       
   128     StatusWindow *statusWindow; /* our own status window  */
       
   129 #endif
       
   130     char        *lookup_buf;    /* buffer used for XmbLookupString */
       
   131     int         lookup_buf_len; /* lookup buffer size in bytes */
       
   132 } X11InputMethodData;
       
   133 
       
   134 /*
       
   135  * When XIC is created, a global reference is created for
       
   136  * sun.awt.X11InputMethod object so that it could be used by the XIM callback
       
   137  * functions. This could be a dangerous thing to do when the original
       
   138  * X11InputMethod object is garbage collected and as a result,
       
   139  * destroyX11InputMethodData is called to delete the global reference.
       
   140  * If any XIM callback function still holds and uses the "already deleted"
       
   141  * global reference, disaster is going to happen. So we have to maintain
       
   142  * a list for these global references which is consulted first when the
       
   143  * callback functions or any function tries to use "currentX11InputMethodObject"
       
   144  * which always refers to the global reference try to use it.
       
   145  *
       
   146  */
       
   147 typedef struct _X11InputMethodGRefNode {
       
   148     jobject inputMethodGRef;
       
   149     struct _X11InputMethodGRefNode* next;
       
   150 } X11InputMethodGRefNode;
       
   151 
       
   152 X11InputMethodGRefNode *x11InputMethodGRefListHead = NULL;
       
   153 
       
   154 /* reference to the current X11InputMethod instance, it is always
       
   155    point to the global reference to the X11InputMethodObject since
       
   156    it could be referenced by different threads. */
       
   157 jobject currentX11InputMethodInstance = NULL;
       
   158 
       
   159 Window  currentFocusWindow = 0;  /* current window that has focus for input
       
   160                                        method. (the best place to put this
       
   161                                        information should be
       
   162                                        currentX11InputMethodInstance's pData) */
       
   163 static XIM X11im = NULL;
       
   164 Display * dpy = NULL;
       
   165 
       
   166 #define GetJNIEnv() (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2)
       
   167 
       
   168 static void DestroyXIMCallback(XIM, XPointer, XPointer);
       
   169 static void OpenXIMCallback(Display *, XPointer, XPointer);
       
   170 /* Solaris XIM Extention */
       
   171 #define XNCommitStringCallback "commitStringCallback"
       
   172 static void CommitStringCallback(XIC, XPointer, XPointer);
       
   173 
       
   174 static X11InputMethodData * getX11InputMethodData(JNIEnv *, jobject);
       
   175 static void setX11InputMethodData(JNIEnv *, jobject, X11InputMethodData *);
       
   176 static void destroyX11InputMethodData(JNIEnv *, X11InputMethodData *);
       
   177 static void freeX11InputMethodData(JNIEnv *, X11InputMethodData *);
       
   178 
       
   179 #ifdef __solaris__
       
   180 /* Prototype for this function is missing in Solaris X11R6 Xlib.h */
       
   181 extern char *XSetIMValues(
       
   182 #if NeedVarargsPrototypes
       
   183     XIM /* im */, ...
       
   184 #endif
       
   185 );
       
   186 #endif
       
   187 
       
   188 /*
       
   189  * This function is stolen from /src/solaris/hpi/src/system_md.c
       
   190  * It is used in setting the time in Java-level InputEvents
       
   191  */
       
   192 jlong
       
   193 awt_util_nowMillisUTC()
       
   194 {
       
   195     struct timeval t;
       
   196     gettimeofday(&t, NULL);
       
   197     return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000);
       
   198 }
       
   199 
       
   200 /*
       
   201  * Converts the wchar_t string to a multi-byte string calling wcstombs(). A
       
   202  * buffer is allocated by malloc() to store the multi-byte string. NULL is
       
   203  * returned if the given wchar_t string pointer is NULL or buffer allocation is
       
   204  * failed.
       
   205  */
       
   206 static char *
       
   207 wcstombsdmp(wchar_t *wcs, int len)
       
   208 {
       
   209     size_t n;
       
   210     char *mbs;
       
   211 
       
   212     if (wcs == NULL)
       
   213         return NULL;
       
   214 
       
   215     n = len*MB_CUR_MAX + 1;
       
   216 
       
   217     mbs = (char *) malloc(n * sizeof(char));
       
   218     if (mbs == NULL) {
       
   219         THROW_OUT_OF_MEMORY_ERROR();
       
   220         return NULL;
       
   221     }
       
   222 
       
   223     /* TODO: check return values... Handle invalid characters properly...  */
       
   224     if (wcstombs(mbs, wcs, n) == (size_t)-1) {
       
   225         free(mbs);
       
   226         return NULL;
       
   227     }
       
   228 
       
   229     return mbs;
       
   230 }
       
   231 
       
   232 /*
       
   233  * Returns True if the global reference is still in the list,
       
   234  * otherwise False.
       
   235  */
       
   236 static Bool isX11InputMethodGRefInList(jobject imGRef) {
       
   237     X11InputMethodGRefNode *pX11InputMethodGRef = x11InputMethodGRefListHead;
       
   238 
       
   239     if (imGRef == NULL) {
       
   240         return False;
       
   241     }
       
   242 
       
   243     while (pX11InputMethodGRef != NULL) {
       
   244         if (pX11InputMethodGRef->inputMethodGRef == imGRef) {
       
   245             return True;
       
   246         }
       
   247         pX11InputMethodGRef = pX11InputMethodGRef->next;
       
   248     }
       
   249 
       
   250     return False;
       
   251 }
       
   252 
       
   253 /*
       
   254  * Add the new created global reference to the list.
       
   255  */
       
   256 static void addToX11InputMethodGRefList(jobject newX11InputMethodGRef) {
       
   257     X11InputMethodGRefNode *newNode = NULL;
       
   258 
       
   259     if (newX11InputMethodGRef == NULL ||
       
   260         isX11InputMethodGRefInList(newX11InputMethodGRef)) {
       
   261         return;
       
   262     }
       
   263 
       
   264     newNode = (X11InputMethodGRefNode *)malloc(sizeof(X11InputMethodGRefNode));
       
   265 
       
   266     if (newNode == NULL) {
       
   267         return;
       
   268     } else {
       
   269         newNode->inputMethodGRef = newX11InputMethodGRef;
       
   270         newNode->next = x11InputMethodGRefListHead;
       
   271         x11InputMethodGRefListHead = newNode;
       
   272     }
       
   273 }
       
   274 
       
   275 /*
       
   276  * Remove the global reference from the list.
       
   277  */
       
   278 static void removeX11InputMethodGRefFromList(jobject x11InputMethodGRef) {
       
   279      X11InputMethodGRefNode *pX11InputMethodGRef = NULL;
       
   280      X11InputMethodGRefNode *cX11InputMethodGRef = x11InputMethodGRefListHead;
       
   281 
       
   282      if (x11InputMethodGRefListHead == NULL ||
       
   283          x11InputMethodGRef == NULL) {
       
   284          return;
       
   285      }
       
   286 
       
   287      /* cX11InputMethodGRef always refers to the current node while
       
   288         pX11InputMethodGRef refers to the previous node.
       
   289      */
       
   290      while (cX11InputMethodGRef != NULL) {
       
   291          if (cX11InputMethodGRef->inputMethodGRef == x11InputMethodGRef) {
       
   292              break;
       
   293          }
       
   294          pX11InputMethodGRef = cX11InputMethodGRef;
       
   295          cX11InputMethodGRef = cX11InputMethodGRef->next;
       
   296      }
       
   297 
       
   298      if (cX11InputMethodGRef == NULL) {
       
   299          return; /* Not found. */
       
   300      }
       
   301 
       
   302      if (cX11InputMethodGRef == x11InputMethodGRefListHead) {
       
   303          x11InputMethodGRefListHead = x11InputMethodGRefListHead->next;
       
   304      } else {
       
   305          pX11InputMethodGRef->next = cX11InputMethodGRef->next;
       
   306      }
       
   307      free(cX11InputMethodGRef);
       
   308 
       
   309      return;
       
   310 }
       
   311 
       
   312 
       
   313 static X11InputMethodData * getX11InputMethodData(JNIEnv * env, jobject imInstance) {
       
   314     X11InputMethodData *pX11IMData =
       
   315         (X11InputMethodData *)JNU_GetLongFieldAsPtr(env, imInstance, x11InputMethodIDs.pData);
       
   316 
       
   317     /*
       
   318      * In case the XIM server was killed somehow, reset X11InputMethodData.
       
   319      */
       
   320     if (X11im == NULL && pX11IMData != NULL) {
       
   321         JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
       
   322                              "flushText",
       
   323                              "()V");
       
   324         JNU_CHECK_EXCEPTION_RETURN(env, NULL);
       
   325         /* IMPORTANT:
       
   326            The order of the following calls is critical since "imInstance" may
       
   327            point to the global reference itself, if "freeX11InputMethodData" is called
       
   328            first, the global reference will be destroyed and "setX11InputMethodData"
       
   329            will in fact fail silently. So pX11IMData will not be set to NULL.
       
   330            This could make the original java object refers to a deleted pX11IMData
       
   331            object.
       
   332         */
       
   333         setX11InputMethodData(env, imInstance, NULL);
       
   334         freeX11InputMethodData(env, pX11IMData);
       
   335         pX11IMData = NULL;
       
   336     }
       
   337 
       
   338     return pX11IMData;
       
   339 }
       
   340 
       
   341 static void setX11InputMethodData(JNIEnv * env, jobject imInstance, X11InputMethodData *pX11IMData) {
       
   342     JNU_SetLongFieldFromPtr(env, imInstance, x11InputMethodIDs.pData, pX11IMData);
       
   343 }
       
   344 
       
   345 /* this function should be called within AWT_LOCK() */
       
   346 static void
       
   347 destroyX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData)
       
   348 {
       
   349     /*
       
   350      * Destroy XICs
       
   351      */
       
   352     if (pX11IMData == NULL) {
       
   353         return;
       
   354     }
       
   355 
       
   356     if (pX11IMData->ic_active != (XIC)0) {
       
   357         XUnsetICFocus(pX11IMData->ic_active);
       
   358         XDestroyIC(pX11IMData->ic_active);
       
   359         if (pX11IMData->ic_active != pX11IMData->ic_passive) {
       
   360             if (pX11IMData->ic_passive != (XIC)0) {
       
   361                 XUnsetICFocus(pX11IMData->ic_passive);
       
   362                 XDestroyIC(pX11IMData->ic_passive);
       
   363             }
       
   364             pX11IMData->ic_passive = (XIC)0;
       
   365             pX11IMData->current_ic = (XIC)0;
       
   366         }
       
   367     }
       
   368 
       
   369     freeX11InputMethodData(env, pX11IMData);
       
   370 }
       
   371 
       
   372 static void
       
   373 freeX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData)
       
   374 {
       
   375 #if defined(__linux__) || defined(MACOSX)
       
   376     if (pX11IMData->statusWindow != NULL){
       
   377         StatusWindow *sw = pX11IMData->statusWindow;
       
   378         XFreeGC(awt_display, sw->lightGC);
       
   379         XFreeGC(awt_display, sw->dimGC);
       
   380         XFreeGC(awt_display, sw->bgGC);
       
   381         XFreeGC(awt_display, sw->fgGC);
       
   382         if (sw->fontset != NULL) {
       
   383             XFreeFontSet(awt_display, sw->fontset);
       
   384         }
       
   385         XDestroyWindow(awt_display, sw->w);
       
   386         free((void*)sw);
       
   387     }
       
   388 #endif
       
   389 
       
   390     if (pX11IMData->callbacks)
       
   391         free((void *)pX11IMData->callbacks);
       
   392 
       
   393     if (env) {
       
   394         /* Remove the global reference from the list, so that
       
   395            the callback function or whoever refers to it could know.
       
   396         */
       
   397         removeX11InputMethodGRefFromList(pX11IMData->x11inputmethod);
       
   398         (*env)->DeleteGlobalRef(env, pX11IMData->x11inputmethod);
       
   399     }
       
   400 
       
   401     if (pX11IMData->lookup_buf) {
       
   402         free((void *)pX11IMData->lookup_buf);
       
   403     }
       
   404 
       
   405     free((void *)pX11IMData);
       
   406 }
       
   407 
       
   408 /*
       
   409  * Sets or unsets the focus to the given XIC.
       
   410  */
       
   411 static void
       
   412 setXICFocus(XIC ic, unsigned short req)
       
   413 {
       
   414     if (ic == NULL) {
       
   415         (void)fprintf(stderr, "Couldn't find X Input Context\n");
       
   416         return;
       
   417     }
       
   418     if (req == 1)
       
   419         XSetICFocus(ic);
       
   420     else
       
   421         XUnsetICFocus(ic);
       
   422 }
       
   423 
       
   424 /*
       
   425  * Sets the focus window to the given XIC.
       
   426  */
       
   427 static void
       
   428 setXICWindowFocus(XIC ic, Window w)
       
   429 {
       
   430     if (ic == NULL) {
       
   431         (void)fprintf(stderr, "Couldn't find X Input Context\n");
       
   432         return;
       
   433     }
       
   434     (void) XSetICValues(ic, XNFocusWindow, w, NULL);
       
   435 }
       
   436 
       
   437 /*
       
   438  * Invokes XmbLookupString() to get something from the XIM. It invokes
       
   439  * X11InputMethod.dispatchCommittedText() if XmbLookupString() returns
       
   440  * committed text.  This function is called from handleKeyEvent in canvas.c and
       
   441  * it's under the Motif event loop thread context.
       
   442  *
       
   443  * Buffer usage: There is a bug in XFree86-4.3.0 XmbLookupString implementation,
       
   444  * where it never returns XBufferOverflow.  We need to allocate the initial lookup buffer
       
   445  * big enough, so that the possibility that user encounters this problem is relatively
       
   446  * small.  When this bug gets fixed, we can make the initial buffer size smaller.
       
   447  * Note that XmbLookupString() sometimes produces a non-null-terminated string.
       
   448  *
       
   449  * Returns True when there is a keysym value to be handled.
       
   450  */
       
   451 #define INITIAL_LOOKUP_BUF_SIZE 512
       
   452 
       
   453 Boolean
       
   454 awt_x11inputmethod_lookupString(XKeyPressedEvent *event, KeySym *keysymp)
       
   455 {
       
   456     JNIEnv *env = GetJNIEnv();
       
   457     X11InputMethodData *pX11IMData = NULL;
       
   458     KeySym keysym = NoSymbol;
       
   459     Status status;
       
   460     int mblen;
       
   461     jstring javastr;
       
   462     XIC ic;
       
   463     Boolean result = True;
       
   464     static Boolean composing = False;
       
   465 
       
   466     /*
       
   467       printf("lookupString: entering...\n");
       
   468      */
       
   469 
       
   470     if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) {
       
   471         currentX11InputMethodInstance = NULL;
       
   472         return False;
       
   473     }
       
   474 
       
   475     pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance);
       
   476 
       
   477     if (pX11IMData == NULL) {
       
   478 #if defined(__linux__) || defined(MACOSX)
       
   479         return False;
       
   480 #else
       
   481         return result;
       
   482 #endif
       
   483     }
       
   484 
       
   485     if ((ic = pX11IMData->current_ic) == (XIC)0){
       
   486 #if defined(__linux__) || defined(MACOSX)
       
   487         return False;
       
   488 #else
       
   489         return result;
       
   490 #endif
       
   491     }
       
   492 
       
   493     /* allocate the lookup buffer at the first invocation */
       
   494     if (pX11IMData->lookup_buf_len == 0) {
       
   495         pX11IMData->lookup_buf = (char *)malloc(INITIAL_LOOKUP_BUF_SIZE);
       
   496         if (pX11IMData->lookup_buf == NULL) {
       
   497             THROW_OUT_OF_MEMORY_ERROR();
       
   498             return result;
       
   499         }
       
   500         pX11IMData->lookup_buf_len = INITIAL_LOOKUP_BUF_SIZE;
       
   501     }
       
   502 
       
   503     mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf,
       
   504                             pX11IMData->lookup_buf_len - 1, &keysym, &status);
       
   505 
       
   506     /*
       
   507      * In case of overflow, a buffer is allocated and it retries
       
   508      * XmbLookupString().
       
   509      */
       
   510     if (status == XBufferOverflow) {
       
   511         free((void *)pX11IMData->lookup_buf);
       
   512         pX11IMData->lookup_buf_len = 0;
       
   513         pX11IMData->lookup_buf = (char *)malloc(mblen + 1);
       
   514         if (pX11IMData->lookup_buf == NULL) {
       
   515             THROW_OUT_OF_MEMORY_ERROR();
       
   516             return result;
       
   517         }
       
   518         pX11IMData->lookup_buf_len = mblen + 1;
       
   519         mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf,
       
   520                             pX11IMData->lookup_buf_len - 1, &keysym, &status);
       
   521     }
       
   522     pX11IMData->lookup_buf[mblen] = 0;
       
   523 
       
   524     /* Get keysym without taking modifiers into account first to map
       
   525      * to AWT keyCode table.
       
   526      */
       
   527     switch (status) {
       
   528     case XLookupBoth:
       
   529         if (!composing) {
       
   530             if (event->keycode != 0) {
       
   531                 *keysymp = keysym;
       
   532                 result = False;
       
   533                 break;
       
   534             }
       
   535         }
       
   536         composing = False;
       
   537         /*FALLTHRU*/
       
   538     case XLookupChars:
       
   539     /*
       
   540      printf("lookupString: status=XLookupChars, type=%d, state=%x, keycode=%x, keysym=%x\n",
       
   541        event->type, event->state, event->keycode, keysym);
       
   542     */
       
   543         javastr = JNU_NewStringPlatform(env, (const char *)pX11IMData->lookup_buf);
       
   544         if (javastr != NULL) {
       
   545             JNU_CallMethodByName(env, NULL,
       
   546                                  currentX11InputMethodInstance,
       
   547                                  "dispatchCommittedText",
       
   548                                  "(Ljava/lang/String;J)V",
       
   549                                  javastr,
       
   550                                  event->time);
       
   551         }
       
   552         break;
       
   553 
       
   554     case XLookupKeySym:
       
   555     /*
       
   556      printf("lookupString: status=XLookupKeySym, type=%d, state=%x, keycode=%x, keysym=%x\n",
       
   557        event->type, event->state, event->keycode, keysym);
       
   558     */
       
   559         if (keysym == XK_Multi_key)
       
   560             composing = True;
       
   561         if (! composing) {
       
   562             *keysymp = keysym;
       
   563             result = False;
       
   564         }
       
   565         break;
       
   566 
       
   567     case XLookupNone:
       
   568     /*
       
   569      printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n",
       
   570         event->type, event->state, event->keycode, keysym);
       
   571     */
       
   572         break;
       
   573     }
       
   574 
       
   575     return result;
       
   576 }
       
   577 
       
   578 #if defined(__linux__) || defined(MACOSX)
       
   579 static StatusWindow *createStatusWindow(
       
   580                                 Window parent) {
       
   581     StatusWindow *statusWindow;
       
   582     XSetWindowAttributes attrib;
       
   583     unsigned long attribmask;
       
   584     Window containerWindow;
       
   585     Window status;
       
   586     Window child;
       
   587     XWindowAttributes xwa;
       
   588     XWindowAttributes xxwa;
       
   589     /* Variable for XCreateFontSet()*/
       
   590     char **mclr;
       
   591     int  mccr = 0;
       
   592     char *dsr;
       
   593     unsigned long bg, fg, light, dim;
       
   594     int x, y, off_x, off_y, xx, yy;
       
   595     unsigned int w, h, bw, depth;
       
   596     XGCValues values;
       
   597     unsigned long valuemask = 0;  /*ignore XGCvalue and use defaults*/
       
   598     int screen = 0;
       
   599     int i;
       
   600     AwtGraphicsConfigDataPtr adata;
       
   601     extern int awt_numScreens;
       
   602     /*hardcode the size right now, should get the size base on font*/
       
   603     int   width=80, height=22;
       
   604     Window rootWindow;
       
   605     Window *ignoreWindowPtr;
       
   606     unsigned int ignoreUnit;
       
   607 
       
   608     XGetGeometry(dpy, parent, &rootWindow, &x, &y, &w, &h, &bw, &depth);
       
   609 
       
   610     attrib.override_redirect = True;
       
   611     attribmask = CWOverrideRedirect;
       
   612     for (i = 0; i < awt_numScreens; i++) {
       
   613         if (RootWindow(dpy, i) == rootWindow) {
       
   614             screen = i;
       
   615             break;
       
   616         }
       
   617     }
       
   618     adata = getDefaultConfig(screen);
       
   619     bg    = adata->AwtColorMatch(255, 255, 255, adata);
       
   620     fg    = adata->AwtColorMatch(0, 0, 0, adata);
       
   621     light = adata->AwtColorMatch(195, 195, 195, adata);
       
   622     dim   = adata->AwtColorMatch(128, 128, 128, adata);
       
   623 
       
   624     XGetWindowAttributes(dpy, parent, &xwa);
       
   625     bw = 2; /*xwa.border_width does not have the correct value*/
       
   626 
       
   627     /*compare the size difference between parent container
       
   628       and shell widget, the diff should be the border frame
       
   629       and title bar height (?)*/
       
   630 
       
   631     XQueryTree( dpy,
       
   632                 parent,
       
   633                 &rootWindow,
       
   634                 &containerWindow,
       
   635                 &ignoreWindowPtr,
       
   636                 &ignoreUnit);
       
   637     XGetWindowAttributes(dpy, containerWindow, &xxwa);
       
   638 
       
   639     off_x = (xxwa.width - xwa.width) / 2;
       
   640     off_y = xxwa.height - xwa.height - off_x; /*it's magic:-) */
       
   641 
       
   642     /*get the size of root window*/
       
   643     XGetWindowAttributes(dpy, rootWindow, &xxwa);
       
   644 
       
   645     XTranslateCoordinates(dpy,
       
   646                           parent, xwa.root,
       
   647                           xwa.x, xwa.y,
       
   648                           &x, &y,
       
   649                           &child);
       
   650     xx = x - off_x;
       
   651     yy = y + xwa.height - off_y;
       
   652     if (xx < 0 ){
       
   653         xx = 0;
       
   654     }
       
   655     if (xx + width > xxwa.width){
       
   656         xx = xxwa.width - width;
       
   657     }
       
   658     if (yy + height > xxwa.height){
       
   659         yy = xxwa.height - height;
       
   660     }
       
   661 
       
   662     status =  XCreateWindow(dpy,
       
   663                             xwa.root,
       
   664                             xx, yy,
       
   665                             width, height,
       
   666                             0,
       
   667                             xwa.depth,
       
   668                             InputOutput,
       
   669                             adata->awt_visInfo.visual,
       
   670                             attribmask, &attrib);
       
   671     XSelectInput(dpy, status,
       
   672                  ExposureMask | StructureNotifyMask | EnterWindowMask |
       
   673                  LeaveWindowMask | VisibilityChangeMask);
       
   674     statusWindow = (StatusWindow*) calloc(1, sizeof(StatusWindow));
       
   675     if (statusWindow == NULL){
       
   676         THROW_OUT_OF_MEMORY_ERROR();
       
   677         return NULL;
       
   678     }
       
   679     statusWindow->w = status;
       
   680     //12-point font
       
   681     statusWindow->fontset = XCreateFontSet(dpy,
       
   682                                            "-*-*-medium-r-normal-*-*-120-*-*-*-*",
       
   683                                            &mclr, &mccr, &dsr);
       
   684     /* In case we didn't find the font set, release the list of missing characters */
       
   685     if (mccr > 0) {
       
   686         XFreeStringList(mclr);
       
   687     }
       
   688     statusWindow->parent = parent;
       
   689     statusWindow->on  = False;
       
   690     statusWindow->x = x;
       
   691     statusWindow->y = y;
       
   692     statusWindow->width = xwa.width;
       
   693     statusWindow->height = xwa.height;
       
   694     statusWindow->off_x = off_x;
       
   695     statusWindow->off_y = off_y;
       
   696     statusWindow->bWidth  = bw;
       
   697     statusWindow->statusH = height;
       
   698     statusWindow->statusW = width;
       
   699     statusWindow->rootH = xxwa.height;
       
   700     statusWindow->rootW = xxwa.width;
       
   701     statusWindow->lightGC = XCreateGC(dpy, status, valuemask, &values);
       
   702     XSetForeground(dpy, statusWindow->lightGC, light);
       
   703     statusWindow->dimGC = XCreateGC(dpy, status, valuemask, &values);
       
   704     XSetForeground(dpy, statusWindow->dimGC, dim);
       
   705     statusWindow->fgGC = XCreateGC(dpy, status, valuemask, &values);
       
   706     XSetForeground(dpy, statusWindow->fgGC, fg);
       
   707     statusWindow->bgGC = XCreateGC(dpy, status, valuemask, &values);
       
   708     XSetForeground(dpy, statusWindow->bgGC, bg);
       
   709     return statusWindow;
       
   710 }
       
   711 
       
   712 /* This method is to turn off or turn on the status window. */
       
   713 static void onoffStatusWindow(X11InputMethodData* pX11IMData,
       
   714                                 Window parent,
       
   715                                 Bool ON){
       
   716     XWindowAttributes xwa;
       
   717     Window child;
       
   718     int x, y;
       
   719     StatusWindow *statusWindow = NULL;
       
   720 
       
   721     if (NULL == currentX11InputMethodInstance ||
       
   722         NULL == pX11IMData ||
       
   723         NULL == (statusWindow =  pX11IMData->statusWindow)){
       
   724         return;
       
   725     }
       
   726 
       
   727     if (ON == False){
       
   728         XUnmapWindow(dpy, statusWindow->w);
       
   729         statusWindow->on = False;
       
   730         return;
       
   731     }
       
   732     parent = JNU_CallMethodByName(GetJNIEnv(), NULL, pX11IMData->x11inputmethod,
       
   733                                   "getCurrentParentWindow",
       
   734                                   "()J").j;
       
   735     if (statusWindow->parent != parent){
       
   736         statusWindow->parent = parent;
       
   737     }
       
   738     XGetWindowAttributes(dpy, parent, &xwa);
       
   739     XTranslateCoordinates(dpy,
       
   740                           parent, xwa.root,
       
   741                           xwa.x, xwa.y,
       
   742                           &x, &y,
       
   743                           &child);
       
   744     if (statusWindow->x != x
       
   745         || statusWindow->y != y
       
   746         || statusWindow->height != xwa.height){
       
   747         statusWindow->x = x;
       
   748         statusWindow->y = y;
       
   749         statusWindow->height = xwa.height;
       
   750         x = statusWindow->x - statusWindow->off_x;
       
   751         y = statusWindow->y + statusWindow->height - statusWindow->off_y;
       
   752         if (x < 0 ){
       
   753             x = 0;
       
   754         }
       
   755         if (x + statusWindow->statusW > statusWindow->rootW){
       
   756             x = statusWindow->rootW - statusWindow->statusW;
       
   757         }
       
   758         if (y + statusWindow->statusH > statusWindow->rootH){
       
   759             y = statusWindow->rootH - statusWindow->statusH;
       
   760         }
       
   761         XMoveWindow(dpy, statusWindow->w, x, y);
       
   762     }
       
   763     statusWindow->on = True;
       
   764     XMapWindow(dpy, statusWindow->w);
       
   765 }
       
   766 
       
   767 void paintStatusWindow(StatusWindow *statusWindow){
       
   768     Window  win  = statusWindow->w;
       
   769     GC  lightgc = statusWindow->lightGC;
       
   770     GC  dimgc = statusWindow->dimGC;
       
   771     GC  bggc = statusWindow->bgGC;
       
   772     GC  fggc = statusWindow->fgGC;
       
   773 
       
   774     int width = statusWindow->statusW;
       
   775     int height = statusWindow->statusH;
       
   776     int bwidth = statusWindow->bWidth;
       
   777     XFillRectangle(dpy, win, bggc, 0, 0, width, height);
       
   778     /* draw border */
       
   779     XDrawLine(dpy, win, fggc, 0, 0, width, 0);
       
   780     XDrawLine(dpy, win, fggc, 0, height-1, width-1, height-1);
       
   781     XDrawLine(dpy, win, fggc, 0, 0, 0, height-1);
       
   782     XDrawLine(dpy, win, fggc, width-1, 0, width-1, height-1);
       
   783 
       
   784     XDrawLine(dpy, win, lightgc, 1, 1, width-bwidth, 1);
       
   785     XDrawLine(dpy, win, lightgc, 1, 1, 1, height-2);
       
   786     XDrawLine(dpy, win, lightgc, 1, height-2, width-bwidth, height-2);
       
   787     XDrawLine(dpy, win, lightgc, width-bwidth-1, 1, width-bwidth-1, height-2);
       
   788 
       
   789     XDrawLine(dpy, win, dimgc, 2, 2, 2, height-3);
       
   790     XDrawLine(dpy, win, dimgc, 2, height-3, width-bwidth-1, height-3);
       
   791     XDrawLine(dpy, win, dimgc, 2, 2, width-bwidth-2, 2);
       
   792     XDrawLine(dpy, win, dimgc, width-bwidth, 2, width-bwidth, height-3);
       
   793     if (statusWindow->fontset){
       
   794         XmbDrawString(dpy, win, statusWindow->fontset, fggc,
       
   795                       bwidth + 2, height - bwidth - 4,
       
   796                       statusWindow->status,
       
   797                       strlen(statusWindow->status));
       
   798     }
       
   799     else{
       
   800         /*too bad we failed to create a fontset for this locale*/
       
   801         XDrawString(dpy, win, fggc, bwidth + 2, height - bwidth - 4,
       
   802                     "[InputMethod ON]", strlen("[InputMethod ON]"));
       
   803     }
       
   804 }
       
   805 
       
   806 void statusWindowEventHandler(XEvent event){
       
   807     JNIEnv *env = GetJNIEnv();
       
   808     X11InputMethodData *pX11IMData = NULL;
       
   809     StatusWindow *statusWindow;
       
   810 
       
   811     if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) {
       
   812         currentX11InputMethodInstance = NULL;
       
   813         return;
       
   814     }
       
   815 
       
   816     if (NULL == currentX11InputMethodInstance
       
   817         || NULL == (pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance))
       
   818         || NULL == (statusWindow = pX11IMData->statusWindow)
       
   819         || statusWindow->w != event.xany.window){
       
   820         return;
       
   821     }
       
   822 
       
   823     switch (event.type){
       
   824     case Expose:
       
   825         paintStatusWindow(statusWindow);
       
   826         break;
       
   827     case MapNotify:
       
   828     case ConfigureNotify:
       
   829         {
       
   830           /*need to reset the stackMode...*/
       
   831             XWindowChanges xwc;
       
   832             int value_make = CWStackMode;
       
   833             xwc.stack_mode = TopIf;
       
   834             XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
       
   835         }
       
   836         break;
       
   837         /*
       
   838     case UnmapNotify:
       
   839     case VisibilityNotify:
       
   840         break;
       
   841         */
       
   842     default:
       
   843         break;
       
   844   }
       
   845 }
       
   846 
       
   847 static void adjustStatusWindow(Window shell){
       
   848     JNIEnv *env = GetJNIEnv();
       
   849     X11InputMethodData *pX11IMData = NULL;
       
   850     StatusWindow *statusWindow;
       
   851 
       
   852     if (NULL == currentX11InputMethodInstance
       
   853         || !isX11InputMethodGRefInList(currentX11InputMethodInstance)
       
   854         || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))
       
   855         || NULL == (statusWindow = pX11IMData->statusWindow)
       
   856         || !statusWindow->on) {
       
   857         return;
       
   858     }
       
   859     {
       
   860         XWindowAttributes xwa;
       
   861         int x, y;
       
   862         Window child;
       
   863         XGetWindowAttributes(dpy, shell, &xwa);
       
   864         XTranslateCoordinates(dpy,
       
   865                               shell, xwa.root,
       
   866                               xwa.x, xwa.y,
       
   867                               &x, &y,
       
   868                               &child);
       
   869         if (statusWindow->x != x
       
   870             || statusWindow->y != y
       
   871             || statusWindow->height != xwa.height){
       
   872           statusWindow->x = x;
       
   873           statusWindow->y = y;
       
   874           statusWindow->height = xwa.height;
       
   875 
       
   876           x = statusWindow->x - statusWindow->off_x;
       
   877           y = statusWindow->y + statusWindow->height - statusWindow->off_y;
       
   878           if (x < 0 ){
       
   879               x = 0;
       
   880           }
       
   881           if (x + statusWindow->statusW > statusWindow->rootW){
       
   882               x = statusWindow->rootW - statusWindow->statusW;
       
   883           }
       
   884           if (y + statusWindow->statusH > statusWindow->rootH){
       
   885               y = statusWindow->rootH - statusWindow->statusH;
       
   886           }
       
   887           XMoveWindow(dpy, statusWindow->w, x, y);
       
   888         }
       
   889     }
       
   890 }
       
   891 #endif  /* __linux__ || MACOSX */
       
   892 /*
       
   893  * Creates two XICs, one for active clients and the other for passive
       
   894  * clients. All information on those XICs are stored in the
       
   895  * X11InputMethodData given by the pX11IMData parameter.
       
   896  *
       
   897  * For active clients: Try to use preedit callback to support
       
   898  * on-the-spot. If tc is not null, the XIC to be created will
       
   899  * share the Status Area with Motif widgets (TextComponents). If the
       
   900  * preferable styles can't be used, fallback to root-window styles. If
       
   901  * root-window styles failed, fallback to None styles.
       
   902  *
       
   903  * For passive clients: Try to use root-window styles. If failed,
       
   904  * fallback to None styles.
       
   905  */
       
   906 static Bool
       
   907 createXIC(JNIEnv * env, X11InputMethodData *pX11IMData, Window w)
       
   908 {
       
   909     XVaNestedList preedit = NULL;
       
   910     XVaNestedList status = NULL;
       
   911     XIMStyle on_the_spot_styles = XIMPreeditCallbacks,
       
   912              active_styles = 0,
       
   913              passive_styles = 0,
       
   914              no_styles = 0;
       
   915     XIMCallback *callbacks;
       
   916     unsigned short i;
       
   917     XIMStyles *im_styles;
       
   918     char *ret = NULL;
       
   919 
       
   920     if (X11im == NULL) {
       
   921         return False;
       
   922     }
       
   923     if (!w) {
       
   924         return False;
       
   925     }
       
   926 
       
   927     ret = XGetIMValues(X11im, XNQueryInputStyle, &im_styles, NULL);
       
   928 
       
   929     if (ret != NULL) {
       
   930         jio_fprintf(stderr,"XGetIMValues: %s\n",ret);
       
   931         return FALSE ;
       
   932     }
       
   933 
       
   934 #if defined(__linux__) || defined(MACOSX)
       
   935     on_the_spot_styles |= XIMStatusNothing;
       
   936 
       
   937     /*kinput does not support XIMPreeditCallbacks and XIMStatusArea
       
   938       at the same time, so use StatusCallback to draw the status
       
   939       ourself
       
   940     */
       
   941     for (i = 0; i < im_styles->count_styles; i++) {
       
   942         if (im_styles->supported_styles[i] == (XIMPreeditCallbacks | XIMStatusCallbacks)) {
       
   943             on_the_spot_styles = (XIMPreeditCallbacks | XIMStatusCallbacks);
       
   944             break;
       
   945         }
       
   946     }
       
   947 #else /*! __linux__ && !MACOSX */
       
   948     on_the_spot_styles |= XIMStatusNothing;
       
   949 #endif /* __linux__ || MACOSX */
       
   950 
       
   951     for (i = 0; i < im_styles->count_styles; i++) {
       
   952         active_styles |= im_styles->supported_styles[i] & on_the_spot_styles;
       
   953         passive_styles |= im_styles->supported_styles[i] & ROOT_WINDOW_STYLES;
       
   954         no_styles |= im_styles->supported_styles[i] & NO_STYLES;
       
   955     }
       
   956 
       
   957     XFree(im_styles);
       
   958 
       
   959     if (active_styles != on_the_spot_styles) {
       
   960         if (passive_styles == ROOT_WINDOW_STYLES)
       
   961             active_styles = passive_styles;
       
   962         else {
       
   963             if (no_styles == NO_STYLES)
       
   964                 active_styles = passive_styles = NO_STYLES;
       
   965             else
       
   966                 active_styles = passive_styles = 0;
       
   967         }
       
   968     } else {
       
   969         if (passive_styles != ROOT_WINDOW_STYLES) {
       
   970             if (no_styles == NO_STYLES)
       
   971                 active_styles = passive_styles = NO_STYLES;
       
   972             else
       
   973                 active_styles = passive_styles = 0;
       
   974         }
       
   975     }
       
   976 
       
   977     if (active_styles == on_the_spot_styles) {
       
   978         pX11IMData->ic_passive = XCreateIC(X11im,
       
   979                                    XNClientWindow, w,
       
   980                                    XNFocusWindow, w,
       
   981                                    XNInputStyle, passive_styles,
       
   982                                    NULL);
       
   983 
       
   984         callbacks = (XIMCallback *)malloc(sizeof(XIMCallback) * NCALLBACKS);
       
   985         if (callbacks == (XIMCallback *)NULL)
       
   986             return False;
       
   987         pX11IMData->callbacks = callbacks;
       
   988 
       
   989         for (i = 0; i < NCALLBACKS; i++, callbacks++) {
       
   990             callbacks->client_data = (XPointer) pX11IMData->x11inputmethod;
       
   991             callbacks->callback = callback_funcs[i];
       
   992         }
       
   993 
       
   994         callbacks = pX11IMData->callbacks;
       
   995         preedit = (XVaNestedList)XVaCreateNestedList(0,
       
   996                         XNPreeditStartCallback, &callbacks[PreeditStartIndex],
       
   997                         XNPreeditDoneCallback,  &callbacks[PreeditDoneIndex],
       
   998                         XNPreeditDrawCallback,  &callbacks[PreeditDrawIndex],
       
   999                         XNPreeditCaretCallback, &callbacks[PreeditCaretIndex],
       
  1000                         NULL);
       
  1001         if (preedit == (XVaNestedList)NULL)
       
  1002             goto err;
       
  1003 #if defined(__linux__) || defined(MACOSX)
       
  1004         /*always try XIMStatusCallbacks for active client...*/
       
  1005         {
       
  1006             status = (XVaNestedList)XVaCreateNestedList(0,
       
  1007                         XNStatusStartCallback, &callbacks[StatusStartIndex],
       
  1008                         XNStatusDoneCallback,  &callbacks[StatusDoneIndex],
       
  1009                         XNStatusDrawCallback, &callbacks[StatusDrawIndex],
       
  1010                         NULL);
       
  1011 
       
  1012             if (status == NULL)
       
  1013                 goto err;
       
  1014             pX11IMData->statusWindow = createStatusWindow(w);
       
  1015             pX11IMData->ic_active = XCreateIC(X11im,
       
  1016                                               XNClientWindow, w,
       
  1017                                               XNFocusWindow, w,
       
  1018                                               XNInputStyle, active_styles,
       
  1019                                               XNPreeditAttributes, preedit,
       
  1020                                               XNStatusAttributes, status,
       
  1021                                               NULL);
       
  1022             XFree((void *)status);
       
  1023             XFree((void *)preedit);
       
  1024         }
       
  1025 #else /* !__linux__ && !MACOSX */
       
  1026             pX11IMData->ic_active = XCreateIC(X11im,
       
  1027                                               XNClientWindow, w,
       
  1028                                               XNFocusWindow, w,
       
  1029                                               XNInputStyle, active_styles,
       
  1030                                               XNPreeditAttributes, preedit,
       
  1031                                               NULL);
       
  1032         XFree((void *)preedit);
       
  1033 #endif /* __linux__ || MACOSX */
       
  1034     } else {
       
  1035         pX11IMData->ic_active = XCreateIC(X11im,
       
  1036                                           XNClientWindow, w,
       
  1037                                           XNFocusWindow, w,
       
  1038                                           XNInputStyle, active_styles,
       
  1039                                           NULL);
       
  1040         pX11IMData->ic_passive = pX11IMData->ic_active;
       
  1041     }
       
  1042 
       
  1043     if (pX11IMData->ic_active == (XIC)0
       
  1044         || pX11IMData->ic_passive == (XIC)0) {
       
  1045         return False;
       
  1046     }
       
  1047 
       
  1048     /*
       
  1049      * Use commit string call back if possible.
       
  1050      * This will ensure the correct order of preedit text and commit text
       
  1051      */
       
  1052     {
       
  1053         XIMCallback cb;
       
  1054         cb.client_data = (XPointer) pX11IMData->x11inputmethod;
       
  1055         cb.callback = (XIMProc) CommitStringCallback;
       
  1056         XSetICValues (pX11IMData->ic_active, XNCommitStringCallback, &cb, NULL);
       
  1057         if (pX11IMData->ic_active != pX11IMData->ic_passive) {
       
  1058             XSetICValues (pX11IMData->ic_passive, XNCommitStringCallback, &cb, NULL);
       
  1059         }
       
  1060     }
       
  1061 
       
  1062     /* Add the global reference object to X11InputMethod to the list. */
       
  1063     addToX11InputMethodGRefList(pX11IMData->x11inputmethod);
       
  1064 
       
  1065     return True;
       
  1066 
       
  1067  err:
       
  1068     if (preedit)
       
  1069         XFree((void *)preedit);
       
  1070     THROW_OUT_OF_MEMORY_ERROR();
       
  1071     return False;
       
  1072 }
       
  1073 
       
  1074 static void
       
  1075 PreeditStartCallback(XIC ic, XPointer client_data, XPointer call_data)
       
  1076 {
       
  1077     /*ARGSUSED*/
       
  1078     /* printf("Native: PreeditCaretCallback\n"); */
       
  1079 }
       
  1080 
       
  1081 static void
       
  1082 PreeditDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
       
  1083 {
       
  1084     /*ARGSUSED*/
       
  1085     /* printf("Native: StatusStartCallback\n"); */
       
  1086 }
       
  1087 
       
  1088 /*
       
  1089  * Translate the preedit draw callback items to Java values and invoke
       
  1090  * X11InputMethod.dispatchComposedText().
       
  1091  *
       
  1092  * client_data: X11InputMethod object
       
  1093  */
       
  1094 static void
       
  1095 PreeditDrawCallback(XIC ic, XPointer client_data,
       
  1096                     XIMPreeditDrawCallbackStruct *pre_draw)
       
  1097 {
       
  1098     JNIEnv *env = GetJNIEnv();
       
  1099     X11InputMethodData *pX11IMData = NULL;
       
  1100     jmethodID x11imMethodID;
       
  1101 
       
  1102     XIMText *text;
       
  1103     jstring javastr = NULL;
       
  1104     jintArray style = NULL;
       
  1105 
       
  1106     /* printf("Native: PreeditDrawCallback() \n"); */
       
  1107     if (pre_draw == NULL) {
       
  1108         return;
       
  1109     }
       
  1110     AWT_LOCK();
       
  1111     if (!isX11InputMethodGRefInList((jobject)client_data)) {
       
  1112         if ((jobject)client_data == currentX11InputMethodInstance) {
       
  1113             currentX11InputMethodInstance = NULL;
       
  1114         }
       
  1115         goto finally;
       
  1116     }
       
  1117     if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {
       
  1118         goto finally;
       
  1119     }
       
  1120 
       
  1121     if ((text = pre_draw->text) != NULL) {
       
  1122         if (text->string.multi_byte != NULL) {
       
  1123             if (pre_draw->text->encoding_is_wchar == False) {
       
  1124                 javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte);
       
  1125                 if (javastr == NULL) {
       
  1126                     goto finally;
       
  1127                 }
       
  1128             } else {
       
  1129                 char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
       
  1130                 if (mbstr == NULL) {
       
  1131                     goto finally;
       
  1132                 }
       
  1133                 javastr = JNU_NewStringPlatform(env, (const char *)mbstr);
       
  1134                 free(mbstr);
       
  1135                 if (javastr == NULL) {
       
  1136                     goto finally;
       
  1137                 }
       
  1138             }
       
  1139         }
       
  1140         if (text->feedback != NULL) {
       
  1141             int cnt;
       
  1142             jint *tmpstyle;
       
  1143 
       
  1144             style = (*env)->NewIntArray(env, text->length);
       
  1145             if (JNU_IsNull(env, style)) {
       
  1146                 (*env)->ExceptionClear(env);
       
  1147                 THROW_OUT_OF_MEMORY_ERROR();
       
  1148                 goto finally;
       
  1149             }
       
  1150 
       
  1151             if (sizeof(XIMFeedback) == sizeof(jint)) {
       
  1152                 /*
       
  1153                  * Optimization to avoid copying the array
       
  1154                  */
       
  1155                 (*env)->SetIntArrayRegion(env, style, 0,
       
  1156                                           text->length, (jint *)text->feedback);
       
  1157             } else {
       
  1158                 tmpstyle  = (jint *)malloc(sizeof(jint)*(text->length));
       
  1159                 if (tmpstyle == (jint *) NULL) {
       
  1160                     THROW_OUT_OF_MEMORY_ERROR();
       
  1161                     goto finally;
       
  1162                 }
       
  1163                 for (cnt = 0; cnt < (int)text->length; cnt++)
       
  1164                         tmpstyle[cnt] = text->feedback[cnt];
       
  1165                 (*env)->SetIntArrayRegion(env, style, 0,
       
  1166                                           text->length, (jint *)tmpstyle);
       
  1167             }
       
  1168         }
       
  1169     }
       
  1170     JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
       
  1171                          "dispatchComposedText",
       
  1172                          "(Ljava/lang/String;[IIIIJ)V",
       
  1173                          javastr,
       
  1174                          style,
       
  1175                          (jint)pre_draw->chg_first,
       
  1176                          (jint)pre_draw->chg_length,
       
  1177                          (jint)pre_draw->caret,
       
  1178                          awt_util_nowMillisUTC());
       
  1179 finally:
       
  1180     AWT_UNLOCK();
       
  1181     return;
       
  1182 }
       
  1183 
       
  1184 static void
       
  1185 PreeditCaretCallback(XIC ic, XPointer client_data,
       
  1186                      XIMPreeditCaretCallbackStruct *pre_caret)
       
  1187 {
       
  1188     /*ARGSUSED*/
       
  1189     /* printf("Native: PreeditCaretCallback\n"); */
       
  1190 
       
  1191 }
       
  1192 
       
  1193 #if defined(__linux__) || defined(MACOSX)
       
  1194 static void
       
  1195 StatusStartCallback(XIC ic, XPointer client_data, XPointer call_data)
       
  1196 {
       
  1197     /*ARGSUSED*/
       
  1198     /*printf("StatusStartCallback:\n");  */
       
  1199 
       
  1200 }
       
  1201 
       
  1202 static void
       
  1203 StatusDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
       
  1204 {
       
  1205     /*ARGSUSED*/
       
  1206     /*printf("StatusDoneCallback:\n"); */
       
  1207 
       
  1208 }
       
  1209 
       
  1210 static void
       
  1211 StatusDrawCallback(XIC ic, XPointer client_data,
       
  1212                      XIMStatusDrawCallbackStruct *status_draw)
       
  1213 {
       
  1214     /*ARGSUSED*/
       
  1215     /*printf("StatusDrawCallback:\n"); */
       
  1216     JNIEnv *env = GetJNIEnv();
       
  1217     X11InputMethodData *pX11IMData = NULL;
       
  1218     StatusWindow *statusWindow;
       
  1219 
       
  1220     AWT_LOCK();
       
  1221 
       
  1222     if (!isX11InputMethodGRefInList((jobject)client_data)) {
       
  1223         if ((jobject)client_data == currentX11InputMethodInstance) {
       
  1224             currentX11InputMethodInstance = NULL;
       
  1225         }
       
  1226         goto finally;
       
  1227     }
       
  1228 
       
  1229     if (NULL == (pX11IMData = getX11InputMethodData(env, (jobject)client_data))
       
  1230         || NULL == (statusWindow = pX11IMData->statusWindow)){
       
  1231         goto finally;
       
  1232     }
       
  1233    currentX11InputMethodInstance = (jobject)client_data;
       
  1234 
       
  1235     if (status_draw->type == XIMTextType){
       
  1236         XIMText *text = (status_draw->data).text;
       
  1237         if (text != NULL){
       
  1238           if (text->string.multi_byte != NULL) {
       
  1239               strncpy(statusWindow->status, text->string.multi_byte, MAX_STATUS_LEN);
       
  1240               statusWindow->status[MAX_STATUS_LEN - 1] = '\0';
       
  1241           }
       
  1242           else {
       
  1243               char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
       
  1244               strncpy(statusWindow->status, mbstr, MAX_STATUS_LEN);
       
  1245               statusWindow->status[MAX_STATUS_LEN - 1] = '\0';
       
  1246           }
       
  1247           statusWindow->on = True;
       
  1248           onoffStatusWindow(pX11IMData, statusWindow->parent, True);
       
  1249           paintStatusWindow(statusWindow);
       
  1250         }
       
  1251         else {
       
  1252             statusWindow->on = False;
       
  1253             /*just turnoff the status window
       
  1254             paintStatusWindow(statusWindow);
       
  1255             */
       
  1256             onoffStatusWindow(pX11IMData, 0, False);
       
  1257         }
       
  1258     }
       
  1259 
       
  1260  finally:
       
  1261     AWT_UNLOCK();
       
  1262 }
       
  1263 #endif /* __linux__ || MACOSX */
       
  1264 
       
  1265 static void CommitStringCallback(XIC ic, XPointer client_data, XPointer call_data) {
       
  1266     JNIEnv *env = GetJNIEnv();
       
  1267     XIMText * text = (XIMText *)call_data;
       
  1268     X11InputMethodData *pX11IMData = NULL;
       
  1269     jstring javastr;
       
  1270 
       
  1271     AWT_LOCK();
       
  1272 
       
  1273     if (!isX11InputMethodGRefInList((jobject)client_data)) {
       
  1274         if ((jobject)client_data == currentX11InputMethodInstance) {
       
  1275             currentX11InputMethodInstance = NULL;
       
  1276         }
       
  1277         goto finally;
       
  1278     }
       
  1279 
       
  1280     if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {
       
  1281         goto finally;
       
  1282     }
       
  1283     currentX11InputMethodInstance = (jobject)client_data;
       
  1284 
       
  1285     if (text->encoding_is_wchar == False) {
       
  1286         javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte);
       
  1287     } else {
       
  1288         char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
       
  1289         if (mbstr == NULL) {
       
  1290             goto finally;
       
  1291         }
       
  1292         javastr = JNU_NewStringPlatform(env, (const char *)mbstr);
       
  1293         free(mbstr);
       
  1294     }
       
  1295 
       
  1296     if (javastr != NULL) {
       
  1297         JNU_CallMethodByName(env, NULL,
       
  1298                                  pX11IMData->x11inputmethod,
       
  1299                                  "dispatchCommittedText",
       
  1300                                  "(Ljava/lang/String;J)V",
       
  1301                                  javastr,
       
  1302                                  awt_util_nowMillisUTC());
       
  1303     }
       
  1304  finally:
       
  1305     AWT_UNLOCK();
       
  1306 }
       
  1307 
       
  1308 static void OpenXIMCallback(Display *display, XPointer client_data, XPointer call_data) {
       
  1309     XIMCallback ximCallback;
       
  1310 
       
  1311     X11im = XOpenIM(display, NULL, NULL, NULL);
       
  1312     if (X11im == NULL) {
       
  1313         return;
       
  1314     }
       
  1315 
       
  1316     ximCallback.callback = (XIMProc)DestroyXIMCallback;
       
  1317     ximCallback.client_data = NULL;
       
  1318     XSetIMValues(X11im, XNDestroyCallback, &ximCallback, NULL);
       
  1319 }
       
  1320 
       
  1321 static void DestroyXIMCallback(XIM im, XPointer client_data, XPointer call_data) {
       
  1322     /* mark that XIM server was destroyed */
       
  1323     X11im = NULL;
       
  1324     JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
       
  1325     /* free the old pX11IMData and set it to null. this also avoids crashing
       
  1326      * the jvm if the XIM server reappears */
       
  1327     X11InputMethodData *pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance);
       
  1328 }
       
  1329 
       
  1330 /*
       
  1331  * Class:     sun_awt_X11InputMethod
       
  1332  * Method:    initIDs
       
  1333  * Signature: ()V
       
  1334  */
       
  1335 
       
  1336 /* This function gets called from the static initializer for
       
  1337    X11InputMethod.java
       
  1338    to initialize the fieldIDs for fields that may be accessed from C */
       
  1339 JNIEXPORT void JNICALL
       
  1340 Java_sun_awt_X11InputMethod_initIDs(JNIEnv *env, jclass cls)
       
  1341 {
       
  1342     x11InputMethodIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J");
       
  1343 }
       
  1344 
       
  1345 
       
  1346 JNIEXPORT jboolean JNICALL
       
  1347 Java_sun_awt_X11_XInputMethod_openXIMNative(JNIEnv *env,
       
  1348                                           jobject this,
       
  1349                                           jlong display)
       
  1350 {
       
  1351     Bool registered;
       
  1352 
       
  1353     AWT_LOCK();
       
  1354 
       
  1355     dpy = (Display *)jlong_to_ptr(display);
       
  1356 
       
  1357 /* Use IMInstantiate call back only on Linux, as there is a bug in Solaris
       
  1358    (4768335)
       
  1359 */
       
  1360 #if defined(__linux__) || defined(MACOSX)
       
  1361     registered = XRegisterIMInstantiateCallback(dpy, NULL, NULL,
       
  1362                      NULL, (XIDProc)OpenXIMCallback, NULL);
       
  1363     if (!registered) {
       
  1364         /* directly call openXIM callback */
       
  1365 #endif
       
  1366         OpenXIMCallback(dpy, NULL, NULL);
       
  1367 #if defined(__linux__) || defined(MACOSX)
       
  1368     }
       
  1369 #endif
       
  1370 
       
  1371     AWT_UNLOCK();
       
  1372 
       
  1373     return JNI_TRUE;
       
  1374 }
       
  1375 
       
  1376 JNIEXPORT jboolean JNICALL
       
  1377 Java_sun_awt_X11_XInputMethod_createXICNative(JNIEnv *env,
       
  1378                                                   jobject this,
       
  1379                                                   jlong window)
       
  1380 {
       
  1381     X11InputMethodData *pX11IMData;
       
  1382     jobject globalRef;
       
  1383     XIC ic;
       
  1384 
       
  1385     AWT_LOCK();
       
  1386 
       
  1387     if (!window) {
       
  1388         JNU_ThrowNullPointerException(env, "NullPointerException");
       
  1389         AWT_UNLOCK();
       
  1390         return JNI_FALSE;
       
  1391     }
       
  1392 
       
  1393     pX11IMData = (X11InputMethodData *) calloc(1, sizeof(X11InputMethodData));
       
  1394     if (pX11IMData == NULL) {
       
  1395         THROW_OUT_OF_MEMORY_ERROR();
       
  1396         AWT_UNLOCK();
       
  1397         return JNI_FALSE;
       
  1398     }
       
  1399 
       
  1400     globalRef = (*env)->NewGlobalRef(env, this);
       
  1401     pX11IMData->x11inputmethod = globalRef;
       
  1402 #if defined(__linux__) || defined(MACOSX)
       
  1403     pX11IMData->statusWindow = NULL;
       
  1404 #endif /* __linux__ || MACOSX */
       
  1405 
       
  1406     pX11IMData->lookup_buf = 0;
       
  1407     pX11IMData->lookup_buf_len = 0;
       
  1408 
       
  1409     if (createXIC(env, pX11IMData, (Window)window) == False) {
       
  1410         destroyX11InputMethodData((JNIEnv *) NULL, pX11IMData);
       
  1411         pX11IMData = (X11InputMethodData *) NULL;
       
  1412         if ((*env)->ExceptionCheck(env)) {
       
  1413             goto finally;
       
  1414         }
       
  1415     }
       
  1416 
       
  1417     setX11InputMethodData(env, this, pX11IMData);
       
  1418 
       
  1419 finally:
       
  1420     AWT_UNLOCK();
       
  1421     return (pX11IMData != NULL);
       
  1422 }
       
  1423 
       
  1424 JNIEXPORT void JNICALL
       
  1425 Java_sun_awt_X11_XInputMethod_setXICFocusNative(JNIEnv *env,
       
  1426                                               jobject this,
       
  1427                                               jlong w,
       
  1428                                               jboolean req,
       
  1429                                               jboolean active)
       
  1430 {
       
  1431     X11InputMethodData *pX11IMData;
       
  1432     AWT_LOCK();
       
  1433     pX11IMData = getX11InputMethodData(env, this);
       
  1434     if (pX11IMData == NULL) {
       
  1435         AWT_UNLOCK();
       
  1436         return;
       
  1437     }
       
  1438 
       
  1439     if (req) {
       
  1440         if (!w) {
       
  1441             AWT_UNLOCK();
       
  1442             return;
       
  1443         }
       
  1444         pX11IMData->current_ic = active ?
       
  1445                         pX11IMData->ic_active : pX11IMData->ic_passive;
       
  1446         /*
       
  1447          * On Solaris2.6, setXICWindowFocus() has to be invoked
       
  1448          * before setting focus.
       
  1449          */
       
  1450         setXICWindowFocus(pX11IMData->current_ic, w);
       
  1451         setXICFocus(pX11IMData->current_ic, req);
       
  1452         currentX11InputMethodInstance = pX11IMData->x11inputmethod;
       
  1453         currentFocusWindow =  w;
       
  1454 #if defined(__linux__) || defined(MACOSX)
       
  1455         if (active && pX11IMData->statusWindow && pX11IMData->statusWindow->on)
       
  1456             onoffStatusWindow(pX11IMData, w, True);
       
  1457 #endif
       
  1458     } else {
       
  1459         currentX11InputMethodInstance = NULL;
       
  1460         currentFocusWindow = 0;
       
  1461 #if defined(__linux__) || defined(MACOSX)
       
  1462         onoffStatusWindow(pX11IMData, 0, False);
       
  1463         if (pX11IMData->current_ic != NULL)
       
  1464 #endif
       
  1465         setXICFocus(pX11IMData->current_ic, req);
       
  1466 
       
  1467         pX11IMData->current_ic = (XIC)0;
       
  1468     }
       
  1469 
       
  1470     XFlush(dpy);
       
  1471     AWT_UNLOCK();
       
  1472 }
       
  1473 
       
  1474 JNIEXPORT void JNICALL
       
  1475 Java_sun_awt_X11InputMethod_turnoffStatusWindow(JNIEnv *env,
       
  1476                                                 jobject this)
       
  1477 {
       
  1478 #if defined(__linux__) || defined(MACOSX)
       
  1479     X11InputMethodData *pX11IMData;
       
  1480     StatusWindow *statusWindow;
       
  1481 
       
  1482     AWT_LOCK();
       
  1483 
       
  1484     if (NULL == currentX11InputMethodInstance
       
  1485         || !isX11InputMethodGRefInList(currentX11InputMethodInstance)
       
  1486         || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))
       
  1487         || NULL == (statusWindow = pX11IMData->statusWindow)
       
  1488         || !statusWindow->on ){
       
  1489         AWT_UNLOCK();
       
  1490         return;
       
  1491     }
       
  1492     onoffStatusWindow(pX11IMData, 0, False);
       
  1493 
       
  1494     AWT_UNLOCK();
       
  1495 #endif
       
  1496 }
       
  1497 
       
  1498 JNIEXPORT void JNICALL
       
  1499 Java_sun_awt_X11InputMethod_disposeXIC(JNIEnv *env,
       
  1500                                              jobject this)
       
  1501 {
       
  1502     X11InputMethodData *pX11IMData = NULL;
       
  1503 
       
  1504     AWT_LOCK();
       
  1505     pX11IMData = getX11InputMethodData(env, this);
       
  1506     if (pX11IMData == NULL) {
       
  1507         AWT_UNLOCK();
       
  1508         return;
       
  1509     }
       
  1510 
       
  1511     setX11InputMethodData(env, this, NULL);
       
  1512 
       
  1513     if (pX11IMData->x11inputmethod == currentX11InputMethodInstance) {
       
  1514         currentX11InputMethodInstance = NULL;
       
  1515         currentFocusWindow = 0;
       
  1516     }
       
  1517     destroyX11InputMethodData(env, pX11IMData);
       
  1518     AWT_UNLOCK();
       
  1519 }
       
  1520 
       
  1521 JNIEXPORT jstring JNICALL
       
  1522 Java_sun_awt_X11InputMethod_resetXIC(JNIEnv *env,
       
  1523                                            jobject this)
       
  1524 {
       
  1525     X11InputMethodData *pX11IMData;
       
  1526     char *xText = NULL;
       
  1527     jstring jText = (jstring)0;
       
  1528 
       
  1529     AWT_LOCK();
       
  1530     pX11IMData = getX11InputMethodData(env, this);
       
  1531     if (pX11IMData == NULL) {
       
  1532         AWT_UNLOCK();
       
  1533         return jText;
       
  1534     }
       
  1535 
       
  1536     if (pX11IMData->current_ic)
       
  1537         xText = XmbResetIC(pX11IMData->current_ic);
       
  1538     else {
       
  1539         /*
       
  1540          * If there is no reference to the current XIC, try to reset both XICs.
       
  1541          */
       
  1542         xText = XmbResetIC(pX11IMData->ic_active);
       
  1543         /*it may also means that the real client component does
       
  1544           not have focus -- has been deactivated... its xic should
       
  1545           not have the focus, bug#4284651 showes reset XIC for htt
       
  1546           may bring the focus back, so de-focus it again.
       
  1547         */
       
  1548         setXICFocus(pX11IMData->ic_active, FALSE);
       
  1549         if (pX11IMData->ic_active != pX11IMData->ic_passive) {
       
  1550             char *tmpText = XmbResetIC(pX11IMData->ic_passive);
       
  1551             setXICFocus(pX11IMData->ic_passive, FALSE);
       
  1552             if (xText == (char *)NULL && tmpText)
       
  1553                 xText = tmpText;
       
  1554         }
       
  1555 
       
  1556     }
       
  1557     if (xText != NULL) {
       
  1558         jText = JNU_NewStringPlatform(env, (const char *)xText);
       
  1559         XFree((void *)xText);
       
  1560     }
       
  1561 
       
  1562     AWT_UNLOCK();
       
  1563     return jText;
       
  1564 }
       
  1565 
       
  1566 /*
       
  1567  * Class:     sun_awt_X11InputMethod
       
  1568  * Method:    setCompositionEnabledNative
       
  1569  * Signature: (ZJ)V
       
  1570  *
       
  1571  * This method tries to set the XNPreeditState attribute associated with the current
       
  1572  * XIC to the passed in 'enable' state.
       
  1573  *
       
  1574  * Return JNI_TRUE if XNPreeditState attribute is successfully changed to the
       
  1575  * 'enable' state; Otherwise, if XSetICValues fails to set this attribute,
       
  1576  * java.lang.UnsupportedOperationException will be thrown. JNI_FALSE is returned if this
       
  1577  * method fails due to other reasons.
       
  1578  *
       
  1579  */
       
  1580 JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethod_setCompositionEnabledNative
       
  1581   (JNIEnv *env, jobject this, jboolean enable)
       
  1582 {
       
  1583     X11InputMethodData *pX11IMData;
       
  1584     char * ret = NULL;
       
  1585 
       
  1586     AWT_LOCK();
       
  1587     pX11IMData = getX11InputMethodData(env, this);
       
  1588 
       
  1589     if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {
       
  1590         AWT_UNLOCK();
       
  1591         return JNI_FALSE;
       
  1592     }
       
  1593 
       
  1594     ret = XSetICValues(pX11IMData->current_ic, XNPreeditState,
       
  1595                        (enable ? XIMPreeditEnable : XIMPreeditDisable), NULL);
       
  1596     AWT_UNLOCK();
       
  1597 
       
  1598     if ((ret != 0) && (strcmp(ret, XNPreeditState) == 0)) {
       
  1599         JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
       
  1600     }
       
  1601 
       
  1602     return (jboolean)(ret == 0);
       
  1603 }
       
  1604 
       
  1605 /*
       
  1606  * Class:     sun_awt_X11InputMethod
       
  1607  * Method:    isCompositionEnabledNative
       
  1608  * Signature: (J)Z
       
  1609  *
       
  1610  * This method tries to get the XNPreeditState attribute associated with the current XIC.
       
  1611  *
       
  1612  * Return JNI_TRUE if the XNPreeditState is successfully retrieved. Otherwise, if
       
  1613  * XGetICValues fails to get this attribute, java.lang.UnsupportedOperationException
       
  1614  * will be thrown. JNI_FALSE is returned if this method fails due to other reasons.
       
  1615  *
       
  1616  */
       
  1617 JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethod_isCompositionEnabledNative
       
  1618   (JNIEnv *env, jobject this)
       
  1619 {
       
  1620     X11InputMethodData *pX11IMData = NULL;
       
  1621     char * ret = NULL;
       
  1622     XIMPreeditState state;
       
  1623 
       
  1624     AWT_LOCK();
       
  1625     pX11IMData = getX11InputMethodData(env, this);
       
  1626 
       
  1627     if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {
       
  1628         AWT_UNLOCK();
       
  1629         return JNI_FALSE;
       
  1630     }
       
  1631 
       
  1632     ret = XGetICValues(pX11IMData->current_ic, XNPreeditState, &state, NULL);
       
  1633     AWT_UNLOCK();
       
  1634 
       
  1635     if ((ret != 0) && (strcmp(ret, XNPreeditState) == 0)) {
       
  1636         JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
       
  1637         return JNI_FALSE;
       
  1638     }
       
  1639 
       
  1640     return (jboolean)(state == XIMPreeditEnable);
       
  1641 }
       
  1642 
       
  1643 JNIEXPORT void JNICALL Java_sun_awt_X11_XInputMethod_adjustStatusWindow
       
  1644   (JNIEnv *env, jobject this, jlong window)
       
  1645 {
       
  1646 #if defined(__linux__) || defined(MACOSX)
       
  1647     AWT_LOCK();
       
  1648     adjustStatusWindow(window);
       
  1649     AWT_UNLOCK();
       
  1650 #endif
       
  1651 }