Back to index

im-sdk  12.3.91
i18nMethod.c
Go to the documentation of this file.
00001 /******************************************************************
00002  
00003          Copyright 1994, 1995 by Sun Microsystems, Inc.
00004          Copyright 1993, 1994 by Hewlett-Packard Company
00005  
00006 Permission to use, copy, modify, distribute, and sell this software
00007 and its documentation for any purpose is hereby granted without fee,
00008 provided that the above copyright notice appear in all copies and
00009 that both that copyright notice and this permission notice appear
00010 in supporting documentation, and that the name of Sun Microsystems, Inc.
00011 and Hewlett-Packard not be used in advertising or publicity pertaining to
00012 distribution of the software without specific, written prior permission.
00013 Sun Microsystems, Inc. and Hewlett-Packard make no representations about
00014 the suitability of this software for any purpose.  It is provided "as is"
00015 without express or implied warranty.
00016  
00017 SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL
00018 WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
00019 WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
00020 SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY
00021 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
00022 RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
00023 CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
00024 IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00025  
00026   Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc.
00027  
00028 ******************************************************************/
00029 #include <X11/Xlib.h>
00030 #include <X11/Xatom.h>
00031 #ifndef NEED_EVENTS
00032 #define NEED_EVENTS
00033 #endif
00034 #include <X11/Xproto.h>
00035 #undef NEED_EVENTS
00036 #include "FrameMgr.h"
00037 #include "Xi18n.h"
00038 #include "XIC_Interface.h"
00039 
00040 extern Xi18nClient *_Xi18nFindClient(Xi18n, CARD16);
00041 static void *xi18n_setup(Display*, XIMArg*);
00042 static Status xi18n_openIM(XIMS);
00043 static Status xi18n_closeIM(XIMS);
00044 static char *xi18n_setIMValues(XIMS, XIMArg*);
00045 static char *xi18n_getIMValues(XIMS, XIMArg*);
00046 static Status xi18n_forwardEvent(XIMS, IMForwardEventStruct*);
00047 static Status xi18n_commit(XIMS, IMCommitEventStruct*);
00048 static Status xi18n_callCallback(XIMS, X11R6IMProtocol);
00049 static Status xi18n_preeditStart(XIMS, X11R6IMProtocol);
00050 static Status xi18n_preeditEnd(XIMS, X11R6IMProtocol);
00051 
00052 IMMethodsRec Xi18n_im_methods = {
00053     xi18n_setup,
00054     xi18n_openIM,
00055     xi18n_closeIM,
00056     xi18n_setIMValues,
00057     xi18n_getIMValues,
00058     xi18n_forwardEvent,
00059     xi18n_commit,
00060     xi18n_callCallback,
00061     xi18n_preeditStart,
00062     xi18n_preeditEnd,
00063 };
00064 
00065 extern Bool _Xi18nCheckXAddress(Xi18n, TransportSW *, char *);
00066 extern Bool _Xi18nCheckTransAddress(Xi18n, TransportSW *, char *);
00067 extern void _Xi18nChangeIMList(Xi18n i18n_core, XPointer value);
00068 extern void _Xi18nChangeICList(Xi18n i18n_core, XPointer value);
00069 extern void _Xi18nInitAttrList(Xi18n i18n_core);
00070 extern void _Xi18nInitExtension(Xi18n i18n_core);
00071 extern int _Xi18nNeedSwap(Xi18n i18n_core, CARD16 connect_id);
00072 extern void _Xi18nSendMessage(XIMS ims, CARD16 connect_id,
00073                            CARD8 major_opcode, CARD8 minor_opcode,
00074                            unsigned char *data, long length);
00075 extern int _Xi18nGeometryCallback(XIMS ims, X11R6IMProtocol call_data);
00076 extern int _Xi18nPreeditStartCallback(XIMS ims, X11R6IMProtocol call_data);
00077 extern int _Xi18nPreeditDrawCallback(XIMS ims, X11R6IMProtocol call_data);
00078 extern int _Xi18nPreeditCaretCallback(XIMS ims, X11R6IMProtocol call_data);
00079 extern int _Xi18nPreeditDoneCallback(XIMS ims, X11R6IMProtocol call_data);
00080 extern int _Xi18nStatusStartCallback(XIMS ims, X11R6IMProtocol call_data);
00081 extern int _Xi18nStatusDrawCallback(XIMS ims, X11R6IMProtocol call_data);
00082 extern int _Xi18nStatusDoneCallback(XIMS ims, X11R6IMProtocol call_data);
00083 extern int _Xi18nStringConversionCallback(XIMS ims, X11R6IMProtocol call_data);
00084 extern void _Xi18nSetEventMask(XIMS ims, CARD16 connect_id,
00085                             CARD16 im_id, CARD16 ic_id,
00086                             CARD32 forward_mask, CARD32 sync_mask);
00087 
00088 TransportSW _TransR[] = {
00089     {"X",          1, _Xi18nCheckXAddress},
00090 #ifdef USE_DIRECT_CONN
00091     {"tcp",        3, _Xi18nCheckTransAddress},
00092     {"local",      5, _Xi18nCheckTransAddress},
00093 #endif
00094 #ifdef DNETCONN
00095     {"decnet",     6, _Xi18nCheckTransAddress},
00096 #endif
00097     {(char *)NULL, 0, (Bool (*)())NULL}
00098 };
00099 
00100 static Bool
00101 GetInputStyles(Xi18n i18n_core, XIMStyles **p_style)
00102 {
00103     Xi18nAddressRec  *address = (Xi18nAddressRec *)&i18n_core->address;
00104     XIMStyles        *p;
00105     int                     i;
00106 
00107     p = &address->input_styles;
00108     if ((*p_style = (XIMStyles *)malloc(sizeof(XIMStyles)
00109               + p->count_styles * sizeof(XIMStyle))) == NULL)
00110       return False;
00111     (*p_style)->count_styles = p->count_styles;
00112     (*p_style)->supported_styles = (XIMStyle *)((XPointer)*p_style + sizeof(XIMStyles));
00113     for (i = 0; i < (int)p->count_styles; i++) {
00114        (*p_style)->supported_styles[i] = p->supported_styles[i];
00115     }
00116     return True;
00117 }
00118 
00119 static Bool
00120 GetOnOffKeys(Xi18n i18n_core, long mask, XIMTriggerKeys **p_key)
00121 {
00122     Xi18nAddressRec  *address = (Xi18nAddressRec *)&i18n_core->address;
00123     XIMTriggerKeys   *p;
00124     int                     i;
00125 
00126     if (mask & I18N_ON_KEYS)
00127       p = &address->on_keys;
00128     else
00129       p = &address->off_keys;
00130 
00131     if ((*p_key = (XIMTriggerKeys *)malloc(sizeof(XIMTriggerKeys)
00132               + p->count_keys * sizeof(XIMTriggerKey))) == NULL)
00133       return False;
00134     (*p_key)->count_keys = p->count_keys;
00135     (*p_key)->keylist = (XIMTriggerKey *)((XPointer)*p_key + sizeof(XIMTriggerKeys));
00136     for (i = 0; i < (int)p->count_keys; i++) {
00137        (*p_key)->keylist[i].keysym = p->keylist[i].keysym;
00138        (*p_key)->keylist[i].modifier = p->keylist[i].modifier;
00139        (*p_key)->keylist[i].modifier_mask = p->keylist[i].modifier_mask;
00140     }
00141     return True;
00142 }
00143 
00144 static Bool
00145 GetEncodings(Xi18n i18n_core, XIMEncodings **p_encoding)
00146 {
00147     Xi18nAddressRec  *address = (Xi18nAddressRec *)&i18n_core->address;
00148     XIMEncodings     *p;
00149     int                     i;
00150 
00151     p = &address->encoding_list;
00152 
00153     if ((*p_encoding = (XIMEncodings *)malloc(sizeof(XIMEncodings)
00154               + p->count_encodings * sizeof(XIMEncoding))) == NULL)
00155       return False;
00156     (*p_encoding)->count_encodings = p->count_encodings;
00157     (*p_encoding)->supported_encodings = (XIMEncoding *)((XPointer)*p_encoding + sizeof(XIMEncodings));
00158     for (i = 0; i < (int)p->count_encodings; i++) {
00159        (*p_encoding)->supported_encodings[i]
00160          = (char *)malloc(strlen(p->supported_encodings[i]) + 1);
00161        strcpy((*p_encoding)->supported_encodings[i],
00162               p->supported_encodings[i]);
00163     }
00164     return True;
00165 }
00166 
00167 static char *
00168 ParseArgs(Xi18n i18n_core, int mode, XIMArg *args)
00169 {
00170     Xi18nAddressRec *address = (Xi18nAddressRec *)&i18n_core->address;
00171     XIMArg *p;
00172     
00173     if (mode == I18N_OPEN || mode == I18N_SET) {
00174        for (p = args; p->name != NULL; p++) {
00175            if (!strcmp(p->name, IMLocale)) {
00176               if (address->imvalue_mask & I18N_IM_LOCALE) {
00177                   return IMLocale;
00178               }
00179               address->im_locale = (char *)malloc(strlen(p->value) + 1);
00180               if (!address->im_locale)
00181                 return IMLocale;
00182               strcpy(address->im_locale, p->value);
00183               address->imvalue_mask |= I18N_IM_LOCALE;
00184            }
00185            else if (!strcmp(p->name, IMSupportedIMValues)) {
00186               _Xi18nChangeIMList(i18n_core, p->value);
00187            }
00188            else if (!strcmp(p->name, IMSupportedICValues)) {
00189               _Xi18nChangeICList(i18n_core, p->value);
00190            }
00191            else if (!strcmp(p->name, IMServerTransport)) {
00192               if (address->imvalue_mask & I18N_IM_ADDRESS) {
00193                   return IMServerTransport;
00194               }
00195               address->im_addr = (char *)malloc(strlen(p->value) + 1);
00196               if (!address->im_addr)
00197                 return IMServerTransport;
00198               strcpy(address->im_addr, p->value);
00199               address->imvalue_mask |= I18N_IM_ADDRESS;
00200            }
00201            else if (!strcmp(p->name, IMServerName)) {
00202               if (address->imvalue_mask & I18N_IM_NAME) {
00203                   return IMServerName;
00204               }
00205               address->im_name = (char *)malloc(strlen(p->value) + 1);
00206               if (!address->im_name)
00207                 return IMServerName;
00208               strcpy(address->im_name, p->value);
00209               address->imvalue_mask |= I18N_IM_NAME;
00210            }
00211            else if (!strcmp(p->name, IMServerWindow)) {
00212               if (address->imvalue_mask & I18N_IMSERVER_WIN) {
00213                   return IMServerWindow;
00214               }
00215               address->im_window = (Window)p->value;
00216               address->imvalue_mask |= I18N_IMSERVER_WIN;
00217            }
00218            else if (!strcmp(p->name, IMInputStyles)) {
00219               if (address->imvalue_mask & I18N_INPUT_STYLES) {
00220                   return IMInputStyles;
00221               }
00222               address->input_styles.count_styles =
00223                 ((XIMStyles*)p->value)->count_styles;
00224               address->input_styles.supported_styles =
00225                 (XIMStyle*)malloc(sizeof(XIMStyle)
00226                                 * address->input_styles.count_styles);
00227               if (address->input_styles.supported_styles == (XIMStyle*)NULL)
00228                 return IMInputStyles;
00229               memmove(address->input_styles.supported_styles,
00230                      ((XIMStyles*)p->value)->supported_styles,
00231                      sizeof(XIMStyle) *
00232                         address->input_styles.count_styles);
00233               address->imvalue_mask |= I18N_INPUT_STYLES;
00234            }
00235            else if (!strcmp(p->name, IMProtocolHandler)) {
00236 #if IM_PROTO_HANDLER
00237               address->improto = (X11R6IMProtoHandler*)p->value;
00238               address->imvalue_mask |= I18N_IM_HANDLER;
00239 #endif
00240            }
00241            else if (!strcmp(p->name, IMOnKeysList)) {
00242               if (address->imvalue_mask & I18N_ON_KEYS) {
00243                   return IMOnKeysList;
00244               }
00245               address->on_keys.count_keys =
00246                 ((XIMTriggerKeys*)p->value)->count_keys;
00247               if (address->on_keys.count_keys > 0) {
00248                 address->on_keys.keylist =
00249                   (XIMTriggerKey*)malloc(sizeof(XIMTriggerKey)
00250                                       * address->on_keys.count_keys);
00251                 if (address->on_keys.keylist == (XIMTriggerKey*)NULL)
00252                   return IMOnKeysList;
00253                 memmove(address->on_keys.keylist,
00254                        ((XIMTriggerKeys*)p->value)->keylist,
00255                        sizeof(XIMTriggerKey) * address->on_keys.count_keys);
00256                 address->imvalue_mask |= I18N_ON_KEYS;
00257               }
00258            }
00259            else if (!strcmp(p->name, IMOffKeysList)) {
00260               if (address->imvalue_mask & I18N_OFF_KEYS) {
00261                   return IMOffKeysList;
00262               }
00263               if (address->off_keys.count_keys > 0) {
00264                 address->off_keys.count_keys =
00265                   ((XIMTriggerKeys*)p->value)->count_keys;
00266                 address->off_keys.keylist =
00267                   (XIMTriggerKey*)malloc(sizeof(XIMTriggerKey)
00268                                       * address->off_keys.count_keys);
00269                 if (address->off_keys.keylist == (XIMTriggerKey*)NULL)
00270                   return IMOffKeysList;
00271                 memmove(address->off_keys.keylist,
00272                        ((XIMTriggerKeys*)p->value)->keylist,
00273                        sizeof(XIMTriggerKey) * address->off_keys.count_keys);
00274                 address->imvalue_mask |= I18N_OFF_KEYS;
00275               }
00276            }
00277            else if (!strcmp(p->name, IMEncodingList)) {
00278               if (address->imvalue_mask & I18N_ENCODINGS) {
00279                   return IMEncodingList;
00280               }
00281               address->encoding_list.count_encodings =
00282                 ((XIMEncodings*)p->value)->count_encodings;
00283               address->encoding_list.supported_encodings =
00284                 (XIMEncoding*)malloc(sizeof(XIMEncoding) *
00285                                    address->encoding_list.count_encodings);
00286               if (address->encoding_list.supported_encodings
00287                   == (XIMEncoding*)NULL)
00288                 return IMEncodingList;
00289               memmove(address->encoding_list.supported_encodings,
00290                      ((XIMEncodings*)p->value)->supported_encodings,
00291                      sizeof(XIMEncoding) *
00292                        address->encoding_list.count_encodings);
00293               address->imvalue_mask |= I18N_ENCODINGS;
00294            }
00295            else if (!strcmp(p->name, IMFilterEventMask)) {
00296               if (address->imvalue_mask & I18N_FILTERMASK) {
00297                   return IMFilterEventMask;
00298               }
00299               address->filterevent_mask = (long)p->value;
00300               address->imvalue_mask |= I18N_FILTERMASK;
00301            }
00302        }
00303        if (mode == I18N_OPEN) {
00304            /* check mandatory IM values */
00305            if (!(address->imvalue_mask & I18N_IM_LOCALE)) {
00306               /* locales must be set in IMOpenIM */
00307               return IMLocale;
00308            }
00309            if (!(address->imvalue_mask & I18N_IM_ADDRESS)) {
00310               /* address must be set in IMOpenIM */
00311               return IMServerTransport;
00312            }
00313        }
00314     } else if (mode == I18N_GET) {
00315        for (p = args; p->name != NULL; p++) {
00316            if (!strcmp(p->name, IMLocale)) {
00317               p->value = (char *)malloc(strlen(address->im_locale) + 1);
00318               if (!p->value)
00319                 return IMLocale;
00320               strcpy(p->value, address->im_locale);
00321            }
00322            else if (!strcmp(p->name, IMServerTransport)) {
00323               p->value = (char *)malloc(strlen(address->im_addr) + 1);
00324               if (!p->value)
00325                 return IMServerTransport;
00326               strcpy(p->value, address->im_addr);
00327            }
00328            else if (!strcmp(p->name, IMServerName)) {
00329               if (address->imvalue_mask & I18N_IM_NAME) {
00330                   p->value = (char *)malloc(strlen(address->im_name) + 1);
00331                   if (!p->value)
00332                     return IMServerName;
00333                   strcpy(p->value, address->im_name);
00334               } else {
00335                   return IMServerName;
00336               }
00337            }
00338            else if (!strcmp(p->name, IMServerWindow)) {
00339               if (address->imvalue_mask & I18N_IMSERVER_WIN) {
00340                   *((Window *)(p->value)) = address->im_window;
00341               } else {
00342                   return IMServerWindow;
00343               }
00344            }
00345            else if (!strcmp(p->name, IMInputStyles)) {
00346               if (GetInputStyles(i18n_core,
00347                                (XIMStyles **)p->value) == False) {
00348                   return IMInputStyles;
00349               }
00350            }
00351            else if (!strcmp(p->name, IMProtocolHandler)) {
00352 #if IM_PROTO_HANDLER
00353               if (address->imvalue_mask & I18N_IM_HANDLER) {
00354                   X11R6IMProtoHandler **handler =
00355                     (X11R6IMProtoHandler **)p->value;
00356                   *handler = address->improto;
00357               } else {
00358                   return IMProtocolHandler;
00359               }
00360 #endif
00361            }
00362            else if (!strcmp(p->name, IMOnKeysList)) {
00363               if (address->imvalue_mask & I18N_ON_KEYS) {
00364                   if (GetOnOffKeys(i18n_core, I18N_ON_KEYS,
00365                                  (XIMTriggerKeys **)p->value) == False) {
00366                      return IMOnKeysList;
00367                   }
00368               } else {
00369                   return IMOnKeysList;
00370               }
00371            }
00372            else if (!strcmp(p->name, IMOffKeysList)) {
00373               if (address->imvalue_mask & I18N_OFF_KEYS) {
00374                   if (GetOnOffKeys(i18n_core, I18N_OFF_KEYS,
00375                                  (XIMTriggerKeys **)p->value) == False) {
00376                      return IMOffKeysList;
00377                   }
00378               } else {
00379                   return IMOffKeysList;
00380               }
00381            }
00382            else if (!strcmp(p->name, IMEncodingList)) {
00383               if (address->imvalue_mask & I18N_ENCODINGS) {
00384                   if (GetEncodings(i18n_core,
00385                                  (XIMEncodings **)p->value) == False) {
00386                      return IMEncodingList;
00387                   }
00388               } else {
00389                   return IMEncodingList;
00390               }
00391            }
00392            else if (!strcmp(p->name, IMFilterEventMask)) {
00393               if (address->imvalue_mask & I18N_FILTERMASK) {
00394                   *((long *)(p->value)) = address->filterevent_mask;
00395               } else {
00396                   return IMFilterEventMask;
00397               }
00398            }
00399        }
00400     }
00401     return NULL;
00402 }
00403 
00404 static int
00405 CheckIMName(Xi18n i18n_core)
00406 {
00407     char *address = i18n_core->address.im_addr;
00408     int i;
00409 
00410     for (i = 0; _TransR[i].transportname; i++) {
00411        while (*address == ' ' || *address == '\t') address++;
00412        if (!strncmp(address, _TransR[i].transportname,
00413                    _TransR[i].namelen)
00414            && address[_TransR[i].namelen] == '/') {
00415            if (_TransR[i].checkAddr(i18n_core, &_TransR[i],
00416                           address+_TransR[i].namelen + 1) == True) {
00417               return True;
00418            } else {
00419               return False;
00420            }
00421        }
00422     }
00423     return False;
00424 }
00425 
00426 #ifndef XIM_SERVERS
00427 #define XIM_SERVERS "XIM_SERVERS"
00428 #endif
00429 
00430 static int
00431 SetXi18nSelectionOwner(Xi18n i18n_core)
00432 {
00433     static Atom XIM_Servers = None;
00434     Display *dpy = i18n_core->address.dpy;
00435     Window ims_win = i18n_core->address.im_window;
00436     Window root = RootWindow(dpy, DefaultScreen(dpy));
00437     Atom realtype;
00438     int realformat;
00439     unsigned long bytesafter;
00440     long *data;
00441     unsigned long length;
00442     Atom atom;
00443     Atom atom_bwc;
00444     int i;
00445     int found;
00446     int forse = False;
00447     char buf[256];
00448 
00449     /* FIXME */
00450     (void)sprintf(buf, "@server=%s", i18n_core->address.im_name);
00451     if ((atom = XInternAtom(dpy, buf, False)) == 0) {
00452        return False;
00453     }
00454     if ((atom_bwc = XInternAtom(dpy, "@server=htt", False)) == 0) {
00455         return False;
00456     }
00457     i18n_core->address.selection = atom;
00458     i18n_core->address.selection_bwc = atom_bwc;
00459 
00460     if (XIM_Servers == None)
00461       XIM_Servers = XInternAtom(dpy, XIM_SERVERS, False);
00462     XGetWindowProperty(dpy, root,
00463                      XIM_Servers, 0L, 1000000L, False, XA_ATOM,
00464                      &realtype, &realformat, &length,
00465                      &bytesafter, (unsigned char **)(&data));
00466     if (realtype == None) {
00467        /* specified property doesn't exist yet */
00468     } else if (realtype != XA_ATOM) {
00469        /* wrong type */
00470        return False;
00471     } else if (realformat != 32) {
00472        /* wrong format */
00473        if (data != NULL) XFree((char *)data);
00474        return False;
00475     }
00476     found = False;
00477     for (i = 0; i < length; i++) {
00478        if (data[i] == atom) {
00479            Window owner;
00480            found = True;
00481            if ((owner = XGetSelectionOwner(dpy, atom)) != ims_win ||
00482                 (owner = XGetSelectionOwner(dpy, atom_bwc)) != ims_win) {
00483               if (owner == None || forse == True) {
00484                 XSetSelectionOwner(dpy, atom, ims_win, CurrentTime);
00485                 XSetSelectionOwner(dpy, atom_bwc, ims_win, CurrentTime);
00486                 }
00487               else
00488                 return False;
00489            }
00490            break;
00491        }
00492     }
00493     if (data != NULL) XFree((char *)data);
00494 
00495     if (found == False) {
00496        XSetSelectionOwner(dpy, atom, ims_win, CurrentTime);
00497        XSetSelectionOwner(dpy, atom_bwc, ims_win, CurrentTime);
00498        (void)XChangeProperty(dpy, root, XIM_Servers, XA_ATOM,
00499                            32, PropModePrepend, (unsigned char *)&atom, 1);
00500        (void)XChangeProperty(dpy, root, XIM_Servers, XA_ATOM,
00501                            32, PropModePrepend, (unsigned char *)&atom_bwc, 1);
00502     }
00503     /* Intern "LOCALES" and "TRANSOPORT" Target Atoms */
00504     i18n_core->address.Localename = XInternAtom(dpy, LOCALES, False);
00505     i18n_core->address.Transportname = XInternAtom(dpy, TRANSPORT, False);
00506     return (XGetSelectionOwner(dpy, atom) == ims_win);
00507 }
00508 
00509 /* XIM protocol methods */
00510 static void *
00511 xi18n_setup(Display *dpy, XIMArg *args)
00512 {
00513     Xi18n i18n_core;
00514     CARD16 endian = 1;
00515 
00516     if ((i18n_core = (Xi18n)malloc(sizeof(Xi18nCore)))
00517        == (Xi18n)NULL) {
00518        return NULL;
00519     }
00520     memset(i18n_core, 0, sizeof(Xi18nCore));
00521 
00522     i18n_core->address.dpy = dpy;
00523 
00524     if (ParseArgs(i18n_core, I18N_OPEN, args) != NULL) {
00525        XFree(i18n_core);
00526        return NULL;
00527     }
00528     if (*(char *)&endian) {
00529        i18n_core->address.im_byteOrder = 'l';
00530     } else {
00531        i18n_core->address.im_byteOrder = 'B';
00532     }
00533 
00534     /* install IMAttr and ICAttr list in i18n_core */
00535     _Xi18nInitAttrList(i18n_core);
00536 
00537     /* install IMExtension list in i18n_core */
00538     _Xi18nInitExtension(i18n_core);
00539 
00540     return i18n_core;
00541 }
00542 
00543 static void
00544 ReturnSelectionNotify(Xi18n i18n_core, XSelectionRequestEvent *ev)
00545 {
00546     XEvent event;
00547     Display *dpy = i18n_core->address.dpy;
00548     char buf[256];
00549 
00550     event.type = SelectionNotify;
00551     event.xselection.requestor = ev->requestor;
00552     event.xselection.selection = ev->selection;
00553     event.xselection.target = ev->target;
00554     event.xselection.time = ev->time;
00555     event.xselection.property = ev->property;
00556     if (ev->target == i18n_core->address.Localename) {
00557        (void)sprintf(buf, "@locale=%s", i18n_core->address.im_locale);
00558     } else if (ev->target == i18n_core->address.Transportname) {
00559        (void)sprintf(buf, "@transport=%s", i18n_core->address.im_addr);
00560     }
00561     XChangeProperty(dpy, event.xselection.requestor,
00562                   ev->target, ev->target, 8,
00563                   PropModeReplace, (unsigned char *)buf, strlen(buf));
00564     XSendEvent(dpy, event.xselection.requestor, False, NoEventMask, &event);
00565     XFlush(i18n_core->address.dpy);
00566 }
00567 
00568 static Bool
00569 WaitXSelectionRequest(Display *dpy, Window win,
00570                     XEvent *ev, XPointer client_data)
00571 {
00572     XIMS ims = (XIMS)client_data;
00573     Xi18n i18n_core = ims->protocol;
00574 
00575     if (((XSelectionRequestEvent *)ev)->selection ==
00576        i18n_core->address.selection ||
00577         ((XSelectionRequestEvent *)ev)->selection ==
00578         i18n_core->address.selection_bwc) {
00579        ReturnSelectionNotify(i18n_core,
00580                            (XSelectionRequestEvent *)ev);
00581        return True;
00582     }
00583     return False;
00584 }
00585 
00586 static Status
00587 xi18n_openIM(XIMS ims)
00588 {
00589     Xi18n i18n_core = ims->protocol;
00590     Display *dpy = i18n_core->address.dpy;
00591 
00592     if (!CheckIMName(i18n_core)
00593        || !SetXi18nSelectionOwner(i18n_core)
00594        || !i18n_core->methods.begin(ims)) {
00595        XFree(i18n_core->address.im_name);
00596        XFree(i18n_core->address.im_locale);
00597        XFree(i18n_core->address.im_addr);
00598        XFree(i18n_core);
00599        return False;
00600     }
00601 
00602     _XRegisterFilterByType(dpy, i18n_core->address.im_window,
00603                         SelectionRequest, SelectionRequest,
00604                         WaitXSelectionRequest, (XPointer)ims);
00605     return True;
00606 }
00607 
00608 static Status
00609 xi18n_closeIM(XIMS ims)
00610 {
00611     Xi18n i18n_core = ims->protocol;
00612     Display *dpy = i18n_core->address.dpy;
00613 
00614     if (!i18n_core->methods.end(ims)) {
00615        return False;
00616     }
00617     _XUnregisterFilter(dpy, i18n_core->address.im_window,
00618                      WaitXSelectionRequest, (XPointer)ims);
00619     XFree(i18n_core->address.im_name);
00620     XFree(i18n_core->address.im_locale);
00621     XFree(i18n_core->address.im_addr);
00622     XFree(i18n_core);
00623     return True;
00624 }
00625 
00626 static char *
00627 xi18n_setIMValues(XIMS ims, XIMArg *args)
00628 {
00629     Xi18n i18n_core = ims->protocol;
00630     char *ret;
00631 
00632     if ((ret = ParseArgs(i18n_core, I18N_SET, args)) != NULL) {
00633        return ret;
00634     }
00635     return NULL;
00636 }
00637 
00638 static char *
00639 xi18n_getIMValues(XIMS ims, XIMArg *args)
00640 {
00641     Xi18n i18n_core = ims->protocol;
00642     char *ret;
00643 
00644     if ((ret = ParseArgs(i18n_core, I18N_GET, args)) != NULL) {
00645        return ret;
00646     }
00647     return NULL;
00648 }
00649 
00650 static void
00651 EventToWireEvent(XEvent *ev, xEvent *event, CARD16 *serial)
00652 {
00653     *serial = (CARD16)(ev->xany.serial >> 16);
00654     event->u.u.sequenceNumber = (CARD16)(ev->xany.serial & (unsigned long)0xffff);
00655 
00656     switch (ev->type) {
00657       case KeyPress:
00658       case KeyRelease:
00659        {
00660            XKeyEvent *kev = (XKeyEvent*)ev;
00661 
00662            event->u.u.type = ev->type;
00663            event->u.keyButtonPointer.root = kev->root;
00664            event->u.keyButtonPointer.state = kev->state;
00665            event->u.keyButtonPointer.time = kev->time;
00666            event->u.keyButtonPointer.event = kev->window;
00667            event->u.keyButtonPointer.child = kev->subwindow;
00668            event->u.keyButtonPointer.eventX = kev->x;
00669            event->u.keyButtonPointer.eventY = kev->y;
00670            event->u.keyButtonPointer.rootX = kev->x_root;
00671            event->u.keyButtonPointer.rootY = kev->y_root;
00672            event->u.keyButtonPointer.sameScreen = kev->same_screen;
00673            event->u.u.detail = kev->keycode;
00674        }
00675     }
00676 }
00677 
00678 static Status
00679 xi18n_forwardEvent(XIMS ims, IMForwardEventStruct *call_data)
00680 {
00681     Xi18n i18n_core = ims->protocol;
00682     FrameMgr fm;
00683     extern XimFrameRec forward_event_fr[];
00684     register int total_size;
00685     unsigned char *reply = NULL;
00686     unsigned char *replyp;
00687     CARD16 serial;
00688     int event_size;
00689     Xi18nClient *client = (Xi18nClient *)_Xi18nFindClient(i18n_core,
00690                                      call_data->connect_id);
00691 
00692     /* create FrameMgr */
00693     fm = FrameMgrInit(forward_event_fr, NULL,
00694                     _Xi18nNeedSwap(i18n_core, call_data->connect_id));
00695 
00696     total_size = FrameMgrGetTotalSize(fm);
00697     event_size = sizeof(xEvent);
00698     reply = (unsigned char *)malloc(total_size + event_size);
00699     if (!reply) {
00700        _Xi18nSendMessage(ims, call_data->connect_id,
00701                        XIM_ERROR, 0, 0, 0);
00702        return False;
00703     }
00704     memset(reply, 0, total_size + event_size);
00705     FrameMgrSetBuffer(fm, reply);
00706     replyp = reply;
00707 
00708 #ifdef FULL_SYNC_MODE
00709     call_data->sync_bit = 0;       /* off; SYNC_REPLY will sync */
00710 #else
00711     call_data->sync_bit = 1;       /* always sync */
00712     client->sync = True;
00713 #endif
00714 
00715     FrameMgrPutToken(fm, call_data->connect_id);
00716     FrameMgrPutToken(fm, call_data->icid);
00717     FrameMgrPutToken(fm, call_data->sync_bit);
00718 
00719     replyp += total_size;
00720     EventToWireEvent(&(call_data->event), (xEvent *)replyp, &serial);
00721 
00722     FrameMgrPutToken(fm, serial);
00723 
00724     _Xi18nSendMessage(ims, call_data->connect_id,
00725                     XIM_FORWARD_EVENT, 0,
00726                     reply, total_size + event_size);
00727 
00728     XFree(reply);
00729     /* free FrameMgr */
00730     FrameMgrFree(fm);
00731 
00732     return True;
00733 }
00734 
00735 static Status
00736 xi18n_commit(XIMS ims, IMCommitEventStruct *call_data)
00737 {
00738     Xi18n i18n_core = ims->protocol;
00739     FrameMgr fm;
00740     extern XimFrameRec commit_chars_fr[], commit_both_fr[];
00741     register int total_size;
00742     unsigned char *reply = NULL;
00743     CARD16 str_length;
00744 #ifndef FULL_SYNC_MODE
00745     Xi18nClient *client = (Xi18nClient *)_Xi18nFindClient(i18n_core,
00746                                      call_data->connect_id);
00747 
00748     call_data->flag |= XimSYNCHRONUS; /* always sync */
00749     client->sync = True;
00750 #endif
00751 
00752     if (!(call_data->flag & XimLookupKeySym) &&
00753        (call_data->flag & XimLookupChars)) {
00754        /* create FrameMgr */
00755        fm = FrameMgrInit(commit_chars_fr, NULL,
00756                        _Xi18nNeedSwap(i18n_core, call_data->connect_id));
00757 
00758        /* set length of STRING8 */
00759        str_length = strlen(call_data->commit_string);
00760        FrameMgrSetSize(fm, str_length);
00761        total_size = FrameMgrGetTotalSize(fm);
00762        reply = (unsigned char *)malloc(total_size);
00763        if (!reply) {
00764            _Xi18nSendMessage(ims, call_data->connect_id,
00765                            XIM_ERROR, 0, 0, 0);
00766            return False;
00767        }
00768        memset(reply, 0, total_size);
00769        FrameMgrSetBuffer(fm, reply);
00770 
00771        str_length = FrameMgrGetSize(fm);
00772        FrameMgrPutToken(fm, call_data->connect_id);
00773        FrameMgrPutToken(fm, call_data->icid);
00774        FrameMgrPutToken(fm, call_data->flag);
00775        FrameMgrPutToken(fm, str_length);
00776        FrameMgrPutToken(fm, call_data->commit_string);
00777     } else {
00778        /* create FrameMgr */
00779        fm = FrameMgrInit(commit_both_fr, NULL,
00780                        _Xi18nNeedSwap(i18n_core, call_data->connect_id));
00781        /* set length of STRING8 */
00782        str_length = strlen(call_data->commit_string);
00783        if (str_length > 0)
00784          FrameMgrSetSize(fm, str_length);
00785 
00786        total_size = FrameMgrGetTotalSize(fm);
00787        reply = (unsigned char *)malloc(total_size);
00788        if (!reply) {
00789            _Xi18nSendMessage(ims, call_data->connect_id,
00790                            XIM_ERROR, 0, 0, 0);
00791            return False;
00792        }
00793        memset(reply, 0, total_size);
00794        FrameMgrSetBuffer(fm, reply);
00795 
00796        FrameMgrPutToken(fm, call_data->connect_id);
00797        FrameMgrPutToken(fm, call_data->icid);
00798        FrameMgrPutToken(fm, call_data->flag);
00799        FrameMgrPutToken(fm, call_data->keysym);
00800        if (str_length > 0) {
00801          str_length = FrameMgrGetSize(fm);
00802          FrameMgrPutToken(fm, str_length);
00803          FrameMgrPutToken(fm, call_data->commit_string);
00804       }
00805     }
00806     if (IsFocused(call_data->icid)) {
00807       _Xi18nSendMessage(ims, call_data->connect_id,
00808                      XIM_COMMIT, 0, reply, total_size);
00809       XFree(reply);
00810     } else {
00811       Xi18nClient *client =
00812        (Xi18nClient *)_Xi18nFindClient(i18n_core,
00813                                    call_data->connect_id);
00814       client->pending_commit = reply;
00815       client->pending_commit_size = total_size;
00816     }
00817     /* free FrameMgr */
00818     FrameMgrFree(fm);
00819 
00820     return True;
00821 }
00822 
00823 static int
00824 xi18n_callCallback(XIMS ims, X11R6IMProtocol call_data) {
00825     switch (call_data->major_code) {
00826       case XIM_GEOMETRY:
00827        return _Xi18nGeometryCallback(ims, call_data);
00828       case XIM_PREEDIT_START:
00829        return _Xi18nPreeditStartCallback(ims, call_data);
00830       case XIM_PREEDIT_DRAW:
00831        return _Xi18nPreeditDrawCallback(ims, call_data);
00832       case XIM_PREEDIT_CARET:
00833        return _Xi18nPreeditCaretCallback(ims, call_data);
00834       case XIM_PREEDIT_DONE:
00835        return _Xi18nPreeditDoneCallback(ims, call_data);
00836       case XIM_STATUS_START:
00837        return _Xi18nStatusStartCallback(ims, call_data);
00838       case XIM_STATUS_DRAW:
00839        return _Xi18nStatusDrawCallback(ims, call_data);
00840       case XIM_STATUS_DONE:
00841        return _Xi18nStatusDoneCallback(ims, call_data);
00842       case XIM_STR_CONVERSION:
00843        return _Xi18nStringConversionCallback(ims, call_data);
00844       default:
00845        return False;
00846     }
00847 }
00848 
00849 /* preeditStart and preeditEnd are used only for Dynamic Event Flow. */
00850 static int
00851 xi18n_preeditStart(XIMS ims, X11R6IMProtocol call_data) {
00852     Xi18n i18n_core = ims->protocol;
00853     IMPreeditStateStruct *preedit_state =
00854       (IMPreeditStateStruct *)&call_data->preedit_state;
00855     long mask;
00856     int on_key_num = i18n_core->address.on_keys.count_keys;
00857     int off_key_num = i18n_core->address.off_keys.count_keys;
00858 
00859     if (on_key_num == 0 && off_key_num == 0)
00860       return False;
00861 
00862     if (i18n_core->address.imvalue_mask & I18N_FILTERMASK)
00863       mask = i18n_core->address.filterevent_mask;
00864     else
00865       mask = DEFAULT_FILTER_MASK;
00866 
00867       _Xi18nSetEventMask(ims, preedit_state->connect_id,
00868                       preedit_state->connect_id, preedit_state->icid,
00869 #ifdef FULL_SYNC_MODE
00870                       mask, mask);
00871 #else
00872                       mask, ~mask);
00873 #endif
00874     return True;
00875 }
00876 
00877 static int
00878 xi18n_preeditEnd(XIMS ims, X11R6IMProtocol call_data) {
00879     Xi18n i18n_core = ims->protocol;
00880     int on_key_num = i18n_core->address.on_keys.count_keys;
00881     int off_key_num = i18n_core->address.off_keys.count_keys;
00882     IMPreeditStateStruct *preedit_state =
00883       (IMPreeditStateStruct *)&call_data->preedit_state;
00884 
00885     if (on_key_num == 0 && off_key_num == 0)
00886       return False;
00887 
00888     _Xi18nSetEventMask(ims, preedit_state->connect_id,
00889                      preedit_state->connect_id, preedit_state->icid,
00890                      0, 0);
00891     return True;
00892 }