gen-inp.c
来自「linux 下的 oxim 输入法,简单易用.」· C语言 代码 · 共 1,468 行 · 第 1/3 页
C
1,468 行
/* Copyright (C) 2006 by OXIM TEAM This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/ #ifdef HAVE_CONFIG_H# include "config.h"#endif#include <string.h>#include <X11/Xlib.h>#include <X11/keysym.h>#include "oximtool.h"#include "module.h"#include "gen-inp.h"static char *bopomofo[] = {"ㄅㄆㄇㄈㄉㄊㄋㄌㄍㄎㄏㄐㄑㄒㄓㄔㄕㄖㄗㄘㄙ", /* 聲母 */ "ㄧㄨㄩ", "ㄚㄛㄜㄝㄞㄟㄠㄡㄢㄣㄤㄥㄦ" /* 韻母 */};static int fillpage(gen_inp_conf_t *cf, inpinfo_t *inpinfo, gen_inp_iccf_t *iccf, byte_t dir);/*---------------------------------------------------------------------------- gen_inp_init()----------------------------------------------------------------------------*/static intloadtab(gen_inp_conf_t *cf){ int n, nn, ret=1; char modID[MODULE_ID_SIZE]; int size; size = sizeof(char) * MODULE_ID_SIZE; cf->word_start_pos = size; if (gzread(cf->zfp , modID, size) != size || strcmp(modID, "gencin")) { oxim_perr(OXIMMSG_WARNING, N_("gen_inp: %s: invalid tab file.\n"),cf->tabfn); return False; } size = sizeof(cintab_head_t); cf->word_start_pos += size; if (gzread(cf->zfp, &(cf->header), size) != size) { oxim_perr(OXIMMSG_WARNING, N_("gen_inp: %s: reading error.\n"), cf->tabfn); return False; } if (strcmp(GENCIN_VERSION, cf->header.version) > 0) { oxim_perr(OXIMMSG_WARNING, N_("gen_inp: %s: invalid version.\n"), cf->tabfn); return False; } n = nn = cf->header.n_icode; cf->ic1 = oxim_malloc(sizeof(icode_t) * n, 0); cf->ichar = oxim_malloc(sizeof(ichar_t) * nn, 0); int n_size = sizeof(icode_t) * n; cf->word_start_pos += n_size; int nn_size = sizeof(ichar_t) * nn; cf->word_start_pos += nn_size; if (!n || !nn || gzread(cf->zfp, cf->ic1, n_size) != n_size || gzread(cf->zfp, cf->ichar, nn_size) != nn_size ) { if (n) { free(cf->ic1); cf->ic1 = NULL; } if (nn) { free(cf->ichar); cf->ichar = NULL; } ret = False; } if (ret && cf->header.icode_mode == ICODE_MODE2) { cf->word_start_pos += n_size; cf->ic2 = oxim_malloc(n_size, 0); if (gzread(cf->zfp, cf->ic2, n_size) != n_size) { if (n) { free(cf->ic2); cf->ic2 = NULL; } ret = False; } } if (! ret) { oxim_perr(OXIMMSG_WARNING, N_("gen_inp: %s: reading error.\n"), cf->tabfn); return False; } else return True;}static voidgen_inp_resource(gen_inp_conf_t *cf, char *objname){ settings_t *im_settings = oxim_get_im_settings(objname); if (!im_settings) { printf("Null setting: %s !\n", objname); return; } int boolean; if (oxim_setting_GetBoolean(im_settings, "AutoCompose", &boolean)) oxim_setflag(&cf->mode, INP_MODE_AUTOCOMPOSE, boolean); if (oxim_setting_GetBoolean(im_settings, "AutoUpChar", &boolean)) oxim_setflag(&cf->mode, INP_MODE_AUTOUPCHAR, boolean); if (oxim_setting_GetBoolean(im_settings, "AutoFullUp", &boolean)) oxim_setflag(&cf->mode, INP_MODE_AUTOFULLUP, boolean); if (oxim_setting_GetBoolean(im_settings, "SpaceAutoUp", &boolean)) oxim_setflag(&cf->mode, INP_MODE_SPACEAUTOUP, boolean); if (oxim_setting_GetBoolean(im_settings, "SelectKeyShift", &boolean)) oxim_setflag(&cf->mode, INP_MODE_SELKEYSHIFT, boolean); if (oxim_setting_GetBoolean(im_settings, "SpaceIgnore", &boolean)) oxim_setflag(&cf->mode, INP_MODE_SPACEIGNOR, boolean); if (oxim_setting_GetBoolean(im_settings, "SpaceReset", &boolean)) oxim_setflag(&cf->mode, INP_MODE_SPACERESET, boolean); if (oxim_setting_GetBoolean(im_settings, "AutoReset", &boolean)) oxim_setflag(&cf->mode, INP_MODE_AUTORESET, boolean); if (oxim_setting_GetBoolean(im_settings, "WildEnable", &boolean)) oxim_setflag(&cf->mode, INP_MODE_WILDON, boolean); if (oxim_setting_GetBoolean(im_settings, "EndKey", &boolean)) oxim_setflag(&cf->mode, INP_MODE_ENDKEY, boolean); char *string; if (oxim_setting_GetString(im_settings, "DisableSelectList", &string)) { if (cf->disable_sel_list) free(cf->disable_sel_list); if (strcasecmp("NONE", string) == 0) cf->disable_sel_list = NULL; else cf->disable_sel_list = strdup(string); } oxim_settings_destroy(im_settings);}static intgen_inp_init(void *conf, char *objname){ gen_inp_conf_t *cf = (gen_inp_conf_t *)conf, cfd; char *s, value[128], truefn[256]; char *sub_path = "tables"; int ret; bzero(&cfd, sizeof(gen_inp_conf_t)); cfd.mode = DEFAULT_INP_MODE; cf->modesc = 0; gen_inp_resource(&cfd, objname);/* * Resource setup. */ if ((cfd.mode & INP_MODE_AUTOCOMPOSE)) cf->mode |= INP_MODE_AUTOCOMPOSE; if ((cfd.mode & INP_MODE_AUTOUPCHAR)) { cf->mode |= INP_MODE_AUTOUPCHAR; if ((cfd.mode & INP_MODE_SPACEAUTOUP)) cf->mode |= INP_MODE_SPACEAUTOUP; if ((cfd.mode & INP_MODE_SELKEYSHIFT)) cf->mode |= INP_MODE_SELKEYSHIFT; } if ((cfd.mode & INP_MODE_AUTOFULLUP)) { cf->mode |= INP_MODE_AUTOFULLUP; if ((cfd.mode & INP_MODE_SPACEIGNOR)) cf->mode |= INP_MODE_SPACEIGNOR; } if ((cfd.mode & INP_MODE_AUTORESET)) cf->mode |= INP_MODE_AUTORESET; else if ((cfd.mode & INP_MODE_SPACERESET)) cf->mode |= INP_MODE_SPACERESET; if ((cfd.mode & INP_MODE_WILDON)) cf->mode |= INP_MODE_WILDON; cf->modesc = cfd.modesc; cf->disable_sel_list = cfd.disable_sel_list;/* * Read the IM tab file. */ sprintf(value, "%s.tab", objname); if (oxim_check_datafile(value, sub_path, truefn, 256) == True) { cf->tabfn = (char *)strdup(truefn); if ((cf->zfp = gzopen(truefn, "rb")) == NULL) return False; ret = loadtab(cf); if (!ret) { gzclose(cf->zfp); cf->zfp = NULL; } } else return False; if (cf->header.n_endkey) { if ((cfd.mode & INP_MODE_ENDKEY)) cf->mode |= INP_MODE_ENDKEY; } return ret;}/*---------------------------------------------------------------------------- gen_inp_xim_init()----------------------------------------------------------------------------*/static intgen_inp_xim_init(void *conf, inpinfo_t *inpinfo){ gen_inp_conf_t *cf = (gen_inp_conf_t *)conf; gen_inp_iccf_t *iccf; int i; inpinfo->iccf = oxim_malloc(sizeof(gen_inp_iccf_t), True); iccf = (gen_inp_iccf_t *)inpinfo->iccf; inpinfo->etymon_list = cf->header.keyname; inpinfo->guimode = 0; inpinfo->keystroke_len = 0; inpinfo->s_keystroke = oxim_malloc((INP_CODE_LENGTH+1)*sizeof(uch_t), True); inpinfo->suggest_skeystroke = oxim_malloc((INP_CODE_LENGTH+1)*sizeof(uch_t), True); if (! (cf->mode & INP_MODE_SELKEYSHIFT)) { inpinfo->n_selkey = cf->header.n_selkey; inpinfo->s_selkey = oxim_malloc(inpinfo->n_selkey*sizeof(uch_t), True); for (i=0; i<SELECT_KEY_LENGTH && i<cf->header.n_selkey; i++) inpinfo->s_selkey[i].s[0] = cf->header.selkey[i]; } else { inpinfo->n_selkey = cf->header.n_selkey+1; inpinfo->s_selkey = oxim_malloc(inpinfo->n_selkey*sizeof(uch_t), True); for (i=0; i<SELECT_KEY_LENGTH && i<cf->header.n_selkey; i++) inpinfo->s_selkey[i+1].s[0] = cf->header.selkey[i]; } inpinfo->n_mcch = 0; i = inpinfo->n_selkey; inpinfo->mcch = NULL; inpinfo->mcch_grouping = oxim_malloc((i+1) * sizeof(uint_t), True); inpinfo->mcch_pgstate = MCCH_ONEPG; inpinfo->n_lcch = 0; inpinfo->lcch = NULL; inpinfo->lcch_grouping = NULL; inpinfo->cch_publish.uch = 0; return True;}static unsigned intgen_inp_xim_end(void *conf, inpinfo_t *inpinfo){ gen_inp_iccf_t *iccf = (gen_inp_iccf_t *)inpinfo->iccf; if (iccf->n_mcch_list) { free(iccf->mcch_list); free(iccf->mcch_list_grouping); } if (iccf->n_mkey_list) free(iccf->mkey_list); free(inpinfo->iccf); free(inpinfo->s_keystroke); free(inpinfo->suggest_skeystroke); free(inpinfo->s_selkey); free(inpinfo->mcch_grouping); inpinfo->iccf = NULL; inpinfo->s_keystroke = NULL; inpinfo->suggest_skeystroke = NULL; inpinfo->s_selkey = NULL; inpinfo->mcch = NULL; inpinfo->mcch_grouping = NULL; return IMKEY_ABSORB;}/*---------------------------------------------------------------------------- gen_inp_keystroke()----------------------------------------------------------------------------*/static unsigned intreturn_wrong(gen_inp_conf_t *cf){ return IMKEY_ABSORB;}static unsigned intreturn_correct(gen_inp_conf_t *cf){ return IMKEY_ABSORB;}static voidreset_keystroke(inpinfo_t *inpinfo, gen_inp_iccf_t *iccf){ inpinfo->s_keystroke[0].uch = 0; inpinfo->keystroke_len = 0; inpinfo->n_mcch = 0; iccf->keystroke[0] = '\0'; iccf->mode = 0; inpinfo->mcch_pgstate = MCCH_ONEPG; if (iccf->n_mcch_list) { free(iccf->mcch_list); free(iccf->mcch_list_grouping); iccf->n_mcch_list = 0; } if (iccf->n_mkey_list) { free(iccf->mkey_list); iccf->n_mkey_list = 0; }}/*------------------------------------------------------------------------*/static intcmp_icvalue(icode_t *ic1, icode_t *ic2, unsigned int idx, icode_t icode1, icode_t icode2, int mode){ if (ic1[idx] > icode1) return 1; else if (ic1[idx] < icode1) return -1; else { if (! mode) return 0; else if (ic2[idx] > icode2) return 1; else if (ic2[idx] < icode2) return -1; else return 0; }}static int bsearch_char(icode_t *ic1, icode_t *ic2, icode_t icode1, icode_t icode2, int size, int mode, int wild, int *end_idx){ int head, middle, end, ret; head = 0; middle = size / 2; end = size; while ((ret=cmp_icvalue(ic1, ic2, middle, icode1, icode2, mode))) { if (ret > 0) end = middle; else head = middle + 1; middle = (end + head) / 2; if (middle == head && middle == end) break; } if (ret == 0) { int last_idx = middle; /* 找該組字的一筆索引 */ while(middle > 0 && ! cmp_icvalue(ic1, ic2, middle-1, icode1, icode2, mode)) { middle --; } /* 找最後一筆索引 */ if (end_idx) { while(last_idx > 0 && ! cmp_icvalue(ic1, ic2, last_idx+1, icode1, icode2, mode)) { last_idx++; } *end_idx = last_idx; } return middle; } else return (wild) ? middle : -1;}/*---------------------------------------------------------------------找詞---------------------------------------------------------------------*/static char *get_word(gen_inp_conf_t *cf, unsigned int ichar, unsigned int *ret_len){ unsigned int offset = ichar & ~WORD_MASK; if (gzseek(cf->zfp, cf->word_start_pos + offset, SEEK_SET) >= 0) { unsigned short word_len = 0; if (gzread(cf->zfp, &word_len, sizeof(unsigned short)) >= 0) { char *word = oxim_malloc(word_len + 1, True); if (gzread(cf->zfp, word, word_len) == word_len) { *ret_len = word_len; return word; } free(word); } } *ret_len = 0; return NULL;}static intpick_cch_wild(gen_inp_conf_t *cf, gen_inp_iccf_t *iccf, int *head, byte_t dir, inpinfo_t *inpinfo, unsigned int *n_mcch){ unsigned int i, size, klist[2]; int n_klist, ks_size, r=0, idx, n_igrp=0; char *ks; unsigned int start = *head; unsigned int mcch_size = inpinfo->n_selkey; int have_word = False; size = cf->header.n_icode; ks_size = cf->header.n_max_keystroke + 1; ks = oxim_malloc(ks_size, 0); n_klist = (cf->header.icode_mode == ICODE_MODE1) ? 1 : 2; dir = (dir > 0) ? (byte_t)1 : (byte_t)-1; if (iccf->n_mkey_list) { free(iccf->mkey_list); } iccf->mkey_list = oxim_malloc(mcch_size*sizeof(int), False); if (iccf->n_mcch_list) { free(iccf->mcch_list); free(iccf->mcch_list_grouping); } iccf->mcch_list = oxim_malloc(mcch_size*sizeof(uch_t), False); iccf->mcch_list_grouping = oxim_malloc(mcch_size*sizeof(word_group_t), False); for (i=0, idx = *head; idx>=0 && idx<size && i<=mcch_size; idx+=dir) { klist[0] = cf->ic1[idx]; if (cf->header.icode_mode == ICODE_MODE2) klist[1] = cf->ic2[idx]; oxim_codes2keys(klist, n_klist, ks, ks_size); if (strcmp_wild(iccf->keystroke, ks) == 0) { if (i < mcch_size) { iccf->mcch_list_grouping[n_igrp].n_idx = i; if (cf->ichar[idx] & WORD_MASK)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?