Back to index

im-sdk  12.3.91
iiimpAux.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: iiimpAux.c,v 1.1.1.1.2.4 2001/11/05 19:40:34 tajima Exp $
00045  */
00046 
00047 
00048 #ifdef HAVE_CONFIG_H
00049 #include <config.h>
00050 #endif
00051 
00052 #include <sys/types.h>
00053 #include <sys/stat.h>
00054 #include <unistd.h>
00055 #include <fcntl.h>
00056 #include <sys/mman.h>
00057 #include <dlfcn.h>
00058 #include <string.h>
00059 #include <strings.h>
00060 #include <ctype.h>
00061 #include <sys/param.h>
00062 #ifdef HAVE_SYNCN_H
00063 #include <synch.h>
00064 #endif
00065 
00066 #include <X11/Xmd.h>
00067 #include <X11/Xlib.h>
00068 
00069 #include "Xlcint.h"
00070 
00071 #include "iiimpIM.h"
00072 #include "iiimpAux.h"
00073 #include "iiimpAuxP.h"
00074 #include "guiIMPre.h"
00075 #include "iiimpConv.h"
00076 
00077 #include "XimpIm.h"
00078 
00079 #include "trace_message.h"
00080 
00081 
00082 #define AUX_BASE_DIR        IIIMLEDIR
00083 
00084 #if defined(__sparcv9)
00085 #define SPARCV9_DIR         "sparcv9/"
00086 #define SPARCV9_DIR_LEN            (8)
00087 #endif /* __sparcv9 */
00088 
00089 typedef struct _aux_entry {
00090     int created;
00091     aux_dir_t dir;
00092     unsigned int if_version;
00093 } aux_entry_t;
00094 
00095  
00096 typedef struct _aux_handle {
00097     aux_name_t aux_name;
00098     char *file_name;
00099     void *handle;
00100     aux_entry_t *ae;
00101     int ae_num; 
00102     struct _aux_handle *next;
00103 } aux_handle_t;
00104 
00105 
00106 struct _aux_im_data {
00107     int im_id;
00108     int ic_id;
00109     aux_entry_t *ae;
00110     void *data;
00111     aux_im_data_t *next;
00112 };
00113 
00114 
00115 typedef struct _aux_ic_info {
00116     int im_id;
00117     int ic_id;
00118     XicCommon ic_common;
00119     struct _aux_ic_info *next;
00120 } aux_ic_info_t;
00121 
00122 #define AUX_DIR_SYMBOL             "aux_dir"
00123 #define AUX_CONF_MAGIC             "# IIIM X auxiliary"
00124 
00125 #define AUX_INFO_SYMBOL            "aux_info"
00126 
00127 
00128 #define IS_SPACE(len, ptr)  ((0 < (len)) &&                           \
00129                              (('\t' == *(p)) || (' ' == *(p))))
00130 #define IS_EOL(len, ptr)    (((len) <= 0) || ('\n' == *(p)))
00131 #define IS_NOT_EOL(len, ptr)       ((0 < (len)) && ('\n' != *(p)))
00132 
00133 #define IS_PREEDIT_POSITION(ic)                                        \
00134                      (XIMP_CHK_PRESPOTLMASK(ic) &&                     \
00135                       (!((ic)->core.input_style & XIMPreeditArea)) && \
00136                       ((ic->core.input_style & XIMPreeditPosition) || \
00137                       (ic->core.input_style & XIMPreeditCallbacks)) )
00138 
00139 /*
00140  * internal method
00141  */
00142 static aux_handle_t*
00143 aux_load(
00144     char * aux_file_name
00145 );
00146 static aux_handle_t*
00147 aux_conf_load(
00148     char * aux_file_name
00149 );
00150 static aux_handle_t*
00151 aux_so_load(
00152     char * aux_file_name
00153 );
00154 static aux_t*
00155 aux_get(
00156     XicCommon ic,
00157     IIIMCF_event ev,
00158     const IIIMP_card16 *aux_name
00159 );
00160 static aux_entry_t*
00161 aux_entry_get(
00162     const IIIMP_card16 *name
00163 );
00164 static aux_im_data_t*
00165 aux_im_get(
00166     XicCommon, int
00167 );
00168 static int 
00169 aux_string_length(
00170     const IIIMP_card16 *str
00171 );
00172 
00173 /* faked "COMPOSED":-P structure.  */
00174 typedef struct {
00175     int len;
00176     aux_t *aux;
00177     IIIMCF_event ev;
00178     aux_data_t *pad;
00179 } AUXComposed;
00180 
00181 /*
00182  * X auxiliary object service method
00183  */
00184 static void          service_aux_setvalue(aux_t *,
00185                                         const unsigned char *, int);
00186 static void          service_aux_getvalue(aux_t *,
00187                                         const unsigned char *, int);
00188 static int           service_im_id(aux_t *);
00189 static int           service_ic_id(aux_t *);
00190 static void          service_data_set(aux_t *, int, void *);
00191 static void *        service_data_get(aux_t *, int);
00192 static Display *     service_display(aux_t *);
00193 static Window        service_window(aux_t *);
00194 static XPoint *             service_point(aux_t *, XPoint *);
00195 static XPoint *             service_point_caret(aux_t *, XPoint *);
00196 static size_t        service_utf16_mb(const char **, size_t *,
00197                                     char **, size_t *);
00198 static size_t        service_mb_utf16(const char **, size_t *,
00199                                     char **, size_t *);
00200 static unsigned char *      service_compose(const aux_data_t *, int *);
00201 static int           service_compose_size(aux_data_type_t,
00202                                         const unsigned char *);
00203 static aux_data_t *  service_decompose(aux_data_type_t,
00204                                      const unsigned char *);
00205 static void          service_decompose_free(aux_data_t *);
00206 static void          service_register_X_filter(Display *, Window, int, int,
00207                                             Bool (* filter)(Display *,
00208                                                           Window,
00209                                                           XEvent *,
00210                                                           XPointer),
00211                                             XPointer);
00212 static void          service_unregister_X_filter(Display *, Window,
00213                                               Bool (* filter)(Display *,
00214                                                             Window,
00215                                                             XEvent *,
00216                                                             XPointer),
00217                                               XPointer);
00218 static Bool          service_server(aux_t *);
00219 static Window        service_client_window(aux_t *);
00220 static Window        service_focus_window(aux_t *);
00221 static int           service_screen_number(aux_t *);
00222 static int           service_point_screen(aux_t *, XPoint *);
00223 static int           service_point_caret_screen(aux_t *, XPoint *);
00224 static Bool          service_get_conversion_mode(aux_t*);
00225 static void          service_set_conversion_mode(aux_t*, int);
00226 static aux_t *              service_aux_get_from_id(int im_id, int ic_id,
00227                                           CARD16 *aux_name,
00228                                           int aux_name_length);
00229 
00230 static aux_service_t aux_service = {
00231        service_aux_setvalue,
00232        service_im_id,
00233        service_ic_id,
00234        service_data_set,
00235        service_data_get,
00236        service_display,
00237        service_window,
00238        service_point,
00239        service_point_caret,
00240        service_utf16_mb,
00241        service_mb_utf16,
00242        service_compose,
00243        service_compose_size,
00244        service_decompose,
00245        service_decompose_free,
00246        service_register_X_filter,
00247        service_unregister_X_filter,
00248        service_server,
00249        service_client_window,
00250        service_focus_window,
00251        service_screen_number,
00252        service_point_screen,
00253        service_point_caret_screen,
00254        service_get_conversion_mode,
00255        service_set_conversion_mode,
00256        service_aux_getvalue,
00257        service_aux_get_from_id
00258 };
00259 
00260 
00261 #if defined(ENABLE_TRACE)
00262 static const char *  AuxChangeReasonName[] = {
00263        "NONE",
00264        "AUX_DOWNLOAD",
00265        "AUX_START",
00266        "AUX_DRAW",
00267        "AUX_DONE",
00268        "AUX_SWITCHED",
00269        "AUX_DESTROY"
00270 };
00271 #endif /* ENABLE_TRACE */
00272 
00273 
00274 static aux_handle_t *       aux_handle;
00275 static aux_ic_info_t *      aux_ic_info = NULL;
00276 
00277 /*
00278  * object downloading
00279  */
00280 void
00281 IIimpAuxDownload(
00282     IIIMCF_downloaded_object obj
00283 )
00284 {
00285     char *aux_file_name;
00286     char *aux_file_name_buf;
00287     int       aux_file_name_len;
00288     char file_name[MAXPATHLEN];
00289     char *dir_name;
00290     int       dir_name_len;
00291     Bool useUnicode = False; /* default */
00292     IIIMF_status st;
00293     const IIIMP_card16 *u16filename;
00294 
00295     TRACE_MESSAGE('A', ("iiimpAux: download\n"));
00296 
00297     aux_file_name = NULL;
00298     aux_file_name_buf = NULL;
00299 
00300     st = iiimcf_get_downloaded_object_filename(obj, &u16filename);
00301     if (st != IIIMF_STATUS_SUCCESS) return;
00302     st = IIimpUTF16ToString(u16filename, useUnicode, &aux_file_name);
00303     if (st != IIIMF_STATUS_SUCCESS) return;
00304     aux_file_name_buf = aux_file_name;
00305 
00306 #if defined(IIIM_AUX_SO_PATH_ENV)
00307     p = getenv(IIIM_AUX_SO_PATH_ENV);
00308 
00309     if (NULL != p) {
00310        aux_file_name = p;
00311     }
00312 
00313     if (NULL == aux_file_name) {
00314        aux_file_name = "./aux.so";
00315     }
00316 #endif /* IIIM_AUX_SO_PATH_ENV */
00317 
00318     if (NULL == aux_file_name) {
00319        return;
00320     }
00321 
00322     aux_file_name_len = strlen(aux_file_name);
00323 
00324     /*
00325      * may not start with "/"
00326      * may not start with "../"
00327      * may not contain "/../"
00328      * may not end with "/"
00329      * may not end with "/."
00330      * may not end with "/.."
00331      * may not be ".."
00332      */
00333 
00334     if (((1 <= aux_file_name_len) &&
00335         ('/' == *(aux_file_name + 0))) ||
00336        ((3 <= aux_file_name_len) &&
00337         ('.' == *(aux_file_name + 0)) &&
00338         ('.' == *(aux_file_name + 1)) &&
00339         ('/' == *(aux_file_name + 2))) ||
00340        (NULL != strstr(aux_file_name, "/../")) ||
00341        ((1 <= aux_file_name_len) &&
00342         ('/' == *(aux_file_name + aux_file_name_len - 1))) ||
00343        ((2 <= aux_file_name_len) &&
00344         ('/' == *(aux_file_name + aux_file_name_len - 2)) &&
00345         ('.' == *(aux_file_name + aux_file_name_len - 1))) ||
00346        ((3 <= aux_file_name_len) &&
00347         ('/' == *(aux_file_name + aux_file_name_len - 3)) &&
00348         ('.' == *(aux_file_name + aux_file_name_len - 2)) &&
00349         ('.' == *(aux_file_name + aux_file_name_len - 1))) ||
00350        ((2 == aux_file_name_len) &&
00351         ('.' == *(aux_file_name + 0)) &&
00352         ('.' == *(aux_file_name + 1)))) {
00353 
00354        Xfree (aux_file_name_buf);
00355        return;
00356     }
00357 
00358     /*
00359      * eliminate leading "./"
00360      */
00361     if ((2 <= aux_file_name_len) &&
00362        ('.' == *(aux_file_name + 0)) &&
00363        ('/' == *(aux_file_name + 1))) {
00364        aux_file_name += 2;
00365        aux_file_name_len -= 2;
00366     }
00367 
00368     dir_name = AUX_BASE_DIR;
00369 
00370 #if defined(IIIM_AUX_SO_BASE_ENV)
00371     {
00372        char * p;
00373        if (NULL != (p = getenv(IIIM_AUX_SO_BASE_ENV))) {
00374            dir_name = p;
00375        }
00376     }
00377 #endif /* IIIM_AUX_SO_BASE_ENV */
00378 
00379     dir_name_len = strlen(dir_name);
00380 
00381 #if defined(__sparcv9)
00382     if (MAXPATHLEN <
00383        (dir_name_len + 1 + aux_file_name_len + SPARCV9_DIR_LEN + 1)) {
00384        Xfree (aux_file_name_buf);
00385        return;
00386     }
00387     p = strrchr(aux_file_name, '/');
00388     if (NULL == p) {
00389        p = aux_file_name;
00390     } else {
00391        p += 1;
00392     }
00393     memcpy(file_name, dir_name, dir_name_len);
00394     len = (p - aux_file_name);
00395     if (dir_name_len > 0 && dir_name[dir_name_len-1] == '/') {
00396        memcpy(file_name + dir_name_len, aux_file_name, len);
00397        len += dir_name_len;
00398     } else {
00399        file_name[dir_name_len] = '/';
00400        memcpy(file_name + dir_name_len + 1, aux_file_name, len);
00401        len += (dir_name_len + 1);
00402     }
00403     memcpy(file_name + len, SPARCV9_DIR, SPARCV9_DIR_LEN);
00404     len += SPARCV9_DIR_LEN;
00405     memcpy(file_name + len, p, aux_file_name_len - (p - aux_file_name) + 1);
00406 
00407 #else /* !__sparcv9 */
00408 
00409     if (MAXPATHLEN <= (dir_name_len + 1 + aux_file_name_len + 1)) {
00410        Xfree (aux_file_name_buf);
00411        return;
00412     }
00413 
00414     memcpy(file_name, dir_name, dir_name_len + 1);
00415     if (dir_name_len > 0 && dir_name[dir_name_len-1] == '/') {
00416        memcpy(file_name + dir_name_len,
00417               aux_file_name, aux_file_name_len + 1);
00418     } else {
00419        file_name[dir_name_len] = '/';
00420        memcpy(file_name + dir_name_len + 1,
00421               aux_file_name, aux_file_name_len + 1);
00422     }
00423 #endif /* !__sparcv9 */
00424 
00425     (void)aux_load(file_name);
00426 
00427     Xfree (aux_file_name_buf);
00428 
00429     return;
00430 }
00431 
00432 static AUXComposed*
00433 create_composed_from_event(
00434     aux_t *aux,
00435     IIIMCF_event ev
00436 )
00437 {
00438     unsigned char *p;
00439     AUXComposed *pac;
00440     IIIMF_status st;
00441     const IIIMP_card16 *aux_name;
00442     IIIMP_card32 class_idx;
00443     int num_intvals;
00444     const IIIMP_card32 *pintvals;
00445     int num_strvals;
00446     const IIIMP_card16 **pstrs;
00447     aux_data_t *pad;
00448 
00449     int i, n;
00450     int aux_data_t_n;
00451     int aux_name_len, aux_name_n;
00452     int integer_list_n = 0, string_list_n = 0;
00453     int string_n = 0;
00454     int *pstring_len;
00455 
00456 #define ROUNDUP(n) ((n + sizeof(int) - 1) / sizeof(int) * sizeof(int))
00457 
00458     st = iiimcf_get_aux_event_value(ev, &aux_name, &class_idx,
00459                                 &num_intvals, &pintvals,
00460                                 &num_strvals, &pstrs);
00461     if (st != IIIMF_STATUS_SUCCESS) return NULL;
00462 
00463     /* first of all, caliculate size. */
00464     n = ROUNDUP(sizeof(AUXComposed));
00465     aux_data_t_n = n;
00466     n += sizeof(aux_data_t);
00467     aux_name_n = n = ROUNDUP(n);
00468     aux_name_len = aux_string_length(aux_name);
00469     n += (aux_name_len + 1) * sizeof(IIIMP_card16);
00470     if (num_intvals > 0) {
00471        integer_list_n = n = ROUNDUP(n);
00472        n += num_intvals * sizeof(int);
00473     }
00474     pstring_len = NULL;
00475     if (num_strvals > 0) {
00476        pstring_len = (int*) malloc(sizeof(int) * num_strvals);
00477        if (!pstring_len) return NULL;
00478        string_list_n = n = ROUNDUP(n);
00479        n += num_strvals * sizeof(aux_string_t);
00480        string_n = n = ROUNDUP(n);
00481        for (i = 0; i < num_strvals; i++) {
00482            pstring_len[i] = aux_string_length(pstrs[i]);
00483            n += (pstring_len[i] + 1) * sizeof(IIIMP_card16);
00484        }
00485     }
00486     p = (unsigned char*) malloc(n);
00487     if (!p) {
00488        if (pstring_len) free(pstring_len);
00489        return NULL;
00490     }
00491     memset(p, 0, n);
00492 
00493     pac = (AUXComposed*) p;
00494     pac->len = n;
00495     pac->ev = ev;
00496     pad = (aux_data_t*)(p + aux_data_t_n);
00497     pac->pad = pad;
00498 
00499     if (aux) {
00500        pac->aux = aux;
00501        pad->im = aux->im->im_id;
00502        pad->ic = aux->im->ic_id;
00503     }
00504 
00505     pad->aux_index = class_idx;
00506     pad->aux_name = p + aux_name_n;
00507     memcpy(pad->aux_name, aux_name, (aux_name_len + 1) * sizeof(IIIMP_card16));
00508     pad->aux_name_length = aux_name_len * sizeof(IIIMP_card16);
00509 
00510     pad->integer_count = num_intvals;
00511     if (num_intvals > 0) {
00512        pad->integer_list = (int*)(p + integer_list_n);
00513        for (i = 0; i < num_intvals; i++) {
00514            pad->integer_list[i] = pintvals[i];
00515        }
00516     }
00517     pad->string_count = num_strvals;
00518     pad->string_ptr = p;
00519     if (num_strvals > 0) {
00520        aux_string_t *pas;
00521 
00522        pad->string_list = pas = (aux_string_t*)(p + string_list_n);
00523        p += string_n;
00524        for (i = 0; i < num_strvals; i++, pas++) {
00525            pas->length = pstring_len[i] * sizeof(IIIMP_card16);
00526            pas->ptr = p;
00527            n = (pstring_len[i] + 1) * sizeof(IIIMP_card16);
00528            memcpy(p, pstrs[i], n);
00529            p += n;
00530        }
00531     }
00532 
00533     if (pstring_len) free(pstring_len);
00534     return pac;
00535 
00536 #undef ROUNDUP
00537 }
00538 
00539 static AUXComposed*
00540 create_composed_from_aux_data(
00541     const aux_data_t *pad1
00542 )
00543 {
00544     unsigned char *p;
00545     AUXComposed *pac;
00546     aux_data_t *pad2;
00547 
00548     int i, n;
00549     int aux_data_t_n;
00550     int aux_name_n;
00551     int integer_list_n, string_list_n;
00552     int string_n;
00553 
00554 #define ROUNDUP(n) ((n + sizeof(int) - 1) / sizeof(int) * sizeof(int))
00555 
00556     /* first of all, caliculate size. */
00557     n = ROUNDUP(sizeof(AUXComposed));
00558     aux_data_t_n = n;
00559     n += sizeof(aux_data_t);
00560     aux_name_n = n = ROUNDUP(n);
00561     n += pad1->aux_name_length + sizeof(IIIMP_card16);
00562     integer_list_n = n = ROUNDUP(n);
00563     n += pad1->integer_count * sizeof(int);
00564     string_list_n = n = ROUNDUP(n);
00565     n += pad1->string_count * sizeof(aux_string_t);
00566     string_n = n = ROUNDUP(n);
00567     for (i = 0; i < pad1->string_count; i++) {
00568        n += pad1->string_list[i].length + sizeof(IIIMP_card16);
00569     }
00570 
00571     p = (unsigned char*) malloc(n);
00572     if (!p) return NULL;
00573     memset(p, 0, n);
00574 
00575     pac = (AUXComposed*) p;
00576     pac->len = n;
00577     pad2 = (aux_data_t*)(p + aux_data_t_n);
00578     pac->pad = pad2;
00579 
00580     *pad2 = *pad1;
00581     pad2->aux_name = p + aux_name_n;
00582     memcpy(pad2->aux_name, pad1->aux_name, pad1->aux_name_length);
00583 
00584     if (pad1->integer_count > 0) {
00585        pad2->integer_list = (int*)(p + integer_list_n);
00586        memcpy(pad2->integer_list, pad1->integer_list,
00587               sizeof(int) * pad1->integer_count);
00588     } else {
00589        pad2->integer_list = NULL;
00590     }
00591 
00592     pad2->string_ptr = p;
00593     if (pad1->string_count > 0) {
00594        aux_string_t *pas1, *pas2;
00595 
00596        pas1= pad1->string_list;
00597        pad2->string_list = pas2 = (aux_string_t*)(p + string_list_n);
00598        p += string_n;
00599        for (i = 0; i < pad1->string_count; i++, pas1++, pas2++) {
00600            pas2->length = pas1->length;
00601            pas2->ptr = p;
00602            memcpy(p, pas1->ptr, pas2->length);
00603            p += pas2->length + sizeof(IIIMP_card16);
00604        }
00605     } else {
00606        pad2->string_list = NULL;
00607     }
00608 
00609     return pac;
00610 
00611 #undef ROUNDUP
00612 }
00613 
00614 /*
00615  * IM_AUX_START
00616  */
00617 void
00618 IIimpAuxStart(
00619     XicCommon ic,
00620     IIIMCF_event ev
00621 )
00622 {
00623     aux_t *aux;
00624     AUXComposed ac;
00625 
00626     TRACE_MESSAGE('A', ("iiimpAux: start\n"));
00627 
00628     aux = aux_get(ic, ev, NULL);
00629     if (!aux) {
00630        TRACE_MESSAGE('A', ("iiimpAux: start: failed to get aux\n"));
00631        return;
00632     }
00633 
00634     memset(&ac, 0, sizeof(ac));
00635     ac.aux = aux;
00636     ac.ev = ev;
00637 
00638     aux->im->ae->dir.method->start(aux, 
00639                                (XPointer) &ac,
00640                                /* Always set 0! */
00641                                0);
00642 
00643     return;
00644 }
00645 
00646 
00647 /*
00648  * IM_AUX_DRAW
00649  */
00650 void
00651 IIimpAuxDraw(
00652     XicCommon ic,
00653     IIIMCF_event ev
00654 )
00655 {
00656     aux_t *aux;
00657     AUXComposed ac;
00658 
00659     TRACE_MESSAGE('A', ("iiimpAux: draw\n"));
00660 
00661     aux = aux_get(ic, ev, NULL);
00662     if (!aux) {
00663        TRACE_MESSAGE('A', ("iiimpAux: draw: failed to get aux\n"));
00664        return;
00665     }
00666 
00667     memset(&ac, 0, sizeof(ac));
00668     ac.aux = aux;
00669     ac.ev = ev;
00670 
00671     aux->im->ae->dir.method->draw(aux,
00672                               (XPointer) &ac,
00673                               /* Always set 0! */
00674                               0);
00675     return;
00676 }
00677 
00678 
00679 /*
00680  * IM_AUX_DONE
00681  */
00682 void
00683 IIimpAuxDone(
00684     XicCommon ic,
00685     IIIMCF_event ev
00686 )
00687 {
00688     aux_t *aux;
00689     AUXComposed ac;
00690 
00691     TRACE_MESSAGE('A', ("iiimpAux: done\n"));
00692 
00693     aux = aux_get(ic, ev, NULL);
00694     if (!aux) {
00695        TRACE_MESSAGE('A', ("iiimpAux: done: failed to get aux\n"));
00696        return;
00697     }
00698 
00699     memset(&ac, 0, sizeof(ac));
00700     ac.aux = aux;
00701     ac.ev = ev;
00702 
00703     aux->im->ae->dir.method->done(aux,
00704                               (XPointer) &ac,
00705                               /* Always set 0! */
00706                               0);
00707     return;
00708 }
00709 
00710 /*
00711  * IM_AUX_GETVALUES
00712  */
00713 void
00714 IIimpAuxGetValuesReply(
00715     XicCommon ic,
00716     IIIMCF_event ev
00717 )
00718 {
00719     aux_t *aux;
00720     AUXComposed ac;
00721 
00722     TRACE_MESSAGE('A', ("iiimpAux: getvalues reply\n"));
00723 
00724     aux = aux_get(ic, ev, NULL);
00725     if (!aux) {
00726        TRACE_MESSAGE('A', ("iiimpAux: getvalues reply: failed to get aux\n"));
00727        return;
00728     }
00729 
00730     memset(&ac, 0, sizeof(ac));
00731     ac.aux = aux;
00732     ac.ev = ev;
00733 
00734     if (aux->im->ae->dir.method->getvalues_reply)
00735        aux->im->ae->dir.method->getvalues_reply(aux,
00736                                            (XPointer) &ac,
00737                                            /* Always set 0! */
00738                                            0);
00739     return;
00740 }
00741 
00742 #if 0
00743 /*
00744  * not defined yet
00745  */
00746 void
00747 IIimpAuxSwitched(
00748     XicCommon ic,
00749     XPointer call_data
00750 )
00751 {
00752     int *            ip;
00753     int              im_id;
00754     int              on_off;
00755     aux_t *          aux;
00756 
00757     TRACE_MESSAGE('A', ("iiimpAux: switched\n"));
00758 
00759     if (NULL == (aux = aux_get(ic, call_data, NULL))) {
00760        TRACE_MESSAGE('A', ("iiimpAux: switched: failed to get aux\n"));
00761        return;
00762     }
00763 
00764     ip = (int *)call_data;
00765     im_id = *(ip + 0);
00766     on_off = *(ip + 1);
00767 
00768     aux->im->ae->dir.method->switched(aux, im_id, on_off);
00769     return;
00770 }
00771 #endif
00772 
00773 void
00774 IIimpAuxSetICFocus(
00775     XicCommon ic
00776 ) 
00777 {
00778     aux_t *aux;
00779     aux_im_data_t *aux_im;
00780 
00781     aux = XIC_IIIMP(ic, aux);
00782     if (!aux)
00783        return;
00784 
00785     for (aux_im = aux->im_list; aux_im; aux_im = aux_im->next) {
00786        if (aux_im->ae->if_version >= AUX_IF_VERSION_2 &&
00787            aux_im->ae->dir.method->set_icforcus != NULL) {
00788            aux->im = aux_im;
00789            aux_im->ae->dir.method->set_icforcus(aux);
00790        }
00791     }
00792 }
00793 
00794 void
00795 IIimpAuxUnsetICFocus(
00796     XicCommon ic
00797 )
00798 {
00799     aux_t *aux;
00800     aux_im_data_t *aux_im;
00801 
00802     aux = XIC_IIIMP(ic, aux);
00803     if (!aux)
00804        return;
00805 
00806     for (aux_im = aux->im_list; aux_im; aux_im = aux_im->next) {
00807        if (aux_im->ae->if_version >= AUX_IF_VERSION_2 &&
00808            aux_im->ae->dir.method->unset_icforcus != NULL) {
00809            aux->im = aux_im;
00810            aux_im->ae->dir.method->unset_icforcus(aux);
00811        }
00812     }
00813 }
00814 
00815 static void
00816 delete_aux_ic(
00817     XicCommon ic
00818 )
00819 {
00820     aux_t *aux;
00821     aux_im_data_t *aux_im;
00822     aux_ic_info_t *aux_ic;
00823     aux_ic_info_t *prev_aux_ic;
00824 
00825     aux = XIC_IIIMP(ic, aux);
00826     if (!aux)
00827        return;
00828 
00829     for (aux_im = aux->im_list; aux_im; aux_im = aux_im->next) {
00830        if (aux_im->ae->if_version >= AUX_IF_VERSION_2 &&
00831            aux_im->ae->dir.method->destroy_ic != NULL) {
00832            aux->im = aux_im;
00833            aux_im->ae->dir.method->destroy_ic(aux);
00834        }
00835     }
00836 
00837     prev_aux_ic = NULL;
00838     for (aux_ic = aux_ic_info; aux_ic != NULL; aux_ic = aux_ic->next) {
00839        if (aux_ic->ic_common == ic) {
00840            if (prev_aux_ic == NULL)
00841               aux_ic_info = aux_ic->next;
00842            else
00843               prev_aux_ic->next = aux_ic->next;
00844            Xfree(aux_ic);
00845            break;
00846        }
00847        prev_aux_ic = aux_ic;
00848     }
00849 }
00850 
00851 void
00852 IIimpDestroryAuxData(
00853     XicCommon ic
00854 )
00855 {
00856     aux_t *aux;
00857     aux_im_data_t *pai1, *pai2;
00858 
00859     if (!ic || !ic->iiimp_icpart) return;
00860     aux = XIC_IIIMP(ic, aux);
00861     if (!aux) return;
00862 
00863     delete_aux_ic(ic);
00864 
00865     for (pai1 = aux->im_list; pai1; ) {
00866        pai2 = pai1->next;
00867        free(pai1);
00868        pai1 = pai2;
00869     }
00870     aux->im_list = NULL;
00871 }
00872 
00873 /*
00874  * not defined yet
00875  */
00876 void
00877 IIimpFreeAllAuxData()
00878 {
00879     aux_handle_t *ah;
00880     aux_handle_t *ah_next;
00881     int       i;
00882 
00883     TRACE_MESSAGE('A', ("iiimpAux: destroy\n"));
00884 
00885     for (ah = aux_handle; NULL != ah; ah = ah_next) {
00886        for (i = 0; i < ah->ae_num; i++) {
00887            if (0 == (ah->ae + i)->created) {
00888               continue;
00889            }
00890            (ah->ae + i)->dir.method->destroy(NULL);
00891            (ah->ae + i)->created = 0;
00892        }
00893        ah_next = ah->next;
00894        Xfree(ah->aux_name.ptr);
00895        Xfree(ah->file_name);
00896        dlclose(ah->handle);
00897        Xfree(ah->ae);
00898        Xfree(ah);
00899     }
00900 
00901     aux_handle = NULL;
00902 
00903     return;
00904 }
00905 
00906 /*
00907  *
00908  */
00909 static aux_handle_t *
00910 aux_load(
00911     char * aux_file_name
00912 )
00913 {
00914     int              fd;
00915     char             buf[64];
00916     int              magic_len;
00917     int              len;
00918 
00919     TRACE_MESSAGE('A', ("iiimpAux: aux_load\n"));
00920 
00921     if (-1 == (fd = open(aux_file_name, O_RDONLY, 0))) {
00922        TRACE_MESSAGE('A', ("iiimpAux: aux_load: can not open %s\n",
00923                          aux_file_name));
00924        return NULL;
00925     }
00926 
00927     magic_len = strlen(AUX_CONF_MAGIC);
00928 
00929     len = read(fd, buf, magic_len);
00930 
00931     close(fd);
00932 
00933     if ((len == magic_len) &&
00934        (0 == memcmp(buf, AUX_CONF_MAGIC, len))) {
00935        return aux_conf_load(aux_file_name);
00936     } else {
00937        return aux_so_load(aux_file_name);
00938     }
00939 }
00940 
00941 
00942 /*
00943  *
00944  */
00945 static aux_handle_t *
00946 aux_conf_load(
00947     char * aux_file_name
00948 )
00949 {
00950     int              fd;
00951     struct stat      st_buf;
00952     void *           addr;
00953     char *           p;
00954     char *           aux_name;
00955     int              aux_name_len;
00956     char *           aux_so;
00957     int              aux_so_len;
00958     aux_handle_t *   ah;
00959     int              len;
00960     char *           inbuf;
00961     size_t           inbytesleft;
00962     char *           outbuf;
00963     size_t           outbytesleft;
00964     int              dir_name_len;
00965     char *           dir_name_last;
00966 
00967     dir_name_last = strrchr(aux_file_name, '/');
00968     if (NULL == dir_name_last) {
00969        return NULL;
00970     }
00971     dir_name_len = ((dir_name_last - aux_file_name) + 1);
00972 
00973     if (-1 == (fd = open(aux_file_name, O_RDONLY, 0))) {
00974        return NULL;
00975     }
00976 
00977     if (0 != fstat(fd, &st_buf)) {
00978        close(fd);
00979        return NULL;
00980     }
00981 
00982     addr = mmap(0, st_buf.st_size,
00983               PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
00984 
00985     close(fd);
00986 
00987     if (MAP_FAILED == addr) {
00988        return NULL;
00989     }
00990 
00991     ah = NULL;
00992        
00993     for (p = addr, len = st_buf.st_size; 0 < len; ) {
00994        if ('#' == *p) {
00995            while (IS_NOT_EOL(len, p)) {
00996               p++;
00997               --len;
00998            }
00999            if (IS_EOL(len, p)) {
01000               p++;
01001               --len;
01002            }
01003            continue;
01004        }
01005 
01006        while (IS_SPACE(len, p)) {
01007            p++;
01008            --len;
01009        }
01010        if (IS_EOL(len, p)) {
01011            p++;
01012            --len;
01013            continue;
01014        }
01015 
01016        aux_name = p;
01017        while ((!(IS_SPACE(len, p))) && IS_NOT_EOL(len, p)) {
01018            p++;
01019            --len;
01020        }
01021        if (IS_EOL(len, p)) {
01022            p++;
01023            --len;
01024            continue;
01025        }
01026 
01027        aux_name_len = (p - aux_name);
01028 
01029        while (IS_SPACE(len, p)) {
01030            p++;
01031            --len;
01032        }
01033        if (IS_EOL(len, p)) {
01034            p++;
01035            --len;
01036            continue;
01037        }
01038 
01039        aux_so = p;
01040        while ((!(IS_SPACE(len, p))) && IS_NOT_EOL(len, p)) {
01041            p++;
01042            --len;
01043        }
01044        aux_so_len = (p - aux_so);
01045 
01046        ah = (aux_handle_t *)Xmalloc(sizeof (aux_handle_t));
01047        if (NULL == ah) {
01048            break;
01049        }
01050 
01051        ah->aux_name.len = (aux_name_len * (sizeof (CARD16)));
01052        ah->aux_name.ptr = Xmalloc(ah->aux_name.len);
01053        if (NULL == ah->aux_name.ptr) {
01054            XFree(ah);
01055            break;
01056        }
01057 
01058        inbuf = aux_name;
01059        inbytesleft = aux_name_len;
01060        outbuf = (char *)(ah->aux_name.ptr);
01061        outbytesleft = ah->aux_name.len;
01062        IIimpConvertToUTF16(inbuf, inbytesleft,
01063                          &outbuf, &outbytesleft);
01064 
01065        if ('/' == *aux_so) {
01066            ah->file_name = Xmalloc(aux_so_len + 1);
01067        } else {
01068            ah->file_name = Xmalloc(dir_name_len + aux_so_len + 1);
01069        }
01070        if (NULL == ah->file_name) {
01071            Xfree(ah->aux_name.ptr);
01072            Xfree(ah);
01073            break;
01074        }
01075        if ('/' == *aux_so) {
01076            memcpy(ah->file_name, aux_so, aux_so_len);
01077            *(ah->file_name + aux_so_len) = '\0';
01078        } else {
01079            memcpy(ah->file_name, aux_file_name, dir_name_len);
01080            memcpy(ah->file_name + dir_name_len, aux_so, aux_so_len);
01081            *(ah->file_name + dir_name_len + aux_so_len) = '\0';
01082        }
01083        ah->handle = NULL;
01084        ah->ae = NULL;
01085        ah->ae_num = 0;
01086        ah->next = aux_handle;
01087        aux_handle = ah;
01088     }
01089 
01090     munmap(addr, st_buf.st_size);
01091 
01092     return ah;
01093 }
01094 
01095 
01096 /*
01097  *
01098  */
01099 static aux_dir_t *
01100 get_aux_dir_from_aux_info (void *handle, unsigned int *ifversion)
01101 {
01102     aux_info_t       *aux_info;
01103 
01104     aux_info = (aux_info_t*)dlsym(handle, AUX_INFO_SYMBOL);
01105 
01106     if(aux_info && aux_info->if_version >= AUX_IF_VERSION_2 &&
01107        aux_info->register_service != NULL) {
01108        aux_info->register_service (AUX_IF_VERSION_2, &aux_service);
01109        *ifversion = aux_info->if_version;
01110        return aux_info->dir;
01111     }
01112 
01113        return NULL;
01114 }
01115 
01116 
01117 /*
01118  *
01119  */
01120 static aux_handle_t *
01121 aux_so_load(
01122     char * aux_file_name
01123 )
01124 {
01125     void *           handle = (void *)NULL;
01126     aux_dir_t *      aux_dir;
01127     aux_dir_t *      ad;
01128     int              adn;
01129     aux_handle_t *   ah;
01130     aux_handle_t *   ah_free;
01131     int              i;
01132     unsigned int ifversion;
01133 
01134     TRACE_MESSAGE('A', ("iiimpAux: aux_so_load\n"));
01135 
01136     /*
01137      * check whether the object is already loaded
01138      */
01139     for (ah = aux_handle; NULL != ah; ah = ah->next) {
01140        if ((0 == strcmp(aux_file_name, ah->file_name)) &&
01141            (NULL != ah->handle)) {
01142            return ah;
01143        }
01144     }
01145 
01146     /*
01147      * load the object and construct aux_handle_t structure for it
01148      */
01149     handle = dlopen(aux_file_name, RTLD_LAZY);
01150     if (NULL == handle) {
01151        TRACE_MESSAGE('A',
01152                     ("iiimpAux: aux_so_load: failed to dlopen %s (%s)\n",
01153                      aux_file_name, dlerror()));
01154        return NULL;
01155     }
01156 
01157 
01158     aux_dir = get_aux_dir_from_aux_info (handle, &ifversion);
01159     if (NULL == aux_dir) {
01160        aux_dir = (aux_dir_t *)dlsym(handle, AUX_DIR_SYMBOL);
01161        if (NULL == aux_dir) {
01162            dlclose(handle);
01163            return NULL;
01164        }
01165        ifversion = 0;
01166     }
01167 
01168     for (adn = 0, ad = aux_dir; 0 < ad->name.len; ad += 1, adn += 1);
01169 
01170     if (NULL == ah) {
01171        ah = (aux_handle_t *)Xmalloc(sizeof (aux_handle_t));
01172        if (NULL == ah) {
01173            dlclose(handle);
01174            return NULL;
01175        }
01176        memset(ah, 0, sizeof (aux_handle_t));
01177 
01178        ah_free = ah;
01179     } else {
01180        ah_free = NULL;
01181     }
01182 
01183     if (NULL == ah->file_name) {
01184        ah->file_name = strdup(aux_file_name);
01185        if (NULL == ah->file_name) {
01186            Xfree(ah);
01187            dlclose(handle);
01188            return NULL;
01189        }
01190     }
01191     ah->handle = handle;
01192     ah->ae_num = adn;
01193     ah->ae = Xmalloc(adn * (sizeof (aux_entry_t)));
01194     if (NULL == ah->ae) {
01195        if (NULL != ah_free) {
01196            Xfree(ah->file_name);
01197            Xfree(ah);
01198        }
01199        dlclose(handle);
01200        return NULL;
01201     }
01202     memset(ah->ae, 0, adn * (sizeof (aux_entry_t)));
01203     for (i = 0; i < adn; i++) {
01204        (ah->ae + i)->created = 0;
01205        memcpy(&((ah->ae + i)->dir), aux_dir + i, sizeof (aux_dir_t));
01206        (ah->ae + i)->if_version = ifversion;
01207     }
01208 
01209     ah->next = aux_handle;
01210     aux_handle = ah;
01211 
01212     return ah;
01213 }
01214 
01215 static int
01216 auxname_strncmp(
01217     const IIIMP_card16 *s1,
01218     const IIIMP_card16 *s2,
01219     int len
01220 )
01221 {
01222     len /= sizeof(IIIMP_card16);
01223     for (;len > 0; len--, s1++, s2++) {
01224        if (*s1 > *s2) return 1;
01225        if (*s1 < *s2) return -1;
01226        if (!*s1) return 0;
01227     }
01228     if (!*s1) return 0;
01229     return 2;
01230 }
01231 
01232 static aux_im_data_t*
01233 create_aux_im_data(
01234     aux_t *aux,
01235     int id,
01236     const IIIMP_card16 *auxname
01237 )
01238 {
01239     aux_entry_t *ae;
01240     aux_im_data_t *aux_im;
01241     XicCommon ic;
01242     XimCommon im;
01243     IIIMCF_handle handle;
01244     IIIMF_status st;
01245 
01246     ae = aux_entry_get(auxname);
01247     if (!ae) return NULL;
01248     aux_im = (aux_im_data_t *) Xmalloc(sizeof(*aux_im));
01249     if (!aux_im) return NULL;
01250     memset(aux_im, 0, sizeof(*aux_im));
01251     ic = (XicCommon)aux->ic;
01252     im = (XimCommon)ic->core.im;
01253     handle = XIM_IIIMP(im, handle);
01254     st = iiimcf_get_im_id(handle, &aux_im->im_id);
01255     if (st != IIIMF_STATUS_SUCCESS) {
01256        XFree(aux_im);
01257        return NULL;
01258     }
01259     /* The following members are only for fake. */
01260     aux_im->ic_id = id;
01261     /* end */
01262     aux_im->ae = ae;
01263 
01264     aux_im->next = aux->im_list;
01265     aux->im_list = aux_im;
01266     aux->im = aux_im;
01267     if (!ae->created) {
01268        if (!ae->dir.method->create(aux)) return NULL;
01269        ae->created = 1;
01270     }
01271 
01272     return aux_im;
01273 }
01274 
01275 static aux_t *
01276 aux_get(
01277     XicCommon ic,
01278     IIIMCF_event ev,
01279     const IIIMP_card16 *aux_name
01280 )
01281 {
01282     IIIMF_status st;
01283     aux_t *aux;
01284     aux_im_data_t *aux_im;
01285     aux_ic_info_t *aux_ic;
01286     XimCommon im;
01287     IIIMCF_handle handle;
01288 
01289     TRACE_MESSAGE('A', ("iiimpAux: aux_get\n"));
01290 
01291     if (aux_name == NULL) {
01292        st = iiimcf_get_aux_event_value(ev, &aux_name,
01293                                    NULL, NULL, NULL, NULL, NULL);
01294        if (st != IIIMF_STATUS_SUCCESS) return NULL;
01295     }
01296 
01297 #if defined(ENABLE_TRACE)
01298     if (TRACE_P('s')) {
01299        const IIIMP_card16 *pu;
01300        TRACE_MESSAGE('s', ("iiimpAux: aux_get: "));
01301        for (pu = aux_name; *pu; pu++) {
01302            TRACE_MESSAGE('s', ("%04x ", *pu));
01303        }
01304        TRACE_MESSAGE('s', ("\n"));
01305     }
01306 #endif /* ENABLE_TRACE */
01307 
01308     /*
01309      * create aux object if it is not created
01310      */
01311 
01312     aux = XIC_IIIMP(ic, aux);
01313     if (!aux) {
01314        aux = (aux_t *) Xmalloc(sizeof(*aux));
01315        if (!aux) return NULL;
01316        memset(aux, 0, sizeof(*aux));
01317        aux->ic = ic;
01318        aux->service = &aux_service;
01319        XIC_IIIMP(ic, aux) = aux;
01320 
01321        aux_ic = Xmalloc(sizeof(*aux_ic));
01322        if (!aux_ic) return NULL;
01323        memset(aux_ic, 0, sizeof(*aux_ic));
01324        im = (XimCommon)ic->core.im;
01325        handle = XIM_IIIMP(im, handle);
01326        st = iiimcf_get_im_id(handle, &aux_ic->im_id);
01327        if (st != IIIMF_STATUS_SUCCESS) {
01328            XFree(aux_ic);
01329            return NULL;
01330        }
01331        aux_ic->ic_id = XIC_IIIMP(ic, id);
01332        aux_ic->ic_common = ic;
01333        aux_ic->next = aux_ic_info;
01334        aux_ic_info = aux_ic;
01335     }
01336 
01337     if (aux) {
01338        /*
01339         * search for aux_im_data corresponding to aux_name.
01340         */
01341        for (aux_im = aux->im_list; aux_im; aux_im = aux_im->next) {
01342            if (!auxname_strncmp(aux_name,
01343                              aux_im->ae->dir.name.ptr,
01344                              aux_im->ae->dir.name.len)) {
01345               aux->im = aux_im;
01346               return aux;
01347            }
01348        }
01349     } else {
01350        if (NULL == (aux = (aux_t *)Xmalloc(sizeof (aux_t)))) {
01351            return NULL;
01352        }
01353        aux->ic = ic;
01354        aux->service = &aux_service;
01355        aux->im = NULL;
01356        aux->im_list = NULL;
01357        XIC_IIIMP(ic, aux) = aux;
01358     }
01359 
01360     aux_im = create_aux_im_data(aux, XIC_IIIMP(ic, id), aux_name);
01361 
01362     if (!aux_im) return NULL;
01363 
01364     return aux;
01365 }
01366 
01367 static aux_entry_t *
01368 aux_entry_get(
01369     const IIIMP_card16 *name
01370 )
01371 {
01372     aux_handle_t *ah;
01373     aux_handle_t *ah0;
01374     aux_entry_t *ae;
01375     int       i;
01376 
01377     TRACE_MESSAGE('H', ("iiimpAux: aux_entry_get\n"));
01378 
01379     if (!name) return NULL;
01380 
01381     for (ah = aux_handle; NULL != ah; ah = ah->next) {
01382        if ((ah->aux_name.len > 0)
01383            && (!auxname_strncmp(name, ah->aux_name.ptr, ah->aux_name.len))) {
01384            /* This handle is created from a configuration file.
01385               Load SO now.  */
01386            ah0 = aux_so_load(ah->file_name);
01387            if (!ah0) continue;
01388            ah = ah0;
01389        }
01390        for (ae = ah->ae, i = ah->ae_num; 0 < i; ae += 1, --i) {
01391            if (!auxname_strncmp(name, ae->dir.name.ptr, ae->dir.name.len)) {
01392               return ae;
01393            }
01394        }
01395     }
01396 
01397     return NULL;
01398 }
01399 
01400 
01401 /*
01402  *
01403  */
01404 static aux_im_data_t *
01405 aux_im_get(
01406     XicCommon ic,
01407     int im_id
01408 )
01409 {
01410     aux_im_data_t *  im;
01411     aux_t *          aux;
01412 
01413     TRACE_MESSAGE('I', ("iiimpAux: aux_im_get\n"));
01414        
01415     aux = XIC_IIIMP(ic, aux);
01416 
01417     for (im = aux->im_list; NULL != im; im = im->next) {
01418        if (im_id == im->im_id) {
01419            aux->im = im;
01420            return im;
01421        }
01422     }
01423 
01424     if (NULL == (im = (aux_im_data_t *)Xmalloc(sizeof (aux_im_data_t)))) {
01425        return NULL;
01426     }
01427 
01428     im->ae = NULL;
01429     im->data = NULL;
01430     im->next = aux->im_list;
01431     aux->im_list = im;
01432     aux->im = im;
01433 
01434     return im;
01435 }
01436 
01437 static int
01438 aux_string_length(
01439     const IIIMP_card16 *str
01440 )
01441 {
01442     int n;
01443     for (n = 0; *str; str++, n++);
01444     return n;
01445 }
01446 
01447 /*
01448  * aux service function
01449  */
01450 
01451 static void
01452 service_aux_setvalue(
01453     aux_t * aux,
01454     const unsigned char * p,
01455     int len
01456 )
01457 {
01458     AUXComposed *pac = (AUXComposed*) p;
01459 
01460     if (pac->ev) {
01461        IMAuxSetValues(aux->ic, pac->ev);
01462     } else if (pac->pad) {
01463        int i;
01464        aux_data_t *pad = pac->pad;
01465        IIIMF_status st;
01466        IIIMCF_event ev;
01467        IIIMP_card32 *pintvals;
01468        const IIIMP_card16 **pstrs;
01469 
01470 #ifdef ENABLE_TRACE
01471        static void show_AC(aux_data_t *pad);
01472        show_AC(pac->pad);
01473 #endif
01474        if (pad->integer_count > 0) {
01475            pintvals = (IIIMP_card32*) malloc(sizeof(*pintvals) * pad->integer_count);
01476            if (!pintvals) return;
01477            for (i = 0; i < pad->integer_count; i++) {
01478               pintvals[i] = pad->integer_list[i];
01479            }
01480        } else {
01481            pintvals = NULL;
01482        }
01483        if (pad->string_count > 0) {
01484            pstrs = (const IIIMP_card16**) malloc(sizeof(*pstrs) * pad->string_count);
01485            if (!pstrs) {
01486               if (pintvals) free(pintvals);
01487               return;
01488            }
01489            for (i = 0; i < pad->string_count; i++) {
01490               pstrs[i] = (const IIIMP_card16*) pad->string_list[i].ptr;
01491            }
01492        } else {
01493            pstrs = NULL;
01494        }
01495 
01496        st = iiimcf_create_aux_setvalues_event((IIIMP_card16*) pad->aux_name,
01497                                           pad->aux_index,
01498                                           pad->integer_count,
01499                                           pintvals,
01500                                           pad->string_count,
01501                                           pstrs,
01502                                           &ev);
01503        if (st == IIIMF_STATUS_SUCCESS) {
01504            IMAuxSetValues(aux->ic, ev);
01505        }
01506 
01507        if (pintvals) free(pintvals);
01508        if (pstrs) free(pstrs);
01509     }
01510 
01511 }
01512 
01513 static void
01514 service_aux_getvalue(
01515     aux_t * aux,
01516     const unsigned char * p,
01517     int len
01518 )
01519 {
01520     AUXComposed *pac = (AUXComposed*) p;
01521 
01522     if (pac->ev) {
01523        IMAuxGetValues(aux->ic, pac->ev);
01524     } else if (pac->pad) {
01525        int i;
01526        aux_data_t *pad = pac->pad;
01527        IIIMF_status st;
01528        IIIMCF_event ev;
01529        IIIMP_card32 *pintvals;
01530        const IIIMP_card16 **pstrs;
01531 
01532 #ifdef ENABLE_TRACE
01533        static void show_AC(aux_data_t *pad);
01534        show_AC(pac->pad);
01535 #endif
01536        if (pad->integer_count > 0) {
01537            pintvals = (IIIMP_card32*) malloc(sizeof(*pintvals) * pad->integer_count);
01538            if (!pintvals) return;
01539            for (i = 0; i < pad->integer_count; i++) {
01540               pintvals[i] = pad->integer_list[i];
01541            }
01542        } else {
01543            pintvals = NULL;
01544        }
01545        if (pad->string_count > 0) {
01546            pstrs = (const IIIMP_card16**) malloc(sizeof(*pstrs) * pad->string_count);
01547            if (!pstrs) {
01548               if (pintvals) free(pintvals);
01549               return;
01550            }
01551            for (i = 0; i < pad->string_count; i++) {
01552               pstrs[i] = (const IIIMP_card16*) pad->string_list[i].ptr;
01553            }
01554        } else {
01555            pstrs = NULL;
01556        }
01557 
01558        st = iiimcf_create_aux_getvalues_event((IIIMP_card16*) pad->aux_name,
01559                                           pad->aux_index,
01560                                           pad->integer_count,
01561                                           pintvals,
01562                                           pad->string_count,
01563                                           pstrs,
01564                                           &ev);
01565        if (st == IIIMF_STATUS_SUCCESS) {
01566            IMAuxGetValues(aux->ic, ev);
01567        }
01568 
01569        if (pintvals) free(pintvals);
01570        if (pstrs) free(pstrs);
01571     }
01572 
01573 }
01574 
01575 static int
01576 service_im_id(
01577     aux_t * aux
01578 )
01579 {
01580     return aux->im->im_id;
01581 }
01582 
01583 
01584 static int
01585 service_ic_id(
01586     aux_t * aux
01587 )
01588 {
01589     return aux->im->ic_id;
01590 }
01591 
01592 
01593 static void
01594 service_data_set(
01595     aux_t * aux,
01596     int im_id,
01597     void * data
01598 )
01599 {
01600     aux_im_data_t *  aux_im;
01601 
01602     for (aux_im = aux->im; NULL != aux_im; aux_im = aux_im->next) {
01603        if (im_id == aux_im->im_id) {
01604            aux_im->data = data;
01605        }
01606     }
01607 
01608     return;
01609 }
01610 
01611 
01612 static void *
01613 service_data_get(
01614     aux_t * aux,
01615     int im_id
01616 )
01617 {
01618     aux_im_data_t *  aux_im;
01619 
01620     for (aux_im = aux->im; NULL != aux_im; aux_im = aux_im->next) {
01621        if (im_id == aux_im->im_id) {
01622            return aux_im->data;
01623        }
01624     }
01625 
01626     return NULL;
01627 }
01628 
01629 
01630 static Display *
01631 service_display(
01632     aux_t * aux
01633 )
01634 {
01635     return aux->ic->core.im->core.display;
01636 }
01637 
01638 
01639 static Window
01640 service_window(
01641     aux_t * aux
01642 )
01643 {
01644     if (XIMP_CHK_FOCUSWINMASK(aux->ic)) {
01645        return aux->ic->core.focus_window;
01646     } else if (aux->ic->ximp_icpart->value_mask & XIMP_CLIENT_WIN) {
01647        return aux->ic->core.client_window;
01648     } else {
01649        return None;
01650     }
01651 }
01652 
01653 
01654 static XPoint *
01655 service_point(
01656     aux_t * aux,
01657     XPoint * point
01658 )
01659 {
01660     if (IS_PREEDIT_POSITION(aux->ic)) {
01661        point->x = aux->ic->core.preedit_attr.spot_location.x;
01662        point->y = aux->ic->core.preedit_attr.spot_location.y;
01663     } else {
01664        point->x = -1;
01665        point->y = -1;
01666     }
01667 
01668     return point;
01669 }
01670 
01671 
01672 static XPoint *
01673 service_point_caret(
01674     aux_t * aux,
01675     XPoint * point
01676 )
01677 {
01678     point->x = -1;
01679     point->y = -1;
01680 
01681     if (!IS_PREEDIT_POSITION(aux->ic)) {
01682        return point;
01683     }
01684 
01685     PreeditCaretPlacementRelative(aux->ic, point);
01686 
01687     if ((-1 == point->x) && (-1 == point->y)) {
01688        return service_point(aux, point);
01689     }
01690 
01691     return point;
01692 }
01693 
01694 
01695 static size_t
01696 service_utf16_mb(
01697     const char **    inbuf,
01698     size_t *  inbytesleft,
01699     char **          outbuf,
01700     size_t *  outbytesleft
01701 )
01702 {
01703     int       r;
01704 
01705     r = IIimpConvertFromUTF16((char *)(*inbuf), *inbytesleft,
01706                            outbuf, outbytesleft);
01707     return (size_t)r;
01708 }
01709 
01710 
01711 static size_t
01712 service_mb_utf16(
01713     const char **    inbuf,
01714     size_t *  inbytesleft,
01715     char **          outbuf,
01716     size_t *  outbytesleft
01717 )
01718 {
01719     int       r;
01720 
01721     r = IIimpConvertToUTF16((char *)(*inbuf), *inbytesleft,
01722                          outbuf, outbytesleft);
01723     return (size_t)r;
01724 }
01725 
01726 
01727 static unsigned char *
01728 service_compose(
01729     const aux_data_t *pad,
01730     int *size
01731 )
01732 {
01733     AUXComposed *pac;
01734 
01735     pac = create_composed_from_aux_data(pad);
01736     return (unsigned char*) pac;
01737 }
01738 
01739 
01740 static int
01741 service_compose_size(
01742     aux_data_type_t type,
01743     const unsigned char *p
01744 )
01745 {
01746     /* now this function is dummy... */
01747     return 0;
01748 }
01749 
01750 #ifdef ENABLE_TRACE
01751 static void
01752 show_string(
01753     unsigned char *p,
01754     int len
01755 )
01756 {
01757     int i, flag;
01758     int ch;
01759     IIIMP_card16 *pu = (IIIMP_card16*) p;
01760 
01761     flag = 0;
01762     for (i = 0;i < len; i += sizeof(*pu), pu++)  {
01763        ch = *pu;
01764        if (ch <= 0x7F) {
01765            if (flag)
01766               TRACE_MESSAGE('A', ("%c", ch));
01767            else
01768               TRACE_MESSAGE('A', (" %c", ch));
01769            flag = 1;
01770        } else {
01771            TRACE_MESSAGE('A', (" %X", ch));
01772            flag = 0;
01773        }
01774     }
01775     TRACE_MESSAGE('A', ("\n"));
01776 }
01777 
01778 static void
01779 show_AC(
01780     aux_data_t *pad
01781 )
01782 {
01783     int i;
01784     TRACE_MESSAGE('A', ("dtype:%d, im:%d, ic:%d, index:%d\n",
01785                      pad->type, pad->im, pad->ic, pad->aux_index));
01786 
01787     TRACE_MESSAGE('A', ("aux_name:"));
01788     show_string(pad->aux_name, pad->aux_name_length);
01789 
01790     TRACE_MESSAGE('A', ("IL:"));
01791     for (i = 0; i < pad->integer_count; i++)
01792        TRACE_MESSAGE('A', ("%d,", pad->integer_list[i]));
01793     TRACE_MESSAGE('A', ("\n"));
01794 
01795     for (i = 0; i < pad->string_count; i++) {
01796        TRACE_MESSAGE('A', ("SL(%d):", i));
01797        show_string(pad->string_list[i].ptr, pad->string_list[i].length);
01798     }
01799 }
01800 #endif /* ENABLE_TRACE */
01801 
01802 static aux_data_t *
01803 service_decompose(
01804     aux_data_type_t type,
01805     const unsigned char * p
01806 )
01807 {
01808     AUXComposed *pac = (AUXComposed*) p;
01809 
01810     if (pac->pad) {
01811        pac = create_composed_from_aux_data(pac->pad);
01812        if (!pac) return NULL;
01813        pac->pad->type = type;
01814 #ifdef ENABLE_TRACE
01815        show_AC(pac->pad);
01816 #endif
01817        return pac->pad;
01818     }
01819 
01820     if (pac->ev) {
01821        pac = create_composed_from_event(pac->aux, pac->ev);
01822        if (!pac) return NULL;
01823        pac->pad->type = type;
01824 #ifdef ENABLE_TRACE
01825        show_AC(pac->pad);
01826 #endif
01827        return pac->pad;
01828     }
01829 
01830     return NULL;
01831 }
01832 
01833 
01834 static void
01835 service_decompose_free(
01836     aux_data_t *pad
01837 )
01838 {
01839     if (!pad) return;
01840     if (!pad->string_ptr) return;
01841     free(pad->string_ptr);
01842 }
01843 
01844 
01845 static void
01846 service_register_X_filter(
01847     Display * display,
01848     Window window,
01849     int       start_type,
01850     int       end_type,
01851     Bool (* filter)(Display *, Window, XEvent *, XPointer),
01852     XPointer client_data
01853 )
01854 {
01855     _XRegisterFilterByType(display, window, start_type, end_type,
01856                         filter, client_data);
01857 
01858     return;
01859 }
01860 
01861 
01862 static void
01863 service_unregister_X_filter(
01864     Display *display,
01865     Window window,
01866     Bool (* filter)(Display *, Window, XEvent *, XPointer),
01867     XPointer client_data
01868 )
01869 {
01870     _XUnregisterFilter(display, window, filter, client_data);
01871 }
01872 
01873 
01874 static Bool
01875 service_server(
01876     aux_t * aux
01877 )
01878 {
01879     char *    client_type;
01880 
01881     client_type = XIM_IIIMP(aux->ic->core.im, client_type);
01882 
01883     return ((0 == strcmp(client_type, "IIIMX XIM Server")) ? True : False);
01884 }
01885 
01886 
01887 static Window
01888 service_client_window(
01889     aux_t * aux
01890 )
01891 {
01892     /* ic is initialized to zero in CreateIC().
01893      * there is no need not to test
01894      * (aux->ic->ximp_icpart->value_mask & XIMP_CLIENT_WIN)
01895      */
01896     return aux->ic->core.client_window;
01897 }
01898 
01899 
01900 static Window
01901 service_focus_window(
01902     aux_t * aux
01903 )
01904 {
01905     /* ic is initialized to zero in CreateIC().
01906      * there is no need not to test
01907      * XIMP_CHK_FOCUSWINMASK(aux->ic)
01908      */
01909     return aux->ic->core.focus_window;
01910 }
01911 
01912 
01913 static int
01914 service_screen_number(
01915     aux_t * aux
01916 )
01917 {
01918     return XIC_GUI(aux->ic, screen_number);
01919 }
01920 
01921 
01922 static int
01923 service_point_screen(
01924     aux_t * aux,
01925     XPoint * point
01926 )
01927 {
01928     Display * display;
01929     Window           window;
01930     Window           root_window;
01931     Window           child;
01932     int              screen_number;
01933     int              x;
01934     int              y;
01935     int              new_x;
01936     int              new_y;
01937 
01938     display = aux->ic->core.im->core.display;
01939 
01940     screen_number = XIC_GUI(aux->ic, screen_number);
01941 
01942     if (!IS_PREEDIT_POSITION(aux->ic)) {
01943        point->x = -1;
01944        point->y = -1;
01945        return screen_number;
01946     }
01947 
01948     if (XIMP_CHK_FOCUSWINMASK(aux->ic)) {
01949        window =  aux->ic->core.focus_window;
01950     } else if (aux->ic->ximp_icpart->value_mask & XIMP_CLIENT_WIN) {
01951        window = aux->ic->core.client_window;
01952     } else {
01953        return -1;
01954     }
01955 
01956     root_window = RootWindow(display, screen_number);
01957 
01958     x = aux->ic->core.preedit_attr.spot_location.x;
01959     y = aux->ic->core.preedit_attr.spot_location.y;
01960 
01961     XTranslateCoordinates(display, window, root_window,
01962                        x, y,
01963                        &new_x, &new_y, &child);
01964 
01965     point->x = new_x;
01966     point->y = new_y;
01967 
01968     return screen_number;
01969 }
01970 
01971 
01972 static int
01973 service_point_caret_screen(
01974     aux_t * aux,
01975     XPoint * point
01976 )
01977 {
01978     point->x = -1;
01979     point->y = -1;
01980 
01981     if (IS_PREEDIT_POSITION(aux->ic)) {
01982 
01983        PreeditCaretPlacement(aux->ic, point);
01984 
01985        if ((-1 == point->x) && (-1 == point->y)) {
01986            return service_point_screen(aux, point);
01987        }
01988     }
01989 
01990     return XIC_GUI(aux->ic, screen_number);
01991 }
01992 
01993 static Bool
01994 service_get_conversion_mode(aux_t * aux)
01995 {
01996   XIC xic = (XIC)aux->ic;
01997   XIMPreeditState preedit_state;
01998 
01999   XVaNestedList preedit_attr = XVaCreateNestedList(0,
02000                                              XNPreeditState, &preedit_state,
02001                                              0);
02002   XGetICValues((XIC)xic,
02003               XNPreeditAttributes, preedit_attr,
02004               0);
02005   XFree(preedit_attr);
02006   return preedit_state;
02007 }
02008 
02009 static void
02010 service_set_conversion_mode(aux_t * aux, int conversion_mode)
02011 {
02012   XIC xic = (XIC)aux->ic;
02013   XIMPreeditState preedit_state;
02014 
02015   preedit_state = (conversion_mode == 1 ? XIMPreeditEnable : XIMPreeditDisable);
02016   XVaNestedList preedit_attr = XVaCreateNestedList(0,
02017                                              XNPreeditState, preedit_state,
02018                                              0);
02019   XSetICValues((XIC)xic,
02020               XNPreeditAttributes, preedit_attr,
02021               0);
02022   XFree(preedit_attr);
02023 }
02024 
02025 static aux_t *
02026 service_aux_get_from_id(int im_id, int ic_id,
02027        CARD16 *aux_name, int aux_name_length)
02028 {
02029     aux_ic_info_t *aux_ic;
02030 
02031     for (aux_ic = aux_ic_info; aux_ic != NULL; aux_ic = aux_ic->next) {
02032        if (aux_ic->im_id == im_id && aux_ic->ic_id == ic_id)
02033            break;
02034     }
02035     if (aux_ic == NULL)
02036        return NULL;
02037 
02038     return aux_get(aux_ic->ic_common, NULL, aux_name);
02039 }
02040 
02041 /* Local Variables: */
02042 /* c-file-style: "iiim-project" */
02043 /* End: */