Back to index

im-sdk  12.3.91
iiimcf.c
Go to the documentation of this file.
00001 /*
00002   iiimcf.c
00003 */
00004 
00005 #define NODE_DEFAULT      "localhost"
00006 #define SERVICE_DEFAULT   "9010"
00007 #define TLS_DEFAULT       "9011"
00008 
00009 #ifdef HAVE_CONFIG_H
00010 #include <config.h>
00011 #endif
00012 
00013 #ifdef HAVE_STDLIB_H
00014 #include <stdlib.h>
00015 #endif
00016 #ifdef HAVE_STRING_H
00017 #include <string.h>
00018 #endif
00019 #ifdef HAVE_MEMORY_H
00020 #include <memory.h>
00021 #endif
00022 
00023 #include "iiimcfint.h"
00024 #include <EIMIL.h>
00025 
00026 #define IIIMCF_DEFAULT_IC_HASH_TABLE_SIZE 17
00027 #define IIIMCF_DEFAULT_TIMEOUT 10000
00028 
00029 static void free_object_descriptor(
00030     IIIMCF_object_descriptor *pod,
00031     int n
00032 );
00033 
00034 /********************************************************************************
00035                             util. functions
00036 ********************************************************************************/
00037 
00038 IIIMP_card16*
00039 iiimcf_make_string(
00040     const IIIMP_card16 *str,
00041     int len
00042 )
00043 {
00044     IIIMP_card16 *pu16;
00045 
00046     pu16 = (IIIMP_card16*) malloc(sizeof(*pu16) * (len + 1));
00047     if (!pu16) return NULL;
00048     if (len > 0)
00049        memcpy(pu16, str, sizeof(*pu16) * len);
00050     pu16[len] = 0;
00051 
00052     return pu16;
00053 }
00054 
00055 int
00056 iiimcf_string_length(
00057     const IIIMP_card16 *str
00058 )
00059 {
00060     int i;
00061     for (i = 0; *str; str++) i++;
00062     return i;
00063 }
00064 
00065 IIIMP_card16*
00066 iiimcf_duplicate_string(
00067     const IIIMP_card16 *str
00068 )
00069 {
00070     if (!str) return NULL;
00071     return iiimcf_make_string(str, iiimcf_string_length(str));
00072 }
00073 
00074 void
00075 iiimcf_lock_handle(
00076     IIIMCF_handle_rec *ph
00077 )
00078 {
00079     THREAD_ID_OBJECT tid;
00080 
00081     THREAD_SET_CURRENT_ID(tid);
00082     if ((ph->thread_lock_count == 0)
00083        || (!THREAD_ID_EQUAL(ph->thread_owner_id, tid))) {
00084        LOCK_SYNC_OBJECT(ph->so);
00085        ASSERT(ph->thread_lock_count == 0);
00086        ph->thread_owner_id = tid;
00087     }
00088     ph->thread_lock_count++;
00089 }
00090 
00091 void
00092 iiimcf_unlock_handle(
00093     IIIMCF_handle_rec *ph
00094 )
00095 {
00096     THREAD_ID_OBJECT tid;
00097 
00098     THREAD_SET_CURRENT_ID(tid);
00099 
00100     ASSERT(THREAD_ID_EQUAL(ph->thread_owner_id, tid));
00101     ASSERT(ph->thread_lock_count > 0);
00102     ph->thread_lock_count--;
00103     if (ph->thread_lock_count == 0) {
00104        UNLOCK_SYNC_OBJECT(ph->so);
00105     }
00106 }
00107 
00108 
00109 /********************************************************************************
00110                             message handlers
00111 ********************************************************************************/
00112 
00113 void
00114 iiimcf_unregister_langs(
00115     int n,
00116     IIIMCF_language_rec **ppl
00117 )
00118 {
00119     IIIMCF_language_rec **pp, *p;
00120     int i;
00121 
00122     if (!ppl) return;
00123     for (pp = ppl, i = 0; i < n; i++, pp++) {
00124        p = *pp;
00125        if (p) {
00126            if (p->lang_id) free(p->lang_id);
00127            if (p->hrn) free(p->hrn);
00128            free(p);
00129        }
00130     }
00131     free(ppl);
00132 }
00133 
00134 static IIIMF_status
00135 iiimcf_register_langs(
00136     IIIMCF_handle_rec *ph,
00137     IIIMP_string *pstr
00138 )
00139 {
00140     IIIMCF_language_rec **ppl, *pl;
00141     IIIMP_string *p;
00142     IIIMP_card16 *pu;
00143     char *plang_id, *pc;
00144     int i, n;
00145 
00146     iiimcf_unregister_langs(ph->num_langs, ph->pplangs);
00147     ph->pplangs = NULL;
00148     ph->num_langs = 0;
00149     for (n = 0, p = pstr; p; p = p->next) n++;
00150     ppl = (IIIMCF_language_rec**) malloc(sizeof(IIIMCF_language_rec*) * n);
00151     if (!ppl) return IIIMF_STATUS_MALLOC;
00152     memset(ppl, 0, sizeof(IIIMCF_language_rec*) * n);
00153     for (i = 0; i < n; i++) {
00154        pl = (IIIMCF_language_rec*) malloc(sizeof(*pl));
00155        if (!pl) {
00156            iiimcf_unregister_langs(n, ppl);
00157            return IIIMF_STATUS_MALLOC;
00158        }
00159        memset(pl, 0, sizeof(*pl));
00160        ppl[i] = pl;
00161     }
00162 
00163     ph->num_langs = n;
00164     ph->pplangs = ppl;
00165     for (p = pstr; p; p = p->next, ppl++) {
00166        pl = *ppl;
00167        plang_id = (char*) malloc(sizeof(char) * (p->len + 1));
00168        if (!plang_id) {
00169            iiimcf_unregister_langs(ph->num_langs, ph->pplangs);
00170            ph->num_langs = 0;
00171            ph->pplangs = NULL;
00172            return IIIMF_STATUS_MALLOC;
00173        }
00174        for (i = 0, pu = p->ptr, pc = plang_id;i < p->len; i++) {
00175            *pc++ = (*pu++ & 0x7F);
00176        }
00177        *pc = '\0';
00178        pl->lang_id = plang_id;
00179     }
00180 
00181     return IIIMF_STATUS_SUCCESS;
00182 }
00183 
00184 void
00185 iiimcf_unregister_imeinfos(
00186     int n,
00187     IIIMCF_imeinfo_rec **ppi
00188 )
00189 {
00190     IIIMCF_imeinfo_rec **pp, *p;
00191     int i;
00192 
00193     if (!ppi) return;
00194     for (pp = ppi, i = 0; i < n; i++, pp++) {
00195         p = *pp;
00196         if (p) {
00197             if (p->ime_id) free(p->ime_id);
00198             if (p->imename) free(p->imename);
00199             if (p->version) free(p->version);
00200             if (p->description) free(p->description);
00201             if (p->author) free(p->author);
00202             if (p->copyright) free(p->copyright);
00203             if (p->reserved1) free(p->reserved1);
00204             if (p->reserved2) free(p->reserved2);
00205             free(p);
00206         }
00207     }
00208     free(ppi);
00209 }
00210 
00211 IIIMF_status
00212 iiimcf_register_trigger_keys(
00213     IIIMCF_handle_rec *ph,
00214     IIIMP_message *pmes
00215 )
00216 {
00217     int i, n;
00218     IIIMP_keyevent_list *pimkl;
00219     IIIMP_keyevent *pimk;
00220     IIIMCF_keyevent *pkev;
00221     IIIMP_register_trigger_keys_v *pimrk = &pmes->v.register_trigger_keys;
00222     ASSERT(pmes->opcode == IM_REGISTER_TRIGGER_KEYS);
00223 
00224     pimkl = pimrk->trigger_on;
00225     n = pimkl->count;
00226     if (n > 0) {
00227        pkev = (IIIMCF_keyevent*) malloc(sizeof(IIIMCF_keyevent) * n);
00228        if (!pkev) return IIIMF_STATUS_MALLOC;
00229 
00230        if (ph->pon_keys) free(ph->pon_keys);
00231        ph->pon_keys = pkev;
00232        pimk = pimkl->keyevent;
00233        for (i = 0; i < n; i++, pkev++, pimk++) {
00234            pkev->keycode = pimk->keycode;
00235            pkev->keychar = pimk->keychar;
00236            pkev->modifier = pimk->modifier;
00237            pkev->time_stamp = pimk->time_stamp;
00238        }
00239 
00240        ph->num_on_keys = i;
00241     }
00242 
00243     pimkl = pimrk->trigger_off;
00244     n = pimkl->count;
00245     if (n > 0) {
00246        pkev = (IIIMCF_keyevent*) malloc(sizeof(IIIMCF_keyevent) * n);
00247        if (!pkev) {
00248            if (ph->pon_keys) free(ph->pon_keys);
00249            ph->num_on_keys = 0;
00250            return IIIMF_STATUS_MALLOC;
00251        }
00252 
00253        if (ph->poff_keys) free(ph->poff_keys);
00254        ph->poff_keys = pkev;
00255        pimk = pimkl->keyevent;
00256        for (i = 0; i < n; i++, pkev++, pimk++) {
00257            pkev->keycode = pimk->keycode;
00258            pkev->keychar = pimk->keychar;
00259            pkev->modifier = pimk->modifier;
00260            pkev->time_stamp = pimk->time_stamp;
00261        }
00262 
00263        ph->num_off_keys = i;
00264     }
00265 
00266     return IIIMF_STATUS_SUCCESS;
00267 }
00268 
00269 IIIMF_status
00270 iiimcf_register_hotkeys(
00271     IIIMCF_handle_rec *ph,
00272     IIIMP_message *pmes
00273 )
00274 {
00275     int i, j, n, n_hkp, n_hotkeys;
00276     HOTKEY_LIST *hklist;
00277     IIIMCF_hotkey *hk;
00278     IIIMCF_keyevent *pkev;
00279     IIIMP_keyevent *pimk;
00280 
00281     IIIMP_register_hotkeys_v *pimrk = &pmes->v.register_hotkeys;
00282 
00283     ASSERT(pmes->opcode == IM_REGISTER_HOTKEYS);
00284 
00285     n_hkp = ph->num_of_hkprofiles;
00286     hklist = pimrk->hotkeys;
00287     n_hotkeys = pimrk->hotkeys->count;
00288 
00289     if (!n_hkp) {
00290       ph->phk_profile = (IIIMCF_hotkey_profile *) malloc(10 * sizeof(IIIMCF_hotkey_profile));
00291       memset(ph->phk_profile, 0, 10 * sizeof(IIIMCF_hotkey_profile));
00292     } else if (n_hkp > 10) {
00293       ph->phk_profile = (IIIMCF_hotkey_profile *) realloc((IIIMCF_hotkey_profile *)ph->phk_profile, (n_hkp + 1) * sizeof(IIIMCF_hotkey_profile));
00294     }
00295     if (!ph->phk_profile) return IIIMF_STATUS_MALLOC;
00296     ph->phk_profile[n_hkp].scope = pimrk->scope;
00297     ph->phk_profile[n_hkp].profile_id = pimrk->profile_id;
00298 
00299     if (n_hotkeys > 0) {
00300        hk = (IIIMCF_hotkey *) malloc(sizeof(IIIMCF_hotkey) * n_hotkeys);
00301        if (!hk) return IIIMF_STATUS_MALLOC;
00302         ph->phk_profile[n_hkp].phot_keys = hk;
00303 
00304        for(i=0; i<n_hotkeys; i++) {
00305            IIIMP_string *label = hklist->hotkey[i].label;
00306            char *pc;
00307            IIIMP_card16 *pu;
00308 
00309            hk[i].hotkey_id = hklist->hotkey[i].hotkeyctrl.hotkey_id;
00310            hk[i].state_flag = hklist->hotkey[i].hotkeyctrl.state_flag;
00311            hk[i].action_flag = hklist->hotkey[i].hotkeyctrl.action_flag;
00312 
00313            /* copy label from IIIMP_string* to char* */
00314            hk[i].hotkey_label = (char *)malloc (label->len + 1);
00315            memset (hk[i].hotkey_label, 0, label->len + 1);
00316            for (j = 0, pu = label->ptr, pc = hk[i].hotkey_label; j < label->len; ++j)
00317              *pc++ = (*pu++ & 0x7f);
00318 
00319            n = hklist->hotkey[i].hotkeylist->count;
00320            if (n > 0) {
00321               pkev = (IIIMCF_keyevent*) malloc(sizeof(IIIMCF_keyevent) * n);
00322               if (!pkev) return IIIMF_STATUS_MALLOC;
00323 
00324               hk[i].keys = pkev;
00325               pimk = hklist->hotkey[i].hotkeylist->keyevent;
00326               for (j = 0; j < n; j++, pkev++, pimk++) {
00327                   pkev->keycode = pimk->keycode;
00328                   pkev->keychar = pimk->keychar;
00329                   pkev->modifier = pimk->modifier;
00330                   pkev->time_stamp = pimk->time_stamp;
00331               }
00332               hk[i].nkeys = j;
00333            }
00334        }
00335         ph->phk_profile[n_hkp].num_hotkeys = n_hotkeys;
00336     }
00337     ph->num_of_hkprofiles = n_hkp + 1; 
00338     return IIIMF_STATUS_SUCCESS;
00339 }
00340 
00341 static IIIMF_status
00342 iiimcf_register_object_descriptor_list(
00343     IIIMCF_handle_rec *ph,
00344     IIIMP_object_descriptor *piiimp_objdesc
00345 )
00346 {
00347     int n;
00348     IIIMP_object_descriptor *pimod;
00349     IIIMCF_object_descriptor *pod, *podh;
00350     IIIMP_card16 *pu16;
00351 
00352     free_object_descriptor(ph->pobjdesc, ph->object_descriptor_size);
00353     ph->pobjdesc = NULL;
00354     ph->object_descriptor_size = 0;
00355     for (n = 0, pimod = piiimp_objdesc; pimod; pimod = pimod->next) n++;
00356 
00357     pod = podh = (IIIMCF_object_descriptor*) malloc(sizeof(*pod) * n);
00358     if (!pod) return IIIMF_STATUS_MALLOC;
00359     memset(podh, 0, sizeof(*podh) * n);
00360 
00361     for (pimod = piiimp_objdesc; pimod; pimod = pimod->next, pod++) {
00362        pod->category = pimod->category;
00363        pod->size = pimod->size;
00364        pod->predefined_id = pimod->id_pre;
00365        pod->dynamic_id = pimod->id_dyn;
00366        pu16 = iiimcf_make_string(pimod->rdun->ptr, pimod->rdun->len);
00367        if (!pu16) {
00368            free_object_descriptor(podh, n);
00369            return IIIMF_STATUS_MALLOC;
00370        }
00371        pod->domain = pu16;
00372 
00373        pu16 = iiimcf_make_string(pimod->hrn->ptr, pimod->hrn->len);
00374        if (!pu16) {
00375            free_object_descriptor(podh, n);
00376            return IIIMF_STATUS_MALLOC;
00377        }
00378        pod->hrn = pu16;
00379 
00380        pu16 = iiimcf_make_string(pimod->signature->ptr,
00381                               pimod->signature->len);
00382        if (!pu16) {
00383            free_object_descriptor(podh, n);
00384            return IIIMF_STATUS_MALLOC;
00385        }
00386        pod->signature = pu16;
00387 
00388        pu16 = iiimcf_make_string(pimod->user->ptr, pimod->user->len);
00389        if (!pu16) {
00390            free_object_descriptor(podh, n);
00391            return IIIMF_STATUS_MALLOC;
00392        }
00393        pod->user = pu16;
00394     }
00395     ph->pobjdesc = podh;
00396     ph->object_descriptor_size = n;
00397 
00398     return IIIMF_STATUS_SUCCESS;
00399 }
00400 
00401 IIIMF_status
00402 iiimcf_setimvalues(
00403     IIIMCF_handle_rec *ph,
00404     IIIMP_message *pmes
00405 )
00406 {
00407     IIIMF_status st;
00408     IIIMP_imattribute *pimattrs;
00409     ASSERT(pmes->opcode == IM_SETIMVALUES);
00410 
00411     for (pimattrs = pmes->v.setimvalues.attr_list;
00412         pimattrs;
00413         pimattrs = pimattrs->next) {
00414        switch (pimattrs->id_pre) {
00415          case IIIMP_IMATTRIBUTE_INPUT_METHOD_LIST:
00416           st = iiimcf_register_input_method_list(ph, pimattrs->value.inputmethod_descriptor);
00417           if (st != IIIMF_STATUS_SUCCESS) return st;
00418           break;
00419 
00420          case IIIMP_IMATTRIBUTE_OBJECT_DESCRIPTOR_LIST:
00421           st = iiimcf_register_object_descriptor_list(ph, pimattrs->value.object_descriptor);
00422           if (st != IIIMF_STATUS_SUCCESS) return st;
00423           break;
00424 
00425          default:
00426           /* simply ignore */
00427           break;
00428        }
00429     }
00430 
00431     return IIIMF_STATUS_SUCCESS;
00432 }
00433 
00434 static void
00435 free_object_descriptor(
00436     IIIMCF_object_descriptor *pod,
00437     int n
00438 )
00439 {
00440     int i;
00441     IIIMCF_object_descriptor *pod2 = pod;
00442 
00443     if (!pod) return;
00444     for (i = 0; i < n; i++, pod++) {
00445        if (pod->domain)
00446            free((IIIMP_card16*) pod->domain);
00447        if (pod->hrn)
00448            free((IIIMP_card16*) pod->hrn);
00449        if (pod->signature)
00450            free((IIIMP_card16*) pod->signature);
00451        if (pod->user)
00452            free((IIIMP_card16*) pod->user);
00453     }
00454     free(pod2);
00455 }
00456 
00457 
00458 /********************************************************************************
00459                           connection/send/receive management
00460 ********************************************************************************/
00461 
00462 static void
00463 iiimcf_delete_stream(
00464     IIIMCF_handle_rec *ph
00465 )
00466 {
00467     if (ph->pconf && ph->pconf->use_tls) {
00468         iiimf_delete_tls_stream(ph->pstream);
00469     } else {
00470         iiimf_delete_socket_stream(ph->pstream);
00471     }
00472     ph->pstream = NULL;
00473 }
00474 
00475 IIIMF_status
00476 iiimcf_connect(
00477     IIIMCF_handle_rec *ph
00478 )
00479 {
00480     IIIMF_status st = IIIMF_STATUS_SUCCESS;
00481     IIIMP_message *pmes;
00482 
00483     if (!ph->data_s) ph->data_s = iiimp_data_s_new();
00484     if (!ph->data_s) return IIIMF_STATUS_MALLOC;
00485 
00486     if (!ph->pstream) {
00487         IIIMCF_client_conf *pconf;
00488         if (ph->pconf) {
00489             pconf = ph->pconf;
00490             ph->pconf = NULL;
00491         } else {
00492             pconf = ph->penv->pconf;
00493         }
00494         for ( ; pconf; pconf = pconf->next) {
00495             /* use TLS */
00496             if (pconf->use_tls) {
00497                 /* check whther libiiimp is compiled with TLS support */
00498                 st = iiimf_tls_supported();
00499                 if (st != IIIMF_STATUS_SUCCESS) continue;
00500 
00501                 st = iiimf_connect_tls_stream(pconf->server_node ? pconf->server_node : NODE_DEFAULT,
00502                                               pconf->service ? pconf->service : TLS_DEFAULT,
00503                                               IIIMCF_DEFAULT_TIMEOUT,
00504                                               &ph->pstream);
00505                 if (st != IIIMF_STATUS_SUCCESS) continue;
00506 
00507                 /* TODO*/
00508                 iiimf_tls_set_certificate(ph->pstream,
00509                                           pconf->cert_file,
00510                                           pconf->cert_key,
00511                                           pconf->ca_file,
00512                                           pconf->ca_path);
00513             } else {
00514                st = iiimf_connect_socket_stream(pconf->server_node ? pconf->server_node : NODE_DEFAULT,
00515                                              pconf->service ? pconf->service : SERVICE_DEFAULT,
00516                                             IIIMCF_DEFAULT_TIMEOUT,
00517                                            &ph->pstream);
00518             }
00519 
00520             if (st == IIIMF_STATUS_SUCCESS) {
00521                 /* set current configuration to IIIMCF_handle */
00522                 ph->pconf = pconf;
00523                 break;
00524             }
00525         }
00526     }
00527     if (st != IIIMF_STATUS_SUCCESS) {
00528         /* finally try to connect to 127.0.0.1:9010 */
00529         st = iiimf_connect_socket_stream(NODE_DEFAULT, SERVICE_DEFAULT,
00530                                          IIIMCF_DEFAULT_TIMEOUT,
00531                                          &ph->pstream);
00532     }
00533     if (st != IIIMF_STATUS_SUCCESS) return st;
00534 
00535     st = iiimcf_create_im_connect_message(ph, &pmes);
00536     if (st != IIIMF_STATUS_SUCCESS) return st;
00537 
00538     st = iiimf_stream_send(ph->pstream, ph->data_s, pmes);
00539     iiimp_message_delete(ph->data_s, pmes);
00540     if (st != IIIMF_STATUS_SUCCESS) goto reconnect;
00541 
00542     st = iiimcf_wait_message(ph, NULL, IM_CONNECT_REPLY, &pmes);
00543     if (st != IIIMF_STATUS_SUCCESS) {
00544         if (pmes) iiimp_message_delete(ph->data_s, pmes);
00545         goto reconnect;
00546     }
00547 
00548     ph->im_id = pmes->im_id;
00549     st = iiimp_data_s_limit_protocol_version(ph->data_s,
00550                                         ph->server_protocol_version);
00551     if (st != IIIMF_STATUS_SUCCESS) return st;
00552     st = iiimcf_register_langs(ph, pmes->v.connect_reply.language);
00553     iiimp_message_delete(ph->data_s, pmes);
00554 
00555     /* send CLIENTDESCRIPTOR */
00556     st = iiimcf_create_client_descriptor_message(ph, &pmes);
00557     if (st != IIIMF_STATUS_SUCCESS) return st;
00558 
00559     st = iiimf_stream_send(ph->pstream, ph->data_s, pmes);
00560     iiimp_message_delete(ph->data_s, pmes);
00561     if (st != IIIMF_STATUS_SUCCESS) return st;
00562     st = iiimcf_wait_message(ph, NULL, IM_SETIMVALUES_REPLY, NULL);
00563 
00564     return st;
00565 
00566 reconnect:
00567     /* 
00568      * in this case, iiimcf connects iiimsf successfully,
00569      * but iiimsf refuses the connection.
00570      *
00571      * so, try to next iiimsf if any.
00572      */
00573     if (!ph->pconf) return st;
00574     if (ph->pconf->next) {
00575         /* first, destroy current stream */
00576         iiimcf_delete_stream(ph);
00577         /* ph->pconf store current configuration */
00578         ph->pconf = ph->pconf->next;
00579         return iiimcf_connect(ph);
00580     }
00581     return st;
00582 }
00583 
00584 static IIIMF_status
00585 iiimcf_hungup(
00586     IIIMCF_handle_rec *ph
00587 )
00588 {
00589     ph->im_id = -1;
00590 
00591     /* Should we delete downloaded objects?  */
00592     /* iiimcf_delete_all_downloaded_objects(ph); */
00593     if (ph->pstream) {
00594         iiimcf_delete_stream(ph);
00595     }
00596 #if 0
00597     if (ph->data_s) {
00598        iiimp_data_s_delete(ph->data_s);
00599        ph->data_s = NULL;
00600     }
00601 #endif
00602 
00603     return iiimcf_cleanup_context(ph, 0);
00604 }
00605 
00606 static IIIMF_status
00607 iiimcf_disconnect(
00608     IIIMCF_handle_rec *ph
00609 )
00610 {
00611     IIIMF_status st1 = IIIMF_STATUS_SUCCESS, st2 = IIIMF_STATUS_SUCCESS;
00612     IIIMP_message *pmes;
00613 
00614     if (IIIMCF_IS_CONNECTED(ph)) {
00615        pmes = iiimp_disconnect_new(ph->data_s, ph->im_id);
00616        if (pmes) {
00617            st1 = iiimf_stream_send(ph->pstream, ph->data_s, pmes);
00618            iiimp_message_delete(ph->data_s, pmes);
00619            if (st1 == IIIMF_STATUS_SUCCESS) {
00620               st1 = iiimcf_wait_message(ph, NULL, IM_DISCONNECT_REPLY, NULL);
00621            }
00622        } else {
00623            st1 = IIIMF_STATUS_MALLOC;
00624        }
00625     }
00626 
00627     st2 = iiimcf_cleanup_context(ph, 1);
00628     if (st2 != IIIMF_STATUS_SUCCESS) return st2;
00629 
00630     return st1;
00631 }
00632 
00633 IIIMF_status
00634 iiimcf_send_message(
00635     IIIMCF_handle_rec *ph,
00636     IIIMP_message *pmes,
00637     int deletep
00638 )
00639 {
00640     IIIMF_status st;
00641 
00642     st = iiimf_stream_send(ph->pstream, ph->data_s, pmes);
00643     if (deletep) iiimp_message_delete(ph->data_s, pmes);
00644 
00645     if (st == IIIMF_STATUS_SUCCESS)
00646        return IIIMF_STATUS_SUCCESS;
00647 
00648     if ((st == IIIMF_STATUS_CONNECTION_CLOSED)
00649        || (st == IIIMF_STATUS_STREAM_SEND)) {
00650        iiimcf_hungup(ph);
00651     }
00652 
00653     return st;
00654 }
00655 
00656 IIIMF_status
00657 iiimcf_receive_message(
00658     IIIMCF_handle_rec *ph,
00659     IIIMP_message **ppmes
00660 )
00661 {
00662     IIIMF_status st;
00663 
00664     st = iiimf_stream_receive(ph->pstream, ph->data_s, ppmes);
00665 
00666     if (st == IIIMF_STATUS_SUCCESS) {
00667        if ((ph->im_id >= 0) && ((*ppmes)->im_id != ph->im_id)) {
00668            iiimp_message_delete(ph->data_s, *ppmes);
00669            *ppmes = NULL;
00670            return IIIMF_STATUS_IM_INVALID;
00671        }
00672        return IIIMF_STATUS_SUCCESS;
00673     }
00674 
00675     if ((st == IIIMF_STATUS_CONNECTION_CLOSED)
00676        || (st == IIIMF_STATUS_STREAM_RECEIVE)) {
00677        iiimcf_hungup(ph);
00678     }
00679 
00680     return st;
00681 }
00682 
00683 /********************************************************************************
00684                          create & destroy handle
00685 ********************************************************************************/
00686 
00687 IIIMF_status
00688 iiimcf_create_handle(
00689     IIIMCF_attr attr,
00690     IIIMCF_handle *phandle
00691 )
00692 {
00693     IIIMF_status st;
00694     int disable_automatic_connection_restoration = 0;
00695     IIIMCF_handle_rec *ph;
00696     IIIMCF_context_rec **ppc;
00697 
00698     st = iiimcf_attr_get_integer_value(attr, IIIMCF_ATTR_DISABLE_AUTOMATIC_RESTORATION,
00699                                    &disable_automatic_connection_restoration);
00700     if ((st != IIIMF_STATUS_SUCCESS)
00701        && (st != IIIMF_STATUS_NO_ATTR_VALUE)) {
00702        return st;
00703     }
00704 
00705     ph = (IIIMCF_handle_rec*) malloc(sizeof(*ph));
00706     if (!ph) {
00707        return IIIMF_STATUS_MALLOC;
00708     }
00709     memset(ph, 0, sizeof(*ph));
00710     ph->context_table_size = IIIMCF_DEFAULT_IC_HASH_TABLE_SIZE;
00711     ppc = (IIIMCF_context_rec**) malloc(sizeof(*ppc) * ph->context_table_size);
00712     if (!ppc) {
00713        free(ph);
00714        return IIIMF_STATUS_MALLOC;
00715     }
00716     memset(ppc, 0, sizeof(*ppc) * ph->context_table_size);
00717     ph->ppcontext_table = ppc;
00718     ph->im_id = -1;
00719 
00720     /* When not received IM_PROTOCOL_VERSION,
00721        we assume the server supports protocol version 2.  */
00722     ph->server_protocol_version = 2;
00723 
00724     INIT_SYNC_OBJECT(ph->so);
00725     if (disable_automatic_connection_restoration)
00726        ph->disable_automatic_connection_restoration = 1;
00727     else
00728        ph->disable_automatic_connection_restoration = 0;
00729 
00730     st = iiimcf_create_client_env(attr, &ph->penv);
00731     if (st != IIIMF_STATUS_SUCCESS) {
00732        DESTROY_SYNC_OBJECT(ph->so);
00733        free(ppc);
00734        free(ph);
00735        return st;
00736     }
00737 
00738     st = iiimcf_register_predefined_components(ph);
00739     if (st != IIIMF_STATUS_SUCCESS) {
00740        iiimcf_delete_client_env(ph->penv);
00741        DESTROY_SYNC_OBJECT(ph->so);
00742        free(ppc);
00743        free(ph);
00744        return st;
00745     }
00746     
00747     st = iiimcf_connect(ph);
00748     if (st != IIIMF_STATUS_SUCCESS) {
00749         iiimcf_destroy_handle(ph);
00750         return st;
00751     }
00752 
00753     *phandle = ph;
00754 
00755     return IIIMF_STATUS_SUCCESS;
00756 }
00757 
00758 IIIMF_status
00759 iiimcf_destroy_handle(
00760     IIIMCF_handle handle
00761 )
00762 {
00763     IIIMCF_handle_rec *ph = (IIIMCF_handle_rec*) handle;
00764     int i,j;
00765 
00766     iiimcf_disconnect(ph);
00767     iiimcf_unregister_langs(ph->num_langs, ph->pplangs);
00768     iiimcf_unregister_input_method_list(ph->num_input_methods,
00769                                    ph->ppinput_methods);
00770     /* must be before iiimcf_delete_client_env */
00771     if (ph->pstream)  iiimcf_delete_stream(ph);
00772     iiimcf_delete_client_env(ph->penv);
00773     iiimcf_delete_all_components(ph);
00774     iiimcf_delete_all_downloaded_objects(ph);
00775     free_object_descriptor(ph->pobjdesc, ph->object_descriptor_size);
00776     if (ph->pon_keys) free(ph->pon_keys);
00777     if (ph->poff_keys) free(ph->poff_keys);
00778 
00779     if (ph->phk_profile) {
00780        for (i=0; i < ph->num_of_hkprofiles; ++i) {
00781            if (ph->phk_profile[i].phot_keys) {
00782               for (j=0; j < ph->phk_profile[i].num_hotkeys; ++j) {
00783                   if (ph->phk_profile[i].phot_keys[j].keys) free(ph->phk_profile[i].phot_keys[j].keys);
00784               }
00785               free(ph->phk_profile[i].phot_keys);
00786            }
00787        }
00788         free(ph->phk_profile);
00789     }
00790     if (ph->data_s) iiimp_data_s_delete(ph->data_s);
00791     free(ph->ppcontext_table);
00792     DESTROY_SYNC_OBJECT(ph->so);
00793     free(ph);
00794     return IIIMF_STATUS_SUCCESS;
00795 }
00796 
00797 /********************************************************************************
00798                      initialization & finalization
00799 ********************************************************************************/
00800 
00801 static int iiimcf_inited = 0;
00802 
00803 IIIMF_status
00804 iiimcf_initialize(
00805     IIIMCF_attr attr
00806 )
00807 {
00808     if (iiimcf_inited) return IIIMF_STATUS_SUCCESS;
00809     if (!EIMIL_initialize())
00810        return IIIMF_STATUS_FAIL;
00811     iiimcf_inited = 1;
00812 
00813     return IIIMF_STATUS_SUCCESS;
00814 }
00815 
00816 IIIMF_status
00817 iiimcf_finalize()
00818 {
00819     EIMIL_finalize();
00820     iiimcf_inited = 0;
00821     return IIIMF_STATUS_SUCCESS;
00822 }
00823 
00824 /********************************************************************************
00825                        misc. information
00826 ********************************************************************************/
00827 
00828 IIIMF_status
00829 iiimcf_get_version_number(
00830     IIIMCF_handle handle,
00831     int flag,
00832     int *pversion_number
00833 )
00834 {
00835     IIIMCF_handle_rec *ph = (IIIMCF_handle_rec*) handle;
00836 
00837     if (flag & ~IIIMCF_VERSION_FLAGS_MASK) {
00838        return IIIMF_STATUS_ARGUMENT;
00839     }
00840     if (flag & IIIMCF_LIBRARY_VERSION) {
00841        if ((flag & ~IIIMCF_VERSION_FLAGS_ITEM_MASK)
00842            != IIIMCF_LIBRARY_VERSION) {
00843            return IIIMF_STATUS_ARGUMENT;
00844        }
00845        if (flag & IIIMCF_MAJOR_VERSION) {
00846            if ((flag & ~IIIMCF_VERSION_FLAGS_CATEGORY_MASK)
00847               != IIIMCF_MAJOR_VERSION) {
00848               return IIIMF_STATUS_ARGUMENT;
00849            }
00850            *pversion_number = LIBIIIMCF_MAJOR_VERSION;
00851        } else if (flag & IIIMCF_MINOR_VERSION) {
00852            if ((flag & ~IIIMCF_VERSION_FLAGS_CATEGORY_MASK)
00853               != IIIMCF_MINOR_VERSION) {
00854               return IIIMF_STATUS_ARGUMENT;
00855            }
00856            *pversion_number = LIBIIIMCF_MINOR_VERSION;
00857        } else {
00858            return IIIMF_STATUS_ARGUMENT;
00859        }
00860     } else if (flag & IIIMCF_PROTOCOL_VERSION) {
00861        if ((flag & ~IIIMCF_VERSION_FLAGS_ITEM_MASK)
00862            != IIIMCF_PROTOCOL_VERSION) {
00863            return IIIMF_STATUS_ARGUMENT;
00864        }
00865        if (flag & IIIMCF_MAJOR_VERSION) {
00866            if ((flag & ~IIIMCF_VERSION_FLAGS_CATEGORY_MASK)
00867               != IIIMCF_MAJOR_VERSION) {
00868               return IIIMF_STATUS_ARGUMENT;
00869            }
00870            *pversion_number = iiimp_data_s_get_protocol_version(ph->data_s);
00871        } else if (flag & IIIMCF_MINOR_VERSION) {
00872            if ((flag & ~IIIMCF_VERSION_FLAGS_CATEGORY_MASK)
00873               != IIIMCF_MINOR_VERSION) {
00874               return IIIMF_STATUS_ARGUMENT;
00875            }
00876            /* Now IM_CONNECT has no minor version */
00877            *pversion_number = 0;
00878        } else {
00879            return IIIMF_STATUS_ARGUMENT;
00880        }
00881     } else {
00882        return IIIMF_STATUS_ARGUMENT;
00883     }
00884 
00885     return IIIMF_STATUS_SUCCESS;
00886 }
00887 
00888 IIIMF_status
00889 iiimcf_get_supported_languages(
00890     IIIMCF_handle handle,
00891     int *pnum_langs,
00892     IIIMCF_language **pplangs
00893 )
00894 {
00895     IIIMCF_handle_rec *ph = (IIIMCF_handle_rec*) handle;
00896 
00897     *pnum_langs = ph->num_langs;
00898     *pplangs = (IIIMCF_language*) ph->pplangs;
00899 
00900     return IIIMF_STATUS_SUCCESS;
00901 }
00902 
00903 IIIMF_status
00904 iiimcf_get_language_id(
00905     IIIMCF_language lang,
00906     const char **plangid
00907 )
00908 {
00909     IIIMCF_language_rec *pl = (IIIMCF_language_rec*) lang;
00910 
00911     *plangid = pl->lang_id;
00912     return IIIMF_STATUS_SUCCESS;
00913 }
00914 
00915 IIIMF_status
00916 iiimcf_get_trigger_keys(
00917     IIIMCF_handle handle,
00918     int *pnum_on_keys,
00919     const IIIMCF_keyevent **pponkeys,
00920     int *pnum_off_keys,
00921     const IIIMCF_keyevent **ppoffkeys
00922 )
00923 {
00924     IIIMCF_handle_rec *ph = (IIIMCF_handle_rec*) handle;
00925 
00926     if ((ph->num_on_keys == 0)
00927        && (ph->num_off_keys == 0))
00928        return IIIMF_STATUS_STATIC_EVENT_FLOW;
00929 
00930     *pnum_on_keys = ph->num_on_keys;
00931     *pponkeys = ph->pon_keys;
00932     *pnum_off_keys = ph->num_off_keys;
00933     *ppoffkeys = ph->poff_keys;
00934 
00935     return IIIMF_STATUS_SUCCESS;
00936 }
00937 
00938 IIIMF_status
00939 iiimcf_get_object_descriptor_list(
00940     IIIMCF_handle handle,
00941     int *pnum_object_descriptors,
00942     const IIIMCF_object_descriptor **ppdesc
00943 )
00944 {
00945     IIIMCF_handle_rec *ph = (IIIMCF_handle_rec*) handle;
00946 
00947     *pnum_object_descriptors = ph->object_descriptor_size;
00948     *ppdesc = ph->pobjdesc;
00949 
00950     return IIIMF_STATUS_SUCCESS;
00951 }
00952 
00953 IIIMF_status
00954 iiimcf_get_im_id(
00955     IIIMCF_handle handle,
00956     int *pim_id
00957 )
00958 {
00959     IIIMCF_handle_rec *ph = (IIIMCF_handle_rec*) handle;
00960 
00961     if (!ph) {
00962        *pim_id = -1;
00963        return IIIMF_STATUS_IM_INVALID;
00964     }
00965 
00966     *pim_id = ph->im_id;
00967 
00968     if (ph->im_id < 0)
00969        return IIIMF_STATUS_IM_INVALID;
00970 
00971     return IIIMF_STATUS_SUCCESS;
00972 }
00973 
00974 void
00975 check_pathname(
00976     char *p
00977 )
00978 {
00979     char *q;
00980     int index = 0;
00981 
00982     while (*p) {
00983         if ((q = (strstr(p, "../")))) {
00984             index = p - q;
00985             if (index < 0)
00986                 index = -index;
00987             strcpy(p+index, p+index+3);
00988         } else if ((q = (strstr(p, "//")))) {
00989             index = p - q;
00990             if (index < 0)
00991                 index = -index;
00992             strcpy(p+index, p+index+1);
00993         } else if ((q = (strstr(p, "./")))) {
00994             index = p - q;
00995             if (index < 0)
00996                 index = -index;
00997             strcpy(p+index, p+index+2);
00998         } else {
00999             break ;
01000         }
01001     }
01002     return;
01003 }
01004 
01005 /* Local Variables: */
01006 /* c-file-style: "iiim-project" */
01007 /* End: */