< 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 /*
   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 *


 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         */


 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 /*


 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);


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 }
   1 /*
   2  * Copyright (c) 1997, 2018, 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 #include "awt.h"
  27 #include "awt_p.h"
  28 
  29 #include <sun_awt_X11InputMethodBase.h>
  30 #include <sun_awt_X11InputMethod.h>
  31 #include <sun_awt_X11_XInputMethod.h>
  32 
  33 #include <langinfo.h>
  34 #include <stdio.h>
  35 #include <stdlib.h>
  36 #include <sys/time.h>
  37 #include <wchar.h>
  38 #include <wctype.h>
  39 #include <X11/Intrinsic.h>
  40 #include <X11/keysym.h>
  41 #include <X11/Xlib.h>
  42 
  43 #ifdef HEADLESS
  44     #error This file should not be included in headless library
  45 #endif
  46 
  47 #define THROW_OUT_OF_MEMORY_ERROR() \
  48         JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL)
  49 
  50 struct X11InputMethodIDs {
  51   jfieldID pData;
  52 } x11InputMethodIDs;
  53 
  54 static int PreeditStartCallback(XIC, XPointer, XPointer);
  55 static void PreeditDoneCallback(XIC, XPointer, XPointer);
  56 static void PreeditDrawCallback(XIC, XPointer,
  57                                 XIMPreeditDrawCallbackStruct *);
  58 static void PreeditCaretCallback(XIC, XPointer,
  59                                  XIMPreeditCaretCallbackStruct *);

  60 static void StatusStartCallback(XIC, XPointer, XPointer);
  61 static void StatusDoneCallback(XIC, XPointer, XPointer);
  62 static void StatusDrawCallback(XIC, XPointer,
  63                                XIMStatusDrawCallbackStruct *);

  64 
  65 #define ROOT_WINDOW_STYLES      (XIMPreeditNothing | XIMStatusNothing)
  66 #define NO_STYLES               (XIMPreeditNone | XIMStatusNone)
  67 /* added style to allow for in-place composition, such as "dead" keys for accents */
  68 #define IN_PLACE_STYLES         (XIMPreeditNothing | XIMStatusNone)
  69 
  70 #define PreeditStartIndex       0
  71 #define PreeditDoneIndex        1
  72 #define PreeditDrawIndex        2
  73 #define PreeditCaretIndex       3

  74 #define StatusStartIndex        4
  75 #define StatusDoneIndex         5
  76 #define StatusDrawIndex         6
  77 #define NCALLBACKS              7
  78 
  79 #define STATUS_BORDER 2         /* Status Border width */
  80 #define CARET_OFFSET 1          /* Offset of caret position (pixel) */
  81 #define BORDER_MARGIN 3         /* BORDER MARGIN width */
  82 #define STATUS_MARGIN 7         /* Margin between the status window and its parent window */
  83 #define PREEDIT_ATTR_MASK (XIMReverse|XIMUnderline)
  84           /* Preedit attribute which host adapter can handle */
  85 
  86 /*
  87  * Callback function pointers: the order has to match the *Index
  88  * values above.
  89  */
  90 static XIMProc callback_funcs[NCALLBACKS] = {
  91     (XIMProc)PreeditStartCallback,
  92     (XIMProc)PreeditDoneCallback,
  93     (XIMProc)PreeditDrawCallback,
  94     (XIMProc)PreeditCaretCallback,

  95     (XIMProc)StatusStartCallback,
  96     (XIMProc)StatusDoneCallback,
  97     (XIMProc)StatusDrawCallback,

  98 };
  99 

 100 #define MAX_STATUS_LEN  100
 101 typedef struct {
 102     Window   w;                /*status window id        */
 103     Window   root;             /*the root window id      */
 104     Window   parent;           /*parent shell window     */
 105     Window   grandParent;      /*window has WM frame     */
 106     int      x, y;             /*parent's upperleft position */
 107     int      width, height;    /*parent's width, height  */
 108     GC       lightGC;          /*gc for light border     */
 109     GC       dimGC;            /*gc for dim border       */
 110     GC       bgGC;             /*normal painting         */
 111     GC       fgGC;             /*normal painting         */
 112     int      statusW, statusH; /*status window's w, h    */
 113     int      rootW, rootH;     /*root window's w, h    */
 114     int      bWidth;           /*border width            */
 115     wchar_t  status[MAX_STATUS_LEN + 1]; /*status text       */
 116     XFontSet fontset;           /*fontset for drawing    */
 117     int      off_x, off_y;
 118     Bool     on;                /*if the status window on*/
 119     int      fOff;              /* font base line(in pixel) from top */
 120     int      fBot;              /* font bottom line(in pixel) from top */
 121     int      peTextW;           /* Composition text width in pixel */
 122     wchar_t* peText;            /* Composed string (wide char.) */
 123     XIMFeedback* peAttr;        /* Composed text attribute */
 124     int      peCaret;           /* Caret position in number of character */
 125     Bool     status_ready;      /* Not draw Status at XCreateIC */
 126 } StatusWindow;

 127 
 128 /*
 129  * X11InputMethodData keeps per X11InputMethod instance information. A pointer
 130  * to this data structure is kept in an X11InputMethod object (pData).
 131  */
 132 typedef struct _X11InputMethodData {
 133     XIC         current_ic;     /* current X Input Context */
 134     XIC         ic_active;      /* X Input Context for active clients */
 135     XIC         ic_passive;     /* X Input Context for passive clients */
 136     XIMCallback *callbacks;     /* callback parameters */
 137     jobject     x11inputmethod; /* global ref to X11InputMethod instance */
 138                                 /* associated with the XIC */

 139     StatusWindow *statusWindow; /* our own status window  */
 140     Bool        passiveStatusWindow;/* Passive Client uses StatusWindow */
 141     Bool        isActiveClient;     /* True:clinet is active */
 142     Bool        forceReset;     /* True: call resetXIC before UnsetICFocus */
 143 } X11InputMethodData;
 144 




















 145 /* reference to the current X11InputMethod instance, it is always
 146    point to the global reference to the X11InputMethodObject since
 147    it could be referenced by different threads. */
 148 jobject currentX11InputMethodInstance = NULL;
 149 
 150 Window  currentFocusWindow = 0;  /* current window that has focus for input
 151                                        method. (the best place to put this
 152                                        information should be
 153                                        currentX11InputMethodInstance's pData) */
 154 static XIM X11im = NULL;
 155 Display * dpy = NULL;
 156 
 157 #define GetJNIEnv() (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2)
 158 






 159 static X11InputMethodData * getX11InputMethodData(JNIEnv *, jobject);
 160 static void setX11InputMethodData(JNIEnv *, jobject, X11InputMethodData *);
 161 static void destroyX11InputMethodData(JNIEnv *, X11InputMethodData *);
 162 static void freeX11InputMethodData(JNIEnv *, X11InputMethodData *);
 163 
 164 /* Prototype for this function is missing in AIX Xlib.h */

 165 extern char *XSetIMValues(
 166 #if NeedVarargsPrototypes
 167     XIM /* im */, ...
 168 #endif
 169 );
 170 
 171 static int st_wcslen(wchar_t *string);
 172 static Bool isPreeditStateActive(XIC ic);
 173 static void * buf_insert(void * src, void * insert, int size,
 174                          int src_len, int ins_len, int offset);
 175 static void * handle_buffer(void * source, void * insert,
 176                             int size, int src_len, int ins_len,
 177                             int del_len, int offset);
 178 static void preedit_draw_passive(X11InputMethodData *pX11IMData,
 179                                  XIMPreeditDrawCallbackStruct *pre_draw);
 180 static void resetPassivePreeditText(StatusWindow *statusWindow);
 181 static void draw_caret(StatusWindow *statusWindow, GC gc, int pos);
 182 static int  get_next_attr(int len, unsigned long *attr);
 183 static void draw_preedit(StatusWindow *statusWindow);
 184 static void align_status(StatusWindow *statusWindow);
 185 static void shrink_status(StatusWindow *statusWindow);
 186 static GC create_gc(Window win, Bool isReverse);
 187 static XFontSet create_fontset(void);
 188 static Bool is_text_available(XIMText * text);
 189 static Bool isNativeIm();
 190 static Window getGrandParent(Window parent);
 191 static void moveStatusWindow(StatusWindow *statusWindow);
 192 static void arrange_window_stack(StatusWindow* statusWindow);
 193 static Window get_current_focus(XIC ic);
 194 
 195 /*
 196  * This function is stolen from /src/solaris/hpi/src/system_md.c
 197  * It is used in setting the time in Java-level InputEvents
 198  */
 199 jlong
 200 awt_util_nowMillisUTC()
 201 {
 202     struct timeval t;
 203     gettimeofday(&t, NULL);
 204     return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000);
 205 }
 206 
 207 /*
 208  * Converts the wchar_t string to a multi-byte string calling wcstombs(). A
 209  * buffer is allocated by malloc() to store the multi-byte string. NULL is
 210  * returned if the given wchar_t string pointer is NULL or buffer allocation is
 211  * failed.
 212  */
 213 static char *


 219     if (wcs == NULL)
 220         return NULL;
 221 
 222     n = len*MB_CUR_MAX + 1;
 223 
 224     mbs = (char *) malloc(n * sizeof(char));
 225     if (mbs == NULL) {
 226         THROW_OUT_OF_MEMORY_ERROR();
 227         return NULL;
 228     }
 229 
 230     /* TODO: check return values... Handle invalid characters properly...  */
 231     if (wcstombs(mbs, wcs, n) == (size_t)-1) {
 232         free(mbs);
 233         return NULL;
 234     }
 235 
 236     return mbs;
 237 }
 238 

















































































 239 static X11InputMethodData * getX11InputMethodData(JNIEnv * env, jobject imInstance) {
 240     X11InputMethodData *pX11IMData =
 241         (X11InputMethodData *)JNU_GetLongFieldAsPtr(env, imInstance, x11InputMethodIDs.pData);
 242 
 243     /*
 244      * In case the XIM server was killed somehow, reset X11InputMethodData.
 245      */
 246     if (X11im == NULL && pX11IMData != NULL) {
 247         JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
 248                              "flushText",
 249                              "()V");
 250         JNU_CHECK_EXCEPTION_RETURN(env, NULL);
 251         /* IMPORTANT:
 252            The order of the following calls is critical since "imInstance" may
 253            point to the global reference itself, if "freeX11InputMethodData" is called
 254            first, the global reference will be destroyed and "setX11InputMethodData"
 255            will in fact fail silently. So pX11IMData will not be set to NULL.
 256            This could make the original java object refers to a deleted pX11IMData
 257            object.
 258         */


 281 
 282     if (pX11IMData->ic_active != (XIC)0) {
 283         XUnsetICFocus(pX11IMData->ic_active);
 284         XDestroyIC(pX11IMData->ic_active);
 285         if (pX11IMData->ic_active != pX11IMData->ic_passive) {
 286             if (pX11IMData->ic_passive != (XIC)0) {
 287                 XUnsetICFocus(pX11IMData->ic_passive);
 288                 XDestroyIC(pX11IMData->ic_passive);
 289             }
 290             pX11IMData->ic_passive = (XIC)0;
 291             pX11IMData->current_ic = (XIC)0;
 292         }
 293     }
 294 
 295     freeX11InputMethodData(env, pX11IMData);
 296 }
 297 
 298 static void
 299 freeX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData)
 300 {

 301     if (pX11IMData->statusWindow != NULL){
 302         StatusWindow *sw = pX11IMData->statusWindow;
 303         XFreeGC(awt_display, sw->lightGC);
 304         XFreeGC(awt_display, sw->dimGC);
 305         XFreeGC(awt_display, sw->bgGC);
 306         XFreeGC(awt_display, sw->fgGC);
 307         if (sw->fontset != NULL) {
 308             XFreeFontSet(awt_display, sw->fontset);
 309         }
 310         XDestroyWindow(awt_display, sw->w);
 311         if (pX11IMData->statusWindow->peText){
 312             free((void *)pX11IMData->statusWindow->peText);
 313             pX11IMData->statusWindow->peText = NULL;
 314         }
 315         if (pX11IMData->statusWindow->peAttr){
 316             free((void *)pX11IMData->statusWindow->peAttr);
 317             pX11IMData->statusWindow->peAttr = NULL;
 318         }
 319         free((void*)sw);
 320     }

 321 
 322     if (pX11IMData->callbacks)
 323         free((void *)pX11IMData->callbacks);
 324 
 325     if (env) {




 326         (*env)->DeleteGlobalRef(env, pX11IMData->x11inputmethod);
 327     }
 328 




 329     free((void *)pX11IMData);
 330 }
 331 
 332 /*
 333  * Sets or unsets the focus to the given XIC.
 334  */
 335 static void
 336 setXICFocus(XIC ic, unsigned short req)
 337 {
 338     if (ic == NULL) {
 339         (void)fprintf(stderr, "Couldn't find X Input Context\n");
 340         return;
 341     }
 342     if (req == 1)
 343         XSetICFocus(ic);
 344     else
 345         XUnsetICFocus(ic);
 346 }
 347 
 348 /*


 362  * Invokes XmbLookupString() to get something from the XIM. It invokes
 363  * X11InputMethod.dispatchCommittedText() if XmbLookupString() returns
 364  * committed text.  This function is called from handleKeyEvent in canvas.c and
 365  * it's under the Motif event loop thread context.
 366  *
 367  * Buffer usage: There is a bug in XFree86-4.3.0 XmbLookupString implementation,
 368  * where it never returns XBufferOverflow.  We need to allocate the initial lookup buffer
 369  * big enough, so that the possibility that user encounters this problem is relatively
 370  * small.  When this bug gets fixed, we can make the initial buffer size smaller.
 371  * Note that XmbLookupString() sometimes produces a non-null-terminated string.
 372  *
 373  * Returns True when there is a keysym value to be handled.
 374  */
 375 #define INITIAL_LOOKUP_BUF_SIZE 512
 376 
 377 Boolean
 378 awt_x11inputmethod_lookupString(XKeyPressedEvent *event, KeySym *keysymp)
 379 {
 380     JNIEnv *env = GetJNIEnv();
 381     X11InputMethodData *pX11IMData = NULL;
 382     int buf_len = INITIAL_LOOKUP_BUF_SIZE;
 383     char mbbuf[INITIAL_LOOKUP_BUF_SIZE];
 384     char *buf;
 385     KeySym keysym = NoSymbol;
 386     Status status;
 387     int mblen;
 388     jstring javastr;
 389     XIC ic;
 390     Boolean result = True;
 391     static Boolean composing = False;
 392 
 393     /*
 394       printf("lookupString: entering...\n");
 395      */
 396 





 397     pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance);
 398 
 399     if (pX11IMData == NULL) {

 400         return False;



 401     }
 402 
 403     if ((ic = pX11IMData->current_ic) == (XIC)0){

 404         return False;













 405     }
 406 
 407     buf = mbbuf;
 408     mblen = XmbLookupString(ic, event, buf,
 409                             buf_len - 1, &keysym, &status);
 410 
 411     /*
 412      * In case of overflow, a buffer is allocated and it retries
 413      * XmbLookupString().
 414      */
 415     if (status == XBufferOverflow) {
 416         buf_len = mblen + 1;
 417         buf = (char *)malloc(buf_len);
 418         if (buf == NULL) {

 419             THROW_OUT_OF_MEMORY_ERROR();
 420             return result;
 421         }
 422         mblen = XmbLookupString(ic, event, buf, buf_len, &keysym, &status);


 423     }
 424     buf[mblen] = 0;
 425 
 426     /* Get keysym without taking modifiers into account first to map
 427      * to AWT keyCode table.
 428      */
 429     switch (status) {
 430     case XLookupBoth:
 431         if (!composing) {
 432             if (event->keycode != 0) {
 433                 *keysymp = keysym;
 434                 result = False;
 435                 break;
 436             }
 437         }
 438         composing = False;
 439         /*FALLTHRU*/
 440     case XLookupChars:
 441         /*
 442         printf("lookupString: status=XLookupChars, type=%d, state=%x, keycode=%x, keysym=%x\n",
 443                event->type, event->state, event->keycode, keysym);
 444         */
 445         javastr = JNU_NewStringPlatform(env, (const char *)buf);
 446         if (javastr != NULL) {
 447             JNU_CallMethodByName(env, NULL,
 448                                  currentX11InputMethodInstance,
 449                                  "dispatchCommittedText",
 450                                  "(Ljava/lang/String;J)V",
 451                                  javastr,
 452                                  event->time);
 453             if ((*env)->ExceptionOccurred(env)) {
 454                 (*env)->ExceptionDescribe(env);
 455                 (*env)->ExceptionClear(env);
 456             }
 457         }
 458         break;
 459 
 460     case XLookupKeySym:
 461         /*
 462         printf("lookupString: status=XLookupKeySym, type=%d, state=%x, keycode=%x, keysym=%x\n",
 463                event->type, event->state, event->keycode, keysym);
 464         */
 465         if (keysym == XK_Multi_key)
 466             composing = True;
 467         if (! composing) {
 468             *keysymp = keysym;
 469             result = False;
 470         }
 471         break;
 472 
 473     case XLookupNone:
 474         /*
 475         printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n",
 476                event->type, event->state, event->keycode, keysym);
 477         */
 478         break;
 479     }
 480 
 481     if (buf != mbbuf) {
 482         free(buf);
 483     }
 484     return result;
 485 }
 486 
 487 static StatusWindow *createStatusWindow(Window parent) {


 488     StatusWindow *statusWindow;
 489     XSetWindowAttributes attrib;
 490     unsigned long attribmask;
 491     Window containerWindow;
 492     Window status;
 493     Window child;
 494     XWindowAttributes xwa;
 495     XWindowAttributes xxwa;
 496     /* Variable for XCreateFontSet()*/
 497     char **mclr;
 498     int  mccr = 0;
 499     char *dsr;
 500     unsigned long bg, fg, light, dim;
 501     int x, y, off_x, off_y, xx, yy;
 502     unsigned int w, h, bw, depth;
 503     XGCValues values;
 504     unsigned long valuemask = 0;  /*ignore XGCvalue and use defaults*/
 505     int screen = 0;
 506     int i;
 507     AwtGraphicsConfigDataPtr adata;
 508     extern int awt_numScreens;
 509     /*hardcode the size right now, should get the size base on font*/
 510     int width=80, height=22;
 511     Window rootWindow;
 512     Window *ignoreWindowPtr;
 513     unsigned int ignoreUnit;
 514     Window grandParent;
 515     Window target;
 516     XFontSet fontset;
 517 
 518     fontset = create_fontset();
 519     if (NULL == fontset) {
 520         return NULL;
 521     }
 522 
 523     XGetGeometry(dpy, parent, &rootWindow, &x, &y, &w, &h, &bw, &depth);
 524 
 525     attrib.override_redirect = True;
 526     attribmask = CWOverrideRedirect;
 527     for (i = 0; i < awt_numScreens; i++) {
 528         if (RootWindow(dpy, i) == rootWindow) {
 529             screen = i;
 530             break;
 531         }
 532     }
 533     adata = getDefaultConfig(screen);
 534     bg    = adata->AwtColorMatch(255, 255, 255, adata);
 535     fg    = adata->AwtColorMatch(0, 0, 0, adata);
 536     light = adata->AwtColorMatch(195, 195, 195, adata);
 537     dim   = adata->AwtColorMatch(128, 128, 128, adata);
 538 
 539     grandParent = getGrandParent(parent);
 540     target = (grandParent == 0) ? parent : grandParent;
 541     XGetWindowAttributes(dpy, target, &xwa);
 542     bw = 2; /*xwa.border_width does not have the correct value*/
 543 
 544     /*compare the size difference between parent container
 545       and shell widget, the diff should be the border frame
 546       and title bar height (?)*/
 547 
 548     XQueryTree( dpy,
 549                 target,
 550                 &rootWindow,
 551                 &containerWindow,
 552                 &ignoreWindowPtr,
 553                 &ignoreUnit);
 554     XGetWindowAttributes(dpy, containerWindow, &xxwa);
 555 
 556     XTranslateCoordinates(dpy,
 557                           target, xwa.root,
 558                           0, 0,
 559                           &x, &y, &child);
 560 
 561     if (containerWindow == rootWindow) {
 562         off_x = 0; off_y = STATUS_MARGIN;
 563     } else {
 564         XGetWindowAttributes(dpy, containerWindow, &xxwa);
 565         off_x = (xxwa.width - xwa.width) / 2;
 566         /* off_y = xxwa.height - xwa.height - off_x;*/ /*it's magic:-) */
 567         {
 568             int cx, cy;
 569             XTranslateCoordinates(dpy,
 570                                   containerWindow, xxwa.root,
 571                                   0, 0,
 572                                   &cx, &cy,
 573                                   &child);
 574             off_y = (xxwa.height + cy) - (xwa.height + y);
 575         }
 576     }
 577 
 578     /*get the size of root window*/
 579     XGetWindowAttributes(dpy, rootWindow, &xxwa);
 580 
 581     XTranslateCoordinates(dpy,
 582                           target, xwa.root,
 583                           xwa.x, xwa.y,
 584                           &x, &y,
 585                           &child);
 586     xx = x - off_x;
 587     yy = y + xwa.height - off_y;
 588     if (xx < 0 ){
 589         xx = 0;
 590     }
 591     if (xx + width > xxwa.width) {
 592         xx = xxwa.width - width;
 593     }
 594     if (yy + height > xxwa.height) {
 595         yy = xxwa.height - height;
 596     }
 597 
 598     if ((DefaultVisual(dpy,screen))->class != adata->awt_visInfo.visual->class &&
 599         adata->awt_visInfo.visual->class == TrueColor) {
 600         attrib.colormap = XCreateColormap(dpy, xwa.root,
 601             adata->awt_visInfo.visual, AllocNone );
 602         attrib.border_pixel = BlackPixel(dpy, screen) ;
 603         attribmask |= CWColormap | CWBorderPixel;
 604     }
 605 
 606     status =  XCreateWindow(dpy,
 607                             xwa.root,
 608                             xx, yy,
 609                             width, height,
 610                             0,
 611                             xwa.depth,
 612                             InputOutput,
 613                             adata->awt_visInfo.visual,
 614                             attribmask, &attrib);
 615     XSelectInput(dpy, status,
 616                  ExposureMask | StructureNotifyMask | EnterWindowMask |
 617                  LeaveWindowMask | VisibilityChangeMask);
 618     if (grandParent != 0){
 619         long mask;
 620         XGetWindowAttributes(dpy, grandParent, &xwa);
 621         mask = xwa.your_event_mask | StructureNotifyMask |
 622                VisibilityChangeMask | PropertyChangeMask;
 623         XSelectInput(dpy, grandParent,mask);
 624     }
 625 
 626     statusWindow = (StatusWindow*) calloc(1, sizeof(StatusWindow));
 627     if (statusWindow == NULL){
 628         THROW_OUT_OF_MEMORY_ERROR();
 629         return NULL;
 630     }
 631     statusWindow->w = status;
 632     statusWindow->fontset = fontset;







 633     statusWindow->parent = parent;
 634     statusWindow->grandParent = grandParent;
 635     statusWindow->on  = False;
 636     statusWindow->x = x;
 637     statusWindow->y = y;
 638     statusWindow->width = xwa.width;
 639     statusWindow->height = xwa.height;
 640     statusWindow->off_x = off_x;
 641     statusWindow->off_y = off_y;
 642     statusWindow->bWidth  = bw;
 643     statusWindow->statusH = height;
 644     statusWindow->statusW = width;
 645     statusWindow->peTextW = 0;
 646     statusWindow->rootH = xxwa.height;
 647     statusWindow->rootW = xxwa.width;
 648     statusWindow->lightGC = XCreateGC(dpy, status, valuemask, &values);
 649     XSetForeground(dpy, statusWindow->lightGC, light);
 650     statusWindow->dimGC = XCreateGC(dpy, status, valuemask, &values);
 651     XSetForeground(dpy, statusWindow->dimGC, dim);
 652     statusWindow->fgGC = create_gc(status, FALSE);
 653     XSetForeground(dpy, statusWindow->fgGC, fg);
 654     statusWindow->bgGC = create_gc(status, TRUE);
 655     XSetForeground(dpy, statusWindow->bgGC, bg);
 656     statusWindow->status_ready = False;
 657     wcscpy(statusWindow->status, L"");
 658     return statusWindow;
 659 }
 660 
 661 /* This method is to turn off or turn on the status window. */
 662 static void onoffStatusWindow(X11InputMethodData* pX11IMData,
 663                                 Window parent,
 664                                 Bool ON){
 665     XWindowAttributes xwa;
 666     Window child;
 667     int x, y;
 668     StatusWindow *statusWindow = NULL;
 669 
 670     if (NULL == pX11IMData ||

 671         NULL == (statusWindow =  pX11IMData->statusWindow)){
 672         return;
 673     }
 674 
 675     if (ON == False) {
 676         XUnmapWindow(dpy, statusWindow->w);

 677         return;
 678     }
 679     if (NULL == currentX11InputMethodInstance){
 680         return;



 681     }
 682     {
 683         JNIEnv *env = GetJNIEnv();
 684         parent = JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
 685                                       "getCurrentParentWindow",
 686                                       "()J").j;
 687         if ((*env)->ExceptionOccurred(env)) {
 688             (*env)->ExceptionDescribe(env);
 689             (*env)->ExceptionClear(env);














 690         }

 691     }
 692     if (statusWindow->parent != parent) {
 693         statusWindow->parent = parent;
 694     }
 695     if (st_wcslen(statusWindow->status) > 0 ||
 696         (statusWindow->peText != NULL && st_wcslen(statusWindow->peText) > 0 )) {
 697         moveStatusWindow(statusWindow);
 698         XMapRaised(dpy, statusWindow->w);
 699     }
 700 }
 701 
 702 void paintStatusWindow(StatusWindow *statusWindow){
 703     Window  win  = statusWindow->w;
 704     GC  lightgc = statusWindow->lightGC;
 705     GC  dimgc = statusWindow->dimGC;
 706     GC  bggc = statusWindow->bgGC;
 707     GC  fggc = statusWindow->fgGC;
 708 
 709     int width = statusWindow->statusW;
 710     int height = statusWindow->statusH;
 711     int bwidth = statusWindow->bWidth;
 712     int len;
 713     XRectangle logical, ink;
 714 
 715     if (NULL == statusWindow) return;
 716     if ((len = st_wcslen(statusWindow->status)) == 0) {
 717         return;















 718     }
 719     XwcTextExtents(statusWindow->fontset, statusWindow->status,
 720                    len, &ink, &logical);
 721     width = logical.width;
 722     height = logical.height;
 723 
 724     XFillRectangle(dpy, win, bggc, 0, 0, width+2, height+2);
 725 
 726     XDrawLine(dpy, win, fggc, 0, 0, width+2, 0);
 727     XDrawLine(dpy, win, fggc, 0, height+2, width+2, height+2);
 728     XDrawLine(dpy, win, fggc, 0, 0, 0, height+2);
 729     XDrawLine(dpy, win, fggc, width+2, 0, width+2, height+2);
 730 
 731     if (statusWindow->fontset) {
 732         XwcDrawString(dpy, win, statusWindow->fontset, fggc,
 733                       -logical.x + 1, -logical.y + 1,
 734                       statusWindow->status,
 735                       st_wcslen(statusWindow->status));
 736     } else {
 737         /*too bad we failed to create a fontset for this locale*/
 738         XDrawString(dpy, win, fggc, bwidth + 2, height - bwidth - 4,
 739                     "[InputMethod ON]", strlen("[InputMethod ON]"));
 740     }
 741 }
 742 
 743 Bool statusWindowEventHandler(XEvent event) {
 744     JNIEnv *env = GetJNIEnv();
 745     X11InputMethodData *pX11IMData = NULL;
 746     StatusWindow *statusWindow;
 747 
 748     if (NULL == currentX11InputMethodInstance ||
 749         NULL == (pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance)) ||
 750         NULL == (statusWindow = pX11IMData->statusWindow))
 751     {
 752         return False;





 753     }
 754 
 755     if (statusWindow->w == event.xany.window) {
 756         switch (event.type) {
 757         case Expose:
 758             paintStatusWindow(statusWindow);
 759             if (statusWindow->peText)
 760                 draw_preedit(statusWindow);
 761             arrange_window_stack(statusWindow);
 762             break;
 763         case ConfigureNotify:
 764         case VisibilityNotify:
 765             arrange_window_stack(statusWindow);
 766             break;


 767         /*
 768         case UnmapNotify:
 769         case VisibilityNotify:
 770             break;
 771         */
 772         default:
 773             break;
 774         }
 775         return True;
 776     } else if ((statusWindow->parent == event.xany.window) ||
 777                (statusWindow->grandParent && statusWindow->grandParent == event.xany.window)) {
 778         switch (event.type) {
 779         case MapNotify:
 780             if (statusWindow->on) {
 781                 onoffStatusWindow(pX11IMData, statusWindow->parent, True);
 782             }
 783             break;
 784         case UnmapNotify:
 785             onoffStatusWindow(pX11IMData, 0, False);
 786             break;
 787         case VisibilityNotify:
 788             if (statusWindow->on) {
 789                 arrange_window_stack(statusWindow);
 790             }
 791             break;
 792         case ConfigureNotify:
 793             if (statusWindow->grandParent && statusWindow->on) {
 794                 moveStatusWindow(statusWindow);
 795             }
 796         case PropertyNotify:
 797             if (statusWindow->on) {
 798                 arrange_window_stack(statusWindow);
 799             }
 800             break;
 801         default:
 802             break;
 803         }
 804     }
 805     return False;
 806 }
 807 
 808 static void adjustStatusWindow(Window shell) {
 809     JNIEnv *env = GetJNIEnv();
 810     X11InputMethodData *pX11IMData = NULL;
 811     StatusWindow *statusWindow;
 812 
 813     if (NULL == currentX11InputMethodInstance

 814         || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))
 815         || NULL == (statusWindow = pX11IMData->statusWindow)
 816         || !statusWindow->on)


 817     {
 818         return;




























 819     }
 820 
 821     moveStatusWindow(statusWindow);
 822 }
 823 
 824 /*
 825  * Creates two XICs, one for active clients and the other for passive
 826  * clients. All information on those XICs are stored in the
 827  * X11InputMethodData given by the pX11IMData parameter.
 828  *
 829  * For active clients: Try to use preedit callback to support
 830  * on-the-spot. If tc is not null, the XIC to be created will
 831  * share the Status Area with Motif widgets (TextComponents). If the
 832  * preferable styles can't be used, fallback to root-window styles. If
 833  * root-window styles failed, fallback to None styles.
 834  *
 835  * For passive clients: Try to use root-window styles. If failed,
 836  * fallback to None styles.
 837  */
 838 static Bool
 839 createXIC(JNIEnv * env, X11InputMethodData *pX11IMData, Window w)
 840 {
 841     XVaNestedList preedit = NULL;
 842     XVaNestedList status = NULL;
 843     XIMStyle on_the_spot_styles = XIMPreeditCallbacks,
 844              in_place_styles = 0,
 845              active_styles = 0,
 846              passive_styles = 0,
 847              no_styles = 0;
 848     XIMCallback *callbacks;
 849     unsigned short i;
 850     XIMStyles *im_styles;
 851     char *ret = NULL;
 852     Bool passiveStatusWindow = False;
 853     pX11IMData->statusWindow = NULL;
 854 
 855     if (X11im == NULL) {
 856         return False;
 857     }
 858     if (!w) {
 859         return False;
 860     }
 861 
 862     if (getenv("IBMJAVA_PASSIVE") == NULL) {
 863         passiveStatusWindow = False;
 864     } else {
 865         passiveStatusWindow = True;
 866     }
 867 
 868     if (isNativeIm()) { passiveStatusWindow = True; }
 869 
 870     ret = XGetIMValues(X11im, XNQueryInputStyle, &im_styles, NULL);
 871 
 872     if (ret != NULL) {
 873         jio_fprintf(stderr,"XGetIMValues: %s\n",ret);
 874         return FALSE ;
 875     }
 876 

 877     on_the_spot_styles |= XIMStatusNothing;
 878 
 879     /*kinput does not support XIMPreeditCallbacks and XIMStatusArea
 880       at the same time, so use StatusCallback to draw the status
 881       ourself
 882     */
 883     for (i = 0; i < im_styles->count_styles; i++) {
 884         if (im_styles->supported_styles[i] == (XIMPreeditCallbacks | XIMStatusCallbacks)) {
 885             on_the_spot_styles = (XIMPreeditCallbacks | XIMStatusCallbacks);
 886             break;
 887         }
 888     }



 889 
 890     for (i = 0; i < im_styles->count_styles; i++) {
 891         if (im_styles->supported_styles[i] == on_the_spot_styles)
 892             active_styles = im_styles->supported_styles[i];
 893         if (im_styles->supported_styles[i] == ROOT_WINDOW_STYLES)
 894             passive_styles = im_styles->supported_styles[i];
 895         if (im_styles->supported_styles[i] == IN_PLACE_STYLES) {
 896             in_place_styles = im_styles->supported_styles[i];
 897         }
 898         if (im_styles->supported_styles[i] == NO_STYLES) {
 899             no_styles = im_styles->supported_styles[i];
 900         }
 901     }
 902 
 903     XFree(im_styles);
 904 
 905     if (active_styles != on_the_spot_styles) {
 906         if (passive_styles == ROOT_WINDOW_STYLES)
 907             active_styles = passive_styles;
 908         else {
 909           if (in_place_styles == IN_PLACE_STYLES){
 910               active_styles = passive_styles = IN_PLACE_STYLES;
 911           } else {
 912             if (no_styles == NO_STYLES)
 913                 active_styles = passive_styles = NO_STYLES;
 914             else
 915                 active_styles = passive_styles = 0;
 916           }
 917         }
 918     } else {
 919       if (!passiveStatusWindow) {
 920         if (passive_styles != ROOT_WINDOW_STYLES) {
 921             if (no_styles == NO_STYLES)
 922                 active_styles = passive_styles = NO_STYLES;
 923             else
 924                 active_styles = passive_styles = 0;
 925         }
 926       } else
 927           passive_styles = active_styles;
 928     }
 929 
 930     if (active_styles == on_the_spot_styles) {






 931         callbacks = (XIMCallback *)malloc(sizeof(XIMCallback) * NCALLBACKS);
 932         if (callbacks == (XIMCallback *)NULL)
 933             return False;
 934         pX11IMData->callbacks = callbacks;
 935 
 936         for (i = 0; i < NCALLBACKS; i++, callbacks++) {
 937             callbacks->client_data = (XPointer) pX11IMData->x11inputmethod;
 938             callbacks->callback = callback_funcs[i];
 939         }
 940 
 941         callbacks = pX11IMData->callbacks;
 942         preedit = (XVaNestedList)XVaCreateNestedList(0,
 943                         XNPreeditStartCallback, &callbacks[PreeditStartIndex],
 944                         XNPreeditDoneCallback,  &callbacks[PreeditDoneIndex],
 945                         XNPreeditDrawCallback,  &callbacks[PreeditDrawIndex],
 946                         XNPreeditCaretCallback, &callbacks[PreeditCaretIndex],
 947                         NULL);
 948         if (preedit == (XVaNestedList)NULL)
 949             goto err;

 950         /*always try XIMStatusCallbacks for active client...*/
 951         {
 952         if (on_the_spot_styles & XIMStatusCallbacks) {
 953             status = (XVaNestedList)XVaCreateNestedList(0,
 954                         XNStatusStartCallback, &callbacks[StatusStartIndex],
 955                         XNStatusDoneCallback,  &callbacks[StatusDoneIndex],
 956                         XNStatusDrawCallback, &callbacks[StatusDrawIndex],
 957                         NULL);
 958 
 959             if (status == NULL)
 960                 goto err;
 961           }
 962             pX11IMData->statusWindow = createStatusWindow(w);
 963             pX11IMData->ic_active = XCreateIC(X11im,
 964                                               XNClientWindow, w,
 965                                               XNFocusWindow, w,
 966                                               XNInputStyle, active_styles,
 967                                               XNPreeditAttributes, preedit,
 968                                               XNStatusAttributes, status,
 969                                               NULL);
 970             if (NULL != pX11IMData->statusWindow) {
 971                 pX11IMData->statusWindow->status_ready = True;
 972             }
 973             XFree((void *)status);
 974             XFree((void *)preedit);
 975         }
 976         if (passiveStatusWindow) {
 977             pX11IMData->ic_passive = pX11IMData->ic_active;
 978         } else {
 979             pX11IMData->ic_passive = XCreateIC(X11im,
 980                                                XNClientWindow, w,
 981                                                XNFocusWindow, w,
 982                                                XNInputStyle, passive_styles,
 983                                                NULL);
 984         }
 985     } else {
 986         pX11IMData->ic_active = XCreateIC(X11im,
 987                                           XNClientWindow, w,
 988                                           XNFocusWindow, w,
 989                                           XNInputStyle, active_styles,
 990                                           NULL);
 991         pX11IMData->ic_passive = pX11IMData->ic_active;
 992     }
 993 
 994     // The code set the IC mode that the preedit state is not initialied
 995     // at XmbResetIC.  This attribute can be set at XCreateIC.  I separately
 996     // set the attribute to avoid the failure of XCreateIC at some platform
 997     // which does not support the attribute.
 998     if (pX11IMData->ic_active != 0)
 999         XSetICValues(pX11IMData->ic_active,
1000                         XNResetState, XIMPreserveState, NULL);
1001     if (pX11IMData->ic_passive != 0 &&
1002         pX11IMData->ic_active != pX11IMData->ic_passive)
1003             XSetICValues(pX11IMData->ic_passive,
1004              XNResetState, XIMInitialState, NULL);
1005 
1006     pX11IMData->passiveStatusWindow = passiveStatusWindow;
1007 
1008     if (pX11IMData->ic_active == (XIC)0
1009         || pX11IMData->ic_passive == (XIC)0) {
1010         return False;
1011     }
1012 
1013     /* Unset focus to avoid unexpected IM on */
1014     setXICFocus(pX11IMData->ic_active, False);
1015     if (pX11IMData->ic_active != pX11IMData->ic_passive)
1016         setXICFocus(pX11IMData->ic_passive, False);












1017 
1018     return True;
1019 
1020  err:
1021     if (preedit)
1022         XFree((void *)preedit);
1023     THROW_OUT_OF_MEMORY_ERROR();
1024     return False;
1025 }
1026 
1027 static int
1028 PreeditStartCallback(XIC ic, XPointer client_data, XPointer call_data)
1029 {
1030     JNIEnv *env = GetJNIEnv();
1031     X11InputMethodData *pX11IMData;
1032 
1033     pX11IMData = getX11InputMethodData(env, (jobject)client_data);
1034     if (pX11IMData == NULL || pX11IMData->statusWindow == NULL) {
1035         return 0;
1036     }
1037     resetPassivePreeditText(pX11IMData->statusWindow);
1038 
1039     return -1;  /* unlimited length for preedit text  */
1040 }
1041 
1042 static void
1043 PreeditDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
1044 {
1045     JNIEnv *env = GetJNIEnv();
1046     X11InputMethodData *pX11IMData;
1047 
1048     pX11IMData = getX11InputMethodData(env, (jobject)client_data);
1049     if (pX11IMData == NULL) {
1050         return;
1051     }
1052 
1053     if (!pX11IMData->isActiveClient) {
1054         resetPassivePreeditText(pX11IMData->statusWindow);
1055         shrink_status(pX11IMData->statusWindow);
1056     }
1057     else{
1058             JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
1059                                  "clearComposedText",
1060                                  "(J)V",
1061                                  awt_util_nowMillisUTC());
1062             if ((*env)->ExceptionOccurred(env)) {
1063                 (*env)->ExceptionDescribe(env);
1064                 (*env)->ExceptionClear(env);
1065             }
1066     }
1067 }
1068 
1069 /*
1070  * Translate the preedit draw callback items to Java values and invoke
1071  * X11InputMethod.dispatchComposedText().
1072  *
1073  * client_data: X11InputMethod object
1074  */
1075 static void
1076 PreeditDrawCallback(XIC ic, XPointer client_data,
1077                     XIMPreeditDrawCallbackStruct *pre_draw)
1078 {
1079     JNIEnv *env = GetJNIEnv();
1080     X11InputMethodData *pX11IMData = NULL;
1081     jmethodID x11imMethodID;
1082 
1083     XIMText *text;
1084     jstring javastr = NULL;
1085     jintArray style = NULL;
1086 
1087     /* printf("Native: PreeditDrawCallback() \n"); */
1088     if (pre_draw == NULL) {
1089         return;
1090     }
1091     AWT_LOCK();
1092     if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {



1093         goto finally;
1094     }
1095 
1096     if (!pX11IMData->isActiveClient){
1097         if (ic == pX11IMData->ic_passive) {
1098             preedit_draw_passive(pX11IMData, pre_draw);
1099         }
1100         goto finally;
1101     }
1102 
1103     if ((text = pre_draw->text) != NULL) {
1104         if (is_text_available(text)) {
1105             if (text->string.multi_byte != NULL) {
1106                 if (pre_draw->text->encoding_is_wchar == False) {
1107                     javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte);
1108                     if (javastr == NULL) {
1109                         goto finally;
1110                     }
1111                 } else {
1112                     char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
1113                     if (mbstr == NULL) {
1114                         goto finally;
1115                     }
1116                     javastr = JNU_NewStringPlatform(env, (const char *)mbstr);
1117                     free(mbstr);
1118                     if (javastr == NULL) {
1119                         goto finally;
1120                     }
1121                 }
1122             }
1123         }
1124         if (text->feedback != NULL) {
1125             int cnt;
1126             jint *tmpstyle;
1127 
1128             style = (*env)->NewIntArray(env, text->length);
1129             if (JNU_IsNull(env, style)) {
1130                 (*env)->ExceptionClear(env);
1131                 THROW_OUT_OF_MEMORY_ERROR();
1132                 goto finally;
1133             }
1134 
1135             if (sizeof(XIMFeedback) == sizeof(jint)) {
1136                 /*
1137                  * Optimization to avoid copying the array
1138                  */
1139                 (*env)->SetIntArrayRegion(env, style, 0,
1140                                           text->length, (jint *)text->feedback);


1143                 if (tmpstyle == (jint *) NULL) {
1144                     THROW_OUT_OF_MEMORY_ERROR();
1145                     goto finally;
1146                 }
1147                 for (cnt = 0; cnt < (int)text->length; cnt++)
1148                         tmpstyle[cnt] = text->feedback[cnt];
1149                 (*env)->SetIntArrayRegion(env, style, 0,
1150                                           text->length, (jint *)tmpstyle);
1151             }
1152         }
1153     }
1154     JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
1155                          "dispatchComposedText",
1156                          "(Ljava/lang/String;[IIIIJ)V",
1157                          javastr,
1158                          style,
1159                          (jint)pre_draw->chg_first,
1160                          (jint)pre_draw->chg_length,
1161                          (jint)pre_draw->caret,
1162                          awt_util_nowMillisUTC());
1163 
1164     if ((*env)->ExceptionOccurred(env)) {
1165         (*env)->ExceptionDescribe(env);
1166         (*env)->ExceptionClear(env);
1167     }
1168 
1169 finally:
1170     AWT_UNLOCK();
1171     return;
1172 }
1173 
1174 static void
1175 PreeditCaretCallback(XIC ic, XPointer client_data,
1176                      XIMPreeditCaretCallbackStruct *pre_caret)
1177 {
1178     XIMPreeditDrawCallbackStruct pre_draw;

1179 
1180     if (pre_caret != NULL && pre_caret->direction == XIMAbsolutePosition) {
1181         pre_draw.caret = pre_caret->position;
1182         pre_draw.chg_first = 0;
1183         pre_draw.chg_length = 0;
1184         pre_draw.text = NULL;
1185         PreeditDrawCallback(ic, client_data, &pre_draw);
1186     }
1187 }
1188 

