/* iiimcf.c */ #define NODE_DEFAULT "localhost" #define SERVICE_DEFAULT "9010" #define TLS_DEFAULT "9011" #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_MEMORY_H #include #endif #include "iiimcfint.h" #include #define IIIMCF_DEFAULT_IC_HASH_TABLE_SIZE 17 #define IIIMCF_DEFAULT_TIMEOUT 10000 static void free_object_descriptor( IIIMCF_object_descriptor *pod, int n ); /******************************************************************************** util. functions ********************************************************************************/ IIIMP_card16* iiimcf_make_string( const IIIMP_card16 *str, int len ) { IIIMP_card16 *pu16; pu16 = (IIIMP_card16*) malloc(sizeof(*pu16) * (len + 1)); if (!pu16) return NULL; if (len > 0) memcpy(pu16, str, sizeof(*pu16) * len); pu16[len] = 0; return pu16; } int iiimcf_string_length( const IIIMP_card16 *str ) { int i; for (i = 0; *str; str++) i++; return i; } IIIMP_card16* iiimcf_duplicate_string( const IIIMP_card16 *str ) { if (!str) return NULL; return iiimcf_make_string(str, iiimcf_string_length(str)); } void iiimcf_lock_handle( IIIMCF_handle_rec *ph ) { THREAD_ID_OBJECT tid; THREAD_SET_CURRENT_ID(tid); if ((ph->thread_lock_count == 0) || (!THREAD_ID_EQUAL(ph->thread_owner_id, tid))) { LOCK_SYNC_OBJECT(ph->so); ASSERT(ph->thread_lock_count == 0); ph->thread_owner_id = tid; } ph->thread_lock_count++; } void iiimcf_unlock_handle( IIIMCF_handle_rec *ph ) { THREAD_ID_OBJECT tid; THREAD_SET_CURRENT_ID(tid); ASSERT(THREAD_ID_EQUAL(ph->thread_owner_id, tid)); ASSERT(ph->thread_lock_count > 0); ph->thread_lock_count--; if (ph->thread_lock_count == 0) { UNLOCK_SYNC_OBJECT(ph->so); } } /******************************************************************************** message handlers ********************************************************************************/ void iiimcf_unregister_langs( int n, IIIMCF_language_rec **ppl ) { IIIMCF_language_rec **pp, *p; int i; if (!ppl) return; for (pp = ppl, i = 0; i < n; i++, pp++) { p = *pp; if (p) { if (p->lang_id) free(p->lang_id); if (p->hrn) free(p->hrn); free(p); } } free(ppl); } static IIIMF_status iiimcf_register_langs( IIIMCF_handle_rec *ph, IIIMP_string *pstr ) { IIIMCF_language_rec **ppl, *pl; IIIMP_string *p; IIIMP_card16 *pu; char *plang_id, *pc; int i, n; iiimcf_unregister_langs(ph->num_langs, ph->pplangs); ph->pplangs = NULL; ph->num_langs = 0; for (n = 0, p = pstr; p; p = p->next) n++; ppl = (IIIMCF_language_rec**) malloc(sizeof(IIIMCF_language_rec*) * n); if (!ppl) return IIIMF_STATUS_MALLOC; memset(ppl, 0, sizeof(IIIMCF_language_rec*) * n); for (i = 0; i < n; i++) { pl = (IIIMCF_language_rec*) malloc(sizeof(*pl)); if (!pl) { iiimcf_unregister_langs(n, ppl); return IIIMF_STATUS_MALLOC; } memset(pl, 0, sizeof(*pl)); ppl[i] = pl; } ph->num_langs = n; ph->pplangs = ppl; for (p = pstr; p; p = p->next, ppl++) { pl = *ppl; plang_id = (char*) malloc(sizeof(char) * (p->len + 1)); if (!plang_id) { iiimcf_unregister_langs(ph->num_langs, ph->pplangs); ph->num_langs = 0; ph->pplangs = NULL; return IIIMF_STATUS_MALLOC; } for (i = 0, pu = p->ptr, pc = plang_id;i < p->len; i++) { *pc++ = (*pu++ & 0x7F); } *pc = '\0'; pl->lang_id = plang_id; } return IIIMF_STATUS_SUCCESS; } IIIMF_status iiimcf_register_trigger_keys( IIIMCF_handle_rec *ph, IIIMP_message *pmes ) { int i, n; IIIMP_keyevent_list *pimkl; IIIMP_keyevent *pimk; IIIMCF_keyevent *pkev; IIIMP_register_trigger_keys_v *pimrk = &pmes->v.register_trigger_keys; ASSERT(pmes->opcode == IM_REGISTER_TRIGGER_KEYS); pimkl = pimrk->trigger_on; n = pimkl->count; if (n > 0) { pkev = (IIIMCF_keyevent*) malloc(sizeof(IIIMCF_keyevent) * n); if (!pkev) return IIIMF_STATUS_MALLOC; if (ph->pon_keys) free(ph->pon_keys); ph->pon_keys = pkev; pimk = pimkl->keyevent; for (i = 0; i < n; i++, pkev++, pimk++) { pkev->keycode = pimk->keycode; pkev->keychar = pimk->keychar; pkev->modifier = pimk->modifier; pkev->time_stamp = pimk->time_stamp; } ph->num_on_keys = i; } pimkl = pimrk->trigger_off; n = pimkl->count; if (n > 0) { pkev = (IIIMCF_keyevent*) malloc(sizeof(IIIMCF_keyevent) * n); if (!pkev) { if (ph->pon_keys) free(ph->pon_keys); ph->num_on_keys = 0; return IIIMF_STATUS_MALLOC; } if (ph->poff_keys) free(ph->poff_keys); ph->poff_keys = pkev; pimk = pimkl->keyevent; for (i = 0; i < n; i++, pkev++, pimk++) { pkev->keycode = pimk->keycode; pkev->keychar = pimk->keychar; pkev->modifier = pimk->modifier; pkev->time_stamp = pimk->time_stamp; } ph->num_off_keys = i; } return IIIMF_STATUS_SUCCESS; } IIIMF_status iiimcf_register_hotkeys( IIIMCF_handle_rec *ph, IIIMP_message *pmes ) { int i, j, n, n_hkp, n_hotkeys; HOTKEY_LIST *hklist; IIIMCF_hotkey *hk; IIIMCF_keyevent *pkev; IIIMP_keyevent *pimk; IIIMP_register_hotkeys_v *pimrk = &pmes->v.register_hotkeys; ASSERT(pmes->opcode == IM_REGISTER_HOTKEYS); n_hkp = ph->num_of_hkprofiles; hklist = pimrk->hotkeys; n_hotkeys = pimrk->hotkeys->count; if (!n_hkp) { ph->phk_profile = (IIIMCF_hotkey_profile *) malloc(10 * sizeof(IIIMCF_hotkey_profile)); memset(ph->phk_profile, 0, 10 * sizeof(IIIMCF_hotkey_profile)); } else if (n_hkp > 10) { ph->phk_profile = (IIIMCF_hotkey_profile *) realloc((IIIMCF_hotkey_profile *)ph->phk_profile, (n_hkp + 1) * sizeof(IIIMCF_hotkey_profile)); } if (!ph->phk_profile) return IIIMF_STATUS_MALLOC; ph->phk_profile[n_hkp].scope = pimrk->scope; ph->phk_profile[n_hkp].profile_id = pimrk->profile_id; if (n_hotkeys > 0) { hk = (IIIMCF_hotkey *) malloc(sizeof(IIIMCF_hotkey) * n_hotkeys); if (!hk) return IIIMF_STATUS_MALLOC; ph->phk_profile[n_hkp].phot_keys = hk; for(i=0; ihotkey[i].hotkeyctrl.hotkey_id; hk[i].state_flag = hklist->hotkey[i].hotkeyctrl.state_flag; hk[i].action_flag = hklist->hotkey[i].hotkeyctrl.action_flag; n = hklist->hotkey[i].hotkeylist->count; if (n > 0) { pkev = (IIIMCF_keyevent*) malloc(sizeof(IIIMCF_keyevent) * n); if (!pkev) return IIIMF_STATUS_MALLOC; hk[i].keys = pkev; pimk = hklist->hotkey[i].hotkeylist->keyevent; for (j = 0; j < n; j++, pkev++, pimk++) { pkev->keycode = pimk->keycode; pkev->keychar = pimk->keychar; pkev->modifier = pimk->modifier; pkev->time_stamp = pimk->time_stamp; } hk[i].nkeys = j; } } ph->phk_profile[n_hkp].num_hotkeys = n_hotkeys; } ph->num_of_hkprofiles = n_hkp + 1; return IIIMF_STATUS_SUCCESS; } static IIIMF_status iiimcf_register_object_descriptor_list( IIIMCF_handle_rec *ph, IIIMP_object_descriptor *piiimp_objdesc ) { int n; IIIMP_object_descriptor *pimod; IIIMCF_object_descriptor *pod, *podh; IIIMP_card16 *pu16; free_object_descriptor(ph->pobjdesc, ph->object_descriptor_size); ph->pobjdesc = NULL; ph->object_descriptor_size = 0; for (n = 0, pimod = piiimp_objdesc; pimod; pimod = pimod->next) n++; pod = podh = (IIIMCF_object_descriptor*) malloc(sizeof(*pod) * n); if (!pod) return IIIMF_STATUS_MALLOC; memset(podh, 0, sizeof(*podh) * n); for (pimod = piiimp_objdesc; pimod; pimod = pimod->next, pod++) { pod->category = pimod->category; pod->size = pimod->size; pod->predefined_id = pimod->id_pre; pod->dynamic_id = pimod->id_dyn; pu16 = iiimcf_make_string(pimod->rdun->ptr, pimod->rdun->len); if (!pu16) { free_object_descriptor(podh, n); return IIIMF_STATUS_MALLOC; } pod->domain = pu16; pu16 = iiimcf_make_string(pimod->hrn->ptr, pimod->hrn->len); if (!pu16) { free_object_descriptor(podh, n); return IIIMF_STATUS_MALLOC; } pod->hrn = pu16; pu16 = iiimcf_make_string(pimod->signature->ptr, pimod->signature->len); if (!pu16) { free_object_descriptor(podh, n); return IIIMF_STATUS_MALLOC; } pod->signature = pu16; pu16 = iiimcf_make_string(pimod->user->ptr, pimod->user->len); if (!pu16) { free_object_descriptor(podh, n); return IIIMF_STATUS_MALLOC; } pod->user = pu16; } ph->pobjdesc = podh; ph->object_descriptor_size = n; return IIIMF_STATUS_SUCCESS; } IIIMF_status iiimcf_setimvalues( IIIMCF_handle_rec *ph, IIIMP_message *pmes ) { IIIMF_status st; IIIMP_imattribute *pimattrs; ASSERT(pmes->opcode == IM_SETIMVALUES); for (pimattrs = pmes->v.setimvalues.attr_list; pimattrs; pimattrs = pimattrs->next) { switch (pimattrs->id_pre) { case IIIMP_IMATTRIBUTE_INPUT_METHOD_LIST: st = iiimcf_register_input_method_list(ph, pimattrs->value.inputmethod_descriptor); if (st != IIIMF_STATUS_SUCCESS) return st; break; case IIIMP_IMATTRIBUTE_OBJECT_DESCRIPTOR_LIST: st = iiimcf_register_object_descriptor_list(ph, pimattrs->value.object_descriptor); if (st != IIIMF_STATUS_SUCCESS) return st; break; default: /* simply ignore */ break; } } return IIIMF_STATUS_SUCCESS; } static void free_object_descriptor( IIIMCF_object_descriptor *pod, int n ) { int i; IIIMCF_object_descriptor *pod2 = pod; if (!pod) return; for (i = 0; i < n; i++, pod++) { if (pod->domain) free((IIIMP_card16*) pod->domain); if (pod->hrn) free((IIIMP_card16*) pod->hrn); if (pod->signature) free((IIIMP_card16*) pod->signature); if (pod->user) free((IIIMP_card16*) pod->user); } free(pod2); } /******************************************************************************** connection/send/receive management ********************************************************************************/ static void iiimcf_delete_stream( IIIMCF_handle_rec *ph ) { if (ph->pconf && ph->pconf->use_tls) { iiimf_delete_tls_stream(ph->pstream); } else { iiimf_delete_socket_stream(ph->pstream); } ph->pstream = NULL; } IIIMF_status iiimcf_connect( IIIMCF_handle_rec *ph ) { IIIMF_status st = IIIMF_STATUS_SUCCESS; IIIMP_message *pmes; if (!ph->data_s) ph->data_s = iiimp_data_s_new(); if (!ph->data_s) return IIIMF_STATUS_MALLOC; if (!ph->pstream) { IIIMCF_client_conf *pconf; if (ph->pconf) { pconf = ph->pconf; ph->pconf = NULL; } else { pconf = ph->penv->pconf; } for ( ; pconf; pconf = pconf->next) { /* use TLS */ if (pconf->use_tls) { /* check whther libiiimp is compiled with TLS support */ st = iiimf_tls_supported(); if (st != IIIMF_STATUS_SUCCESS) continue; st = iiimf_connect_tls_stream(pconf->server_node ? pconf->server_node : NODE_DEFAULT, pconf->service ? pconf->service : TLS_DEFAULT, IIIMCF_DEFAULT_TIMEOUT, &ph->pstream); if (st != IIIMF_STATUS_SUCCESS) continue; /* TODO*/ iiimf_tls_set_certificate(ph->pstream, pconf->cert_file, pconf->cert_key, pconf->ca_file, pconf->ca_path); } else { st = iiimf_connect_socket_stream(pconf->server_node ? pconf->server_node : NODE_DEFAULT, pconf->service ? pconf->service : SERVICE_DEFAULT, IIIMCF_DEFAULT_TIMEOUT, &ph->pstream); } if (st == IIIMF_STATUS_SUCCESS) { /* set current configuration to IIIMCF_handle */ ph->pconf = pconf; break; } } } if (st != IIIMF_STATUS_SUCCESS) { /* finally try to connect to 127.0.0.1:9010 */ st = iiimf_connect_socket_stream(NODE_DEFAULT, SERVICE_DEFAULT, IIIMCF_DEFAULT_TIMEOUT, &ph->pstream); } if (st != IIIMF_STATUS_SUCCESS) return st; st = iiimcf_create_im_connect_message(ph, &pmes); if (st != IIIMF_STATUS_SUCCESS) return st; st = iiimf_stream_send(ph->pstream, ph->data_s, pmes); iiimp_message_delete(ph->data_s, pmes); if (st != IIIMF_STATUS_SUCCESS) goto reconnect; st = iiimcf_wait_message(ph, NULL, IM_CONNECT_REPLY, &pmes); if (st != IIIMF_STATUS_SUCCESS) { if (pmes) iiimp_message_delete(ph->data_s, pmes); goto reconnect; } ph->im_id = pmes->im_id; st = iiimp_data_s_limit_protocol_version(ph->data_s, ph->server_protocol_version); if (st != IIIMF_STATUS_SUCCESS) return st; st = iiimcf_register_langs(ph, pmes->v.connect_reply.language); iiimp_message_delete(ph->data_s, pmes); /* send CLIENTDESCRIPTOR */ st = iiimcf_create_client_descriptor_message(ph, &pmes); if (st != IIIMF_STATUS_SUCCESS) return st; st = iiimf_stream_send(ph->pstream, ph->data_s, pmes); iiimp_message_delete(ph->data_s, pmes); if (st != IIIMF_STATUS_SUCCESS) return st; st = iiimcf_wait_message(ph, NULL, IM_SETIMVALUES_REPLY, NULL); return st; reconnect: /* * in this case, iiimcf connects iiimsf successfully, * but iiimsf refuses the connection. * * so, try to next iiimsf if any. */ if (!ph->pconf) return st; if (ph->pconf->next) { /* first, destroy current stream */ iiimcf_delete_stream(ph); /* ph->pconf store current configuration */ ph->pconf = ph->pconf->next; return iiimcf_connect(ph); } return st; } static IIIMF_status iiimcf_hungup( IIIMCF_handle_rec *ph ) { ph->im_id = -1; /* Should we delete downloaded objects? */ /* iiimcf_delete_all_downloaded_objects(ph); */ if (ph->pstream) { iiimcf_delete_stream(ph); } #if 0 if (ph->data_s) { iiimp_data_s_delete(ph->data_s); ph->data_s = NULL; } #endif return iiimcf_cleanup_context(ph, 0); } static IIIMF_status iiimcf_disconnect( IIIMCF_handle_rec *ph ) { IIIMF_status st1 = IIIMF_STATUS_SUCCESS, st2 = IIIMF_STATUS_SUCCESS; IIIMP_message *pmes; if (IIIMCF_IS_CONNECTED(ph)) { pmes = iiimp_disconnect_new(ph->data_s, ph->im_id); if (pmes) { st1 = iiimf_stream_send(ph->pstream, ph->data_s, pmes); iiimp_message_delete(ph->data_s, pmes); if (st1 == IIIMF_STATUS_SUCCESS) { st1 = iiimcf_wait_message(ph, NULL, IM_DISCONNECT_REPLY, NULL); } } else { st1 = IIIMF_STATUS_MALLOC; } } st2 = iiimcf_cleanup_context(ph, 1); if (st2 != IIIMF_STATUS_SUCCESS) return st2; return st1; } IIIMF_status iiimcf_send_message( IIIMCF_handle_rec *ph, IIIMP_message *pmes, int deletep ) { IIIMF_status st; st = iiimf_stream_send(ph->pstream, ph->data_s, pmes); if (deletep) iiimp_message_delete(ph->data_s, pmes); if (st == IIIMF_STATUS_SUCCESS) return IIIMF_STATUS_SUCCESS; if ((st == IIIMF_STATUS_CONNECTION_CLOSED) || (st == IIIMF_STATUS_STREAM_SEND)) { iiimcf_hungup(ph); } return st; } IIIMF_status iiimcf_receive_message( IIIMCF_handle_rec *ph, IIIMP_message **ppmes ) { IIIMF_status st; st = iiimf_stream_receive(ph->pstream, ph->data_s, ppmes); if (st == IIIMF_STATUS_SUCCESS) { if ((ph->im_id >= 0) && ((*ppmes)->im_id != ph->im_id)) { iiimp_message_delete(ph->data_s, *ppmes); *ppmes = NULL; return IIIMF_STATUS_IM_INVALID; } return IIIMF_STATUS_SUCCESS; } if ((st == IIIMF_STATUS_CONNECTION_CLOSED) || (st == IIIMF_STATUS_STREAM_RECEIVE)) { iiimcf_hungup(ph); } return st; } /******************************************************************************** create & destroy handle ********************************************************************************/ IIIMF_status iiimcf_create_handle( IIIMCF_attr attr, IIIMCF_handle *phandle ) { IIIMF_status st; int disable_automatic_connection_restoration = 0; IIIMCF_handle_rec *ph; IIIMCF_context_rec **ppc; st = iiimcf_attr_get_integer_value(attr, IIIMCF_ATTR_DISABLE_AUTOMATIC_RESTORATION, &disable_automatic_connection_restoration); if ((st != IIIMF_STATUS_SUCCESS) && (st != IIIMF_STATUS_NO_ATTR_VALUE)) { return st; } ph = (IIIMCF_handle_rec*) malloc(sizeof(*ph)); if (!ph) { return IIIMF_STATUS_MALLOC; } memset(ph, 0, sizeof(*ph)); ph->context_table_size = IIIMCF_DEFAULT_IC_HASH_TABLE_SIZE; ppc = (IIIMCF_context_rec**) malloc(sizeof(*ppc) * ph->context_table_size); if (!ppc) { free(ph); return IIIMF_STATUS_MALLOC; } memset(ppc, 0, sizeof(*ppc) * ph->context_table_size); ph->ppcontext_table = ppc; ph->im_id = -1; /* When not received IM_PROTOCOL_VERSION, we assume the server supports protocol version 2. */ ph->server_protocol_version = 2; INIT_SYNC_OBJECT(ph->so); if (disable_automatic_connection_restoration) ph->disable_automatic_connection_restoration = 1; else ph->disable_automatic_connection_restoration = 0; st = iiimcf_create_client_env(attr, &ph->penv); if (st != IIIMF_STATUS_SUCCESS) { DESTROY_SYNC_OBJECT(ph->so); free(ppc); free(ph); return st; } st = iiimcf_register_predefined_components(ph); if (st != IIIMF_STATUS_SUCCESS) { iiimcf_delete_client_env(ph->penv); DESTROY_SYNC_OBJECT(ph->so); free(ppc); free(ph); return st; } st = iiimcf_connect(ph); if (st != IIIMF_STATUS_SUCCESS) { iiimcf_destroy_handle(ph); return st; } *phandle = ph; return IIIMF_STATUS_SUCCESS; } IIIMF_status iiimcf_destroy_handle( IIIMCF_handle handle ) { IIIMCF_handle_rec *ph = (IIIMCF_handle_rec*) handle; int i,j; iiimcf_disconnect(ph); iiimcf_unregister_langs(ph->num_langs, ph->pplangs); iiimcf_unregister_input_method_list(ph->num_input_methods, ph->ppinput_methods); /* must be before iiimcf_delete_client_env */ if (ph->pstream) iiimcf_delete_stream(ph); iiimcf_delete_client_env(ph->penv); iiimcf_delete_all_components(ph); iiimcf_delete_all_downloaded_objects(ph); free_object_descriptor(ph->pobjdesc, ph->object_descriptor_size); if (ph->pon_keys) free(ph->pon_keys); if (ph->poff_keys) free(ph->poff_keys); if (ph->phk_profile) { for (i=0; i < ph->num_of_hkprofiles; ++i) { if (ph->phk_profile[i].phot_keys) { for (j=0; j < ph->phk_profile[i].num_hotkeys; ++j) { if (ph->phk_profile[i].phot_keys[j].keys) free(ph->phk_profile[i].phot_keys[j].keys); } free(ph->phk_profile[i].phot_keys); } } free(ph->phk_profile); } if (ph->data_s) iiimp_data_s_delete(ph->data_s); free(ph->ppcontext_table); DESTROY_SYNC_OBJECT(ph->so); free(ph); return IIIMF_STATUS_SUCCESS; } /******************************************************************************** initialization & finalization ********************************************************************************/ static int iiimcf_inited = 0; IIIMF_status iiimcf_initialize( IIIMCF_attr attr ) { if (iiimcf_inited) return IIIMF_STATUS_SUCCESS; if (!EIMIL_initialize()) return IIIMF_STATUS_FAIL; iiimcf_inited = 1; return IIIMF_STATUS_SUCCESS; } IIIMF_status iiimcf_finalize() { EIMIL_finalize(); iiimcf_inited = 0; return IIIMF_STATUS_SUCCESS; } /******************************************************************************** misc. information ********************************************************************************/ IIIMF_status iiimcf_get_version_number( IIIMCF_handle handle, int flag, int *pversion_number ) { IIIMCF_handle_rec *ph = (IIIMCF_handle_rec*) handle; if (flag & ~IIIMCF_VERSION_FLAGS_MASK) { return IIIMF_STATUS_ARGUMENT; } if (flag & IIIMCF_LIBRARY_VERSION) { if ((flag & ~IIIMCF_VERSION_FLAGS_ITEM_MASK) != IIIMCF_LIBRARY_VERSION) { return IIIMF_STATUS_ARGUMENT; } if (flag & IIIMCF_MAJOR_VERSION) { if ((flag & ~IIIMCF_VERSION_FLAGS_CATEGORY_MASK) != IIIMCF_MAJOR_VERSION) { return IIIMF_STATUS_ARGUMENT; } *pversion_number = LIBIIIMCF_MAJOR_VERSION; } else if (flag & IIIMCF_MINOR_VERSION) { if ((flag & ~IIIMCF_VERSION_FLAGS_CATEGORY_MASK) != IIIMCF_MINOR_VERSION) { return IIIMF_STATUS_ARGUMENT; } *pversion_number = LIBIIIMCF_MINOR_VERSION; } else { return IIIMF_STATUS_ARGUMENT; } } else if (flag & IIIMCF_PROTOCOL_VERSION) { if ((flag & ~IIIMCF_VERSION_FLAGS_ITEM_MASK) != IIIMCF_PROTOCOL_VERSION) { return IIIMF_STATUS_ARGUMENT; } if (flag & IIIMCF_MAJOR_VERSION) { if ((flag & ~IIIMCF_VERSION_FLAGS_CATEGORY_MASK) != IIIMCF_MAJOR_VERSION) { return IIIMF_STATUS_ARGUMENT; } *pversion_number = iiimp_data_s_get_protocol_version(ph->data_s); } else if (flag & IIIMCF_MINOR_VERSION) { if ((flag & ~IIIMCF_VERSION_FLAGS_CATEGORY_MASK) != IIIMCF_MINOR_VERSION) { return IIIMF_STATUS_ARGUMENT; } /* Now IM_CONNECT has no minor version */ *pversion_number = 0; } else { return IIIMF_STATUS_ARGUMENT; } } else { return IIIMF_STATUS_ARGUMENT; } return IIIMF_STATUS_SUCCESS; } IIIMF_status iiimcf_get_supported_languages( IIIMCF_handle handle, int *pnum_langs, IIIMCF_language **pplangs ) { IIIMCF_handle_rec *ph = (IIIMCF_handle_rec*) handle; *pnum_langs = ph->num_langs; *pplangs = (IIIMCF_language*) ph->pplangs; return IIIMF_STATUS_SUCCESS; } IIIMF_status iiimcf_get_language_id( IIIMCF_language lang, const char **plangid ) { IIIMCF_language_rec *pl = (IIIMCF_language_rec*) lang; *plangid = pl->lang_id; return IIIMF_STATUS_SUCCESS; } IIIMF_status iiimcf_get_trigger_keys( IIIMCF_handle handle, int *pnum_on_keys, const IIIMCF_keyevent **pponkeys, int *pnum_off_keys, const IIIMCF_keyevent **ppoffkeys ) { IIIMCF_handle_rec *ph = (IIIMCF_handle_rec*) handle; if ((ph->num_on_keys == 0) && (ph->num_off_keys == 0)) return IIIMF_STATUS_STATIC_EVENT_FLOW; *pnum_on_keys = ph->num_on_keys; *pponkeys = ph->pon_keys; *pnum_off_keys = ph->num_off_keys; *ppoffkeys = ph->poff_keys; return IIIMF_STATUS_SUCCESS; } IIIMF_status iiimcf_get_object_descriptor_list( IIIMCF_handle handle, int *pnum_object_descriptors, const IIIMCF_object_descriptor **ppdesc ) { IIIMCF_handle_rec *ph = (IIIMCF_handle_rec*) handle; *pnum_object_descriptors = ph->object_descriptor_size; *ppdesc = ph->pobjdesc; return IIIMF_STATUS_SUCCESS; } IIIMF_status iiimcf_get_im_id( IIIMCF_handle handle, int *pim_id ) { IIIMCF_handle_rec *ph = (IIIMCF_handle_rec*) handle; if (!ph) { *pim_id = -1; return IIIMF_STATUS_IM_INVALID; } *pim_id = ph->im_id; if (ph->im_id < 0) return IIIMF_STATUS_IM_INVALID; return IIIMF_STATUS_SUCCESS; } void check_pathname( char *p ) { char *q; int index = 0; while (*p) { if ((q = (strstr(p, "../")))) { index = p - q; if (index < 0) index = -index; strcpy(p+index, p+index+3); } else if ((q = (strstr(p, "//")))) { index = p - q; if (index < 0) index = -index; strcpy(p+index, p+index+1); } else if ((q = (strstr(p, "./")))) { index = p - q; if (index < 0) index = -index; strcpy(p+index, p+index+2); } else { break ; } } return; } /* Local Variables: */ /* c-file-style: "iiim-project" */ /* End: */