< prev index next >

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

Print this page




  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #ifdef HEADLESS
  27     #error This file should not be included in headless library
  28 #endif
  29 
  30 #include <stdio.h>
  31 #include <stdlib.h>
  32 #include <X11/Xlib.h>
  33 #include <X11/keysym.h>
  34 #include <sys/time.h>
  35 








  36 #include "awt.h"
  37 #include "awt_p.h"
  38 
  39 #include <sun_awt_X11InputMethod.h>
  40 #include <sun_awt_X11_XInputMethod.h>
  41 
  42 #define THROW_OUT_OF_MEMORY_ERROR() \
  43         JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL)
  44 




  45 struct X11InputMethodIDs {
  46   jfieldID pData;
  47 } x11InputMethodIDs;
  48 

  49 static void PreeditStartCallback(XIC, XPointer, XPointer);



  50 static void PreeditDoneCallback(XIC, XPointer, XPointer);
  51 static void PreeditDrawCallback(XIC, XPointer,
  52                                 XIMPreeditDrawCallbackStruct *);
  53 static void PreeditCaretCallback(XIC, XPointer,
  54                                  XIMPreeditCaretCallbackStruct *);
  55 #if defined(__linux__) || defined(MACOSX)
  56 static void StatusStartCallback(XIC, XPointer, XPointer);
  57 static void StatusDoneCallback(XIC, XPointer, XPointer);
  58 static void StatusDrawCallback(XIC, XPointer,
  59                                XIMStatusDrawCallbackStruct *);
  60 #endif
  61 
  62 #define ROOT_WINDOW_STYLES      (XIMPreeditNothing | XIMStatusNothing)
  63 #define NO_STYLES               (XIMPreeditNone | XIMStatusNone)




  64 
  65 #define PreeditStartIndex       0
  66 #define PreeditDoneIndex        1
  67 #define PreeditDrawIndex        2
  68 #define PreeditCaretIndex       3
  69 #if defined(__linux__) || defined(MACOSX)
  70 #define StatusStartIndex        4
  71 #define StatusDoneIndex         5
  72 #define StatusDrawIndex         6
  73 #define NCALLBACKS              7
  74 #else
  75 #define NCALLBACKS              4
  76 #endif
  77 









  78 /*
  79  * Callback function pointers: the order has to match the *Index
  80  * values above.
  81  */
  82 static XIMProc callback_funcs[NCALLBACKS] = {
  83     (XIMProc)PreeditStartCallback,
  84     (XIMProc)PreeditDoneCallback,
  85     (XIMProc)PreeditDrawCallback,
  86     (XIMProc)PreeditCaretCallback,
  87 #if defined(__linux__) || defined(MACOSX)
  88     (XIMProc)StatusStartCallback,
  89     (XIMProc)StatusDoneCallback,
  90     (XIMProc)StatusDrawCallback,
  91 #endif
  92 };
  93 
  94 #if defined(__linux__) || defined(MACOSX)
  95 #define MAX_STATUS_LEN  100
  96 typedef struct {
  97     Window   w;                /*status window id        */
  98     Window   root;             /*the root window id      */
  99     Window   parent;           /*parent shell window     */



 100     int      x, y;             /*parent's upperleft position */
 101     int      width, height;    /*parent's width, height  */
 102     GC       lightGC;          /*gc for light border     */
 103     GC       dimGC;            /*gc for dim border       */
 104     GC       bgGC;             /*normal painting         */
 105     GC       fgGC;             /*normal painting         */
 106     int      statusW, statusH; /*status window's w, h    */
 107     int      rootW, rootH;     /*root window's w, h    */
 108     int      bWidth;           /*border width            */

 109     char     status[MAX_STATUS_LEN]; /*status text       */



 110     XFontSet fontset;           /*fontset for drawing    */
 111     int      off_x, off_y;
 112     Bool     on;                /*if the status window on*/









 113 } StatusWindow;
 114 #endif
 115 
 116 /*
 117  * X11InputMethodData keeps per X11InputMethod instance information. A pointer
 118  * to this data structure is kept in an X11InputMethod object (pData).
 119  */
 120 typedef struct _X11InputMethodData {
 121     XIC         current_ic;     /* current X Input Context */
 122     XIC         ic_active;      /* X Input Context for active clients */
 123     XIC         ic_passive;     /* X Input Context for passive clients */
 124     XIMCallback *callbacks;     /* callback parameters */
 125     jobject     x11inputmethod; /* global ref to X11InputMethod instance */
 126                                 /* associated with the XIC */
 127 #if defined(__linux__) || defined(MACOSX)
 128     StatusWindow *statusWindow; /* our own status window  */
 129 #endif

 130     char        *lookup_buf;    /* buffer used for XmbLookupString */
 131     int         lookup_buf_len; /* lookup buffer size in bytes */





 132 } X11InputMethodData;
 133 

 134 /*
 135  * When XIC is created, a global reference is created for
 136  * sun.awt.X11InputMethod object so that it could be used by the XIM callback
 137  * functions. This could be a dangerous thing to do when the original
 138  * X11InputMethod object is garbage collected and as a result,
 139  * destroyX11InputMethodData is called to delete the global reference.
 140  * If any XIM callback function still holds and uses the "already deleted"
 141  * global reference, disaster is going to happen. So we have to maintain
 142  * a list for these global references which is consulted first when the
 143  * callback functions or any function tries to use "currentX11InputMethodObject"
 144  * which always refers to the global reference try to use it.
 145  *
 146  */
 147 typedef struct _X11InputMethodGRefNode {
 148     jobject inputMethodGRef;
 149     struct _X11InputMethodGRefNode* next;
 150 } X11InputMethodGRefNode;
 151 
 152 X11InputMethodGRefNode *x11InputMethodGRefListHead = NULL;

 153 
 154 /* reference to the current X11InputMethod instance, it is always
 155    point to the global reference to the X11InputMethodObject since
 156    it could be referenced by different threads. */
 157 jobject currentX11InputMethodInstance = NULL;
 158 
 159 Window  currentFocusWindow = 0;  /* current window that has focus for input
 160                                        method. (the best place to put this
 161                                        information should be
 162                                        currentX11InputMethodInstance's pData) */
 163 static XIM X11im = NULL;
 164 Display * dpy = NULL;
 165 
 166 #define GetJNIEnv() (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2)
 167 

 168 static void DestroyXIMCallback(XIM, XPointer, XPointer);
 169 static void OpenXIMCallback(Display *, XPointer, XPointer);



 170 /* Solaris XIM Extention */
 171 #define XNCommitStringCallback "commitStringCallback"
 172 static void CommitStringCallback(XIC, XPointer, XPointer);

 173 
 174 static X11InputMethodData * getX11InputMethodData(JNIEnv *, jobject);
 175 static void setX11InputMethodData(JNIEnv *, jobject, X11InputMethodData *);
 176 static void destroyX11InputMethodData(JNIEnv *, X11InputMethodData *);
 177 static void freeX11InputMethodData(JNIEnv *, X11InputMethodData *);
 178 
 179 #ifdef __solaris__
 180 /* Prototype for this function is missing in Solaris X11R6 Xlib.h */
 181 extern char *XSetIMValues(
 182 #if NeedVarargsPrototypes
 183     XIM /* im */, ...
 184 #endif
 185 );
 186 #endif
 187 


























 188 /*
 189  * This function is stolen from /src/solaris/hpi/src/system_md.c
 190  * It is used in setting the time in Java-level InputEvents
 191  */
 192 jlong
 193 awt_util_nowMillisUTC()
 194 {
 195     struct timeval t;
 196     gettimeofday(&t, NULL);
 197     return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000);
 198 }
 199 
 200 /*
 201  * Converts the wchar_t string to a multi-byte string calling wcstombs(). A
 202  * buffer is allocated by malloc() to store the multi-byte string. NULL is
 203  * returned if the given wchar_t string pointer is NULL or buffer allocation is
 204  * failed.
 205  */
 206 static char *
 207 wcstombsdmp(wchar_t *wcs, int len)


 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 }


 291          if (cX11InputMethodGRef->inputMethodGRef == x11InputMethodGRef) {
 292              break;
 293          }
 294          pX11InputMethodGRef = cX11InputMethodGRef;
 295          cX11InputMethodGRef = cX11InputMethodGRef->next;
 296      }
 297 
 298      if (cX11InputMethodGRef == NULL) {
 299          return; /* Not found. */
 300      }
 301 
 302      if (cX11InputMethodGRef == x11InputMethodGRefListHead) {
 303          x11InputMethodGRefListHead = x11InputMethodGRefListHead->next;
 304      } else {
 305          pX11InputMethodGRef->next = cX11InputMethodGRef->next;
 306      }
 307      free(cX11InputMethodGRef);
 308 
 309      return;
 310 }

 311 
 312 
 313 static X11InputMethodData * getX11InputMethodData(JNIEnv * env, jobject imInstance) {
 314     X11InputMethodData *pX11IMData =
 315         (X11InputMethodData *)JNU_GetLongFieldAsPtr(env, imInstance, x11InputMethodIDs.pData);
 316 
 317     /*
 318      * In case the XIM server was killed somehow, reset X11InputMethodData.
 319      */
 320     if (X11im == NULL && pX11IMData != NULL) {
 321         JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
 322                              "flushText",
 323                              "()V");
 324         JNU_CHECK_EXCEPTION_RETURN(env, NULL);






 325         /* IMPORTANT:
 326            The order of the following calls is critical since "imInstance" may
 327            point to the global reference itself, if "freeX11InputMethodData" is called
 328            first, the global reference will be destroyed and "setX11InputMethodData"
 329            will in fact fail silently. So pX11IMData will not be set to NULL.
 330            This could make the original java object refers to a deleted pX11IMData
 331            object.
 332         */
 333         setX11InputMethodData(env, imInstance, NULL);
 334         freeX11InputMethodData(env, pX11IMData);
 335         pX11IMData = NULL;
 336     }
 337 
 338     return pX11IMData;
 339 }
 340 
 341 static void setX11InputMethodData(JNIEnv * env, jobject imInstance, X11InputMethodData *pX11IMData) {
 342     JNU_SetLongFieldFromPtr(env, imInstance, x11InputMethodIDs.pData, pX11IMData);
 343 }
 344 


 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 


 438  * Invokes XmbLookupString() to get something from the XIM. It invokes
 439  * X11InputMethod.dispatchCommittedText() if XmbLookupString() returns
 440  * committed text.  This function is called from handleKeyEvent in canvas.c and
 441  * it's under the Motif event loop thread context.
 442  *
 443  * Buffer usage: There is a bug in XFree86-4.3.0 XmbLookupString implementation,
 444  * where it never returns XBufferOverflow.  We need to allocate the initial lookup buffer
 445  * big enough, so that the possibility that user encounters this problem is relatively
 446  * small.  When this bug gets fixed, we can make the initial buffer size smaller.
 447  * Note that XmbLookupString() sometimes produces a non-null-terminated string.
 448  *
 449  * Returns True when there is a keysym value to be handled.
 450  */
 451 #define INITIAL_LOOKUP_BUF_SIZE 512
 452 
 453 Boolean
 454 awt_x11inputmethod_lookupString(XKeyPressedEvent *event, KeySym *keysymp)
 455 {
 456     JNIEnv *env = GetJNIEnv();
 457     X11InputMethodData *pX11IMData = NULL;





 458     KeySym keysym = NoSymbol;
 459     Status status;
 460     int mblen;
 461     jstring javastr;
 462     XIC ic;
 463     Boolean result = True;
 464     static Boolean composing = False;
 465 
 466     /*
 467       printf("lookupString: entering...\n");
 468      */
 469 

 470     if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) {
 471         currentX11InputMethodInstance = NULL;
 472         return False;
 473     }

 474 
 475     pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance);
 476 
 477     if (pX11IMData == NULL) {
 478 #if defined(__linux__) || defined(MACOSX)
 479         return False;
 480 #else
 481         return result;
 482 #endif
 483     }
 484 
 485     if ((ic = pX11IMData->current_ic) == (XIC)0){
 486 #if defined(__linux__) || defined(MACOSX)
 487         return False;
 488 #else
 489         return result;
 490 #endif
 491     }
 492 

 493     /* allocate the lookup buffer at the first invocation */
 494     if (pX11IMData->lookup_buf_len == 0) {
 495         pX11IMData->lookup_buf = (char *)malloc(INITIAL_LOOKUP_BUF_SIZE);
 496         if (pX11IMData->lookup_buf == NULL) {
 497             THROW_OUT_OF_MEMORY_ERROR();
 498             return result;
 499         }
 500         pX11IMData->lookup_buf_len = INITIAL_LOOKUP_BUF_SIZE;
 501     }
 502 
 503     mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf,
 504                             pX11IMData->lookup_buf_len - 1, &keysym, &status);





 505 
 506     /*
 507      * In case of overflow, a buffer is allocated and it retries
 508      * XmbLookupString().
 509      */
 510     if (status == XBufferOverflow) {

 511         free((void *)pX11IMData->lookup_buf);
 512         pX11IMData->lookup_buf_len = 0;
 513         pX11IMData->lookup_buf = (char *)malloc(mblen + 1);
 514         if (pX11IMData->lookup_buf == NULL) {
 515             THROW_OUT_OF_MEMORY_ERROR();
 516             return result;
 517         }
 518         pX11IMData->lookup_buf_len = mblen + 1;
 519         mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf,
 520                             pX11IMData->lookup_buf_len - 1, &keysym, &status);






 521     }




 522     pX11IMData->lookup_buf[mblen] = 0;



 523 
 524     /* Get keysym without taking modifiers into account first to map
 525      * to AWT keyCode table.
 526      */
 527     switch (status) {
 528     case XLookupBoth:
 529         if (!composing) {
 530             if (event->keycode != 0) {
 531                 *keysymp = keysym;
 532                 result = False;
 533                 break;
 534             }
 535         }
 536         composing = False;
 537         /*FALLTHRU*/
 538     case XLookupChars:
 539     /*
 540      printf("lookupString: status=XLookupChars, type=%d, state=%x, keycode=%x, keysym=%x\n",
 541        event->type, event->state, event->keycode, keysym);
 542     */

 543         javastr = JNU_NewStringPlatform(env, (const char *)pX11IMData->lookup_buf);



 544         if (javastr != NULL) {
 545             JNU_CallMethodByName(env, NULL,
 546                                  currentX11InputMethodInstance,
 547                                  "dispatchCommittedText",
 548                                  "(Ljava/lang/String;J)V",
 549                                  javastr,
 550                                  event->time);






 551         }
 552         break;
 553 
 554     case XLookupKeySym:
 555     /*
 556      printf("lookupString: status=XLookupKeySym, type=%d, state=%x, keycode=%x, keysym=%x\n",
 557        event->type, event->state, event->keycode, keysym);
 558     */
 559         if (keysym == XK_Multi_key)
 560             composing = True;
 561         if (! composing) {
 562             *keysymp = keysym;
 563             result = False;
 564         }
 565         break;
 566 
 567     case XLookupNone:
 568     /*
 569      printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n",
 570         event->type, event->state, event->keycode, keysym);
 571     */
 572         break;
 573     }
 574 



 575     return result;
 576 }
 577 
 578 #if defined(__linux__) || defined(MACOSX)
 579 static StatusWindow *createStatusWindow(
 580                                 Window parent) {
 581     StatusWindow *statusWindow;
 582     XSetWindowAttributes attrib;
 583     unsigned long attribmask;
 584     Window containerWindow;
 585     Window status;
 586     Window child;
 587     XWindowAttributes xwa;
 588     XWindowAttributes xxwa;
 589     /* Variable for XCreateFontSet()*/
 590     char **mclr;
 591     int  mccr = 0;
 592     char *dsr;
 593     unsigned long bg, fg, light, dim;
 594     int x, y, off_x, off_y, xx, yy;
 595     unsigned int w, h, bw, depth;
 596     XGCValues values;
 597     unsigned long valuemask = 0;  /*ignore XGCvalue and use defaults*/
 598     int screen = 0;
 599     int i;
 600     AwtGraphicsConfigDataPtr adata;
 601     extern int awt_numScreens;
 602     /*hardcode the size right now, should get the size base on font*/
 603     int   width=80, height=22;
 604     Window rootWindow;
 605     Window *ignoreWindowPtr;
 606     unsigned int ignoreUnit;








 607 
 608     XGetGeometry(dpy, parent, &rootWindow, &x, &y, &w, &h, &bw, &depth);
 609 
 610     attrib.override_redirect = True;
 611     attribmask = CWOverrideRedirect;
 612     for (i = 0; i < awt_numScreens; i++) {
 613         if (RootWindow(dpy, i) == rootWindow) {
 614             screen = i;
 615             break;
 616         }
 617     }
 618     adata = getDefaultConfig(screen);
 619     bg    = adata->AwtColorMatch(255, 255, 255, adata);
 620     fg    = adata->AwtColorMatch(0, 0, 0, adata);
 621     light = adata->AwtColorMatch(195, 195, 195, adata);
 622     dim   = adata->AwtColorMatch(128, 128, 128, adata);
 623 

 624     XGetWindowAttributes(dpy, parent, &xwa);









 625     bw = 2; /*xwa.border_width does not have the correct value*/
 626 
 627     /*compare the size difference between parent container
 628       and shell widget, the diff should be the border frame
 629       and title bar height (?)*/
 630 
 631     XQueryTree( dpy,

 632                 parent,



 633                 &rootWindow,
 634                 &containerWindow,
 635                 &ignoreWindowPtr,
 636                 &ignoreUnit);
 637     XGetWindowAttributes(dpy, containerWindow, &xxwa);
 638 

 639     off_x = (xxwa.width - xwa.width) / 2;
 640     off_y = xxwa.height - xwa.height - off_x; /*it's magic:-) */























 641 
 642     /*get the size of root window*/
 643     XGetWindowAttributes(dpy, rootWindow, &xxwa);
 644 
 645     XTranslateCoordinates(dpy,

 646                           parent, xwa.root,



 647                           xwa.x, xwa.y,
 648                           &x, &y,
 649                           &child);
 650     xx = x - off_x;
 651     yy = y + xwa.height - off_y;
 652     if (xx < 0 ){
 653         xx = 0;
 654     }
 655     if (xx + width > xxwa.width){
 656         xx = xxwa.width - width;
 657     }
 658     if (yy + height > xxwa.height){
 659         yy = xxwa.height - height;
 660     }
 661 










 662     status =  XCreateWindow(dpy,
 663                             xwa.root,
 664                             xx, yy,
 665                             width, height,
 666                             0,
 667                             xwa.depth,
 668                             InputOutput,
 669                             adata->awt_visInfo.visual,
 670                             attribmask, &attrib);
 671     XSelectInput(dpy, status,
 672                  ExposureMask | StructureNotifyMask | EnterWindowMask |
 673                  LeaveWindowMask | VisibilityChangeMask);










 674     statusWindow = (StatusWindow*) calloc(1, sizeof(StatusWindow));
 675     if (statusWindow == NULL){
 676         THROW_OUT_OF_MEMORY_ERROR();
 677         return NULL;
 678     }
 679     statusWindow->w = status;

 680     //12-point font
 681     statusWindow->fontset = XCreateFontSet(dpy,
 682                                            "-*-*-medium-r-normal-*-*-120-*-*-*-*",
 683                                            &mclr, &mccr, &dsr);
 684     /* In case we didn't find the font set, release the list of missing characters */
 685     if (mccr > 0) {
 686         XFreeStringList(mclr);
 687     }



 688     statusWindow->parent = parent;



 689     statusWindow->on  = False;
 690     statusWindow->x = x;
 691     statusWindow->y = y;
 692     statusWindow->width = xwa.width;
 693     statusWindow->height = xwa.height;
 694     statusWindow->off_x = off_x;
 695     statusWindow->off_y = off_y;
 696     statusWindow->bWidth  = bw;
 697     statusWindow->statusH = height;
 698     statusWindow->statusW = width;



 699     statusWindow->rootH = xxwa.height;
 700     statusWindow->rootW = xxwa.width;
 701     statusWindow->lightGC = XCreateGC(dpy, status, valuemask, &values);
 702     XSetForeground(dpy, statusWindow->lightGC, light);
 703     statusWindow->dimGC = XCreateGC(dpy, status, valuemask, &values);
 704     XSetForeground(dpy, statusWindow->dimGC, dim);

 705     statusWindow->fgGC = XCreateGC(dpy, status, valuemask, &values);



 706     XSetForeground(dpy, statusWindow->fgGC, fg);

 707     statusWindow->bgGC = XCreateGC(dpy, status, valuemask, &values);



 708     XSetForeground(dpy, statusWindow->bgGC, bg);




 709     return statusWindow;
 710 }
 711 
 712 /* This method is to turn off or turn on the status window. */
 713 static void onoffStatusWindow(X11InputMethodData* pX11IMData,
 714                                 Window parent,
 715                                 Bool ON){
 716     XWindowAttributes xwa;
 717     Window child;
 718     int x, y;
 719     StatusWindow *statusWindow = NULL;
 720 

 721     if (NULL == currentX11InputMethodInstance ||
 722         NULL == pX11IMData ||



 723         NULL == (statusWindow =  pX11IMData->statusWindow)){
 724         return;
 725     }
 726 
 727     if (ON == False){
 728         XUnmapWindow(dpy, statusWindow->w);

 729         statusWindow->on = False;

 730         return;
 731     }

 732     parent = JNU_CallMethodByName(GetJNIEnv(), NULL, pX11IMData->x11inputmethod,








 733                                   "getCurrentParentWindow",
 734                                   "()J").j;







 735     if (statusWindow->parent != parent){
 736         statusWindow->parent = parent;
 737     }

 738     XGetWindowAttributes(dpy, parent, &xwa);
 739     XTranslateCoordinates(dpy,
 740                           parent, xwa.root,
 741                           xwa.x, xwa.y,
 742                           &x, &y,
 743                           &child);
 744     if (statusWindow->x != x
 745         || statusWindow->y != y
 746         || statusWindow->height != xwa.height){
 747         statusWindow->x = x;
 748         statusWindow->y = y;
 749         statusWindow->height = xwa.height;
 750         x = statusWindow->x - statusWindow->off_x;
 751         y = statusWindow->y + statusWindow->height - statusWindow->off_y;
 752         if (x < 0 ){
 753             x = 0;
 754         }
 755         if (x + statusWindow->statusW > statusWindow->rootW){
 756             x = statusWindow->rootW - statusWindow->statusW;
 757         }
 758         if (y + statusWindow->statusH > statusWindow->rootH){
 759             y = statusWindow->rootH - statusWindow->statusH;
 760         }
 761         XMoveWindow(dpy, statusWindow->w, x, y);
 762     }
 763     statusWindow->on = True;
 764     XMapWindow(dpy, statusWindow->w);







 765 }
 766 
 767 void paintStatusWindow(StatusWindow *statusWindow){
 768     Window  win  = statusWindow->w;
 769     GC  lightgc = statusWindow->lightGC;
 770     GC  dimgc = statusWindow->dimGC;
 771     GC  bggc = statusWindow->bgGC;
 772     GC  fggc = statusWindow->fgGC;
 773 
 774     int width = statusWindow->statusW;
 775     int height = statusWindow->statusH;
 776     int bwidth = statusWindow->bWidth;
















 777     XFillRectangle(dpy, win, bggc, 0, 0, width, height);
 778     /* draw border */
 779     XDrawLine(dpy, win, fggc, 0, 0, width, 0);
 780     XDrawLine(dpy, win, fggc, 0, height-1, width-1, height-1);
 781     XDrawLine(dpy, win, fggc, 0, 0, 0, height-1);
 782     XDrawLine(dpy, win, fggc, width-1, 0, width-1, height-1);
 783 
 784     XDrawLine(dpy, win, lightgc, 1, 1, width-bwidth, 1);
 785     XDrawLine(dpy, win, lightgc, 1, 1, 1, height-2);
 786     XDrawLine(dpy, win, lightgc, 1, height-2, width-bwidth, height-2);
 787     XDrawLine(dpy, win, lightgc, width-bwidth-1, 1, width-bwidth-1, height-2);
 788 
 789     XDrawLine(dpy, win, dimgc, 2, 2, 2, height-3);
 790     XDrawLine(dpy, win, dimgc, 2, height-3, width-bwidth-1, height-3);
 791     XDrawLine(dpy, win, dimgc, 2, 2, width-bwidth-2, 2);
 792     XDrawLine(dpy, win, dimgc, width-bwidth, 2, width-bwidth, height-3);







 793     if (statusWindow->fontset){

 794         XmbDrawString(dpy, win, statusWindow->fontset, fggc,
 795                       bwidth + 2, height - bwidth - 4,




 796                       statusWindow->status,

 797                       strlen(statusWindow->status));



 798     }
 799     else{
 800         /*too bad we failed to create a fontset for this locale*/
 801         XDrawString(dpy, win, fggc, bwidth + 2, height - bwidth - 4,
 802                     "[InputMethod ON]", strlen("[InputMethod ON]"));
 803     }
 804 }
 805 

 806 void statusWindowEventHandler(XEvent event){



 807     JNIEnv *env = GetJNIEnv();
 808     X11InputMethodData *pX11IMData = NULL;
 809     StatusWindow *statusWindow;
 810 

 811     if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) {
 812         currentX11InputMethodInstance = NULL;

 813         return;



 814     }

 815 
 816     if (NULL == currentX11InputMethodInstance
 817         || NULL == (pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance))

 818         || NULL == (statusWindow = pX11IMData->statusWindow)
 819         || statusWindow->w != event.xany.window){
 820         return;




 821     }
 822 



 823     switch (event.type){
 824     case Expose:
 825         paintStatusWindow(statusWindow);





 826         break;

 827     case MapNotify:

 828     case ConfigureNotify:





 829         {
 830           /*need to reset the stackMode...*/
 831             XWindowChanges xwc;
 832             int value_make = CWStackMode;
 833             xwc.stack_mode = TopIf;
 834             XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
 835         }

 836         break;
 837         /*
 838     case UnmapNotify:
 839     case VisibilityNotify:
 840         break;
 841         */
 842     default:
 843         break;
 844   }


































 845 }
 846 
 847 static void adjustStatusWindow(Window shell){
 848     JNIEnv *env = GetJNIEnv();
 849     X11InputMethodData *pX11IMData = NULL;
 850     StatusWindow *statusWindow;
 851 
 852     if (NULL == currentX11InputMethodInstance

 853         || !isX11InputMethodGRefInList(currentX11InputMethodInstance)

 854         || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))
 855         || NULL == (statusWindow = pX11IMData->statusWindow)
 856         || !statusWindow->on) {
 857         return;
 858     }




 859     {
 860         XWindowAttributes xwa;
 861         int x, y;
 862         Window child;
 863         XGetWindowAttributes(dpy, shell, &xwa);
 864         XTranslateCoordinates(dpy,
 865                               shell, xwa.root,
 866                               xwa.x, xwa.y,
 867                               &x, &y,
 868                               &child);
 869         if (statusWindow->x != x
 870             || statusWindow->y != y
 871             || statusWindow->height != xwa.height){
 872           statusWindow->x = x;
 873           statusWindow->y = y;
 874           statusWindow->height = xwa.height;
 875 
 876           x = statusWindow->x - statusWindow->off_x;
 877           y = statusWindow->y + statusWindow->height - statusWindow->off_y;
 878           if (x < 0 ){
 879               x = 0;
 880           }
 881           if (x + statusWindow->statusW > statusWindow->rootW){
 882               x = statusWindow->rootW - statusWindow->statusW;
 883           }
 884           if (y + statusWindow->statusH > statusWindow->rootH){
 885               y = statusWindow->rootH - statusWindow->statusH;
 886           }
 887           XMoveWindow(dpy, statusWindow->w, x, y);
 888         }
 889     }

 890 }
 891 #endif  /* __linux__ || MACOSX */
 892 /*
 893  * Creates two XICs, one for active clients and the other for passive
 894  * clients. All information on those XICs are stored in the
 895  * X11InputMethodData given by the pX11IMData parameter.
 896  *
 897  * For active clients: Try to use preedit callback to support
 898  * on-the-spot. If tc is not null, the XIC to be created will
 899  * share the Status Area with Motif widgets (TextComponents). If the
 900  * preferable styles can't be used, fallback to root-window styles. If
 901  * root-window styles failed, fallback to None styles.
 902  *
 903  * For passive clients: Try to use root-window styles. If failed,
 904  * fallback to None styles.
 905  */
 906 static Bool
 907 createXIC(JNIEnv * env, X11InputMethodData *pX11IMData, Window w)
 908 {
 909     XVaNestedList preedit = NULL;
 910     XVaNestedList status = NULL;
 911     XIMStyle on_the_spot_styles = XIMPreeditCallbacks,



 912              active_styles = 0,
 913              passive_styles = 0,
 914              no_styles = 0;
 915     XIMCallback *callbacks;
 916     unsigned short i;
 917     XIMStyles *im_styles;
 918     char *ret = NULL;





 919 
 920     if (X11im == NULL) {
 921         return False;
 922     }
 923     if (!w) {
 924         return False;
 925     }
 926 










 927     ret = XGetIMValues(X11im, XNQueryInputStyle, &im_styles, NULL);
 928 
 929     if (ret != NULL) {
 930         jio_fprintf(stderr,"XGetIMValues: %s\n",ret);
 931         return FALSE ;
 932     }
 933 
 934 #if defined(__linux__) || defined(MACOSX)
 935     on_the_spot_styles |= XIMStatusNothing;
 936 
 937     /*kinput does not support XIMPreeditCallbacks and XIMStatusArea
 938       at the same time, so use StatusCallback to draw the status
 939       ourself
 940     */
 941     for (i = 0; i < im_styles->count_styles; i++) {
 942         if (im_styles->supported_styles[i] == (XIMPreeditCallbacks | XIMStatusCallbacks)) {
 943             on_the_spot_styles = (XIMPreeditCallbacks | XIMStatusCallbacks);
 944             break;
 945         }
 946     }
 947 #else /*! __linux__ && !MACOSX */
 948     on_the_spot_styles |= XIMStatusNothing;
 949 #endif /* __linux__ || MACOSX */
 950 

 951     for (i = 0; i < im_styles->count_styles; i++) {
 952         active_styles |= im_styles->supported_styles[i] & on_the_spot_styles;
 953         passive_styles |= im_styles->supported_styles[i] & ROOT_WINDOW_STYLES;
 954         no_styles |= im_styles->supported_styles[i] & NO_STYLES;
 955     }













 956 
 957     XFree(im_styles);
 958 
 959     if (active_styles != on_the_spot_styles) {
 960         if (passive_styles == ROOT_WINDOW_STYLES)
 961             active_styles = passive_styles;
 962         else {





 963             if (no_styles == NO_STYLES)
 964                 active_styles = passive_styles = NO_STYLES;
 965             else
 966                 active_styles = passive_styles = 0;



 967         }
 968     } else {



 969         if (passive_styles != ROOT_WINDOW_STYLES) {
 970             if (no_styles == NO_STYLES)
 971                 active_styles = passive_styles = NO_STYLES;
 972             else
 973                 active_styles = passive_styles = 0;
 974         }




 975     }
 976 
 977     if (active_styles == on_the_spot_styles) {

 978         pX11IMData->ic_passive = XCreateIC(X11im,
 979                                    XNClientWindow, w,
 980                                    XNFocusWindow, w,
 981                                    XNInputStyle, passive_styles,
 982                                    NULL);
 983 

 984         callbacks = (XIMCallback *)malloc(sizeof(XIMCallback) * NCALLBACKS);
 985         if (callbacks == (XIMCallback *)NULL)
 986             return False;
 987         pX11IMData->callbacks = callbacks;
 988 
 989         for (i = 0; i < NCALLBACKS; i++, callbacks++) {
 990             callbacks->client_data = (XPointer) pX11IMData->x11inputmethod;
 991             callbacks->callback = callback_funcs[i];
 992         }
 993 
 994         callbacks = pX11IMData->callbacks;
 995         preedit = (XVaNestedList)XVaCreateNestedList(0,
 996                         XNPreeditStartCallback, &callbacks[PreeditStartIndex],
 997                         XNPreeditDoneCallback,  &callbacks[PreeditDoneIndex],
 998                         XNPreeditDrawCallback,  &callbacks[PreeditDrawIndex],
 999                         XNPreeditCaretCallback, &callbacks[PreeditCaretIndex],
1000                         NULL);
1001         if (preedit == (XVaNestedList)NULL)
1002             goto err;
1003 #if defined(__linux__) || defined(MACOSX)
1004         /*always try XIMStatusCallbacks for active client...*/
1005         {



1006             status = (XVaNestedList)XVaCreateNestedList(0,
1007                         XNStatusStartCallback, &callbacks[StatusStartIndex],
1008                         XNStatusDoneCallback,  &callbacks[StatusDoneIndex],
1009                         XNStatusDrawCallback, &callbacks[StatusDrawIndex],
1010                         NULL);
1011 
1012             if (status == NULL)
1013                 goto err;



1014             pX11IMData->statusWindow = createStatusWindow(w);
1015             pX11IMData->ic_active = XCreateIC(X11im,
1016                                               XNClientWindow, w,
1017                                               XNFocusWindow, w,
1018                                               XNInputStyle, active_styles,
1019                                               XNPreeditAttributes, preedit,
1020                                               XNStatusAttributes, status,
1021                                               NULL);





1022             XFree((void *)status);
1023             XFree((void *)preedit);
1024         }
1025 #else /* !__linux__ && !MACOSX */
1026             pX11IMData->ic_active = XCreateIC(X11im,
1027                                               XNClientWindow, w,
1028                                               XNFocusWindow, w,
1029                                               XNInputStyle, active_styles,
1030                                               XNPreeditAttributes, preedit,
1031                                               NULL);
1032         XFree((void *)preedit);
1033 #endif /* __linux__ || MACOSX */











1034     } else {
1035         pX11IMData->ic_active = XCreateIC(X11im,
1036                                           XNClientWindow, w,
1037                                           XNFocusWindow, w,
1038                                           XNInputStyle, active_styles,
1039                                           NULL);
1040         pX11IMData->ic_passive = pX11IMData->ic_active;
1041     }
1042 
















1043     if (pX11IMData->ic_active == (XIC)0
1044         || pX11IMData->ic_passive == (XIC)0) {
1045         return False;
1046     }
1047 
1048     /*
1049      * Use commit string call back if possible.
1050      * This will ensure the correct order of preedit text and commit text
1051      */
1052     {
1053         XIMCallback cb;
1054         cb.client_data = (XPointer) pX11IMData->x11inputmethod;
1055         cb.callback = (XIMProc) CommitStringCallback;
1056         XSetICValues (pX11IMData->ic_active, XNCommitStringCallback, &cb, NULL);
1057         if (pX11IMData->ic_active != pX11IMData->ic_passive) {
1058             XSetICValues (pX11IMData->ic_passive, XNCommitStringCallback, &cb, NULL);
1059         }
1060     }

1061 

1062     /* Add the global reference object to X11InputMethod to the list. */
1063     addToX11InputMethodGRefList(pX11IMData->x11inputmethod);








1064 
1065     return True;
1066 
1067  err:
1068     if (preedit)
1069         XFree((void *)preedit);
1070     THROW_OUT_OF_MEMORY_ERROR();
1071     return False;
1072 }
1073 