1189 static void
1190 StatusStartCallback(XIC ic, XPointer client_data, XPointer call_data)
1191 {
1192     /*ARGSUSED*/
1193     /*printf("StatusStartCallback:\n");  */

1194 }
1195 
1196 static void
1197 StatusDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
1198 {
1199     /*ARGSUSED*/
1200     /*printf("StatusDoneCallback:\n"); */

1201 }
1202 
1203 static void StatusDrawCallback
1204   (XIC ic, XPointer client_data, XIMStatusDrawCallbackStruct *status_draw)

1205 {
1206     /*ARGSUSED*/
1207     /*printf("StatusDrawCallback:\n"); */
1208     JNIEnv *env = GetJNIEnv();
1209     X11InputMethodData *pX11IMData = NULL;
1210     StatusWindow *statusWindow;
1211     int value_make = CWX|CWWidth|CWHeight;
1212     XRectangle logical, ink;
1213     XWindowChanges xwc;
1214     int len;
1215 
1216     AWT_LOCK();
1217 







1218     if (NULL == (pX11IMData = getX11InputMethodData(env, (jobject)client_data))
1219         || NULL == (statusWindow = pX11IMData->statusWindow)){
1220         goto finally;
1221     }

1222 
1223     if (status_draw->type == XIMTextType) {
1224         XIMText *text = (status_draw->data).text;
1225         if (text != NULL) {
1226             if (text->string.multi_byte != NULL) {
1227                 if(!strcmp(text->string.multi_byte," ")){
1228                     wcscpy(statusWindow->status, L"");
1229                     onoffStatusWindow(pX11IMData, 0, False);
1230                     goto finally;
1231                 }
1232                 mbstowcs(statusWindow->status,
1233                          (const char *)text->string.multi_byte,
1234                          (size_t)MAX_STATUS_LEN);
1235             } else {
1236                 if (0 == st_wcslen(text->string.wide_char)){
1237                     wcscpy(statusWindow->status, L"");
1238                     onoffStatusWindow(pX11IMData, 0, False);
1239                     goto finally;
1240                 }
1241                 wcsncpy(statusWindow->status,
1242                         text->string.wide_char,
1243                         MAX_STATUS_LEN);
1244             }
1245             XwcTextExtents(statusWindow->fontset, statusWindow->status,
1246                            st_wcslen(statusWindow->status), &ink, &logical);
1247             statusWindow->statusW = logical.width + BORDER_MARGIN;
1248             statusWindow->statusH = logical.height + BORDER_MARGIN;
1249             xwc.x = statusWindow->x - statusWindow->off_x;
1250             if (xwc.x < 0 ) xwc.x = 0;
1251             xwc.width = statusWindow->statusW;
1252             xwc.height = statusWindow->statusH;
1253             if (xwc.x + xwc.width > statusWindow->rootW){
1254                 xwc.x = statusWindow->rootW - xwc.width;
1255             }
1256             XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
1257           if (statusWindow->status_ready && statusWindow->on == True){
1258             onoffStatusWindow(pX11IMData, statusWindow->parent, True);
1259           }
1260             paintStatusWindow(statusWindow);
1261             if (statusWindow->peText)
1262                 draw_preedit(statusWindow);
1263         }
1264         else {
1265             wcscpy(statusWindow->status, L"");
1266             /*just turnoff the status window
1267             paintStatusWindow(statusWindow);
1268             */
1269             onoffStatusWindow(pX11IMData, 0, False);
1270         }
1271     }
1272 
1273  finally:
1274     AWT_UNLOCK();
1275 }

