Back to index

im-sdk  12.3.91
chewing.c
Go to the documentation of this file.
00001 
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <sys/types.h>
00028 #include <chewing/chewing.h>
00029 #include <iconv.h>
00030 
00031 #define CARD32BIT CARD32
00032 
00033 /*
00034  * header files for SunIM library
00035  */
00036 #include "SunIM.h"
00037 
00038 #define CHEWING_VERSION "0.0.2"
00039 
00040 #ifdef DEBUG
00041 #define DEBUG_printf    printf
00042 #define DEBUG_fflush    fflush
00043 #else
00044 #define DEBUG_printf(s, ...)
00045 #define DEBUG_fflush(fp)
00046 #endif
00047 
00048 static iconv_t iconv_context = (iconv_t) -1;
00049 
00050 typedef struct chewing_session {
00051        ChewingData chewing_data;
00052        ChewingOutput chewing_output;
00053        int conv_on;
00054        int focus_on;
00055 
00056        int luc_start;
00057        int preedit_start;
00058 
00059 #if 0
00060        int status_start;
00061        long fLastUpdateLength;
00062        int caret_pos;
00063        int candidate;
00064 #endif
00065 } chewing_session_t;
00066 
00067 int get_session_caret_pos(iml_session_t *s)
00068 {
00069        int pos = 0;
00070        if (s && s->specific_data) {
00071               chewing_session_t *session = (chewing_session_t *)s->specific_data;
00072               pos = session->chewing_output.chiSymbolCursor;
00073               if (pos < 0 || pos > 100)
00074                      pos = 0;
00075        }
00076        return pos;
00077 }
00078 
00079 IMFeedbackList *create_feedback (iml_session_t *s, int size)
00080 {
00081        IMFeedbackList *feedback =
00082               (IMFeedbackList *) s->If->m->iml_new(s, sizeof(IMFeedbackList) * size);
00083        memset(feedback, 0, sizeof(IMFeedbackList) * size);
00084 
00085        while (size-- > 0) {
00086               IMFeedbackList *fbl = &(feedback[size]);
00087               fbl->count_feedbacks = 4;
00088               fbl->feedbacks = 
00089                      (IMFeedback *)s->If->m->iml_new(
00090                             s, fbl->count_feedbacks*sizeof(IMFeedback));
00091               memset(fbl->feedbacks, 0, fbl->count_feedbacks*sizeof(IMFeedback));
00092 
00093               IMFeedback *fb = &(fbl->feedbacks[0]);
00094               IM_FEEDBACK_TYPE(fb) = IM_DECORATION_FEEDBACK;
00095               IM_FEEDBACK_VALUE(fb) = IMUnderline;
00096        }
00097 
00098        return feedback;
00099 }
00100 
00101 
00102 UTFCHAR chewing_string[] = {0x9177, 0x97f3, 0x0};
00103 
00104 void status_draw (iml_session_t *s)
00105 {
00106        iml_inst *lp = NULL;
00107        iml_inst *rrv = NULL;
00108 
00109        if (s == NULL || s->specific_data == NULL)
00110               return;
00111        chewing_session_t *session = (chewing_session_t *)s->specific_data;
00112        if (!session->conv_on /* || !session->focus_on */) {
00113               lp = s->If->m->iml_make_status_done_inst(s);
00114               s->If->m->iml_execute(s, &lp);
00115               return;
00116        }
00117 
00118        lp = s->If->m->iml_make_status_start_inst(s);
00119        s->If->m->iml_link_inst_tail(&rrv, lp);
00120 
00121        IMText *p = (IMText *) s->If->m->iml_new(s, sizeof(IMText));
00122        memset(p, 0, sizeof(IMText));
00123        p->char_length = 2;
00124        p->encoding = UTF16_CODESET;
00125        p->text.utf_chars = chewing_string;
00126        p->feedback = create_feedback(s, p->char_length);
00127 
00128        lp = s->If->m->iml_make_status_draw_inst(s, p);
00129        s->If->m->iml_link_inst_tail(&rrv, lp);
00130        s->If->m->iml_execute(s, &rrv);
00131 }
00132 
00133 void commit (iml_session_t *s)
00134 {
00135        int len, i, buflen;
00136        char buf[128], *bufp = buf, *bufutfp;
00137        iml_inst *lp;
00138        iml_inst *rrv = NULL;
00139        IMText *p;
00140        chewing_session_t *session = (chewing_session_t *)s->specific_data;
00141        ChewingOutput *op = &session->chewing_output;
00142 
00143        if (!op->nCommitStr)
00144               return;
00145        p = (IMText *) s->If->m->iml_new(s, sizeof(IMText));
00146        memset(p, 0, sizeof(IMText));
00147        p->encoding = UTF16_CODESET;
00148 
00149        memset (buf, 0, 128);
00150        for (i=0; i<op->nCommitStr; ++i) {
00151               strcat (buf, op->commitStr[i].s);
00152        }
00153 
00154        len = strlen (buf) + 0;
00155        buflen = (op->nCommitStr + 1) * sizeof(UTFCHAR);
00156 
00157        p->text.utf_chars = (UTFCHAR *) s->If->m->iml_new(s, buflen);
00158        memset(p->text.utf_chars, 0, buflen);
00159        p->char_length = op->nCommitStr;
00160 
00161        bufutfp = (unsigned char *)p->text.utf_chars;
00162        iconv (iconv_context, (char **)&bufp, &len, &bufutfp, &buflen);
00163 
00164        if (session->preedit_start) {
00165               lp = s->If->m->iml_make_preedit_erase_inst(s);
00166               s->If->m->iml_link_inst_tail(&rrv, lp);
00167        }
00168 
00169        lp = s->If->m->iml_make_commit_inst(s, p);
00170        s->If->m->iml_link_inst_tail(&rrv, lp);
00171        s->If->m->iml_execute(s, &rrv);
00172 
00173        op->keystrokeRtn = KEYSTROKE_IGNORE;
00174        op->nCommitStr = 0;
00175 }
00176 
00177 static int currentKeyboard = KB_DEFAULT;
00178 
00179 int does_preedit_contain_text(iml_session_t *s)
00180 {
00181        chewing_session_t *session = (chewing_session_t *)s->specific_data;
00182        ChewingOutput *op = &session->chewing_output;
00183 
00184        int i, len=0;
00185        for(i=0; len == 0 && i<op->chiSymbolCursor; ++i)
00186               if (op->chiSymbolBuf[i].s[0]) len = 1;
00187        for(i=0; len == 0 && i<ZUIN_SIZE; ++i)
00188               if (op->zuinBuf[i].s[0]) len = 1;
00189        for(i=op->chiSymbolCursor; len == 0 && i < op->chiSymbolBufLen; ++i)
00190               if (op->chiSymbolBuf[i].s[0]) len = 1;
00191        return len;
00192 }
00193 
00194 IMText *make_preedit_imtext (iml_session_t *s)
00195 {
00196        int len, i, zuinlen = 0, buflen;
00197        char buf[128], *bufp = buf, *bufutfp;
00198        chewing_session_t *session = (chewing_session_t *)s->specific_data;
00199        ChewingOutput *op = &session->chewing_output;
00200 
00201        memset (buf, 0, 128);
00202        IMText *p = (IMText *) s->If->m->iml_new(s, sizeof(IMText));
00203        memset(p, 0, sizeof(IMText));
00204 
00205        for(i=0; i<op->chiSymbolCursor; ++i)
00206               strcat (buf, op->chiSymbolBuf[i].s);
00207        len = strlen(buf);
00208 
00209        for(i=0; i<ZUIN_SIZE; ++i) {
00210               strcat (buf, op->zuinBuf[i].s);
00211        }
00212        zuinlen = (strlen (buf) - len) / 2;
00213        for(i=op->chiSymbolCursor; i < op->chiSymbolBufLen; ++i)
00214               strcat (buf, op->chiSymbolBuf[i].s);
00215        len = strlen (buf) + 1;
00216        p->encoding = UTF16_CODESET;
00217 
00218        p->char_length = op->chiSymbolBufLen + zuinlen;
00219        buflen = (p->char_length + 1) * sizeof(UTFCHAR);
00220        p->text.utf_chars = (UTFCHAR *) s->If->m->iml_new(s, buflen);
00221        memset(p->text.utf_chars, 0, buflen);
00222 
00223        DEBUG_printf("Big5 text is %s\n", buf);
00224        DEBUG_printf("drawing preedit (charlen = %d, big5_bytes_len = %d)\n", p->char_length, len-1);
00225 
00226        bufutfp = (char *)p->text.utf_chars;
00227        iconv(iconv_context, (char **)&bufp, &len, &bufutfp, &buflen);
00228 
00229        p->feedback = create_feedback(s, p->char_length);
00230        return p;
00231 }
00232 
00233 void init_session_context(iml_session_t *s)
00234 {
00235        int i;
00236        ChewingConf cf ;
00237        ConfigData config;
00238        chewing_session_t *session = (chewing_session_t*)s->specific_data;
00239 
00240        if (session == NULL)
00241               session = calloc (sizeof (chewing_session_t), 1);
00242        else
00243               memset(session, 0, sizeof(chewing_session_t)); 
00244        /* Indeed we should free session entirely and realloc an new one */
00245 
00246        /* init chewing core */
00247        cf.kb_type = KB_DEFAULT;
00248        InitChewing(&session->chewing_data, &cf) ;
00249 
00250        config.selectAreaLen = 40;
00251        config.maxChiSymbolLen = 16;
00252        for(i=0; i<9; i++)
00253               config.selKey[i] = i + '1';
00254        config.selKey[9] = '0';
00255        SetConfig(&session->chewing_data, &config);
00256 
00257        MakeOutput(&session->chewing_output, &session->chewing_data);
00258 
00259        s->specific_data = (void*) session;
00260 }
00261 
00262 void open_preedit(iml_session_t *s)
00263 {
00264        iml_inst *lp = NULL;
00265        chewing_session_t *session = (chewing_session_t*)s->specific_data;
00266        if (!session->preedit_start) {
00267               lp = s->If->m->iml_make_preedit_start_inst(s);
00268               s->If->m->iml_execute(s, &lp);
00269        }
00270        session->preedit_start = True;
00271 }
00272 
00273 void close_preedit(iml_session_t *s)
00274 {
00275        iml_inst *lp=NULL, *rrv = NULL;
00276        chewing_session_t *session = (chewing_session_t*)s->specific_data;
00277        if (session->preedit_start) {
00278               lp = s->If->m->iml_make_preedit_erase_inst(s);
00279               s->If->m->iml_link_inst_tail(&rrv, lp);
00280               lp = s->If->m->iml_make_preedit_done_inst(s);
00281               s->If->m->iml_link_inst_tail(&rrv, lp);
00282               s->If->m->iml_execute(s, &rrv);
00283        }
00284        session->preedit_start = False;
00285 }
00286 
00287 void preedit_draw(iml_session_t *s)
00288 {
00289        IMText *p = NULL;
00290        iml_inst *lp=NULL, *rrv = NULL;
00291 
00292        if (!does_preedit_contain_text(s)) {
00293               close_preedit(s);
00294               return;
00295        }
00296 
00297        open_preedit(s);
00298        p = make_preedit_imtext(s);
00299        lp = s->If->m->iml_make_preedit_draw_inst(s, p);
00300        s->If->m->iml_link_inst_tail(&rrv, lp);
00301        lp = s->If->m->iml_make_preedit_caret_inst(s, get_session_caret_pos(s));
00302        s->If->m->iml_link_inst_tail(&rrv, lp);
00303        s->If->m->iml_execute(s, &rrv);
00304 }
00305 
00306 void open_candidate(iml_session_t *s)
00307 {
00308        chewing_session_t *session = (chewing_session_t *)s->specific_data;
00309 
00310        //   if (!session->luc_start) {
00311        ChoiceInfo *pci = session->chewing_output.pci;
00312        IMLookupStartCallbackStruct *start = 
00313               (IMLookupStartCallbackStruct *)s->If->m->iml_new(
00314                      s, sizeof(IMLookupStartCallbackStruct));
00315        memset(start, 0, sizeof(IMLookupStartCallbackStruct));
00316        start->whoIsMaster = IMIsMaster;
00317        start->IMPreference = (LayoutInfo *) s->If->m->iml_new(s, sizeof(LayoutInfo));
00318        memset(start->IMPreference, 0, sizeof(LayoutInfo));
00319        start->IMPreference->choice_per_window = pci->nChoicePerPage;
00320        start->IMPreference->ncolumns = pci->nChoicePerPage;
00321        start->IMPreference->nrows = 1;
00322        start->IMPreference->drawUpDirection = DrawUpHorizontally;
00323        start->IMPreference->whoOwnsLabel = IMOwnsLabel;
00324        start->CBPreference = NULL;
00325        iml_inst *lp = s->If->m->iml_make_lookup_start_inst(s, start);
00326        s->If->m->iml_execute(s, &lp);
00327        //    }
00328        //    session->luc_start = True;
00329 }
00330 
00331 void close_candidate (iml_session_t *s)
00332 {
00333        //chewing_session_t *session = (chewing_session_t *)s->specific_data;
00334 
00335        //    if (session->luc_start) {
00336        iml_inst *lp = s->If->m->iml_make_lookup_done_inst(s);
00337        s->If->m->iml_execute(s, &lp);
00338        //    }
00339        //    session->luc_start = False;
00340 }
00341 
00342 void draw_candidate (iml_session_t *s)
00343 {
00344        iml_inst *lp=NULL;
00345        chewing_session_t *session = (chewing_session_t *)s->specific_data;
00346        ChewingOutput *op = &session->chewing_output;
00347        IMLookupDrawCallbackStruct *draw;
00348        ChoiceInfo *pci = op->pci;
00349        int i, fc = pci->pageNo * pci->nChoicePerPage;
00350 
00351        open_candidate(s);
00352 
00353        draw = (IMLookupDrawCallbackStruct *) s->If->m->iml_new(s, sizeof(IMLookupDrawCallbackStruct));
00354        memset(draw, 0, sizeof(IMLookupDrawCallbackStruct));
00355        draw->n_choices = pci->nTotalChoice - fc;
00356        if (draw->n_choices > pci->nChoicePerPage) 
00357               draw->n_choices = pci->nChoicePerPage;
00358        draw->index_of_current_candidate = draw->index_of_first_candidate = 0;
00359        draw->index_of_last_candidate = draw->index_of_first_candidate + draw->n_choices - 1;
00360        draw->title = NULL;
00361 
00362        draw->title = (IMText *) s->If->m->iml_new(s, sizeof(IMText));
00363        memset(draw->title, 0, sizeof(IMText));
00364        draw->title->encoding = UTF16_CODESET;
00365        draw->title->char_length = 2;
00366        draw->title->text.utf_chars = (UTFCHAR *) s->If->m->iml_new(s, sizeof(IMText) * (draw->title->char_length + 1));
00367        memset(draw->title->text.utf_chars, 0, sizeof(IMText) * (draw->title->char_length + 1));
00368        memcpy (draw->title->text.utf_chars, chewing_string, (draw->title->char_length + 1) * sizeof(UTFCHAR));
00369        draw->title->feedback = create_feedback(s, draw->title->char_length);
00370 
00371        DEBUG_printf("%d of %d choices, starting at %d\n", draw->n_choices, draw->n_choices, draw->index_of_first_candidate);
00372 
00373        IMText **candidates = NULL, **labels=NULL;
00374        candidates = (IMText **) s->If->m->iml_new(s, draw->n_choices * sizeof(IMText *));
00375        memset(candidates, 0, draw->n_choices * sizeof(IMText *));
00376        for (i=0; i < draw->n_choices; ++i) {
00377               int buflen = 0, len=0;
00378               char *bufutfp = NULL;
00379               char *bufp = pci->totalChoiceStr[fc+i];
00380               DEBUG_printf("        --%d. %s\n", i+1, bufp); DEBUG_fflush(stdout);
00381 
00382               IMText *vt = candidates[i] = (IMText *)s->If->m->iml_new(s, sizeof(IMText));
00383               memset(vt, 0, sizeof(IMText));
00384 
00385               vt->encoding = UTF16_CODESET;
00386               len = (bufp)?(strlen(bufp)):0; 
00387               vt->char_length = len / 2;
00388               buflen = (vt->char_length + 1) * sizeof(UTFCHAR);
00389               vt->text.utf_chars = (UTFCHAR *)s->If->m->iml_new(s, buflen);
00390               memset(vt->text.utf_chars, 0, buflen);
00391               bufutfp = (char *)vt->text.utf_chars;
00392               iconv(iconv_context, (char **)&bufp, &len, &bufutfp, &buflen);
00393               vt->text.utf_chars[vt->char_length] = 0;
00394               vt->feedback = create_feedback(s, vt->char_length);
00395        }
00396 
00397        labels = (IMText **) s->If->m->iml_new(s, draw->n_choices * sizeof(IMText *));
00398        memset(labels, 0, draw->n_choices * sizeof(IMText *));
00399        for (i=0; i < draw->n_choices; ++i) {
00400               IMText *lt = labels[i] = (IMText *)s->If->m->iml_new(s, sizeof(IMText));
00401               memset(lt, 0, sizeof(IMText));
00402               lt->encoding = UTF16_CODESET;
00403               lt->char_length = 1;
00404               lt->text.utf_chars = (UTFCHAR *)s->If->m->iml_new(s, 2*sizeof(UTFCHAR));
00405               lt->text.utf_chars[0] = (UTFCHAR)(i+'1');
00406               lt->text.utf_chars[1] = (UTFCHAR)0;
00407               lt->feedback = create_feedback(s, lt->char_length);
00408        }
00409 
00410 
00411        draw->choices = (IMChoiceObject *)s->If->m->iml_new(s, draw->n_choices * sizeof(IMChoiceObject));
00412        memset(draw->choices, 0, draw->n_choices * sizeof(IMChoiceObject));
00413        for (i = draw->max_len = 0; i < draw->n_choices; i++) {
00414               draw->choices[i].value = candidates[i];
00415               if (draw->choices[i].value->char_length > draw->max_len)
00416                      draw->max_len = draw->choices[i].value->char_length;
00417               draw->choices[i].label = labels[i];
00418        }
00419        lp = s->If->m->iml_make_lookup_draw_inst(s, draw);
00420        s->If->m->iml_execute(s, &lp);
00421 }
00422 
00423 void handle_candidate (iml_session_t *s)
00424 {
00425        if (s) {
00426               chewing_session_t *session = (chewing_session_t *)s->specific_data;
00427 
00428               if (
00429                      session && 
00430                      (session->chewing_output.pci != NULL) && 
00431                      (session->chewing_output.pci->nTotalChoice > 0)) {
00432                      draw_candidate(s);
00433               } else {
00434                      close_candidate (s);
00435               }
00436        }
00437 }
00438 
00439 void chewing_conversion_on (iml_session_t *s)
00440 {
00441        if (s == NULL || s->specific_data == NULL) return;
00442 
00443        chewing_session_t *session = (chewing_session_t *)s->specific_data;
00444        iml_inst *lp = s->If->m->iml_make_start_conversion_inst(s);
00445        s->If->m->iml_execute(s, &lp);
00446 
00447        session->conv_on = True;
00448        status_draw(s);
00449 }
00450 
00451 void chewing_conversion_off (iml_session_t *s)
00452 {
00453        if (s == NULL || s->specific_data == NULL)
00454               return;
00455 
00456        close_candidate(s);
00457        close_preedit(s);
00458        init_session_context(s);
00459 
00460        iml_inst *lp = s->If->m->iml_make_end_conversion_inst(s);
00461        s->If->m->iml_execute(s, &lp);
00462 
00463        chewing_session_t *session = (chewing_session_t *)s->specific_data;
00464        session->conv_on = False;
00465        status_draw(s);
00466 }
00467 
00468 /* IF method implementation */
00469 
00470 Bool if_chewing_OpenIF (iml_if_t *If)
00471 {
00472        /* fix the data installation path and put it here */
00473        char *prefix = CHEWING_DATADIR;
00474 
00475        iconv_context = iconv_open ("UTF-16LE", "BIG5");
00476        DEBUG_printf("  ====> Chewing opening, iconv handle is %d ...", (int)iconv_context);
00477 
00478        ReadTree(prefix);
00479        InitChar(prefix);
00480        InitDict(prefix);
00481        ReadHash(prefix);
00482 
00483        DEBUG_printf(" done\n");
00484        return True;
00485 }
00486 
00487 /* FIX_NEEDED! Memory Leak! But not serious */
00488 Bool if_chewing_CloseIF (iml_if_t *If)
00489 {
00490        DEBUG_printf("  ====> Chewing closing...");
00491        iconv_close(iconv_context);
00492        DEBUG_printf(" done\n");
00493        return True;
00494 }
00495 
00496 Bool if_chewing_GetIFValues (iml_if_t *If, IMArgList args, int num_args)
00497 {
00498        return True;
00499 }
00500 
00501 Bool if_chewing_SetIFValues (iml_if_t *If, IMArgList args, int num_args)
00502 {
00503        return True;
00504 }
00505 
00506 Bool if_chewing_OpenDesktop (iml_desktop_t *desktop, IMArgList args, int num_args)
00507 {
00508        DEBUG_printf("  ====> Chewing open desktop...done!\n"); DEBUG_fflush(stdout);
00509        return True;
00510 }
00511 
00512 Bool if_chewing_CloseDesktop(iml_desktop_t *desktop)
00513 {
00514        DEBUG_printf("  ====> Chewing close desktop...done!\n"); DEBUG_fflush(stdout);
00515        return True;
00516 }
00517 
00518 Bool if_chewing_CreateSC (iml_session_t *s, IMArgList args, int num_args)
00519 {
00520        DEBUG_printf("  ====> Chewing create session..."); DEBUG_fflush(stdout);
00521 
00522        s->specific_data = NULL;
00523        init_session_context(s);
00524 
00525        DEBUG_printf("created session data %x, done!\n", (unsigned int)s->specific_data); DEBUG_fflush(stdout);
00526        return True;
00527 }
00528 
00529 Bool if_chewing_DestroySC (iml_session_t *s)
00530 {
00531        DEBUG_printf("  ====> Chewing destroy session..."); DEBUG_fflush(stdout);
00532        if (s->specific_data != NULL) {
00533               close_candidate(s);
00534               close_preedit(s);
00535               init_session_context(s);
00536               free(s->specific_data);
00537               s->specific_data = NULL;
00538        }
00539        DEBUG_printf("  done\n"); DEBUG_fflush(stdout);
00540        return True;
00541 }
00542 
00543 Bool if_chewing_GetSCValues(iml_session_t *s, IMArgList args, int num_args)
00544 {
00545        int i;
00546        IMArg *p = args;
00547 
00548        for (i = 0; i < num_args; i++, p++) {
00549               switch (p->id) {
00550                      default:
00551                             break;
00552               }
00553        }
00554        return True;
00555 }
00556 
00557 Bool if_chewing_SetSCValues (iml_session_t *s, IMArgList args, int num_args)
00558 {
00559        int i;
00560        IMArg *p = args;
00561        for (i = 0; i < num_args; i++, p++) {
00562               switch (p->id) {
00563                      case SC_TRIGGER_ON_NOTIFY:
00564                             DEBUG_printf("  ====> Chewing SC_TRIGGER_ON_NOTIFY \n");
00565                             chewing_conversion_on(s);
00566                             break;
00567                      case SC_TRIGGER_OFF_NOTIFY:
00568                             DEBUG_printf("  ====> Chewing SC_TRIGGER_OFF_NOTIFY \n");
00569                             chewing_conversion_off(s);
00570                             break;
00571                      case SC_REALIZE:
00572                             if(s->desktop->session_count == 1){
00573                                    DEBUG_printf("  ====> Chewing SC_REALIZE: just after OpenDesktop\n");
00574                             } else {
00575                                    DEBUG_printf("  ====> Chewing SC_REALIZE: received\n");
00576                             }
00577                             break;
00578                      default:
00579                             break;
00580               }
00581        }
00582        return True;
00583 }
00584 
00585 IMText *if_chewing_ResetSC (iml_session_t *s)
00586 {
00587        close_candidate(s);
00588        close_preedit(s);
00589        init_session_context(s);
00590        return (IMText *) NULL;
00591 }
00592 
00593 void if_chewing_SetSCFocus (iml_session_t *s)
00594 {
00595        if (s == NULL || s->specific_data == NULL) return;
00596 
00597        DEBUG_printf("  ====> Chewing set focus..."); DEBUG_fflush(stdout);
00598 
00599        chewing_session_t *session = (chewing_session_t *)s->specific_data;
00600        session->focus_on = True;
00601 
00602        status_draw(s);
00603        preedit_draw(s);
00604        handle_candidate(s);
00605        DEBUG_printf("  done\n"); DEBUG_fflush(stdout);
00606 }
00607 
00608 void if_chewing_UnsetSCFocus (iml_session_t *s)
00609 {
00610        if (s == NULL || s->specific_data == NULL) return;
00611 
00612        DEBUG_printf("  ====> Chewing lose focus..."); DEBUG_fflush(stdout);
00613 
00614        chewing_session_t *session = (chewing_session_t *)s->specific_data;
00615        session->focus_on = False;
00616 
00617        //status_draw(s);
00618        close_candidate(s);
00619        //close_preedit(s);
00620        DEBUG_printf("  done\n"); DEBUG_fflush(stdout);
00621 }
00622 
00623 void if_chewing_SendEvent (iml_session_t *s, IMInputEvent *ev)
00624 {
00625        chewing_session_t *session = (chewing_session_t *)s->specific_data;
00626        ChewingOutput *op = &session->chewing_output;
00627        ChewingData *pgdata = &session->chewing_data;
00628        IMKeyListEvent *keylistevent;
00629        IMKeyEventStruct *key;
00630 
00631        if (ev->type != IM_EventKeyList) 
00632               return;
00633 
00634        keylistevent = (IMKeyListEvent *) ev;
00635        key = (IMKeyEventStruct *) keylistevent->keylist;
00636        DEBUG_printf("  ====> Chewing processing key (0X%X - 0X%X - 0X%X) ...\n", 
00637                      key->keyCode, key->keyChar, key->modifier); 
00638        DEBUG_fflush(stdout);
00639 
00640        if ( (key->modifier & (IM_SHIFT_MASK | IM_CTRL_MASK | IM_ALT_MASK)) == IM_CTRL_MASK &&
00641                      key->keyChar == ' ' && session->conv_on ) {
00642               chewing_conversion_off(s);
00643               return;        
00644        }
00645        if (!session->conv_on) {
00646               iml_inst *lp;
00647               lp = s->If->m->iml_make_keypress_inst(s, key);
00648               s->If->m->iml_execute(s, &lp);
00649               return;
00650        }
00651 
00652        op->keystrokeRtn = KEYSTROKE_IGNORE;
00653        pgdata->zuinData.kbtype = currentKeyboard;
00654        switch (key->keyCode) {
00655               case IM_VK_CAPS_LOCK:
00656                      OnKeyCapslock(pgdata, op);
00657                      break;
00658 
00659               case IM_VK_ENTER:
00660                      OnKeyEnter(pgdata, op);
00661                      break;
00662 
00663               case IM_VK_ESCAPE:
00664                      OnKeyEsc(pgdata, op) ;
00665                      break;
00666 
00667               case IM_VK_BACK_SPACE:
00668                      OnKeyBackspace(pgdata, op);
00669                      break;
00670 
00671               case IM_VK_LEFT:
00672                      OnKeyLeft(pgdata, op);
00673                      break;
00674 
00675               case IM_VK_RIGHT:
00676                      OnKeyRight(pgdata, op);
00677                      break;
00678 
00679               case IM_VK_UP:
00680                      OnKeyUp(pgdata, op);
00681                      break;
00682 
00683               case IM_VK_DOWN:
00684                      OnKeyDown(pgdata, op);
00685                      break;
00686 
00687               case IM_VK_SPACE:
00688                      OnKeySpace(pgdata, op);
00689                      break;
00690 
00691               case IM_VK_HOME:
00692                      OnKeyHome(pgdata, op);
00693                      break;
00694 
00695               case IM_VK_END:
00696                      OnKeyEnd(pgdata, op);
00697                      break;
00698 
00699               case IM_VK_PAGE_UP:
00700               case IM_VK_PAGE_DOWN:
00701                      break;
00702 
00703               case IM_VK_TAB:
00704                      OnKeyTab(pgdata, op);
00705                      break;
00706 
00707               default:
00708                      /*
00709                         if (key->modifier & (controlKey|rightControlKey) && (inCharCode > '0' && inCharCode < '9'))
00710                         OnKeyCtrlNum(pgdata, inCharCode, op);
00711 
00712                         else if (inCharCode) {
00713                         if (modifiers & alphaLock && !(modifiers & shiftKey))
00714                         inCharCode |= 32;
00715                         */
00716                      if (key->keyChar && (key->modifier & (IM_CTRL_MASK | IM_ALT_MASK)) == 0)
00717                             OnKeyDefault(pgdata, key->keyChar, op);
00718                      break;
00719        }
00720 
00721        DEBUG_printf("        ---->return bitmask 0x%x\n", op->keystrokeRtn); DEBUG_fflush(stdout);
00722        if (op->keystrokeRtn & KEYSTROKE_COMMIT) {
00723               DEBUG_printf("    ---->commiting...\n");
00724               commit(s);
00725        }
00726        DEBUG_printf("        ---->update preedit...\n"); DEBUG_fflush(stdout);
00727        preedit_draw(s);
00728        DEBUG_printf("        ---->handle candidate...\n"); DEBUG_fflush(stdout);
00729        handle_candidate(s);
00730        DEBUG_printf("done!"); DEBUG_fflush(stdout);
00731 
00732        /* is there any way to bell on the client? */
00733        /*
00734           if (op->keystrokeRtn & KEYSTROKE_BELL)
00735           SysBeep();
00736           */
00737 
00738        if (op->keystrokeRtn & KEYSTROKE_IGNORE) {
00739               iml_inst *lp;
00740               lp = s->If->m->iml_make_keypress_inst(s, key);
00741               s->If->m->iml_execute(s, &lp);
00742        }
00743 
00744        return;
00745 }
00746 
00747 /* IF Method */
00748 static if_methods_t chewing_methods = {
00749        if_chewing_OpenIF,
00750        if_chewing_CloseIF,
00751        if_chewing_GetIFValues,
00752        if_chewing_SetIFValues,
00753        if_chewing_OpenDesktop,
00754        if_chewing_CloseDesktop,
00755        if_chewing_CreateSC,
00756        if_chewing_DestroySC,
00757        if_chewing_GetSCValues,
00758        if_chewing_SetSCValues,
00759        if_chewing_ResetSC,
00760        if_chewing_SetSCFocus,
00761        if_chewing_UnsetSCFocus,
00762        if_chewing_SendEvent
00763 };
00764 
00765 /* 酷音輸入法 */
00766 UTFCHAR lename_string[] = {
00767        0x9177, 0x97f3, 0x8f38, 0x5165, 0x6cd5, 0x0
00768 };
00769 
00770 static IMLEName lename = {
00771        "chewing", (UTFCHAR *) lename_string
00772 };
00773 
00774 /* 繁體中文 */
00775 UTFCHAR locale_string[] = {
00776        0x7e41, 0x9ad4, 0x4e2d, 0x6587, 0x0
00777 };
00778 static IMLocale locales[] = {
00779        { "zh_TW", (UTFCHAR *) locale_string },
00780        { NULL, NULL }
00781 };
00782 
00783 void if_GetIfInfo (IMArgList args, int num_args)
00784 {
00785        int i;
00786 
00787        for (i = 0; i < num_args; i++, args++) {
00788               switch (args->id) {
00789                      case IF_VERSION:
00790                             args->value = (IMArgVal) CHEWING_VERSION;
00791                             break;
00792                      case IF_METHOD_TABLE:
00793                             args->value = (IMArgVal) & chewing_methods;
00794                             break;
00795                      case IF_LE_NAME:
00796                             args->value = (IMArgVal) & lename;
00797                             break;
00798                      case IF_SUPPORTED_LOCALES:
00799                             args->value = (IMArgVal) & locales;
00800                             break;
00801                      case IF_SUPPORTED_OBJECTS:
00802                             break;
00803                      case IF_NEED_THREAD_LOCK:
00804                             args->value = (IMArgVal) True;
00805                             break;
00806                      default:
00807                             break;
00808               }
00809        }
00810 }
00811