1074 static void



1075 PreeditStartCallback(XIC ic, XPointer client_data, XPointer call_data)
1076 {





1077     /*ARGSUSED*/

1078     /* printf("Native: PreeditCaretCallback\n"); */











1079 }
1080 
1081 static void
1082 PreeditDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
1083 {





1084     /*ARGSUSED*/

1085     /* printf("Native: StatusStartCallback\n"); */






















1086 }
1087 
1088 /*
1089  * Translate the preedit draw callback items to Java values and invoke
1090  * X11InputMethod.dispatchComposedText().
1091  *
1092  * client_data: X11InputMethod object
1093  */
1094 static void
1095 PreeditDrawCallback(XIC ic, XPointer client_data,
1096                     XIMPreeditDrawCallbackStruct *pre_draw)
1097 {
1098     JNIEnv *env = GetJNIEnv();
1099     X11InputMethodData *pX11IMData = NULL;
1100     jmethodID x11imMethodID;
1101 
1102     XIMText *text;
1103     jstring javastr = NULL;
1104     jintArray style = NULL;
1105 
1106     /* printf("Native: PreeditDrawCallback() \n"); */
1107     if (pre_draw == NULL) {
1108         return;
1109     }
1110     AWT_LOCK();

1111     if (!isX11InputMethodGRefInList((jobject)client_data)) {
1112         if ((jobject)client_data == currentX11InputMethodInstance) {
1113             currentX11InputMethodInstance = NULL;
1114         }
1115         goto finally;
1116     }

1117     if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {
1118         goto finally;
1119     }
1120 









1121     if ((text = pre_draw->text) != NULL) {



1122         if (text->string.multi_byte != NULL) {
1123             if (pre_draw->text->encoding_is_wchar == False) {
1124                 javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte);
1125                 if (javastr == NULL) {
1126                     goto finally;
1127                 }
1128             } else {
1129                 char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
1130                 if (mbstr == NULL) {
1131                     goto finally;
1132                 }
1133                 javastr = JNU_NewStringPlatform(env, (const char *)mbstr);
1134                 free(mbstr);
1135                 if (javastr == NULL) {
1136                     goto finally;
1137                 }
1138             }
1139         }



1140         if (text->feedback != NULL) {
1141             int cnt;
1142             jint *tmpstyle;
1143 
1144             style = (*env)->NewIntArray(env, text->length);
1145             if (JNU_IsNull(env, style)) {
1146                 (*env)->ExceptionClear(env);
1147                 THROW_OUT_OF_MEMORY_ERROR();
1148                 goto finally;
1149             }
1150 
1151             if (sizeof(XIMFeedback) == sizeof(jint)) {
1152                 /*
1153                  * Optimization to avoid copying the array
1154                  */
1155                 (*env)->SetIntArrayRegion(env, style, 0,
1156                                           text->length, (jint *)text->feedback);
1157             } else {
1158                 tmpstyle  = (jint *)malloc(sizeof(jint)*(text->length));
1159                 if (tmpstyle == (jint *) NULL) {
1160                     THROW_OUT_OF_MEMORY_ERROR();
1161                     goto finally;
1162                 }
1163                 for (cnt = 0; cnt < (int)text->length; cnt++)
1164                         tmpstyle[cnt] = text->feedback[cnt];
1165                 (*env)->SetIntArrayRegion(env, style, 0,
1166                                           text->length, (jint *)tmpstyle);
1167             }
1168         }
1169     }
1170     JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
1171                          "dispatchComposedText",
1172                          "(Ljava/lang/String;[IIIIJ)V",
1173                          javastr,
1174                          style,
1175                          (jint)pre_draw->chg_first,
1176                          (jint)pre_draw->chg_length,
1177                          (jint)pre_draw->caret,
1178                          awt_util_nowMillisUTC());