1276 
1277 /* return the string length without trailing spaces    */
1278 /* work around code for Japanese AIXIM is implemented. */
1279 static int st_wcslen(wchar_t *string)
1280 {
1281     int len = (int32_t)wcslen(string);
1282     if (len == 0)
1283         return 0;
1284    for (len--;len >= 0; len--) {
1285         if (!iswspace((wint_t) string[len])) break;
1286     }
1287     return len+1;
1288 }
1289 
1290 /*
1291  * Checks whether given XIMText contains a string data.
1292  */
1293 static Bool is_text_available(XIMText * text)
1294 {
1295     if (text == NULL || text->length==0)
1296         return False;
1297     if (text->encoding_is_wchar) {
1298         if(text->string.wide_char[0] == L'\0')
1299             return False;
1300     } else {
1301         if (text->string.multi_byte[0] == '\0')
1302             return False;
1303     }
1304     return True;
1305 }
1306 
1307 /*
1308  * check if preedit status is active
1309 */
1310 static Bool isPreeditStateActive(XIC ic)
1311 {
1312     XIMPreeditState state = XIMPreeditUnKnown;
1313     XVaNestedList pr_atrb;
1314     char* nosupportAttr;
1315 
1316     if (ic == NULL) return False;
1317 
1318     pr_atrb = XVaCreateNestedList(0,XNPreeditState,&state,NULL);
1319     nosupportAttr=XGetICValues(ic,XNPreeditAttributes,pr_atrb,NULL);
1320     XFree(pr_atrb);
1321     if (nosupportAttr==NULL && state & XIMPreeditDisable)
1322         return False;
1323     else
1324         return True;
1325 }
1326 
1327 static void * buf_insert(void * src, void * insert, int size,
1328                          int src_len, int ins_len, int offset)
1329 {
1330     char *temp;
1331 
1332     temp = realloc(src, size*(src_len+ins_len+1));
1333     if (temp == NULL) {
1334         THROW_OUT_OF_MEMORY_ERROR();
1335         return src;
1336     }
1337     if (offset != src_len) {
1338         memmove(&temp[size*(offset+ins_len)],
1339                 &((char *)temp)[size*offset],
1340                 size*(src_len-offset));
1341     }
1342     memcpy(&temp[size*offset], insert, size*ins_len);
1343 
1344     return (void *)temp;
1345 }
1346 
1347 static void * handle_buffer(void * source, void * insert,
1348                             int size,int src_len, int ins_len,
1349                             int del_len, int offset)
1350 {
1351     void * temp = source;
1352 
1353     if (del_len > 0) {
1354         if (del_len == ins_len) {
1355             memcpy(&((char *)source)[size*offset], insert, size*ins_len);
1356             return source;
1357         }
1358         else if (src_len > offset+del_len) {
1359             memmove(&((char *)source)[size*offset],
1360                     &((char *)source)[size*(offset+del_len)],
1361                     size*(src_len-offset-del_len));
1362         }
1363     }
1364     if (ins_len > 0) {
1365         temp = buf_insert(source, insert, size, src_len,
1366                           ins_len, offset);
1367     }
1368     return temp;
1369 }
1370 /*
1371  * Display the given preedit text to the root window which is ownd by
1372  * myself. All of the character is converted to wide char.
1373  * this function is used for the passive client.
1374  */
1375 static void preedit_draw_passive(X11InputMethodData *pX11IMData,
1376                     XIMPreeditDrawCallbackStruct *pre_draw)
1377 {
1378     XIMText *text;
1379     wchar_t *tempbuf = NULL;
1380     StatusWindow *statusWindow;
1381     wchar_t *cur_text;
1382     unsigned long *cur_attr;
1383     int     cur_len = 0;
1384     int     chg_len = pre_draw->chg_length;
1385     int     chg_1st = pre_draw->chg_first;
1386 
1387     if (NULL == (statusWindow = pX11IMData->statusWindow))
1388         return;
1389     cur_text = statusWindow->peText;
1390     cur_attr = statusWindow->peAttr;
1391     if (cur_text == NULL && pre_draw->text == NULL)
1392         return;
1393 
1394     if (cur_text != NULL)
1395         cur_len = (int32_t)wcslen(cur_text);
1396     text = pre_draw->text;
1397     if (text == NULL) {
1398         /* delete only */
1399         if (cur_len >  chg_1st+chg_len) {
1400             memmove(&cur_text[chg_1st],
1401                     &cur_text[chg_1st+chg_len],
1402                     sizeof(wchar_t)*(cur_len-chg_1st-chg_len));
1403             memmove(&cur_attr[chg_1st],
1404                     &cur_attr[chg_1st+chg_len],
1405                     sizeof(long)*(cur_len-chg_1st-chg_len));
1406         }
1407         if ((pre_draw->chg_length <= cur_len ) && (pre_draw->chg_length >0))
1408             cur_text[cur_len-pre_draw->chg_length] =L'\0';
1409     } else {
1410         /* insert or replace */
1411         int     ins_len = 0;
1412         void *  ins_text = NULL;
1413 
1414         /* if invalid offset is specified, do nothing. */
1415         /* this fix is for aixim for eucTW             */
1416         if (cur_len < chg_1st)
1417             return;
1418         if(is_text_available(text)) {
1419             /* insert or replace the text */
1420             if (text->encoding_is_wchar == False) {
1421                 /* convert the text to wide chars.
1422                    allocate enough size buffer
1423                 */
1424                 tempbuf = (wchar_t *)malloc(sizeof(wchar_t)*(text->length+1));
1425                 if (tempbuf == NULL) {
1426                     THROW_OUT_OF_MEMORY_ERROR();
1427                     return;
1428                 }
1429                 ins_len = (int32_t)mbstowcs(tempbuf, text->string.multi_byte,
1430                                    text->length);
1431                 if (ins_len == -1) {
1432                         free(tempbuf);
1433                         return;
1434                 }
1435                 ins_text = (void *)tempbuf;
1436             }
1437             else {
1438                 ins_len = text->length;
1439                 ins_text = text->string.wide_char;
1440             }
1441             /* finish prepare the data to be inserted */
1442 
1443             statusWindow->peText =
1444                     handle_buffer(cur_text, ins_text, sizeof(wchar_t),
1445                                   cur_len, ins_len, chg_len, chg_1st);
1446             statusWindow->peAttr =
1447                     handle_buffer(cur_attr, text->feedback, sizeof(long),
1448                                   cur_len, ins_len, chg_len, chg_1st);
1449             statusWindow->peText[cur_len-chg_len+ins_len] =L'\0';
1450 
1451             if (tempbuf != NULL)
1452                 free(tempbuf);
1453         } /* endof insert or replace text */
1454         else {
1455             /* change attribute only */
1456             memcpy(&cur_attr[chg_1st], text->feedback,
1457                     sizeof(long)*text->length);
1458         }


1459     }
1460     statusWindow->peCaret= pre_draw->caret;
1461     draw_preedit(statusWindow);
1462     if (statusWindow->on && wcslen(statusWindow->peText) > 0)
1463         onoffStatusWindow(pX11IMData, statusWindow->parent, True);
1464     else if (wcslen(statusWindow->status) == 0)
1465         onoffStatusWindow(pX11IMData, 0, False);
1466 }
1467 
1468 /*
1469  * reset predit test of passive mode
1470  */
1471 static void
1472 resetPassivePreeditText(StatusWindow *statusWindow)
1473 {
1474     if (NULL == statusWindow) return;
1475     if(statusWindow->peText != NULL) {
1476         free(statusWindow->peText);
1477         statusWindow->peText = NULL;
1478     }
1479     if(statusWindow->peAttr != NULL) {
1480         free(statusWindow->peAttr);
1481         statusWindow->peAttr = NULL;
1482     }
1483     statusWindow->peCaret= 0;
1484 }
1485 
1486 static void draw_caret(StatusWindow *statusWindow, GC gc, int pos)
1487 {
1488     if (NULL == statusWindow) return;
1489     XSetFunction(dpy, gc, GXinvert);
1490     XDrawLine(dpy, statusWindow->w,
1491               gc, pos, STATUS_BORDER/2,
1492               pos, STATUS_BORDER/2+statusWindow->fOff);
1493     XSetFunction(dpy, gc, GXcopy);
1494 }
1495 
1496 static int  get_next_attr(int len, unsigned long *attr)
1497 {
1498     int count;
1499 
1500     for (count = 1; count < len; count++)  {
1501         if ((attr[count-1] & PREEDIT_ATTR_MASK)
1502             != (attr[count] & PREEDIT_ATTR_MASK))
1503             break;
1504     }
1505     return count;
1506 }
1507 
1508 static void draw_preedit(StatusWindow *statusWindow)
1509 {
1510     unsigned long *attr;
1511     int x_pos,x_caret;
1512     unsigned int  len;
1513     int len_disp, pos;
1514     wchar_t *str;
1515     GC  gc;
1516     XRectangle ink, rect, rect_c;
1517     Bool caret_done = False;
1518 
1519     if (NULL == statusWindow) return;
1520     align_status(statusWindow);
1521     XFillRectangle(dpy, statusWindow->w,
1522                    statusWindow->bgGC,
1523                    statusWindow->statusW,0,
1524                    statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN,
1525                    statusWindow->fBot+2);
1526 
1527 
1528     XDrawLine(dpy, statusWindow->w, statusWindow->fgGC,
1529               statusWindow->statusW, 0,
1530               statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, 0);
1531     XDrawLine(dpy, statusWindow->w, statusWindow->fgGC,
1532               statusWindow->statusW, statusWindow->fBot+2,
1533               statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN,
1534               statusWindow->fBot+2);
1535     XDrawLine(dpy, statusWindow->w, statusWindow->fgGC,
1536               statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, 0,
1537               statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN,
1538               statusWindow->fBot+2);
1539     if (0 == statusWindow->statusW)
1540         XDrawLine(dpy, statusWindow->w, statusWindow->fgGC,
1541                   0, 0, 0, statusWindow->fBot+2);
1542 
1543     str =  statusWindow->peText;
1544 
1545     if (str != NULL &&  (len = (int32_t)wcslen(str)) != 0) {
1546         pos = 0;
1547         attr = statusWindow->peAttr;
1548         x_pos = x_caret = statusWindow->statusW + STATUS_BORDER;
1549         while((int)len-1 >= pos) {
1550             len_disp = get_next_attr(len - pos, &attr[pos]);
1551             if (attr[pos] & XIMReverse) {
1552                 gc = statusWindow->bgGC;
1553             }
1554             else {
1555                 gc = statusWindow->fgGC;
1556             }
1557             XwcTextExtents(statusWindow->fontset,
1558                            &str[pos],
1559                            len_disp, &ink, &rect);
1560             XwcDrawImageString(dpy, statusWindow->w,
1561                                statusWindow->fontset, gc,
1562                                x_pos, statusWindow->fOff+1, &str[pos], len_disp);
1563             if (attr[pos] & XIMUnderline) {
1564                 XDrawLine(dpy, statusWindow->w,
1565                           gc, x_pos, statusWindow->fBot,
1566                           x_pos+rect.width, statusWindow->fBot);
1567             }
1568             if (!caret_done) {
1569                 if( statusWindow->peCaret >= pos &&
1570                     statusWindow->peCaret <= pos+len_disp) {
1571                     if (statusWindow->peCaret == 0)
1572                         x_caret = x_pos;
1573                     else if (statusWindow->peCaret == pos+len_disp)
1574                         x_caret = x_pos+rect.width;
1575                     else {
1576                         XwcTextExtents(statusWindow->fontset,
1577                                         &str[pos],
1578                                         statusWindow->peCaret-pos,
1579                                         &ink, &rect_c);
1580                         x_caret = x_pos+ rect_c.width;
1581                     }
1582                     x_caret-=CARET_OFFSET;
1583                     caret_done = True;
1584                 }
1585             }
1586             pos += len_disp;
1587             x_pos += rect.width;
1588         }
1589         if (caret_done)
1590             draw_caret(statusWindow, statusWindow->fgGC, x_caret);
1591     }
1592 }
1593 
1594 /* calc required status window size and resize the window */
1595 static void align_status(StatusWindow *statusWindow)
1596 {
1597     int len_st, len_pe = 0;
1598     XRectangle rect_st, rect_pe, ink;
1599     Dimension cur_w;
1600     int value_make = CWX|CWWidth|CWHeight;
1601     XWindowChanges xwc;
1602 
1603     if (NULL == statusWindow) return;
1604     if ((len_st = st_wcslen(statusWindow->status)) == 0
1605         && (statusWindow->peText == NULL || st_wcslen(statusWindow->peText) == 0 ))
1606         return;
1607 
1608     rect_pe.x = rect_pe.y = rect_pe.width = rect_pe.height = 0;
1609 
1610     XwcTextExtents(statusWindow->fontset,
1611                    statusWindow->status,
1612                    len_st, &ink, &rect_st);
1613     if (statusWindow->peText != NULL
1614         && (len_pe = (int32_t)wcslen(statusWindow->peText)) > 0) {
1615         XwcTextExtents(statusWindow->fontset,
1616                        statusWindow->peText,
1617                        len_pe, &ink, &rect_pe);
1618     }
1619     statusWindow->fOff = max(-rect_st.y, -rect_pe.y);
1620     statusWindow->fBot = max(rect_st.height, rect_pe.height);
1621     statusWindow->statusW =rect_st.width;
1622     if (rect_st.width > 0) statusWindow->statusW += BORDER_MARGIN;
1623     statusWindow->peTextW = rect_pe.width;
1624 
1625     xwc.x = statusWindow->x - statusWindow->off_x;
1626     if (xwc.x < 0 ) xwc.x = 0;
1627 
1628     if (len_pe > 0) {
1629         xwc.width = statusWindow->statusW
1630                     + statusWindow->peTextW + BORDER_MARGIN + 1;
1631         xwc.height = statusWindow->fBot + BORDER_MARGIN;
1632     } else {
1633         xwc.width = statusWindow->statusW;
1634         xwc.height = statusWindow->fBot + BORDER_MARGIN;
1635     }
1636     if (xwc.x + xwc.width > statusWindow->rootW){
1637       xwc.x = statusWindow->rootW - xwc.width;
1638     }
1639     XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
1640 }
1641 
1642 static void shrink_status(StatusWindow *statusWindow)
1643 {
1644     int value_make = CWX|CWWidth|CWHeight;
1645     XWindowChanges xwc;
1646 
1647     if (NULL == statusWindow) return;
1648     xwc.width  = statusWindow->statusW;
1649     xwc.height = statusWindow->statusH;
1650     statusWindow->peTextW = 0;
1651     xwc.x = statusWindow->x - statusWindow->off_x;
1652     if (xwc.x < 0 ) xwc.x = 0;
1653     if (xwc.x + xwc.width > statusWindow->rootW){
1654       xwc.x = statusWindow->rootW - xwc.width;
1655     }
1656     XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
1657 }
1658 
1659 static GC create_gc(Window win, Bool isReverse)
1660 {
1661     XGCValues xgcv;
1662     unsigned long mask;
1663     AwtScreenDataPtr defaultScreen;
1664 
1665     defaultScreen = getScreenData(DefaultScreen(dpy));
1666 
1667     mask = (GCForeground | GCBackground );
1668     if (isReverse) {
1669         xgcv.foreground = defaultScreen->whitepixel;
1670         xgcv.background = defaultScreen->blackpixel;
1671     } else {
1672         xgcv.foreground = defaultScreen->blackpixel;
1673         xgcv.background = defaultScreen->whitepixel;
1674     }
1675     return XCreateGC(dpy, win, mask, &xgcv);
1676 }
1677 
1678 static Bool isNativeIm()
1679 {
1680 #define XIMMODIFIER          "@im="
1681 #define XIM_SERVER_CATEGORY  "@server="
1682     char *immodifiers;
1683     char *imserver, *imserverPtr;
1684     Atom imserverAtom;
1685 
1686     if (!(immodifiers = getenv("XMODIFIERS"))) return True;
1687     if (!(imserver = calloc(1,strlen(immodifiers)+strlen(XIM_SERVER_CATEGORY)+1))) return True;
1688     if (!(immodifiers = strstr(immodifiers,XIMMODIFIER))) return True;
1689     immodifiers += strlen(XIMMODIFIER);
1690     strcpy(imserver,XIM_SERVER_CATEGORY);
1691     imserverPtr = imserver + strlen(imserver);
1692     while(*immodifiers != '@' && *immodifiers != '\0') {
1693         *imserverPtr = *immodifiers;
1694         imserverPtr++;
1695         immodifiers++;
1696     }
1697     imserverAtom = XInternAtom(awt_display, imserver, True);
1698     free(imserver);
1699     if (imserverAtom > 0)
1700         return False;
1701     else
1702         return True;
1703 }
1704 
1705 static Window getGrandParent(Window parent)




