Back to index

im-sdk  12.3.91
aux_so.c
Go to the documentation of this file.
00001 /*
00002 Copyright 1990-2001 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 /*
00044  * "$Id: aux_so.c,v 1.1.1.1.2.1 2001/03/15 07:52:21 himi Exp $"
00045  */
00046 
00047 #pragma ident "@(#)aux_so.c 1.21   00/09/14 SMI"
00048 
00049 
00050 #include <stddef.h>
00051 #include <stdlib.h>
00052 #include <stdio.h>
00053 #include <sys/types.h>
00054 #include <unistd.h>
00055 #include <limits.h>
00056 
00057 #include <X11/Xmd.h>
00058 #include <X11/Xlib.h>
00059 #include <X11/Xatom.h>
00060 
00061 #include "iiimpAux.h"
00062 
00063 #include "trace_message.h"
00064 
00065 
00066 #define HASH_SIZE 137
00067 
00068 #define ME                  "aux_so"
00069 
00070 #define HTT_AUX_EXT_NAME    "htt_aux_sample_ext"
00071 #define HTT_AUX_SO_NAME            "htt_aux_sample_so"
00072 #define HTT_AUX_PROP_NAME   "htt_aux_sample_prop"
00073 #define HTT_AUX_PROP1_NAME  "htt_aux_sample_prop1"
00074 
00075 #define       AUX_EXT                     "/usr/lib/iiim/le/sampleja/aux_ext"
00076 
00077 typedef struct _aux_icid {
00078        aux_t *                     aux;
00079        int                  icid;
00080        struct _aux_icid *   prev;
00081        struct _aux_icid *   next;
00082 } aux_icid_t;
00083 
00084 
00085 static void   aux_ext_send(aux_t *, const unsigned char *, int);
00086 static void   process_property_notify(Display *, Window);
00087 static void   process_client_message(Display *, Window, XEvent *);
00088 static Bool   aux_event_filter(Display *, Window, XEvent *, XPointer);
00089 
00090 static Bool   aux_init(aux_t *);
00091 
00092 static void          aux_icid_init(void);
00093 static void          aux_icid_finish(void);
00094 static aux_icid_t *  aux_icid_get(int);
00095 static void          aux_icid_delete(int);
00096 
00097 static Bool   aux_Create(aux_t *);
00098 static Bool   aux_Start(aux_t *, const unsigned char *, int);
00099 static Bool   aux_Draw(aux_t *, const unsigned char *, int);
00100 static Bool   aux_Done(aux_t *, const unsigned char *, int);
00101 static Bool   aux_Switched(aux_t *, int, int);
00102 static Bool   aux_Destroy(aux_t *);
00103 
00104 static Bool   panel_Create(aux_t *);
00105 static Bool   panel_Start(aux_t *, const unsigned char *, int);
00106 static Bool   panel_Draw(aux_t *, const unsigned char *, int);
00107 static Bool   panel_Done(aux_t *, const unsigned char *, int);
00108 static Bool   panel_Switched(aux_t *, int, int);
00109 static Bool   panel_Destroy(aux_t *);
00110 
00111 
00112 /*
00113  * com.sun.iiim.sample.sampleja.SampleAux
00114 */
00115 static CARD16 aux_name_aux_name[] = {
00116        0x0063, 0x006f, 0x006d, 0x002e,
00117        0x0073, 0x0075, 0x006e, 0x002e,
00118        0x0069, 0x0069, 0x0069, 0x006d,
00119        0x002e, 0x0073, 0x0061, 0x006d,
00120        0x0070, 0x006c, 0x0065, 0x002e,
00121        0x0073, 0x0061, 0x006d, 0x0070,
00122        0x006c, 0x0065, 0x006a, 0x0061,
00123        0x002e, 0x0053, 0x0061, 0x006d,
00124        0x0070, 0x006c, 0x0065, 0x0041,
00125        0x0075, 0x0078,
00126 };
00127 
00128 
00129 /*
00130  * com.sun.iiim.sample.sampleja.SamplePanel
00131 */
00132 static CARD16 aux_name_panel_name[] = {
00133        0x0063, 0x006f, 0x006d, 0x002e,
00134        0x0073, 0x0075, 0x006e, 0x002e,
00135        0x0069, 0x0069, 0x0069, 0x006d,
00136        0x002e, 0x0073, 0x0061, 0x006d,
00137        0x0070, 0x006c, 0x0065, 0x002e,
00138        0x0073, 0x0061, 0x006d, 0x0070,
00139        0x006c, 0x0065, 0x006a, 0x0061,
00140        0x002e, 0x0053, 0x0061, 0x006d,
00141        0x0070, 0x006c, 0x0065, 0x0050,
00142        0x0061, 0x006e, 0x0065, 0x006c,
00143 };
00144 
00145 
00146 static aux_method_t  aux_method_aux = {
00147        aux_Create,
00148        aux_Start,
00149        aux_Draw,
00150        aux_Done,
00151        aux_Switched,
00152        aux_Destroy
00153 };
00154 
00155 
00156 static aux_method_t  aux_method_panel = {
00157        panel_Create,
00158        panel_Start,
00159        panel_Draw,
00160        panel_Done,
00161        panel_Switched,
00162        panel_Destroy
00163 };
00164 
00165 
00166 aux_dir_t     aux_dir[] = {
00167        {{sizeof (aux_name_aux_name),
00168          aux_name_aux_name},
00169         &aux_method_aux},
00170 
00171        {{sizeof (aux_name_panel_name),
00172          aux_name_panel_name},
00173         &aux_method_panel},
00174 
00175        {{0, NULL}, NULL}
00176 };
00177 
00178 
00179 static int           aux_initialized = 0;
00180 static aux_icid_t    aux_icid[HASH_SIZE];
00181 
00182 static Atom   aux_so_atom;
00183 static Atom   aux_ext_atom;
00184 static Atom   aux_prop_atom;
00185 static Atom   aux_prop1_atom;
00186 
00187 static Window aux_window;
00188 
00189 
00190 static void
00191 aux_ext_send(aux_t * aux, const unsigned char * p, int len)
00192 {
00193        Display *     display;
00194        Window        w_ext;
00195 
00196        TRACE_MESSAGE('S', (ME ":aux_ext_send: \"%.*s\" len=%d\n", len - 4, p + 4, len));
00197        
00198        display = aux->service->display(aux);
00199 
00200        if (None == (w_ext = XGetSelectionOwner(display, aux_ext_atom))) {
00201               TRACE_MESSAGE('s', (ME ":aux_ext_send: no owner of %08x (display=%08x)\n",
00202                                 aux_ext_atom, display));
00203               XChangeProperty(display, aux_window, aux_prop1_atom, XA_STRING,
00204                             8, PropModeReplace, (unsigned char *)p, len);
00205 
00206               return;
00207        }
00208 
00209        TRACE_MESSAGE('s', (ME ":aux_ext_send: owner %08x\n", w_ext));
00210 
00211        XChangeProperty(display, w_ext, aux_prop_atom, XA_STRING,
00212                      8, PropModeReplace, (unsigned char *)p, len);
00213 
00214        return;
00215 }
00216 
00217 
00218 aux_ext_client_message(aux_t * aux, int im_id, int ic_id, const int * p, int n)
00219 {
00220        Display *            display;
00221        Window               w_ext;
00222        int                  i;
00223        XClientMessageEvent  event;
00224 
00225 #if defined(ENABLE_TRACE)
00226        if (TRACE_P('S')) {
00227               TRACE_MESSAGE('S', (ME ":aux_ext_client_message:"));
00228               for (i = 0; i < n; i++) {
00229                      TRACE_MESSAGE('S', (" %08x", *(p + i)));
00230               }
00231               TRACE_MESSAGE('S', ("\n"));
00232        }
00233 #endif /* ENABLE_TRACE */
00234 
00235        if (4 < n) {
00236               n = 4;
00237        }
00238 
00239        display = aux->service->display(aux);
00240 
00241        if (None == (w_ext = XGetSelectionOwner(display, aux_ext_atom))) {
00242               TRACE_MESSAGE('s', (ME ":aux_ext_send: no owner of %08x (display=%08x)\n",
00243                                 aux_ext_atom, display));
00244               return;
00245        }
00246        TRACE_MESSAGE('s', (ME ":aux_ext_send: owner %08x\n", w_ext));
00247 
00248 
00249        event.type = ClientMessage;
00250        event.serial = 0;
00251        event.send_event = True;
00252        event.display = display;
00253        event.window = w_ext;
00254        event.message_type = aux_ext_atom;
00255        event.format = 32;
00256        event.data.s[0] = im_id;
00257        event.data.s[1] = ic_id;
00258        for (i = 0; i < n; i++) {
00259               event.data.l[i + 1] = *(p + i);
00260        }
00261        for (i++; i < 5; i++) {
00262               event.data.l[i] = 0;
00263        }
00264 
00265        XSendEvent(display, w_ext, True, 0, (XEvent *)(&event));
00266 }
00267 
00268 static void
00269 process_property_notify(Display * display, Window window)
00270 {
00271        long          long_length;
00272        Atom          actual_type_return;
00273        int           actual_format_return;
00274        unsigned long nitem_return;
00275        unsigned long bytes_after_return;
00276        unsigned char *      prop_return;
00277        int           r;
00278        int           imid;
00279        int           icid;
00280        aux_icid_t *  ic;
00281        int           size;
00282        aux_data_t *  aux_data;
00283        unsigned char *      p;
00284        unsigned char buf[1024];
00285        const char *  inbuf;
00286        size_t        inbytesleft;
00287        char *        outbuf;
00288        size_t        outbytesleft;
00289 
00290        TRACE_MESSAGE('P', (ME ":process_property_notify: %08x %08x %08x\n",
00291                          display, window, aux_prop_atom));
00292 
00293        r = XGetWindowProperty(display, window,
00294                             aux_prop_atom, 0, INT_MAX, False,
00295                             AnyPropertyType, &actual_type_return,
00296                             &actual_format_return, &nitem_return,
00297                             &bytes_after_return, &prop_return);
00298        if (Success != r) {
00299               return;
00300        }
00301 
00302        imid = ((*(prop_return + 0) << 8) +
00303               (*(prop_return + 1) << 0));
00304        icid = ((*(prop_return + 2) << 8) +
00305               (*(prop_return + 3) << 0));
00306 
00307        TRACE_MESSAGE('P', (ME ":process_property_notify: imid=%d icid=%d \"%.*s\"\n",
00308                          imid, icid, nitem_return - 4, prop_return + 4));
00309 
00310        ic = aux_icid_get(icid);
00311 
00312        if (NULL == ic->aux) {
00313               TRACE_MESSAGE('P', (ME ":process_property_notify: no aux\n"));
00314               XFree(prop_return);
00315               return;
00316        }
00317 
00318        aux_data = (aux_data_t *)malloc(sizeof (aux_data_t));
00319        aux_data->type = AUX_DATA_SETVALUE;
00320        aux_data->im = imid;
00321        aux_data->ic = icid;
00322        aux_data->aux_index = 0;
00323        aux_data->aux_name = (unsigned char *)aux_name_aux_name;
00324        aux_data->aux_name_length = (sizeof (aux_name_aux_name));
00325 
00326        aux_data->integer_count = 2;
00327        aux_data->integer_list = (int *)malloc(2 * (sizeof (int)));
00328        *(aux_data->integer_list + 0) = aux_data->im;
00329        *(aux_data->integer_list + 1) = aux_data->ic;
00330 
00331        aux_data->string_count = 2;
00332        aux_data->string_list =
00333               (aux_string_t *)malloc(2 * (sizeof (aux_string_t)));
00334 
00335        inbuf = (const char *)(prop_return + 4);
00336        inbytesleft = (nitem_return - 4);
00337        outbuf = (char *)buf;
00338        outbytesleft = (sizeof (buf));
00339        ic->aux->service->mb_utf16(&inbuf, &inbytesleft,
00340                                &outbuf, &outbytesleft);
00341 
00342        (aux_data->string_list + 0)->ptr = buf;
00343        (aux_data->string_list + 0)->length = ((sizeof (buf)) - outbytesleft);
00344 
00345        (aux_data->string_list + 1)->ptr = buf;
00346        (aux_data->string_list + 1)->length = ((sizeof (buf)) - outbytesleft);
00347 #if 0
00348        (aux_data->string_list + 1)->ptr = (prop_return + 4);
00349        (aux_data->string_list + 1)->length = ((nitem_return - 4) -
00350                                           (nitem_return % 2));
00351 #endif /* 0 */
00352 
00353        aux_data->string_ptr = NULL;
00354 
00355        p = ic->aux->service->compose(aux_data, &size);
00356 
00357 #if defined(ENABLE_TRACE)
00358        if (TRACE_P('p')) {
00359               int    i;
00360               int    j;
00361               int    k;
00362               TRACE_MESSAGE('p', ("process_property_notify: len=%d\n", size));
00363               for (i = 0, k = 0; i < size; i += 4) {
00364                      for (j = 0; j < 4; j++) {
00365                             TRACE_MESSAGE('p', ("%02x", *(p + i + j)));
00366                      }
00367                      if (7 == k) {
00368                             TRACE_MESSAGE('p', ("\n"));
00369                             k = 0;
00370                      } else {
00371                             TRACE_MESSAGE('p', (" "));
00372                             k += 1;
00373                      }
00374               }
00375               TRACE_MESSAGE('p', ("\n"));
00376        }
00377 #endif /* ENABLE_TRACE */
00378 
00379        ic->aux->service->aux_setvalue(ic->aux, p, size);
00380 
00381        free(p);
00382        free(aux_data->string_list);
00383        free(aux_data->integer_list);
00384        free(aux_data);
00385        XFree(prop_return);
00386 
00387        return;
00388 }
00389 
00390 
00391 static void
00392 process_client_message(Display * display, Window window, XEvent * event)
00393 {
00394        XClientMessageEvent *       message;
00395        int                  imid;
00396        int                  icid;
00397 
00398        message = (XClientMessageEvent *)event;
00399 
00400        imid = ((*(message->data.b + 0) << 8) +
00401               (*(message->data.b + 1) << 0));
00402        icid = ((*(message->data.b + 2) << 8) +
00403               (*(message->data.b + 3) << 0));
00404 
00405        if (message->message_type == aux_so_atom) {
00406               TRACE_MESSAGE('M',
00407                            (ME ":process_client_message: %08x %08x %d\n",
00408                             display, window, message->data.l[0]));
00409               TRACE_MESSAGE('M',
00410                            (ME ":process_client_message: exiting...\n"));
00411               exit(0);
00412        }
00413               
00414        switch (message->message_type) {
00415        case XA_INTEGER:
00416               TRACE_MESSAGE('M',
00417                            (ME ":process_client_message: %d %d %d\n",
00418                             display, window, message->data.l[0]));
00419               break;
00420        case XA_STRING:
00421               TRACE_MESSAGE('M',
00422                            (ME ":process_client_message: d=%08x w=%08x im=%d ic=%d %s\n",
00423                             display, window, imid, icid, message->data.b + 4));
00424               break;
00425        }
00426 
00427        return;
00428 }
00429 
00430 
00431 static Bool
00432 aux_event_filter(
00433        Display *     display,
00434        Window        window,
00435        XEvent *      event,
00436        XPointer      pointer)
00437 {
00438        switch (event->type) {
00439        case PropertyNotify:
00440               if (aux_prop_atom != ((XPropertyEvent *)event)->atom) {
00441                      return False;
00442               }
00443               process_property_notify(display, window);
00444               return True;
00445               break;
00446        case ClientMessage:
00447               process_client_message(display, window, event);
00448               return True;
00449               break;
00450        }
00451        return False;
00452 }
00453 
00454 
00455 static Bool
00456 aux_init(aux_t * aux)
00457 {
00458        Display *     display;
00459 
00460        TRACE_MESSAGE('I', (ME ":aux_init: display = %08x\n", display));
00461 
00462        display = aux->service->display(aux);
00463 
00464        aux_ext_atom = XInternAtom(display, HTT_AUX_EXT_NAME, False);
00465        aux_so_atom = XInternAtom(display, HTT_AUX_SO_NAME, False);
00466        aux_prop_atom = XInternAtom(display, HTT_AUX_PROP_NAME, False);
00467        aux_prop1_atom = XInternAtom(display, HTT_AUX_PROP1_NAME, False);
00468 
00469        if (None != XGetSelectionOwner(display, aux_so_atom)) {
00470               TRACE_MESSAGE('I', (ME ":aux_init: aux_so already exists\n"));
00471               return False;
00472        }
00473        aux_window = XCreateSimpleWindow(display, RootWindow(display, 0),
00474                                  0, 0, 1, 1, 0, 0, 0);
00475 
00476        TRACE_MESSAGE('I', (ME ":aux_init: window = %08x\n", aux_window));
00477 
00478        if (None != XGetSelectionOwner(display, aux_so_atom)) {
00479               TRACE_MESSAGE('I', (ME ":aux_init: aux_so already exists (0)\n"));
00480               return False;
00481        }
00482        XSetSelectionOwner(display, aux_so_atom, aux_window, CurrentTime);
00483        if (aux_window != XGetSelectionOwner(display, aux_so_atom)) {
00484               TRACE_MESSAGE('I', (ME ":aux_init: aux_so already exists (1)\n"));
00485               return False;
00486        }
00487 
00488        XSelectInput(display, aux_window, PropertyChangeMask);
00489 
00490        aux->service->register_X_filter(display, aux_window,
00491                                    PropertyNotify, PropertyNotify,
00492                                    aux_event_filter, NULL);
00493 
00494        aux->service->register_X_filter(display, aux_window,
00495                                    ClientMessage, ClientMessage,
00496                                    aux_event_filter, NULL);
00497 }
00498 
00499 
00500 static void
00501 aux_icid_init(void)
00502 {
00503        int    i;
00504 
00505        for (i = 0; i < HASH_SIZE; i++) {
00506               aux_icid[i].icid = (-1);
00507        }
00508 }
00509 
00510 
00511 static void
00512 aux_icid_finish(void)
00513 {
00514        int           i;
00515        aux_icid_t *  p0;
00516        aux_icid_t *  p1;
00517 
00518        for (i = 0; i < HASH_SIZE; i++) {
00519               p0 = aux_icid[i].next;
00520 
00521               for (; NULL != p0; p0 = p1) {
00522                      free(p0);
00523                      p1 = p0->next;
00524               }
00525        }
00526 }
00527 
00528 
00529 static aux_icid_t *
00530 aux_icid_get(int icID)
00531 {
00532        int           hash_value;
00533        aux_icid_t *  p;
00534 
00535        hash_value = (icID % HASH_SIZE);
00536 
00537        p = &(aux_icid[hash_value]);
00538 
00539        if ((-1) == p->icid) {
00540               p->icid = icID;
00541               return p;
00542        }
00543 
00544        for (; NULL != p; p = p->next) {
00545               if (icID == p->icid) {
00546                      return p;
00547               }
00548               if (NULL == p->next) {
00549                      p->next = malloc(sizeof (aux_icid_t));
00550                      if (NULL == p->next) {
00551                             return NULL;
00552                      }
00553                      memset(p->next, 0, (sizeof (aux_icid_t)));
00554                      p->next->prev = p;
00555                      return p->next;
00556               }
00557        }
00558        return NULL;  /* never comes here */
00559 }
00560 
00561 
00562 static void
00563 aux_icid_delete(int icID)
00564 {
00565        aux_icid_t *  p;
00566 
00567        p = aux_icid_get(icID);
00568        if (NULL == p) {
00569               return;
00570        }
00571        if (NULL != p->prev) {
00572               p->prev->next = p->next;
00573               free(p);
00574        }
00575 }
00576 
00577 
00578 static Bool
00579 aux_Create(aux_t * aux)
00580 {
00581        int           i;
00582        pid_t         pid;
00583        aux_icid_t *  aux_icid;
00584 
00585        TRACE_MESSAGE_INIT("TRACE_AUX_SO");
00586 
00587        TRACE_MESSAGE('X', (ME ":aux_Create\n"));
00588 
00589        if (0 == aux_initialized) {
00590               aux_icid_init();
00591        }
00592 
00593        if (NULL == (aux_icid = aux_icid_get(aux->service->ic_id(aux)))) {
00594               return False;
00595        }
00596        aux_icid->aux = aux;
00597        if (0 == aux_initialized) {
00598               aux_init(aux);
00599        }
00600 
00601        aux_initialized = 1;
00602 
00603 #if 0
00604        aux->service->data_set(aux, im_id,(void *)aux_icid);
00605 #endif /* 0 */
00606 
00607        pid = fork1();
00608        if ((pid_t)(-1) == pid) {
00609               return False;
00610        } else if (0 == pid) {
00611               execl(AUX_EXT, "aux", "-name", "aux", NULL);
00612               _exit(1);
00613        } else {
00614               return True;
00615        }
00616 }
00617 
00618 
00619 static Bool
00620 aux_Start(aux_t * aux, const unsigned char * p, int size)
00621 {
00622        TRACE_MESSAGE('X', (ME ":aux_Start: size = %d\n", size));
00623        return True;
00624 }
00625 
00626 
00627 static Bool
00628 aux_Draw(aux_t * aux, const unsigned char * p, int size)
00629 {
00630        aux_data_t *  aux_data;
00631        char *        string_ptr;
00632        char          string_buf[1024 * 128];
00633        int           string_len;
00634        Window        w;
00635        XPoint        point;
00636 
00637        TRACE_MESSAGE('X', (ME ":aux_Draw: im=%d ic=%d size = %d\n",
00638                          aux->service->im_id(aux),
00639                          aux->service->ic_id(aux),
00640                          size));
00641 
00642        *((CARD16 *)(string_buf + 0)) = aux->service->im_id(aux);
00643        *((CARD16 *)(string_buf + 2)) = aux->service->ic_id(aux);
00644        string_ptr = (string_buf + 4);
00645        string_len = 4;
00646 
00647        w = aux->service->window(aux);
00648        aux->service->point_caret(aux, &point);
00649 
00650        TRACE_MESSAGE('D', (ME ":aux_Draw: w=%08x x=%d y=%d\n", w, point.x, point.y));
00651 
00652        aux_data = aux->service->decompose(AUX_DATA_DRAW, p);
00653 
00654 #if defined(ENABLE_TRACE)
00655        if (TRACE_P('D')) {
00656               char          aux_name;
00657               const char *  inbuf;
00658               size_t        inbytesleft;
00659               char *        outbuf;
00660               size_t        outbytesleft;
00661               char          buf[1024];
00662 
00663               TRACE_MESSAGE('D', (ME ":aux_Draw: aux_index = %d\n",
00664                                 aux_data->aux_index));
00665               inbuf = (char *)(aux_data->aux_name);
00666               inbytesleft = aux_data->aux_name_length;
00667               outbuf = buf;
00668               outbytesleft = (sizeof (buf));
00669               aux->service->utf16_mb(&inbuf, &inbytesleft,
00670                                    &outbuf, &outbytesleft);
00671               TRACE_MESSAGE('D', (ME ":aux_Draw: aux_name = \"%.*s\"\n",
00672                                 (sizeof (buf)) - outbytesleft, buf));
00673        }
00674 #endif /* ENABLE_TRACE */
00675 
00676        do {
00677               int           i;
00678               int           int_buf[4];
00679               int           im_id;
00680               int           ic_id;
00681 
00682               int_buf[0] = w;
00683               int_buf[1] = point.x;
00684               int_buf[2] = point.y;
00685 
00686               TRACE_MESSAGE('D', (ME ":aux_Draw: client_message: %d %d %x %d %d\n",
00687                                 aux->service->im_id(aux),
00688                                 aux->service->ic_id(aux),
00689                                 w, point.x, point.y));
00690                                 
00691               aux_ext_client_message(aux, 
00692                                    aux->service->im_id(aux),
00693                                    aux->service->ic_id(aux),
00694                                    int_buf, 3);
00695        } while (0);
00696 
00697        if (0 < aux_data->integer_count) {
00698               int    i;
00699               TRACE_MESSAGE('D', (ME ":aux_Draw: integer_list[%d] =",
00700                                 aux_data->integer_count));
00701               for (i = 0; i < aux_data->integer_count; i++) {
00702                      TRACE_MESSAGE('D',
00703                                   (" %d", *(aux_data->integer_list + i)));
00704               }
00705               TRACE_MESSAGE('D', ("\n"));
00706        } else {
00707               TRACE_MESSAGE('D',
00708                            (ME ":aux_Draw: integer_count = 0\n"));
00709        }
00710        if (0 < aux_data->string_count) {
00711               int    i;
00712               for (i = 0; i < aux_data->string_count; i++) {
00713                      const char *  inbuf;
00714                      size_t        inbytesleft;
00715                      char *        outbuf;
00716                      size_t        outbytesleft;
00717                      int           j;
00718 
00719                      inbuf = (char *)((aux_data->string_list + i)->ptr);
00720                      inbytesleft = (aux_data->string_list + i)->length;
00721                      outbuf = string_ptr;
00722                      outbytesleft = ((sizeof (string_buf)) - string_len);
00723 
00724                      aux->service->utf16_mb(&inbuf, &inbytesleft,
00725                                           &outbuf, &outbytesleft);
00726 #if defined(ENABLE_TRACE)
00727                      j = (((sizeof (string_buf)) - string_len) - outbytesleft);
00728                      TRACE_MESSAGE('D',
00729                                   (ME ":aux_Draw: "
00730                                    "*(string_list + %d) = \"%.*s\" len=%d\n",
00731                                    i, j, string_ptr, j));
00732 #endif /* ENABLE_TRACE */
00733                      string_len = ((sizeof (string_buf)) - outbytesleft);
00734                      string_ptr = (string_buf + string_len);
00735                      switch (*(string_ptr - 1)) {
00736                      case '\0':
00737                             *(string_ptr - 1) = ' ';
00738                             break;
00739                      case ' ':
00740                             break;
00741                      default:
00742                             *string_ptr = ' ';
00743                             string_ptr += 1;
00744                             string_len += 1;
00745                             break;
00746                      }
00747               }
00748        } else {
00749               TRACE_MESSAGE('D',
00750                            (ME ":aux_Draw: string_count = 0\n"));
00751        }
00752 
00753        if (0 < string_len) {
00754               aux_ext_send(aux, (unsigned char *)string_buf, string_len);
00755        }
00756 
00757        aux->service->decompose_free(aux_data);
00758 
00759        return True;
00760 }
00761 
00762 
00763 static Bool
00764 aux_Done(aux_t * aux, const unsigned char * p, int size)
00765 {
00766        TRACE_MESSAGE('X', (ME ":aux_Done: size = %d\n", size));
00767        return True;
00768 }
00769 
00770 
00771 static Bool
00772 aux_Switched(aux_t * aux, int im_id, int on_off)
00773 {
00774        TRACE_MESSAGE('X', (ME ":aux_Switched im_id = %d %s\n",
00775                          im_id, ((1 == on_off) ? "on" : "off")));
00776 
00777        return True;
00778 }
00779 
00780 
00781 static Bool
00782 aux_Destroy(aux_t * aux)
00783 {
00784        TRACE_MESSAGE('X', (ME ":aux_Destroy\n"));
00785 
00786        return True;
00787 }
00788 
00789 
00790 
00791 #define HTT_PANEL_EXT_NAME  "htt_panel_sample_ext"
00792 #define HTT_PANEL_SO_NAME   "htt_panel_sample_so"
00793 #define HTT_PANEL_PROP_NAME "htt_panel_sample_prop"
00794 #define HTT_PANEL_PROP1_NAME       "htt_panel_sample_prop1"
00795 
00796 static void   panel_ext_send(aux_t *, const unsigned char *, int);
00797 static void   panel_process_property_notify(Display *, Window);
00798 static void   panel_process_client_message(Display *, Window, XEvent *);
00799 static Bool   panel_event_filter(Display *, Window, XEvent *, XPointer);
00800 
00801 static Bool   panel_init(aux_t *);
00802 
00803 static void          panel_icid_init(void);
00804 static void          panel_icid_finish(void);
00805 static aux_icid_t *  panel_icid_get(int);
00806 static void          panel_icid_delete(int);
00807 
00808 static int           panel_initialized = 0;
00809 static aux_icid_t    panel_icid[HASH_SIZE];
00810 
00811 static Atom   panel_so_atom;
00812 static Atom   panel_ext_atom;
00813 static Atom   panel_prop_atom;
00814 static Atom   panel_prop1_atom;
00815 
00816 static Window panel_window;
00817 
00818 
00819 static void
00820 panel_ext_send(aux_t * aux, const unsigned char * p, int len)
00821 {
00822        Display *     display;
00823        Window        w_ext;
00824 
00825        TRACE_MESSAGE('S', (ME ":panel_ext_send: \"%.*s\" len=%d\n", len - 4, p + 4, len));
00826        
00827        display = aux->service->display(aux);
00828 
00829        if (None == (w_ext = XGetSelectionOwner(display, panel_ext_atom))) {
00830               TRACE_MESSAGE('s', (ME ":panel_ext_send: no owner of %08x (display=%08x)\n",
00831                                 panel_ext_atom, display));
00832 
00833               XChangeProperty(display, panel_window, panel_prop1_atom, XA_STRING,
00834                             8, PropModeReplace, (unsigned char *)p, len);
00835 
00836               return;
00837        }
00838 
00839        TRACE_MESSAGE('s', (ME ":panel_ext_send: owner %08x\n", w_ext));
00840 
00841        XChangeProperty(display, w_ext, panel_prop_atom, XA_STRING,
00842                      8, PropModeReplace, (unsigned char *)p, len);
00843 
00844        return;
00845 }
00846 
00847 
00848 static void
00849 panel_process_property_notify(Display * display, Window window)
00850 {
00851        long          long_length;
00852        Atom          actual_type_return;
00853        int           actual_format_return;
00854        unsigned long nitem_return;
00855        unsigned long bytes_after_return;
00856        unsigned char *      prop_return;
00857        int           r;
00858        int           imid;
00859        int           icid;
00860        aux_icid_t *  ic;
00861        int           size;
00862        aux_data_t *  aux_data;
00863        unsigned char *      p;
00864        unsigned char buf[1024];
00865        const char *  inbuf;
00866        size_t        inbytesleft;
00867        char *        outbuf;
00868        size_t        outbytesleft;
00869 
00870        TRACE_MESSAGE('P', (ME ":panel_process_property_notify: %08x %08x %08x\n",
00871                          display, window, panel_prop_atom));
00872 
00873        r = XGetWindowProperty(display, window,
00874                             panel_prop_atom, 0, INT_MAX, False,
00875                             AnyPropertyType, &actual_type_return,
00876                             &actual_format_return, &nitem_return,
00877                             &bytes_after_return, &prop_return);
00878        if (Success != r) {
00879               return;
00880        }
00881 
00882        imid = ((*(prop_return + 0) << 8) +
00883               (*(prop_return + 1) << 0));
00884        icid = ((*(prop_return + 2) << 8) +
00885               (*(prop_return + 3) << 0));
00886 
00887        TRACE_MESSAGE('P', (ME ":panel_process_property_notify: imid=%d icid=%d \"%s\"\n",
00888                          imid, icid, prop_return + 4));
00889 
00890        ic = panel_icid_get(icid);
00891 
00892        if (NULL == ic->aux) {
00893               XFree(prop_return);
00894               return;
00895        }
00896 
00897        aux_data = (aux_data_t *)malloc(sizeof (aux_data_t));
00898        aux_data->type = AUX_DATA_SETVALUE;
00899        aux_data->im = imid;
00900        aux_data->ic = icid;
00901        aux_data->aux_index = 0;
00902        aux_data->aux_name = (unsigned char *)aux_name_panel_name;
00903        aux_data->aux_name_length = (sizeof (aux_name_panel_name));
00904 
00905        aux_data->integer_count = 2;
00906        aux_data->integer_list = (int *)malloc(2 * (sizeof (int)));
00907        *(aux_data->integer_list + 0) = aux_data->im;
00908        *(aux_data->integer_list + 1) = aux_data->ic;
00909 
00910        aux_data->string_count = 2;
00911        aux_data->string_list =
00912               (aux_string_t *)malloc(2 * (sizeof (aux_string_t)));
00913 
00914        inbuf = (const char *)(prop_return + 4);
00915        inbytesleft = (nitem_return - 4);
00916        outbuf = (char *)buf;
00917        outbytesleft = (sizeof (buf));
00918        ic->aux->service->mb_utf16(&inbuf, &inbytesleft,
00919                                &outbuf, &outbytesleft);
00920 
00921        (aux_data->string_list + 0)->ptr = buf;
00922        (aux_data->string_list + 0)->length = ((sizeof (buf)) - outbytesleft);
00923 
00924        (aux_data->string_list + 1)->ptr = buf;
00925        (aux_data->string_list + 1)->length = ((sizeof (buf)) - outbytesleft);
00926 
00927 #if 0
00928        (aux_data->string_list + 1)->ptr = (prop_return + 4);
00929        (aux_data->string_list + 1)->length = (nitem_return - 4);
00930 #endif /* 0 */
00931 
00932        aux_data->string_ptr = NULL;
00933 
00934        p = ic->aux->service->compose(aux_data, &size);
00935 
00936 #if defined(ENABLE_TRACE)
00937        if (TRACE_P('p')) {
00938               int    i;
00939               int    j;
00940               int    k;
00941               TRACE_MESSAGE('p', ("panel_process_property_notify: len=%d\n", size));
00942               for (i = 0, k = 0; i < size; i += 4) {
00943                      for (j = 0; j < 4; j++) {
00944                             TRACE_MESSAGE('p', ("%02x", *(p + i + j)));
00945                      }
00946                      if (7 == k) {
00947                             TRACE_MESSAGE('p', ("\n"));
00948                             k = 0;
00949                      } else {
00950                             TRACE_MESSAGE('p', (" "));
00951                             k += 1;
00952                      }
00953               }
00954               TRACE_MESSAGE('p', ("\n"));
00955        }
00956 #endif /* ENABLE_TRACE */
00957 
00958        ic->aux->service->aux_setvalue(ic->aux, p, size);
00959 
00960        free(p);
00961        free(aux_data->string_list);
00962        free(aux_data->integer_list);
00963        free(aux_data);
00964        XFree(prop_return);
00965 
00966        return;
00967 }
00968 
00969 
00970 static void
00971 panel_process_client_message(Display * display, Window window, XEvent * event)
00972 {
00973        XClientMessageEvent *       message;
00974        int                  imid;
00975        int                  icid;
00976 
00977        message = (XClientMessageEvent *)event;
00978 
00979        imid = ((*(message->data.b + 0) << 8) +
00980               (*(message->data.b + 1) << 0));
00981        icid = ((*(message->data.b + 2) << 8) +
00982               (*(message->data.b + 3) << 0));
00983 
00984        if (message->message_type == panel_so_atom) {
00985               TRACE_MESSAGE('M',
00986                            (ME ":process_client_message: %08x %08x %d\n",
00987                             display, window, message->data.l[0]));
00988               TRACE_MESSAGE('M',
00989                            (ME ":process_client_message: exiting...\n"));
00990               exit(0);
00991        }
00992               
00993        switch (message->message_type) {
00994        case XA_INTEGER:
00995               TRACE_MESSAGE('M',
00996                            (ME ":panel_process_client_message: %08x %08x %d\n",
00997                             display, window, message->data.l[0]));
00998               break;
00999        case XA_STRING:
01000               TRACE_MESSAGE('M',
01001                            (ME ":panel_process_client_message: d=%08x w=%08x im=%d ic=%d %s\n",
01002                             display, window, imid, icid, message->data.b + 4));
01003               break;
01004        }
01005 
01006        return;
01007 }
01008 
01009 
01010 static Bool
01011 panel_event_filter(
01012        Display *     display,
01013        Window        window,
01014        XEvent *      event,
01015        XPointer      pointer)
01016 {
01017        switch (event->type) {
01018        case PropertyNotify:
01019               if (panel_prop_atom != ((XPropertyEvent *)event)->atom) {
01020                      return False;
01021               }
01022               panel_process_property_notify(display, window);
01023               return True;
01024               break;
01025        case ClientMessage:
01026               panel_process_client_message(display, window, event);
01027               return True;
01028               break;
01029        }
01030        return False;
01031 }
01032 
01033 
01034 static Bool
01035 panel_init(aux_t * aux)
01036 {
01037        Display *     display;
01038 
01039        TRACE_MESSAGE('I', (ME ":panel_init: display = %08x\n", display));
01040 
01041        display = aux->service->display(aux);
01042 
01043        panel_ext_atom = XInternAtom(display, HTT_PANEL_EXT_NAME, False);
01044        panel_so_atom = XInternAtom(display, HTT_PANEL_SO_NAME, False);
01045        panel_prop_atom = XInternAtom(display, HTT_PANEL_PROP_NAME, False);
01046        panel_prop1_atom = XInternAtom(display, HTT_PANEL_PROP1_NAME, False);
01047 
01048        if (None != XGetSelectionOwner(display, panel_so_atom)) {
01049               TRACE_MESSAGE('I', (ME ":panel_init: panel_so already exists\n"));
01050               return False;
01051        }
01052        panel_window = XCreateSimpleWindow(display, RootWindow(display, 0),
01053                                  0, 0, 1, 1, 0, 0, 0);
01054 
01055        TRACE_MESSAGE('I', (ME ":panel_init: window = %08x\n", panel_window));
01056 
01057        if (None != XGetSelectionOwner(display, panel_so_atom)) {
01058               TRACE_MESSAGE('I', (ME ":panel_init: panel_so already exists (0)\n"));
01059               return False;
01060        }
01061        XSetSelectionOwner(display, panel_so_atom, panel_window, CurrentTime);
01062        if (panel_window != XGetSelectionOwner(display, panel_so_atom)) {
01063               TRACE_MESSAGE('I', (ME ":panel_init: panel_so already exists (1)\n"));
01064               return False;
01065        }
01066 
01067        XSelectInput(display, panel_window, PropertyChangeMask);
01068 
01069        aux->service->register_X_filter(display, panel_window,
01070                                    PropertyNotify, PropertyNotify,
01071                                    panel_event_filter, NULL);
01072 
01073        aux->service->register_X_filter(display, panel_window,
01074                                    ClientMessage, ClientMessage,
01075                                    panel_event_filter, NULL);
01076 }
01077 
01078 
01079 static void
01080 panel_icid_init(void)
01081 {
01082        int    i;
01083 
01084        for (i = 0; i < HASH_SIZE; i++) {
01085               panel_icid[i].icid = (-1);
01086        }
01087 }
01088 
01089 
01090 static void
01091 panel_icid_finish(void)
01092 {
01093        int           i;
01094        aux_icid_t *  p0;
01095        aux_icid_t *  p1;
01096 
01097        for (i = 0; i < HASH_SIZE; i++) {
01098               p0 = panel_icid[i].next;
01099 
01100               for (; NULL != p0; p0 = p1) {
01101                      free(p0);
01102                      p1 = p0->next;
01103               }
01104        }
01105 }
01106 
01107 
01108 static aux_icid_t *
01109 panel_icid_get(int icID)
01110 {
01111        int           hash_value;
01112        aux_icid_t *  p;
01113 
01114        hash_value = (icID % HASH_SIZE);
01115 
01116        p = &(panel_icid[hash_value]);
01117 
01118        if ((-1) == p->icid) {
01119               p->icid = icID;
01120               return p;
01121        }
01122 
01123        for (; NULL != p; p = p->next) {
01124               if (icID == p->icid) {
01125                      return p;
01126               }
01127               if (NULL == p->next) {
01128                      p->next = malloc(sizeof (aux_icid_t));
01129                      if (NULL == p->next) {
01130                             return NULL;
01131                      }
01132                      memset(p->next, 0, (sizeof (aux_icid_t)));
01133                      p->next->prev = p;
01134                      return p->next;
01135               }
01136        }
01137        return NULL;  /* never comes here */
01138 }
01139 
01140 
01141 static void
01142 panel_icid_delete(int icID)
01143 {
01144        aux_icid_t *  p;
01145 
01146        p = panel_icid_get(icID);
01147        if (NULL == p) {
01148               return;
01149        }
01150        if (NULL != p->prev) {
01151               p->prev->next = p->next;
01152               free(p);
01153        }
01154 }
01155 
01156 
01157 static Bool
01158 panel_Create(aux_t * aux)
01159 {
01160        int           i;
01161        pid_t         pid;
01162        aux_icid_t *  aux_icid;
01163 
01164        TRACE_MESSAGE_INIT("TRACE_AUX_SO");
01165 
01166        TRACE_MESSAGE('X', (ME ":panel_Create\n"));
01167 
01168        if (0 == panel_initialized) {
01169               panel_icid_init();
01170        }
01171 
01172        if (NULL == (aux_icid = panel_icid_get(aux->service->ic_id(aux)))) {
01173               return False;
01174        }
01175        aux_icid->aux = aux;
01176        if (0 == panel_initialized) {
01177               panel_init(aux);
01178        }
01179 
01180        panel_initialized = 1;
01181 
01182 #if 0
01183        aux->service->data_set(aux, im_id,(void *)aux_icid);
01184 #endif /* 0 */
01185 
01186        pid = fork1();
01187        if ((pid_t)(-1) == pid) {
01188               return False;
01189        } else if (0 == pid) {
01190               execl(AUX_EXT, "panel", "-name", "panel", NULL);
01191               _exit(1);
01192        } else {
01193               return True;
01194        }
01195 }
01196 
01197 
01198 static Bool
01199 panel_Start(aux_t * aux, const unsigned char * p, int size)
01200 {
01201        TRACE_MESSAGE('X', (ME ":panel_Start: size = %d\n", size));
01202        return True;
01203 }
01204 
01205 
01206 static Bool
01207 panel_Draw(aux_t * aux, const unsigned char * p, int size)
01208 {
01209        aux_data_t *  aux_data;
01210        char *        string_ptr;
01211        char          string_buf[1024 * 128];
01212        int           string_len;
01213        Window        w;
01214        XPoint        point;
01215 
01216        TRACE_MESSAGE('X', (ME ":panel_Draw: im=%d ic=%d size = %d\n",
01217                          aux->service->im_id(aux),
01218                          aux->service->ic_id(aux),
01219                          size));
01220 
01221        *((CARD16 *)(string_buf + 0)) = aux->service->im_id(aux);
01222        *((CARD16 *)(string_buf + 2)) = aux->service->ic_id(aux);
01223        string_ptr = (string_buf + 4);
01224        string_len = 4;
01225 
01226        w = aux->service->window(aux);
01227        aux->service->point(aux, &point);
01228 
01229        TRACE_MESSAGE('D', (ME ":panel_Draw: w=%08x x=%d y=%d\n", w, point.x, point.y));
01230 
01231        aux_data = aux->service->decompose(AUX_DATA_DRAW, p);
01232 
01233 #if defined(ENABLE_TRACE)
01234        if (TRACE_P('D')) {
01235               char          aux_name;
01236               const char *  inbuf;
01237               size_t        inbytesleft;
01238               char *        outbuf;
01239               size_t        outbytesleft;
01240               char          buf[1024];
01241 
01242               TRACE_MESSAGE('D', (ME ":panel_Draw: aux_index = %d\n",
01243                                 aux_data->aux_index));
01244               inbuf = (char *)(aux_data->aux_name);
01245               inbytesleft = aux_data->aux_name_length;
01246               outbuf = buf;
01247               outbytesleft = (sizeof (buf));
01248               aux->service->utf16_mb(&inbuf, &inbytesleft,
01249                                    &outbuf, &outbytesleft);
01250               TRACE_MESSAGE('D', (ME ":panel_Draw: aux_name = \"%.*s\"\n",
01251                                 (sizeof (buf)) - outbytesleft, buf));
01252        }
01253 #endif /* ENABLE_TRACE */
01254 
01255        if (0 < aux_data->integer_count) {
01256               int    i;
01257               TRACE_MESSAGE('D', (ME ":panel_Draw: integer_list[%d] =",
01258                                 aux_data->integer_count));
01259               for (i = 0; i < aux_data->integer_count; i++) {
01260                      TRACE_MESSAGE('D',
01261                                   (" %d", *(aux_data->integer_list + i)));
01262               }
01263               TRACE_MESSAGE('D', ("\n"));
01264        } else {
01265               TRACE_MESSAGE('D',
01266                            (ME ":panel_Draw: integer_count = 0\n"));
01267        }
01268        if (0 < aux_data->string_count) {
01269               int    i;
01270               for (i = 0; i < aux_data->string_count; i++) {
01271                      const char *  inbuf;
01272                      size_t        inbytesleft;
01273                      char *        outbuf;
01274                      size_t        outbytesleft;
01275                      int           j;
01276 
01277                      inbuf = (char *)((aux_data->string_list + i)->ptr);
01278                      inbytesleft = (aux_data->string_list + i)->length;
01279                      outbuf = string_ptr;
01280                      outbytesleft = ((sizeof (string_buf)) - string_len);
01281 
01282                      aux->service->utf16_mb(&inbuf, &inbytesleft,
01283                                           &outbuf, &outbytesleft);
01284 #if defined(ENABLE_TRACE)
01285                      j = (((sizeof (string_buf)) - string_len) - outbytesleft);
01286                      TRACE_MESSAGE('D',
01287                                   (ME ":panel_Draw: "
01288                                    "*(string_list + %d) = \"%.*s\" len=%d\n",
01289                                    i, j, string_ptr, j));
01290 #endif /* ENABLE_TRACE */
01291                      string_len = ((sizeof (string_buf)) - outbytesleft);
01292                      string_ptr = (string_buf + string_len);
01293                      switch (*(string_ptr - 1)) {
01294                      case '\0':
01295                             *(string_ptr - 1) = ' ';
01296                             break;
01297                      case ' ':
01298                             break;
01299                      default:
01300                             *string_ptr = ' ';
01301                             string_ptr += 1;
01302                             string_len += 1;
01303                             break;
01304                      }
01305               }
01306        } else {
01307               TRACE_MESSAGE('D',
01308                            (ME ":panel_Draw: string_count = 0\n"));
01309        }
01310 
01311        if (0 < string_len) {
01312               panel_ext_send(aux, (unsigned char *)string_buf, string_len);
01313        }
01314 
01315        aux->service->decompose_free(aux_data);
01316 
01317        return True;
01318 }
01319 
01320 
01321 static Bool
01322 panel_Done(aux_t * aux, const unsigned char * p, int size)
01323 {
01324        TRACE_MESSAGE('X', (ME ":panel_Done: size = %d\n", size));
01325        return True;
01326 }
01327 
01328 
01329 static Bool
01330 panel_Switched(aux_t * aux, int im_id, int on_off)
01331 {
01332        TRACE_MESSAGE('X', (ME ":panel_Switched im_id = %d %s\n",
01333                          im_id, ((1 == on_off) ? "on" : "off")));
01334 
01335        return True;
01336 }
01337 
01338 
01339 static Bool
01340 panel_Destroy(aux_t * aux)
01341 {
01342        TRACE_MESSAGE('X', (ME ":panel_Destroy\n"));
01343 
01344        return True;
01345 }