1179 finally:
1180     AWT_UNLOCK();
1181     return;
1182 }
1183 
1184 static void
1185 PreeditCaretCallback(XIC ic, XPointer client_data,
1186                      XIMPreeditCaretCallbackStruct *pre_caret)
1187 {




1188     /*ARGSUSED*/
1189     /* printf("Native: PreeditCaretCallback\n"); */
1190 









1191 }
1192 
1193 #if defined(__linux__) || defined(MACOSX)
1194 static void
1195 StatusStartCallback(XIC ic, XPointer client_data, XPointer call_data)
1196 {
1197     /*ARGSUSED*/
1198     /*printf("StatusStartCallback:\n");  */
1199 
1200 }
1201 
1202 static void
1203 StatusDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
1204 {
1205     /*ARGSUSED*/
1206     /*printf("StatusDoneCallback:\n"); */
1207 
1208 }
1209 
1210 static void
1211 StatusDrawCallback(XIC ic, XPointer client_data,
1212                      XIMStatusDrawCallbackStruct *status_draw)
1213 {
1214     /*ARGSUSED*/
1215     /*printf("StatusDrawCallback:\n"); */
1216     JNIEnv *env = GetJNIEnv();
1217     X11InputMethodData *pX11IMData = NULL;
1218     StatusWindow *statusWindow;






1219 
1220     AWT_LOCK();
1221 

1222     if (!isX11InputMethodGRefInList((jobject)client_data)) {
1223         if ((jobject)client_data == currentX11InputMethodInstance) {
1224             currentX11InputMethodInstance = NULL;
1225         }
1226         goto finally;
1227     }

1228 
1229     if (NULL == (pX11IMData = getX11InputMethodData(env, (jobject)client_data))
1230         || NULL == (statusWindow = pX11IMData->statusWindow)){
1231         goto finally;
1232     }

1233    currentX11InputMethodInstance = (jobject)client_data;

1234 
1235     if (status_draw->type == XIMTextType){
1236         XIMText *text = (status_draw->data).text;
1237         if (text != NULL){
1238           if (text->string.multi_byte != NULL) {

1239               strncpy(statusWindow->status, text->string.multi_byte, MAX_STATUS_LEN);
1240               statusWindow->status[MAX_STATUS_LEN - 1] = '\0';










1241           }
1242           else {

1243               char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
1244               strncpy(statusWindow->status, mbstr, MAX_STATUS_LEN);
1245               statusWindow->status[MAX_STATUS_LEN - 1] = '\0';










1246           }

1247           statusWindow->on = True;
1248           onoffStatusWindow(pX11IMData, statusWindow->parent, True);
1249           paintStatusWindow(statusWindow);




















1250         }
1251         else {

1252             statusWindow->on = False;



1253             /*just turnoff the status window
1254             paintStatusWindow(statusWindow);
1255             */
1256             onoffStatusWindow(pX11IMData, 0, False);
1257         }
1258     }
1259 
1260  finally:
1261     AWT_UNLOCK();
1262 }
1263 #endif /* __linux__ || MACOSX */
1264 

