gen-inp-v1.c
来自「linux 下的 oxim 输入法,简单易用.」· C语言 代码 · 共 1,570 行 · 第 1/3 页
C
1,570 行
return cmp;}static int sort_cache(const void *a, const void *b){ cache_t *aa = (cache_t *)a, *bb = (cache_t *)b; int cmp = strcmp(aa->keystroke, bb->keystroke); if (cmp == 0) return 0; else if (cmp > 0) return 1; else return -1;}static int get_cache(gen_inp_conf_t *cf, char *keystroke, unsigned int *ret_start, unsigned int *ret_end){ int low, middle, high; int cmp_value; if (cf->n_cache) { low = 0; high = cf->n_cache - 1; while (low <= high) { middle = (low+high) >> 1; cmp_value = strcmp(cf->cache[middle].keystroke, keystroke); if (cmp_value == 0) { break; } else if (cmp_value > 0) { high = middle - 1; } else { low = middle + 1; } } if (cmp_value == 0) { *ret_start = cf->cache[middle].start_idx; *ret_end = cf->cache[middle].end_idx; return True; } } return False;}static void set_cache(gen_inp_conf_t *cf, char *keystroke, unsigned int start_idx, unsigned int end_idx){ cf->n_cache ++; unsigned int cache_pos = cf->n_cache - 1; if (cf->n_cache == 1) { cf->cache = oxim_malloc(sizeof(cache_t), False); } else { cf->cache = oxim_realloc(cf->cache, sizeof(cache_t) * cf->n_cache); } cf->cache[cache_pos].keystroke = strdup(keystroke); cf->cache[cache_pos].start_idx = start_idx; cf->cache[cache_pos].end_idx = end_idx; stable_sort(cf->cache, cf->n_cache, sizeof(cache_t), sort_cache);}static int bsearch_keystroke(gen_inp_conf_t *cf, char *keystroke, int size, int *end_idx){ int head, middle, end, start_idx, last_idx; int ret; /* 優先找 cache */ /* 全部存放於記憶體,就不必找 cache */ if (!cf->direct_mode) { unsigned int ret_start, ret_end; if (get_cache(cf, keystroke, &ret_start, &ret_end)) { *end_idx = ret_end; return (ret_start); } } head = 0; middle = size >> 1; end = size; while ((ret=cmp_icvalue(cf, keystroke, middle, False))) { if (ret > 0) end = middle; else head = middle + 1; middle = (end + head) >> 1; if (middle == head && middle == end) break; } if (ret == 0) { start_idx = last_idx = middle; /* 找該組字的一筆索引 */ while(start_idx > 0 && ! cmp_icvalue(cf, keystroke, start_idx-1, False)) { start_idx --; } /* 找最後一筆索引 */ while(!cmp_icvalue(cf, keystroke, last_idx+1, False)) { last_idx++; } *end_idx = last_idx; /* 如果直接讀取磁碟,且同字根數量超過 50,就加入 cache 列表 */ if (cf->direct_mode && (last_idx - start_idx) >= 50) { set_cache(cf, keystroke, start_idx, last_idx); } return start_idx; } return -1;}static intmatch_keystroke(gen_inp_conf_t *cf, inpinfo_t *inpinfo, gen_inp_iccf_t *iccf){ int ret, start_idx, end_idx; char *keystroke = iccf->keystroke; inpinfo->n_mcch = 0; if (!(iccf->mode & INPINFO_MODE_INWILD)) { start_idx = bsearch_keystroke(cf, keystroke, cf->header.n_input_content, &end_idx); if (start_idx < 0) { return False; } } else { int i, cmp; /* 如果只有一個 '*' 或 '?' 沒啥意義,當作沒這回事 :-P */ if (strlen(keystroke) == 1 && (keystroke[0]=='*' || keystroke[0]=='?')) { return False; } /* 查 cache */ int first = -1, last; int hit_cache = get_cache(cf, keystroke, &start_idx, &end_idx); if (!hit_cache) { start_idx = 0; end_idx = cf->header.n_input_content - 1; } if (iccf->mkey_list) { free(iccf->mkey_list); iccf->mkey_list = NULL; } iccf->n_mkey_list = 0; for (i = start_idx ; i < end_idx ; i++) { cmp = cmp_icvalue(cf, keystroke, i, True); if (cmp == 0) { if (first < 0) { first = i; } iccf->n_mkey_list ++; if (iccf->n_mkey_list == 1) { iccf->mkey_list = oxim_malloc(sizeof(unsigned int), False); } else { iccf->mkey_list = oxim_realloc(iccf->mkey_list, sizeof(unsigned int)*iccf->n_mkey_list); } iccf->mkey_list[iccf->n_mkey_list -1] = i; last = i; } } if (!iccf->n_mkey_list) { return False; } /* 如果沒有找到 cache, 就設定 cache */ if (!hit_cache) { set_cache(cf, keystroke, first, last); } start_idx = 0; end_idx = iccf->n_mkey_list - 1; } iccf->n_record = end_idx - start_idx + 1; /* 總共幾筆紀錄 */ iccf->n_page = iccf->n_record / inpinfo->n_selkey + ((iccf->n_record % inpinfo->n_selkey) ? 1 : 0); iccf->start_idx = start_idx; iccf->end_idx = end_idx; iccf->this_page = 0; ret = fillpage(cf, inpinfo, iccf, 0); if (inpinfo->n_mcch > 1 && (iccf->mode & INPINFO_MODE_SPACE)) { iccf->mode &= ~(INPINFO_MODE_SPACE); } return ret;}/*------------------------------------------------------------------------*/static voidcommit_content(gen_inp_conf_t *cf, inpinfo_t *inpinfo, gen_inp_iccf_t *iccf, int idx){ static char cch_s[1024]; unsigned int n_char = inpinfo->mcch_grouping[idx+1]; /* 有幾個字? */ unsigned int mcch_idx = 0; int i; for (i=0 ; i < idx ; i++) { mcch_idx += inpinfo->mcch_grouping[i+1]; } cch_s[0] = '\0'; while (n_char--) { strcat(cch_s, inpinfo->mcch[mcch_idx++].s); } inpinfo->cch = cch_s; inpinfo->cch_publish.uch = 0; /* 只有單一字元才需要提示字根 */ if (inpinfo->mcch_grouping[idx+1] == 1) { /* 計算真正的索引位置 */ /* idx 是目前頁的位置,所以要加上該筆劃的起始偏移值 */ unsigned int new_idx = (iccf->this_page * inpinfo->n_selkey) + idx + iccf->start_idx; unsigned int true_idx = new_idx; /* 有萬用字元的話要取 mkey_list[new_idx] */ if (strchr(iccf->keystroke,'*') || strchr(iccf->keystroke,'?')) { true_idx = iccf->mkey_list[new_idx]; } cintab_input_content cic; void *icr = get_input_content(cf, true_idx); /* 字根長度 */ memcpy(&cic.n_keystroke, icr, 1); /* 字根內容(注意! 沒有包含 NULL 字元) */ cic.keystroke = icr+2; /* 字元內容 */ cic.content = icr + 2 + cic.n_keystroke; for (i = 0 ; i < cic.n_keystroke ; i++) { int keycode = cic.keystroke[i]; inpinfo->suggest_skeystroke[i].uch = cf->header.keyname[keycode].uch; } oxim_ucs4_to_utf8(cic.content[0], inpinfo->cch_publish.s); free(icr); } if (inpinfo->mcch) { free(inpinfo->mcch); inpinfo->mcch = NULL; inpinfo->n_mcch = 0; } inpinfo->keystroke_len = 0; inpinfo->s_keystroke[0].uch = 0; inpinfo->mcch_pgstate = MCCH_ONEPG; iccf->mode &= ~(INPINFO_MODE_MCCH); iccf->mode &= ~(INPINFO_MODE_INWILD); inpinfo->guimode &= ~(GUIMOD_SELKEYSPOT);}static unsigned intcommit_keystroke(gen_inp_conf_t *cf, inpinfo_t *inpinfo, gen_inp_iccf_t *iccf)/* return: the IMKEY state */{ if (cf->n_kremap) { int i; for (i=0; i<cf->n_kremap; i++) { if (strcmp(iccf->keystroke, cf->kremap[i].keystroke) == 0) { inpinfo->cch = cf->kremap[i].uch.s; inpinfo->keystroke_len = 0; inpinfo->s_keystroke[0].uch = (uchar_t)0; inpinfo->n_mcch = 0; inpinfo->cch_publish.uch = 0; inpinfo->mcch_pgstate = MCCH_ONEPG; iccf->mode &= ~(INPINFO_MODE_MCCH); iccf->mode &= ~(INPINFO_MODE_INWILD); inpinfo->guimode &= ~(GUIMOD_SELKEYSPOT); return IMKEY_COMMIT; } } } if (match_keystroke(cf, inpinfo, iccf)) { if (inpinfo->n_mcch == 1) { commit_content(cf, inpinfo, iccf, 0); return IMKEY_COMMIT; } else { iccf->mode |= INPINFO_MODE_MCCH; inpinfo->guimode |= GUIMOD_SELKEYSPOT; return return_correct(cf); } } else { if ((cf->mode & INP_MODE_AUTORESET)) { reset_keystroke(inpinfo, iccf); } else { iccf->mode |= INPINFO_MODE_WRONG; } return return_wrong(cf); }}/*------------------------------------------------------------------------*/static intmcch_choosech(gen_inp_conf_t *cf, inpinfo_t *inpinfo, gen_inp_iccf_t *iccf, int idx){ int min; if (inpinfo->n_mcch == 0 && ! match_keystroke(cf, inpinfo, iccf)) { return 0; } if (idx < 0) /* Always select the first. */ { idx = 0; } else { if ((cf->mode & INP_MODE_SELKEYSHIFT)) { idx ++; } min = (inpinfo->n_selkey > inpinfo->n_mcch) ? inpinfo->n_mcch : inpinfo->n_selkey; if (idx >= min) { return 0; } } commit_content(cf, inpinfo, iccf, idx); reset_keystroke(inpinfo, iccf); return 1;}static intfillpage(gen_inp_conf_t *cf, inpinfo_t *inpinfo, gen_inp_iccf_t *iccf, byte_t dir){ unsigned int n_pg = inpinfo->n_selkey; /* 每一頁顯示項目長度 */ cintab_input_content cic; void *icr; unsigned int i, j, idx, item, have_word; switch (dir) { case 0: /* 從第一頁開始 */ iccf->this_page = 0; break; case 1: /* 下一頁 */ if ((iccf->this_page + 1) >= iccf->n_page) { return False; } iccf->this_page ++; break; case -1: /* 前一頁 */ if ((iccf->this_page - 1) < 0) { return False; } iccf->this_page --; break; } /* 計算顯示頁的起始索引 */ idx = (iccf->this_page * n_pg) + iccf->start_idx; /* 本頁筆數 */ if ((iccf->end_idx - idx + 1) < n_pg) { n_pg = iccf->end_idx - idx + 1; } if (inpinfo->mcch) { free(inpinfo->mcch); inpinfo->mcch = NULL; } inpinfo->n_mcch = 0; inpinfo->mcch_grouping[0] = 0; /* 預設是沒有詞 */ i = 0; have_word = False; for (item = 0 ; item < n_pg ; item++) { /* 讀取真正的輸入資料 */ icr = get_input_content(cf, ((iccf->mode & INPINFO_MODE_INWILD) ? iccf->mkey_list[idx] : idx)); /* 字根長度 */ memcpy(&cic.n_keystroke, icr, 1); /* 字元數目 */ memcpy(&cic.n_char, icr+1, 1); /* 字根內容(注意! 沒有包含 NULL 字元) */ cic.keystroke = icr+2; /* 字元內容 */ cic.content = icr + 2 + cic.n_keystroke; /* 加總字元數目 */ inpinfo->n_mcch += cic.n_char; /* 配置所需的記憶體 */ if (inpinfo->n_mcch == cic.n_char) { inpinfo->mcch = oxim_malloc(sizeof(uch_t) * cic.n_char, False); } else { inpinfo->mcch = oxim_realloc(inpinfo->mcch, sizeof(uch_t)*inpinfo->n_mcch); } /* i : inpinfo->mcch 的索引 j : 單一輸入資料字元索引 */ for (j = 0 ; j < cic.n_char; j++, i++) { oxim_ucs4_to_utf8(cic.content[j], inpinfo->mcch[i].s); } inpinfo->mcch_grouping[item+1] = cic.n_char; /* 超過一個字,表示這是詞 */ if (cic.n_char > 1) { have_word = True; } idx ++; free(icr); } inpinfo->mcch_grouping[0] = have_word ? n_pg : 0; if (iccf->n_page == 1) inpinfo->mcch_pgstate = MCCH_ONEPG; else if (iccf->this_page == 0) inpinfo->mcch_pgstate = MCCH_BEGIN; else if ((iccf->this_page + 1) == iccf->n_page) inpinfo->mcch_pgstate = MCCH_END; else inpinfo->mcch_pgstate = MCCH_MIDDLE; return True;}static intmcch_nextpage(gen_inp_conf_t *cf, inpinfo_t *inpinfo, gen_inp_iccf_t *iccf, char key){ int ret=0; switch (inpinfo->mcch_pgstate) { case MCCH_ONEPG: switch (key) { case ' ': if ((cf->mode & INP_MODE_AUTOUPCHAR)) ret = (mcch_choosech(cf, inpinfo, iccf, -1)) ? IMKEY_COMMIT : return_wrong(cf); else ret = return_correct(cf); break; case '<': case '>': ret = return_correct(cf); break; default: ret = return_wrong(cf); break; } break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?