Back to index

im-sdk  12.3.91
IIIMP_ICState.cpp
Go to the documentation of this file.
00001 #include <config.h>
00002 #include <stdio.h>
00003 #include <vector>
00004 #include "IIIMP_ICState.hh"
00005 #include "IIIMPTrans.hh"
00006 #include "IIIMPUtil.hh"
00007 
00008 /*******************************************************************************
00009                 Initial ICState
00010 *******************************************************************************/
00011 
00012 IIIMP_ICState_REQUESTED*
00013 IIIMP_ICState::start_request()
00014 {
00015     IIIMP_ICState_REQUESTED *picsr = new IIIMP_ICState_REQUESTED(this);
00016     // TODO: throw memory error.
00017     change_state(*picsr, false);
00018     return picsr;
00019 }
00020 
00021 
00022 bool
00023 IIIMP_ICState::message_proc(
00024     void *x_pmes
00025 )
00026 {
00027     IIIMP_message *pmes = (IIIMP_message*) x_pmes;
00028 
00029     switch (pmes->opcode) {
00030       case IM_TRIGGER_NOTIFY:
00031       {
00032          bool flag = (pmes->v.trigger_notify.flag == 0) ? true : false;
00033           if (ihk->get_lang_selection())
00034               ihk->set_lang_selection(false);
00035          return start_request()->toggle_server_convmode(flag);
00036       }
00037       case IM_HOTKEY_NOTIFY:
00038       {
00039           int hotkey_id = pmes->v.hotkey_notify.hotkey_id;
00040           int ikev = pmes->v.hotkey_notify.index;
00041           ihk->set_hotkey_mode(true);
00042           return ihk->process_hotkey(this, hotkey_id, ikev);
00043       }
00044       case IM_LOOKUP_CHOICE_START_REPLY:
00045       {
00046           int keycode = 0;
00047           return ihk->draw_lang_selection_window(this, keycode);
00048       }
00049       case IM_LOOKUP_CHOICE_DRAW_REPLY:
00050       {
00051           if (ihk->get_hotkey_mode())
00052               return ihk->send_hotkey_reply(this);
00053           return true;
00054       }
00055       case IM_LOOKUP_CHOICE_DONE_REPLY:
00056       {
00057           if (ihk->get_hotkey_mode())
00058               return ihk->send_hotkey_reply(this);
00059           return true;
00060       }
00061       case IM_SETICVALUES:
00062        return start_request()->set_values(pmes);
00063       case IM_SETICFOCUS:
00064       {
00065          return start_request()->toggle_icfocus(true);
00066       }
00067       case IM_UNSETICFOCUS:
00068        return start_request()->toggle_icfocus(false);
00069       case IM_RESETIC:
00070        return start_request()->reset();
00071       case IM_AUX_SETVALUES:
00072        return start_request()->aux_setvalues(pmes);
00073       case IM_AUX_GETVALUES:
00074        return start_request()->aux_getvalues(pmes);
00075       case IM_FORWARD_EVENT:
00076       {
00077          if (ihk->get_lang_selection()) {
00078              ihk->set_forward_event(true);
00079              return ihk->process_lang_selection_window(this, pmes);
00080          } else
00081              return start_request()->forward_event(pmes);
00082       }
00083       case IM_FORWARD_EVENT_WITH_OPERATIONS:
00084        return start_request()->forward_event_with_operations(pmes);
00085       case IM_DESTROYIC:
00086        return start_request()->destroyic();
00087 
00088       default:
00089        LOG_ERROR("Invalid message(IC normal state):%d", pmes->opcode);
00090     }
00091     return true;
00092 }
00093 
00094 IIIMP_ICState::IIIMP_ICState(
00095     CARD16BIT ic_id,
00096     IIIMP_IMState* piiims,
00097     ICHandler *pich,
00098     IMLExec_ICState *pimlex
00099 ) : ICState(ic_id, piiims, pich, pimlex)
00100 {
00101     pshared = new SharedState();
00102     pshared->conversion_mode = false;
00103     pshared->preedit = false;
00104     pshared->status = false;
00105     pshared->lookup_choice = false;
00106 
00107     langimlist.clear();
00108     ihk = new IIIMP_hotkey(this);
00109 }
00110 
00111 IIIMP_ICState*
00112 IIIMP_ICState::create(
00113     CARD16BIT ic_id,
00114     IIIMP_IMState* piiims,
00115     ICHandler *pich
00116 )
00117 {
00118     // The current implementation use the same IMLExec.
00119     // Note that it will be changed later.
00120     IMLExec_ICState *pimlex = new IMLExec_ICState();
00121     // memory error;
00122     if (!pimlex) return NULL;
00123     IIIMP_ICState *pics = new IIIMP_ICState(ic_id, piiims, pich, pimlex);
00124     // memory error;
00125     if (!pics) {
00126        delete pimlex;
00127        return NULL;
00128     }
00129     return pics;
00130 }
00131 
00132 void
00133 IIIMP_ICState::destroy()
00134 {
00135     if (get_ichandler()) {
00136        /* Normally, client must send IM_DESTROYIC before terminating IC,
00137           hence, ichandler must be dead here.  But when client abruptly
00138           shut down the connection, we have to clean up ichandler.  */
00139        get_ichandler()->destroy();
00140        invalidate_ichandler();
00141     }
00142     ICState::destroy();
00143 }
00144 
00145 IMSvr *
00146 IIIMP_ICState::get_imsvr ()
00147 {
00148     IMSvr *imsvr;
00149     IMInputContext *pimic;
00150 
00151     pimic = get_iminputcontext ();
00152     imsvr = pimic->get_imconnection()->get_imsvr();
00153 
00154     if (imsvr) return imsvr;
00155     else return NULL;
00156 }
00157 
00158 LEMgr *
00159 IIIMP_ICState::get_lemgr ()
00160 {
00161     IMSvr *pimsvr = get_imsvr ();
00162     return pimsvr->get_lemgr();
00163 
00164 }
00165 
00166 IMLangList *
00167 IIIMP_ICState::get_langlist (
00168     iml_desktop_t *curr_desktop
00169 )
00170 {
00171     LEMgr *plemgr = get_lemgr ();
00172 
00173     IMLangList *planglist =
00174         const_cast<IMLangList *>(plemgr->get_all_langlist(curr_desktop));
00175     IMLangList::iterator it;
00176     for (it = planglist->begin (); it != planglist->end (); it++){
00177        // LOG_DEBUG("LangID [%s]", it->get_id ());
00178     }
00179     return planglist;
00180 }
00181 
00182 bool 
00183 IIIMP_ICState::create_langimlist ()
00184 {
00185     LEMgr *plemgr = get_lemgr ();
00186     IMDescriptorList::iterator it;
00187     IMLangList::iterator itt;
00188 
00189     IMDescriptorList *pimdlist = const_cast<IMDescriptorList *>(plemgr->get_all_imdesclist(get_ichandler()->get_current_desktop()));
00190 
00191     langimlist.clear();
00192     for (it = pimdlist->begin (); it != pimdlist->end (); it++){
00193         u16string imname;
00194         u16string hrn;
00195         imname = it->get_imname();
00196         hrn = it->get_hrn();
00197         IMLangList *llist = const_cast<IMLangList *>(it->get_languages());
00198         for (itt = llist->begin (); itt != llist->end (); itt++) { 
00199            langimlist.push_back(LangIM(langimlist.size() + 1,
00200               // this '+ 1' is a crack - index in lang choice starts from 1...
00201               itt->get_id(),
00202               u16string(imname),
00203               u16string(hrn),
00204               it->get_hotkey_profile()
00205               )
00206            );
00207         }
00208     }
00209     return true;
00210 }
00211 
00212 LangIMList *
00213 IIIMP_ICState::get_langimlist ()
00214 {
00215     return &langimlist;
00216 }
00217 
00218 IIIMP_ICState::~IIIMP_ICState()
00219 {
00220     if (!substatep()) {
00221        delete pshared;
00222        delete get_imlexec();
00223         if (ihk) delete ihk;
00224     }
00225 }
00226 
00227 /*******************************************************************************
00228                 ICState_REQUESTED
00229 *******************************************************************************/
00230 
00231 bool
00232 IIIMP_ICState_REQUESTED::message_proc(
00233     void *x_pmes
00234 )
00235 {
00236     IIIMP_message *pmes = (IIIMP_message*) x_pmes;
00237 
00238     LOG_ERROR("REQUESTED state cannot accept any messages. (%d, %d, %d)",
00239              get_im_id(), get_ic_id(), pmes->opcode);
00240 
00241     return false;
00242 }
00243 
00244 bool
00245 IIIMP_ICState_REQUESTED::finish()
00246 {
00247     bool flag;
00248 
00249     if (ihk->get_hotkey_mode()) {
00250        preply = iiimp_hotkey_notify_reply_new(get_iiimptrans()->get_data_s(), get_im_id(), get_ic_id());
00251        ihk->set_hotkey_mode(false);
00252     }
00253 
00254     if (ihk->get_forward_event()) {
00255        preply = iiimp_forward_event_reply_new(get_iiimptrans()->get_data_s(),
00256                                           get_im_id(),
00257                                           get_ic_id());
00258         ihk->set_forward_event(false);
00259     }
00260 
00261     flag = send(preply, true);
00262     if (pprev_state)
00263        change_state(*pprev_state, true);
00264     else
00265        reset_state();
00266 
00267     return flag;
00268 }
00269 
00270 bool
00271 IIIMP_ICState_REQUESTED::dealing()
00272 {
00273     bool result;
00274     // execute remaining IML instructions.
00275     ASSERT(send_avail_p() == true);
00276     result = get_imlexec()->execute();
00277     if (send_avail_p()) {
00278        if (get_imlexec()->empty())
00279            result = finish() && result;
00280     }
00281 
00282     return result;
00283 }
00284 
00285 bool
00286 IIIMP_ICState_REQUESTED::wait(
00287     int opcode
00288 )
00289 {
00290     IIIMP_ICState_WAITING *picsw = new IIIMP_ICState_WAITING(this, opcode);
00291     // TODO: throw memory error.
00292     change_state(*picsw, false);
00293     return true;
00294 }
00295 
00296 bool
00297 IIIMP_ICState_REQUESTED::wait_aux(
00298     int opcode,
00299     int index,
00300     const u16string& imname
00301 )
00302 {
00303     IIIMP_ICState_WAITING *picsw;
00304     picsw = new IIIMP_ICState_WAITING(this, opcode,
00305                                   index, imname);
00306     // TODO: throw memory error.
00307     change_state(*picsw, false);
00308     return true;
00309 }
00310 
00311 IIIMP_ICState_REQUESTED::IIIMP_ICState_REQUESTED(
00312     IIIMP_ICState *pbase
00313 ) : IIIMP_ICState(*pbase)
00314 {
00315     pprev_state = pbase;
00316 }
00317 
00318 
00319 /****************************************
00320            REQUEST functions.
00321 ****************************************/
00322 
00323 bool
00324 IIIMP_ICState_REQUESTED::set_values(
00325     IIIMP_message *pmes
00326 )
00327 {
00328     bool result = false;
00329 
00330     // Send TRIGGER_OFF_NOTIFY to current language engine
00331     get_ichandler()->toggle_conversion(get_imlexec(), false);
00332     pshared->conversion_mode = false;
00333 
00334     const ICAttribute& attr = convert_iiimp_icattr(pmes->v.seticvalues.attr_list);
00335     result = get_ichandler()->set_icattr(attr);
00336 
00337     preply = iiimp_seticvalues_reply_new(get_iiimptrans()->get_data_s(),
00338                                     get_im_id(),
00339                                     get_ic_id());
00340     result = dealing() && result;
00341     return result;
00342 }
00343 
00344 bool
00345 IIIMP_ICState_REQUESTED::toggle_server_convmode(
00346     bool flag
00347 )
00348 {
00349     bool result = get_ichandler()->toggle_conversion(get_imlexec(), flag);
00350     pshared->conversion_mode = flag;
00351     preply = iiimp_trigger_notify_reply_new(get_iiimptrans()->get_data_s(),
00352                                        get_im_id(),
00353                                        get_ic_id());
00354 
00355     result = dealing() && result;
00356     return result;
00357 }
00358 
00359 bool
00360 IIIMP_ICState_REQUESTED::toggle_icfocus(
00361     bool flag
00362 )
00363 {
00364     bool result = get_ichandler()->toggle_focus(get_imlexec(), flag);
00365 
00366     if (flag)
00367        preply = iiimp_seticfocus_reply_new(get_iiimptrans()->get_data_s(),
00368                                        get_im_id(),
00369                                        get_ic_id());
00370     else
00371        preply = iiimp_unseticfocus_reply_new(get_iiimptrans()->get_data_s(),
00372                                          get_im_id(),
00373                                          get_ic_id());
00374 
00375     result = dealing() && result;
00376     return result;
00377 }
00378 
00379 bool
00380 IIIMP_ICState_REQUESTED::reset()
00381 {
00382     bool result = get_ichandler()->reset(get_imlexec());
00383     preply = iiimp_resetic_reply_new(get_iiimptrans()->get_data_s(),
00384                                  get_im_id(),
00385                                  get_ic_id());
00386     result = dealing() && result;
00387     return result;
00388 }
00389 
00390 bool
00391 IIIMP_ICState_REQUESTED::aux_setvalues(
00392     IIIMP_message *pmes
00393 )
00394 {
00395     bool result = false;
00396     IIIMP_aux_setvalues_v *pauxval = &pmes->v.aux_setvalues;
00397 
00398     IMAuxDrawCallbackStruct aux_draw;
00399 
00400     u16string auxnamestr = CONV_IIIMP_STR(pauxval->input_method_name);
00401     if (auxnamestr.get_charstr()) {
00402        vector<char> auxnamev;
00403        auxnamev.reserve(auxnamestr.size() + 1);
00404        memcpy(&auxnamev[0], auxnamestr.get_charstr(), auxnamestr.size() + 1);
00405        aux_draw.aux_name = &auxnamev[0];
00406        aux_draw.aux_index = pauxval->class_index;
00407 
00408        {
00409            // integer value array.
00410            int i;
00411            int num = pauxval->integer_value->count;
00412            IIIMP_card32 *pc32 = pauxval->integer_value->ptr;
00413            vector<int> intvalv;
00414            intvalv.reserve(num);
00415            aux_draw.count_integer_values = num;
00416            for (i = 0; i < num; i++, pc32++) {
00417               intvalv.push_back(*pc32);
00418            }
00419            aux_draw.integer_values = &intvalv[0];
00420 
00421            // string value array.
00422            int count = 0;
00423            IIIMP_string *pstr;
00424            vector<IMText> imtextvec;
00425 
00426            for (pstr = pauxval->string_value; pstr; pstr = pstr->next) {
00427               IMText text;
00428               memset(&text, 0, sizeof(text));
00429               text.encoding = UTF16_CODESET;
00430               text.char_length = pstr->len;
00431               text.text.utf_chars = pstr->ptr;
00432               imtextvec.push_back(text);
00433               count++;
00434            }
00435            aux_draw.count_string_values = count;
00436            aux_draw.string_values = &imtextvec[0];
00437 
00438            IMAuxEvent aux_event;
00439            aux_event.type = IM_EventAuxSet;
00440            aux_event.aux = &aux_draw;
00441            result = get_ichandler()->send_event(get_imlexec(),
00442                                            (IMInputEvent*) &aux_event);
00443        }
00444     }
00445 
00446     IIIMP_string* pimname = iiimp_string_new(get_iiimptrans()->get_data_s(),
00447                                         pauxval->input_method_name->len,
00448                                         pauxval->input_method_name->ptr);
00449     if (!pimname) {
00450        // TODO: we should throw memory exception.
00451        return false;
00452     }
00453     preply = iiimp_aux_setvalues_reply_new(get_iiimptrans()->get_data_s(),
00454                                       get_im_id(),
00455                                       get_ic_id(),
00456                                       pauxval->class_index,
00457                                       pimname);
00458     result = dealing() && result;
00459     return result;
00460 }
00461 
00462 bool
00463 IIIMP_ICState_REQUESTED::aux_getvalues(
00464     IIIMP_message *pmes
00465 )
00466 {
00467     bool result = false;
00468     IIIMP_aux_getvalues_v *pauxval = &pmes->v.aux_getvalues;
00469     int i;
00470 
00471     IMAuxGetEvent aux_event;
00472     IMAuxDrawCallbackStruct *aux_draw, aux_data_struct;
00473     aux_draw = &aux_data_struct;
00474 
00475     vector<char> auxnamev;
00476     vector<int> intvalv;
00477     vector<IMText> imtextvec;
00478 
00479     u16string auxnamestr = CONV_IIIMP_STR(pauxval->input_method_name);
00480     if (auxnamestr.get_charstr()) {
00481        auxnamev.reserve(auxnamestr.size() + 1);
00482        memcpy(&auxnamev[0], auxnamestr.get_charstr(), auxnamestr.size() + 1);
00483        aux_draw->aux_name = &auxnamev[0];
00484        aux_draw->aux_index = pauxval->class_index;
00485 
00486        {
00487            // integer value array.
00488            int i;
00489            int num = pauxval->integer_value->count;
00490            IIIMP_card32 *pc32 = pauxval->integer_value->ptr;
00491            intvalv.reserve(num);
00492            aux_draw->count_integer_values = num;
00493            for (i = 0; i < num; i++, pc32++) {
00494               intvalv.push_back(*pc32);
00495            }
00496            aux_draw->integer_values = &intvalv[0];
00497 
00498            // string value array.
00499            int count = 0;
00500            IIIMP_string *pstr;
00501 
00502            for (pstr = pauxval->string_value; pstr; pstr = pstr->next) {
00503               IMText text;
00504               memset(&text, 0, sizeof(text));
00505               text.encoding = UTF16_CODESET;
00506               text.char_length = pstr->len;
00507               text.text.utf_chars = pstr->ptr;
00508               imtextvec.push_back(text);
00509               count++;
00510            }
00511            aux_draw->count_string_values = count;
00512            aux_draw->string_values = &imtextvec[0];
00513 
00514            aux_event.type = IM_EventAuxGet;
00515            aux_event.fromaux = aux_draw;
00516            result = get_ichandler()->send_event_getvalues(get_imlexec(),
00517                                                     (IMInputEvent*) &aux_event);
00518        }
00519     }
00520 
00521     IIIMP_string* pimname = iiimp_string_new(get_iiimptrans()->get_data_s(),
00522                                         pauxval->input_method_name->len,
00523                                         pauxval->input_method_name->ptr);
00524     if (!pimname) {
00525        // TODO: we should throw memory exception.
00526        get_ichandler()->send_event_getvalues_finished(get_imlexec());
00527        return false;
00528     }
00529 
00530     // send aux_getvalues_reply
00531     aux_draw = aux_event.toaux;
00532 
00533     IIIMP_string *pstrh = NULL, *pstr = NULL, *pcur;
00534     IIIMP_card32_list *pilist = NULL;
00535 
00536     if (aux_draw->count_integer_values > 0) {
00537        // `Int' and `IIIMP_card32' is not always compatible especially
00538        // in array form.  Thus, it's inevitable to convert `int' array
00539        // manually.
00540        IIIMP_card32* pc32h, *pc32;
00541        pc32h = pc32 = new IIIMP_card32[aux_draw->count_integer_values];
00542        if (!pc32) {
00543            get_ichandler()->send_event_getvalues_finished(get_imlexec());
00544            return -1;
00545        }
00546        int *pi = aux_draw->integer_values;
00547        for (i = 0; i < aux_draw->count_integer_values; i++) {
00548            *pc32++ = (unsigned) *pi++;
00549        }
00550        pilist = iiimp_card32_list_new(get_iiimptrans()->get_data_s(),
00551                                    aux_draw->count_integer_values,
00552                                    pc32h);
00553        if (!pilist) goto error;
00554        delete[] pc32h;
00555     }
00556 
00557     IMText *pimt;
00558     for (i = 0, pimt = aux_draw->string_values;
00559         i < aux_draw->count_string_values;
00560         i++, pimt++) {
00561        pcur = convert_IMText_to_iiimp_string(get_iiimptrans()->get_data_s(),
00562                                          pimt);
00563        if (!pcur) goto error;
00564        if (!pstrh) {
00565            pstrh = pcur;
00566        } else {
00567            pstr->next = pcur;
00568        }
00569        pstr = pcur;
00570     }
00571 
00572     preply = iiimp_aux_getvalues_reply_new(get_iiimptrans()->get_data_s(),
00573                                       get_im_id(),
00574                                       get_ic_id(),
00575                                       pauxval->class_index,
00576                                       pimname,
00577                                       pilist,
00578                                       pstrh);
00579 
00580 error:
00581     get_ichandler()->send_event_getvalues_finished(get_imlexec());
00582     result = dealing() && result;
00583 
00584 #if 0
00585     // FIXME. The pilist and pstrh must be freed, but freeing them will
00586     // cause htt_server to freeze.
00587     if (pilist)
00588        iiimp_card32_list_delete(get_iiimptrans()->get_data_s(), pilist);
00589     if (pstrh)
00590        iiimp_string_delete(get_iiimptrans()->get_data_s(), pstrh);
00591 #endif
00592     return result;
00593 }
00594 
00595 bool
00596 IIIMP_ICState_REQUESTED::forward_event(
00597     IIIMP_message *pmes
00598 )
00599 {
00600     bool result = false;
00601     IIIMP_contents *pc = pmes->v.forward_event.contents;
00602 
00603     IMInputEvent ev;
00604     
00605     switch (pc->type) {
00606       case IIIMP_CONTENTS_KEYEVENT:
00607       {
00608          vector<IMKeyEventStruct> keyvec;
00609          IIIMP_keyevent *piiimpkey = pc->value.keyevent_list->keyevent;
00610          int count = pc->value.keyevent_list->count;
00611          int i;
00612          for (i = 0; i < count; i++, piiimpkey++) {
00613              IMKeyEventStruct kev;
00614              kev.keyCode = piiimpkey->keycode;
00615              kev.keyChar = piiimpkey->keychar;
00616              kev.modifier = piiimpkey->modifier;
00617              kev.time_stamp = piiimpkey->time_stamp;
00618              keyvec.push_back(kev);
00619          }
00620 
00621 
00622          IMKeyListEvent *pimkey = &ev.keylist;
00623          memset(pimkey, 0, sizeof(*pimkey));
00624          pimkey->type = IM_EventKeyList;
00625          pimkey->n_key = count;
00626          pimkey->keylist = &keyvec[0];
00627 
00628          result = get_ichandler()->send_event(get_imlexec(), &ev);
00629       }
00630           
00631       break;
00632       case IIIMP_CONTENTS_STRING:
00633       case IIIMP_CONTENTS_TEXT:
00634        // ignore
00635        break;
00636       default:
00637        abort();
00638     }
00639 
00640     preply = iiimp_forward_event_reply_new(get_iiimptrans()->get_data_s(),
00641                                       get_im_id(),
00642                                       get_ic_id());
00643     result = dealing() && result;
00644     return result;
00645 }
00646 
00647 bool
00648 IIIMP_ICState_REQUESTED::forward_event_with_operations(
00649     IIIMP_message *pmes
00650 )
00651 {
00652     IIIMP_operation *pop = pmes->v.forward_event_with_operations_reply.operation;
00653 
00654     // currently do nothing.
00655 
00656     preply = iiimp_forward_event_with_operations_reply_new(get_iiimptrans()->get_data_s(),
00657                                                     get_im_id(),
00658                                                     get_ic_id(),
00659                                                     pop);
00660     // TODO: check memory error, throw exception.
00661     return dealing();
00662 }
00663 
00664 bool
00665 IIIMP_ICState_REQUESTED::destroyic()
00666 {
00667     bool result = get_ichandler()->destroy(get_imlexec());
00668     if (result) invalidate_ichandler();
00669     preply = iiimp_destroyic_reply_new(get_iiimptrans()->get_data_s(),
00670                                    get_im_id(),
00671                                    get_ic_id());
00672     mark_terminal();
00673     result = dealing();
00674     return result;
00675 }
00676 
00677 /****************************************
00678  IC operation handler for REQUESTED state
00679 ****************************************/
00680 
00681 int
00682 IIIMP_ICState_REQUESTED::toggle_client_convmode(
00683     bool flag
00684 )
00685 {
00686     LOG_DEBUG("Toggle client conversion mode to %s.",
00687              flag ? "true" : "false");
00688     if (conversion_enable_p() != flag) {
00689        IIIMP_message *pmes = iiimp_trigger_notify_new(get_iiimptrans()->get_data_s(),
00690                                                  get_im_id(),
00691                                                  get_ic_id(),
00692                                                  flag ? 0 : 1);
00693        if (!send(pmes, true)) return -1;
00694        pshared->conversion_mode = flag;
00695 
00696        return wait(IM_TRIGGER_NOTIFY_REPLY) ? 0 : -1;
00697     }
00698     return 0;
00699 }
00700 
00701 int
00702 IIIMP_ICState_REQUESTED::forward_keyevent(
00703     IMKeyEventStruct *pkeyevent
00704 )
00705 {
00706     IIIMP_keyevent ikev;
00707 
00708     ikev.keycode = pkeyevent->keyCode;
00709     ikev.keychar = pkeyevent->keyChar;
00710     ikev.modifier = pkeyevent->modifier;
00711     ikev.time_stamp = pkeyevent->time_stamp;
00712 
00713     IIIMP_keyevent_list *pikl = iiimp_keyevent_list_new(get_iiimptrans()->get_data_s(),
00714                                                  1, &ikev);
00715     if (!pikl) return -1;
00716 
00717     IIIMP_contents *pcon = iiimp_contents_keyevent_list_new(get_iiimptrans()->get_data_s(),
00718                                                      pikl);
00719     if (!pcon) {
00720        iiimp_keyevent_list_delete(get_iiimptrans()->get_data_s(), pikl);
00721        return -1;
00722     }
00723 
00724     IIIMP_message *pmes = iiimp_forward_event_new(get_iiimptrans()->get_data_s(),
00725                                             get_im_id(),
00726                                             get_ic_id(),
00727                                             pcon);
00728     if (!pmes) {
00729        iiimp_contents_delete(get_iiimptrans()->get_data_s(), pcon);
00730        return -1;
00731     }
00732     if (!send(pmes, true)) return -1;
00733 
00734     return wait(IM_FORWARD_EVENT_REPLY) ? 0 : -1;
00735 }
00736 
00737 int
00738 IIIMP_ICState_REQUESTED::commit_string(
00739     IMText *pimtext
00740 )
00741 {
00742     IIIMP_contents *pcon;
00743 
00744     pcon = convert_IMText_to_iiimp_contents_string(get_iiimptrans()->get_data_s(),
00745                                              pimtext);
00746     if (!pcon) return -1;
00747     IIIMP_message *pmes = iiimp_commit_string_new(get_iiimptrans()->get_data_s(),
00748                                             get_im_id(),
00749                                             get_ic_id(),
00750                                             pcon);
00751     if (!pmes) {
00752        iiimp_contents_delete(get_iiimptrans()->get_data_s(), pcon);
00753        return -1;
00754     }
00755     return send(pmes, true) ? 0 : -1;
00756 }
00757 
00758 int
00759 IIIMP_ICState_REQUESTED::preedit_start()
00760 {
00761     IIIMP_message *pmes = iiimp_preedit_start_new(get_iiimptrans()->get_data_s(),
00762                                             get_im_id(),
00763                                             get_ic_id());
00764     if (!send(pmes, true)) return -1;
00765     pshared->preedit = true;
00766 
00767     return wait(IM_PREEDIT_START_REPLY) ? 0 : -1;
00768 }
00769 
00770 int
00771 IIIMP_ICState_REQUESTED::draw_preedit(
00772     IMPreeditDrawCallbackStruct *pimpdraw
00773 )
00774 {
00775     IIIMP_contents *pcon;
00776 
00777     if (!pshared->preedit) {
00778        LOG_ERROR("preedit has not been enabled yet. (%d, %d)",
00779                 get_im_id(), get_ic_id());
00780     }
00781 
00782     if (pimpdraw->text) {
00783        pcon = convert_IMText_to_iiimp_contents_text(get_iiimptrans()->get_data_s(),
00784                                                pimpdraw->text);
00785     } else {
00786        // create empty text contents.
00787        IIIMP_text *ptext = iiimp_text_new(get_iiimptrans()->get_data_s(), NULL, NULL);
00788        if (!ptext) return -1;
00789        pcon = iiimp_contents_text_new(get_iiimptrans()->get_data_s(), ptext);
00790     }
00791     if (!pcon) return -1;
00792     IIIMP_message *pmes = iiimp_preedit_draw_new(get_iiimptrans()->get_data_s(),
00793                                            get_im_id(), get_ic_id(),
00794                                            pimpdraw->caret,
00795                                            pimpdraw->chg_first,
00796                                            pimpdraw->chg_length,
00797                                            pcon);
00798     if (!pmes) {
00799        iiimp_contents_delete(get_iiimptrans()->get_data_s(), pcon);
00800        return -1;
00801     }
00802     if (!send(pmes, true)) return 0;
00803 
00804     return wait(IM_PREEDIT_DRAW_REPLY) ? 0 : -1;
00805 }
00806 
00807 int
00808 IIIMP_ICState_REQUESTED::preedit_done()
00809 {
00810     IIIMP_message *pmes = iiimp_preedit_done_new(get_iiimptrans()->get_data_s(),
00811                                            get_im_id(),
00812                                            get_ic_id());
00813     if (!send(pmes, true)) return -1;
00814     pshared->preedit = false;
00815 
00816     return wait(IM_PREEDIT_DONE_REPLY) ? 0 : -1;
00817 }
00818 
00819 int
00820 IIIMP_ICState_REQUESTED::status_start()
00821 {
00822     IIIMP_message *pmes = iiimp_status_start_new(get_iiimptrans()->get_data_s(),
00823                                            get_im_id(),
00824                                            get_ic_id());
00825     if (!send(pmes, true)) return -1;
00826     pshared->status = true;
00827 
00828     return wait(IM_STATUS_START_REPLY) ? 0 : -1;
00829 }
00830 
00831 int
00832 IIIMP_ICState_REQUESTED::draw_status(
00833     IMStatusDrawCallbackStruct *pimsdraw
00834 )
00835 {
00836     IIIMP_contents *pcon;
00837 
00838     if (!pshared->status) {
00839        LOG_ERROR("status has not been enabled yet. (%d, %d)",
00840                 get_im_id(), get_ic_id());
00841     }
00842     pcon = convert_IMText_to_iiimp_contents_text(get_iiimptrans()->get_data_s(),
00843                                            pimsdraw->text);
00844     if (!pcon) return -1;
00845     IIIMP_message *pmes = iiimp_status_draw_new(get_iiimptrans()->get_data_s(),
00846                                           get_im_id(), get_ic_id(),
00847                                           pcon);
00848     if (!pmes) {
00849        iiimp_contents_delete(get_iiimptrans()->get_data_s(), pcon);
00850        return -1;
00851     }
00852     if (!send(pmes, true)) return 0;
00853 
00854     return wait(IM_STATUS_DRAW_REPLY) ? 0 : -1;
00855 }
00856 
00857 int
00858 IIIMP_ICState_REQUESTED::status_done()
00859 {
00860     IIIMP_message *pmes = iiimp_status_done_new(get_iiimptrans()->get_data_s(),
00861                                           get_im_id(),
00862                                           get_ic_id());
00863     if (!send(pmes, true)) return -1;
00864     pshared->status = false;
00865 
00866     return wait(IM_STATUS_DONE_REPLY) ? 0 : -1;
00867 }
00868 
00869 
00870 int
00871 IIIMP_ICState_REQUESTED::lookup_start(
00872     IMLookupStartCallbackStruct *pimls
00873 )
00874 {
00875     int master, direction, labelowner;
00876     LayoutInfo *playout;
00877 
00878     if (pimls->whoIsMaster == IMIsMaster) {
00879        playout = pimls->IMPreference;
00880        master = IM_LOOKUP_CHOICE_START_SERVER_IS_MASTER;
00881     } else {
00882        ASSERT(pimls->whoIsMaster == CBIsMaster);
00883        playout = pimls->CBPreference;
00884        master = IM_LOOKUP_CHOICE_START_CLIENT_IS_MASTER;
00885     }
00886 
00887     if (playout->drawUpDirection == DrawUpHorizontally) {
00888        direction = IM_LOOKUP_CHOICE_START_DRAWING_UP_HORIZONTALLY;
00889     } else {
00890        ASSERT(playout->drawUpDirection == DrawUpVertically);
00891        direction = IM_LOOKUP_CHOICE_START_DRAWING_UP_VERTICALLY;
00892     }
00893 
00894     if (playout->whoOwnsLabel == IMOwnsLabel) {
00895        labelowner = IM_LOOKUP_CHOICE_START_SERVER_OWNS_LABEL;
00896     } else {
00897        ASSERT(playout->whoOwnsLabel == CBOwnsLabel);
00898        labelowner = IM_LOOKUP_CHOICE_START_CLIENT_OWNS_LABEL;
00899     }
00900 
00901     IIIMP_message *pmes;
00902     pmes = iiimp_lookup_choice_start_new(get_iiimptrans()->get_data_s(),
00903                                     get_im_id(),
00904                                     get_ic_id(),
00905                                     master,
00906                                     playout->choice_per_window,
00907                                     playout->nrows,
00908                                     playout->ncolumns,
00909                                     direction,
00910                                     labelowner);
00911     if (!send(pmes, true)) return -1;
00912     pshared->lookup_choice = true;
00913 
00914     return wait(IM_LOOKUP_CHOICE_START_REPLY) ? 0 : -1;
00915 }
00916 
00917 int
00918 IIIMP_ICState_REQUESTED::draw_lookup(
00919     IMLookupDrawCallbackStruct *pimld
00920 )
00921 {
00922     if (!pshared->lookup_choice) {
00923        LOG_ERROR("lookup-choice has not been enabled yet. (%d, %d)",
00924                 get_im_id(), get_ic_id());
00925     }
00926 
00927     IIIMP_message *pmes;
00928     IIIMP_text *pchoiceh, *pchoice = NULL;
00929     IIIMP_text *plabelh, *plabel = NULL;
00930     IIIMP_text *ptitle;
00931     IMChoiceObject *pco;
00932     int i;
00933     pchoiceh = plabelh = NULL;
00934 
00935     ptitle = convert_IMText_to_iiimp_text(get_iiimptrans()->get_data_s(),
00936                                      pimld->title);
00937     if (!ptitle) goto error;
00938 
00939     IIIMP_text *pcur;
00940     for (i = 0, pco = pimld->choices;
00941         i < pimld->n_choices;
00942         i++, pco++) {
00943        // value.
00944        pcur = convert_IMText_to_iiimp_text(get_iiimptrans()->get_data_s(),
00945                                        pco->value);
00946        if (!pcur) goto error;
00947        if (!pchoiceh) {
00948            pchoiceh = pcur;
00949        } else {
00950            pchoice->next = pcur;
00951        }
00952        pchoice = pcur;
00953 
00954        //label
00955        pcur = convert_IMText_to_iiimp_text(get_iiimptrans()->get_data_s(),
00956                                        pco->label);
00957        if (!pcur) goto error;
00958        if (!plabelh) {
00959            plabelh = pcur;
00960        } else {
00961            plabel->next = pcur;
00962        }
00963        plabel = pcur;
00964     }
00965 
00966     pmes = iiimp_lookup_choice_draw_new(get_iiimptrans()->get_data_s(),
00967                                    get_im_id(),
00968                                    get_ic_id(),
00969                                    pimld->index_of_first_candidate,
00970                                    pimld->index_of_last_candidate,
00971                                    pimld->index_of_current_candidate,
00972                                    pchoiceh,
00973                                    plabelh,
00974                                    ptitle);
00975     if (!pmes) goto error;
00976 
00977     if (!send(pmes, true)) return -1;
00978 
00979     return wait(IM_LOOKUP_CHOICE_DRAW_REPLY) ? 0 : -1;
00980 
00981 error:
00982     if (ptitle) iiimp_text_delete(get_iiimptrans()->get_data_s(), ptitle);
00983     if (plabelh) iiimp_text_delete(get_iiimptrans()->get_data_s(), plabelh);
00984     if (pchoiceh) iiimp_text_delete(get_iiimptrans()->get_data_s(), pchoiceh);
00985 
00986     return -1;
00987 }
00988 
00989 int
00990 IIIMP_ICState_REQUESTED::lookup_process(
00991     IMLookupProcessCallbackStruct *pimlp
00992 )
00993 {
00994     if (!pshared->lookup_choice) {
00995        LOG_ERROR("lookup-choice has not been enabled yet. (%d, %d)",
00996                 get_im_id(), get_ic_id());
00997     }
00998 
00999     IIIMP_card16 type, value;
01000     if (pimlp->type == LookupIndex) {
01001        type = IM_LOOKUP_CHOICE_PROCESS_INDEX;
01002        value = pimlp->value.index_of_choice_selected;
01003     } else {
01004        ASSERT(pimlp->type == LookupPage);
01005        type = IM_LOOKUP_CHOICE_PROCESS_PAGE;
01006        // Note that page_operation_id must have the same value
01007        // as that of libiiimp.
01008        value = pimlp->value.page_operation_id;
01009     }
01010     IIIMP_message *pmes;
01011     pmes = iiimp_lookup_choice_process_new(get_iiimptrans()->get_data_s(),
01012                                       get_im_id(),
01013                                       get_ic_id(),
01014                                       type,
01015                                       value);
01016 
01017     if (!send(pmes, true)) return -1;
01018 
01019     return wait(IM_LOOKUP_CHOICE_PROCESS_REPLY) ? 0 : -1;
01020 }
01021 
01022 int
01023 IIIMP_ICState_REQUESTED::lookup_done()
01024 {
01025     IIIMP_message *pmes;
01026     pmes = iiimp_lookup_choice_done_new(get_iiimptrans()->get_data_s(),
01027                                    get_im_id(),
01028                                    get_ic_id());
01029     if (!send(pmes, true)) return -1;
01030     pshared->lookup_choice = false;
01031 
01032     return wait(IM_LOOKUP_CHOICE_DONE_REPLY) ? 0 : -1;
01033 }
01034 
01035 int
01036 IIIMP_ICState_REQUESTED::aux_start(
01037     IMAuxStartCallbackStruct *pimauxstart
01038 )
01039 {
01040     IIIMP_message *pmes;
01041     u16string auxname(pimauxstart->aux_name);
01042     IIIMP_string *iiimpauxname;
01043     int index = pimauxstart->aux_index;
01044 
01045     iiimpauxname = iiimp_string_new(get_iiimptrans()->get_data_s(),
01046                                 auxname.size(),
01047                                 auxname.data());
01048     if (!iiimpauxname) return -1;
01049 
01050     pmes = iiimp_aux_start_new(get_iiimptrans()->get_data_s(),
01051                             get_im_id(),
01052                             get_ic_id(),
01053                             index,
01054                             iiimpauxname);
01055                             
01056     if (!send(pmes, true)) return -1;
01057 
01058     return wait_aux(IM_AUX_START_REPLY, index, auxname) ? 0 : -1;
01059 }
01060 
01061 int
01062 IIIMP_ICState_REQUESTED::draw_aux(
01063     IMAuxDrawCallbackStruct *pimauxdraw
01064 )
01065 {
01066     int i;
01067     IIIMP_message *pmes;
01068     u16string auxname(pimauxdraw->aux_name);
01069     IIIMP_string *iiimpauxname;
01070     int index = pimauxdraw->aux_index;
01071     IIIMP_string *pstrh = NULL, *pstr = NULL, *pcur;
01072     IIIMP_card32_list *pilist = NULL;
01073 
01074     iiimpauxname = iiimp_string_new(get_iiimptrans()->get_data_s(),
01075                                 auxname.size(),
01076                                 auxname.data());
01077     if (!iiimpauxname) return -1;
01078 
01079     if (pimauxdraw->count_integer_values > 0) {
01080        // `int' and `IIIMP_card32' is not always compatible especially
01081        // in array form.  Thus, it's inevitable to convert `int' array
01082        // manually.
01083        IIIMP_card32* pc32h, *pc32;
01084        pc32h = pc32 = new IIIMP_card32[pimauxdraw->count_integer_values];
01085        if (!pc32) return -1;
01086        int *pi = pimauxdraw->integer_values;
01087        for (i = 0; i < pimauxdraw->count_integer_values; i++) {
01088            *pc32++ = (unsigned) *pi++;
01089        }
01090        pilist = iiimp_card32_list_new(get_iiimptrans()->get_data_s(),
01091                                    pimauxdraw->count_integer_values,
01092                                    pc32h);
01093        delete[] pc32h;
01094        if (!pilist) goto error;
01095     }
01096 
01097     IMText *pimt;
01098     for (i = 0, pimt = pimauxdraw->string_values;
01099         i < pimauxdraw->count_string_values;
01100         i++, pimt++) {
01101        pcur = convert_IMText_to_iiimp_string(get_iiimptrans()->get_data_s(),
01102                                          pimt);
01103        if (!pcur) goto error;
01104        if (!pstrh) {
01105            pstrh = pcur;
01106        } else {
01107            pstr->next = pcur;
01108        }
01109        pstr = pcur;
01110     }
01111 
01112     pmes = iiimp_aux_draw_new(get_iiimptrans()->get_data_s(),
01113                            get_im_id(),
01114                            get_ic_id(),
01115                            index,
01116                            iiimpauxname,
01117                            pilist,
01118                            pstrh);
01119                            
01120     if (!send(pmes, true)) return -1;
01121 
01122     return wait_aux(IM_AUX_DRAW_REPLY, index, auxname) ? 0 : -1;
01123 
01124 error:
01125     if (iiimpauxname) iiimp_string_delete(get_iiimptrans()->get_data_s(), iiimpauxname);
01126     if (pilist) iiimp_card32_list_delete(get_iiimptrans()->get_data_s(), pilist);
01127     if (pstrh) iiimp_string_delete(get_iiimptrans()->get_data_s(), pstrh);
01128     return -1;
01129 }
01130 
01131 int
01132 IIIMP_ICState_REQUESTED::aux_done(
01133     IMAuxDoneCallbackStruct *pimauxdone
01134 )
01135 {
01136     IIIMP_message *pmes;
01137     u16string auxname(pimauxdone->aux_name);
01138     IIIMP_string *iiimpauxname;
01139     int index = pimauxdone->aux_index;
01140 
01141     iiimpauxname = iiimp_string_new(get_iiimptrans()->get_data_s(),
01142                                 auxname.size(),
01143                                 auxname.data());
01144     if (!iiimpauxname) return -1;
01145 
01146     pmes = iiimp_aux_done_new(get_iiimptrans()->get_data_s(),
01147                            get_im_id(),
01148                            get_ic_id(),
01149                            index,
01150                            iiimpauxname);
01151                             
01152     if (!send(pmes, true)) return -1;
01153 
01154     return wait_aux(IM_AUX_DONE_REPLY, index, auxname) ? 0 : -1;
01155 }
01156 
01157 /*******************************************************************************
01158                 ICState_WAITING
01159 *******************************************************************************/
01160 
01161 bool
01162 IIIMP_ICState_WAITING::match_waiting_message(
01163     IIIMP_message *pmes
01164 )
01165 {
01166     bool flag = (opcode == pmes->opcode);
01167     if (flag && wait_aux_message) {
01168        int midx = pmes->v.aux_simple.class_index;
01169        u16string mimname = CONV_IIIMP_STR(pmes->v.aux_simple.input_method_name);
01170        flag = ((index == midx) && (imname.compare(mimname) == 0));
01171     } 
01172     return flag;
01173 }
01174 
01175 void
01176 IIIMP_ICState_WAITING::restore_state()
01177 {
01178     // change_state() will delete `this'.
01179     IIIMP_ICState_REQUESTED *preq = pstreq;
01180     change_state(*pstreq);
01181     preq->dealing();
01182 }
01183 
01184 bool
01185 IIIMP_ICState_WAITING::message_proc(
01186     void *x_pmes
01187 )
01188 {
01189     IIIMP_message *pmes = (IIIMP_message*) x_pmes;
01190 
01191     if (!match_waiting_message(pmes)) {
01192 #if 0
01193        LOG_ERROR("Client sends an invalid message. (%d,%d,%d)\n"
01194                 "Now ICState is waiting for (%d,%d,%d).",
01195                 pmes->opcode, pmes->im_id, pmes->ic_id,
01196                 opcode, get_im_id(), get_ic_id());
01197        return false;
01198 #else
01199        // It may cause W->R transition.
01200        return IIIMP_ICState::message_proc(pmes);
01201 #endif
01202     }
01203     restore_state();
01204     
01205     return true;
01206 }
01207 
01208 IIIMP_ICState_WAITING::IIIMP_ICState_WAITING(
01209     IIIMP_ICState_REQUESTED *pbase,
01210     int x_opcode
01211 ) : IIIMP_ICState(*pbase)
01212 {
01213     pstreq = pbase;
01214     opcode = x_opcode;
01215     wait_aux_message = false;
01216     wait_ns_message = false;
01217 }
01218 
01219 IIIMP_ICState_WAITING::IIIMP_ICState_WAITING(
01220     IIIMP_ICState_REQUESTED *pbase,
01221     int x_opcode,
01222     int x_index,
01223     const u16string& x_imname
01224 ) : IIIMP_ICState(*pbase), imname(x_imname)
01225 {
01226     pstreq = pbase;
01227     opcode = x_opcode;
01228     index = x_index;
01229     wait_aux_message = true;
01230     wait_ns_message = false;
01231 }
01232 
01233 /* Local Variables: */
01234 /* c-file-style: "iiim-project" */
01235 /* End: */