1265 static void CommitStringCallback(XIC ic, XPointer client_data, XPointer call_data) {
1266     JNIEnv *env = GetJNIEnv();
1267     XIMText * text = (XIMText *)call_data;
1268     X11InputMethodData *pX11IMData = NULL;
1269     jstring javastr;
1270 
1271     AWT_LOCK();
1272 
1273     if (!isX11InputMethodGRefInList((jobject)client_data)) {
1274         if ((jobject)client_data == currentX11InputMethodInstance) {
1275             currentX11InputMethodInstance = NULL;
1276         }
1277         goto finally;
1278     }
1279 
1280     if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {
1281         goto finally;
1282     }
1283     currentX11InputMethodInstance = (jobject)client_data;
1284 


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 


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 }






































































































































































































































































































































































































































































































































































































































































  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 #if defined(AIX)
  37 #include <X11/Intrinsic.h>
  38 
  39 #include <wchar.h>
  40 #include <wctype.h>
  41 #include <langinfo.h>
  42 #endif
  43 
  44 #include "awt.h"
  45 #include "awt_p.h"
  46 
  47 #include <sun_awt_X11InputMethod.h>
  48 #include <sun_awt_X11_XInputMethod.h>
  49 
  50 #define THROW_OUT_OF_MEMORY_ERROR() \
  51         JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL)
  52 
  53 #if !defined(AIX)
  54 #define RESUME_ENABLE 1
  55 #endif
  56 
  57 struct X11InputMethodIDs {
  58   jfieldID pData;
  59 } x11InputMethodIDs;
  60 
  61 #if !defined(AIX)
  62 static void PreeditStartCallback(XIC, XPointer, XPointer);
  63 #else
  64 static int PreeditStartCallback(XIC, XPointer, XPointer);
  65 #endif
  66 static void PreeditDoneCallback(XIC, XPointer, XPointer);
  67 static void PreeditDrawCallback(XIC, XPointer,
  68                                 XIMPreeditDrawCallbackStruct *);
  69 static void PreeditCaretCallback(XIC, XPointer,
  70                                  XIMPreeditCaretCallbackStruct *);
  71 #if defined(__linux__) || defined(MACOSX) || defined(AIX)
  72 static void StatusStartCallback(XIC, XPointer, XPointer);
  73 static void StatusDoneCallback(XIC, XPointer, XPointer);
  74 static void StatusDrawCallback(XIC, XPointer,
  75                                XIMStatusDrawCallbackStruct *);
  76 #endif
  77 
  78 #define ROOT_WINDOW_STYLES      (XIMPreeditNothing | XIMStatusNothing)
  79 #define NO_STYLES               (XIMPreeditNone | XIMStatusNone)
  80 #if defined(AIX)
  81 /* added style to allow for in-place composition, such as "dead" keys for accents */
  82 #define IN_PLACE_STYLES         (XIMPreeditNothing | XIMStatusNone)
  83 #endif
  84 
  85 #define PreeditStartIndex       0
  86 #define PreeditDoneIndex        1
  87 #define PreeditDrawIndex        2
  88 #define PreeditCaretIndex       3
  89 #if defined(__linux__) || defined(MACOSX) || defined(AIX)
  90 #define StatusStartIndex        4
  91 #define StatusDoneIndex         5
  92 #define StatusDrawIndex         6
  93 #define NCALLBACKS              7
  94 #else
  95 #define NCALLBACKS              4
  96 #endif
  97 
  98 #if defined(AIX)
  99 #define STATUS_BORDER 2         /* Status Border width */
 100 #define CARET_OFFSET 1          /* Offset of caret position (pixel) */
 101 #define BORDER_MARGIN 3         /* BORDER MARGIN width */
 102 #define STATUS_MARGIN 7         /* Margin between the status window and its parent window */
 103 #define PREEDIT_ATTR_MASK (XIMReverse|XIMUnderline)
 104           /* Preedit attribute which host adapter can handle */
 105 #endif
 106 
 107 /*
 108  * Callback function pointers: the order has to match the *Index
 109  * values above.
 110  */
 111 static XIMProc callback_funcs[NCALLBACKS] = {
 112     (XIMProc)PreeditStartCallback,
 113     (XIMProc)PreeditDoneCallback,
 114     (XIMProc)PreeditDrawCallback,
 115     (XIMProc)PreeditCaretCallback,
 116 #if defined(__linux__) || defined(MACOSX) || defined(AIX)
 117     (XIMProc)StatusStartCallback,
 118     (XIMProc)StatusDoneCallback,
 119     (XIMProc)StatusDrawCallback,
 120 #endif
 121 };
 122 
 123 #if defined(__linux__) || defined(MACOSX) || defined(AIX)
 124 #define MAX_STATUS_LEN  100
 125 typedef struct {
 126     Window   w;                /*status window id        */
 127     Window   root;             /*the root window id      */
 128     Window   parent;           /*parent shell window     */
 129 #if defined(AIX)
 130     Window   grandParent;      /*window has WM frame     */
 131 #endif
 132     int      x, y;             /*parent's upperleft position */
 133     int      width, height;    /*parent's width, height  */
 134     GC       lightGC;          /*gc for light border     */
 135     GC       dimGC;            /*gc for dim border       */
 136     GC       bgGC;             /*normal painting         */
 137     GC       fgGC;             /*normal painting         */
 138     int      statusW, statusH; /*status window's w, h    */
 139     int      rootW, rootH;     /*root window's w, h    */
 140     int      bWidth;           /*border width            */
 141 #if !defined(AIX)
 142     char     status[MAX_STATUS_LEN]; /*status text       */
 143 #else
 144     wchar_t  status[MAX_STATUS_LEN+1]; /*status text       */
 145 #endif
 146     XFontSet fontset;           /*fontset for drawing    */
 147     int      off_x, off_y;
 148     Bool     on;                /*if the status window on*/
 149 #if defined(AIX)
 150     int      fOff;              /* font base line(in pixel) from top */
 151     int      fBot;              /* font bottom line(in pixel) from top */
 152     int      peTextW;           /* Composition text width in pixel */
 153     wchar_t* peText;            /* Composed string (wide char.) */
 154     XIMFeedback* peAttr;        /* Composed text attribute */
 155     int      peCaret;           /* Caret position in number of character */
 156     Bool     status_ready;      /* Not draw Status at XCreateIC */
 157 #endif
 158 } StatusWindow;
 159 #endif
 160 
 161 /*
 162  * X11InputMethodData keeps per X11InputMethod instance information. A pointer
 163  * to this data structure is kept in an X11InputMethod object (pData).
 164  */
 165 typedef struct _X11InputMethodData {
 166     XIC         current_ic;     /* current X Input Context */
 167     XIC         ic_active;      /* X Input Context for active clients */
 168     XIC         ic_passive;     /* X Input Context for passive clients */
 169     XIMCallback *callbacks;     /* callback parameters */
 170     jobject     x11inputmethod; /* global ref to X11InputMethod instance */
 171                                 /* associated with the XIC */
 172 #if defined(__linux__) || defined(MACOSX) || defined(AIX)
 173     StatusWindow *statusWindow; /* our own status window  */
 174 #endif
 175 #if !defined(AIX)
 176     char        *lookup_buf;    /* buffer used for XmbLookupString */
 177     int         lookup_buf_len; /* lookup buffer size in bytes */
 178 #else
 179     Bool        passiveStatusWindow;/* Passive Client uses StatusWindow */
 180     Bool        isActiveClient;     /* True:clinet is active */
 181     Bool        forceReset;     /* True: call resetXIC before UnsetICFocus */
 182 #endif
 183 } X11InputMethodData;
 184 
 185 #if defined(RESUME_ENABLE)
 186 /*
 187  * When XIC is created, a global reference is created for
 188  * sun.awt.X11InputMethod object so that it could be used by the XIM callback
 189  * functions. This could be a dangerous thing to do when the original
 190  * X11InputMethod object is garbage collected and as a result,
 191  * destroyX11InputMethodData is called to delete the global reference.
 192  * If any XIM callback function still holds and uses the "already deleted"
 193  * global reference, disaster is going to happen. So we have to maintain
 194  * a list for these global references which is consulted first when the
 195  * callback functions or any function tries to use "currentX11InputMethodObject"
 196  * which always refers to the global reference try to use it.
 197  *
 198  */
 199 typedef struct _X11InputMethodGRefNode {
 200     jobject inputMethodGRef;
 201     struct _X11InputMethodGRefNode* next;
 202 } X11InputMethodGRefNode;
 203 
 204 X11InputMethodGRefNode *x11InputMethodGRefListHead = NULL;
 205 #endif
 206 
 207 /* reference to the current X11InputMethod instance, it is always
 208    point to the global reference to the X11InputMethodObject since
 209    it could be referenced by different threads. */
 210 jobject currentX11InputMethodInstance = NULL;
 211 
 212 Window  currentFocusWindow = 0;  /* current window that has focus for input
 213                                        method. (the best place to put this
 214                                        information should be
 215                                        currentX11InputMethodInstance's pData) */
 216 static XIM X11im = NULL;
 217 Display * dpy = NULL;
 218 
 219 #define GetJNIEnv() (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2)
 220 
 221 #if defined(RESUME_ENABLE)
 222 static void DestroyXIMCallback(XIM, XPointer, XPointer);
 223 static void OpenXIMCallback(Display *, XPointer, XPointer);
 224 #endif
 225 
 226 #if !defined(AIX)
 227 /* Solaris XIM Extention */
 228 #define XNCommitStringCallback "commitStringCallback"
 229 static void CommitStringCallback(XIC, XPointer, XPointer);
 230 #endif
 231 
 232 static X11InputMethodData * getX11InputMethodData(JNIEnv *, jobject);
 233 static void setX11InputMethodData(JNIEnv *, jobject, X11InputMethodData *);
 234 static void destroyX11InputMethodData(JNIEnv *, X11InputMethodData *);
 235 static void freeX11InputMethodData(JNIEnv *, X11InputMethodData *);
 236 
 237 #if defined(__solaris__) || defined(AIX)
 238 /* Prototype for this function is missing in Solaris X11R6 Xlib.h */
 239 extern char *XSetIMValues(
 240 #if NeedVarargsPrototypes
 241     XIM /* im */, ...
 242 #endif
 243 );
 244 #endif
 245 
 246 #if defined(AIX)
 247 static int st_wcslen(wchar_t *string);
 248 static Bool isPreeditStateActive(XIC ic);
 249 static void * buf_insert(void * src, void * insert, int size,
 250                          int src_len, int ins_len, int offset);
 251 static void * handle_buffer(void * source, void * insert,
 252                             int size, int src_len, int ins_len,
 253                             int del_len, int offset);
 254 static void preedit_draw_passive(X11InputMethodData *pX11IMData,
 255                                  XIMPreeditDrawCallbackStruct *pre_draw);
 256 static void resetPassivePreeditText(StatusWindow *statusWindow);
 257 static void draw_caret(StatusWindow *statusWindow, GC gc, int pos);
 258 static int  get_next_attr(int len, unsigned long *attr);
 259 static void draw_preedit(StatusWindow *statusWindow);
 260 static void align_status(StatusWindow *statusWindow);
 261 static void shrink_status(StatusWindow *statusWindow);
 262 static GC create_gc(Window win, Bool isReverse);
 263 static XFontSet create_fontset(void);
 264 static Bool is_text_available(XIMText * text);
 265 static Bool isNativeIm();
 266 static Window getGrandParent(Window parent);
 267 static void moveStatusWindow(StatusWindow *statusWindow);
 268 static void arrange_window_stack(StatusWindow* statusWindow);
 269 static Window get_current_focus(XIC ic);
 270 #endif
 271 
 272 /*
 273  * This function is stolen from /src/solaris/hpi/src/system_md.c
 274  * It is used in setting the time in Java-level InputEvents
 275  */
 276 jlong
 277 awt_util_nowMillisUTC()
 278 {
 279     struct timeval t;
 280     gettimeofday(&t, NULL);
 281     return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000);
 282 }
 283 
 284 /*
 285  * Converts the wchar_t string to a multi-byte string calling wcstombs(). A
 286  * buffer is allocated by malloc() to store the multi-byte string. NULL is
 287  * returned if the given wchar_t string pointer is NULL or buffer allocation is
 288  * failed.
 289  */
 290 static char *
 291 wcstombsdmp(wchar_t *wcs, int len)


 296     if (wcs == NULL)
 297         return NULL;
 298 
 299     n = len*MB_CUR_MAX + 1;
 300 
 301     mbs = (char *) malloc(n * sizeof(char));
 302     if (mbs == NULL) {
 303         THROW_OUT_OF_MEMORY_ERROR();
 304         return NULL;
 305     }
 306 
 307     /* TODO: check return values... Handle invalid characters properly...  */
 308     if (wcstombs(mbs, wcs, n) == (size_t)-1) {
 309         free(mbs);
 310         return NULL;
 311     }
 312 
 313     return mbs;
 314 }
 315 
 316 #if defined(RESUME_ENABLE)
 317 /*
 318  * Returns True if the global reference is still in the list,
 319  * otherwise False.
 320  */
 321 static Bool isX11InputMethodGRefInList(jobject imGRef) {
 322     X11InputMethodGRefNode *pX11InputMethodGRef = x11InputMethodGRefListHead;
 323 
 324     if (imGRef == NULL) {
 325         return False;
 326     }
 327 
 328     while (pX11InputMethodGRef != NULL) {
 329         if (pX11InputMethodGRef->inputMethodGRef == imGRef) {
 330             return True;
 331         }
 332         pX11InputMethodGRef = pX11InputMethodGRef->next;
 333     }
 334 
 335     return False;
 336 }


 376          if (cX11InputMethodGRef->inputMethodGRef == x11InputMethodGRef) {
 377              break;
 378          }
 379          pX11InputMethodGRef = cX11InputMethodGRef;
 380          cX11InputMethodGRef = cX11InputMethodGRef->next;
 381      }
 382 
 383      if (cX11InputMethodGRef == NULL) {
 384          return; /* Not found. */
 385      }
 386 
 387      if (cX11InputMethodGRef == x11InputMethodGRefListHead) {
 388          x11InputMethodGRefListHead = x11InputMethodGRefListHead->next;
 389      } else {
 390          pX11InputMethodGRef->next = cX11InputMethodGRef->next;
 391      }
 392      free(cX11InputMethodGRef);
 393 
 394      return;
 395 }
 396 #endif /* RESUME_ENABLE */
 397 
 398 
 399 static X11InputMethodData * getX11InputMethodData(JNIEnv * env, jobject imInstance) {
 400     X11InputMethodData *pX11IMData =
 401         (X11InputMethodData *)JNU_GetLongFieldAsPtr(env, imInstance, x11InputMethodIDs.pData);
 402 
 403     /*
 404      * In case the XIM server was killed somehow, reset X11InputMethodData.
 405      */
 406     if (X11im == NULL && pX11IMData != NULL) {
 407         JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
 408                              "flushText",
 409                              "()V");
 410         JNU_CHECK_EXCEPTION_RETURN(env, NULL);
 411 #if defined(AIX)
 412         if ((*env)->ExceptionOccurred(env)) {
 413             (*env)->ExceptionDescribe(env);
 414             (*env)->ExceptionClear(env);
 415         }
 416 #endif
 417         /* IMPORTANT:
 418            The order of the following calls is critical since "imInstance" may
 419            point to the global reference itself, if "freeX11InputMethodData" is called
 420            first, the global reference will be destroyed and "setX11InputMethodData"
 421            will in fact fail silently. So pX11IMData will not be set to NULL.
 422            This could make the original java object refers to a deleted pX11IMData
 423            object.
 424         */
 425         setX11InputMethodData(env, imInstance, NULL);
 426         freeX11InputMethodData(env, pX11IMData);
 427         pX11IMData = NULL;
 428     }
 429 
 430     return pX11IMData;
 431 }
 432 
 433 static void setX11InputMethodData(JNIEnv * env, jobject imInstance, X11InputMethodData *pX11IMData) {
 434     JNU_SetLongFieldFromPtr(env, imInstance, x11InputMethodIDs.pData, pX11IMData);
 435 }
 436 


 447 
 448     if (pX11IMData->ic_active != (XIC)0) {
 449         XUnsetICFocus(pX11IMData->ic_active);
 450         XDestroyIC(pX11IMData->ic_active);
 451         if (pX11IMData->ic_active != pX11IMData->ic_passive) {
 452             if (pX11IMData->ic_passive != (XIC)0) {
 453                 XUnsetICFocus(pX11IMData->ic_passive);
 454                 XDestroyIC(pX11IMData->ic_passive);
 455             }
 456             pX11IMData->ic_passive = (XIC)0;
 457             pX11IMData->current_ic = (XIC)0;
 458         }
 459     }
 460 
 461     freeX11InputMethodData(env, pX11IMData);
 462 }
 463 
 464 static void
 465 freeX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData)
 466 {
 467 #if defined(__linux__) || defined(MACOSX) || defined(AIX)
 468     if (pX11IMData->statusWindow != NULL){
 469         StatusWindow *sw = pX11IMData->statusWindow;
 470         XFreeGC(awt_display, sw->lightGC);
 471         XFreeGC(awt_display, sw->dimGC);
 472         XFreeGC(awt_display, sw->bgGC);
 473         XFreeGC(awt_display, sw->fgGC);
 474         if (sw->fontset != NULL) {
 475             XFreeFontSet(awt_display, sw->fontset);
 476         }
 477         XDestroyWindow(awt_display, sw->w);
 478 #if defined(AIX)
 479       if (pX11IMData->statusWindow->peText){
 480             free((void *)pX11IMData->statusWindow->peText);
 481             pX11IMData->statusWindow->peText = NULL;
 482         }
 483         if (pX11IMData->statusWindow->peAttr){
 484             free((void *)pX11IMData->statusWindow->peAttr);
 485             pX11IMData->statusWindow->peAttr = NULL;
 486         }
 487 #endif
 488         free((void*)sw);
 489     }
 490 #endif
 491 
 492     if (pX11IMData->callbacks)
 493         free((void *)pX11IMData->callbacks);
 494 
 495     if (env) {
 496 #if defined(RESUME_ENABLE)
 497         /* Remove the global reference from the list, so that
 498            the callback function or whoever refers to it could know.
 499         */
 500         removeX11InputMethodGRefFromList(pX11IMData->x11inputmethod);
 501 #endif
 502         (*env)->DeleteGlobalRef(env, pX11IMData->x11inputmethod);
 503     }
 504 
 505 #if !defined(AIX)
 506     if (pX11IMData->lookup_buf) {
 507         free((void *)pX11IMData->lookup_buf);
 508     }
 509 #endif
 510 
 511     free((void *)pX11IMData);
 512 }
 513 
 514 /*
 515  * Sets or unsets the focus to the given XIC.
 516  */
 517 static void
 518 setXICFocus(XIC ic, unsigned short req)
 519 {
 520     if (ic == NULL) {
 521         (void)fprintf(stderr, "Couldn't find X Input Context\n");
 522         return;
 523     }
 524     if (req == 1)
 525         XSetICFocus(ic);
 526     else
 527         XUnsetICFocus(ic);
 528 }
 529 


 544  * Invokes XmbLookupString() to get something from the XIM. It invokes
 545  * X11InputMethod.dispatchCommittedText() if XmbLookupString() returns
 546  * committed text.  This function is called from handleKeyEvent in canvas.c and
 547  * it's under the Motif event loop thread context.
 548  *
 549  * Buffer usage: There is a bug in XFree86-4.3.0 XmbLookupString implementation,
 550  * where it never returns XBufferOverflow.  We need to allocate the initial lookup buffer
 551  * big enough, so that the possibility that user encounters this problem is relatively
 552  * small.  When this bug gets fixed, we can make the initial buffer size smaller.
 553  * Note that XmbLookupString() sometimes produces a non-null-terminated string.
 554  *
 555  * Returns True when there is a keysym value to be handled.
 556  */
 557 #define INITIAL_LOOKUP_BUF_SIZE 512
 558 
 559 Boolean
 560 awt_x11inputmethod_lookupString(XKeyPressedEvent *event, KeySym *keysymp)
 561 {
 562     JNIEnv *env = GetJNIEnv();
 563     X11InputMethodData *pX11IMData = NULL;
 564 #if defined(AIX)
 565     int buf_len = INITIAL_LOOKUP_BUF_SIZE;
 566     char mbbuf[INITIAL_LOOKUP_BUF_SIZE];
 567     char *buf;
 568 #endif
 569     KeySym keysym = NoSymbol;
 570     Status status;
 571     int mblen;
 572     jstring javastr;
 573     XIC ic;
 574     Boolean result = True;
 575     static Boolean composing = False;
 576 
 577     /*
 578       printf("lookupString: entering...\n");
 579      */
 580 
 581 #if defined(RESUME_ENABLE)
 582     if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) {
 583         currentX11InputMethodInstance = NULL;
 584         return False;
 585     }
 586 #endif
 587 
 588     pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance);
 589 
 590     if (pX11IMData == NULL) {
 591 #if defined(__linux__) || defined(MACOSX) || defined(AIX)
 592         return False;
 593 #else
 594         return result;
 595 #endif
 596     }
 597 
 598     if ((ic = pX11IMData->current_ic) == (XIC)0){
 599 #if defined(__linux__) || defined(MACOSX) || defined(AIX)
 600         return False;
 601 #else
 602         return result;
 603 #endif
 604     }
 605 
 606 #if !defined(AIX)
 607     /* allocate the lookup buffer at the first invocation */
 608     if (pX11IMData->lookup_buf_len == 0) {
 609         pX11IMData->lookup_buf = (char *)malloc(INITIAL_LOOKUP_BUF_SIZE);
 610         if (pX11IMData->lookup_buf == NULL) {
 611             THROW_OUT_OF_MEMORY_ERROR();
 612             return result;
 613         }
 614         pX11IMData->lookup_buf_len = INITIAL_LOOKUP_BUF_SIZE;
 615     }
 616 
 617     mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf,
 618                             pX11IMData->lookup_buf_len - 1, &keysym, &status);
 619 #else
 620     buf = mbbuf;
 621     mblen = XmbLookupString(ic, event, buf,
 622                             buf_len - 1, &keysym, &status);
 623 #endif
 624 
 625     /*
 626      * In case of overflow, a buffer is allocated and it retries
 627      * XmbLookupString().
 628      */
 629     if (status == XBufferOverflow) {
 630 #if !defined(AIX)
 631         free((void *)pX11IMData->lookup_buf);
 632         pX11IMData->lookup_buf_len = 0;
 633         pX11IMData->lookup_buf = (char *)malloc(mblen + 1);
 634         if (pX11IMData->lookup_buf == NULL) {
 635             THROW_OUT_OF_MEMORY_ERROR();
 636             return result;
 637         }
 638         pX11IMData->lookup_buf_len = mblen + 1;
 639         mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf,
 640                             pX11IMData->lookup_buf_len - 1, &keysym, &status);
 641 #else
 642         buf_len = mblen + 1;
 643         buf = (char *)malloc(buf_len);
 644         if (buf == NULL) {
 645             THROW_OUT_OF_MEMORY_ERROR();
 646             return result;
 647         }
 648         mblen = XmbLookupString(ic, event, buf, buf_len, &keysym, &status);
 649 #endif
 650     }
 651 #if !defined(AIX)
 652     pX11IMData->lookup_buf[mblen] = 0;
 653 #else
 654     buf[mblen] = 0;
 655 #endif
 656 
 657     /* Get keysym without taking modifiers into account first to map
 658      * to AWT keyCode table.
 659      */
 660     switch (status) {
 661     case XLookupBoth:
 662         if (!composing) {
 663             if (event->keycode != 0) {
 664                 *keysymp = keysym;
 665                 result = False;
 666                 break;
 667             }
 668         }
 669         composing = False;
 670         /*FALLTHRU*/
 671     case XLookupChars:
 672     /*
 673      printf("lookupString: status=XLookupChars, type=%d, state=%x, keycode=%x, keysym=%x\n",
 674        event->type, event->state, event->keycode, keysym);
 675     */
 676 #if !defined(AIX)
 677         javastr = JNU_NewStringPlatform(env, (const char *)pX11IMData->lookup_buf);
 678 #else
 679         javastr = JNU_NewStringPlatform(env, (const char *)buf);
 680 #endif
 681         if (javastr != NULL) {
 682             JNU_CallMethodByName(env, NULL,
 683                                  currentX11InputMethodInstance,
 684                                  "dispatchCommittedText",
 685                                  "(Ljava/lang/String;J)V",
 686                                  javastr,
 687                                  event->time);
 688 #if defined(AIX)
 689             if ((*env)->ExceptionOccurred(env)) {
 690                 (*env)->ExceptionDescribe(env);
 691                 (*env)->ExceptionClear(env);
 692             }
 693 #endif
 694         }
 695         break;
 696 
 697     case XLookupKeySym:
 698     /*
 699      printf("lookupString: status=XLookupKeySym, type=%d, state=%x, keycode=%x, keysym=%x\n",
 700        event->type, event->state, event->keycode, keysym);
 701     */
 702         if (keysym == XK_Multi_key)
 703             composing = True;
 704         if (! composing) {
 705             *keysymp = keysym;
 706             result = False;
 707         }
 708         break;
 709 
 710     case XLookupNone:
 711     /*
 712      printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n",
 713         event->type, event->state, event->keycode, keysym);
 714     */
 715         break;
 716     }
 717 
 718 #if defined(AIX)
 719     if (buf != mbbuf) free(buf);
 720 #endif
 721     return result;
 722 }
 723 
 724 #if defined(__linux__) || defined(MACOSX) || defined(AIX)
 725 static StatusWindow *createStatusWindow(
 726                                 Window parent) {
 727     StatusWindow *statusWindow;
 728     XSetWindowAttributes attrib;
 729     unsigned long attribmask;
 730     Window containerWindow;
 731     Window status;
 732     Window child;
 733     XWindowAttributes xwa;
 734     XWindowAttributes xxwa;
 735     /* Variable for XCreateFontSet()*/
 736     char **mclr;
 737     int  mccr = 0;
 738     char *dsr;
 739     unsigned long bg, fg, light, dim;
 740     int x, y, off_x, off_y, xx, yy;
 741     unsigned int w, h, bw, depth;
 742     XGCValues values;
 743     unsigned long valuemask = 0;  /*ignore XGCvalue and use defaults*/
 744     int screen = 0;
 745     int i;
 746     AwtGraphicsConfigDataPtr adata;
 747     extern int awt_numScreens;
 748     /*hardcode the size right now, should get the size base on font*/
 749     int   width=80, height=22;
 750     Window rootWindow;
 751     Window *ignoreWindowPtr;
 752     unsigned int ignoreUnit;
 753 #if defined(AIX)
 754     Window grandParent;
 755     Window target;
 756     XFontSet fontset;
 757 
 758     fontset = create_fontset();
 759     if (NULL == fontset) return NULL;
 760 #endif
 761 
 762     XGetGeometry(dpy, parent, &rootWindow, &x, &y, &w, &h, &bw, &depth);
 763 
 764     attrib.override_redirect = True;
 765     attribmask = CWOverrideRedirect;
 766     for (i = 0; i < awt_numScreens; i++) {
 767         if (RootWindow(dpy, i) == rootWindow) {
 768             screen = i;
 769             break;
 770         }
 771     }
 772     adata = getDefaultConfig(screen);
 773     bg    = adata->AwtColorMatch(255, 255, 255, adata);
 774     fg    = adata->AwtColorMatch(0, 0, 0, adata);
 775     light = adata->AwtColorMatch(195, 195, 195, adata);
 776     dim   = adata->AwtColorMatch(128, 128, 128, adata);
 777 
 778 #if !defined(AIX)
 779     XGetWindowAttributes(dpy, parent, &xwa);
 780 #else
 781     grandParent=getGrandParent(parent);
 782     if (grandParent == 0){
 783         target = parent;
 784     }else{
 785         target = grandParent;
 786     }
 787     XGetWindowAttributes(dpy, target, &xwa);
 788 #endif
 789     bw = 2; /*xwa.border_width does not have the correct value*/
 790 
 791     /*compare the size difference between parent container
 792       and shell widget, the diff should be the border frame
 793       and title bar height (?)*/
 794 
 795     XQueryTree( dpy,
 796 #if !defined(AIX)
 797                 parent,
 798 #else
 799                 target,
 800 #endif
 801                 &rootWindow,
 802                 &containerWindow,
 803                 &ignoreWindowPtr,
 804                 &ignoreUnit);
 805     XGetWindowAttributes(dpy, containerWindow, &xxwa);
 806 
 807 #if !defined(AIX)
 808     off_x = (xxwa.width - xwa.width) / 2;
 809     off_y = xxwa.height - xwa.height - off_x; /*it's magic:-) */
 810 #else
 811     XTranslateCoordinates(dpy,
 812                           target, xwa.root,
 813                           0, 0,
 814                           &x, &y, &child);
 815 
 816     if (containerWindow == rootWindow){
 817         off_x = 0; off_y = STATUS_MARGIN;
 818     }else{
 819         XGetWindowAttributes(dpy, containerWindow, &xxwa);
 820         off_x = (xxwa.width - xwa.width) / 2;
 821         /* off_y = xxwa.height - xwa.height - off_x;*/ /*it's magic:-) */
 822         {
 823             int cx, cy;
 824             XTranslateCoordinates(dpy,
 825                                   containerWindow, xxwa.root,
 826                                   0, 0,
 827                                   &cx, &cy,
 828                                   &child);
 829             off_y = (xxwa.height + cy) - (xwa.height + y) ;
 830         }
 831     }
 832 #endif
 833 
 834     /*get the size of root window*/
 835     XGetWindowAttributes(dpy, rootWindow, &xxwa);
 836 
 837     XTranslateCoordinates(dpy,
 838 #if !defined(AIX)
 839                           parent, xwa.root,
 840 #else
 841                           target, xwa.root,
 842 #endif
 843                           xwa.x, xwa.y,
 844                           &x, &y,
 845                           &child);
 846     xx = x - off_x;
 847     yy = y + xwa.height - off_y;
 848     if (xx < 0 ){
 849         xx = 0;
 850     }
 851     if (xx + width > xxwa.width){
 852         xx = xxwa.width - width;
 853     }
 854     if (yy + height > xxwa.height){
 855         yy = xxwa.height - height;
 856     }
 857 
 858 #if defined(AIX)
 859     if ((DefaultVisual(dpy,screen))->class != adata->awt_visInfo.visual->class &&
 860         adata->awt_visInfo.visual->class == TrueColor) {
 861         attrib.colormap = XCreateColormap(dpy, xwa.root,
 862             adata->awt_visInfo.visual, AllocNone );
 863         attrib.border_pixel = BlackPixel(dpy, screen) ;
 864         attribmask |= CWColormap | CWBorderPixel;
 865     }
 866 #endif
 867 
 868     status =  XCreateWindow(dpy,
 869                             xwa.root,
 870                             xx, yy,
 871                             width, height,
 872                             0,
 873                             xwa.depth,
 874                             InputOutput,
 875                             adata->awt_visInfo.visual,
 876                             attribmask, &attrib);
 877     XSelectInput(dpy, status,
 878                  ExposureMask | StructureNotifyMask | EnterWindowMask |
 879                  LeaveWindowMask | VisibilityChangeMask);
 880 #if defined(AIX)
 881     if (grandParent != 0){
 882         long mask;
 883         XGetWindowAttributes(dpy, grandParent, &xwa);
 884         mask = xwa.your_event_mask | StructureNotifyMask |
 885                VisibilityChangeMask | PropertyChangeMask;
 886         XSelectInput(dpy, grandParent,mask);
 887     }
 888 #endif
 889 
 890     statusWindow = (StatusWindow*) calloc(1, sizeof(StatusWindow));
 891     if (statusWindow == NULL){
 892         THROW_OUT_OF_MEMORY_ERROR();
 893         return NULL;
 894     }
 895     statusWindow->w = status;
 896 #if !defined(AIX)
 897     //12-point font
 898     statusWindow->fontset = XCreateFontSet(dpy,
 899                                            "-*-*-medium-r-normal-*-*-120-*-*-*-*",
 900                                            &mclr, &mccr, &dsr);
 901     /* In case we didn't find the font set, release the list of missing characters */
 902     if (mccr > 0) {
 903         XFreeStringList(mclr);
 904     }
 905 #else
 906     statusWindow->fontset = fontset;
 907 #endif
 908     statusWindow->parent = parent;
 909 #if defined(AIX)
 910     statusWindow->grandParent = grandParent;
 911 #endif
 912     statusWindow->on  = False;
 913     statusWindow->x = x;
 914     statusWindow->y = y;
 915     statusWindow->width = xwa.width;
 916     statusWindow->height = xwa.height;
 917     statusWindow->off_x = off_x;
 918     statusWindow->off_y = off_y;
 919     statusWindow->bWidth  = bw;
 920     statusWindow->statusH = height;
 921     statusWindow->statusW = width;
 922 #if defined(AIX)
 923     statusWindow->peTextW = 0;
 924 #endif
 925     statusWindow->rootH = xxwa.height;
 926     statusWindow->rootW = xxwa.width;
 927     statusWindow->lightGC = XCreateGC(dpy, status, valuemask, &values);
 928     XSetForeground(dpy, statusWindow->lightGC, light);
 929     statusWindow->dimGC = XCreateGC(dpy, status, valuemask, &values);
 930     XSetForeground(dpy, statusWindow->dimGC, dim);
 931 #if !defined(AIX)
 932     statusWindow->fgGC = XCreateGC(dpy, status, valuemask, &values);
 933 #else
 934     statusWindow->fgGC = create_gc(status, FALSE);
 935 #endif
 936     XSetForeground(dpy, statusWindow->fgGC, fg);
 937 #if !defined(AIX)
 938     statusWindow->bgGC = XCreateGC(dpy, status, valuemask, &values);
 939 #else
 940     statusWindow->bgGC = create_gc(status, TRUE);
 941 #endif
 942     XSetForeground(dpy, statusWindow->bgGC, bg);
 943 #if defined(AIX)
 944     statusWindow->status_ready = False;
 945     wcscpy(statusWindow->status, L"");
 946 #endif
 947     return statusWindow;
 948 }
 949 
 950 /* This method is to turn off or turn on the status window. */
 951 static void onoffStatusWindow(X11InputMethodData* pX11IMData,
 952                                 Window parent,
 953                                 Bool ON){
 954     XWindowAttributes xwa;
 955     Window child;
 956     int x, y;
 957     StatusWindow *statusWindow = NULL;
 958 
 959 #if !defined(AIX)
 960     if (NULL == currentX11InputMethodInstance ||
 961         NULL == pX11IMData ||
 962 #else
 963     if (NULL == pX11IMData ||
 964 #endif
 965         NULL == (statusWindow =  pX11IMData->statusWindow)){
 966         return;
 967     }
 968 
 969     if (ON == False){
 970         XUnmapWindow(dpy, statusWindow->w);
 971 #if !defined(AIX)
 972         statusWindow->on = False;
 973 #endif
 974         return;
 975     }
 976 #if !defined(AIX)
 977     parent = JNU_CallMethodByName(GetJNIEnv(), NULL, pX11IMData->x11inputmethod,
 978 #else
 979     if (NULL == currentX11InputMethodInstance){
 980         return;
 981     }
 982   {
 983     JNIEnv *env = GetJNIEnv();
 984     parent = JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
 985 #endif
 986                                   "getCurrentParentWindow",
 987                                   "()J").j;
 988 #if defined(AIX)
 989     if ((*env)->ExceptionOccurred(env)) {
 990         (*env)->ExceptionDescribe(env);
 991         (*env)->ExceptionClear(env);
 992     }
 993   }
 994 #endif
 995     if (statusWindow->parent != parent){
 996         statusWindow->parent = parent;
 997     }
 998 #if !defined(AIX)
 999     XGetWindowAttributes(dpy, parent, &xwa);
1000     XTranslateCoordinates(dpy,
1001                           parent, xwa.root,
1002                           xwa.x, xwa.y,
1003                           &x, &y,
1004                           &child);
1005     if (statusWindow->x != x
1006         || statusWindow->y != y
1007         || statusWindow->height != xwa.height){
1008         statusWindow->x = x;
1009         statusWindow->y = y;
1010         statusWindow->height = xwa.height;
1011         x = statusWindow->x - statusWindow->off_x;
1012         y = statusWindow->y + statusWindow->height - statusWindow->off_y;
1013         if (x < 0 ){
1014             x = 0;
1015         }
1016         if (x + statusWindow->statusW > statusWindow->rootW){
1017             x = statusWindow->rootW - statusWindow->statusW;
1018         }
1019         if (y + statusWindow->statusH > statusWindow->rootH){
1020             y = statusWindow->rootH - statusWindow->statusH;
1021         }
1022         XMoveWindow(dpy, statusWindow->w, x, y);
1023     }
1024     statusWindow->on = True;
1025     XMapWindow(dpy, statusWindow->w);
1026 #else
1027     if (st_wcslen(statusWindow->status) > 0
1028         || (statusWindow->peText != NULL && st_wcslen(statusWindow->peText) > 0 )){
1029         moveStatusWindow(statusWindow);
1030         XMapRaised(dpy, statusWindow->w);
1031     }
1032 #endif
1033 }
1034 
1035 void paintStatusWindow(StatusWindow *statusWindow){
1036     Window  win  = statusWindow->w;
1037     GC  lightgc = statusWindow->lightGC;
1038     GC  dimgc = statusWindow->dimGC;
1039     GC  bggc = statusWindow->bgGC;
1040     GC  fggc = statusWindow->fgGC;
1041 
1042     int width = statusWindow->statusW;
1043     int height = statusWindow->statusH;
1044     int bwidth = statusWindow->bWidth;
1045 #if defined(AIX)
1046     int len;
1047     XRectangle logical, ink;
1048 
1049     if (NULL == statusWindow) return;
1050     if ((len = st_wcslen(statusWindow->status)) == 0)
1051         return;
1052     XwcTextExtents(statusWindow->fontset, statusWindow->status,
1053                    len, &ink, &logical);
1054     width = logical.width;
1055     height = logical.height;
1056 
1057     XFillRectangle(dpy, win, bggc, 0, 0, width+2, height+2);
1058 #endif
1059 
1060 #if !defined(AIX)
1061     XFillRectangle(dpy, win, bggc, 0, 0, width, height);
1062     /* draw border */
1063     XDrawLine(dpy, win, fggc, 0, 0, width, 0);
1064     XDrawLine(dpy, win, fggc, 0, height-1, width-1, height-1);
1065     XDrawLine(dpy, win, fggc, 0, 0, 0, height-1);
1066     XDrawLine(dpy, win, fggc, width-1, 0, width-1, height-1);
1067 
1068     XDrawLine(dpy, win, lightgc, 1, 1, width-bwidth, 1);
1069     XDrawLine(dpy, win, lightgc, 1, 1, 1, height-2);
1070     XDrawLine(dpy, win, lightgc, 1, height-2, width-bwidth, height-2);
1071     XDrawLine(dpy, win, lightgc, width-bwidth-1, 1, width-bwidth-1, height-2);
1072 
1073     XDrawLine(dpy, win, dimgc, 2, 2, 2, height-3);
1074     XDrawLine(dpy, win, dimgc, 2, height-3, width-bwidth-1, height-3);
1075     XDrawLine(dpy, win, dimgc, 2, 2, width-bwidth-2, 2);
1076     XDrawLine(dpy, win, dimgc, width-bwidth, 2, width-bwidth, height-3);
1077 #else
1078     XDrawLine(dpy, win, fggc, 0, 0, width+2, 0);
1079     XDrawLine(dpy, win, fggc, 0, height+2, width+2, height+2);
1080     XDrawLine(dpy, win, fggc, 0, 0, 0, height+2);
1081     XDrawLine(dpy, win, fggc, width+2, 0, width+2, height+2);
1082 #endif
1083 
1084     if (statusWindow->fontset){
1085 #if !defined(AIX)
1086         XmbDrawString(dpy, win, statusWindow->fontset, fggc,
1087                       bwidth + 2, height - bwidth - 4,
1088 #else
1089         XwcDrawString(dpy, win, statusWindow->fontset, fggc,
1090                       -logical.x + 1, -logical.y + 1,
1091 #endif
1092                       statusWindow->status,
1093 #if !defined(AIX)
1094                       strlen(statusWindow->status));
1095 #else
1096                       st_wcslen(statusWindow->status));
1097 #endif
1098     }
1099     else{
1100         /*too bad we failed to create a fontset for this locale*/
1101         XDrawString(dpy, win, fggc, bwidth + 2, height - bwidth - 4,
1102                     "[InputMethod ON]", strlen("[InputMethod ON]"));
1103     }
1104 }
1105 
1106 #if !defined(AIX)
1107 void statusWindowEventHandler(XEvent event){
1108 #else
1109 Bool statusWindowEventHandler(XEvent event){
1110 #endif
1111     JNIEnv *env = GetJNIEnv();
1112     X11InputMethodData *pX11IMData = NULL;
1113     StatusWindow *statusWindow;
1114 
1115 #if defined(RESUME_ENABLE)
1116     if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) {
1117         currentX11InputMethodInstance = NULL;
1118 #if !defined(AIX)
1119         return;
1120 #else
1121         return False;
1122 #endif
1123     }
1124 #endif
1125 
1126     if (NULL == currentX11InputMethodInstance
1127         || NULL == (pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance))
1128 #if !defined(AIX)
1129         || NULL == (statusWindow = pX11IMData->statusWindow)
1130         || statusWindow->w != event.xany.window){
1131         return;
1132 #else
1133         || NULL == (statusWindow = pX11IMData->statusWindow)){
1134         return False;
1135 #endif
1136     }
1137 
1138 #if defined(AIX)
1139   if (statusWindow->w == event.xany.window){
1140 #endif
1141     switch (event.type){
1142     case Expose:
1143         paintStatusWindow(statusWindow);
1144 #if defined(AIX)
1145         if (statusWindow->peText)
1146             draw_preedit(statusWindow);
1147         arrange_window_stack(statusWindow);
1148 #endif
1149         break;
1150 #if !defined(AIX)
1151     case MapNotify:
1152 #endif
1153     case ConfigureNotify:
1154 #if defined(AIX)
1155     case VisibilityNotify:
1156         arrange_window_stack(statusWindow);
1157 #endif
1158 #if !defined(AIX)
1159         {
1160           /*need to reset the stackMode...*/
1161             XWindowChanges xwc;
1162             int value_make = CWStackMode;
1163             xwc.stack_mode = TopIf;
1164             XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
1165         }
1166 #endif
1167         break;
1168         /*
1169     case UnmapNotify:
1170     case VisibilityNotify:
1171         break;
1172         */
1173     default:
1174         break;
1175   }
1176 #if defined(AIX)
1177     return True;
1178   }else if ((statusWindow->parent == event.xany.window)
1179            ||(statusWindow->grandParent
1180               && statusWindow->grandParent == event.xany.window)){
1181     switch (event.type){
1182       case MapNotify:
1183         if (statusWindow->on){
1184            onoffStatusWindow(pX11IMData, statusWindow->parent, True);
1185         }
1186         break;
1187       case UnmapNotify:
1188         onoffStatusWindow(pX11IMData, 0, False);
1189         break;
1190       case VisibilityNotify:
1191         if (statusWindow->on){
1192             arrange_window_stack(statusWindow);
1193         }
1194         break;
1195       case ConfigureNotify:
1196         if (statusWindow->grandParent && statusWindow->on){
1197             moveStatusWindow(statusWindow);
1198         }
1199       case PropertyNotify:
1200         if (statusWindow->on){
1201             arrange_window_stack(statusWindow);
1202         }
1203         break;
1204       default:
1205         break;
1206       }
1207    }
1208     return False;
1209 #endif
1210 }
1211 
1212 static void adjustStatusWindow(Window shell){
1213     JNIEnv *env = GetJNIEnv();
1214     X11InputMethodData *pX11IMData = NULL;
1215     StatusWindow *statusWindow;
1216 
1217     if (NULL == currentX11InputMethodInstance
1218 #if defined(RESUME_ENABLE)
1219         || !isX11InputMethodGRefInList(currentX11InputMethodInstance)
1220 #endif
1221         || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))
1222         || NULL == (statusWindow = pX11IMData->statusWindow)
1223         || !statusWindow->on) {
1224         return;
1225     }
1226 #if defined(AIX)
1227         moveStatusWindow(statusWindow);
1228 #endif
1229 #if !defined(AIX)
1230     {
1231         XWindowAttributes xwa;
1232         int x, y;
1233         Window child;
1234         XGetWindowAttributes(dpy, shell, &xwa);
1235         XTranslateCoordinates(dpy,
1236                               shell, xwa.root,
1237                               xwa.x, xwa.y,
1238                               &x, &y,
1239                               &child);
1240         if (statusWindow->x != x
1241             || statusWindow->y != y
1242             || statusWindow->height != xwa.height){
1243           statusWindow->x = x;
1244           statusWindow->y = y;
1245           statusWindow->height = xwa.height;
1246 
1247           x = statusWindow->x - statusWindow->off_x;
1248           y = statusWindow->y + statusWindow->height - statusWindow->off_y;
1249           if (x < 0 ){
1250               x = 0;
1251           }
1252           if (x + statusWindow->statusW > statusWindow->rootW){
1253               x = statusWindow->rootW - statusWindow->statusW;
1254           }
1255           if (y + statusWindow->statusH > statusWindow->rootH){
1256               y = statusWindow->rootH - statusWindow->statusH;
1257           }
1258           XMoveWindow(dpy, statusWindow->w, x, y);
1259         }
1260     }
1261 #endif
1262 }
1263 #endif  /* __linux__ || MACOSX || AIX */
1264 /*
1265  * Creates two XICs, one for active clients and the other for passive
1266  * clients. All information on those XICs are stored in the
1267  * X11InputMethodData given by the pX11IMData parameter.
1268  *
1269  * For active clients: Try to use preedit callback to support
1270  * on-the-spot. If tc is not null, the XIC to be created will
1271  * share the Status Area with Motif widgets (TextComponents). If the
1272  * preferable styles can't be used, fallback to root-window styles. If
1273  * root-window styles failed, fallback to None styles.
1274  *
1275  * For passive clients: Try to use root-window styles. If failed,
1276  * fallback to None styles.
1277  */
1278 static Bool
1279 createXIC(JNIEnv * env, X11InputMethodData *pX11IMData, Window w)
1280 {
1281     XVaNestedList preedit = NULL;
1282     XVaNestedList status = NULL;
1283     XIMStyle on_the_spot_styles = XIMPreeditCallbacks,
1284 #if defined(AIX)
1285              in_place_styles = 0,
1286 #endif
1287              active_styles = 0,
1288              passive_styles = 0,
1289              no_styles = 0;
1290     XIMCallback *callbacks;
1291     unsigned short i;
1292     XIMStyles *im_styles;
1293     char *ret = NULL;
1294 #if defined(AIX)
1295     Bool passiveStatusWindow = False;
1296 
1297     pX11IMData->statusWindow = NULL;
1298 #endif
1299 
1300     if (X11im == NULL) {
1301         return False;
1302     }
1303     if (!w) {
1304         return False;
1305     }
1306 
1307 #if defined(AIX)
1308     if (getenv("IBMJAVA_PASSIVE") == NULL) {
1309         passiveStatusWindow = False;
1310     } else {
1311         passiveStatusWindow = True;
1312     }
1313 
1314     if (isNativeIm()) { passiveStatusWindow = True; }
1315 #endif
1316 
1317     ret = XGetIMValues(X11im, XNQueryInputStyle, &im_styles, NULL);
1318 
1319     if (ret != NULL) {
1320         jio_fprintf(stderr,"XGetIMValues: %s\n",ret);
1321         return FALSE ;
1322     }
1323 
1324 #if defined(__linux__) || defined(MACOSX) || defined(AIX)
1325     on_the_spot_styles |= XIMStatusNothing;
1326 
1327     /*kinput does not support XIMPreeditCallbacks and XIMStatusArea
1328       at the same time, so use StatusCallback to draw the status
1329       ourself
1330     */
1331     for (i = 0; i < im_styles->count_styles; i++) {
1332         if (im_styles->supported_styles[i] == (XIMPreeditCallbacks | XIMStatusCallbacks)) {
1333             on_the_spot_styles = (XIMPreeditCallbacks | XIMStatusCallbacks);
1334             break;
1335         }
1336     }
1337 #else /*! __linux__ && !MACOSX && !AIX */
1338     on_the_spot_styles |= XIMStatusNothing;
1339 #endif /* __linux__ || MACOSX || AIX */
1340 
1341 #if !defined(AIX)
1342     for (i = 0; i < im_styles->count_styles; i++) {
1343         active_styles |= im_styles->supported_styles[i] & on_the_spot_styles;
1344         passive_styles |= im_styles->supported_styles[i] & ROOT_WINDOW_STYLES;
1345         no_styles |= im_styles->supported_styles[i] & NO_STYLES;
1346     }
1347 #else
1348     for (i = 0; i < im_styles->count_styles; i++) {
1349         if (im_styles->supported_styles[i] == on_the_spot_styles)
1350             active_styles = im_styles->supported_styles[i];
1351         if (im_styles->supported_styles[i] == ROOT_WINDOW_STYLES)
1352             passive_styles = im_styles->supported_styles[i];
1353         if (im_styles->supported_styles[i] == IN_PLACE_STYLES) {
1354             in_place_styles = im_styles->supported_styles[i];
1355         }
1356         if (im_styles->supported_styles[i] == NO_STYLES)
1357             no_styles = im_styles->supported_styles[i];
1358     }
1359 #endif
1360 
1361     XFree(im_styles);
1362 
1363     if (active_styles != on_the_spot_styles) {
1364         if (passive_styles == ROOT_WINDOW_STYLES)
1365             active_styles = passive_styles;
1366         else {
1367 #if defined(AIX)
1368           if (in_place_styles == IN_PLACE_STYLES){
1369               active_styles = passive_styles = IN_PLACE_STYLES;
1370           } else {
1371 #endif
1372             if (no_styles == NO_STYLES)
1373                 active_styles = passive_styles = NO_STYLES;
1374             else
1375                 active_styles = passive_styles = 0;
1376 #if defined(AIX)
1377           }
1378 #endif
1379         }
1380     } else {
1381 #if defined(AIX)
1382       if (!passiveStatusWindow) {
1383 #endif
1384         if (passive_styles != ROOT_WINDOW_STYLES) {
1385             if (no_styles == NO_STYLES)
1386                 active_styles = passive_styles = NO_STYLES;
1387             else
1388                 active_styles = passive_styles = 0;
1389         }
1390 #if defined(AIX)
1391       } else
1392           passive_styles = active_styles;
1393 #endif
1394     }
1395 
1396     if (active_styles == on_the_spot_styles) {
1397 #if !defined(AIX)
1398         pX11IMData->ic_passive = XCreateIC(X11im,
1399                                    XNClientWindow, w,
1400                                    XNFocusWindow, w,
1401                                    XNInputStyle, passive_styles,
1402                                    NULL);
1403 
1404 #endif
1405         callbacks = (XIMCallback *)malloc(sizeof(XIMCallback) * NCALLBACKS);
1406         if (callbacks == (XIMCallback *)NULL)
1407             return False;
1408         pX11IMData->callbacks = callbacks;
1409 
1410         for (i = 0; i < NCALLBACKS; i++, callbacks++) {
1411             callbacks->client_data = (XPointer) pX11IMData->x11inputmethod;
1412             callbacks->callback = callback_funcs[i];
1413         }
1414 
1415         callbacks = pX11IMData->callbacks;
1416         preedit = (XVaNestedList)XVaCreateNestedList(0,
1417                         XNPreeditStartCallback, &callbacks[PreeditStartIndex],
1418                         XNPreeditDoneCallback,  &callbacks[PreeditDoneIndex],
1419                         XNPreeditDrawCallback,  &callbacks[PreeditDrawIndex],
1420                         XNPreeditCaretCallback, &callbacks[PreeditCaretIndex],
1421                         NULL);
1422         if (preedit == (XVaNestedList)NULL)
1423             goto err;
1424 #if defined(__linux__) || defined(MACOSX) || defined(AIX)
1425         /*always try XIMStatusCallbacks for active client...*/
1426         {
1427 #if defined(AIX)
1428         if (on_the_spot_styles & XIMStatusCallbacks) {
1429 #endif
1430             status = (XVaNestedList)XVaCreateNestedList(0,
1431                         XNStatusStartCallback, &callbacks[StatusStartIndex],
1432                         XNStatusDoneCallback,  &callbacks[StatusDoneIndex],
1433                         XNStatusDrawCallback, &callbacks[StatusDrawIndex],
1434                         NULL);
1435 
1436             if (status == NULL)
1437                 goto err;
1438 #if defined(AIX)
1439           }
1440 #endif
1441             pX11IMData->statusWindow = createStatusWindow(w);
1442             pX11IMData->ic_active = XCreateIC(X11im,
1443                                               XNClientWindow, w,
1444                                               XNFocusWindow, w,
1445                                               XNInputStyle, active_styles,
1446                                               XNPreeditAttributes, preedit,
1447                                               XNStatusAttributes, status,
1448                                               NULL);
1449 #if defined(AIX)
1450             if (NULL != pX11IMData->statusWindow) {
1451                 pX11IMData->statusWindow->status_ready = True;
1452             }
1453 #endif
1454             XFree((void *)status);
1455             XFree((void *)preedit);
1456         }
1457 #else /* !__linux__ && !MACOSX && !AIX */
1458             pX11IMData->ic_active = XCreateIC(X11im,
1459                                               XNClientWindow, w,
1460                                               XNFocusWindow, w,
1461                                               XNInputStyle, active_styles,
1462                                               XNPreeditAttributes, preedit,
1463                                               NULL);
1464         XFree((void *)preedit);
1465 #endif /* __linux__ || MACOSX || AIX */
1466 #if defined(AIX)
1467       if (passiveStatusWindow) {
1468         pX11IMData->ic_passive = pX11IMData->ic_active;
1469       } else {
1470          pX11IMData->ic_passive = XCreateIC(X11im,
1471                                             XNClientWindow, w,
1472                                             XNFocusWindow, w,
1473                                             XNInputStyle, passive_styles,
1474                                             NULL);
1475      }
1476 #endif
1477     } else {
1478         pX11IMData->ic_active = XCreateIC(X11im,
1479                                           XNClientWindow, w,
1480                                           XNFocusWindow, w,
1481                                           XNInputStyle, active_styles,
1482                                           NULL);
1483         pX11IMData->ic_passive = pX11IMData->ic_active;
1484     }
1485 
1486 #if defined(AIX)
1487     // The code set the IC mode that the preedit state is not initialied
1488     // at XmbResetIC.  This attribute can be set at XCreateIC.  I separately
1489     // set the attribute to avoid the failure of XCreateIC at some platform
1490     // which does not support the attribute.
1491     if (pX11IMData->ic_active != 0)
1492         XSetICValues(pX11IMData->ic_active,
1493                         XNResetState, XIMPreserveState, NULL);
1494     if (pX11IMData->ic_passive != 0 &&
1495         pX11IMData->ic_active != pX11IMData->ic_passive)
1496             XSetICValues(pX11IMData->ic_passive,
1497              XNResetState, XIMInitialState, NULL);
1498 
1499     pX11IMData->passiveStatusWindow = passiveStatusWindow;
1500 #endif
1501 
1502     if (pX11IMData->ic_active == (XIC)0
1503         || pX11IMData->ic_passive == (XIC)0) {
1504         return False;
1505     }
1506 #if !defined(AIX)
1507     /*
1508      * Use commit string call back if possible.
1509      * This will ensure the correct order of preedit text and commit text
1510      */
1511     {
1512         XIMCallback cb;
1513         cb.client_data = (XPointer) pX11IMData->x11inputmethod;
1514         cb.callback = (XIMProc) CommitStringCallback;
1515         XSetICValues (pX11IMData->ic_active, XNCommitStringCallback, &cb, NULL);
1516         if (pX11IMData->ic_active != pX11IMData->ic_passive) {
1517             XSetICValues (pX11IMData->ic_passive, XNCommitStringCallback, &cb, NULL);
1518         }
1519     }
1520 #endif
1521 
1522 #if defined(RESUME_ENABLE)
1523     /* Add the global reference object to X11InputMethod to the list. */
1524     addToX11InputMethodGRefList(pX11IMData->x11inputmethod);
1525 #endif
1526 
1527 #if defined(AIX)
1528     /* Unset focus to avoid unexpected IM on */
1529     setXICFocus(pX11IMData->ic_active, False);
1530     if (pX11IMData->ic_active != pX11IMData->ic_passive)
1531         setXICFocus(pX11IMData->ic_passive, False);
1532 #endif
1533 
1534     return True;
1535 
1536  err:
1537     if (preedit)
1538         XFree((void *)preedit);
1539     THROW_OUT_OF_MEMORY_ERROR();
1540     return False;
1541 }
1542 
1543 #if !defined(AIX)
1544 static void
1545 #else
1546 static int
1547 #endif
1548 PreeditStartCallback(XIC ic, XPointer client_data, XPointer call_data)
1549 {
1550 #if defined(AIX)
1551     JNIEnv *env = GetJNIEnv();
1552     X11InputMethodData *pX11IMData;
1553 #endif
1554 
1555     /*ARGSUSED*/
1556 #if !defined(AIX)
1557     /* printf("Native: PreeditCaretCallback\n"); */
1558 #else
1559     /* printf("Native: PreeditStartCallback\n"); */
1560 
1561     pX11IMData = getX11InputMethodData(env, (jobject)client_data);
1562     if (pX11IMData == NULL || pX11IMData->statusWindow == NULL) {
1563         return 0;
1564     }
1565     resetPassivePreeditText(pX11IMData->statusWindow);
1566 
1567     return -1;  /* unlimited length for preedit text  */
1568 #endif
1569 }
1570 
1571 static void
1572 PreeditDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
1573 {
1574 #if defined(AIX)
1575     JNIEnv *env = GetJNIEnv();
1576     X11InputMethodData *pX11IMData;
1577 #endif
1578 
1579     /*ARGSUSED*/
1580 #if !defined(AIX)
1581     /* printf("Native: StatusStartCallback\n"); */
1582 #else
1583     /* printf("Native: PreeditDoneCallback\n"); */
1584     pX11IMData = getX11InputMethodData(env, (jobject)client_data);
1585     if (pX11IMData == NULL) {
1586         return;
1587     }
1588 
1589     if (!pX11IMData->isActiveClient) {
1590         resetPassivePreeditText(pX11IMData->statusWindow);
1591         shrink_status(pX11IMData->statusWindow);
1592     }
1593     else{
1594             JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
1595                                  "clearComposedText",
1596                                  "(J)V",
1597                                  awt_util_nowMillisUTC());
1598             if ((*env)->ExceptionOccurred(env)) {
1599                 (*env)->ExceptionDescribe(env);
1600                 (*env)->ExceptionClear(env);
1601             }
1602     }
1603 #endif
1604 }
1605 
1606 /*
1607  * Translate the preedit draw callback items to Java values and invoke
1608  * X11InputMethod.dispatchComposedText().
1609  *
1610  * client_data: X11InputMethod object
1611  */
1612 static void
1613 PreeditDrawCallback(XIC ic, XPointer client_data,
1614                     XIMPreeditDrawCallbackStruct *pre_draw)
1615 {
1616     JNIEnv *env = GetJNIEnv();
1617     X11InputMethodData *pX11IMData = NULL;
1618     jmethodID x11imMethodID;
1619 
1620     XIMText *text;
1621     jstring javastr = NULL;
1622     jintArray style = NULL;
1623 
1624     /* printf("Native: PreeditDrawCallback() \n"); */
1625     if (pre_draw == NULL) {
1626         return;
1627     }
1628     AWT_LOCK();
1629 #if defined(RESUME_ENABLE)
1630     if (!isX11InputMethodGRefInList((jobject)client_data)) {
1631         if ((jobject)client_data == currentX11InputMethodInstance) {
1632             currentX11InputMethodInstance = NULL;
1633         }
1634         goto finally;
1635     }
1636 #endif
1637     if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {
1638         goto finally;
1639     }
1640 
1641 #if defined(AIX)
1642     if (!pX11IMData->isActiveClient){
1643       if (ic == pX11IMData->ic_passive) {
1644         preedit_draw_passive(pX11IMData, pre_draw);
1645       }
1646         goto finally;
1647     }
1648 #endif
1649 
1650     if ((text = pre_draw->text) != NULL) {
1651 #if defined(AIX)
1652       if (is_text_available(text)) {
1653 #endif
1654         if (text->string.multi_byte != NULL) {
1655             if (pre_draw->text->encoding_is_wchar == False) {
1656                 javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte);
1657                 if (javastr == NULL) {
1658                     goto finally;
1659                 }
1660             } else {
1661                 char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
1662                 if (mbstr == NULL) {
1663                     goto finally;
1664                 }
1665                 javastr = JNU_NewStringPlatform(env, (const char *)mbstr);
1666                 free(mbstr);
1667                 if (javastr == NULL) {
1668                     goto finally;
1669                 }
1670             }
1671         }
1672 #if defined(AIX)
1673       }
1674 #endif
1675         if (text->feedback != NULL) {
1676             int cnt;
1677             jint *tmpstyle;
1678 
1679             style = (*env)->NewIntArray(env, text->length);
1680             if (JNU_IsNull(env, style)) {
1681                 (*env)->ExceptionClear(env);
1682                 THROW_OUT_OF_MEMORY_ERROR();
1683                 goto finally;
1684             }
1685 
1686             if (sizeof(XIMFeedback) == sizeof(jint)) {
1687                 /*
1688                  * Optimization to avoid copying the array
1689                  */
1690                 (*env)->SetIntArrayRegion(env, style, 0,
1691                                           text->length, (jint *)text->feedback);
1692             } else {
1693                 tmpstyle  = (jint *)malloc(sizeof(jint)*(text->length));
1694                 if (tmpstyle == (jint *) NULL) {
1695                     THROW_OUT_OF_MEMORY_ERROR();
1696                     goto finally;
1697                 }
1698                 for (cnt = 0; cnt < (int)text->length; cnt++)
1699                         tmpstyle[cnt] = text->feedback[cnt];
1700                 (*env)->SetIntArrayRegion(env, style, 0,
1701                                           text->length, (jint *)tmpstyle);
1702             }
1703         }
1704     }
1705     JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
1706                          "dispatchComposedText",
1707                          "(Ljava/lang/String;[IIIIJ)V",
1708                          javastr,
1709                          style,
1710                          (jint)pre_draw->chg_first,
1711                          (jint)pre_draw->chg_length,
1712                          (jint)pre_draw->caret,
1713                          awt_util_nowMillisUTC());
1714 #if defined(AIX)
1715     if ((*env)->ExceptionOccurred(env)) {
1716         (*env)->ExceptionDescribe(env);
1717         (*env)->ExceptionClear(env);
1718     }
1719 #endif
1720 finally:
1721     AWT_UNLOCK();
1722     return;
1723 }
1724 
1725 static void
1726 PreeditCaretCallback(XIC ic, XPointer client_data,
1727                      XIMPreeditCaretCallbackStruct *pre_caret)
1728 {
1729 #if defined(AIX)
1730     XIMPreeditDrawCallbackStruct pre_draw;
1731 #endif
1732 
1733     /*ARGSUSED*/
1734     /* printf("Native: PreeditCaretCallback\n"); */
1735 
1736 #if defined(AIX)
1737     if (pre_caret != NULL && pre_caret->direction == XIMAbsolutePosition) {
1738         pre_draw.caret = pre_caret->position;
1739         pre_draw.chg_first = 0;
1740         pre_draw.chg_length = 0;
1741         pre_draw.text = NULL;
1742         PreeditDrawCallback(ic, client_data, &pre_draw);
1743     }
1744 #endif
1745 }
1746 
1747 #if defined(__linux__) || defined(MACOSX) || defined(AIX)
1748 static void
1749 StatusStartCallback(XIC ic, XPointer client_data, XPointer call_data)
1750 {
1751     /*ARGSUSED*/
1752     /*printf("StatusStartCallback:\n");  */
1753 
1754 }
1755 
1756 static void
1757 StatusDoneCallback(XIC ic, XPointer client_data, XPointer call_data)
1758 {
1759     /*ARGSUSED*/
1760     /*printf("StatusDoneCallback:\n"); */
1761 
1762 }
1763 
1764 static void
1765 StatusDrawCallback(XIC ic, XPointer client_data,
1766                      XIMStatusDrawCallbackStruct *status_draw)
1767 {
1768     /*ARGSUSED*/
1769     /*printf("StatusDrawCallback:\n"); */
1770     JNIEnv *env = GetJNIEnv();
1771     X11InputMethodData *pX11IMData = NULL;
1772     StatusWindow *statusWindow;
1773 #if defined(AIX)
1774     int value_make = CWX|CWWidth|CWHeight;
1775     XRectangle logical, ink;
1776     XWindowChanges xwc;
1777     int len;
1778 #endif
1779 
1780     AWT_LOCK();
1781 
1782 #if defined(RESUME_ENABLE)
1783     if (!isX11InputMethodGRefInList((jobject)client_data)) {
1784         if ((jobject)client_data == currentX11InputMethodInstance) {
1785             currentX11InputMethodInstance = NULL;
1786         }
1787         goto finally;
1788     }
1789 #endif
1790 
1791     if (NULL == (pX11IMData = getX11InputMethodData(env, (jobject)client_data))
1792         || NULL == (statusWindow = pX11IMData->statusWindow)){
1793         goto finally;
1794     }
1795 #if !defined(AIX)
1796    currentX11InputMethodInstance = (jobject)client_data;
1797 #endif
1798 
1799     if (status_draw->type == XIMTextType){
1800         XIMText *text = (status_draw->data).text;
1801         if (text != NULL){
1802           if (text->string.multi_byte != NULL) {
1803 #if !defined(AIX)
1804               strncpy(statusWindow->status, text->string.multi_byte, MAX_STATUS_LEN);
1805               statusWindow->status[MAX_STATUS_LEN - 1] = '\0';
1806 #else
1807               if(!strcmp(text->string.multi_byte," ")){
1808                   wcscpy(statusWindow->status, L"");
1809                   onoffStatusWindow(pX11IMData, 0, False);
1810                   goto finally;
1811               }
1812               mbstowcs(statusWindow->status,
1813                        (const char *)text->string.multi_byte,
1814                        (size_t)MAX_STATUS_LEN);
1815 #endif
1816           }
1817           else {
1818 #if !defined(AIX)
1819               char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
1820               strncpy(statusWindow->status, mbstr, MAX_STATUS_LEN);
1821               statusWindow->status[MAX_STATUS_LEN - 1] = '\0';
1822 #else
1823               if (0 == st_wcslen(text->string.wide_char)){
1824                   wcscpy(statusWindow->status, L"");
1825                   onoffStatusWindow(pX11IMData, 0, False);
1826                   goto finally;
1827               }
1828               wcsncpy(statusWindow->status,
1829                       text->string.wide_char,
1830                       MAX_STATUS_LEN);
1831 #endif
1832           }
1833 #if !defined(AIX)
1834           statusWindow->on = True;
1835           onoffStatusWindow(pX11IMData, statusWindow->parent, True);
1836           paintStatusWindow(statusWindow);
1837 #else
1838             XwcTextExtents(statusWindow->fontset, statusWindow->status,
1839                            st_wcslen(statusWindow->status), &ink, &logical);
1840             statusWindow->statusW = logical.width + BORDER_MARGIN;
1841             statusWindow->statusH = logical.height + BORDER_MARGIN;
1842             xwc.x = statusWindow->x - statusWindow->off_x;
1843             if (xwc.x < 0 ) xwc.x = 0;
1844             xwc.width = statusWindow->statusW;
1845             xwc.height = statusWindow->statusH;
1846             if (xwc.x + xwc.width > statusWindow->rootW){
1847                 xwc.x = statusWindow->rootW - xwc.width;
1848             }
1849             XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
1850           if (statusWindow->status_ready && statusWindow->on == True){
1851             onoffStatusWindow(pX11IMData, statusWindow->parent, True);
1852           }
1853             paintStatusWindow(statusWindow);
1854             if (statusWindow->peText)
1855                 draw_preedit(statusWindow);
1856 #endif
1857         }
1858         else {
1859 #if !defined(AIX)
1860             statusWindow->on = False;
1861 #else
1862             wcscpy(statusWindow->status, L"");
1863 #endif
1864             /*just turnoff the status window
1865             paintStatusWindow(statusWindow);
1866             */
1867             onoffStatusWindow(pX11IMData, 0, False);
1868         }
1869     }
1870 
1871  finally:
1872     AWT_UNLOCK();
1873 }
1874 #endif /* __linux__ || MACOSX */
1875 
1876 #if !defined(AIX)
1877 static void CommitStringCallback(XIC ic, XPointer client_data, XPointer call_data) {
1878     JNIEnv *env = GetJNIEnv();
1879     XIMText * text = (XIMText *)call_data;
1880     X11InputMethodData *pX11IMData = NULL;
1881     jstring javastr;
1882 
1883     AWT_LOCK();
1884 
1885     if (!isX11InputMethodGRefInList((jobject)client_data)) {
1886         if ((jobject)client_data == currentX11InputMethodInstance) {
1887             currentX11InputMethodInstance = NULL;
1888         }
1889         goto finally;
1890     }
1891 
1892     if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) {
1893         goto finally;
1894     }
1895     currentX11InputMethodInstance = (jobject)client_data;
1896 


