Back to index

im-sdk  12.3.91
xaux_so_common.c
Go to the documentation of this file.
00001 /*
00002 Copyright 1990-2003 Sun Microsystems, Inc. All Rights Reserved.
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a
00005 copy of this software and associated documentation files (the
00006 "Software"), to deal in the Software without restriction, including
00007 without limitation the rights to use, copy, modify, merge, publish,
00008 distribute, sublicense, and/or sell copies of the Software, and to
00009 permit persons to whom the Software is furnished to do so, subject to
00010 the following conditions: The above copyright notice and this
00011 permission notice shall be included in all copies or substantial
00012 portions of the Software.
00013 
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00016 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00017 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00018 IN NO EVENT SHALL THE OPEN GROUP OR SUN MICROSYSTEMS, INC. BE LIABLE
00019 FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
00020 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
00021 THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE EVEN IF
00022 ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
00023 
00024 
00025 Except as contained in this notice, the names of The Open Group and/or
00026 Sun Microsystems, Inc. shall not be used in advertising or otherwise to
00027 promote the sale, use or other dealings in this Software without prior
00028 written authorization from The Open Group and/or Sun Microsystems,
00029 Inc., as applicable.
00030 
00031 
00032 X Window System is a trademark of The Open Group
00033 
00034 OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF
00035 logo, LBX, X Window System, and Xinerama are trademarks of the Open
00036 Group. All other trademarks and registered trademarks mentioned herein
00037 are the property of their respective owners. No right, title or
00038 interest in or to any trademark, service mark, logo or trade name of
00039 Sun Microsystems, Inc. or its licensors is granted.
00040 
00041 */
00042 
00043 #pragma ident "$Id$"
00044 
00045 #include <stddef.h>
00046 #include <stdlib.h>
00047 #include <stdio.h>
00048 #include <sys/types.h>
00049 #include <unistd.h>
00050 #include <limits.h>
00051 #include <libgen.h>
00052 #include <sys/param.h>
00053 #include <dlfcn.h>
00054 #include <string.h>
00055 #include <errno.h>
00056 #include <sys/stat.h>
00057 #include <fcntl.h>
00058 #include <poll.h>
00059 #if !defined(linux)
00060 #include <libelf.h>
00061 #include <gelf.h>
00062 #endif /* !linux */
00063 
00064 #if defined(IM_LOCALE)
00065 #include <locale.h>
00066 #endif /* defined(IM_LOCALE) */
00067 
00068 #include <X11/Xlib.h>
00069 #include <X11/Xatom.h>
00070 
00071 #include "iiimpAux.h"
00072 
00073 #include "xaux_common.h"
00074 #include "xaux_so_common.h"
00075 
00076 #if defined(linux) && !defined(MAXNAMELEN)
00077 #define MAXNAMELEN (1024)
00078 #endif /* linux && !MAXNAMELEN */
00079 
00080 extern xaux_so_class_t xaux_classes[];
00081 
00082 static void          aux_icid_init(void);
00083 static void          aux_icid_finish(void);
00084 static aux_icid_t *  aux_icid_get(int, Bool);
00085 static void          aux_icid_delete(int);
00086 
00087 static xaux_so_t     so_;
00088 static xaux_so_t *   so = NULL;
00089 
00090 static int           xaux_so_extexec_dirno = -1;
00091 
00092 static unsigned int  sx_seqno = 0;
00093 
00094 static unsigned int  maxpropsz = XAUX_MAXPROPSZ;
00095 
00096 #define HASH_SIZE 137
00097 static aux_icid_t    aux_icid[HASH_SIZE];
00098 
00099 #if defined(WORKAROUND_XXXXXXX)
00100 typedef struct window_list {
00101        Display *            display;
00102        Window               window;
00103        struct window_list * next;
00104 } window_list_t;
00105 static window_list_t *      window_list;
00106 typedef struct event_filter_param {
00107        Display *     display;
00108        Window        window;
00109        Bool          (* filter)(Display *, Window, XEvent *, XPointer);
00110        XPointer      call_data;
00111        struct event_filter_param * next;
00112 } event_filter_param_t;
00113 static event_filter_param_t *      event_filter_param;
00114 static void window_list_remember(Display * display, Window window);
00115 static void window_list_forget(Display * display, Window window);
00116 static void window_list_destroy_all(void);
00117 static void event_filter_remember(
00118        Display *     display,
00119        Window        window,
00120        Bool          (* filter)(Display *, Window, XEvent *, XPointer),
00121        XPointer      call_data);
00122 static void event_filter_forget(
00123        Display *     display,
00124        Window        window,
00125        Bool          (* filter)(Display *, Window, XEvent *, XPointer),
00126        XPointer      call_data);
00127 static void event_filter_unregister_all(void);
00128 #endif /* WORKAROUND_XXXXXXX */
00129 
00130 /* workaround for "stored reference to aux_t is corrupred" problem */
00131 static void (*aux_setvalue)(aux_t *, const unsigned char *, int);
00132 static size_t (* mb_utf16)(const char **, size_t *, char **, size_t *);
00133 static unsigned char * (* compose)(const aux_data_t *, int *);
00134 static void (* register_X_filter)(Display *, Window, int, int,
00135                Bool (* filter)(Display *, Window, XEvent *, XPointer),
00136                XPointer);
00137 static void (* unregister_X_filter)(Display *, Window,
00138                Bool (* filter)(Display *, Window, XEvent *, XPointer),
00139                XPointer);
00140 static aux_t aux_tmp;
00141 
00142 static Bool xaux_so_Create(aux_t *);
00143 static Bool xaux_so_Start(aux_t *, const unsigned char *, int size);
00144 static Bool xaux_so_Draw(aux_t *, const unsigned char *, int size);
00145 static Bool xaux_so_Done(aux_t *, const unsigned char *, int size);
00146 static Bool xaux_so_Switched(aux_t *, int im_id, int on_off);
00147 static Bool xaux_so_Destroy(aux_t *);
00148 
00149 #if defined(NOTIFY_STATE)
00150 static Bool xaux_so_notify_state(xaux_so_class_t *);
00151 #endif /* defined(NOTIFY_STATE) */
00152 
00153 aux_method_t xaux_so_methods = {
00154        xaux_so_Create,
00155        xaux_so_Start,
00156        xaux_so_Draw,
00157        xaux_so_Done,
00158        xaux_so_Switched,
00159        xaux_so_Destroy
00160 };
00161 
00162 #if defined(WORKAROUND_XXXXXXX)
00163 static void
00164 window_list_remember(Display * display, Window window) {
00165        window_list_t *      wl;
00166        
00167        for (wl = window_list; NULL != wl; wl = wl->next) {
00168               if ((display == wl->display) && (window == wl->window)) return;
00169        }
00170 
00171        wl = (window_list_t *)malloc(sizeof (window_list_t));
00172        if (NULL == wl) return;
00173 
00174        wl->display = display;
00175        wl->window = window;
00176        wl->next = window_list;
00177        window_list = wl;
00178 
00179        return;
00180 }
00181 
00182 static void
00183 window_list_forget(Display * display, Window window) {
00184        window_list_t *             wl;
00185        window_list_t **     wl_prev;
00186        
00187        wl_prev = &window_list;
00188        wl = window_list;
00189        while (NULL != wl) {
00190               if ((display == wl->display) && (window == wl->window)) {
00191                      *wl_prev = wl->next;
00192                      free(wl);
00193               } else {
00194                      wl_prev = &(wl->next);
00195               }
00196               wl = *wl_prev;
00197        }
00198 
00199        return;
00200 }
00201 
00202 static void
00203 window_list_destroy_all(void)
00204 {
00205        window_list_t *      wl;
00206        window_list_t *      wl_next;
00207 
00208        for (wl = window_list; NULL != wl; wl = wl_next) {
00209               wl_next = wl->next;
00210               XDestroyWindow(wl->display, wl->window);
00211               free(wl);
00212        }
00213        window_list = NULL;
00214 
00215        return;
00216 }
00217 
00218 static void
00219 event_filter_remember(
00220        Display *     display,
00221        Window        window,
00222        Bool          (* filter)(Display *, Window, XEvent *, XPointer),
00223        XPointer      call_data) {
00224        event_filter_param_t *      efp;
00225        
00226        for (efp = event_filter_param; NULL != efp; efp = efp->next) {
00227               if ((display == efp->display) &&
00228                   (window == efp->window) &&
00229                   (filter == efp->filter) &&
00230                   (call_data == efp->call_data)) {
00231                      return;
00232               }
00233        }
00234 
00235        efp = (event_filter_param_t *)malloc(sizeof (event_filter_param_t));
00236        if (NULL == efp) return;
00237 
00238        efp->display = display;
00239        efp->window = window;
00240        efp->filter = filter;
00241        efp->call_data = call_data;
00242        efp->next = event_filter_param;
00243        event_filter_param = efp;
00244 
00245        return;
00246 }
00247 
00248 static void
00249 event_filter_forget(
00250        Display *     display,
00251        Window        window,
00252        Bool          (* filter)(Display *, Window, XEvent *, XPointer),
00253        XPointer      call_data) {
00254        event_filter_param_t *      efp;
00255        event_filter_param_t **     efp_prev;
00256        
00257        efp_prev = &event_filter_param;
00258        efp = event_filter_param;
00259        while (NULL != efp) {
00260               if ((display == efp->display) &&
00261                   (window == efp->window) &&
00262                   (filter == efp->filter) &&
00263                   (call_data == efp->call_data)) {
00264                      *efp_prev = efp->next;
00265                      free(efp);
00266               } else {
00267                      efp_prev = &(efp->next);
00268               }
00269               efp = *efp_prev;
00270        }
00271 
00272        return;
00273 }
00274 
00275 static void
00276 event_filter_unregister_all(void)
00277 {
00278        event_filter_param_t *      efp;
00279        event_filter_param_t *      efp_next;
00280 
00281        for (efp = event_filter_param; NULL != efp; efp = efp_next) {
00282               efp_next = efp->next;
00283               unregister_X_filter(efp->display, efp->window,
00284                                 efp->filter, efp->call_data);
00285               free(efp);
00286        }
00287        event_filter_param = NULL;
00288 
00289        return;
00290 }
00291 #endif /* WORKAROUND_XXXXXXX */
00292 
00293 static xaux_so_class_t *
00294 xaux_getclass_bysowin(Window win)
00295 {
00296        xaux_so_class_t      *p = xaux_classes;
00297 
00298        while (p->classname != NULL) {
00299               if (p->sowin == win)
00300                      return (p);
00301               p++;
00302        }
00303 
00304        return (NULL);
00305 }
00306 
00307 static xaux_so_class_t *
00308 xaux_getclass_byextwin(Window win)
00309 {
00310        xaux_so_class_t      *p = xaux_classes;
00311 
00312        while (p->classname != NULL) {
00313               if (p->extwin == win)
00314                      return (p);
00315               p++;
00316        }
00317 
00318        return (NULL);
00319 }
00320 
00321 static xaux_so_class_t *
00322 xaux_getclass_byutfname(
00323        const CARD16 *       utfname,
00324        size_t        len)
00325 {
00326        xaux_so_class_t      *p = xaux_classes;
00327 
00328        while (p->classname != NULL) {
00329               if (memcmp(p->utfname, utfname, len) == 0) {
00330                      return p;
00331               }
00332               p++;
00333        }
00334 
00335        return NULL;
00336 }
00337 
00338 static Bool
00339 xaux_so_extwin_event_filter(Display *, Window, XEvent *, XPointer);
00340 
00341 static Bool
00342 xaux_so_get_extwin(
00343        xaux_so_class_t      *xc,
00344        Display *     dpy)
00345 {
00346        size_t        i;
00347 
00348        xc->extwin = XGetSelectionOwner(dpy, xc->atom_extwin);
00349 
00350        if (xc->extwin == None) {
00351               return (False);
00352        } else {
00353 #if defined(DEBUG_XAUX)
00354        fprintf(stderr, "[%s] extwin=0x%x (selection)\n",
00355               xc->shortname, xc->extwin);
00356 #endif /* defined(DEBUG_XAUX) */
00357               XSelectInput(dpy, xc->extwin,
00358                      StructureNotifyMask | PropertyChangeMask);
00359 
00360               register_X_filter(dpy, xc->extwin, DestroyNotify, DestroyNotify,
00361                      xaux_so_extwin_event_filter, (XPointer)xc);
00362 
00363               register_X_filter(dpy, xc->extwin,
00364                      PropertyNotify, PropertyNotify,
00365                      xaux_so_extwin_event_filter, (XPointer)xc);
00366 
00367 #if defined(WORKAROUND_XXXXXXX)
00368               event_filter_remember(dpy, xc->extwin,
00369                                   xaux_so_extwin_event_filter,
00370                                   (XPointer)xc);
00371 #endif /* WORKAROUND_XXXXXXX */
00372 
00373               return (True);
00374        }
00375 }
00376 
00377 xaux_so_execmng_data_t *
00378 xaux_so_execmng_alloc_data(
00379        const char           *classname)
00380 {
00381        xaux_so_execmng_data_t      *data;
00382        int                  i;
00383 
00384        data = (xaux_so_execmng_data_t *)
00385               malloc(sizeof (xaux_so_execmng_data_t));
00386 
00387        if (data == NULL) {
00388               return (NULL);
00389        }
00390 
00391        for (i = 0; i < XAUX_SO_EXECMNG_LOGSIZE; i++) {
00392               data->log[i].time = (time_t)0;
00393               data->log[i].state = Initial;
00394        }
00395 
00396        return (data);
00397 }
00398 
00399 static Bool
00400 xaux_so_execmng_triable(
00401        xaux_so_execmng_data_t      *data)
00402 {
00403        time_t        cur;
00404 
00405        cur = time(NULL);
00406 
00407        if ((cur - data->log[XAUX_SO_EXECMNG_FAILSINPERIOD_TRIES - 1].time)
00408               < XAUX_SO_EXECMNG_FAILSINPERIOD_PERIOD) {
00409               /* too frequent tries */
00410               return (False);
00411        } else {
00412               return (True);
00413        }
00414 }
00415 
00416 static Bool
00417 xaux_so_execmng_logstate(
00418        xaux_so_execmng_data_t      *data,
00419        xaux_so_extstate_t   state)
00420 {
00421        int    i;
00422 
00423        for (i = XAUX_SO_EXECMNG_LOGSIZE - 1; i > 0; i--) {
00424               data->log[i] = data->log[i - 1];
00425        }
00426 
00427        data->log[0].time = time(NULL);
00428        data->log[0].state = state;
00429 
00430        return (True);
00431 }
00432 
00433 void
00434 xaux_so_execmng_free_data(
00435        xaux_so_execmng_data_t      *data
00436 )
00437 {
00438        if (data == NULL) {
00439               return;
00440        }
00441 
00442        free(data);
00443 
00444        return;
00445 }
00446 
00447 #if    defined(__sparcv9)
00448 #define       CHECK_SO             "sparcv9/check.so"
00449 #else  /* !__sparcv9 */
00450 #define       CHECK_SO             "check.so"
00451 #endif /* __sparcv9 */
00452 
00453 /*
00454  * tentative hardcoded logic
00455  * Check if OK to execute binaries under "xaux1" directory, instead of
00456  * those under "xaux" directory.
00457  * The check is done by invoking "check" method in "xaux1/check.so".
00458  */
00459 static Bool
00460 xaux_so_check_xaux1(void)
00461 {
00462        void * handle = NULL;
00463        int    (*check)() = NULL;
00464        char   path[MAXPATHLEN];
00465 
00466        if (xaux_so_extexec_dirno >= 0) {
00467               if (xaux_so_extexec_dirno >= 1) {
00468                      return (True);
00469               } else {
00470                      return (False);
00471               }
00472        }
00473 
00474        snprintf(path, MAXPATHLEN, "%s%d/%s",
00475               xaux_so_extexec_path, 1, CHECK_SO);
00476 
00477        if ((handle = dlopen(path, RTLD_LAZY)) != NULL) {
00478               if ((check = ((int (*)())dlsym(handle, "check"))) != NULL) {
00479                      if ((*check)() == 0) {
00480                             dlclose(handle);
00481                             xaux_so_extexec_dirno = 1;
00482                             return (True);
00483                      }
00484               }
00485               dlclose(handle);
00486        }
00487 
00488        xaux_so_extexec_dirno = 0;
00489        return (False);
00490 }
00491 
00492 static Bool
00493 xaux_so_launch_ext(
00494        xaux_so_class_t      *xc,
00495        aux_icid_t    *ic)
00496 {
00497        pid_t         pid;
00498        char          path[MAXPATHLEN];
00499 
00500 #if defined(DEBUG_XAUX)
00501        fprintf(stderr, "[%s] xaux_so_launch_ext() called\n", xc->shortname);
00502 #endif /* defined(DEBUG_XAUX) */
00503 
00504        if (xc->extstate == ErrorPerm) {
00505 #if defined(DEBUG_XAUX)
00506        fprintf(stderr, "[%s] not attempt to launch; permanent error\n",
00507               xc->shortname);
00508 #endif /* defined(DEBUG_XAUX) */
00509               return (False);
00510        }
00511 
00512        if (xaux_so_get_extwin(xc, ic->dpy) == True) {
00513               /*
00514                * succeeded in communicating
00515                * with already running external program
00516                */
00517               xc->extstate = Connected;
00518 #if defined(DEBUG_XAUX)
00519        fprintf(stderr, "[%s] extwin=0x%x (selection:l)\n",
00520               xc->shortname, xc->extwin);
00521 #endif /* defined(DEBUG_XAUX) */
00522               return (True);
00523        }
00524 
00525        if (ic->server == False) {
00526               /*
00527                * do not launch external program
00528                * if not loaded by server (htt_xbe) program
00529                */
00530               xc->extstate = ErrorPerm;
00531 #if defined(DEBUG_XAUX)
00532        fprintf(stderr, "[%s] not attempt to launch; not xbe process\n",
00533               xc->shortname);
00534 #endif /* defined(DEBUG_XAUX) */
00535               return (False);
00536        }
00537 
00538        /*
00539         * tentative hardcoded logic
00540         * If OK to use xaux1 binaries, use them.
00541         */
00542        if (xaux_so_check_xaux1() == True) {
00543               snprintf(path, MAXPATHLEN, "%s%d/%s",
00544                      xaux_so_extexec_path, 1, xc->extexec);
00545        } else {
00546               snprintf(path, MAXPATHLEN, "%s/%s",
00547                      xaux_so_extexec_path, xc->extexec);
00548        }
00549 
00550 #if defined(DEBUG_XAUX)
00551        fprintf(stderr, "[%s] trying executable \"%s\"....\n",
00552               xc->shortname, path);
00553 #endif /* defined(DEBUG_XAUX) */
00554 
00555        if (access(path, X_OK) != 0) {
00556 #if defined(DEBUG_XAUX)
00557        fprintf(stderr, "[%s] executable \"%s\" not found\n",
00558               xc->shortname, path);
00559 #endif /* defined(DEBUG_XAUX) */
00560               xc->extstate = ErrorPerm;
00561               return (False);
00562        }
00563                      
00564        pid = fork1();
00565 
00566        if (pid == (pid_t)(-1)) { /* fork failed */
00567               xc->extstate = ErrorTemp;
00568 #if defined(DEBUG_XAUX)
00569        fprintf(stderr, "[%s] fork failed\n", xc->shortname);
00570 #endif /* defined(DEBUG_XAUX) */
00571               return (False);
00572        } else if (0 == pid) { /* child */
00573 #if defined(IM_LOCALE)
00574               char   *cur;
00575               size_t bufsz = sizeof ("LC_ALL=") + MAXNAMELEN;
00576               char   buf[sizeof ("LC_ALL=") + MAXNAMELEN];
00577 
00578               cur = setlocale(LC_CTYPE, NULL);
00579 
00580               if (cur == NULL) {
00581                      cur = "C";
00582               }
00583 
00584               if (strncmp(cur, "ja", 2) == 0) { /* locale name is ja* */
00585                      /* Japanese locale; set to current locale */
00586                      snprintf(buf, bufsz, "LC_ALL=%s", cur);
00587                      putenv(buf);
00588                      snprintf(buf, bufsz, "LANG=%s", cur);
00589                      putenv(buf);
00590               } else {
00591                      /* not Japanese locale; set to IM_LOCALE */
00592                      putenv("LC_ALL=" IM_LOCALE);
00593                      putenv("LANG=" IM_LOCALE);
00594               }
00595 #endif /* defined(IM_LOCALE) */
00596 #if defined(DEBUG_XAUX)
00597               chdir("/tmp");
00598 #endif /* defined(DEBUG_XAUX) */
00599               execl(path, xc->classname, NULL);
00600               _exit(1);
00601        }
00602 
00603        /* parent */
00604        xc->extstate = Launched;
00605 #if defined(DEBUG_XAUX)
00606        fprintf(stderr, "[%s] fork done\n", xc->shortname);
00607 #endif /* defined(DEBUG_XAUX) */
00608        return (True);
00609 }
00610 
00611 static Bool
00612 xaux_so_notify_flowstate(
00613        xaux_so_class_t *    xc,
00614        int                  flowstate)
00615 {
00616        int           size;
00617        aux_data_t    aux_data_;
00618        aux_data_t *  aux_data = &(aux_data_);
00619        int           state;
00620        int           int_array[2];
00621        unsigned char *p;
00622 
00623        if (xc->ic == NULL) {
00624               /* no current IC */
00625               return (False);
00626        }
00627 
00628        /* header */
00629 
00630        aux_data->type = AUX_DATA_SETVALUE;
00631        aux_data->im = xc->ic->imid;
00632        aux_data->ic = xc->ic->icid;
00633        aux_data->aux_index = xc->index;
00634        aux_data->aux_name = (unsigned char *)xc->utfname;
00635        aux_data->aux_name_length = strlen(xc->classname)*sizeof(CARD16);
00636 
00637        /* int values */
00638 
00639        aux_data->integer_count = 2;
00640 
00641        aux_data->integer_list = &int_array[0];
00642        aux_data->integer_list[0] = XAUX_SO_NOTIFY_FLOWSTATE_ID;
00643        aux_data->integer_list[1] = flowstate;
00644 
00645        /* no string values */
00646 
00647        aux_data->string_count = 0;
00648        aux_data->string_list = NULL;
00649        aux_data->string_ptr = NULL;
00650 
00651        /* compose and send message to engine */
00652 
00653 /* workaround for "stored reference to aux_t is corrupred" problem */
00654        if ((p = /*ic->aux->service->*/compose(aux_data, &size)) == NULL) {
00655               return (False);
00656        }
00657 
00658 #if defined(DEBUG_XAUX)
00659        fprintf(stderr, "[%s] SETVALUE(flow): im=0x%x ic=0x%x i[0]=0x%x "
00660                      "i[1]=0x%x in=%d sn=%d\n",
00661               xc->shortname, aux_data->im, aux_data->ic,
00662               aux_data->integer_list[0], aux_data->integer_list[1],
00663               aux_data->integer_count, aux_data->string_count);
00664 #endif /* defined(DEBUG_XAUX) */
00665 
00666 /* workaround for "stored reference to aux_t is corrupred" problem */
00667        /*ic->aux->service->*/aux_setvalue(/*ic->aux*/&aux_tmp, p, size);
00668 
00669        return (True);
00670 }
00671 
00672 static Bool
00673 xaux_sx_flushq(
00674        Display              *dpy,
00675        Window        win,
00676        xaux_so_class_t      *xc,
00677        Bool          detour)
00678 {
00679        Bool          rv = True;
00680        unsigned char *p;
00681        int           len;
00682        Atom          atom;
00683        int           qcount;
00684 
00685        if ((win = xc->extwin) == (Window)None) {
00686               if (xaux_so_get_extwin(xc, dpy) == True) {
00687                      win = xc->extwin;
00688               } else if (detour) {
00689 #if defined(DEBUG_XAUX)
00690        fprintf(stderr, "[%s] property detoured to sowin\n", xc->shortname);
00691 #endif /* defined(DEBUG_XAUX) */
00692                      win = xc->sowin;
00693               } else {
00694                      /* discard remaining data */
00695                      xaux_propq_clean(xc->propq);
00696                      return (False);
00697               }
00698        }
00699 
00700        while (xaux_propq_check(xc->propq) > 0) {
00701               atom = xaux_atommng_get_atom(xc->atommng_data, win);
00702               if (atom == (Atom)None) {
00703                      break;
00704               }
00705               if ((qcount = xaux_propq_get(xc->propq, &p, &len)) >= 0) {
00706                      XChangeProperty(dpy, win, atom, XA_STRING, 8,
00707                             PropModeReplace, (unsigned char *)p, len);
00708                      XFlush(dpy);
00709 #if defined(DEBUG_XAUX)
00710 fprintf(stderr, "[%s] send property atom=%d\n", xc->shortname, atom);
00711 #endif /* defined(DEBUG_XAUX) */
00712                      free(p);
00713               } else {
00714                      break;
00715               }
00716        }
00717 
00718        return (rv);
00719 }
00720 
00721 static Bool
00722 xaux_sx_check_propdel(
00723        Display              *dpy,
00724        XEvent        *ev,
00725        XPointer      arg)
00726 {
00727        xaux_so_class_t      *xc = (xaux_so_class_t *)arg;
00728 
00729        if (ev->type == PropertyNotify) {
00730               XPropertyEvent       *pev = &(ev->xproperty);
00731 
00732               if ((pev->state == PropertyDelete)
00733                             && (pev->atom == xc->atom_sx)) {
00734                      return (True);
00735               }
00736        } else if (ev->type == DestroyNotify) {
00737               XDestroyWindowEvent  *dev = &(ev->xdestroywindow);
00738 
00739               if (dev->window == xc->extwin) {
00740                      return (True);
00741               }
00742        }
00743 
00744        return (False);
00745 }
00746 
00747 static Bool
00748 xaux_so_process_destroy_extwin(
00749        Display *     dpy,
00750        Window        win,
00751        XDestroyWindowEvent  *ev)
00752 {
00753        xaux_so_class_t *    xc;
00754 
00755        if ((xc = xaux_getclass_byextwin(ev->window)) == NULL) {
00756               return (False);
00757        }
00758 
00759 #if defined(DEBUG_XAUX)
00760 fprintf(stderr, "[%s] extwin 0x%x destroyed\n", xc->shortname, win);
00761 #endif /* defined(DEBUG_XAUX) */
00762 
00763        xc->extwin = (Window)None;
00764        xc->extstate = Disconnected;
00765 
00766        xaux_atommng_release_atom(xc->atommng_data);
00767        xaux_propq_clean(xc->propq);
00768 
00769 #if defined(NOTIFY_STATE)
00770        (void)xaux_so_notify_state(xc);
00771 #endif /* defined(NOTIFY_STATE) */
00772 
00773         unregister_X_filter(dpy, xc->extwin,
00774                      xaux_so_extwin_event_filter, NULL);
00775 #if defined(WORKAROUND_XXXXXXX)
00776        event_filter_forget(dpy, xc->extwin, xaux_so_extwin_event_filter, NULL);
00777 #endif /* WORKAROUND_XXXXXXX */
00778 
00779 #if defined(SO_RESTART_EXT_AUTO)
00780        if (xc->ic != NULL) { /* have current IC */
00781               /* then restart external process */
00782               if (xaux_so_execmng_triable(xc->execmng_data)) {
00783                      xaux_so_launch_ext(xc, xc->ic);
00784 #if defined(NOTIFY_STATE)
00785        (void)xaux_so_notify_state(xc);
00786 #endif /* defined(NOTIFY_STATE) */
00787               }
00788        }
00789 #endif /* defined(SO_RESTART_EXT_AUTO) */
00790 
00791        return (True);
00792 }
00793 
00794 
00795 static Bool
00796 xaux_so_send_property(
00797        aux_t *                     aux,
00798        xaux_so_class_t *    xc,
00799        unsigned char *             p,     /* data to send */
00800        int                  len,   /* length of data (bytes) */
00801        Bool                 detour)       /* use sowin when extwin is absent */
00802 {
00803        Display *     dpy;
00804        Bool          rv;
00805        Atom          atom;
00806        Window        win;
00807        int           i;
00808        int           qcount;
00809        struct pollfd fds[1];
00810        XEvent        ev;
00811        int           retry_count;
00812 
00813        dpy = aux->service->display(aux);
00814 
00815        fds[0].fd = ConnectionNumber(dpy);
00816        fds[0].events = POLLIN;
00817        fds[0].revents = 0;
00818 
00819        /* first try to flush existing data (if any) */
00820        xaux_sx_flushq(dpy, win, xc, detour);
00821 
00822        retry_count = 0;
00823        while (xaux_propq_check(xc->propq) > 0) {
00824               int    r;
00825 
00826               if (XCheckIfEvent(dpy, &ev, xaux_sx_check_propdel, (XPointer)xc)
00827                             == True) {
00828                      retry_count = 0;
00829                      if (ev.type == PropertyNotify) {
00830                             /* atom released - flush existing data */
00831                             xaux_atommng_process_delete(xc->atommng_data,
00832                                    (XPropertyEvent *)(&(ev.xproperty)));
00833                             xaux_sx_flushq(dpy, win, xc, detour);
00834                      } else if (ev.type == DestroyNotify) {
00835                             /* extwin deleted - discard unset data */
00836                             xaux_so_process_destroy_extwin(dpy,
00837                                    ev.xdestroywindow.window,
00838                                    (XDestroyWindowEvent *)
00839                                    (&(ev.xdestroywindow)));
00840                             free(p);
00841                             return (False);
00842                      }
00843               } else {
00844                      /* wait data from X server */
00845                      retry_count += 1;
00846                      if (retry_count <= 20) {
00847                             r = poll(&(fds[0]), 1, (100 * retry_count));
00848 /*                   if (retry_count <= 3) { */
00849 /*                          r = poll(&(fds[0]), 1, (1000 * retry_count)); */
00850 /*                          r = poll(&(fds[0]), 1, */
00851 /*                                  (1 == retry_count) ? */
00852 /*                                  500 : (1000 * retry_count)); */
00853                      } else {
00854                             r = 0;
00855                      }
00856                      if (r <= 0) {
00857                             xaux_atommng_release_atom(xc->atommng_data);
00858                             xaux_sx_flushq(dpy, win, xc, detour);
00859                      }
00860               }
00861        }
00862 
00863        if ((qcount = xaux_propq_add(xc->propq, p, len)) == -1) {
00864               /* malloc error */
00865               free(p);
00866               return (False);
00867        } else if (qcount == -2) {
00868               /* queue full */
00869               free(p);
00870               return (False);
00871        }
00872 
00873        /* try to flush data just added */
00874        xaux_sx_flushq(dpy, win, xc, detour);
00875 
00876        return (True);
00877 }
00878 
00879 static Bool
00880 xaux_so_dispatch_propnot_extwin(
00881        Display              *dpy,
00882        Window        win,
00883        XPropertyEvent       *pev,
00884        xaux_so_class_t      *xc)
00885 {
00886        Bool          rv = False;
00887 
00888        if (xaux_atommng_check_atom(xc->atommng_data, False, pev->atom)
00889                      == True) {
00890               /* sx */
00891               if (pev->state == PropertyDelete) {
00892                      if (xaux_atommng_process_delete(xc->atommng_data, pev)
00893                                    == True) {
00894                             xaux_sx_flushq(dpy, pev->window, xc, True);
00895                      }
00896               }
00897               rv = True;
00898        }
00899 
00900        return (rv);
00901 }
00902 
00903 static Bool
00904 xaux_so_extwin_event_filter(
00905        Display *     display,
00906        Window        window,
00907        XEvent *      event,
00908        XPointer      pointer)
00909 {
00910        switch (event->type) {
00911        case DestroyNotify:
00912               return (xaux_so_process_destroy_extwin(display, window,
00913                      (XDestroyWindowEvent *)event));
00914        case PropertyNotify:
00915               return (xaux_so_dispatch_propnot_extwin(display, window,
00916                      (XPropertyEvent *)(&event->xproperty),
00917                      (xaux_so_class_t *)pointer));
00918        }
00919        return (False);
00920 }
00921 
00922 static Bool
00923 xaux_so_clean_setv_state(xaux_so_setv_state_t *state, Bool initial)
00924 {
00925        int           maxnprops_sv;
00926        unsigned char **props_sv;
00927        aux_data_t *  aux_data;
00928        int           i;
00929 
00930        if (!initial) {
00931               if (state->aux_data != NULL) {
00932                      free(state->aux_data->integer_list);
00933                      aux_data = state->aux_data;
00934                      if (NULL != aux_data->string_list) {
00935                             for (i = 0; i < aux_data->string_count; i++) {
00936                                    free((aux_data->string_list + i)->ptr);
00937                             }
00938                      }
00939                      free(state->aux_data->string_list);
00940               }
00941               free(state->outbuf);
00942 
00943               for (i = 0; i < state->nprops; i++) {
00944                      if (state->props[i] != NULL) {
00945                             XFree(state->props[i]);
00946                      }
00947               }
00948 
00949               maxnprops_sv = state->maxnprops;
00950               props_sv = state->props;
00951        }
00952 
00953        memset(state, 0, sizeof (xaux_so_setv_state_t));
00954 
00955        if (initial) {
00956               state->maxnprops = XAUX_MAXNPROPS_INIT;
00957               if ((state->props = (unsigned char **)malloc(
00958                             sizeof (unsigned char *)
00959                             * state->maxnprops)) == NULL) {
00960                      return (False);
00961               }
00962        } else {
00963               state->maxnprops = maxnprops_sv;
00964               state->props = props_sv;
00965        }
00966 
00967        state->nprops = 0;
00968        state->stored = False;
00969        state->aux_data = &(state->aux_data_);
00970 
00971        return (True);
00972 }
00973 
00974 static Bool
00975 xaux_so_add_prop_to_setv_state(
00976        xaux_so_setv_state_t *state,
00977        unsigned char        *prop)
00978 {
00979        int           maxnprops = state->maxnprops;
00980        int           nprops = state->nprops;
00981        unsigned char **props = state->props;
00982 
00983        if ((state->nprops) >= state->maxnprops) {
00984               maxnprops += XAUX_MAXNPROPS_INIT;
00985               props = (unsigned char **)realloc(props,
00986                      sizeof (unsigned char *) * maxnprops);
00987               if (props == NULL) {
00988                      return (False);
00989               }
00990               state->maxnprops = maxnprops;
00991               state->props = props;
00992        }
00993 
00994        state->props[state->nprops] = prop;
00995        state->nprops++;
00996        return (True);
00997 }
00998 
00999 static Bool
01000 xaux_so_init_setv_state(
01001        xaux_so_setv_state_t *state,
01002        xaux_so_class_t             *xc,
01003        unsigned char        *prop)
01004 {
01005        aux_data_t    *aux_data;
01006        char          *setv;
01007 
01008        if (xaux_so_clean_setv_state(state, False) == False) {
01009               return (False);
01010        }
01011 
01012        setv = (char *)XS_DATA_TOP(prop);
01013 
01014        state->seqno = BO_SEQNO(prop);
01015 
01016        aux_data = state->aux_data;
01017        aux_data->type = AUX_DATA_DRAW;
01018        aux_data->im = BO_IMID(prop);
01019        aux_data->ic = BO_ICID(prop);
01020        aux_data->aux_index = xc->index;
01021        aux_data->aux_name = (unsigned char *)xc->utfname;
01022        aux_data->aux_name_length =
01023               (strlen((const char *)xc->classname) * (sizeof (CARD16)));
01024        aux_data->integer_count = BO_SETV_INT_COUNT(prop);
01025        aux_data->string_count = BO_SETV_STR_COUNT(prop);
01026 
01027        state->segno = BO_SEGNO(prop);
01028 
01029        state->str_yet = 0;
01030 
01031        if (aux_data->integer_count > 0) {
01032               if ((aux_data->integer_list = (int *)malloc(sizeof (int)
01033                             * aux_data->integer_count)) == NULL) {
01034                      (void)xaux_so_clean_setv_state(state, False);
01035                      return (False);
01036               }
01037        } else {
01038               aux_data->integer_list = NULL;
01039        }
01040 
01041        if (aux_data->string_count > 0) {
01042               if ((aux_data->string_list = (aux_string_t *)malloc(
01043                             sizeof (aux_string_t) *
01044                             aux_data->string_count)) == NULL) {
01045                      (void)xaux_so_clean_setv_state(state, False);
01046                      return (False);
01047               }
01048        }
01049 
01050        return (True);
01051 }
01052 
01053 static Bool
01054 xaux_so_process_property_xs(
01055        Display       *             dpy,
01056        Window               window,
01057        Atom                 atom,
01058        xaux_so_class_t *    xc)
01059 {
01060        Atom          actual_type_return = (Atom)None;
01061        int           actual_format_return = 0;
01062        unsigned long nitem_return = 0;
01063        unsigned long bytes_after_return = 0;
01064        unsigned char *      prop = NULL;
01065        unsigned char *      setv;
01066        unsigned char *p;
01067        int           r;
01068        unsigned char *proptail;
01069 /*
01070        aux_icid_t *  ic;
01071 */
01072        int           size;
01073        aux_data_t    aux_data_;
01074        aux_data_t *  aux_data = &(aux_data_);
01075        int           i;
01076        int           n=0;
01077        Bool          rv = True;
01078 
01079        xaux_so_setv_state_t *state;
01080        int           *ip;
01081        char          *sp;
01082 
01083        r = XGetWindowProperty(dpy, window,
01084                             atom, 0, INT_MAX, True,
01085                             XA_STRING, &actual_type_return,
01086                             &actual_format_return, &nitem_return,
01087                             &bytes_after_return, &prop);
01088 
01089        if ((r != Success) || (actual_type_return != XA_STRING)) {
01090               return False;
01091        }
01092 
01093 /*
01094        if ((ic = aux_icid_get(BO_ICID(prop_return), False)) == NULL) {
01095               XFree(prop_return);
01096               return (False);
01097        }
01098 */
01099        XSetSelectionOwner(dpy, atom, (Window)None, CurrentTime);
01100 
01101        proptail = prop + XS_SIZE_HEADER + BO_SEGSIZE(prop);
01102 
01103        setv = XS_DATA_TOP(prop);
01104 
01105        if (xc->pending_setv == NULL) {
01106               if ((xc->pending_setv = (xaux_so_setv_state_t *)malloc(
01107                             sizeof (xaux_so_setv_state_t))) == NULL) {
01108                      rv = False;
01109                      goto cleanup_return;
01110               }
01111               xaux_so_clean_setv_state(xc->pending_setv, True);
01112        }
01113 
01114        if (BO_SEGNO(prop) > 0) {
01115               if (xc->pending_setv->stored == True) {
01116                      if (BO_SEGNO(prop) == (xc->pending_setv->segno + 1)) {
01117 #if defined(DEBUG_XAUX)
01118 fprintf(stderr, "[%s] SETV: segno=%d, continue with stored segno=%d\n",
01119               xc->shortname, BO_SEGNO(prop), xc->pending_setv->segno);
01120 #endif /* defined(DEBUG_XAUX) */
01121                             state = xc->pending_setv;
01122                             ip = (int *)setv;
01123                      } else {
01124 #if defined(DEBUG_XAUX)
01125 fprintf(stderr, "[%s] SETV: stored segno mismatch (%d expected %d actual)\n",
01126               xc->shortname, xc->pending_setv->segno + 1, BO_SEGNO(prop));
01127 #endif /* defined(DEBUG_XAUX) */
01128                             xaux_so_clean_setv_state(xc->pending_setv,
01129                                    False);
01130                             rv = False;
01131                             goto cleanup_return;
01132                      }
01133               } else {
01134 #if defined(DEBUG_XAUX)
01135 fprintf(stderr, "[%s] SETV: received segno=%d but no stored segs\n",
01136               xc->shortname, BO_SEGNO(prop));
01137 #endif /* defined(DEBUG_XAUX) */
01138                      rv = False;
01139                      goto cleanup_return;
01140               }
01141        } else {
01142               if (xc->pending_setv->stored == True) {
01143 #if defined(DEBUG_XAUX)
01144 fprintf(stderr, "[%s] SETV: stored but received segno=0 (%d expected)\n",
01145                             xc->shortname, xc->pending_setv->segno + 1);
01146 #endif /* defined(DEBUG_XAUX) */
01147                      xaux_so_init_setv_state(xc->pending_setv, xc, prop);
01148               } else {
01149                      xaux_so_init_setv_state(xc->pending_setv, xc, prop);
01150               }
01151               state = xc->pending_setv;
01152               ip = (int *)BO_SETV_INT_LIST(setv);
01153        }
01154 
01155        aux_data = state->aux_data;
01156 
01157        for (i = state->int_next; i < aux_data->integer_count; i++) {
01158               if ((unsigned char *)ip >= proptail) {
01159                      state->int_next = i;
01160                      state->segno = BO_SEGNO(prop);
01161                      xaux_so_add_prop_to_setv_state(state, prop);
01162                      state->stored = True;
01163 #if defined(DEBUG_XAUX)
01164 fprintf(stderr, "[%s] DRAW: received up to int[%d]\n", xc->shortname, i - 1);
01165 #endif /* defined(DEBUG_XAUX) */
01166                      return (True);
01167               }
01168               aux_data->integer_list[i] = BO_CARD32(prop, ip);
01169               ip++;
01170        }
01171 
01172        state->int_next = i;
01173 
01174        sp = (char *)ip;
01175 
01176        for(i = state->str_next; i < aux_data->string_count; i++) {
01177               int    len;
01178 
01179               if (sp >= (char *)proptail) {
01180                      state->str_next = i;
01181                      state->segno = BO_SEGNO(prop);
01182                      xaux_so_add_prop_to_setv_state(state, prop);
01183                      state->stored = True;
01184 #if defined(DEBUG_XAUX)
01185 fprintf(stderr, "(%s) DRAW: received up to string[%d]\n", xc->shortname, i - 1);
01186 #endif /* defined(DEBUG_XAUX) */
01187                      return (True);
01188               }
01189 
01190               len = BO_CARD16(prop, sp);
01191               aux_data->string_list[i].length = len;
01192               sp += sizeof(CARD16);
01193               aux_data->string_list[i].ptr =
01194                      (unsigned char *)malloc((sizeof (CARD16)) * len);
01195               if (1 == (*((CARD16 *)(prop)))) {
01196                      memcpy((char *)(aux_data->string_list[i].ptr), sp,
01197                             (sizeof (CARD16)) * len);
01198               } else {
01199                      swab(sp, (char *)(aux_data->string_list[i].ptr),
01200                           (sizeof (CARD16)) * len);
01201               }
01202               sp += (len + padding[(sizeof(CARD16) + len) % 4]);
01203        }
01204 
01205 #if defined(DEBUG_XAUX)
01206        if (aux_data->integer_count > 0) {
01207               fprintf(stderr, "[%s] SETV: im=0x%x ic=0x%x "
01208                             "i[0]=0x%x in=%d sn=%d\n",
01209                      xc->shortname,
01210                      aux_data->im, aux_data->ic,
01211                      aux_data->integer_list[0],
01212                      aux_data->integer_count,
01213                      aux_data->string_count);
01214        } else {
01215               fprintf(stderr, "[%s] SETV: im=0x%x ic=0x%x in=%d sn=%d\n",
01216                      xc->shortname,
01217                      aux_data->im, aux_data->ic,
01218                      aux_data->integer_count,
01219                      aux_data->string_count);
01220        }
01221 #endif /* defined(DEBUG_XAUX) */
01222 
01223 /* workaround for "stored reference to aux_t is corrupred" problem */
01224        if ((p = /*ic->aux->service->*/compose(aux_data, &size)) == NULL) {
01225               xaux_so_clean_setv_state(state, False);
01226               rv = False;
01227               goto cleanup_return;
01228        }
01229 
01230 /* workaround for "stored reference to aux_t is corrupred" problem */
01231        /*ic->aux->service->*/aux_setvalue(/*ic->aux*/&aux_tmp, p, size);
01232 
01233        xaux_so_clean_setv_state(state, False);
01234 
01235 cleanup_return:
01236        if (prop != NULL) {
01237               XFree(prop);
01238        }
01239 
01240        return (rv);
01241 }
01242 
01243 static Bool
01244 xaux_so_notify_state(
01245        xaux_so_class_t *    xc)
01246 {
01247        int           size;
01248        aux_data_t    aux_data_;
01249        aux_data_t *  aux_data = &(aux_data_);
01250        int           state;
01251        int           int_array[2];
01252        unsigned char *p;
01253 
01254        if (xc->ic == NULL) {
01255               /* no current IC */
01256               return (False);
01257        }
01258 
01259        switch (xc->extstate) {
01260        case Initial:
01261               state = XAUX_SO_NOTIFY_STATE_NOTAVAILABLE;
01262               break;
01263        case ErrorPerm:
01264               state = XAUX_SO_NOTIFY_STATE_NOTAVAILABLE;
01265               break;
01266        case ErrorTemp:
01267               state = XAUX_SO_NOTIFY_STATE_NOTAVAILABLE;
01268               break;
01269        case Launched:
01270               state = XAUX_SO_NOTIFY_STATE_STANDBY;
01271               break;
01272        case Connected:
01273               state = XAUX_SO_NOTIFY_STATE_OK;
01274               break;
01275        case Disconnected:
01276               state = XAUX_SO_NOTIFY_STATE_NOTAVAILABLE;
01277               break;
01278        }
01279 
01280        /* header */
01281 
01282        aux_data->type = AUX_DATA_SETVALUE;
01283        aux_data->im = xc->ic->imid;
01284        aux_data->ic = xc->ic->icid;
01285        aux_data->aux_index = xc->index;
01286        aux_data->aux_name = (unsigned char *)xc->utfname;
01287        aux_data->aux_name_length = strlen(xc->classname)*sizeof(CARD16);
01288 
01289        /* int values */
01290 
01291        aux_data->integer_count = 2;
01292 
01293        aux_data->integer_list = &int_array[0];
01294        aux_data->integer_list[0] = XAUX_SO_NOTIFY_STATE_ID;
01295        aux_data->integer_list[1] = state;
01296 
01297        /* no string values */
01298 
01299        aux_data->string_count = 0;
01300        aux_data->string_list = NULL;
01301        aux_data->string_ptr = NULL;
01302 
01303        /* compose and send message to engine */
01304 
01305 /* workaround for "stored reference to aux_t is corrupred" problem */
01306        if ((p = /*ic->aux->service->*/compose(aux_data, &size)) == NULL) {
01307               return (False);
01308        }
01309 
01310 #if defined(DEBUG_XAUX)
01311        fprintf(stderr, "[%s] SETVALUE(state): im=0x%x ic=0x%x i[0]=0x%x "
01312                      "i[1]=0x%x in=%d sn=%d\n",
01313               xc->shortname, aux_data->im, aux_data->ic,
01314               aux_data->integer_list[0], aux_data->integer_list[1],
01315               aux_data->integer_count, aux_data->string_count);
01316 #endif /* defined(DEBUG_XAUX) */
01317 
01318 /* workaround for "stored reference to aux_t is corrupred" problem */
01319        /*ic->aux->service->*/aux_setvalue(/*ic->aux*/&aux_tmp, p, size);
01320 
01321        return (True);
01322 }
01323 
01324 static Bool
01325 xaux_so_process_property_xs_list(
01326        Display       *             dpy,
01327        Window               win,
01328        xaux_so_class_t             *xc,
01329        Atom                 atom)
01330 {
01331        int           r;            /* return of Xlib functions */
01332        Bool          rv;           /* return of xaux functions */
01333        unsigned long bytes_after_return = 0U;
01334 
01335        rv = xaux_so_process_property_xs(dpy, xc->sowin, atom, xc);
01336 
01337        return (True);
01338 }
01339 
01340 static Bool
01341 xaux_so_process_property_extwin(
01342        Display       *             dpy,
01343        Window               win,
01344        xaux_so_class_t             *xc)
01345 {
01346        int           r;            /* return of Xlib functions */
01347        Atom          actual_type_return;
01348        int           actual_format_return;
01349        unsigned long nitems_return = 0;
01350        unsigned char *prop_return = NULL;
01351        unsigned long bytes_after_return = 0U;
01352 
01353        r = XGetWindowProperty(dpy, xc->sowin, xc->atom_extwin,
01354               (long)0, 1, False, XA_WINDOW,
01355               &actual_type_return,
01356               &actual_format_return,
01357               &nitems_return,
01358               &bytes_after_return,
01359               &prop_return);
01360        
01361        if ((r != Success) || (actual_type_return != XA_WINDOW)) {
01362 #if defined(DEBUG_XAUX)
01363        fprintf(stderr, "[%s] property %s read failed\n",
01364               xc->shortname, XGetAtomName(dpy, xc->atom_extwin));
01365 #endif /* defined(DEBUG_XAUX) */
01366               return (False);
01367        }
01368 
01369        xc->extwin = *(Window *)(prop_return);
01370 #if defined(DEBUG_XAUX)
01371        fprintf(stderr, "[%s] extwin=0x%x (property)\n",
01372               xc->shortname, xc->extwin);
01373 #endif /* defined(DEBUG_XAUX) */
01374 
01375        if (xc->extstate != Connected) {
01376               xc->extstate = Connected;
01377 #if defined(NOTIFY_STATE)
01378               xaux_so_notify_state(xc);
01379 #endif /* defined(NOTIFY_STATE) */
01380        }
01381 
01382        if (prop_return != NULL) {
01383               XFree(prop_return);
01384        }
01385 
01386        XSelectInput(dpy, xc->extwin,
01387               StructureNotifyMask | PropertyChangeMask);
01388 
01389        register_X_filter(dpy, xc->extwin, DestroyNotify, DestroyNotify,
01390               xaux_so_extwin_event_filter, (XPointer)NULL);
01391 
01392 #if defined(WORKAROUND_XXXXXXX)
01393        event_filter_remember(dpy, xc->extwin,
01394                            xaux_so_extwin_event_filter, (XPointer)NULL);
01395 #endif /* WORKAROUND_XXXXXXX */
01396 
01397        register_X_filter(dpy, xc->extwin, PropertyNotify, PropertyNotify,
01398               xaux_so_extwin_event_filter, (XPointer)xc);
01399 
01400 #if defined(WORKAROUND_XXXXXXX)
01401        event_filter_remember(dpy, xc->extwin, 
01402                            xaux_so_extwin_event_filter, (XPointer)xc);
01403 #endif /* WORKAROUND_XXXXXXX */
01404 
01405        return (True);
01406 }
01407 
01408 static Bool
01409 xaux_so_process_property_notify(
01410        Display       *             dpy,
01411        Window               win,
01412        XPropertyEvent              *pev)
01413 {
01414        Bool          rv = False;
01415        xaux_so_class_t      *xc;
01416 
01417        if ((xc = xaux_getclass_bysowin(pev->window)) == NULL) {
01418               return False;
01419        }
01420        
01421        if (pev->atom == xc->atom_extwin) { /* notify extwin */
01422               if (pev->state == PropertyNewValue) {
01423                      rv = xaux_so_process_property_extwin(dpy, win, xc);
01424               } else {
01425                      rv = True;
01426               }
01427        } else if (xaux_atommng_check_atom(xc->atommng_data, True, pev->atom)
01428                      == True) {
01429               /* xs */
01430               if (pev->state == PropertyNewValue) {
01431                      rv = xaux_so_process_property_xs_list(dpy, win, xc,
01432                             pev->atom);
01433               }
01434               rv = True;
01435        } else if (xaux_atommng_check_atom(xc->atommng_data, False, pev->atom)
01436                      == True) {
01437               /* sx(detoured) */
01438               if (pev->state == PropertyDelete) {
01439                      if (xaux_atommng_process_delete(xc->atommng_data, pev)
01440                                    == True) {
01441                             xaux_sx_flushq(dpy, xc->extwin, xc, True);
01442                      }
01443               }
01444               rv = True;
01445        }
01446 
01447 
01448        return (rv);
01449 }
01450 
01451 static Bool
01452 xaux_so_sowin_event_filter(
01453        Display *     display,
01454        Window        window,
01455        XEvent *      event,
01456        XPointer      pointer)
01457 {
01458        xaux_so_class_t      *xc = (xaux_so_class_t *)pointer;
01459        Bool          rv;
01460 
01461        switch (event->type) {
01462        case PropertyNotify:
01463               rv = xaux_so_process_property_notify(display, window,
01464                      (XPropertyEvent *)event);
01465               break;
01466        case SelectionClear:
01467               if ((rv = xaux_atommng_process_selclr(xc->atommng_data,
01468                             (XSelectionClearEvent *)event)) == True) {
01469                      xaux_sx_flushq(display, xc->extwin, xc, True);
01470               }
01471               break;
01472        }
01473 #if defined(DEBUG_XAUX)
01474        fprintf(stderr, "[--] ignore event type=%d\n", event->type);
01475 #endif /* defined(DEBUG_XAUX) */
01476        return False;
01477 }
01478 
01479 static void
01480 aux_icid_init(void)
01481 {
01482        int    i;
01483 
01484        for (i = 0; i < HASH_SIZE; i++) {
01485               aux_icid[i].icid = (-1);
01486        }
01487 }
01488 
01489 static void
01490 aux_icid_finish(void)
01491 {
01492        int           i;
01493        aux_icid_t *  p0;
01494        aux_icid_t *  p1;
01495 
01496        for (i = 0; i < HASH_SIZE; i++) {
01497               p0 = aux_icid[i].next;
01498 
01499               for (; p0 != NULL; p0 = p1) {
01500                      p1 = p0->next;
01501                      free(p0);
01502               }
01503        }
01504 }
01505 
01506 static aux_icid_t *
01507 aux_icid_get(
01508        int    icID,
01509        Bool   createit)
01510 {
01511        int           hash_value;
01512        aux_icid_t *  p;
01513 
01514        p = &(aux_icid[icID % HASH_SIZE]);
01515 
01516        if (p->icid == -1) {
01517               if (!createit)
01518                      return NULL;
01519               p->icid = icID;
01520               return (p);
01521        }
01522 
01523        for (; ; p = p->next) {
01524               if (icID == p->icid) {
01525                      return p;
01526               }
01527               if (p->next == NULL) {
01528                      if (!createit)
01529                             return NULL;
01530                      p->next = malloc(sizeof (aux_icid_t));
01531                      if (p->next == NULL) {
01532                             return NULL;
01533                      }
01534                      memset(p->next, 0, (sizeof (aux_icid_t)));
01535                      p->next->prev = p;
01536                      p->next->next = NULL;
01537                      p->next->icid = icID;
01538                      return (p->next);
01539               }
01540        }
01541 }
01542 
01543 static void
01544 aux_icid_delete(int icID)
01545 {
01546        aux_icid_t *  p;
01547 
01548        p = aux_icid_get(icID, False);
01549 
01550        if (NULL == p) {
01551               return;
01552        }
01553 
01554        p->icid = -1;
01555 
01556        if (p->next != NULL) {
01557               p->next->prev = p->prev;
01558        }
01559        if (p->prev != NULL) {
01560               p->prev->next = p->next;
01561               free(p);
01562        }
01563 }
01564 
01565 static Bool
01566 xaux_so_init_classes_phase1(
01567        xaux_so_t *   so,
01568        aux_t *              aux)
01569 {
01570        Display              *dpy;
01571 
01572        xaux_so_class_t *p = xaux_classes;
01573 
01574        dpy = aux->service->display(aux);
01575 
01576        while (p->classname != NULL) {
01577               if (p->extexec == NULL) {
01578                      /* this class does not use external process */
01579                      p++;
01580                      continue;
01581               }
01582 
01583               p->extstate = Initial;
01584 
01585               p->shortname = strrchr(p->classname, '.');
01586               if (p->shortname == NULL) {
01587                      p->shortname = (char *)p->classname;
01588               } else {
01589                      p->shortname++;
01590               }
01591               p->shortname = strdup(p->shortname);
01592               if (p->shortname == NULL) {
01593                      p->shortname = "";
01594               } else {
01595                      if (strlen(p->shortname) > 4) {
01596                             p->shortname[4] = '\0';
01597                      }
01598               }
01599 
01600               p->atom_classname = (Atom)None;
01601               p->atom_sowin = (Atom)None;
01602               p->atom_extwin = (Atom)None;
01603               p->atommng_data = NULL;
01604               p->execmng_data = NULL;
01605               p->sowin = (Window)None;
01606               p->extwin = (Window)None;
01607               p->propq = NULL;
01608 
01609               p++;
01610        }
01611 
01612        so->classes = xaux_classes;
01613 
01614        return (True);
01615 }
01616 
01617 static Bool
01618 xaux_so_init_class_phase2(
01619        xaux_so_class_t      *xc,
01620        aux_t         *aux)
01621 {
01622        Display              *dpy;
01623        char          buf[XAUX_MAXCLASSNAMELEN + XAUX_MAXSUFFIXLEN + 1];
01624 
01625        if (xc->extexec == NULL) {
01626               /* this class does not use external process */
01627               return (True);
01628        }
01629 
01630        dpy = aux->service->display(aux);
01631 
01632        xc->atom_classname = XInternAtom(dpy, xc->classname, False);
01633 
01634        sprintf(buf, "%s%s", xc->classname, XAUX_SOWIN_SUFFIX);
01635        xc->atom_sowin = XInternAtom(dpy, buf, False);
01636 
01637        sprintf(buf, "%s%s", xc->classname, XAUX_EXTWIN_SUFFIX);
01638        xc->atom_extwin = XInternAtom(dpy, buf, False);
01639 
01640        sprintf(buf, "%s_sx", xc->classname);
01641        xc->atom_sx = XInternAtom(dpy, buf, False);
01642 
01643        sprintf(buf, "%s_xs", xc->classname);
01644        xc->atom_xs = XInternAtom(dpy, buf, False);
01645 
01646        xc->atommng_data = xaux_atommng_alloc_data(
01647               xc->classname, False /* means "sx" */, dpy);
01648 
01649        xc->execmng_data = xaux_so_execmng_alloc_data(xc->classname);
01650 
01651        xc->propq = xaux_propq_alloc(XAUX_MAXPROPSZ);
01652 
01653        if (XGetSelectionOwner(dpy, xc->atom_sowin) != None) {
01654 #if defined(DEBUG_XAUX)
01655               fprintf(stderr, "%s: %s already exists. [%s](1)\n",
01656                      ME_SO, ME_SO, xc->classname);
01657 #endif /* defined(DEBUG_XAUX) */
01658               goto done_sowin;
01659        }
01660 
01661        xc->sowin = XCreateSimpleWindow(dpy, RootWindow(dpy, 0),
01662                    0, 0, 1, 1, 0, 0, 0);
01663 
01664        if (xc->sowin == None) {
01665               fprintf(stderr, "%s: creating window for \"%s\" failed.\n",
01666                      ME_SO, xc->classname);
01667               goto done_sowin;
01668        }
01669 
01670 #if defined(WORKAROUND_XXXXXXX)
01671        window_list_remember(dpy, xc->sowin);
01672 #endif /* WORKAROUND_XXXXXXX */
01673 
01674        XSelectInput(dpy, xc->sowin, PropertyChangeMask);
01675 
01676        aux->service->register_X_filter(dpy, xc->sowin,
01677                      PropertyNotify, PropertyNotify,
01678                      xaux_so_sowin_event_filter, (XPointer)NULL);
01679 
01680 #if defined(WORKAROUND_XXXXXXX)
01681        event_filter_remember(dpy, xc->sowin,
01682                            xaux_so_sowin_event_filter, (XPointer)NULL);
01683 #endif /* WORKAROUND_XXXXXXX */
01684 
01685        aux->service->register_X_filter(dpy, xc->sowin,
01686                      SelectionClear, SelectionClear,
01687                      xaux_so_sowin_event_filter, (XPointer)xc);
01688 
01689 #if defined(WORKAROUND_XXXXXXX)
01690        event_filter_remember(dpy, xc->sowin,
01691                            xaux_so_sowin_event_filter, (XPointer)xc);
01692 #endif /* WORKAROUND_XXXXXXX */
01693 
01694        XSetSelectionOwner(dpy, xc->atom_sowin, xc->sowin, CurrentTime);
01695 
01696        if (XGetSelectionOwner(dpy, xc->atom_sowin) != xc->sowin) {
01697               fprintf(stderr, "%s: %s already exists.[%s](2)\n",
01698                      ME_SO, ME_SO, xc->classname);
01699               XDestroyWindow(dpy, xc->sowin);
01700 #if defined(WORKAROUND_XXXXXXX)
01701               window_list_remember(dpy, xc->sowin);
01702 #endif /* WORKAROUND_XXXXXXX */
01703               xc->sowin = (Window)0;
01704               goto done_sowin;
01705        }
01706 
01707 #if defined(DEBUG_XAUX)
01708        fprintf(stderr, "[%s] sowin created 0x%x\n", xc->shortname, xc->sowin);
01709 #endif /* defined(DEBUG_XAUX) */
01710 
01711 done_sowin:
01712        xc->extwin = (Window)0;
01713 
01714        return (True);
01715 }
01716 
01717 static Bool
01718 xaux_so_Create(aux_t * aux)
01719 {
01720        int           i;
01721        pid_t         pid;
01722        aux_icid_t *  aux_icid;
01723 
01724        if (so == NULL) {
01725               so = &so_;
01726               bzero((void *)so, sizeof (xaux_so_t));
01727               aux_icid_init();
01728        }
01729 
01730        if (NULL == (aux_icid = aux_icid_get(aux->service->ic_id(aux), True))) {
01731               return False;
01732        }
01733 
01734        aux_icid->aux = aux;
01735        aux_icid->imid = aux->service->im_id(aux);
01736        aux_icid->dpy = aux->service->display(aux);
01737        aux_icid->server = aux->service->server(aux);
01738 
01739 #if defined(DEBUG_XAUX)
01740        fprintf(stderr, "[--] CREATE: im=0x%x ic=0x%x\n",
01741               aux->service->im_id(aux),
01742               aux->service->ic_id(aux));
01743 #endif /* defined(DEBUG_XAUX) */
01744 
01745 /* workaround for "stored reference to aux_t is corrupred" problem */
01746 aux_tmp.ic = aux->ic;
01747 aux_setvalue = aux_icid->aux->service->aux_setvalue;
01748 mb_utf16 = aux_icid->aux->service->mb_utf16;
01749 compose = aux_icid->aux->service->compose;
01750 register_X_filter = aux_icid->aux->service->register_X_filter;
01751 unregister_X_filter = aux_icid->aux->service->unregister_X_filter;
01752 
01753        if (so->classes == NULL) {
01754               xaux_so_init_classes_phase1(so, aux);
01755        }
01756 
01757        return (True);
01758 }
01759 
01760 static Bool
01761 xaux_so_Start(aux_t * aux, const unsigned char * p, int size)
01762 {
01763        aux_data_t *  aux_data;
01764        char          *propbuf;
01765        xaux_so_class_t *    xc;
01766        Bool          rv;
01767        aux_icid_t *  ic;
01768 
01769 #if defined(WORKAROUND_XXXXXXX)
01770        if ((ic = aux_icid_get(aux->service->ic_id(aux), False)) == NULL) {
01771               xaux_so_Create(aux);
01772        }
01773 #endif /* WORKAROUND_XXXXXXX */
01774 
01775        aux_data = aux->service->decompose(AUX_DATA_START, p);
01776 
01777        if ((ic = aux_icid_get(aux->service->ic_id(aux), False)) == NULL) {
01778               aux->service->decompose_free(aux_data);
01779 #if defined(DEBUG_XAUX)
01780        fprintf(stderr, "[noinfo] START: unknown ic: 0x%x\n", ic);
01781 #endif /* defined(DEBUG_XAUX) */
01782               return (False);
01783        }
01784 
01785        /* workaround for "stored reference to aux_t is corrupred" problem */
01786        aux_tmp.ic = aux->ic;
01787 
01788        if ((xc = xaux_getclass_byutfname(
01789               (const CARD16 *)aux_data->aux_name,
01790               aux_data->aux_name_length)) == NULL) {
01791               aux->service->decompose_free(aux_data);
01792               return (False);
01793        }
01794 
01795        if ((xc->atom_classname == (Atom)None) &&
01796                      xaux_so_init_class_phase2(xc, aux) == False) {
01797               aux->service->decompose_free(aux_data);
01798               return (False);
01799        }
01800 
01801        if ((propbuf = (char *)malloc(SX_SIZE_HEADER)) == NULL) {
01802               aux->service->decompose_free(aux_data);
01803               return (False);
01804        }
01805 
01806 #if defined(DEBUG_XAUX)
01807        fprintf(stderr, "[%s] START: ic=0x%x\n", xc->shortname, ic);
01808        fprintf(stderr, "[%s] START: before launch extstate=%d\n",
01809               xc->shortname, xc->extstate);
01810 #endif /* defined(DEBUG_XAUX) */
01811 
01812        xc->ic = ic;
01813 
01814        if ((xc->extstate == Initial) ||
01815               (xc->extstate == ErrorTemp) ||
01816               (xc->extstate == Disconnected)) {
01817               rv = xaux_so_launch_ext(xc, ic);
01818        }
01819 
01820 #if defined(DEBUG_XAUX)
01821        fprintf(stderr, "[%s] START: after launch extstate=%d\n",
01822               xc->shortname, xc->extstate);
01823 #endif /* defined(DEBUG_XAUX) */
01824 
01825 #if defined(NOTIFY_STATE)
01826        (void)xaux_so_notify_state(xc);
01827 #endif /* defined(NOTIFY_STATE) */
01828 
01829        if ((xc->extstate != Connected) && (xc->extstate != Launched)) {
01830               aux->service->decompose_free(aux_data);
01831               return (False);
01832        }
01833 
01834        SX_PROTOVERS_MAJOR(propbuf) = XAUX_PROTOVERS_MAJOR;
01835        SX_PROTOVERS_MINOR(propbuf) = XAUX_PROTOVERS_MINOR;
01836        SX_SEQNO(propbuf) = sx_seqno++;
01837        SX_ATOM_AUX_NAME(propbuf) = xc->atom_classname;
01838        SX_INDEX(propbuf) = xc->index;
01839        SX_PRIVTYPE(propbuf) = (CARD8)XAUX_PRIVTYPE_PUBLIC;
01840        SX_AUXTYPE(propbuf) = (CARD8)AUX_DATA_START;
01841        SX_IMID(propbuf) = aux_data->im;
01842        SX_ICID(propbuf) = aux_data->ic;
01843        SX_MORESEGS(propbuf) = 1;
01844        SX_SEGNO(propbuf) = 0;
01845        SX_SEGSIZE(propbuf) = 0;
01846 
01847 #if defined(DEBUG_XAUX)
01848        fprintf(stderr, "[%s] START: im=0x%x ic=0x%x\n",
01849               xc->shortname, aux_data->im, aux_data->ic);
01850 #endif /* defined(DEBUG_XAUX) */
01851 
01852        rv = xaux_so_send_property(aux, xc,
01853               (unsigned char *)propbuf, SX_SIZE_HEADER, True);
01854 
01855        aux->service->decompose_free(aux_data);
01856 
01857        return (rv);
01858 }
01859 
01860 static Bool
01861 xaux_so_send_property_draw(
01862        aux_t         *aux,
01863        xaux_so_class_t      *xc,
01864        char          *prop)
01865 {
01866        char          *draw = SX_DATA_TOP(prop);
01867        Bool          rv;
01868        Bool          detour;
01869 
01870 #if defined(DEBUG_XAUX)
01871        if (BO_SEGNO(prop) == 0) {
01872               if (BO_DRAW_INT_COUNT(draw) > 0) {
01873                      fprintf(stderr, "[%s] DRAW: im=0x%x ic=0x%x "
01874                             "i[0]=0x%x in=%d sn=%d "
01875                             "segno=%d segsize=0x%x\n",
01876                             xc->shortname,
01877                             BO_IMID(prop), BO_ICID(prop),
01878                             *(BO_DRAW_INT_LIST(draw)),
01879                             BO_DRAW_INT_COUNT(draw),
01880                             BO_DRAW_STR_COUNT(draw),
01881                             BO_SEGNO(prop), BO_SEGSIZE(prop));
01882               } else {
01883                      fprintf(stderr, "[%s] DRAW: im=0x%x ic=0x%x "
01884                             "in=%d sn=%d "
01885                             "segno=%d segsize=0x%x\n",
01886                             xc->shortname,
01887                             BO_IMID(prop), BO_ICID(prop),
01888                             BO_DRAW_INT_COUNT(draw),
01889                             BO_DRAW_STR_COUNT(draw),
01890                             BO_SEGNO(prop), BO_SEGSIZE(prop));
01891               }
01892        } else {
01893               fprintf(stderr, "[%s] DRAW: im=0x%x ic=0x%x "
01894                             "segno=%d segsize=0x%x\n",
01895                      xc->shortname,
01896                      BO_IMID(prop), BO_ICID(prop),
01897                      BO_SEGNO(prop), BO_SEGSIZE(prop));
01898        }
01899 #endif /* defined(DEBUG_XAUX) */
01900 
01901        detour = aux->service->server(aux);
01902 
01903        rv = xaux_so_send_property(aux, xc, (unsigned char *)prop,
01904               SX_SIZE_HEADER + SX_SEGSIZE(prop),
01905               detour/* tentative */);
01906 
01907        return (True);
01908 }
01909 
01910 static Bool
01911 xaux_so_Draw(aux_t * aux, const unsigned char * p, int size)
01912 {
01913        aux_data_t *  aux_data;
01914        XPoint        point;
01915        char *        draw;
01916        xaux_so_class_t *    xc;
01917        size_t        i;
01918        int           *ip;
01919        char          *sp;
01920        Bool          rv = True;
01921        int           int_next;
01922        int           str_next;
01923        int           total_str_len;
01924        int           segno;
01925        char          *propbuf = NULL;
01926        char          *propbuftail = NULL;
01927        int           allocsz;
01928 
01929        aux_data = aux->service->decompose(AUX_DATA_DRAW, p);
01930 
01931        if ((xc = xaux_getclass_byutfname(
01932               (const CARD16 *)aux_data->aux_name,
01933               aux_data->aux_name_length)) == NULL) {
01934 #if defined(DEBUG_XAUX)
01935        fprintf(stderr, "im: 0x%x ic:0x%x get faild in so_Draw[%s]\n",
01936                      aux_data->im, aux_data->ic, xc->classname);
01937 #endif /* defined(DEBUG_XAUX) */
01938               goto discard;
01939        }
01940 
01941        /* workaround for "stored reference to aux_t is corrupred" problem */
01942        aux_tmp.ic = aux->ic;
01943 
01944        if ((xc->atom_classname == (Atom)None) &&
01945                      xaux_so_init_class_phase2(xc, aux) == False) {
01946               aux->service->decompose_free(aux_data);
01947               return (False);
01948        }
01949 
01950        if ((xc->extwin == (Window)None) && (aux->service->server(aux) == True)
01951                      && (xc->extstate != Launched)) {
01952               aux->service->decompose_free(aux_data);
01953               return (False);
01954        }
01955 
01956        for (i = 0, total_str_len = 0; i < aux_data->string_count; i++) {
01957               total_str_len += aux_data->string_list[i].length;
01958        }
01959 
01960        allocsz = SX_SIZE_HEADER + SX_SIZE_DRAW_HEADER          /* header */
01961               + (sizeof (CARD32) * aux_data->integer_count)    /* int */
01962               + total_str_len                                  /* str */
01963               + (sizeof (CARD16) * aux_data->string_count)     /* strlen */
01964               + (5 * aux_data->string_count);                  /* pad + null */
01965        
01966        if (allocsz > maxpropsz) {
01967               allocsz = maxpropsz;
01968        }
01969 
01970        for (segno = 0; ; segno++) {
01971               if (segno > 0) {
01972                      allocsz = maxpropsz;
01973               }
01974               if ((propbuf = (char *)malloc(allocsz)) == NULL) {
01975                      goto discard;
01976               }
01977               propbuftail = propbuf + allocsz;
01978        
01979               SX_PROTOVERS_MAJOR(propbuf) = XAUX_PROTOVERS_MAJOR;
01980               SX_PROTOVERS_MINOR(propbuf) = XAUX_PROTOVERS_MINOR;
01981               SX_SEQNO(propbuf) = sx_seqno;
01982               SX_ATOM_AUX_NAME(propbuf) = xc->atom_classname;
01983               SX_INDEX(propbuf) = xc->index;
01984               SX_PRIVTYPE(propbuf) = (CARD8)XAUX_PRIVTYPE_PUBLIC;
01985               SX_AUXTYPE(propbuf) = (CARD8)AUX_DATA_DRAW;
01986               SX_IMID(propbuf) = aux_data->im;
01987               SX_ICID(propbuf) = aux_data->ic;
01988               SX_MORESEGS(propbuf) = 0;
01989               SX_SEGNO(propbuf) = segno;
01990 
01991               draw = SX_DATA_TOP(propbuf);
01992 
01993               if (segno == 0) {
01994                      SX_DRAW_SOWIN(draw) = xc->sowin;
01995                      SX_DRAW_CLIENTWIN(draw) =
01996                             aux->service->client_window(aux);
01997                      SX_DRAW_FOCUSWIN(draw) = aux->service->window(aux);
01998                      aux->service->point(aux, &point);
01999                      SX_DRAW_POSX(draw) = point.x;
02000                      SX_DRAW_POSY(draw) = point.y;
02001                      SX_DRAW_INT_COUNT(draw) = aux_data->integer_count;
02002                      SX_DRAW_STR_COUNT(draw) = aux_data->string_count;
02003                      SX_DRAW_TOTAL_STR_LEN(draw) = total_str_len;
02004                      int_next = 0;
02005                      str_next = 0;
02006                      ip = (int *)SX_DRAW_INT_LIST(draw);
02007               } else {
02008                      ip = (int *)draw;
02009               }
02010 
02011               for (i = int_next; i < aux_data->integer_count; i++) {
02012                      if ((char *)(ip + 1) > propbuftail) {
02013                             /* avoid to exceed tail of buffer */
02014                             SX_MORESEGS(propbuf) = 1;
02015                             SX_SEGSIZE(propbuf) = (char *)ip - draw;
02016                             xaux_so_send_property_draw(aux, xc, propbuf);
02017 #if defined(DEBUG_XAUX)
02018 fprintf(stderr, "[%s] DRAW: sent up to integer[%d]\n", xc->shortname, i - 1);
02019 #endif /* defined(DEBUG_XAUX) */
02020                             int_next = i;
02021                             break;
02022                      }
02023                      *ip++ = aux_data->integer_list[i];
02024               }
02025 
02026               if (i < aux_data->integer_count) {
02027                      continue;
02028               }
02029 
02030               int_next = i;        /* no more int */
02031               sp = (char *)ip;     /* int array tail is str array head */
02032 
02033               for (i = str_next; i < aux_data->string_count; i++) {
02034                      size_t        len;
02035                      int           pn;
02036                      unsigned char *p;
02037                      size_t        j;
02038 
02039                      len = aux_data->string_list[i].length;
02040                      p = aux_data->string_list[i].ptr;
02041                      pn = padding[(sizeof (CARD16)
02042                             + len + sizeof (unsigned char) * 2) % 4];
02043 
02044                      if ((sp + sizeof (CARD16) + len
02045                                    + sizeof (unsigned char) * 2 + pn)
02046                                    > propbuftail) {
02047                             /* avoid to exceed tail of buffer */
02048                             if (i == str_next) {
02049                                    /* single string too long */
02050                                    goto discard;
02051                             }
02052                             SX_MORESEGS(propbuf) = 1;
02053                             SX_SEGSIZE(propbuf) = sp - draw;
02054                             xaux_so_send_property_draw(aux, xc, propbuf);
02055 #if defined(DEBUG_XAUX)
02056 fprintf(stderr, "[%s] DRAW: sent up to string[%d]\n", xc->shortname, i - 1);
02057 #endif /* defined(DEBUG_XAUX) */
02058                             str_next = i;
02059                             break;
02060                      } else {
02061                             /* put length */
02062                             *(CARD16 *)sp = len;
02063                             sp += sizeof (CARD16);
02064                             /* put string */
02065                             for (j = 0; j < len; j++) {
02066                                    *sp++ = *p++;
02067                             }
02068                             /* put UTF-16 null for termination */
02069                             *sp++ = 0U;
02070                             *sp++ = 0U;
02071                             /* put padding */
02072                             for (j = 0; j < pn; j++) {
02073                                    *sp++ = 0U;
02074                             }
02075                      }
02076               }
02077 
02078               if (i < aux_data->string_count) {
02079                      continue;
02080               }
02081 
02082               SX_MORESEGS(propbuf) = 0;
02083               SX_SEGSIZE(propbuf) = (int)(sp - draw);
02084               rv = xaux_so_send_property_draw(aux, xc, propbuf);
02085               break;
02086               /* NOTREACHED */
02087        }
02088 
02089 discard:
02090        sx_seqno++;
02091        aux->service->decompose_free(aux_data);
02092 
02093        return (rv);
02094 }
02095 
02096 static Bool
02097 xaux_so_Done(aux_t * aux, const unsigned char * p, int size)
02098 {
02099        aux_data_t *  aux_data;
02100        char          *propbuf;
02101        xaux_so_class_t *    xc;
02102        Bool          rv;
02103 
02104        aux_data = aux->service->decompose(AUX_DATA_DONE, p);
02105 
02106        if ((xc = xaux_getclass_byutfname(
02107               (const CARD16 *)aux_data->aux_name,
02108               aux_data->aux_name_length)) == NULL) {
02109               aux->service->decompose_free(aux_data);
02110               return (False);
02111        }
02112 
02113        /* workaround for "stored reference to aux_t is corrupred" problem */
02114        aux_tmp.ic = aux->ic;
02115 
02116        if ((xc->atom_classname == (Atom)None) &&
02117                      xaux_so_init_class_phase2(xc, aux) == False) {
02118               aux->service->decompose_free(aux_data);
02119               return (False);
02120        }
02121 
02122        if ((propbuf = (char *)malloc(SX_SIZE_HEADER)) == NULL) {
02123               aux->service->decompose_free(aux_data);
02124               return (False);
02125        }
02126 
02127        SX_PROTOVERS_MAJOR(propbuf) = XAUX_PROTOVERS_MAJOR;
02128        SX_PROTOVERS_MINOR(propbuf) = XAUX_PROTOVERS_MINOR;
02129        SX_SEQNO(propbuf) = sx_seqno++;
02130        SX_ATOM_AUX_NAME(propbuf) = xc->atom_classname;
02131        SX_INDEX(propbuf) = xc->index;
02132        SX_PRIVTYPE(propbuf) = (CARD8)XAUX_PRIVTYPE_PUBLIC;
02133        SX_AUXTYPE(propbuf) = (CARD8)AUX_DATA_DONE;
02134        SX_IMID(propbuf) = aux_data->im;
02135        SX_ICID(propbuf) = aux_data->ic;
02136        SX_MORESEGS(propbuf) = 0;
02137        SX_SEGNO(propbuf) = 0;
02138        SX_SEGSIZE(propbuf) = 0;
02139 
02140 #if defined(DEBUG_XAUX)
02141        fprintf(stderr, "[%s] DONE: im=0x%x ic=0x%x\n",
02142               xc->shortname, aux_data->im, aux_data->ic);
02143 #endif /* defined(DEBUG_XAUX) */
02144 
02145        rv = xaux_so_send_property(aux, xc,
02146               (unsigned char *)propbuf, SX_SIZE_HEADER,
02147               True /* tentative */);
02148 
02149        aux->service->decompose_free(aux_data);
02150 
02151        xc->ic = NULL;
02152 
02153        return (rv);
02154 }
02155 
02156 static Bool
02157 xaux_so_Switched(aux_t * aux, int im_id, int on_off)
02158 {
02159        return True;
02160 }
02161 
02162 static Bool
02163 xaux_so_Destroy(aux_t * aux)
02164 {
02165        Display *            dpy;
02166        xaux_so_class_t *    p;
02167 
02168 #if defined(WORKAROUND_XXXXXXX)
02169        if (NULL == aux) {
02170               event_filter_unregister_all();
02171               window_list_destroy_all();
02172               return True;
02173        }
02174 #endif /* WORKAROUND_XXXXXXX */
02175 
02176        dpy = aux->service->display(aux);
02177 
02178        for (p = xaux_classes; NULL != p->classname; p++) {
02179               if (None != p->sowin) {
02180                      unregister_X_filter(dpy, p->sowin,
02181                                        xaux_so_sowin_event_filter, NULL);
02182                      XDestroyWindow(dpy, p->sowin);
02183               }
02184               if (None != p->extwin) {
02185                      unregister_X_filter(dpy, p->extwin,
02186                                        xaux_so_extwin_event_filter, NULL);
02187               }
02188        }
02189 
02190        return True;
02191 }
02192 
02193 static Bool VersionQueryAux_Start(aux_t *, const unsigned char *, int size);
02194 static Bool VersionQueryAux_Draw(aux_t *, const unsigned char *, int size);
02195 static Bool VersionQueryAux_Done(aux_t *, const unsigned char *, int size);
02196 
02197 aux_method_t VersionQueryAux_methods = {
02198        xaux_so_Create,
02199        VersionQueryAux_Start,
02200        VersionQueryAux_Draw,
02201        VersionQueryAux_Done,
02202        xaux_so_Switched,
02203        xaux_so_Destroy
02204 };
02205 
02206 #define       VERSION_TAG   "(#)IM for Solaris"
02207 
02208 static Bool
02209 VersionQueryAux_elf_tryaline(
02210        char * line,
02211        int *  pmajor,
02212        int *  pminor)
02213 {
02214        char   *p;
02215        long   longval;
02216        char   *endptr;
02217 
02218        *pmajor = -1;
02219        *pminor = -1;
02220 
02221        if ((p = strstr(line, VERSION_TAG)) != NULL) {
02222               p += strlen(VERSION_TAG);
02223 
02224               /* search "/" */
02225               if ((p = strchr(p, '/')) == NULL) {
02226                      goto failed;
02227               } else {
02228                      p++;
02229               }
02230 
02231               /* get version major */
02232 #if defined(DEBUG_XAUX_DETAIL)
02233               fprintf(stderr, "trying to get version major at:\"%s\"\n", p);
02234 #endif /* defined(DEBUG_XAUX_DETAIL) */
02235               errno = 0;
02236               longval = strtol(p, &endptr, 10);
02237               if (errno != 0) {
02238                      goto failed;
02239               } else {
02240                      *pmajor = longval;
02241               }
02242               if ((endptr == NULL) || ((p = endptr + 1) == '\0')) {
02243                      goto failed;
02244               }
02245 
02246               /* get version minor */
02247 #if defined(DEBUG_XAUX_DETAIL)
02248               fprintf(stderr, "trying to get version minor at:\"%s\"\n", p);
02249 #endif /* defined(DEBUG_XAUX_DETAIL) */
02250               errno = 0;
02251               longval = strtol(p, &endptr, 10);
02252               if ((errno != 0) || p == endptr) {
02253                      goto failed;
02254               } else {
02255                      *pminor = longval;
02256               }
02257 #if defined(DEBUG_XAUX)
02258               fprintf(stderr, "major=%d minor=%d\n", *pmajor, *pminor);
02259 #endif /* defined(DEBUG_XAUX) */
02260 failed:
02261               return (False); /* not read lines further */
02262        } else {
02263               return (True); /* read lines further */
02264        }
02265 }
02266 
02267 static Bool
02268 VersionQueryAux_elf(
02269        const char *  filename,
02270        int           *pmajor,
02271        int           *pminor)
02272 {
02273 #if !defined(linux)
02274        Elf *         elf;
02275        Elf_Scn       *      scn = NULL;
02276        GElf_Shdr     shdr;
02277        GElf_Ehdr     ehdr;
02278        Elf_Data *    data;
02279        int           fd;
02280        int           c;
02281        int           cc;
02282        char *        p;
02283        Elf_Data *    cdata;
02284        Bool          terminated = False;
02285 
02286        elf_version(EV_CURRENT);
02287 
02288        if ((fd = open(filename, O_RDONLY)) == -1) {
02289 #if defined(DEBUG_XAUX_DETAIL)
02290               fprintf(stderr, "cannot open: %s\n", filename);
02291 #endif /* defined(DEBUG_XAUX_DETAIL) */
02292               return (False);
02293        }
02294 
02295        elf = elf_begin(fd, ELF_C_READ, NULL);
02296 
02297        /* get ELF header */
02298        if (gelf_getehdr(elf, &ehdr) == NULL) {
02299               perror("gelf_getehdr");
02300               goto failed;
02301        }
02302 
02303        /* get data of section which holds section name strings */
02304        if (((scn = elf_getscn(elf, ehdr.e_shstrndx)) == NULL) ||
02305                      ((data = elf_getdata(scn, NULL)) == NULL)) {
02306               goto failed;
02307        }
02308 
02309        for (scn = NULL; (scn = elf_nextscn(elf, scn)) != NULL; ) {
02310               if (gelf_getshdr(scn, &shdr) == NULL) {
02311                      perror("gelf_getshdr");
02312                      goto failed;
02313               }
02314 #if defined(DEBUG_XAUX_DETAIL)
02315               fprintf(stderr, "skipping section: %s\n",
02316                      (char *)data->d_buf + shdr.sh_name);
02317 #endif /* defined(DEBUG_XAUX_DETAIL) */
02318               if (strcmp(".comment", (char *)data->d_buf + shdr.sh_name)
02319                             == 0) {
02320                      cdata = elf_getdata(scn, NULL);
02321                      p = (char *)(cdata->d_buf);
02322                      c = 1;
02323                      while (c < shdr.sh_size) {
02324                             terminated = False;
02325                             for (cc = c; cc < shdr.sh_size; cc++) {
02326                                    if (*(p + cc) == '\0') {
02327                                           terminated = True;
02328                                    }
02329                             }
02330                             if (terminated == True) {
02331                                    if (VersionQueryAux_elf_tryaline(
02332                                                  p + c, pmajor, pminor)
02333                                                  == False) {
02334                                           break;
02335                                    }
02336                             } else {
02337               fprintf(stderr, "binary file may be corrupted: %s\n",
02338                      filename);
02339                                    goto failed;
02340                             }
02341                             c += (strlen(p + c) + 1);
02342                      }
02343                      if ((*pmajor != -1) && (*pminor != -1)) {
02344                             goto succeeded;
02345                      }
02346               }
02347        }
02348 
02349 failed:
02350        elf_end(elf);
02351        close(fd);
02352        fprintf(stderr, "cannot get version information from \"%s\"\n",
02353               filename);
02354        return (False);
02355 
02356 succeeded:
02357        elf_end(elf);
02358        close(fd);
02359 #endif /* !linux */
02360        return (True);
02361 }
02362 
02363 static Bool
02364 VersionQueryAux_get_extversion(
02365        xaux_so_class_t *    xc,
02366        int *         major,
02367        int *         minor)
02368 {
02369        char          path[MAXPATHLEN];
02370 
02371        /*
02372         * tentaive hardcoded logic
02373         * return major=1 minor=1 in case of either:
02374         *     - VersionQueryAux
02375         *     - other classes and xaux1() check returned true
02376         * otherwise, return default version.
02377         */
02378        if (strcmp(xc->classname,
02379               "com.sun.sampleja4.VersionQueryAux") == 0) {
02380                      *major = 1;
02381                      *minor = 2;
02382        } else {
02383               if (xaux_so_check_xaux1() == True) {
02384                      snprintf(path, MAXPATHLEN, "%s%d/%s",
02385                             xaux_so_extexec_path, 1, xc->extexec);
02386               } else {
02387                      snprintf(path, MAXPATHLEN, "%s/%s",
02388                             xaux_so_extexec_path, xc->extexec);
02389               }
02390 
02391               if (VersionQueryAux_elf(path, major, minor) == True) {
02392 #if defined(DEBUG_XAUX)
02393               fprintf(stderr, "[Vers] \"%s\" major=%d minor=%d (from ELF)\n",
02394                      xc->shortname, *major, *minor);
02395 #endif /* defined(DEBUG_XAUX) */
02396               } else if (access(path, X_OK) == 0) {
02397                      *major = xaux_so_default_extversion[0];
02398                      *minor = xaux_so_default_extversion[1];
02399 #if defined(DEBUG_XAUX)
02400               fprintf(stderr, "[Vers] \"%s\" major=%d minor=%d (default)\n",
02401                      xc->shortname, *major, *minor);
02402 #endif /* defined(DEBUG_XAUX) */
02403               } else {
02404                      *major = XAUX_EXTVERS_MAJOR_NOTAVAIL;
02405                      *minor = XAUX_EXTVERS_MINOR_NOTAVAIL;
02406 #if defined(DEBUG_XAUX)
02407               fprintf(stderr, "[Vers] \"%s\" major=%d minor=%d (notavail)\n",
02408                      xc->shortname, *major, *minor);
02409 #endif /* defined(DEBUG_XAUX) */
02410               }
02411        }
02412 
02413        return (True);
02414 }
02415 
02416 static Bool
02417 VersionQueryAux_send_extversion(
02418        xaux_so_class_t *    xc_vq,
02419        aux_data_t *  aux_data_vq,
02420        int           server)
02421 {
02422        int           major = 0;
02423        int           minor = 0;
02424        int           size;
02425        aux_data_t    aux_data_;
02426        aux_data_t *  aux_data = &(aux_data_);
02427        xaux_so_class_t      *xc = xaux_classes;
02428        int           nclasses = 0;
02429        int           ni;
02430        int           ns;
02431        unsigned char *      p;
02432 
02433        for (xc = xaux_classes, nclasses = 0; xc->classname != NULL; xc++) {
02434                      nclasses++;
02435        }
02436 
02437        aux_data->type = AUX_DATA_SETVALUE;
02438        aux_data->im = aux_data_vq->im;
02439        aux_data->ic = aux_data_vq->ic;
02440        aux_data->aux_index = xc_vq->index;
02441        aux_data->aux_name = (unsigned char *)xc_vq->utfname;
02442        aux_data->aux_name_length = strlen(xc_vq->classname) * sizeof(CARD16);
02443 
02444        aux_data->integer_count = (2 + (nclasses * 2) + 1);
02445        aux_data->integer_list =
02446               (int *)malloc(sizeof (int) * aux_data->integer_count);
02447        
02448        if (aux_data->integer_list == NULL) {
02449               return False;
02450        }
02451 
02452        aux_data->string_count = nclasses;
02453        aux_data->string_list = (aux_string_t *)
02454               malloc(sizeof (aux_string_t) * aux_data->string_count);
02455 
02456        if (aux_data->string_list == NULL) {
02457               free(aux_data->integer_list);
02458               return False;
02459        }
02460 
02461        ni = 0;
02462 
02463        aux_data->integer_list[ni] = 1;
02464 #if defined(DEBUG_XAUX)
02465        fprintf(stderr, "int[%d]=%d\n", ni, aux_data->integer_list[ni]);
02466 #endif /* defined(DEBUG_XAUX) */
02467        ni++;
02468 
02469        aux_data->integer_list[ni] = nclasses;
02470 #if defined(DEBUG_XAUX)
02471        fprintf(stderr, "int[%d]=%d\n", ni, aux_data->integer_list[ni]);
02472 #endif /* defined(DEBUG_XAUX) */
02473        ni++;
02474 
02475        ns = 0;
02476 
02477        for (xc = xaux_classes, nclasses = 0; xc->classname != NULL; xc++) {
02478               int    major = 0;
02479               int    minor = 0;
02480 
02481               VersionQueryAux_get_extversion(xc, &major, &minor);
02482 
02483               aux_data->integer_list[ni] = major;
02484 #if defined(DEBUG_XAUX)
02485               fprintf(stderr, "int[%d]=%d\n", ni, aux_data->integer_list[ni]);
02486 #endif /* defined(DEBUG_XAUX) */
02487               ni++;
02488 
02489               aux_data->integer_list[ni] = minor;
02490 #if defined(DEBUG_XAUX)
02491               fprintf(stderr, "int[%d]=%d\n", ni, aux_data->integer_list[ni]);
02492 #endif /* defined(DEBUG_XAUX) */
02493               ni++;
02494 
02495               aux_data->string_list[ns].length =
02496                      strlen(xc->classname) * sizeof (CARD16);
02497               aux_data->string_list[ns].ptr = (unsigned char *)(xc->utfname);
02498 #if defined(DEBUG_XAUX)
02499 {
02500        int    i;
02501 
02502        fprintf(stderr, "str[%d]=\"", ns);
02503        for (i = 0; i < aux_data->string_list[ns].length; i++) {
02504               if (aux_data->string_list[ns].ptr[i] == '\0') {
02505                      fprintf(stderr, "\\0");
02506               } else {
02507                      fprintf(stderr, "%c", aux_data->string_list[ns].ptr[i]);
02508               }
02509        }
02510        fprintf(stderr, "\"\n");
02511 }
02512 #endif /* defined(DEBUG_XAUX) */
02513               ns++;
02514        }
02515 
02516        aux_data->integer_list[ni] = server;
02517        ni++;
02518 
02519        aux_data->string_ptr = NULL;
02520 
02521        /* compose and send message to engine */
02522 
02523 /* workaround for "stored reference to aux_t is corrupred" problem */
02524 #if    !defined(DONT_SEND_VERSION)
02525        if ((p = /*ic->aux->service->*/compose(aux_data, &size)) == NULL) {
02526               return False;
02527        }
02528 #endif /* !DONT_SEND_VERSION */
02529 
02530 #if defined(DEBUG_XAUX)
02531        fprintf(stderr, "so_SetValue[VersionQueryAux]"
02532               " im:0x%x ic:0x%x ic=%d sc=%d id=%d nclasses=%d\n",
02533               aux_data->im, aux_data->ic,
02534               aux_data->integer_count,
02535               aux_data->string_count,
02536               aux_data->integer_list[0],
02537               aux_data->integer_list[1]);
02538 #endif /* defined(DEBUG_XAUX) */
02539 
02540 /* workaround for "stored reference to aux_t is corrupred" problem */
02541 #if    !defined(DONT_SEND_VERSION)
02542        /*ic->aux->service->*/aux_setvalue(/*ic->aux*/&aux_tmp, p, size);
02543 #endif /* !DONT_SEND_VERSION */
02544 
02545        free(aux_data->integer_list);
02546        free(aux_data->string_list);
02547 
02548        return True;
02549 }
02550 
02551 static Bool
02552 VersionQueryAux_Start(aux_t * aux, const unsigned char * p, int size)
02553 {
02554        aux_data_t *  aux_data;
02555        xaux_so_class_t *    xc;
02556        Bool          rv = True;
02557 
02558        aux_data = aux->service->decompose(AUX_DATA_START, p);
02559 
02560        if ((xc = xaux_getclass_byutfname(
02561               (const CARD16 *)aux_data->aux_name,
02562               aux_data->aux_name_length)) == NULL) {
02563               aux->service->decompose_free(aux_data);
02564               return False;
02565        }
02566 
02567        VersionQueryAux_send_extversion(
02568               xc, aux_data, (False == aux->service->server(aux)) ? 0 : 1);
02569 
02570 #if defined(DEBUG_XAUX)
02571        fprintf(stderr, "so_Start[VersionQueryAux] im:0x%x ic:0x%x\n",
02572               aux_data->im, aux_data->ic);
02573 #endif /* defined(DEBUG_XAUX) */
02574 
02575        aux->service->decompose_free(aux_data);
02576 
02577        return (rv);
02578 }
02579 
02580 static Bool
02581 VersionQueryAux_Draw(aux_t * aux, const unsigned char * p, int size)
02582 {
02583 #if defined(DEBUG_XAUX)
02584        fprintf(stderr, "so_Draw[VersionQueryAux]\n");
02585 #endif /* defined(DEBUG_XAUX) */
02586 
02587        return True;
02588 }
02589 
02590 static Bool
02591 VersionQueryAux_Done(aux_t * aux, const unsigned char * p, int size)
02592 {
02593 #if defined(DEBUG_XAUX)
02594        fprintf(stderr, "so_Done[VersionQueryAux]\n");
02595 #endif /* defined(DEBUG_XAUX) */
02596 
02597        return True;
02598 }