1706 {
1707     Window containerWindow,rootWindow,tmp;
1708     Window *ignoreWindowPtr;
1709     unsigned int ignoreUnit;
1710     Window grandParent=0;
1711     XWindowAttributes xwa;
1712     Atom WM_STATE;
1713     Atom type = None;
1714     int32_t format;
1715     unsigned long nitems, after;
1716     unsigned char * data;
1717 
1718     if (parent == 0) return grandParent;
1719     WM_STATE = XInternAtom(dpy, "WM_STATE", True);
1720     if (WM_STATE == None) return grandParent;
1721 
1722     tmp=parent;
1723     while(XQueryTree(dpy, tmp,
1724                      &rootWindow, &containerWindow,
1725                      &ignoreWindowPtr, &ignoreUnit)){
1726         XFree(ignoreWindowPtr);
1727         if (containerWindow == rootWindow) break;
1728         if (XGetWindowProperty(dpy, containerWindow, WM_STATE,
1729                     0, 0, False, AnyPropertyType,
1730                     &type, &format, &nitems, &after, &data) == Success) {
1731             XFree(data);
1732             if (type) {
1733                 XGetWindowAttributes(dpy, containerWindow, &xwa);
1734                 if (FALSE == xwa.override_redirect){
1735                     grandParent=containerWindow;
1736                 }
1737             }
1738         }
1739         tmp=containerWindow;
1740     }
1741     return grandParent;
1742 }
1743 
1744 static void moveStatusWindow(StatusWindow *statusWindow)
1745 {
1746     XWindowAttributes xwa;
1747     Window child;
1748     int x, y, width;
1749     Window target;
1750 
1751     if (NULL == statusWindow) return;
1752     if (statusWindow->grandParent) {
1753         target = statusWindow->grandParent;
1754     } else {
1755         target = statusWindow->parent;
1756     }
1757     XGetWindowAttributes(dpy, target, &xwa);
1758     XTranslateCoordinates(dpy,
1759                           target, xwa.root,
1760                           0, 0,
1761                           &x, &y,
1762                           &child);
1763     if (statusWindow->x != x
1764         || statusWindow->y != y
1765         || statusWindow->width != xwa.width
1766         || statusWindow->height != xwa.height){
1767         statusWindow->x = x;
1768         statusWindow->y = y;
1769         statusWindow->height = xwa.height;
1770         statusWindow->width = xwa.width;
1771         x = statusWindow->x - statusWindow->off_x;
1772         y = statusWindow->y + statusWindow->height + statusWindow->off_y;
1773         if (x < 0 ){
1774             x = 0;
1775         }
1776         if (statusWindow->peTextW > 0) {
1777             width = statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN + 1;
1778             if (x + width > statusWindow->rootW){
1779                 x = statusWindow->rootW - width;
1780             }
1781         } else {
1782             if (x + statusWindow->statusW > statusWindow->rootW){
1783                 x = statusWindow->rootW - statusWindow->statusW;
1784             }
1785         }
1786         if (y + statusWindow->statusH > statusWindow->rootH){
1787             y = statusWindow->rootH - statusWindow->statusH;
1788         }
1789         XMoveWindow(dpy, statusWindow->w, x, y);
1790     }
1791 }
1792 
1793 static void arrange_window_stack(StatusWindow* statusWindow)
1794 {
1795     XWindowChanges xwc;
1796     int value_make = CWSibling|CWStackMode;
1797     Window root, parent, *children;
1798     unsigned int nchildren;
1799 
1800     if (NULL == statusWindow) return;
1801     if (XQueryTree(dpy, statusWindow->parent,
1802                        &root, &parent, &children, &nchildren)){
1803         XFree(children);
1804         xwc.sibling = parent;
1805         while(XQueryTree(dpy, xwc.sibling, &root, &parent, &children, &nchildren)) {
1806             XFree(children);
1807             if (root != parent) {
1808                 xwc.sibling = parent;
1809             } else {
1810                 break;
1811             }
1812         }
1813         xwc.stack_mode = Above;
1814         XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
1815     }
1816 }
1817 
1818 static int count_missing_fonts(char **charset_list, int charset_count)
1819 {
1820     int i,j;
1821     if (charset_count > 0) {
1822         j=charset_count;
1823         for(i=0; i < charset_count; i++) {
1824             if ((strstr(charset_list[i], "IBM-udc")) ||
1825                 (strstr(charset_list[i], "IBM-sbd")) ||
1826                 (strstr(charset_list[i], "IBM-ucdTW")))
1827                 j--;
1828         }
1829         return j;
1830     }
1831     else
1832         return 0;
1833 }
1834 
1835 static XFontSet create_fontset_name(char * font_name, Bool force)
1836 {
1837     XFontSet fontset = NULL;
1838     char **charset_list;
1839     int charset_count;
1840     char *def_string;
1841     int missing_fonts;
1842 
1843     fontset = XCreateFontSet(dpy, font_name,
1844                 &charset_list, &charset_count, &def_string);
1845     if (charset_count > 0) {
1846         missing_fonts = count_missing_fonts(charset_list,
1847                                             charset_count);
1848         XFreeStringList(charset_list);
1849         if (fontset && (missing_fonts > 0)) {
1850             if (!force) {
1851                 XFreeFontSet(dpy, fontset);
1852                 fontset = NULL;
1853             }
1854         }
1855     }
1856     return fontset;
1857 }
1858 
1859 static XFontSet create_fontset()
1860 {
1861     XFontSet fontset = NULL;
1862     int i;
1863     static char * fontlist[] = {
1864         "-dt-interface user-medium-r-normal-S*-*-*-*-*-*-*-*-*",
1865         "-*-*-medium-r-normal-*-14-*-*-*-c-*-*-*",
1866         "-*-*-medium-r-normal-*-14-*-*-*-m-*-*-*",
1867         "-*-*-medium-r-normal--14-0-0-0-m-*-*-*",
1868         "-monotype-sansmonowt-medium-r-normal--14-*-*-*-m-*-*-*",
1869         "-*--14-*",
1870         "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*",
1871         "-*--16-*",
1872         "-*--17-*",
1873         "-*--18-*",
1874         "-*--19-*",
1875         "-*--20-*",
1876         "-*--24-*",
1877         NULL};
1878 
1879     for (i=0; fontlist[i] != NULL && fontset==NULL; i++)
1880         fontset = create_fontset_name(fontlist[i], False);
1881 
1882     if (!fontset)
1883         fprintf(stdout, "Cannot load fonts for IMF.\n");
1884     return  fontset;
1885 }
1886 
1887 static Window get_current_focus(XIC ic) {
1888     Window w = 0;
1889     if (ic != NULL)
1890         XGetICValues(ic, XNFocusWindow, &w, NULL);
1891     return w;
1892 }
1893 
1894 JNIEXPORT jboolean JNICALL
1895 Java_sun_awt_X11_XInputMethod_openXIMNative(JNIEnv *env,
1896                                             jobject this,
1897                                             jlong display)
1898 {
1899     Bool registered;
1900 
1901     AWT_LOCK();
1902 
1903     dpy = (Display *)jlong_to_ptr(display);
1904 
1905     if (X11im == NULL) {
1906         X11im = XOpenIM(dpy, NULL, NULL, NULL);









1907     }

1908 
1909     AWT_UNLOCK();
1910 
1911     return JNI_TRUE;
1912 }
1913 
1914 JNIEXPORT jboolean JNICALL
1915 Java_sun_awt_X11_XInputMethod_createXICNative(JNIEnv *env,
1916                                               jobject this,
1917                                               jlong window)
1918 {
1919     X11InputMethodData *pX11IMData;
1920     jobject globalRef;
1921     XIC ic;
1922 
1923     AWT_LOCK();
1924 
1925     if (!window) {
1926         JNU_ThrowNullPointerException(env, "NullPointerException");
1927         AWT_UNLOCK();
1928         return JNI_FALSE;
1929     }
1930 
1931     pX11IMData = (X11InputMethodData *) calloc(1, sizeof(X11InputMethodData));
1932     if (pX11IMData == NULL) {
1933         THROW_OUT_OF_MEMORY_ERROR();
1934         AWT_UNLOCK();
1935         return JNI_FALSE;
1936     }
1937 
1938     globalRef = (*env)->NewGlobalRef(env, this);
1939     pX11IMData->x11inputmethod = globalRef;

1940     pX11IMData->statusWindow = NULL;

1941 
1942     setX11InputMethodData(env, this, pX11IMData);

1943 
1944     if (createXIC(env, pX11IMData, (Window)window) == False) {
1945         destroyX11InputMethodData((JNIEnv *) NULL, pX11IMData);
1946         pX11IMData = (X11InputMethodData *) NULL;
1947         setX11InputMethodData(env, this, pX11IMData);
1948         if ((*env)->ExceptionCheck(env)) {
1949             goto finally;
1950         }
1951     }
1952 


1953 finally:
1954     AWT_UNLOCK();
1955     return (pX11IMData != NULL);
1956 }
1957 
1958 JNIEXPORT void JNICALL
1959 Java_sun_awt_X11_XInputMethod_setXICFocusNative(JNIEnv *env,
1960                                                 jobject this,
1961                                                 jlong w,
1962                                                 jboolean req,
1963                                                 jboolean active)
1964 {
1965     X11InputMethodData *pX11IMData;
1966     AWT_LOCK();
1967     pX11IMData = getX11InputMethodData(env, this);
1968     if (pX11IMData == NULL) {
1969         AWT_UNLOCK();
1970         return;
1971     }
1972 
1973     if (req) {
1974         if (!w) {
1975             AWT_UNLOCK();
1976             return;
1977         }
1978         pX11IMData->isActiveClient = active;
1979         pX11IMData->current_ic = active ?
1980                         pX11IMData->ic_active : pX11IMData->ic_passive;
1981         /*
1982          * On Solaris2.6, setXICWindowFocus() has to be invoked
1983          * before setting focus.
1984          */
1985         get_current_focus(pX11IMData->current_ic); /* workaround for kinput2 and SCIM */
1986         if (currentFocusWindow != w) {
1987             setXICWindowFocus(pX11IMData->current_ic, w);
1988             setXICFocus(pX11IMData->current_ic, req);
1989             currentX11InputMethodInstance = pX11IMData->x11inputmethod;
1990             currentFocusWindow =  w;
1991         } else {
1992             setXICFocus(pX11IMData->current_ic, req);
1993         }
1994         if ((active || pX11IMData->passiveStatusWindow)
1995             && (pX11IMData->statusWindow && pX11IMData->statusWindow->on))
1996             onoffStatusWindow(pX11IMData, w, True);

1997     } else {
1998         currentX11InputMethodInstance = NULL;
1999         currentFocusWindow = 0;

2000         onoffStatusWindow(pX11IMData, 0, False);
2001         if (pX11IMData->current_ic != NULL)

2002         setXICFocus(pX11IMData->current_ic, req);
2003 
2004         pX11IMData->current_ic = (XIC)0;
2005     }
2006 
2007     XFlush(dpy);
2008     AWT_UNLOCK();
2009 }
2010 
2011 /*
2012  * Class:     sun_awt_X11InputMethodBase
2013  * Method:    initIDs
2014  * Signature: ()V
2015  * This function gets called from the static initializer for
2016  * X11InputMethod.java to initialize the fieldIDs for fields
2017  * that may be accessed from C
2018  */
2019 JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_initIDs
2020   (JNIEnv *env, jclass cls)
2021 {
2022     x11InputMethodIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J");
2023 }
2024 
2025 /*
2026  * Class:     sun_awt_X11InputMethodBase
2027  * Method:    turnoffStatusWindow
2028  * Signature: ()V
2029  */
2030 JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_turnoffStatusWindow
2031   (JNIEnv *env, jobject this)
2032 {

2033     X11InputMethodData *pX11IMData;
2034     StatusWindow *statusWindow;
2035 
2036     AWT_LOCK();
2037 
2038     if (NULL == currentX11InputMethodInstance

2039         || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))
2040         || NULL == (statusWindow = pX11IMData->statusWindow)
2041         || !statusWindow->on ){
2042         AWT_UNLOCK();
2043         return;
2044     }
2045     onoffStatusWindow(pX11IMData, 0, False);
2046     statusWindow->on = False;
2047 
2048     AWT_UNLOCK();

