Back to index

im-sdk  12.3.91
i18nX.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 #include "FrameMgr.h"
00032 #include "X11R6IMProtoData.h"
00033 #include "Xi18n.h"
00034 #include "Xi18nX.h"
00035 
00036 extern Xi18nClient *_Xi18nFindClient(Xi18n, CARD16);
00037 extern Xi18nClient *_Xi18nNewClient(Xi18n);
00038 extern void _Xi18nDeleteClient(Xi18n, CARD16);
00039 static Bool WaitXConnectMessage(Display*, Window,
00040                             XEvent*, XPointer);
00041 static Bool WaitXIMProtocol(Display*, Window, XEvent*, XPointer);
00042 
00043 static XClient *
00044 NewXClient(Xi18n i18n_core, Window new_client)
00045 {
00046     Display *dpy = i18n_core->address.dpy;
00047     Xi18nClient *client = _Xi18nNewClient(i18n_core);
00048     XClient *x_client;
00049 
00050     x_client = (XClient *)malloc(sizeof(XClient));
00051     x_client->client_win = new_client;
00052     x_client->accept_win = XCreateSimpleWindow(dpy,
00053                                           DefaultRootWindow(dpy),
00054                                           0, 0, 1, 1, 1, 0, 0);
00055     client->trans_rec = x_client;
00056     return ((XClient *)x_client);
00057 }
00058 
00059 static unsigned char *
00060 ReadXIMMessage(XIMS ims, XClientMessageEvent *ev,
00061               int *connect_id)
00062 {
00063     Xi18n i18n_core = ims->protocol;
00064     Xi18nClient *client = i18n_core->address.clients;
00065     XClient *x_client = NULL;
00066 
00067     FrameMgr fm;
00068     extern XimFrameRec packet_header_fr[];
00069     register int total_size;
00070     unsigned char *p = NULL;
00071     unsigned char *p1;
00072 
00073     while (client != NULL) {
00074        x_client = (XClient *)client->trans_rec;
00075        if (x_client->accept_win == ev->window) {
00076            *connect_id = client->connect_id;
00077            break;
00078        }
00079        client = client->next;
00080     }
00081 
00082     if (ev->format == 8) {  /* ClientMessage only */
00083        XimProtoHdr *hdr = (XimProtoHdr *)ev->data.b;
00084        unsigned char *rec = (unsigned char *)(hdr + 1);
00085        CARD8 major_opcode, minor_opcode;
00086        CARD16 length;
00087        extern int _Xi18nNeedSwap(Xi18n, CARD16);
00088 
00089        if (client->byte_order == '?') {
00090            if (hdr->major_opcode == XIM_CONNECT)
00091              client->byte_order = (CARD8)rec[0];
00092            else
00093              return (unsigned char *)NULL;       /* can do nothing */
00094        }
00095        /* create FrameMgr */
00096        fm = FrameMgrInit(packet_header_fr, (char *)hdr,
00097                        _Xi18nNeedSwap(i18n_core, *connect_id));
00098 
00099        total_size = FrameMgrGetTotalSize(fm);
00100        /* get data */
00101        FrameMgrGetToken(fm, major_opcode);
00102        FrameMgrGetToken(fm, minor_opcode);
00103        FrameMgrGetToken(fm, length);
00104 
00105        /* free FrameMgr */
00106        FrameMgrFree(fm);
00107 
00108        if ((p = (unsigned char *)malloc(total_size + length * 4)) == NULL)
00109          return (unsigned char *)NULL;
00110        p1 = p;
00111        memmove(p1, &major_opcode, sizeof(CARD8)); p1 += sizeof(CARD8);
00112        memmove(p1, &minor_opcode, sizeof(CARD8)); p1 += sizeof(CARD8);
00113        memmove(p1, &length, sizeof(CARD16)); p1 += sizeof(CARD16);
00114        memmove(p1, rec, length * 4);
00115     } else if (ev->format == 32) { /* ClientMessage and WindowProperty */
00116        unsigned long length = (unsigned long)ev->data.l[0];
00117        Atom atom = (Atom)ev->data.l[1];
00118        int         return_code;
00119        Atom        actual_type_ret;
00120        int         actual_format_ret;
00121        unsigned long    bytes_after_ret;
00122        unsigned char    *prop;
00123        unsigned long    nitems;
00124 
00125        return_code = XGetWindowProperty(i18n_core->address.dpy,
00126                                     x_client->accept_win, atom,
00127                                     0L, length,
00128                                     True, AnyPropertyType,
00129                                     &actual_type_ret, &actual_format_ret,
00130                                     &nitems, &bytes_after_ret, &prop);
00131        if (return_code != Success
00132            || actual_format_ret == 0 || nitems == 0) {
00133            if (return_code == Success)
00134              XFree(prop);
00135            return (unsigned char *)NULL;
00136        }
00137        if (length != nitems) length = nitems;
00138                             /* if hit, it might be an error */
00139        if ((p = (unsigned char *)malloc(length)) == NULL)
00140          return (unsigned char *)NULL;
00141        memmove(p, prop, length);
00142        XFree(prop);
00143     }
00144     return (unsigned char *)p;
00145 }
00146 
00147 static void
00148 ReadXConnectMessage(XIMS ims, XClientMessageEvent *ev)
00149 {
00150     Xi18n i18n_core = ims->protocol;
00151     XSpecRec *spec = (XSpecRec *)i18n_core->address.connect_addr;
00152     XEvent event;
00153     Display *dpy = i18n_core->address.dpy;
00154     Window new_client = ev->data.l[0];
00155     CARD32 major_version = ev->data.l[1];
00156     CARD32 minor_version = ev->data.l[2];
00157     XClient *x_client = NewXClient(i18n_core, new_client);
00158 
00159     if (ev->window != i18n_core->address.im_window)
00160       return;               /* incorrect connection request */
00161 
00162     if (major_version != 0 || minor_version != 0) {
00163        major_version = minor_version = 0;
00164        /* Only supporting only-CM & Property-with-CM method */
00165     }
00166     _XRegisterFilterByType(dpy, x_client->accept_win,
00167                         ClientMessage, ClientMessage,
00168                         WaitXIMProtocol, (XPointer)ims);
00169     event.xclient.type = ClientMessage;
00170     event.xclient.display = dpy;
00171     event.xclient.window = new_client;
00172     event.xclient.message_type = spec->connect_request;
00173     event.xclient.format       = 32;
00174     event.xclient.data.l[0]    = x_client->accept_win;
00175     event.xclient.data.l[1]    = major_version;
00176     event.xclient.data.l[2]    = minor_version;
00177     event.xclient.data.l[3]    = XCM_DATA_LIMIT;
00178 
00179     XSendEvent(dpy, new_client,
00180               False, NoEventMask, &event);
00181     XFlush(dpy);
00182 }
00183 
00184 static Bool
00185 Xi18nXBegin(XIMS ims)
00186 {
00187     Xi18n i18n_core = ims->protocol;
00188     Display *dpy = i18n_core->address.dpy;
00189     XSpecRec *spec = (XSpecRec *)i18n_core->address.connect_addr;
00190 
00191     spec->xim_request = XInternAtom(i18n_core->address.dpy,
00192                                 _XIM_PROTOCOL, False);
00193     spec->connect_request = XInternAtom(i18n_core->address.dpy,
00194                                    _XIM_XCONNECT, False);
00195 
00196     _XRegisterFilterByType(dpy, i18n_core->address.im_window,
00197                         ClientMessage, ClientMessage,
00198                         WaitXConnectMessage, (XPointer)ims);
00199     return True;
00200 }
00201 
00202 static Bool
00203 Xi18nXEnd(XIMS ims)
00204 {
00205     Xi18n i18n_core = ims->protocol;
00206     Display *dpy = i18n_core->address.dpy;
00207 
00208     _XUnregisterFilter(dpy, i18n_core->address.im_window,
00209                      WaitXConnectMessage, (XPointer)ims);
00210     return True;
00211 }
00212 
00213 static char *
00214 MakeNewAtom(CARD16 connect_id, char *atomName)
00215 {
00216     static int sequence = 0;
00217     sprintf(atomName, "_server%d_%d", connect_id,
00218            (sequence > 20 ? (sequence = 0) : sequence++));
00219     return atomName;
00220 }
00221 
00222 static Bool
00223 Xi18nXSend(XIMS ims, CARD16 connect_id,
00224           unsigned char *reply, long length)
00225 {
00226     Xi18n i18n_core = ims->protocol;
00227     Xi18nClient *client = _Xi18nFindClient(i18n_core, connect_id);
00228     XSpecRec *spec = (XSpecRec *)i18n_core->address.connect_addr;
00229     XClient *x_client = (XClient *)client->trans_rec;
00230     XEvent event;
00231     
00232     event.type = ClientMessage;
00233     event.xclient.window = x_client->client_win;
00234     event.xclient.message_type = spec->xim_request;
00235 
00236     if (length > XCM_DATA_LIMIT) {
00237        Atom atom;
00238        char atomName[16];
00239        Atom actual_type_ret;
00240        int actual_format_ret;
00241        int return_code;
00242        unsigned long nitems_ret;
00243        unsigned long bytes_after_ret;
00244        unsigned char *win_data;
00245 
00246        event.xclient.format = 32;
00247        atom = XInternAtom(i18n_core->address.dpy,
00248                         MakeNewAtom(connect_id, atomName), False);
00249        return_code = XGetWindowProperty(i18n_core->address.dpy,
00250                              x_client->client_win, atom, 0L, 10000L,
00251                              False, XA_STRING, &actual_type_ret,
00252                              &actual_format_ret, &nitems_ret,
00253                              &bytes_after_ret, &win_data);
00254        if (return_code != Success)
00255          return False;
00256        if (win_data)
00257          XFree((char *)win_data);
00258        XChangeProperty(i18n_core->address.dpy,
00259                      x_client->client_win, atom, XA_STRING, 8,
00260                      PropModeAppend, (unsigned char *)reply, length);
00261        event.xclient.data.l[0] = length;
00262        event.xclient.data.l[1] = atom;
00263     }
00264     else {
00265        unsigned char buffer[XCM_DATA_LIMIT];
00266        int i;
00267 
00268        event.xclient.format = 8;
00269 
00270        /* Clear unused field with NULL */
00271        memmove(buffer, reply, length);
00272        for (i = length; i < XCM_DATA_LIMIT; i++) {
00273            buffer[i] = (char)0;
00274        }
00275        length = XCM_DATA_LIMIT;
00276        memmove(event.xclient.data.b, buffer, length);
00277     }
00278     XSendEvent(i18n_core->address.dpy,
00279               x_client->client_win, False, NoEventMask, &event);
00280     XFlush(i18n_core->address.dpy);
00281     return True;
00282 }
00283 
00284 static Bool
00285 CheckCMEvent(Display *display, XEvent *event, XPointer xi18n_core)
00286 {
00287     Xi18n i18n_core = (Xi18n)((void *)xi18n_core);
00288     XSpecRec *spec = (XSpecRec *)i18n_core->address.connect_addr;
00289 
00290     if ((event->type == ClientMessage)
00291        && (event->xclient.message_type == spec->xim_request))
00292       return True;
00293     return False;
00294 
00295 }
00296 
00297 static Bool
00298 Xi18nXWait(XIMS ims, CARD16 connect_id,
00299           CARD8 major_opcode, CARD8 minor_opcode)
00300 {
00301     Xi18n i18n_core = ims->protocol;
00302     XEvent event;
00303     Xi18nClient *client = _Xi18nFindClient(i18n_core, connect_id);
00304     XClient *x_client = (XClient *)client->trans_rec;
00305 
00306     for (;;) {
00307        unsigned char *packet;
00308        XimProtoHdr *hdr;
00309        int connect_id_ret;
00310 
00311        XIfEvent(i18n_core->address.dpy, &event,
00312                CheckCMEvent, (XPointer)i18n_core);
00313        if (event.xclient.window == x_client->accept_win) {
00314 
00315            if ((packet = ReadXIMMessage(ims,
00316                              (XClientMessageEvent *)&event,
00317                              &connect_id_ret))
00318               == (unsigned char*)NULL) return False;
00319 
00320            hdr = (XimProtoHdr *)packet;
00321 
00322            if ((hdr->major_opcode == major_opcode) &&
00323               (hdr->minor_opcode == minor_opcode))
00324              return True;
00325            else if (hdr->major_opcode == XIM_ERROR)
00326              return False;
00327        }
00328     }
00329 }
00330 
00331 static Bool
00332 Xi18nXDisconnect(XIMS ims, CARD16 connect_id)
00333 {
00334     Xi18n i18n_core = ims->protocol;
00335     Display *dpy = i18n_core->address.dpy;
00336     Xi18nClient *client = _Xi18nFindClient(i18n_core, connect_id);
00337     XClient *x_client = (XClient *)client->trans_rec;
00338 
00339     XDestroyWindow(dpy, x_client->accept_win);
00340     _XUnregisterFilter(dpy, x_client->accept_win,
00341                      WaitXIMProtocol, (XPointer)ims);
00342     XFree(x_client);
00343     _Xi18nDeleteClient(i18n_core, connect_id);
00344     return True;
00345 }
00346 
00347 Bool
00348 _Xi18nCheckXAddress(Xi18n i18n_core, TransportSW *transSW,
00349                   char *address)
00350 {
00351     XSpecRec *spec;
00352 
00353     if(!(spec = (XSpecRec *)malloc(sizeof(XSpecRec))))
00354       return False ;
00355 
00356     i18n_core->address.connect_addr = (XSpecRec *)spec;
00357     i18n_core->methods.begin = Xi18nXBegin;
00358     i18n_core->methods.end  = Xi18nXEnd;
00359     i18n_core->methods.send = Xi18nXSend;
00360     i18n_core->methods.wait = Xi18nXWait;
00361     i18n_core->methods.disconnect = Xi18nXDisconnect;
00362     return True;
00363 }
00364 
00365 static Bool
00366 WaitXConnectMessage(Display *dpy, Window win,
00367                   XEvent *ev, XPointer client_data)
00368 {
00369     XIMS ims = (XIMS)client_data;
00370     Xi18n i18n_core = ims->protocol;
00371     XSpecRec *spec = (XSpecRec *)i18n_core->address.connect_addr;
00372 
00373     if (((XClientMessageEvent *)ev)->message_type ==
00374        spec->connect_request) {
00375        ReadXConnectMessage(ims,
00376                          (XClientMessageEvent *)ev);
00377        return True;
00378     }
00379     return False;
00380 }
00381 
00382 static Bool
00383 WaitXIMProtocol(Display *dpy, Window win,
00384               XEvent *ev, XPointer client_data)
00385 {
00386     XIMS ims = (XIMS)client_data;
00387     Xi18n i18n_core = ims->protocol;
00388     XSpecRec *spec = (XSpecRec *)i18n_core->address.connect_addr;
00389     extern void _Xi18nMessageHandler(XIMS, CARD16,
00390                                  unsigned char*, Bool*);
00391     Bool delete = True;
00392     unsigned char *packet;
00393     int connect_id;
00394 
00395     if (((XClientMessageEvent *)ev)->message_type ==
00396        spec->xim_request) {
00397        if ((packet = ReadXIMMessage(ims,
00398                                  (XClientMessageEvent *)ev,
00399                                  &connect_id))
00400            == (unsigned char*)NULL) return False;
00401 
00402        _Xi18nMessageHandler(ims, connect_id, packet, &delete);
00403        if (delete == True)
00404            XFree(packet);
00405        return True;
00406     }
00407     return False;
00408 }