Back to index

im-sdk  12.3.91
xaux_so_common.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
00002 /*
00003  * Copyright (c) 1999 by Sun Microsystem, Inc.
00004  * All rights reserved.
00005  *
00006  * xaux_so_common.c
00007  */
00008 
00009 /*
00010    Copyright (c) 2004 Yu Shao <yshao@redhat.com>
00011    Copyright (c) 1997-2004 Red Hat, Inc. All rights reserved.
00012 */
00013 
00014 #include <stddef.h>
00015 #include <stdlib.h>
00016 #include <stdio.h>
00017 #include <string.h>
00018 #include <sys/types.h>
00019 #include <unistd.h>
00020 #include <limits.h>
00021 #include <libgen.h>
00022 #include <sys/param.h>
00023 
00024 #include <X11/Xlib.h>
00025 #include <X11/Xatom.h>
00026 
00027 #include "iiimpAux.h"
00028 
00029 #include "xaux_common.h"
00030 #include "xaux_so_common.h"
00031 
00032 #ifdef DEBUG
00033 #define       ENTER  fprintf(stderr, "%s enter.\n", __FUNCTION__);
00034 #define       LEAVE  fprintf(stderr, "%s leave.\n", __FUNCTION__);
00035 #else
00036 #define       ENTER
00037 #define       LEAVE
00038 #endif
00039 
00040 extern xaux_class_t xaux_classes[];
00041 
00042 static void          aux_icid_init(void);
00043 //static void        aux_icid_finish(void);
00044 static aux_icid_t *  aux_icid_get(int, Bool);
00045 //static void        aux_icid_delete(int);
00046 
00047 static int           aux_initialized = 0;
00048 
00049 #define HASH_SIZE 137
00050 static aux_icid_t    aux_icid[HASH_SIZE];
00051 
00052 /* workaround for "stored reference to aux_t is corrupred" problem */
00053 static void (*aux_setvalue)(aux_t *, const unsigned char *, int);
00054 static size_t (* mb_utf16)(const char **, size_t *, char **, size_t *);
00055 static unsigned char * (* compose)(const aux_data_t *, int *);
00056 static aux_t aux_tmp;
00057 
00058 static Bool xaux_so_Create(aux_t *);
00059 static Bool xaux_so_Start(aux_t *, const unsigned char *, int size);
00060 static Bool xaux_so_Draw(aux_t *, const unsigned char *, int size);
00061 static Bool xaux_so_Done(aux_t *, const unsigned char *, int size);
00062 static Bool xaux_so_Switched(aux_t *, int im_id, int on_off);
00063 static Bool xaux_so_Destroy(aux_t *);
00064 
00065 static Bool xaux_set_property (xaux_class_t *xc, unsigned char *prop_return);
00066 
00067 /* workaround_slowdtlogin */
00068 static Atom   atom_xbe = None;
00069 static Bool   is_server = False;
00070 static Atom   atom_launch_this = None;
00071 static Atom   atom_draw_this = None;
00072 /* workaround_slowdtlogin_end */
00073 
00074 aux_method_t xaux_so_methods = {
00075     xaux_so_Create,
00076     xaux_so_Start,
00077     xaux_so_Draw,
00078     xaux_so_Done,
00079     xaux_so_Switched,
00080     xaux_so_Destroy
00081 };
00082 
00083 static xaux_class_t *
00084 xaux_getclass_byatomxs(Atom atom)
00085 {
00086        xaux_class_t  *p = xaux_classes;
00087 
00088        while (p->classname != NULL) {
00089               if (p->atom_xs[0] == atom)
00090                      return (p);
00091               p++;
00092        }
00093 
00094        return (NULL);
00095 }
00096 
00097 static xaux_class_t *
00098 xaux_getclass_byutfname(
00099        const CARD16 *       utfname,
00100        size_t        len)
00101 {
00102        xaux_class_t  *p = xaux_classes;
00103 
00104        while (p->classname != NULL) {
00105               if (memcmp(p->utfname, utfname, len) == 0) {
00106                      return p;
00107               }
00108               p++;
00109        }
00110 
00111        return NULL;
00112 }
00113 
00114 static Bool
00115 xaux_so_get_extwin(xaux_class_t *xc,
00116                  Display    *display)
00117 {
00118     if (xc->atom_extwin == (Atom)None) {
00119        return False;
00120     }
00121 
00122     xc->extwin = XGetSelectionOwner(display, xc->atom_extwin);
00123     if (xc->extwin == None) {
00124        if (XAUX_MAXRETRY_EXTWIN <= 0) {
00125            return False;
00126        }
00127 
00128        /* workaround_slowdtlogin */
00129 /*shao        if (is_server == False) {
00130                      Window w;
00131 
00132                      if (atom_xbe == None) {
00133                             xc->atom_extwin = (Atom)None;
00134                             return False;
00135                      }
00136                      w = XGetSelectionOwner(display, atom_xbe);
00137                      if (w == None) {
00138                             xc->atom_extwin = (Atom)None;
00139                             return False;
00140                      }
00141               }
00142 */            /* workaround_slowdtlogin_end */
00143 
00144        //sleep(XAUX_RETRYINT_EXTWIN);
00145 
00146        xc->extwin = XGetSelectionOwner(display, xc->atom_extwin);
00147        if (xc->extwin != None) {
00148            return True;
00149        }
00150 
00151        return False;
00152     }
00153     return True;
00154 }
00155 
00156 #if 0
00157 static Bool
00158 xaux_so_send_aux_launch_to_external (xaux_class_t *xc,
00159                                  aux_t *aux)
00160 {
00161   Display *display;
00162   XClientMessageEvent event;
00163   Window external;
00164   char string_buf[20];
00165 
00166   display = aux->service->display(aux);
00167   external = XGetSelectionOwner(display, atom_xbe);
00168 
00169   if (atom_launch_this == None)
00170     atom_launch_this = XInternAtom(display, "xaux_launch_this", False);
00171 
00172   SX_PROP_ATOM_AUX_NAME(string_buf) = xc->atom_classname;
00173   SX_PROP_TYPE(string_buf) = 0;
00174   SX_PROP_INDEX(string_buf) = xc->index;
00175   SX_PROP_IMID(string_buf) = 0;
00176   SX_PROP_ICID(string_buf) = 0;
00177 
00178   XChangeProperty(display, external,
00179                 atom_launch_this, XA_STRING,
00180                 8, PropModeReplace, (unsigned char *)(&string_buf),
00181                 SX_SIZE_PROP_STARTDONE);
00182 
00183   event.type = ClientMessage;
00184   event.serial = 0;
00185   event.send_event = True;
00186   event.display = display;
00187   event.window = external;
00188   event.message_type = atom_launch_this;
00189   event.format = 32;
00190 
00191   /* not used */
00192   event.data.l[0] = 0;
00193   event.data.l[1] = 0;
00194   event.data.l[2] = 0;
00195   event.data.l[3] = 0;
00196   event.data.l[4] = 0;
00197   XSendEvent(display, external, True, 0, (XEvent *)(&event));
00198   return True;
00199 }
00200 #endif
00201 
00202 #if 0
00203 static Bool
00204 xaux_so_send_aux_draw_to_external (xaux_class_t *xc,
00205                                aux_t *aux)
00206 {
00207   Display *display;
00208   XClientMessageEvent event;
00209   Window external;
00210   char string_buf[20];
00211   Bool conversion_mode;
00212 
00213   display = aux->service->display(aux);
00214   external = XGetSelectionOwner(display, atom_xbe);
00215 
00216   if (atom_draw_this == None)
00217     atom_draw_this = XInternAtom(display, "xaux_draw_this", False);
00218 
00219   conversion_mode = aux->service->get_conversion_mode(aux);
00220 
00221   SX_PROP_ATOM_AUX_NAME(string_buf) = xc->atom_classname;
00222   SX_PROP_TYPE(string_buf) = 0;
00223   SX_PROP_INDEX(string_buf) = xc->index;
00224   SX_PROP_IMID(string_buf) = conversion_mode; /* hack */
00225   SX_PROP_ICID(string_buf) = 0;
00226 
00227   XChangeProperty(display, external,
00228                 atom_draw_this, XA_STRING,
00229                 8, PropModeReplace, (unsigned char *)(&string_buf),
00230                 SX_SIZE_PROP_STARTDONE);
00231 
00232   event.type = ClientMessage;
00233   event.serial = 0;
00234   event.send_event = True;
00235   event.display = display;
00236   event.window = external;
00237   event.message_type = atom_draw_this;
00238   event.format = 32;
00239 
00240   /* not used */
00241   event.data.l[0] = 0;
00242   event.data.l[1] = 0;
00243   event.data.l[2] = 0;
00244   event.data.l[3] = 0;
00245   event.data.l[4] = 0;
00246   XSendEvent(display, external, True, 0, (XEvent *)(&event));
00247   return True;
00248 }
00249 #endif
00250 
00251 static Bool
00252 xaux_so_launch_ext(
00253        xaux_class_t  *xc,
00254        aux_t         *aux
00255 )
00256 {
00257     pid_t pid;
00258     const char *ext = xc->extexec;
00259 
00260     ENTER;
00261 
00262     if (xc->atom_extwin == (Atom)0) {
00263        LEAVE;
00264        return False;
00265     }
00266 
00267     if (xaux_so_get_extwin(xc, aux->service->display(aux)) == True) {
00268        /*
00269         * succeeded in communicating
00270         * with already running external program
00271         * no need to launch external program
00272         */
00273        LEAVE;
00274        return True;
00275     }
00276     if (aux->service->server(aux) == False) {
00277        /*
00278         * let external program be launched if not loaded by server 
00279         * (htt_xbe) program yet,
00280         */
00281        //return xaux_so_send_aux_launch_to_external (xc, aux);
00282     }
00283     if (access(ext, X_OK) != 0) {
00284 #if defined(DEBUG_XAUX)
00285        fprintf(stderr, "executable \"%s\" not found\n", ext);
00286 #endif /* defined(DEBUG_XAUX) */
00287        /* no use to try to get extwin */
00288        xc->atom_extwin = (Atom)0;
00289        LEAVE;
00290        return False;
00291     }
00292                      
00293 #ifdef sun
00294     pid = fork1();
00295 #else
00296     pid = fork();
00297 #endif
00298 
00299     if (pid == (pid_t)(-1)) { /* fork failed */
00300        LEAVE;
00301        return False;
00302     } else if (0 == pid) { /* child */
00303 #if defined(DEBUG_XAUX)
00304        chdir("/tmp");
00305 #endif /* defined(DEBUG_XAUX) */
00306        execl(ext, xc->classname, NULL);
00307        _exit(1);
00308     }
00309 
00310     /* parent */
00311     LEAVE;
00312 
00313     return True;
00314 }
00315 
00316 static Bool
00317 xaux_so_send_message_detour_to_prop(
00318        aux_t *                     aux,
00319        xaux_class_t *              xc,
00320        int                  im_id,
00321        int                  ic_id,
00322        aux_data_type_t             type)
00323 {
00324        Display *            display;
00325        char                 string_buf[1024];
00326 
00327        display = aux->service->display(aux);
00328 
00329        SX_PROP_ATOM_AUX_NAME(string_buf) = xc->atom_classname;
00330        SX_PROP_TYPE(string_buf) = type;
00331        SX_PROP_INDEX(string_buf) = xc->index;
00332        SX_PROP_IMID(string_buf) = im_id;
00333        SX_PROP_ICID(string_buf) = ic_id;
00334 
00335        XChangeProperty(display, xc->sowin,
00336               xc->atom_sx[xc->atom_sx_idx], XA_STRING,
00337               8, PropModeReplace, (unsigned char *)(&string_buf),
00338               SX_SIZE_PROP_STARTDONE);
00339 
00340        /* needed in en_US.UTF-8 */
00341         XFlush(display);
00342 
00343        if (++xc->atom_sx_idx == XAUX_SX_NATOMS)
00344               xc->atom_sx_idx = 1;
00345        
00346        return True;
00347 }
00348 
00349 static xaux_class_t *
00350 xaux_getclass_byclientwinatom(Atom atom)
00351 {
00352   xaux_class_t *p = xaux_classes;
00353 
00354   while (p->classname != NULL) {
00355     if (p->atom_clientwin == atom)
00356       return (p);
00357     p++;
00358   }
00359 
00360   return (NULL);
00361 }
00362 
00363 static Bool
00364 xaux_client_process_client_message(Display *display, Window window,
00365                                XClientMessageEvent *event)
00366 {
00367   Atom actual_type_return;
00368   int actual_format_return;
00369   unsigned long nitem_return;
00370   unsigned long bytes_after_return;
00371   unsigned char *prop_return = NULL;
00372   int r;
00373   xaux_class_t *xc;
00374   Bool ret;
00375 
00376   if ((xc = xaux_getclass_byclientwinatom(event->message_type)) == NULL)
00377     return False;
00378 
00379   r = XGetWindowProperty(display, window,
00380                       xc->atom_clientwin, 0, INT_MAX, False,
00381                       AnyPropertyType, &actual_type_return,
00382                       &actual_format_return, &nitem_return,
00383                       &bytes_after_return, &prop_return);
00384   if (r != Success || prop_return == NULL)
00385     return False;
00386   else
00387     ret = xaux_set_property (xc, prop_return);
00388 
00389   XFree (prop_return);
00390   return ret;
00391 }
00392 
00393 static Bool
00394 xaux_set_property (xaux_class_t *xc, unsigned char *prop_return)
00395 {
00396     int              size;
00397     aux_data_t       aux_data_;
00398     aux_data_t *     aux_data = &(aux_data_);
00399     unsigned char *  p;
00400     int              i;
00401 
00402     /* header */
00403 
00404     aux_data->type = AUX_DATA_SETVALUE;
00405     aux_data->im = XS_PROP_IMID(prop_return);
00406     aux_data->ic = XS_PROP_ICID(prop_return);
00407     aux_data->aux_index = xc->index;
00408     aux_data->aux_name = (unsigned char *)xc->utfname;
00409     aux_data->aux_name_length = strlen(xc->classname)*sizeof(CARD16);
00410 
00411     /* int values */
00412 
00413     aux_data->integer_count = XS_PROP_INT_COUNT(prop_return);
00414 
00415     if (aux_data->integer_count > 0) {
00416        aux_data->integer_list = (int *)XS_PROP_INT_LIST(prop_return);
00417     } else {
00418        aux_data->integer_list = NULL;
00419     }
00420 
00421     /* string values */
00422     aux_data->string_count = XS_PROP_STR_COUNT(prop_return);
00423 
00424     if (aux_data->string_count > 0) {
00425        unsigned char * prop_str = XS_PROP_STR_LIST(prop_return);
00426 
00427        if ((aux_data->string_list =
00428             (aux_string_t *)malloc(sizeof (aux_string_t) *
00429                                 aux_data->string_count)) == NULL) {
00430            XFree(prop_return);
00431            return False;
00432        }
00433 
00434        for (i = 0; i < aux_data->string_count; i++) {
00435            int       j;
00436            int       pn;
00437            size_t    len;
00438 
00439            len = *((CARD16 *)(prop_str));
00440            prop_str += sizeof (CARD16);
00441            aux_data->string_list[i].ptr = prop_str;
00442            aux_data->string_list[i].length = len;
00443            prop_str += len;
00444            pn = padding[(sizeof(CARD16) + len) % 4];
00445            for (j = 0; j < pn; j++) {
00446               *prop_str++ = 0U;
00447            }
00448        }
00449     } else {
00450        aux_data->string_list = NULL;
00451     }
00452 
00453     aux_data->string_ptr = NULL;
00454 
00455     /* compose and send message to engine */
00456 
00457     /* workaround for "stored reference to aux_t is corrupred" problem */
00458     if ((p = /*ic->aux->service->*/compose(aux_data, &size)) == NULL) {
00459        free(aux_data->string_list);
00460        return False;
00461     }
00462 
00463 #if defined(DEBUG_XAUX)
00464     fprintf(stderr, "so_SetValue[%s] im:0x%x ic:0x%x in=%d sn=%d\n",
00465            xc->classname, aux_data->im, aux_data->ic,
00466            aux_data->integer_count, aux_data->string_count);
00467 #endif /* defined(DEBUG_XAUX) */
00468 
00469     /* workaround for "stored reference to aux_t is corrupred" problem */
00470     /*ic->aux->service->*/aux_setvalue(/*ic->aux*/&aux_tmp, p, size);
00471 
00472     free(p);
00473     free(aux_data->string_list);
00474     return True;
00475 }
00476 
00477 static Bool
00478 xaux_client_event_filter(
00479                       Display *    display,
00480                       Window              window,
00481                       XEvent *     event,
00482                       XPointer     pointer)
00483 {
00484   switch (event->type) {
00485   case ClientMessage:
00486     return (xaux_client_process_client_message(display, window,
00487                                           (XClientMessageEvent *)event));
00488   default:
00489     return False;
00490   }
00491 }
00492 
00493 static Bool
00494 xaux_so_send_message(
00495        aux_t *              aux,
00496        xaux_class_t *       xc,
00497        int           im_id,
00498        int           ic_id,
00499        aux_data_type_t      type,
00500        Atom          atom)
00501 {
00502        Display *            display;
00503        XClientMessageEvent  event;
00504 
00505 
00506        display = aux->service->display(aux);
00507 
00508         if (xaux_so_get_extwin(xc, display) == False) {
00509             return False;
00510         }
00511        if (xc->extwin == None) {
00512               /* cannot get extwin */
00513               if (xc->atom_extwin == (Atom)None) {
00514                      return False;
00515               } else {
00516                      if (type == AUX_DATA_DRAW) {
00517                             return True;
00518                      } else {
00519                                 if (xc->sowin != None)
00520                                 return xaux_so_send_message_detour_to_prop(
00521                                    aux, xc, im_id, ic_id, type);
00522                      }
00523               }
00524        }
00525               
00526        event.type = ClientMessage;
00527        event.serial = 0;
00528        event.send_event = True;
00529        event.display = display;
00530        event.window = xc->extwin;
00531        event.message_type = xc->atom_sx[0];
00532        event.format = 32;
00533 
00534        event.data.l[0] = xc->atom_classname;
00535        event.data.l[1] = ((CARD32)im_id << 16) | ((CARD32)ic_id & 0xffff);
00536        event.data.l[2] = xc->index;
00537        event.data.l[3] = type; /* CREATE, DONE, ... */
00538        if (type == AUX_DATA_DRAW) {
00539               event.data.l[4] = atom;
00540        } else {
00541               event.data.l[4] = 0; /* unused */
00542        }
00543 
00544        XSendEvent(display, xc->extwin, True, 0, (XEvent *)(&event));
00545        if (xc->clientwin == None)
00546          {
00547            xc->clientwin = XCreateSimpleWindow(display, RootWindow(display, 0),
00548                                        0, 0, 1, 1, 0, 0, 0);
00549            if (xc->clientwin)
00550              aux->service->register_X_filter(display, xc->clientwin,
00551                                          ClientMessage, ClientMessage,
00552                                          xaux_client_event_filter, NULL);
00553          }
00554        if (xc->clientwin && type == AUX_DATA_DRAW)
00555          XSetSelectionOwner(display, xc->atom_clientwin,
00556                           xc->clientwin, CurrentTime);
00557 
00558        /* needed in en_US.UTF-8 */
00559         XFlush(display);
00560 
00561        return True;
00562 }
00563 
00564 static Bool
00565 xaux_so_send_property(
00566        aux_t *                     aux,
00567        xaux_class_t *              xc,
00568        const unsigned char *       p,
00569        int                  len)
00570 {
00571        Display *     display;
00572        Window        win;
00573 
00574        display = aux->service->display(aux);
00575 
00576        if (xaux_so_get_extwin(xc, display) == False) {
00577               return False;
00578        }
00579        if ((xc->extwin == None) && (xc->atom_extwin == (Atom)None)) {
00580               return False;
00581        }
00582 
00583        win = (xc->extwin != (Window)None) ? xc->extwin : xc->sowin;
00584         if (win == None) return False;
00585 
00586        XChangeProperty(display, win,
00587               xc->atom_sx[xc->atom_sx_idx], XA_STRING,
00588               8, PropModeReplace, (unsigned char *)p, len);
00589 
00590        if (xaux_so_send_message(aux, xc,
00591               aux->service->im_id(aux), aux->service->ic_id(aux),
00592               AUX_DATA_DRAW, xc->atom_sx[xc->atom_sx_idx]) == False) {
00593                      return False;
00594        }
00595 
00596        /* XFlush() has been called in xaux_so_send_message() */
00597        
00598        if (++xc->atom_sx_idx == XAUX_SX_NATOMS)
00599               xc->atom_sx_idx = 1;
00600        
00601        return True;
00602 }
00603 
00604 static Bool
00605 xaux_so_process_property_update(
00606        Display       *             display,
00607        Window               window,
00608        Atom                 atom,
00609        xaux_class_t *              xc)
00610 {
00611        Atom          actual_type_return;
00612        int           actual_format_return;
00613        unsigned long nitem_return;
00614        unsigned long bytes_after_return;
00615        unsigned char *      prop_return;
00616        int           r;
00617        char *atom_name;
00618 /*
00619        aux_icid_t *  ic;
00620 */
00621        r = XGetWindowProperty(display, window,
00622                             atom, 0, INT_MAX, False,
00623                             AnyPropertyType, &actual_type_return,
00624                             &actual_format_return, &nitem_return,
00625                             &bytes_after_return, &prop_return);
00626 
00627        if (r != Success) {
00628               return False;
00629        }
00630 
00631 /*
00632        if ((ic = aux_icid_get(XS_PROP_ICID(prop_return), False)) == NULL) {
00633               XFree(prop_return);
00634               return False;
00635        }
00636 */
00637 
00638        atom_name = XGetAtomName (display, atom);
00639        if ((strstr (atom_name, "palette") != NULL ) &&
00640            xc->atom_clientwin != None)
00641        {
00642            Window owner = XGetSelectionOwner(display, xc->atom_clientwin);
00643            if (owner != None)
00644              {
00645               XClientMessageEvent event;
00646 
00647               XChangeProperty(display, owner,
00648                             xc->atom_clientwin, XA_STRING,
00649                             8, PropModeReplace,
00650                             (unsigned char *)prop_return, nitem_return);
00651 
00652               event.type = ClientMessage;
00653               event.serial = 0;
00654               event.send_event = True;
00655               event.display = display;
00656               event.window = owner;
00657               event.message_type = xc->atom_clientwin;
00658               event.format = 32;
00659 
00660               event.data.l[0] = atom;
00661               event.data.l[1] = nitem_return;
00662 
00663               XSendEvent(display, owner, True, 0, (XEvent *)(&event));
00664              }
00665        }
00666        else
00667            xaux_set_property (xc, prop_return);
00668 
00669        XFree(prop_return);
00670 
00671        return True;
00672 }
00673 
00674 static Bool
00675 xaux_so_process_client_message(
00676        Display       *             display,
00677        Window               window,
00678        XClientMessageEvent *       event)
00679 {
00680     aux_data_t aux_data_;
00681     aux_data_t *aux_data = &(aux_data_);
00682     aux_data_type_t type;
00683     xaux_class_t *xc;
00684 
00685     ENTER;
00686 
00687     if ((xc = xaux_getclass_byatomxs(event->message_type)) == NULL) {
00688        LEAVE;
00689        return False;
00690     }
00691 
00692     aux_data->im = ((CARD32)(event->data.l[1])) >> 16;
00693     aux_data->ic = ((CARD32)(event->data.l[1])) & 0xffff;
00694     aux_data->aux_index = (CARD32)(event->data.l[2]);
00695 
00696     type = (CARD32)(event->data.l[3]);
00697 
00698     switch (type) {
00699        case AUX_DATA_SETVALUE:
00700            return xaux_so_process_property_update(display, window,
00701                                              (Atom)(event->data.l[4]), xc);
00702        default:
00703            return False;
00704     }
00705 
00706     return False;
00707 }
00708 
00709 static Bool
00710 xaux_so_event_filter(Display *display,
00711                    Window window,
00712                    XEvent *event,
00713                    XPointer pointer)
00714 {
00715     ENTER;
00716 
00717     switch (event->type) {
00718        case ClientMessage:
00719            LEAVE;
00720            return (xaux_so_process_client_message(display, window,
00721                                              (XClientMessageEvent *)event));
00722     }
00723 
00724     LEAVE;
00725 
00726     return False;
00727 }
00728 
00729 static void
00730 aux_icid_init(void)
00731 {
00732     int i;
00733 
00734     for (i = 0; i < HASH_SIZE; i++) {
00735        aux_icid[i].icid = (-1);
00736     }
00737 }
00738 
00739 #if 0
00740 static void
00741 aux_icid_finish(void)
00742 {
00743     int i;
00744     aux_icid_t *p0;
00745     aux_icid_t *p1;
00746 
00747     ENTER;
00748 
00749     for (i = 0; i < HASH_SIZE; i++) {
00750        p0 = aux_icid[i].next;
00751 
00752        for (; p0 != NULL; p0 = p1) {
00753            p1 = p0->next;
00754            free(p0);
00755        }
00756     }
00757     LEAVE;
00758 }
00759 #endif
00760 
00761 static aux_icid_t *
00762 aux_icid_get(int icID,
00763             Bool createit)
00764 {
00765     aux_icid_t *p;
00766 
00767     ENTER;
00768 
00769     p = &(aux_icid[icID % HASH_SIZE]);
00770 
00771     if (p->icid == -1) {
00772        if (!createit) {
00773            LEAVE;
00774            return NULL;
00775        }
00776        p->icid = icID;
00777        return (p);
00778     }
00779 
00780     for (; ; p = p->next) {
00781        if (icID == p->icid) {
00782            LEAVE;
00783            return p;
00784        }
00785        if (p->next == NULL) {
00786            if (!createit) {
00787               LEAVE;
00788               return NULL;
00789            }
00790            p->next = malloc(sizeof (aux_icid_t));
00791            if (p->next == NULL) {
00792               LEAVE;
00793               return NULL;
00794            }
00795            memset(p->next, 0, (sizeof (aux_icid_t)));
00796            p->next->prev = p;
00797            p->next->next = NULL;
00798            p->next->icid = icID;
00799 
00800            LEAVE;
00801            return (p->next);
00802        }
00803     }
00804     LEAVE;
00805 
00806     return NULL;
00807 }
00808 
00809 #if 0
00810 static void
00811 aux_icid_delete(int icID)
00812 {
00813     aux_icid_t *p;
00814 
00815     ENTER;
00816 
00817     p = aux_icid_get(icID, False);
00818 
00819     if (NULL == p) {
00820        LEAVE;
00821        return;
00822     }
00823 
00824     p->icid = -1;
00825 
00826     if (p->next != NULL) {
00827        p->next->prev = p->prev;
00828     }
00829     if (p->prev != NULL) {
00830        p->prev->next = p->next;
00831        free(p);
00832     }
00833     LEAVE;
00834 }
00835 #endif
00836 
00837 static Bool
00838 xaux_xbe_process_client_message(Display *display, Window window,
00839                             XClientMessageEvent *event,
00840                             XPointer aux)
00841 {
00842     Atom actual_type_return;
00843     int actual_format_return;
00844     unsigned long nitem_return;
00845     unsigned long bytes_after_return;
00846     unsigned char *prop_return = NULL;
00847     int r;
00848 
00849     ENTER;
00850 
00851     if (atom_launch_this == None)
00852        atom_launch_this = XInternAtom(display, "xaux_launch_this", False);
00853     if (atom_draw_this == None)
00854        atom_draw_this = XInternAtom(display, "xaux_draw_this", False);
00855 
00856     r = XGetWindowProperty(display, window,
00857                         event->message_type, 0, INT_MAX, False,
00858                         AnyPropertyType, &actual_type_return,
00859                         &actual_format_return, &nitem_return,
00860                         &bytes_after_return, &prop_return);
00861     if (r != Success || prop_return == NULL) {
00862        LEAVE;
00863        return False;
00864     }
00865 
00866     if (atom_launch_this == event->message_type) {
00867        const char *ext;
00868        char *classname;
00869        pid_t pid;
00870        CARD16 class_index;
00871 
00872        classname = XGetAtomName (display, (Atom)(*((CARD32*)(prop_return + 0))));
00873        class_index = (*((CARD16 *)(prop_return + 6)));
00874        ext = xaux_classes[class_index - 1].extexec;
00875 
00876        if (access(ext, X_OK) != 0) {
00877 #if defined(DEBUG_XAUX)
00878            fprintf(stderr, "executable \"%s\" not found\n", ext);
00879 #endif /* defined(DEBUG_XAUX) */
00880            /* no use to try to get extwin */
00881            LEAVE;
00882            return False;
00883        }
00884 #ifdef sun
00885        pid = fork1();
00886 #else
00887        pid = fork();
00888 #endif
00889        if (pid == (pid_t)(-1)) { /* fork failed */
00890            LEAVE;
00891            return False;
00892        } else if (0 == pid) { /* child */
00893 #if defined(DEBUG_XAUX)
00894            chdir("/tmp");
00895 #endif /* defined(DEBUG_XAUX) */
00896            execl(ext, classname, NULL);
00897            LEAVE;
00898            _exit(1);
00899        }
00900     } else if (atom_draw_this == event->message_type) {
00901        Bool conversion_mode;
00902 
00903        conversion_mode = (*((CARD16 *)(prop_return + 8))); /* hack */
00904 
00905        ((aux_t*)aux)->service->set_conversion_mode((aux_t *)aux, conversion_mode);
00906     }
00907 
00908     if (prop_return)
00909        XFree(prop_return);
00910     /* parent */
00911 
00912     LEAVE;
00913 
00914     return True;
00915 }
00916 
00917 static Bool
00918 xaux_xbe_client_event_filter(Display *display,
00919                           Window window,
00920                           XEvent *event,
00921                           XPointer aux)
00922 {
00923     ENTER;
00924 
00925     switch (event->type) {
00926        case ClientMessage:
00927            return xaux_xbe_process_client_message(display, window,
00928                                              (XClientMessageEvent *)event,
00929                                              aux);
00930            break;
00931        default:
00932            break;
00933     }
00934 
00935     LEAVE;
00936 
00937     return False;
00938 }
00939 
00940 static Bool
00941 xaux_so_init_classes(aux_t * aux)
00942 {
00943     Display *display;
00944     char buf[XAUX_MAXCLASSNAMELEN + XAUX_MAXSUFFIXLEN + 1];
00945     int i;
00946     xaux_class_t *p = xaux_classes;
00947 
00948     ENTER;
00949 
00950     display = aux->service->display(aux);
00951 
00952     /* workaround_slowdtlogin */
00953     atom_xbe = XInternAtom(display, "xaux_xbe", False);
00954 
00955     is_server = aux->service->server(aux);
00956        
00957     if (is_server == True && atom_xbe != None) {
00958        Window htt_xbe_win;
00959        htt_xbe_win = XCreateSimpleWindow(display, RootWindow(display, 0),
00960                                      0, 0, 1, 1, 0, 0, 0);
00961        if (htt_xbe_win) {
00962            XSetSelectionOwner(display, atom_xbe,
00963                             htt_xbe_win, CurrentTime);
00964            aux->service->register_X_filter(display, htt_xbe_win,
00965                                        ClientMessage, ClientMessage,
00966                                        xaux_xbe_client_event_filter,
00967                                        (XPointer)aux);
00968        } else {
00969            XSetSelectionOwner(display, atom_xbe,
00970                             DefaultRootWindow(display), CurrentTime);
00971        }
00972 
00973     }
00974     /* workaround_slowdtlogin_end */
00975 
00976     while (p->classname != NULL) {
00977        p->atom_classname = XInternAtom(display, p->classname, False);
00978 
00979        sprintf(buf, "%s%s", p->classname, XAUX_SOWIN_SUFFIX);
00980        p->atom_sowin = XInternAtom(display, buf, False);
00981 
00982        sprintf(buf, "%s%s", p->classname, XAUX_EXTWIN_SUFFIX);
00983        p->atom_extwin = XInternAtom(display, buf, False);
00984 
00985        sprintf(buf, "%s%s", p->classname, XAUX_CLIENTWIN_SUFFIX);
00986        p->atom_clientwin = XInternAtom(display, buf, False);
00987 
00988        for (i = 0; i < XAUX_SX_NATOMS; i++) {
00989            sprintf(buf, "%s%s_%d",
00990                   p->classname, XAUX_SX_SUFFIX, i);
00991            p->atom_sx[i] = XInternAtom(display, buf, False);
00992        }
00993        p->atom_sx_idx = 1;
00994 
00995        for (i = 0; i < XAUX_XS_NATOMS; i++) {
00996            sprintf(buf, "%s%s_%d",
00997                   p->classname, XAUX_XS_SUFFIX, i);
00998            p->atom_xs[i] = XInternAtom(display, buf, False);
00999        }
01000        p->atom_xs_idx = 1;
01001 
01002        /* create it anyway, even there is multiple say from htt_xbe, we still use
01003           this window as the contact point
01004        if (XGetSelectionOwner(display, p->atom_sowin) != None) {
01005 #if defined(DEBUG_XAUX)
01006            fprintf(stderr, "%s: %s already exists. [%s](1)\n",
01007                   ME_SO, ME_SO, p->classname);
01008 #endif
01009            goto done_sowin;
01010        }
01011        */
01012        p->sowin = XCreateSimpleWindow(display, RootWindow(display, 0),
01013                                    0, 0, 1, 1, 0, 0, 0);
01014        if (p->sowin == None) {
01015            fprintf(stderr,
01016                   "%s: creating window for \"%s\" failed.\n",
01017                   ME_SO, p->classname);
01018            goto done_sowin;
01019        }
01020        XSelectInput(display, p->sowin, PropertyChangeMask);
01021 
01022        aux->service->register_X_filter(display, p->sowin,
01023                                    ClientMessage, ClientMessage,
01024                                    xaux_so_event_filter, NULL);
01025 
01026        XSetSelectionOwner(display,
01027                         p->atom_sowin, p->sowin, CurrentTime);
01028 
01029        if (XGetSelectionOwner(display, p->atom_sowin) != p->sowin) {
01030            fprintf(stderr, "%s: %s already exists.[%s](2)\n",
01031                   ME_SO, ME_SO, p->classname);
01032            XDestroyWindow(display, p->sowin);
01033            p->sowin = (Window)0;
01034            goto done_sowin;
01035        }
01036 
01037        //shao xaux_so_launch_ext(p, aux);
01038 done_sowin:
01039        p->extwin = (Window)0;
01040 
01041        p++;
01042     }
01043 
01044     LEAVE;
01045 
01046     return True;
01047 }
01048 
01049 static Bool
01050 xaux_so_Create(aux_t * aux)
01051 {
01052     aux_icid_t *aux_icid;
01053 
01054     ENTER;
01055 
01056     if (0 == aux_initialized) {
01057        aux_icid_init();
01058     }
01059 
01060     if (NULL == (aux_icid = aux_icid_get(aux->service->ic_id(aux), True))) {
01061        return False;
01062     }
01063 
01064     aux_icid->aux = aux;
01065 
01066     /* workaround for "stored reference to aux_t is corrupred" problem */
01067     aux_tmp.ic = aux->ic;
01068     aux_setvalue = aux_icid->aux->service->aux_setvalue;
01069     mb_utf16 = aux_icid->aux->service->mb_utf16;
01070     compose = aux_icid->aux->service->compose;
01071 
01072     if (aux_initialized == 0) {
01073        xaux_so_init_classes(aux);
01074        aux_initialized = 1;
01075     }
01076 
01077     LEAVE;
01078 
01079     return True;
01080 }
01081 
01082 static Bool
01083 xaux_so_Start(aux_t * aux, const unsigned char * p, int size)
01084 {
01085     aux_data_t   *aux_data;
01086     xaux_class_t *xc;
01087     Bool          rv;
01088 
01089     ENTER;
01090 
01091     aux_data = aux->service->decompose(AUX_DATA_START, p);
01092 
01093     if ((xc = xaux_getclass_byutfname((const CARD16 *)aux_data->aux_name,
01094                                   aux_data->aux_name_length)) == NULL) {
01095        aux->service->decompose_free(aux_data);
01096        LEAVE;
01097        return False;
01098     }
01099     if (xc->extwin == (Window)None &&
01100        xaux_so_launch_ext(xc, aux) == False) {
01101        fprintf(stderr,
01102               "cannot communicate with external program [%s]\n",
01103               xc->classname);
01104        aux->service->decompose_free(aux_data);
01105        LEAVE;
01106        return False;
01107     }
01108 #if defined(DEBUG_XAUX)
01109     fprintf(stderr, "so_Start[%s] im:0x%x ic:0x%x extwin:%x\n",
01110            xc->classname, aux_data->im, aux_data->ic, xc->extwin);
01111 #endif /* defined(DEBUG_XAUX) */
01112 
01113     rv = xaux_so_send_message(aux, xc, aux_data->im, aux_data->ic,
01114                            AUX_DATA_START, (Atom)0);
01115 
01116     aux->service->decompose_free(aux_data);
01117 
01118     LEAVE;
01119 
01120     return (rv);
01121 }
01122 
01123 static Bool
01124 xaux_so_Draw(aux_t * aux, const unsigned char * p, int size)
01125 {
01126     aux_data_t   *aux_data;
01127     XPoint      point;
01128     char         *string_buf;
01129     xaux_class_t *xc;
01130     size_t      i;
01131     int               *ip;
01132     char       *sp;
01133     Bool        rv = True;
01134     size_t      total;
01135 
01136     aux_data = aux->service->decompose(AUX_DATA_DRAW, p);
01137 
01138     if ((xc = xaux_getclass_byutfname((const CARD16 *)aux_data->aux_name,
01139                                   aux_data->aux_name_length)) == NULL) {
01140        aux->service->decompose_free(aux_data);
01141        return False;
01142     }
01143 
01144 
01145 #if 1
01146     /* workaround for "stored reference to aux_t is corrupred" problem */
01147     aux_tmp.ic = aux->ic;
01148 #endif
01149 
01150     /* estimate enough size for string_buf */
01151 
01152     /* size for header */
01153     total = SX_SIZE_PROP_HEADER_DRAW;
01154 
01155     /* add size for integer_values */
01156     total += (sizeof (CARD32) * aux_data->integer_count);
01157 
01158     /* add size for string_values */
01159     if (aux_data->string_count > 0) {
01160        for (i = 0; i < aux_data->string_count; i++) {
01161            size_t    len;
01162 
01163            /* number of bytes */
01164            len = aux_data->string_list[i].length;
01165 
01166            /* consider padding */
01167            total += ((sizeof (CARD16) + len + 3) / 4) * 4;
01168        }
01169     }
01170     if ((string_buf = (char *)malloc(total)) == NULL) {
01171        aux->service->decompose_free(aux_data);
01172 
01173        return False;
01174     }
01175 
01176     SX_PROP_ATOM_AUX_NAME(string_buf) = xc->atom_classname;
01177     SX_PROP_TYPE(string_buf) = AUX_DATA_DRAW;
01178     SX_PROP_INDEX(string_buf) = xc->index;
01179     SX_PROP_IMID(string_buf) = aux_data->im;
01180     SX_PROP_ICID(string_buf) = aux_data->ic;
01181     SX_PROP_SOWIN(string_buf) = xc->sowin;
01182 
01183     SX_PROP_CLIENTWIN(string_buf) = aux->service->client_window(aux);
01184 
01185     aux->service->point(aux, &point);
01186     SX_PROP_POSX(string_buf) = point.x;
01187     SX_PROP_POSY(string_buf) = point.y;
01188 
01189     SX_PROP_FOCUSWIN(string_buf) = aux->service->window(aux);
01190 
01191     SX_PROP_INT_COUNT(string_buf) = aux_data->integer_count;
01192     SX_PROP_STR_COUNT(string_buf) = aux_data->string_count;
01193 
01194     ip = (int *)SX_PROP_INT_LIST(string_buf);
01195 
01196     if (aux_data->integer_count > 0) {
01197        for (i = 0; i < aux_data->integer_count; i++) {
01198            *ip++ = aux_data->integer_list[i];
01199        }
01200     }
01201 
01202     sp = (char *)SX_PROP_STR_LIST(string_buf);
01203 
01204     if (aux_data->string_count > 0) {
01205        char   *ob = sp;
01206 
01207        for (i = 0; i < aux_data->string_count; i++) {
01208            size_t len, j;
01209            int pn;
01210            unsigned char *p;
01211 
01212            len = aux_data->string_list[i].length;
01213            p = aux_data->string_list[i].ptr;
01214 
01215            *(CARD16 *)ob = len;
01216            ob += sizeof (CARD16);
01217 
01218            for (j = 0; j < len; j++) {
01219               *ob++ = *p++;
01220            }
01221 
01222            pn = padding[(sizeof (CARD16) + len) % 4];
01223 
01224            /* padding */
01225            for (j = 0; j < pn; j++) {
01226               *ob++ = 0U;
01227            }
01228            sp = ob;
01229        }
01230     }
01231 
01232 #if defined(DEBUG_XAUX)
01233     fprintf(stderr, "so_Draw[%s] im:0x%x ic:0x%x in=%d sn=%d\n",
01234            xc->classname, aux_data->im, aux_data->ic,
01235            aux_data->integer_count, aux_data->string_count);
01236     fprintf(stderr, "total = %d\n", total);
01237 #endif /* defined(DEBUG_XAUX) */
01238 
01239     XSetSelectionOwner(aux->service->display(aux), xc->atom_sowin, xc->sowin, CurrentTime);
01240 
01241     if (aux_data->integer_count != 0 || aux_data->string_count != 0) {
01242        rv = xaux_so_send_property(aux, xc,
01243                                (unsigned char *)string_buf, (sp - &(string_buf[0])));
01244     }
01245 
01246     aux->service->decompose_free(aux_data);
01247     free(string_buf);
01248 
01249     /* for XIM clients
01250        if (!aux->service->server (aux)) */
01251     //shao xaux_so_send_aux_draw_to_external (xc, aux);
01252 
01253     return (rv);
01254 }
01255 
01256 static Bool
01257 xaux_so_Done(aux_t * aux, const unsigned char * p, int size)
01258 {
01259     aux_data_t   *aux_data;
01260     xaux_class_t *xc;
01261     Bool rv;
01262 
01263     ENTER;
01264 
01265     aux_data = aux->service->decompose(AUX_DATA_DONE, p);
01266 
01267     if ((xc = xaux_getclass_byutfname(
01268             (const CARD16 *)aux_data->aux_name,
01269             aux_data->aux_name_length)) == NULL) {
01270        aux->service->decompose_free(aux_data);
01271        return False;
01272     }
01273 
01274 #if defined(DEBUG_XAUX)
01275     fprintf(stderr, "so_Done[%s] im:0x%x ic:0x%x\n",
01276            xc->classname, aux_data->im, aux_data->ic);
01277 #endif /* defined(DEBUG_XAUX) */
01278 
01279     rv = xaux_so_send_message(aux, xc, aux_data->im, aux_data->ic,
01280                            AUX_DATA_DONE, (Atom)0);
01281 
01282     aux->service->decompose_free(aux_data);
01283 
01284 #if 0
01285     if (xc->clientwin) {
01286        aux->service->unregister_X_filter(display, xc->clientwin,
01287                                      xaux_client_event_filter, NULL);
01288        XSetSelectionOwner(display, xc->atom_clientwin, None, CurrentTime);
01289        XDestroyWindow(display, xc->clientwin);
01290        xc->clientwin = (Window)0;
01291     }
01292     if (xc->sowin) {
01293        XDestroyWindow(display, xc->sowin);
01294        XSetSelectionOwner(display, xc->atom_sowin, None, CurrentTime);
01295        xc->sowin = (Window)0;
01296     }
01297     if (xc->extwin) {
01298        XSync(display, True);
01299        XDestroyWindow(display, xc->extwin);
01300        XSetSelectionOwner(display, xc->atom_extwin, None, CurrentTime);
01301        xc->extwin = (Window)0;
01302     }
01303 #endif
01304 
01305     LEAVE;
01306 
01307     return rv;
01308 }
01309 
01310 static Bool
01311 xaux_so_Switched(aux_t * aux, int im_id, int on_off)
01312 {
01313     ENTER;
01314 
01315     LEAVE;
01316 
01317     return True;
01318 }
01319 
01320 static Bool
01321 xaux_so_Destroy(aux_t * aux)
01322 {
01323     ENTER;
01324 
01325     LEAVE;
01326 
01327     return True;
01328 }