Back to index

im-sdk  12.3.91
chewing_im.c
Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <unistd.h>
00003 
00004 #include "ime.h"
00005 #include "chewing_im.h"
00006 
00007 #define CHEWING_DATADIR         "/usr/share/chewing"
00008 #define CHEWING_NAME_BIG5       "\267\163\273\305\255\265"
00009 #define CHEWING_UUID            "chewing-9d3878a2-ca6a-4dbb-9e81-62b3774716c3"
00010 #define CHEWING_VERSION            200
00011 #define AUTHOR \
00012        "Chewing core team <http://chewing.csie.net>\n" \
00013        "Gavin Tu <Gavin.Tu@sun.com>"
00014 #define COPYRIGHT           "Copyright (c) 2005 Chewing core team"
00015 #define HINTING                    "Chewing Input Method"
00016 #define CHEWING_ICONPATH        "chewing.xpm"
00017 
00018 ImeResult chewing_Initialize(ImeInfo ime_info);
00019 ImeResult chewing_Destroy(ImeInfo ime_info);
00020 ImeResult chewing_Process_Key_Event(ImeInputContext ic, ImeKey key_event);
00021 ImeResult chewing_Create_Session(ImeInputContext ic);
00022 ImeResult chewing_Destroy_Session(ImeInputContext ic);
00023 ImeResult chewing_FocusOut(ImeInputContext ic);
00024 ImeResult chewing_FocusIn(ImeInputContext ic);
00025 
00026 ImmServices imm_services;
00027 
00028 ImeMethodsRec chewing_methods = {
00029     1,                      /* version */
00030     chewing_Initialize,            /* ImeInitialize */
00031     chewing_Destroy,        /* ImeDestroy  */
00032     chewing_Process_Key_Event,     /* ImeProcessKeyEvent */
00033     NULL,                   /* ImeProcessAuxEvent  */
00034     chewing_Create_Session, /* ImeAttachSession */
00035     chewing_Destroy_Session,       /* ImeDetachSession */
00036     chewing_FocusIn,        /* ImeFocusIn  */
00037     chewing_FocusOut,              /* ImeFocusOut */
00038     NULL,                   /* ImeAttachUser */
00039     NULL,                   /* ImeDetachUser */
00040     NULL,                   /* ImeAttachDesktop */
00041     NULL,                   /* ImeDetachDesktop */
00042     NULL,                   /* ImeGetErrorMessage */
00043 #if 0
00044     NULL,                   /* ImeDoConfig */
00045 #endif
00046 };
00047 
00048 #ifdef WIN32
00049 #define EXPORT extern __declspec(dllexport)
00050 EXPORT
00051 #endif
00052 ImeResult RegisterIME(ImmServices srvs, ImeInfo * ppinfo,
00053                     ImeMethods * pmthds, int argc, char **argv)
00054 {
00055     ImeInfoRec *chewing_info = NULL;
00056     char *base_dir = NULL;
00057     int i;
00058 
00059     DEBUG_printf("Register Chewing IM: argc: %d\n", argc);
00060     for (i = 0; i < argc; i++) {
00061        if (!strcasecmp(argv[i], "-basedir")) {
00062            if (argv[i + 1]) {
00063               base_dir = argv[i + 1];
00064               DEBUG_printf("       setting base dir to: %s\n",
00065                           argv[i + 1]);
00066            }
00067            i++;
00068        }
00069     }
00070 
00071     if (access("/usr/lib/libchewing.so", R_OK) != 0) {
00072        fprintf(stderr, "Error: Chewing: /usr/lib/libchewing.so not found !!\n");
00073        return (IME_FAIL);
00074     }
00075 
00076     if (access(CHEWING_DATADIR "/dict.dat", R_OK) != 0) {
00077        fprintf(stderr, "Error: Chewing: data directory: %s not found !!\n", CHEWING_DATADIR);
00078        return (IME_FAIL);
00079     }
00080 
00081     chewing_info = (ImeInfoRec *) calloc(1, sizeof(ImeInfoRec));
00082     DEBUG_printf("chewing_info: %p\n", chewing_info);
00083     if (chewing_info == NULL) {
00084        return (IME_FAIL);
00085     }
00086 
00087     chewing_info->version = CHEWING_VERSION;
00088     chewing_info->mt_safe = 0;
00089     chewing_info->encoding = ENCODE_BIG5;
00090     chewing_info->uuid = CHEWING_UUID;
00091     chewing_info->name = CHEWING_NAME_BIG5;
00092     chewing_info->author = AUTHOR;
00093     chewing_info->hinting = HINTING;
00094     chewing_info->copyright = COPYRIGHT;
00095     chewing_info->icon_file = CHEWING_ICONPATH;
00096     chewing_info->support_locales = "zh_TW.UTF-8,zh_TW.BIG5";
00097     chewing_info->pl = NULL;
00098     chewing_info->specific_data = NULL;
00099 
00100     chewing_Init_Ime_Properties(chewing_info);
00101 
00102     *ppinfo = chewing_info;
00103     *pmthds = &chewing_methods;
00104 
00105     imm_services = srvs;
00106 
00107     DEBUG_printf("begin leave Register IME\n");
00108     return (IME_OK);
00109 }
00110 
00111 ImeResult chewing_Initialize(ImeInfo chewing_info)
00112 {
00113     char *prefix = CHEWING_DATADIR;
00114 
00115     DEBUG_printf("chewing_Initialize\n");
00116 
00117     if (chewing_info == NULL)
00118        return (IME_FAIL);
00119 
00120     ReadTree(prefix);
00121 
00122     if (InitChar(prefix) == 0) {
00123        fprintf(stderr, "Error: Chewing dictionary file corrupted!\n");
00124        return (IME_FAIL);
00125     }
00126 
00127     InitDict(prefix);
00128 
00129     if (ReadHash(prefix) == 0) {
00130        fprintf(stderr, "Error: Chewing's user phrase library load failed! \n");
00131        return (IME_FAIL);
00132     }
00133 
00134     DEBUG_printf("Chewing initialize done\n");
00135 
00136     return (IME_OK);
00137 }
00138 
00139 ImeResult chewing_Destroy(ImeInfo chewing_info)
00140 {
00141     DEBUG_printf("chewing_Destroy\n");
00142 
00143     if (chewing_info != NULL) {
00144        chewing_Destroy_Ime_Properties(chewing_info);
00145        free((char *) chewing_info);
00146     }
00147 
00148     return (IME_OK);
00149 }
00150 
00151 ImeResult chewing_Create_Session(ImeInputContext ic)
00152 {
00153     int i;
00154     ImmResult imm_result;
00155     ImeInfoRec *chewing_info = NULL;
00156     chewing_session_t *chewing_session;
00157 
00158     chewing_session = (chewing_session_t *) imm_services->ImmGetData(ic, IME_SCOPE_SESSION);
00159     DEBUG_printf ("chewing_Create_Session ======= begin get ime_session_data: %p\n",
00160                 chewing_session);
00161     if (chewing_session == NULL) {
00162        int i;
00163        ChewingConf cf;
00164        ConfigData config;
00165        char default_selectionKeys[] = "1234567890";
00166 
00167        DEBUG_printf("chewing_Create_Session ======= begin calloc for chewing_session\n");
00168        chewing_session = (chewing_session_t *) calloc(1, sizeof(chewing_session_t));
00169        if (chewing_session == NULL)
00170            return (IME_FAIL);
00171 
00172        /* init chewing core */
00173        chewing_session->keyboard_type = KB_DEFAULT;
00174 
00175        cf.kb_type = KB_DEFAULT;
00176        InitChewing(&chewing_session->chewing_data, &cf);
00177 
00178        config.selectAreaLen = 40;
00179        config.maxChiSymbolLen = 16;
00180 
00181        for (i = 0; i < 10; i++)
00182            config.selKey[i] = default_selectionKeys[i];
00183 
00184        config.bAddPhraseForward = 1;
00185 
00186        SetConfig(&chewing_session->chewing_data, &config);
00187 
00188        MakeOutput(&chewing_session->chewing_output,
00189                  &chewing_session->chewing_data);
00190 
00191        imm_result = imm_services->ImmSetData(ic, IME_SCOPE_SESSION, chewing_session);
00192        if (imm_result == IMM_FAIL) {
00193            free((char *) chewing_session);
00194            return (IME_FAIL);
00195        }
00196     }
00197 
00198     return (IME_OK);
00199 }
00200 
00201 ImeResult chewing_Destroy_Session(ImeInputContext ic)
00202 {
00203     chewing_session_t *chewing_session;
00204 
00205     chewing_session = (chewing_session_t *) imm_services->ImmGetData(ic, IME_SCOPE_SESSION);
00206     DEBUG_printf (" ====>chewing_Destroy_Session ======= begin get ime_session_data: %p\n",
00207                 chewing_session);
00208 
00209     if (chewing_session != NULL) {
00210        free((char *) chewing_session);
00211     }
00212 
00213     imm_services->ImmSetData(ic, IME_SCOPE_SESSION, NULL);
00214     return (IME_OK);
00215 }
00216 
00217 ImeResult chewing_FocusIn(ImeInputContext ic)
00218 {
00219     DEBUG_printf("codetable: call chewing_FocusIn()\n");
00220     return (IME_OK);
00221 }
00222 
00223 ImeResult chewing_FocusOut(ImeInputContext ic)
00224 {
00225     DEBUG_printf("codetable: call chewing_FocusOut()\n");
00226     return (IME_OK);
00227 }
00228 
00229 ImmResult chewing_session_beep(ImeInputContext ic, chewing_session_t * chewing_session)
00230 {
00231     return (imm_services->ImmBeep(ic, ImeBeepWarning));
00232 }
00233 
00234 ImmResult chewing_session_commit(ImeInputContext ic, chewing_session_t * chewing_session)
00235 {
00236     int i;
00237     char buf[128];
00238 
00239     ChewingOutput *op = &chewing_session->chewing_output;
00240 
00241     if (!op->nCommitStr)
00242        return;
00243 
00244     memset(buf, 0, 128);
00245     for (i = 0; i < op->nCommitStr; ++i) {
00246        strcat(buf, op->commitStr[i].s);
00247     }
00248 
00249     imm_services->ImmCommit(ic, buf);
00250 
00251     op->nCommitStr = 0;
00252 
00253     return (IME_OK);
00254 }
00255 
00256 ImmResult chewing_session_show_preedit(ImeInputContext ic, chewing_session_t * chewing_session)
00257 {
00258     ImePreeditRec ime_preedit;
00259 
00260     int i, caret_pos;
00261     int len = 0;
00262     char buf[128];
00263 
00264     ChewingOutput *op = &chewing_session->chewing_output;
00265 
00266     memset(buf, 0, 128);
00267     for (i = 0; i < op->chiSymbolCursor; ++i)
00268        strcat(buf, op->chiSymbolBuf[i].s);
00269 
00270     for (i = 0; i < ZUIN_SIZE; ++i) {
00271        strcat(buf, op->zuinBuf[i].s);
00272     }
00273 
00274     for (i = op->chiSymbolCursor; i < op->chiSymbolBufLen; ++i)
00275        strcat(buf, op->chiSymbolBuf[i].s);
00276 
00277     len = strlen(buf);
00278     if (len == 0) {
00279        return (imm_services->ImmHidePreedit(ic));
00280     }
00281 
00282     imm_services->ImmShowPreedit(ic);
00283 
00284     caret_pos = op->chiSymbolCursor;
00285     if (caret_pos < 0 || caret_pos > 100)
00286        caret_pos = 0;
00287 
00288     memset(&ime_preedit, 0, sizeof(ImePreeditRec));
00289     ime_preedit.caret = caret_pos;
00290     ime_preedit.preedit.text = buf;
00291 
00292     return (imm_services->ImmUpdatePreedit(ic, &ime_preedit));
00293 }
00294 
00295 ImmResult chewing_session_handle_candidates(ImeInputContext ic, chewing_session_t * chewing_session)
00296 {
00297     ImmResult imm_result;
00298     ImeCandidatesRec ime_candidates;
00299 
00300     ChewingOutput *op = &chewing_session->chewing_output;
00301     ChoiceInfo *pci = op->pci;
00302     int i, fc, num_candidates;
00303     int page_state = 0;
00304 
00305     if (pci == NULL || pci->nTotalChoice <= 0) {
00306        return (imm_services->ImmHideCandidates(ic));
00307     }
00308 
00309     fc = pci->pageNo * pci->nChoicePerPage;
00310     if (pci->pageNo == 0)
00311        page_state |= ImeCandidatesFirstPage;  /* disable PageUp icon */
00312 
00313     num_candidates = pci->nTotalChoice - fc;
00314     if (num_candidates > pci->nChoicePerPage) {
00315        num_candidates = pci->nChoicePerPage;
00316     } else {
00317        page_state |= ImeCandidatesLastPage;    /* disable PageDown icon */
00318     }
00319 
00320     memset(&ime_candidates, 0, sizeof(ImeCandidatesRec));
00321 
00322     ime_candidates.title = NULL;
00323     ime_candidates.numbers = NULL;
00324     ime_candidates.focus = 0;
00325     ime_candidates.page_state = page_state;
00326     ime_candidates.count = num_candidates;
00327     ime_candidates.candidates = (ImeTextRec *) calloc(num_candidates, sizeof(ImeTextRec));
00328     if (ime_candidates.candidates == NULL)
00329        return (IMM_FAIL);
00330 
00331     for (i = 0; i < num_candidates; i++) {
00332        ime_candidates.candidates[i].text = pci->totalChoiceStr[fc + i];
00333     }
00334 
00335     imm_result = imm_services->ImmUpdateCandidates(ic, &ime_candidates);
00336 
00337     imm_services->ImmShowCandidates(ic);
00338 
00339     free ((char *)ime_candidates.candidates);
00340     return (imm_result);
00341 }
00342 
00343 /* process key input event */
00344 /* return value:  IME_UNUSED_KEY:  if IME not use this key, return this key to systerm directly */
00345 /*                IME_OK:      if IME has used this key */
00346 ImeResult chewing_Process_Key_Event(ImeInputContext ic, ImeKey key_event)
00347 {
00348     chewing_session_t *chewing_session = NULL;
00349     ChewingOutput *op;
00350     ChewingData *pgdata;
00351 
00352     long kcode, kstate;
00353     unsigned short kchar;
00354 
00355     DEBUG_printf("chewing_Process_Key_Event: ic: %p\n", ic);
00356     chewing_session = (chewing_session_t *) imm_services->ImmGetData(ic, IME_SCOPE_SESSION); 
00357     if (chewing_session == NULL)
00358        return (IME_UNUSED_KEY);
00359 
00360     kcode = key_event->keycode;
00361     kchar = key_event->keychar;
00362     kstate = key_event->modifier;
00363 
00364     DEBUG_printf ("  ====> Chewing processing key (0X%X - 0X%X - 0X%X) ...\n",
00365                 kcode, kchar, kstate);
00366 
00367     chewing_Set_Ime_Properties(ic, chewing_session);
00368 
00369     op = &chewing_session->chewing_output;
00370     pgdata = &chewing_session->chewing_data;
00371 
00372     op->keystrokeRtn = KEYSTROKE_IGNORE;
00373     pgdata->zuinData.kbtype = chewing_session->keyboard_type;
00374 
00375     if (kstate == 0) {
00376         switch (kcode) {
00377         case IME_VK_PAGE_UP:
00378         case IME_VK_LEFT:
00379            OnKeyLeft(pgdata, op);
00380            break;
00381 
00382         case IME_VK_PAGE_DOWN:
00383         case IME_VK_RIGHT:
00384            OnKeyRight(pgdata, op);
00385            break;
00386 
00387         case IME_VK_UP:
00388            OnKeyUp(pgdata, op);
00389            break;
00390 
00391         case IME_VK_DOWN:
00392            OnKeyDown(pgdata, op);
00393            break;
00394 
00395         case IME_VK_SPACE:
00396            OnKeySpace(pgdata, op);
00397            break;
00398 
00399         case IME_VK_CAPS_LOCK:
00400            OnKeyCapslock(pgdata, op);
00401            break;
00402 
00403         case IME_VK_ENTER:
00404            OnKeyEnter(pgdata, op);
00405            break;
00406 
00407         case IME_VK_BACK_SPACE:
00408            OnKeyBackspace(pgdata, op);
00409            break;
00410 
00411         case IME_VK_ESCAPE:
00412            OnKeyEsc(pgdata, op);
00413            break;
00414 
00415         case IME_VK_DELETE:
00416            OnKeyDel(pgdata, op);
00417            break;
00418 
00419         case IME_VK_HOME:
00420            OnKeyHome(pgdata, op);
00421            break;
00422 
00423         case IME_VK_END:
00424            OnKeyEnd(pgdata, op);
00425            break;
00426 
00427         case IME_VK_TAB:
00428            OnKeyTab(pgdata, op);
00429            break;
00430 
00431         default:
00432            if (kchar)
00433                OnKeyDefault(pgdata, kchar, op);
00434            break;
00435         }
00436     } else if (kstate == IME_SHIFT_MASK) {
00437         switch (kcode) {
00438         case IME_VK_PAGE_UP:
00439         case IME_VK_LEFT:
00440            OnKeyLeft(pgdata, op);
00441            break;
00442 
00443         case IME_VK_PAGE_DOWN:
00444         case IME_VK_RIGHT:
00445            OnKeyRight(pgdata, op);
00446            break;
00447 
00448         default:
00449            if (kchar)
00450                OnKeyDefault(pgdata, kchar, op);
00451            break;
00452         }
00453     } else if (kstate == IME_CTRL_MASK) {
00454         /* Handle user-phrase addition */
00455        if (kchar <= '9' && kchar >= '0')
00456            OnKeyCtrlNum (pgdata, kchar, op);
00457     }
00458 
00459     DEBUG_printf("  ---->return bitmask 0x%x\n", op->keystrokeRtn);
00460     if (op->keystrokeRtn & KEYSTROKE_COMMIT) {
00461        DEBUG_printf("    ---->commiting...\n");
00462        chewing_session_commit(ic, chewing_session);
00463     }
00464 
00465     DEBUG_printf("    ---->show preedit...\n");
00466     chewing_session_show_preedit(ic, chewing_session);
00467 
00468     DEBUG_printf("    ---->handle candidates...\n");
00469     chewing_session_handle_candidates(ic, chewing_session);
00470 
00471     if (op->keystrokeRtn & KEYSTROKE_BELL)
00472        chewing_session_beep(ic, chewing_session);
00473 
00474     if (op->keystrokeRtn & KEYSTROKE_ABSORB)
00475        return (IME_OK);
00476 
00477     if (op->keystrokeRtn & KEYSTROKE_IGNORE)
00478        return (IME_UNUSED_KEY);
00479 
00480     return (IME_OK);
00481 }