2049 }
2050 
2051 /*
2052  * Class:     sun_awt_X11InputMethodBase
2053  * Method:    disposeXIC
2054  * Signature: ()V
2055  */
2056 JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_disposeXIC
2057   (JNIEnv *env, jobject this)
2058 {
2059     X11InputMethodData *pX11IMData = NULL;
2060 
2061     AWT_LOCK();
2062     pX11IMData = getX11InputMethodData(env, this);
2063     if (pX11IMData == NULL) {
2064         AWT_UNLOCK();
2065         return;
2066     }
2067 
2068     setX11InputMethodData(env, this, NULL);
2069 
2070     if (pX11IMData->x11inputmethod == currentX11InputMethodInstance) {
2071         currentX11InputMethodInstance = NULL;
2072         currentFocusWindow = 0;
2073     }
2074     destroyX11InputMethodData(env, pX11IMData);
2075     AWT_UNLOCK();
2076 }
2077 
2078 /*
2079  * Class:     sun_awt_X11InputMethodBase
2080  * Method:    resetXIC
2081  * Signature: ()Ljava/lang/String;
2082  */
2083 JNIEXPORT jstring JNICALL Java_sun_awt_X11InputMethodBase_resetXIC
2084   (JNIEnv *env, jobject this)
2085 {
2086     X11InputMethodData *pX11IMData;
2087     char *xText = NULL;
2088     jstring jText = (jstring)0;
2089 
2090     AWT_LOCK();
2091     pX11IMData = getX11InputMethodData(env, this);
2092     if (pX11IMData == NULL) {
2093         AWT_UNLOCK();
2094         return jText;
2095     }
2096 
2097     if (pX11IMData->current_ic) {
2098         if (!isPreeditStateActive(pX11IMData->current_ic)) {
2099             xText = NULL;
2100         } else {
2101             if (!(pX11IMData->forceReset))
2102                 setXICFocus(pX11IMData->current_ic, FALSE);
2103             xText = XmbResetIC(pX11IMData->current_ic);
2104             if (!(pX11IMData->forceReset))
2105                 setXICFocus(pX11IMData->current_ic, TRUE);
2106         }
2107     } else {
2108         /*
2109          * If there is no reference to the current XIC, try to reset both XICs.
2110          */
2111         if (!isPreeditStateActive(pX11IMData->ic_active))
2112             xText = NULL;
2113         else
2114         xText = XmbResetIC(pX11IMData->ic_active);
2115         /*it may also means that the real client component does
2116           not have focus -- has been deactivated... its xic should
2117           not have the focus, bug#4284651 showes reset XIC for htt
2118           may bring the focus back, so de-focus it again.
2119         */
2120         setXICFocus(pX11IMData->ic_active, FALSE);
2121         if (pX11IMData->ic_active != pX11IMData->ic_passive) {
2122             char *tmpText;
2123             if (!isPreeditStateActive(pX11IMData->ic_passive))
2124                 tmpText = NULL;
2125             else
2126                 tmpText = XmbResetIC(pX11IMData->ic_passive);
2127             setXICFocus(pX11IMData->ic_passive, FALSE);
2128             if (xText == (char *)NULL && tmpText)
2129                 xText = tmpText;
2130         }

2131     }
2132     if (xText != NULL) {
2133         jText = JNU_NewStringPlatform(env, (const char *)xText);
2134         XFree((void *)xText);
2135     }
2136 
2137     /* workaround
2138      * Some IME do not call PreeditDoneCallback routine even
2139      * when XmbResetIC is called. I force to reset the preedit string.
2140      */
2141     if (!pX11IMData->isActiveClient) {
2142         resetPassivePreeditText(pX11IMData->statusWindow);
2143         shrink_status(pX11IMData->statusWindow);
2144     } else {
2145         JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
2146                              "clearComposedText",
2147                              "()V");
2148         if ((*env)->ExceptionOccurred(env)) {
2149             (*env)->ExceptionDescribe(env);
2150             (*env)->ExceptionClear(env);
2151         }
2152     }
2153 
2154     AWT_UNLOCK();
2155     return jText;
2156 }
2157 
2158 /*
2159  * Class:     sun_awt_X11InputMethodBase
2160  * Method:    setCompositionEnabledNative
2161  * Signature: (Z)Z
2162  *
2163  * This method tries to set the XNPreeditState attribute associated with the current
2164  * XIC to the passed in 'enable' state.
2165  *
2166  * Return JNI_TRUE if XNPreeditState attribute is successfully changed to the
2167  * 'enable' state; Otherwise, if XSetICValues fails to set this attribute,
2168  * java.lang.UnsupportedOperationException will be thrown. JNI_FALSE is returned if this
2169  * method fails due to other reasons.

2170  */
2171 JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_setCompositionEnabledNative
2172   (JNIEnv *env, jobject this, jboolean enable)
2173 {
2174     X11InputMethodData *pX11IMData;
2175     char * ret = NULL;
2176     XVaNestedList pr_atrb;
2177 
2178     AWT_LOCK();
2179     pX11IMData = getX11InputMethodData(env, this);
2180 
2181     if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {
2182         AWT_UNLOCK();
2183         return JNI_FALSE;
2184     }
2185 
2186     pr_atrb = XVaCreateNestedList(0, XNPreeditState,
2187                   (enable ? XIMPreeditEnable : XIMPreeditDisable), NULL);
2188     ret = XSetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL);
2189     XFree((void *)pr_atrb);
2190     AWT_UNLOCK();
2191 
2192     if ((ret != 0) &&
2193         ((strcmp(ret, XNPreeditAttributes) == 0)
2194          || (strcmp(ret, XNPreeditState) == 0))) {
2195         JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
2196     }
2197 
2198     return (jboolean)(ret == 0);
2199 }
2200 
2201 /*
2202  * Class:     sun_awt_X11InputMethodBase
2203  * Method:    isCompositionEnabledNative
2204  * Signature: ()Z
2205  *
2206  * This method tries to get the XNPreeditState attribute associated with the current XIC.
2207  *
2208  * Return JNI_TRUE if the XNPreeditState is successfully retrieved. Otherwise, if
2209  * XGetICValues fails to get this attribute, java.lang.UnsupportedOperationException
2210  * will be thrown. JNI_FALSE is returned if this method fails due to other reasons.

2211  */
2212 JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_isCompositionEnabledNative
2213   (JNIEnv *env, jobject this)
2214 {
2215     X11InputMethodData *pX11IMData = NULL;
2216     char * ret = NULL;
2217     XIMPreeditState state = XIMPreeditUnKnown;
2218     XVaNestedList   pr_atrb;
2219 
2220     AWT_LOCK();
2221     pX11IMData = getX11InputMethodData(env, this);
2222 
2223     if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {
2224         AWT_UNLOCK();
2225         return JNI_FALSE;
2226     }
2227 
2228     pr_atrb = XVaCreateNestedList(0, XNPreeditState, &state, NULL);
2229     ret = XGetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL);
2230     XFree((void *)pr_atrb);
2231     AWT_UNLOCK();
2232 
2233     if ((ret != 0) &&
2234         ((strcmp(ret, XNPreeditAttributes) == 0)
2235          || (strcmp(ret, XNPreeditState) == 0))) {
2236         JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
2237         return JNI_FALSE;
2238     }
2239 
2240     return (jboolean)(state == XIMPreeditEnable);
2241 }
2242 
2243 JNIEXPORT void JNICALL Java_sun_awt_X11_XInputMethod_adjustStatusWindow
2244   (JNIEnv *env, jobject this, jlong window)
2245 {
2246 
2247 }
2248 
2249 /*
2250  * Class:     sun_awt_X11InputMethod
2251  * Method:    setStatusAreaVisible
2252  * Signature: (ZJ)V
2253  */
2254 JNIEXPORT void JNICALL Java_sun_awt_X11InputMethod_setStatusAreaVisible
2255   (JNIEnv *env, jobject this, jboolean value, jlong data)
2256 {
2257     X11InputMethodData *pX11IMData;
2258 
2259     pX11IMData = getX11InputMethodData(env, this);
2260     if (NULL == pX11IMData) return;
2261     if (NULL == pX11IMData->statusWindow) return;
2262 
2263     if ((int)value){
2264         pX11IMData->statusWindow->on = True;
2265     }else{
2266         pX11IMData->statusWindow->on = False;
2267     }
2268     return;
2269 }
< prev index next >