/* message.c */ #include "iiimcfint.h" static IIIMF_status iiimcf_reply_to_foward_event_with_operations( IIIMCF_context_rec *pc, IIIMP_message *pmes ) { IIIMCF_handle_rec *ph = pc->ph; IIIMP_operation *pop = pmes->v.forward_event_with_operations_reply.operation; IIIMP_message *preply; preply = iiimp_forward_event_with_operations_reply_new(ph->data_s, ph->im_id, pc->ic_id, pop); if (!preply) return IIIMF_STATUS_MALLOC; return iiimcf_send_message(ph, preply, 1); } static IIIMF_status iiimcf_reply_aux_message( IIIMCF_handle_rec *ph, IIIMP_message *pmes ) { IIIMP_string *pimname; IIIMP_message *preply; if (pmes->opcode == IM_AUX_START) { pimname = iiimp_string_new(ph->data_s, pmes->v.aux_start.input_method_name->len, pmes->v.aux_start.input_method_name->ptr); if (!pimname) return IIIMF_STATUS_MALLOC; preply = iiimp_aux_start_reply_new(ph->data_s, pmes->im_id, pmes->ic_id, pmes->v.aux_start.class_index, pimname); } else if (pmes->opcode == IM_AUX_DRAW) { pimname = iiimp_string_new(ph->data_s, pmes->v.aux_draw.input_method_name->len, pmes->v.aux_draw.input_method_name->ptr); if (!pimname) return IIIMF_STATUS_MALLOC; preply = iiimp_aux_draw_reply_new(ph->data_s, pmes->im_id, pmes->ic_id, pmes->v.aux_draw.class_index, pimname); } else if (pmes->opcode == IM_AUX_DONE) { pimname = iiimp_string_new(ph->data_s, pmes->v.aux_done.input_method_name->len, pmes->v.aux_done.input_method_name->ptr); if (!pimname) return IIIMF_STATUS_MALLOC; preply = iiimp_aux_done_reply_new(ph->data_s, pmes->im_id, pmes->ic_id, pmes->v.aux_done.class_index, pimname); } else { return IIIMF_STATUS_ARGUMENT; } if (!preply) { iiimp_string_delete(ph->data_s, pimname); return IIIMF_STATUS_MALLOC; } return iiimcf_send_message(ph, preply, 1); } static IIIMF_status iiimcf_reply_message( IIIMCF_handle_rec *ph, IIIMP_message *pmes ) { if (!pmes) return IIIMF_STATUS_MALLOC; return iiimcf_send_message(ph, pmes, 1); } /* * Process the message, pmes. * pmes is automatically deleted. */ IIIMF_status iiimcf_process_message( IIIMCF_handle_rec *ph, IIIMP_message *pmes ) { IIIMF_status st = IIIMF_STATUS_SUCCESS; IIIMF_status st_r = IIIMF_STATUS_SUCCESS; IIIMP_message *preply; IIIMCF_context_rec *pc; if (pmes->ic_id >= 0) { pc = iiimcf_lookup_context(ph, pmes->ic_id); if (!pc) { iiimp_message_delete(ph->data_s, pmes); return IIIMF_STATUS_IC_INVALID; } } else { pc = NULL; } switch (pmes->opcode) { case IM_CONNECT_REPLY: if (ph->im_id >= 0) return IIIMF_STATUS_SEQUENCE_STATE; ph->im_id = pmes->im_id; break; case IM_PROTOCOL_VERSION: ph->server_protocol_version = pmes->v.protocol_version.number; ph->num_of_hkprofiles = 0; ph->num_of_ns = 0; ph->num_of_nsl = 0; ph->curr_profile_id = -1; break; case IM_REGISTER_TRIGGER_KEYS: st = iiimcf_register_trigger_keys(ph, pmes); break; case IM_REGISTER_HOTKEYS: st = iiimcf_register_hotkeys(ph, pmes); break; case IM_TRIGGER_NOTIFY: if (pmes->v.trigger_notify.flag == 0) st = iiimcf_receive_trigger_notify(pc, 1); else st = iiimcf_receive_trigger_notify(pc, 0); preply = iiimp_trigger_notify_reply_new(ph->data_s, ph->im_id, pc->ic_id); st_r = iiimcf_reply_message(ph, preply); break; case IM_HOTKEY_NOTIFY: st = iiimcf_receive_hotkey_notify(pc); preply = iiimp_hotkey_notify_reply_new(ph->data_s, ph->im_id, pc->ic_id); st_r = iiimcf_reply_message(ph, preply); break; case IM_HOTKEY_STATE_NOTIFY: if (pmes->v.hotkey_state_notify.current_state_flag) { st = iiimcf_receive_trigger_notify(pc, 1); } else { st = iiimcf_receive_trigger_notify(pc, 0); } /* preply = iiimp_hotkey_state_notify_reply_new(ph->data_s, ph->im_id, pc->ic_id); st_r = iiimcf_reply_message(ph, preply); */ break; case IM_SELECT_HOTKEY_PROFILE: ph->curr_scope = pmes->v.select_hotkey_profile.scope; ph->curr_profile_id = pmes->v.select_hotkey_profile.profile_id; /* maybe we sould reply this message */ break; case IM_FILE_OPERATION: st = iiimcf_perform_file_operation(ph, pmes); break; case IM_FORWARD_EVENT: st = iiimcf_receive_forwarded_event(pc, pmes); preply = iiimp_forward_event_reply_new(ph->data_s, ph->im_id, pc->ic_id); st_r = iiimcf_reply_message(ph, preply); break; case IM_FORWARD_EVENT_WITH_OPERATIONS: st_r = iiimcf_reply_to_foward_event_with_operations(pc, pmes); break; case IM_PREEDIT_START: st = iiimcf_toggle_preedit(pc, 1); preply = iiimp_preedit_start_reply_new(ph->data_s, ph->im_id, pc->ic_id, -1); st_r = iiimcf_reply_message(ph, preply); break; case IM_PREEDIT_DRAW: st = iiimcf_update_preedit(pc, pmes); preply = iiimp_preedit_draw_reply_new(ph->data_s, ph->im_id, pc->ic_id); st_r = iiimcf_reply_message(ph, preply); break; case IM_PREEDIT_DONE: st = iiimcf_toggle_preedit(pc, 0); preply = iiimp_preedit_done_reply_new(ph->data_s, ph->im_id, pc->ic_id); st_r = iiimcf_reply_message(ph, preply); break; case IM_STATUS_START: st = iiimcf_toggle_status(pc, 1); preply = iiimp_status_start_reply_new(ph->data_s, ph->im_id, pc->ic_id); st_r = iiimcf_reply_message(ph, preply); break; case IM_STATUS_DRAW: st = iiimcf_update_status(pc, pmes); preply = iiimp_status_draw_reply_new(ph->data_s, ph->im_id, pc->ic_id); st_r = iiimcf_reply_message(ph, preply); break; case IM_STATUS_DONE: st = iiimcf_toggle_status(pc, 0); preply = iiimp_status_done_reply_new(ph->data_s, ph->im_id, pc->ic_id); st_r = iiimcf_reply_message(ph, preply); break; case IM_LOOKUP_CHOICE_START: st = iiimcf_lookup_choice_start(pc, pmes); preply = iiimp_lookup_choice_start_reply_new(ph->data_s, ph->im_id, pc->ic_id); st_r = iiimcf_reply_message(ph, preply); break; case IM_LOOKUP_CHOICE_DRAW: st = iiimcf_update_lookup_choice(pc, pmes); preply = iiimp_lookup_choice_draw_reply_new(ph->data_s, ph->im_id, pc->ic_id); st_r = iiimcf_reply_message(ph, preply); break; case IM_LOOKUP_CHOICE_PROCESS: st = iiimcf_process_lookup_choice(pc, pmes); preply = iiimp_lookup_choice_process_reply_new(ph->data_s, ph->im_id, pc->ic_id); st_r = iiimcf_reply_message(ph, preply); break; case IM_LOOKUP_CHOICE_DONE: st = iiimcf_lookup_choice_done(pc); preply = iiimp_lookup_choice_done_reply_new(ph->data_s, ph->im_id, pc->ic_id); st_r = iiimcf_reply_message(ph, preply); break; case IM_AUX_START: st = iiimcf_enable_aux(pc, pmes); st_r = iiimcf_reply_aux_message(ph, pmes); break; case IM_AUX_DRAW: st = iiimcf_update_aux_draw(pc, pmes); st_r = iiimcf_reply_aux_message(ph, pmes); break; case IM_AUX_DONE: st = iiimcf_disable_aux(pc, pmes); st_r = iiimcf_reply_aux_message(ph, pmes); break; case IM_COMMIT_STRING: st = iiimcf_commit_string(pc, pmes); break; case IM_SETIMVALUES: st = iiimcf_setimvalues(ph, pmes); preply = iiimp_setimvalues_reply_new(ph->data_s, ph->im_id); st_r = iiimcf_reply_message(ph, preply); break; } iiimp_message_delete(ph->data_s, pmes); if (st_r != IIIMF_STATUS_SUCCESS) return st_r; return st; } static int match_message( IIIMCF_handle_rec *ph, IIIMCF_context_rec *pc, int opcode, IIIMP_message *pmes ) { if (opcode != pmes->opcode) return 0; if ((ph->im_id < 0) && (opcode == IM_CONNECT_REPLY)) return 1; if (ph->im_id != pmes->im_id) return 0; if (!pc) return 1; if (pc->ic_id != pmes->ic_id) return 0; return 1; } IIIMF_status iiimcf_wait_message( IIIMCF_handle_rec *ph, IIIMCF_context_rec *pc, int opcode, IIIMP_message **ppmes ) { IIIMF_status st; IIIMP_message *pmes; for (;;) { st = iiimcf_receive_message(ph, &pmes); if (st != IIIMF_STATUS_SUCCESS) return st; if (match_message(ph, pc, opcode, pmes)) { if (ppmes) { *ppmes = pmes; } else { iiimp_message_delete(ph->data_s, pmes); } return IIIMF_STATUS_SUCCESS; } st = iiimcf_process_message(ph, pmes); if (st != IIIMF_STATUS_SUCCESS) return st; } return IIIMF_STATUS_SUCCESS; } /* * Send pmes, which is deleted, and then wait for the responce of * (pc, opcode), return set it to ppmes if it is not NULL. * Notice that this function allows pmes == *ppmes!!! */ IIIMF_status iiimcf_request_message( IIIMCF_handle_rec *ph, IIIMP_message *pmes, IIIMCF_context_rec *pc, int opcode, IIIMP_message **ppmes ) { IIIMF_status st; IIIMCF_LOCK_HANDLE(ph); /* By other threads, IC may be invalidated. So check it first because valid IC is indispensable for reply message. */ if (pc && IIIMCF_IS_IC_INVALID(pc)) { iiimp_message_delete(ph->data_s, pmes); IIIMCF_UNLOCK_HANDLE(ph); return IIIMF_STATUS_IC_INVALID; } if (!IIIMCF_IS_CONNECTED(ph)) { if (ph->disable_automatic_connection_restoration) { iiimp_message_delete(ph->data_s, pmes); IIIMCF_UNLOCK_HANDLE(ph); return IIIMF_STATUS_CONNECTION_CLOSED; } st = iiimcf_connect(ph); if (st != IIIMF_STATUS_SUCCESS) { iiimp_message_delete(ph->data_s, pmes); IIIMCF_UNLOCK_HANDLE(ph); return st; } } st = iiimcf_send_message(ph, pmes, 1); if (st == IIIMF_STATUS_SUCCESS) { st = iiimcf_wait_message(ph, NULL, opcode, ppmes); } IIIMCF_UNLOCK_HANDLE(ph); return st; } /* Local Variables: */ /* c-file-style: "iiim-project" */ /* End: */