1899     } else {
1900         char *mbstr = wcstombsdmp(text->string.wide_char, text->length);
1901         if (mbstr == NULL) {
1902             goto finally;
1903         }
1904         javastr = JNU_NewStringPlatform(env, (const char *)mbstr);
1905         free(mbstr);
1906     }
1907 
1908     if (javastr != NULL) {
1909         JNU_CallMethodByName(env, NULL,
1910                                  pX11IMData->x11inputmethod,
1911                                  "dispatchCommittedText",
1912                                  "(Ljava/lang/String;J)V",
1913                                  javastr,
1914                                  awt_util_nowMillisUTC());
1915     }
1916  finally:
1917     AWT_UNLOCK();
1918 }
1919 #endif
1920 
1921 #if defined(RESUME_ENABLE)
1922 static void OpenXIMCallback(Display *display, XPointer client_data, XPointer call_data) {
1923     XIMCallback ximCallback;
1924 
1925     X11im = XOpenIM(display, NULL, NULL, NULL);
1926     if (X11im == NULL) {
1927         return;
1928     }
1929 
1930     ximCallback.callback = (XIMProc)DestroyXIMCallback;
1931     ximCallback.client_data = NULL;
1932     XSetIMValues(X11im, XNDestroyCallback, &ximCallback, NULL);
1933 }
1934 
1935 static void DestroyXIMCallback(XIM im, XPointer client_data, XPointer call_data) {
1936     /* mark that XIM server was destroyed */
1937     X11im = NULL;
1938     JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
1939     /* free the old pX11IMData and set it to null. this also avoids crashing
1940      * the jvm if the XIM server reappears */
1941     X11InputMethodData *pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance);
1942 }
1943 #endif /* RESUME_ENABLE */
1944 
1945 /*
1946  * Class:     sun_awt_X11InputMethod
1947  * Method:    initIDs
1948  * Signature: ()V
1949  */
1950 
1951 /* This function gets called from the static initializer for
1952    X11InputMethod.java
1953    to initialize the fieldIDs for fields that may be accessed from C */
1954 JNIEXPORT void JNICALL
1955 Java_sun_awt_X11InputMethod_initIDs(JNIEnv *env, jclass cls)
1956 {
1957     x11InputMethodIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J");
1958 }
1959 
1960 
1961 JNIEXPORT jboolean JNICALL
1962 Java_sun_awt_X11_XInputMethod_openXIMNative(JNIEnv *env,
1963                                           jobject this,
1964                                           jlong display)
1965 {
1966     Bool registered;
1967 
1968     AWT_LOCK();
1969 
1970     dpy = (Display *)jlong_to_ptr(display);
1971 
1972 #ifndef RESUME_ENABLE
1973     if (X11im == NULL) {
1974         X11im = XOpenIM(dpy, NULL, NULL, NULL);
1975     }
1976 #else /* !RESUME_ENABLE */
1977 /* Use IMInstantiate call back only on Linux, as there is a bug in Solaris
1978    (4768335)
1979 */
1980 #if defined(__linux__) || defined(MACOSX)
1981     registered = XRegisterIMInstantiateCallback(dpy, NULL, NULL,
1982                      NULL, (XIDProc)OpenXIMCallback, NULL);
1983     if (!registered) {
1984         /* directly call openXIM callback */
1985 #endif
1986         OpenXIMCallback(dpy, NULL, NULL);
1987 #if defined(__linux__) || defined(MACOSX)
1988     }
1989 #endif
1990 #endif /* RESUME_ENABLE */
1991 
1992     AWT_UNLOCK();
1993 
1994     return JNI_TRUE;
1995 }
1996 
1997 JNIEXPORT jboolean JNICALL
1998 Java_sun_awt_X11_XInputMethod_createXICNative(JNIEnv *env,
1999                                                   jobject this,
2000                                                   jlong window)
2001 {
2002     X11InputMethodData *pX11IMData;
2003     jobject globalRef;
2004     XIC ic;
2005 
2006     AWT_LOCK();
2007 
2008     if (!window) {
2009         JNU_ThrowNullPointerException(env, "NullPointerException");
2010         AWT_UNLOCK();
2011         return JNI_FALSE;
2012     }
2013 
2014     pX11IMData = (X11InputMethodData *) calloc(1, sizeof(X11InputMethodData));
2015     if (pX11IMData == NULL) {
2016         THROW_OUT_OF_MEMORY_ERROR();
2017         AWT_UNLOCK();
2018         return JNI_FALSE;
2019     }
2020 
2021     globalRef = (*env)->NewGlobalRef(env, this);
2022     pX11IMData->x11inputmethod = globalRef;
2023 #if defined(__linux__) || defined(MACOSX) || defined(AIX)
2024     pX11IMData->statusWindow = NULL;
2025 #endif /* __linux__ || MACOSX || AIX */
2026 
2027 #if !defined(AIX)
2028     pX11IMData->lookup_buf = 0;
2029     pX11IMData->lookup_buf_len = 0;
2030 
2031 #else
2032     setX11InputMethodData(env, this, pX11IMData);
2033 
2034 #endif
2035 
2036     if (createXIC(env, pX11IMData, (Window)window) == False) {
2037         destroyX11InputMethodData((JNIEnv *) NULL, pX11IMData);
2038         pX11IMData = (X11InputMethodData *) NULL;
2039 #if defined(AIX)
2040         setX11InputMethodData(env, this, pX11IMData);
2041 #endif
2042         if ((*env)->ExceptionCheck(env)) {
2043             goto finally;
2044         }
2045     }
2046 
2047 #if !defined(AIX)
2048     setX11InputMethodData(env, this, pX11IMData);
2049 #endif
2050 
2051 finally:
2052     AWT_UNLOCK();
2053     return (pX11IMData != NULL);
2054 }
2055 
2056 JNIEXPORT void JNICALL
2057 Java_sun_awt_X11_XInputMethod_setXICFocusNative(JNIEnv *env,
2058                                               jobject this,
2059                                               jlong w,
2060                                               jboolean req,
2061                                               jboolean active)
2062 {
2063     X11InputMethodData *pX11IMData;
2064     AWT_LOCK();
2065     pX11IMData = getX11InputMethodData(env, this);
2066     if (pX11IMData == NULL) {
2067         AWT_UNLOCK();
2068         return;
2069     }
2070 
2071     if (req) {
2072         if (!w) {
2073             AWT_UNLOCK();
2074             return;
2075         }
2076 #if defined(AIX)
2077         pX11IMData->isActiveClient = active;
2078 #endif
2079         pX11IMData->current_ic = active ?
2080                         pX11IMData->ic_active : pX11IMData->ic_passive;
2081         /*
2082          * On Solaris2.6, setXICWindowFocus() has to be invoked
2083          * before setting focus.
2084          */
2085 #if defined(AIX)
2086       get_current_focus(pX11IMData->current_ic); /* workaround for kinput2 and SCIM */
2087       if (currentFocusWindow != w) {
2088 #endif
2089         setXICWindowFocus(pX11IMData->current_ic, w);
2090         setXICFocus(pX11IMData->current_ic, req);
2091         currentX11InputMethodInstance = pX11IMData->x11inputmethod;
2092         currentFocusWindow =  w;
2093 #if defined(AIX)
2094       } else {
2095 #endif
2096 #if defined(__linux__) || defined(MACOSX)
2097         if (active && pX11IMData->statusWindow && pX11IMData->statusWindow->on)
2098 #endif
2099 #if defined(AIX)
2100         setXICFocus(pX11IMData->current_ic, req);
2101       }
2102         if ((active || pX11IMData->passiveStatusWindow)
2103             && (pX11IMData->statusWindow && pX11IMData->statusWindow->on))
2104 #endif
2105 #if defined(__linux__) || defined(MACOSX) || defined(AIX)
2106             onoffStatusWindow(pX11IMData, w, True);
2107 #endif
2108     } else {
2109         currentX11InputMethodInstance = NULL;
2110         currentFocusWindow = 0;
2111 #if defined(__linux__) || defined(MACOSX) || defined(AIX)
2112         onoffStatusWindow(pX11IMData, 0, False);
2113         if (pX11IMData->current_ic != NULL)
2114 #endif
2115         setXICFocus(pX11IMData->current_ic, req);
2116 
2117         pX11IMData->current_ic = (XIC)0;
2118     }
2119 
2120     XFlush(dpy);
2121     AWT_UNLOCK();
2122 }
2123 
2124 JNIEXPORT void JNICALL
2125 Java_sun_awt_X11InputMethod_turnoffStatusWindow(JNIEnv *env,
2126                                                 jobject this)
2127 {
2128 #if defined(__linux__) || defined(MACOSX) || defined(AIX)
2129     X11InputMethodData *pX11IMData;
2130     StatusWindow *statusWindow;
2131 
2132     AWT_LOCK();
2133 
2134     if (NULL == currentX11InputMethodInstance
2135 #if defined(RESUME_ENABLE)
2136         || !isX11InputMethodGRefInList(currentX11InputMethodInstance)
2137 #endif
2138         || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance))
2139         || NULL == (statusWindow = pX11IMData->statusWindow)
2140         || !statusWindow->on ){
2141         AWT_UNLOCK();
2142         return;
2143     }
2144     onoffStatusWindow(pX11IMData, 0, False);
2145 #if defined(AIX)
2146     statusWindow->on = False;
2147 #endif
2148 
2149     AWT_UNLOCK();
2150 #endif
2151 }
2152 
2153 JNIEXPORT void JNICALL
2154 Java_sun_awt_X11InputMethod_disposeXIC(JNIEnv *env,
2155                                              jobject this)
2156 {
2157     X11InputMethodData *pX11IMData = NULL;
2158 
2159     AWT_LOCK();
2160     pX11IMData = getX11InputMethodData(env, this);
2161     if (pX11IMData == NULL) {
2162         AWT_UNLOCK();
2163         return;
2164     }
2165 
2166     setX11InputMethodData(env, this, NULL);
2167 


2172     destroyX11InputMethodData(env, pX11IMData);
2173     AWT_UNLOCK();
2174 }
2175 
2176 JNIEXPORT jstring JNICALL
2177 Java_sun_awt_X11InputMethod_resetXIC(JNIEnv *env,
2178                                            jobject this)
2179 {
2180     X11InputMethodData *pX11IMData;
2181     char *xText = NULL;
2182     jstring jText = (jstring)0;
2183 
2184     AWT_LOCK();
2185     pX11IMData = getX11InputMethodData(env, this);
2186     if (pX11IMData == NULL) {
2187         AWT_UNLOCK();
2188         return jText;
2189     }
2190 
2191     if (pX11IMData->current_ic)
2192 #if defined(AIX)
2193     {
2194       if (!isPreeditStateActive(pX11IMData->current_ic)) {
2195             xText = NULL;
2196       } else {
2197         if (!(pX11IMData->forceReset))
2198             setXICFocus(pX11IMData->current_ic, FALSE);
2199 #endif
2200         xText = XmbResetIC(pX11IMData->current_ic);
2201 #if defined(AIX)
2202         if (!(pX11IMData->forceReset))
2203             setXICFocus(pX11IMData->current_ic, TRUE);
2204       }
2205     }
2206 #endif
2207     else {
2208         /*
2209          * If there is no reference to the current XIC, try to reset both XICs.
2210          */
2211 #if defined(AIX)
2212         if (!isPreeditStateActive(pX11IMData->ic_active))
2213             xText = NULL;
2214         else
2215 #endif
2216         xText = XmbResetIC(pX11IMData->ic_active);
2217         /*it may also means that the real client component does
2218           not have focus -- has been deactivated... its xic should
2219           not have the focus, bug#4284651 showes reset XIC for htt
2220           may bring the focus back, so de-focus it again.
2221         */
2222         setXICFocus(pX11IMData->ic_active, FALSE);
2223         if (pX11IMData->ic_active != pX11IMData->ic_passive) {
2224 #if !defined(AIX)
2225             char *tmpText = XmbResetIC(pX11IMData->ic_passive);
2226 #else
2227             char *tmpText;
2228             if (!isPreeditStateActive(pX11IMData->ic_passive))
2229                 tmpText = NULL;
2230             else
2231                 tmpText = XmbResetIC(pX11IMData->ic_passive);
2232 #endif
2233             setXICFocus(pX11IMData->ic_passive, FALSE);
2234             if (xText == (char *)NULL && tmpText)
2235                 xText = tmpText;
2236         }
2237 
2238     }
2239     if (xText != NULL) {
2240         jText = JNU_NewStringPlatform(env, (const char *)xText);
2241         XFree((void *)xText);
2242     }
2243 
2244 #if defined(AIX)
2245     /* workaround
2246      * Some IME do not call PreeditDoneCallback routine even
2247      * when XmbResetIC is called. I force to reset the preedit string.
2248      */
2249     if (!pX11IMData->isActiveClient) {
2250         resetPassivePreeditText(pX11IMData->statusWindow);
2251         shrink_status(pX11IMData->statusWindow);
2252     } else {
2253         JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod,
2254                              "clearComposedText",
2255                              "()V");
2256         if ((*env)->ExceptionOccurred(env)) {
2257             (*env)->ExceptionDescribe(env);
2258             (*env)->ExceptionClear(env);
2259         }
2260     }
2261 #endif
2262 
2263     AWT_UNLOCK();
2264     return jText;
2265 }
2266 
2267 /*
2268  * Class:     sun_awt_X11InputMethod
2269  * Method:    setCompositionEnabledNative
2270  * Signature: (ZJ)V
2271  *
2272  * This method tries to set the XNPreeditState attribute associated with the current
2273  * XIC to the passed in 'enable' state.
2274  *
2275  * Return JNI_TRUE if XNPreeditState attribute is successfully changed to the
2276  * 'enable' state; Otherwise, if XSetICValues fails to set this attribute,
2277  * java.lang.UnsupportedOperationException will be thrown. JNI_FALSE is returned if this
2278  * method fails due to other reasons.
2279  *
2280  */
2281 JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethod_setCompositionEnabledNative
2282   (JNIEnv *env, jobject this, jboolean enable)
2283 {
2284     X11InputMethodData *pX11IMData;
2285     char * ret = NULL;
2286 #if defined(AIX)
2287     XVaNestedList   pr_atrb;
2288 #endif
2289 
2290     AWT_LOCK();
2291     pX11IMData = getX11InputMethodData(env, this);
2292 
2293     if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {
2294         AWT_UNLOCK();
2295         return JNI_FALSE;
2296     }
2297 
2298 #if !defined(AIX)
2299     ret = XSetICValues(pX11IMData->current_ic, XNPreeditState,
2300                        (enable ? XIMPreeditEnable : XIMPreeditDisable), NULL);
2301     AWT_UNLOCK();
2302 
2303     if ((ret != 0) && (strcmp(ret, XNPreeditState) == 0)) {
2304         JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
2305     }
2306 #else
2307     pr_atrb = XVaCreateNestedList(0, XNPreeditState,
2308                   (enable ? XIMPreeditEnable : XIMPreeditDisable), NULL);
2309     ret = XSetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL);
2310     XFree((void *)pr_atrb);
2311     AWT_UNLOCK();
2312 
2313     if ((ret != 0) &&
2314         ((strcmp(ret, XNPreeditAttributes) == 0)
2315          || (strcmp(ret, XNPreeditState) == 0))) {
2316         JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
2317     }
2318 #endif
2319 
2320     return (jboolean)(ret == 0);
2321 }
2322 
2323 /*
2324  * Class:     sun_awt_X11InputMethod
2325  * Method:    isCompositionEnabledNative
2326  * Signature: (J)Z
2327  *
2328  * This method tries to get the XNPreeditState attribute associated with the current XIC.
2329  *
2330  * Return JNI_TRUE if the XNPreeditState is successfully retrieved. Otherwise, if
2331  * XGetICValues fails to get this attribute, java.lang.UnsupportedOperationException
2332  * will be thrown. JNI_FALSE is returned if this method fails due to other reasons.
2333  *
2334  */
2335 JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethod_isCompositionEnabledNative
2336   (JNIEnv *env, jobject this)
2337 {
2338     X11InputMethodData *pX11IMData = NULL;
2339     char * ret = NULL;
2340 #if !defined(AIX)
2341     XIMPreeditState state;
2342 #else
2343     XIMPreeditState state = XIMPreeditUnKnown;
2344     XVaNestedList   pr_atrb;
2345 #endif
2346 
2347     AWT_LOCK();
2348     pX11IMData = getX11InputMethodData(env, this);
2349 
2350     if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) {
2351         AWT_UNLOCK();
2352         return JNI_FALSE;
2353     }
2354 
2355 #if !defined(AIX)
2356     ret = XGetICValues(pX11IMData->current_ic, XNPreeditState, &state, NULL);
2357     AWT_UNLOCK();
2358 
2359     if ((ret != 0) && (strcmp(ret, XNPreeditState) == 0)) {
2360         JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
2361         return JNI_FALSE;
2362     }
2363 #else
2364     pr_atrb = XVaCreateNestedList(0, XNPreeditState, &state, NULL);
2365     ret = XGetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL);
2366     XFree((void *)pr_atrb);
2367     AWT_UNLOCK();
2368 
2369     if ((ret != 0) &&
2370         ((strcmp(ret, XNPreeditAttributes) == 0)
2371          || (strcmp(ret, XNPreeditState) == 0))) {
2372         JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", "");
2373         return JNI_FALSE;
2374     }
2375 #endif
2376 
2377     return (jboolean)(state == XIMPreeditEnable);
2378 }
2379 
2380 JNIEXPORT void JNICALL Java_sun_awt_X11_XInputMethod_adjustStatusWindow
2381   (JNIEnv *env, jobject this, jlong window)
2382 {
2383 #if defined(__linux__) || defined(MACOSX)
2384     AWT_LOCK();
2385     adjustStatusWindow(window);
2386     AWT_UNLOCK();
2387 #endif
2388 }
2389 #if defined(AIX)
2390 /*
2391  * The following functions are IBM's enhancement.
2392  */
2393 
2394 JNIEXPORT void JNICALL
2395 Java_sun_awt_X11InputMethod_setStatusAreaVisible(JNIEnv *env,
2396                                                  jobject this,
2397                                                  jboolean value,
2398                                                  jlong data)
2399 {
2400     X11InputMethodData *pX11IMData;
2401 
2402     pX11IMData = getX11InputMethodData(env, this);
2403     if (NULL == pX11IMData) return;
2404     if (NULL == pX11IMData->statusWindow) return;
2405 
2406     if ((int)value){
2407         pX11IMData->statusWindow->on = True;
2408     }else{
2409         pX11IMData->statusWindow->on = False;
2410     }
2411     return;
2412 }
2413 
2414 /* return the string length without trailing spaces    */
2415 /* work around code for Japanese AIXIM is implemented. */
2416 static int st_wcslen(wchar_t *string)
2417 {
2418     int len = (int32_t)wcslen(string);
2419     if (len == 0)
2420         return 0;
2421    for (len--;len >= 0; len--) {
2422         if (!iswspace((wint_t) string[len])) break;
2423     }
2424     return len+1;
2425 }
2426 
2427 /*
2428  * Checks whether given XIMText contains a string data.
2429  */
2430 static Bool is_text_available(XIMText * text)
2431 {
2432     if (text == NULL || text->length==0)
2433         return False;
2434     if (text->encoding_is_wchar) {
2435         if(text->string.wide_char[0] == L'\0')
2436             return False;
2437     } else {
2438         if (text->string.multi_byte[0] == '\0')
2439             return False;
2440     }
2441     return True;
2442 }
2443 
2444 /*
2445  * check if preedit status is active
2446 */
2447 static Bool isPreeditStateActive(XIC ic)
2448 {
2449     XIMPreeditState state = XIMPreeditUnKnown;
2450     XVaNestedList pr_atrb;
2451     char* nosupportAttr;
2452 
2453     if (ic == NULL) return False;
2454 
2455     pr_atrb = XVaCreateNestedList(0,XNPreeditState,&state,NULL);
2456     nosupportAttr=XGetICValues(ic,XNPreeditAttributes,pr_atrb,NULL);
2457     XFree(pr_atrb);
2458     if (nosupportAttr==NULL && state & XIMPreeditDisable)
2459         return False;
2460     else
2461         return True;
2462 }
2463 
2464 static void * buf_insert(void * src, void * insert, int size,
2465                          int src_len, int ins_len, int offset)
2466 {
2467     char *temp;
2468 
2469     temp = realloc(src, size*(src_len+ins_len+1));
2470     if (temp == NULL) {
2471         THROW_OUT_OF_MEMORY_ERROR();
2472         return src;
2473     }
2474     if (offset != src_len) {
2475         memmove(&temp[size*(offset+ins_len)],
2476                 &((char *)temp)[size*offset],
2477                 size*(src_len-offset));
2478     }
2479     memcpy(&temp[size*offset], insert, size*ins_len);
2480 
2481     return (void *)temp;
2482 }
2483 
2484 static void * handle_buffer(void * source, void * insert,
2485                             int size,int src_len, int ins_len,
2486                             int del_len, int offset)
2487 {
2488     void * temp = source;
2489 
2490     if(del_len > 0) {
2491         if (del_len == ins_len) {
2492             memcpy(&((char *)source)[size*offset], insert, size*ins_len);
2493             return source;
2494         }
2495         else if (src_len > offset+del_len) {
2496             memmove(&((char *)source)[size*offset],
2497                     &((char *)source)[size*(offset+del_len)],
2498                     size*(src_len-offset-del_len));
2499         }
2500     }
2501     if(ins_len > 0) {
2502         temp = buf_insert(source, insert, size, src_len,
2503                           ins_len, offset);
2504     }
2505     return temp;
2506 }
2507 /*
2508  * Display the given preedit text to the root window which is ownd by
2509  * myself. All of the character is converted to wide char.
2510  * this function is used for the passive client.
2511  */
2512 static void preedit_draw_passive(X11InputMethodData *pX11IMData,
2513                     XIMPreeditDrawCallbackStruct *pre_draw)
2514 {
2515     XIMText *text;
2516     wchar_t *tempbuf = NULL;
2517     StatusWindow *statusWindow;
2518     wchar_t *cur_text;
2519     unsigned long *cur_attr;
2520     int     cur_len = 0;
2521     int     chg_len = pre_draw->chg_length;
2522     int     chg_1st = pre_draw->chg_first;
2523 
2524     if (NULL == (statusWindow = pX11IMData->statusWindow))
2525         return;
2526     cur_text = statusWindow->peText;
2527     cur_attr = statusWindow->peAttr;
2528     if (cur_text == NULL && pre_draw->text == NULL)
2529         return;
2530 
2531     if (cur_text != NULL)
2532         cur_len = (int32_t)wcslen(cur_text);
2533     text = pre_draw->text;
2534     if (text == NULL) {
2535         /* delete only */
2536         if (cur_len >  chg_1st+chg_len) {
2537             memmove(&cur_text[chg_1st],
2538                     &cur_text[chg_1st+chg_len],
2539                     sizeof(wchar_t)*(cur_len-chg_1st-chg_len));
2540             memmove(&cur_attr[chg_1st],
2541                     &cur_attr[chg_1st+chg_len],
2542                     sizeof(long)*(cur_len-chg_1st-chg_len));
2543         }
2544         if ((pre_draw->chg_length <= cur_len ) && (pre_draw->chg_length >0))
2545             cur_text[cur_len-pre_draw->chg_length] =L'\0';
2546     }
2547     else {
2548         /* insert or replace */
2549         int     ins_len = 0;
2550         void *  ins_text = NULL;
2551 
2552         /* if invalid offset is specified, do nothing. */
2553         /* this fix is for aixim for eucTW             */
2554         if (cur_len < chg_1st)
2555             return;
2556         if(is_text_available(text)) {
2557             /* insert or replace the text */
2558             if (text->encoding_is_wchar == False) {
2559                 /* convert the text to wide chars.
2560                    allocate enough size buffer
2561                 */
2562                 tempbuf = (wchar_t *)malloc(sizeof(wchar_t)*(text->length+1));
2563                 if (tempbuf == NULL) {
2564                     THROW_OUT_OF_MEMORY_ERROR();
2565                     return;
2566                 }
2567                 ins_len = (int32_t)mbstowcs(tempbuf, text->string.multi_byte,
2568                                    text->length);
2569                 if (ins_len == -1) {
2570                         free(tempbuf);
2571                         return;
2572                 }
2573                 ins_text = (void *)tempbuf;
2574             }
2575             else {
2576                 ins_len = text->length;
2577                 ins_text = text->string.wide_char;
2578             }
2579             /* finish prepare the data to be inserted */
2580 
2581             statusWindow->peText =
2582                     handle_buffer(cur_text, ins_text, sizeof(wchar_t),
2583                                   cur_len, ins_len, chg_len, chg_1st);
2584             statusWindow->peAttr =
2585                     handle_buffer(cur_attr, text->feedback, sizeof(long),
2586                                   cur_len, ins_len, chg_len, chg_1st);
2587             statusWindow->peText[cur_len-chg_len+ins_len] =L'\0';
2588 
2589             if (tempbuf != NULL)
2590                 free(tempbuf);
2591         } /* endof insert or replace text */
2592         else {
2593             /* change attribute only */
2594             memcpy(&cur_attr[chg_1st], text->feedback,
2595                     sizeof(long)*text->length);
2596         }
2597     }
2598     statusWindow->peCaret= pre_draw->caret;
2599     draw_preedit(statusWindow);
2600     if (statusWindow->on && wcslen(statusWindow->peText) > 0)
2601         onoffStatusWindow(pX11IMData, statusWindow->parent, True);
2602     else if (wcslen(statusWindow->status) == 0)
2603         onoffStatusWindow(pX11IMData, 0, False);
2604 }
2605 
2606 /*
2607  * reset predit test of passive mode
2608  */
2609 static void
2610 resetPassivePreeditText(StatusWindow *statusWindow)
2611 {
2612     if (NULL == statusWindow) return;
2613     if(statusWindow->peText != NULL) {
2614         free(statusWindow->peText);
2615         statusWindow->peText = NULL;
2616     }
2617     if(statusWindow->peAttr != NULL) {
2618         free(statusWindow->peAttr);
2619         statusWindow->peAttr = NULL;
2620     }
2621     statusWindow->peCaret= 0;
2622 }
2623 
2624 static void draw_caret(StatusWindow *statusWindow, GC gc, int pos)
2625 {
2626     if (NULL == statusWindow) return;
2627     XSetFunction(dpy, gc, GXinvert);
2628     XDrawLine(dpy, statusWindow->w,
2629               gc, pos, STATUS_BORDER/2,
2630               pos, STATUS_BORDER/2+statusWindow->fOff);
2631     XSetFunction(dpy, gc, GXcopy);
2632 }
2633 
2634 static int  get_next_attr(int len, unsigned long *attr)
2635 {
2636     int count;
2637 
2638     for (count = 1; count < len; count++)  {
2639         if ((attr[count-1] & PREEDIT_ATTR_MASK)
2640             != (attr[count] & PREEDIT_ATTR_MASK))
2641             break;
2642     }
2643     return count;
2644 }
2645 
2646 static void draw_preedit(StatusWindow *statusWindow)
2647 {
2648     unsigned long *attr;
2649     int x_pos,x_caret;
2650     unsigned int  len;
2651     int len_disp, pos;
2652     wchar_t *str;
2653     GC  gc;
2654     XRectangle ink, rect, rect_c;
2655     Bool caret_done = False;
2656 
2657     if (NULL == statusWindow) return;
2658     align_status(statusWindow);
2659     XFillRectangle(dpy, statusWindow->w,
2660                    statusWindow->bgGC,
2661                    statusWindow->statusW,0,
2662                    statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN,
2663                    statusWindow->fBot+2);
2664 
2665 
2666     XDrawLine(dpy, statusWindow->w, statusWindow->fgGC,
2667               statusWindow->statusW, 0,
2668               statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, 0);
2669     XDrawLine(dpy, statusWindow->w, statusWindow->fgGC,
2670               statusWindow->statusW, statusWindow->fBot+2,
2671               statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN,
2672               statusWindow->fBot+2);
2673     XDrawLine(dpy, statusWindow->w, statusWindow->fgGC,
2674               statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, 0,
2675               statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN,
2676               statusWindow->fBot+2);
2677     if (0 == statusWindow->statusW)
2678         XDrawLine(dpy, statusWindow->w, statusWindow->fgGC,
2679                   0, 0, 0, statusWindow->fBot+2);
2680 
2681     str =  statusWindow->peText;
2682 
2683     if (str != NULL &&  (len = (int32_t)wcslen(str)) != 0) {
2684         pos = 0;
2685         attr = statusWindow->peAttr;
2686         x_pos = x_caret = statusWindow->statusW + STATUS_BORDER;
2687         while((int)len-1 >= pos) {
2688             len_disp = get_next_attr(len - pos, &attr[pos]);
2689             if (attr[pos] & XIMReverse) {
2690                 gc = statusWindow->bgGC;
2691             }
2692             else {
2693                 gc = statusWindow->fgGC;
2694             }
2695             XwcTextExtents(statusWindow->fontset,
2696                            &str[pos],
2697                            len_disp, &ink, &rect);
2698             XwcDrawImageString(dpy, statusWindow->w,
2699                                statusWindow->fontset, gc,
2700                                x_pos, statusWindow->fOff+1, &str[pos], len_disp);
2701             if (attr[pos] & XIMUnderline) {
2702                 XDrawLine(dpy, statusWindow->w,
2703                           gc, x_pos, statusWindow->fBot,
2704                           x_pos+rect.width, statusWindow->fBot);
2705             }
2706             if (!caret_done) {
2707                 if( statusWindow->peCaret >= pos &&
2708                     statusWindow->peCaret <= pos+len_disp) {
2709                     if (statusWindow->peCaret == 0)
2710                         x_caret = x_pos;
2711                     else if (statusWindow->peCaret == pos+len_disp)
2712                         x_caret = x_pos+rect.width;
2713                     else {
2714                         XwcTextExtents(statusWindow->fontset,
2715                                         &str[pos],
2716                                         statusWindow->peCaret-pos,
2717                                         &ink, &rect_c);
2718                         x_caret = x_pos+ rect_c.width;
2719                     }
2720                     x_caret-=CARET_OFFSET;
2721                     caret_done = True;
2722                 }
2723             }
2724             pos += len_disp;
2725             x_pos += rect.width;
2726         }
2727         if (caret_done)
2728             draw_caret(statusWindow, statusWindow->fgGC, x_caret);
2729     }
2730 }
2731 /* calc requied status window size and resize the window */
2732 static void align_status(StatusWindow *statusWindow)
2733 {
2734     int len_st, len_pe = 0;
2735     XRectangle rect_st, rect_pe, ink;
2736     Dimension cur_w;
2737     int value_make = CWX|CWWidth|CWHeight;
2738     XWindowChanges xwc;
2739 
2740     if (NULL == statusWindow) return;
2741     if ((len_st = st_wcslen(statusWindow->status)) == 0
2742         && (statusWindow->peText == NULL || st_wcslen(statusWindow->peText) == 0 ))
2743         return;
2744 
2745     rect_pe.x = rect_pe.y = rect_pe.width = rect_pe.height = 0;
2746 
2747     XwcTextExtents(statusWindow->fontset,
2748                    statusWindow->status,
2749                    len_st, &ink, &rect_st);
2750     if (statusWindow->peText != NULL
2751         && (len_pe = (int32_t)wcslen(statusWindow->peText)) > 0) {
2752         XwcTextExtents(statusWindow->fontset,
2753                        statusWindow->peText,
2754                        len_pe, &ink, &rect_pe);
2755     }
2756     statusWindow->fOff = max(-rect_st.y, -rect_pe.y);
2757     statusWindow->fBot = max(rect_st.height, rect_pe.height);
2758     statusWindow->statusW =rect_st.width;
2759     if (rect_st.width > 0) statusWindow->statusW += BORDER_MARGIN;
2760     statusWindow->peTextW = rect_pe.width;
2761 
2762     xwc.x = statusWindow->x - statusWindow->off_x;
2763     if (xwc.x < 0 ) xwc.x = 0;
2764 
2765     if (len_pe > 0) {
2766         xwc.width = statusWindow->statusW
2767                     + statusWindow->peTextW + BORDER_MARGIN + 1;
2768         xwc.height = statusWindow->fBot + BORDER_MARGIN;
2769     } else {
2770         xwc.width = statusWindow->statusW;
2771         xwc.height = statusWindow->fBot + BORDER_MARGIN;
2772     }
2773     if (xwc.x + xwc.width > statusWindow->rootW){
2774       xwc.x = statusWindow->rootW - xwc.width;
2775     }
2776     XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
2777 }
2778 
2779 static void shrink_status(StatusWindow *statusWindow)
2780 {
2781     int value_make = CWX|CWWidth|CWHeight;
2782     XWindowChanges xwc;
2783 
2784     if (NULL == statusWindow) return;
2785     xwc.width  = statusWindow->statusW;
2786     xwc.height = statusWindow->statusH;
2787     statusWindow->peTextW = 0;
2788     xwc.x = statusWindow->x - statusWindow->off_x;
2789     if (xwc.x < 0 ) xwc.x = 0;
2790     if (xwc.x + xwc.width > statusWindow->rootW){
2791       xwc.x = statusWindow->rootW - xwc.width;
2792     }
2793     XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
2794 }
2795 
2796 static GC create_gc(Window win, Bool isReverse)
2797 {
2798     XGCValues xgcv;
2799     unsigned long mask;
2800     AwtScreenDataPtr defaultScreen;
2801 
2802     defaultScreen = getScreenData(DefaultScreen(dpy));
2803 
2804     mask = (GCForeground | GCBackground );
2805     if (isReverse) {
2806         xgcv.foreground = defaultScreen->whitepixel;
2807         xgcv.background = defaultScreen->blackpixel;
2808     }
2809     else {
2810         xgcv.foreground = defaultScreen->blackpixel;
2811         xgcv.background = defaultScreen->whitepixel;
2812     }
2813     return XCreateGC(dpy, win, mask, &xgcv);
2814 }
2815 
2816 static Bool isNativeIm()
2817 {
2818 #define XIMMODIFIER          "@im="
2819 #define XIM_SERVER_CATEGORY  "@server="
2820     char *immodifiers;
2821     char *imserver, *imserverPtr;
2822     Atom imserverAtom;
2823 
2824     if (!(immodifiers = getenv("XMODIFIERS"))) return True;
2825     if (!(imserver = calloc(1,strlen(immodifiers)+strlen(XIM_SERVER_CATEGORY)+1))) return True;
2826     if (!(immodifiers = strstr(immodifiers,XIMMODIFIER))) return True;
2827     immodifiers += strlen(XIMMODIFIER);
2828     strcpy(imserver,XIM_SERVER_CATEGORY);
2829     imserverPtr = imserver + strlen(imserver);
2830     while(*immodifiers != '@' && *immodifiers != '\0') {
2831         *imserverPtr = *immodifiers;
2832         imserverPtr++;
2833         immodifiers++;
2834     }
2835     imserverAtom = XInternAtom(awt_display, imserver, True);
2836     free(imserver);
2837     if (imserverAtom > 0)
2838         return False;
2839     else
2840         return True;
2841 }
2842 
2843 static Window getGrandParent(Window parent)
2844 {
2845     Window containerWindow,rootWindow,tmp;
2846     Window *ignoreWindowPtr;
2847     unsigned int ignoreUnit;
2848     Window grandParent=0;
2849     XWindowAttributes xwa;
2850     Atom WM_STATE;
2851     Atom type = None;
2852     int32_t format;
2853     unsigned long nitems, after;
2854     unsigned char * data;
2855 
2856     if (parent == 0) return grandParent;
2857     WM_STATE = XInternAtom(dpy, "WM_STATE", True);
2858     if (WM_STATE == None) return grandParent;
2859 
2860     tmp=parent;
2861     while(XQueryTree(dpy, tmp,
2862                      &rootWindow, &containerWindow,
2863                      &ignoreWindowPtr, &ignoreUnit)){
2864         XFree(ignoreWindowPtr);
2865         if (containerWindow == rootWindow) break;
2866         if (XGetWindowProperty(dpy, containerWindow, WM_STATE,
2867                     0, 0, False, AnyPropertyType,
2868                     &type, &format, &nitems, &after, &data) == Success) {
2869             XFree(data);
2870             if (type) {
2871                 XGetWindowAttributes(dpy, containerWindow, &xwa);
2872                 if (FALSE == xwa.override_redirect){
2873                     grandParent=containerWindow;
2874                 }
2875             }
2876         }
2877         tmp=containerWindow;
2878     }
2879     return grandParent;
2880 }
2881 
2882 static void moveStatusWindow(StatusWindow *statusWindow)
2883 {
2884     XWindowAttributes xwa;
2885     Window child;
2886     int x, y, width;
2887     Window target;
2888 
2889     if (NULL == statusWindow) return;
2890     if (statusWindow->grandParent){
2891         target = statusWindow->grandParent;
2892     }else{
2893         target = statusWindow->parent;
2894     }
2895     XGetWindowAttributes(dpy, target, &xwa);
2896     XTranslateCoordinates(dpy,
2897                           target, xwa.root,
2898                           0, 0,
2899                           &x, &y,
2900                           &child);
2901     if (statusWindow->x != x
2902         || statusWindow->y != y
2903         || statusWindow->width != xwa.width
2904         || statusWindow->height != xwa.height){
2905         statusWindow->x = x;
2906         statusWindow->y = y;
2907         statusWindow->height = xwa.height;
2908         statusWindow->width = xwa.width;
2909         x = statusWindow->x - statusWindow->off_x;
2910         y = statusWindow->y + statusWindow->height + statusWindow->off_y;
2911         if (x < 0 ){
2912             x = 0;
2913         }
2914         if (statusWindow->peTextW > 0) {
2915             width = statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN + 1;
2916             if (x + width > statusWindow->rootW){
2917                 x = statusWindow->rootW - width;
2918             }
2919         } else {
2920             if (x + statusWindow->statusW > statusWindow->rootW){
2921                 x = statusWindow->rootW - statusWindow->statusW;
2922             }
2923         }
2924         if (y + statusWindow->statusH > statusWindow->rootH){
2925             y = statusWindow->rootH - statusWindow->statusH;
2926         }
2927         XMoveWindow(dpy, statusWindow->w, x, y);
2928     }
2929 }
2930 
2931 static void arrange_window_stack(StatusWindow* statusWindow)
2932 {
2933     XWindowChanges xwc;
2934     int value_make = CWSibling|CWStackMode;
2935     Window root, parent, *children;
2936     unsigned int nchildren;
2937 
2938     if (NULL == statusWindow) return;
2939     if (XQueryTree(dpy, statusWindow->parent,
2940                        &root, &parent, &children, &nchildren)){
2941         XFree(children);
2942         xwc.sibling = parent;
2943         while(XQueryTree(dpy, xwc.sibling, &root, &parent, &children, &nchildren)) {
2944             XFree(children);
2945             if (root != parent) {
2946                 xwc.sibling = parent;
2947             } else {
2948                 break;
2949             }
2950         }
2951         xwc.stack_mode = Above;
2952         XConfigureWindow(dpy, statusWindow->w, value_make, &xwc);
2953     }
2954 }
2955 
2956 static int count_missing_fonts(char **charset_list, int charset_count)
2957 {
2958     int i,j;
2959     if (charset_count > 0) {
2960         j=charset_count;
2961         for(i=0; i < charset_count; i++) {
2962             if ((strstr(charset_list[i], "IBM-udc")) ||
2963                 (strstr(charset_list[i], "IBM-sbd")) ||
2964                 (strstr(charset_list[i], "IBM-ucdTW")))
2965                 j--;
2966         }
2967         return j;
2968     }
2969     else
2970         return 0;
2971 }
2972 
2973 static XFontSet create_fontset_name(char * font_name, Bool force)
2974 {
2975     XFontSet fontset = NULL;
2976     char **charset_list;
2977     int charset_count;
2978     char *def_string;
2979     int missing_fonts;
2980 
2981     fontset = XCreateFontSet(dpy, font_name,
2982                 &charset_list, &charset_count, &def_string);
2983     if (charset_count > 0) {
2984         missing_fonts = count_missing_fonts(charset_list,
2985                                             charset_count);
2986         XFreeStringList(charset_list);
2987         if (fontset && (missing_fonts > 0)) {
2988             if (!force) {
2989                 XFreeFontSet(dpy, fontset);
2990                 fontset = NULL;
2991             }
2992         }
2993     }
2994     return fontset;
2995 }
2996 
2997 static XFontSet create_fontset()
2998 {
2999     XFontSet fontset = NULL;
3000     int i;
3001     static char * fontlist[] = {
3002         "-dt-interface user-medium-r-normal-S*-*-*-*-*-*-*-*-*",
3003         "-*-*-medium-r-normal-*-14-*-*-*-c-*-*-*",
3004         "-*-*-medium-r-normal-*-14-*-*-*-m-*-*-*",
3005         "-*-*-medium-r-normal--14-0-0-0-m-*-*-*",
3006         "-monotype-sansmonowt-medium-r-normal--14-*-*-*-m-*-*-*",
3007         "-*--14-*",
3008         "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*",
3009         "-*--16-*",
3010         "-*--17-*",
3011         "-*--18-*",
3012         "-*--19-*",
3013         "-*--20-*",
3014         "-*--24-*",
3015         NULL};
3016 
3017     for (i=0; fontlist[i] != NULL && fontset==NULL; i++)
3018         fontset = create_fontset_name(fontlist[i], False);
3019 
3020     if (!fontset)
3021         fprintf(stdout, "Cannot load fonts for IMF.\n");
3022     return  fontset;
3023 }
3024 
3025 static Window get_current_focus(XIC ic)
3026 {
3027     Window w = 0;
3028     if (ic != NULL)
3029         XGetICValues(ic, XNFocusWindow, &w, NULL);
3030     return w;
3031 }
3032 #endif
< prev index next >