gen-inp-v1.c

来自「linux 下的 oxim 输入法,简单易用.」· C语言 代码 · 共 1,570 行 · 第 1/3 页

C
1,570
字号
/*    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-v1.h"static char *bopomofo[] = {"ㄅㄆㄇㄈㄉㄊㄋㄌㄍㄎㄏㄐㄑㄒㄓㄔㄕㄖㄗㄘㄙ", /* 聲母 */		      "ㄧㄨㄩ",		      "ㄚㄛㄜㄝㄞㄟㄠㄡㄢㄣㄤㄥㄦ" /* 韻母 */};static int fillpage(gen_inp_conf_t *cf, inpinfo_t *inpinfo, gen_inp_iccf_t *iccf, byte_t dir);static void gen_inp_resource(gen_inp_conf_t *cf, settings_t *im_settings);/*----------------------------------------------------------------------------        gen_inp_init()----------------------------------------------------------------------------*/static intloadtab(gen_inp_conf_t *cf, char *objname){    table_prefix_t tp;    unsigned int size = MODULE_ID_SIZE;    cf->memory_usage = sizeof(gen_inp_conf_t);    if (gzread(cf->zfp , &tp, size) != size || strcmp(tp.prefix, "gencin") || tp.version != 1)    {	oxim_perr(OXIMMSG_WARNING, N_("gen_inp: %s: invalid tab file.\n"),cf->tabfn);	return False;    }    size = sizeof(cintab_head_v1_t);    cf->memory_usage += size;    if (gzread(cf->zfp, &(cf->header), size) != size)    {	oxim_perr(OXIMMSG_WARNING, N_("gen_inp: %s: reading error.\n"), cf->tabfn);	return False;    }    unsigned int checksum = crc32(0L, (char *)&cf->header, sizeof(cintab_head_v1_t) - sizeof(unsigned int));    if (cf->header.chksum != checksum)    {	oxim_perr(OXIMMSG_WARNING, N_("gen_inp: %s: checksum error.\n"), cf->tabfn);	return False;    }    settings_t *im_settings;    /* 讀取輸入法表格預設的定義 */    im_settings = oxim_get_default_settings(objname, True);    if (im_settings)    {	gen_inp_resource(cf, im_settings);	oxim_settings_destroy(im_settings);    }    /* 讀取使用者的定義 */    im_settings = oxim_get_im_settings(objname);    if (im_settings)    {	gen_inp_resource(cf, im_settings);	oxim_settings_destroy(im_settings);    }    return True;}static voidsetup_kremap(gen_inp_conf_t *cf, char *value){    int i=0;    unsigned int num;    char *s = value, *sp;    while (*s)    {        if (*s == ';')	{            i++;	}        s++;    }    if (!i) return;    cf->n_kremap = i;    cf->kremap = oxim_malloc(sizeof(kremap_t) * i, True);    s = sp = value;    for (i=0; i<cf->n_kremap; i++)    {        while (*s != ':')	{            s++;	}        *s = '\0';        cf->kremap[i].keystroke = strdup(sp);        s++;        sp = s;        while (*s != ';')            s++;        *s = '\0';        strncpy((char *)cf->kremap[i].uch.s, sp, UCH_SIZE);        s++;        sp = s;    }}static voidgen_inp_resource(gen_inp_conf_t *cf, settings_t *im_settings){    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);    /* 使用注音符號字根排列規則 */    if (oxim_setting_GetBoolean(im_settings, "BoPoMoFoCheck", &boolean))	oxim_setflag(&cf->mode, INP_MODE_BOPOMOFOCHK, boolean);    char *string;    bzero(cf->disable_sel_list, N_KEYS);    if (oxim_setting_GetString(im_settings, "DisableSelectList", &string))    {	if (strlen(string) && strcasecmp("NONE", string) != 0)	{	    strcpy(cf->disable_sel_list, string);	}    }    if (oxim_setting_GetString(im_settings, "Remap", &string))    {	if (cf->kremap)	{	    int i;	    for (i=0; i < cf->n_kremap; i++)	    {		free(cf->kremap[i].keystroke);	    }	    free(cf->kremap);	    cf->n_kremap = 0;	    cf->kremap = NULL;	}	if (strlen(string) && strcasecmp(string, "NONE") != 0)	{	    setup_kremap(cf, string);	}    }    /* 有結束鍵設定,就自動設定按結束鍵自動上字 */    if (cf->header.n_end_key)    {	cf->mode |= INP_MODE_ENDKEY;    }}static int gen_inp_init(void *conf, char *objname){    gen_inp_conf_t *cf = (gen_inp_conf_t *)conf;    char *s, value[128], truefn[256];    unsigned int size;/* *  Read the IM tab file. */    sprintf(value, "%s.tab", objname);    if (oxim_check_datafile(value, "tables", truefn, 256) == True)    {	if ((cf->zfp = gzopen(truefn, "rb")) == NULL)	{	    return False;	}	cf->tabfn = (char *)strdup(truefn);	if (!loadtab(cf, objname))	{	    free(cf->tabfn);	    gzclose(cf->zfp);	    cf->zfp = NULL;	    return False;	}	/* 決定檔案讀取模式 */	/* 使用基本的檔案操作函數判斷此檔是否為未壓縮格式 */	table_prefix_t tp;	FILE *fp;	/* 不必判斷 fopen 是否成功!因為 gzopen 若通過,fopen() 沒有理由不行 */	fp = fopen(truefn, "rb");	fread(&tp, 1, MODULE_ID_SIZE, fp);	fclose(fp);	cf->direct_mode = (memcmp(tp.prefix, "gencin", 6) == 0) ? True : False;    }    else    {	return False;    }    /*------------------------------------------------------       如果是壓縮型態的輸入法參考檔,就把 offset table 與 input content       統統讀進記憶體。      ------------------------------------------------------*/    if (!cf->direct_mode)    {	if (gzseek(cf->zfp, cf->header.offset_table_offset, SEEK_SET) < 0)	{	    return False;	}	size = (cf->header.n_input_content+1) * sizeof(unsigned int);	cf->offset_tbl = oxim_malloc(size, False);	if (gzread(cf->zfp, cf->offset_tbl, size) != size)	{	    free(cf->offset_tbl);	    oxim_perr(OXIMMSG_WARNING, N_("gen_inp: %s: reading offset table error.\n"), cf->tabfn);	    return False;	}	cf->offset_size = size;	cf->memory_usage += size;	/* 把輸入資料也讀進記憶體 */	if (gzseek(cf->zfp, cf->header.input_content_offset, SEEK_SET) < 0)	{	    free(cf->offset_tbl);	    cf->offset_tbl = NULL;	    return False;	}	size = cf->offset_tbl[cf->header.n_input_content] - cf->offset_tbl[0];	cf->input_content = oxim_malloc(size, False);	if(gzread(cf->zfp, cf->input_content, size) != size)	{	    free(cf->offset_tbl);	    cf->offset_tbl = NULL;	    free(cf->input_content);	    cf->input_content = NULL;	    return False;	}	cf->input_content_size = size;	cf->memory_usage += size;    }    /*------------------------------------------------------*/    /* 產生給螢幕小鍵盤用的字根表 */    int i;    for (i = 0 ; i <  N_KEYS ; i++)    {	if (cf->header.keyname[i].uch)	{	    int idx = oxim_key2code(i);	    if (idx)	    {		cf->etymon_list[idx].uch = cf->header.keyname[i].uch;	    }	}    }    return True;}/*----------------------------------------------------------------------------        gen_inp_xim_init()----------------------------------------------------------------------------*/static intgen_inp_xim_init(void *conf, inpinfo_t *inpinfo){    gen_inp_conf_t *cf = (gen_inp_conf_t *)conf;    int i;    unsigned int size;    inpinfo->iccf = oxim_malloc(sizeof(gen_inp_iccf_t), True);    inpinfo->etymon_list = cf->etymon_list;    inpinfo->guimode = 0;    inpinfo->keystroke_len = 0;    inpinfo->s_keystroke = oxim_malloc((N_NAME_LENGTH)*sizeof(uch_t), True);    inpinfo->suggest_skeystroke = oxim_malloc((cf->header.n_max_keystroke+1)*sizeof(uch_t), True);    if (! (cf->mode & INP_MODE_SELKEYSHIFT))    {	inpinfo->n_selkey = cf->header.n_selection_key;	inpinfo->s_selkey = oxim_malloc(inpinfo->n_selkey*sizeof(uch_t), True);	for (i=0; i<SELECT_KEY_LENGTH && i<cf->header.n_selection_key; i++)	    inpinfo->s_selkey[i].s[0] = cf->header.selection_keys[i];    }    else    {	inpinfo->n_selkey = cf->header.n_selection_key+1;	inpinfo->s_selkey = oxim_malloc(inpinfo->n_selkey*sizeof(uch_t), True);	for (i=0; i<SELECT_KEY_LENGTH && i<cf->header.n_selection_key; i++)	    inpinfo->s_selkey[i+1].s[0] = cf->header.selection_keys[i];    }    i = inpinfo->n_selkey;    inpinfo->n_mcch = 0;    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_conf_t *cf = (gen_inp_conf_t *)conf;    gen_inp_iccf_t *iccf = (gen_inp_iccf_t *)inpinfo->iccf;    if (iccf->mkey_list)    {	free(iccf->mkey_list);	iccf->mkey_list = NULL;    }    free(inpinfo->iccf);    inpinfo->iccf = NULL;    if (inpinfo->mcch)    {	free(inpinfo->mcch);	inpinfo->mcch = NULL;    }    free(inpinfo->s_keystroke);    inpinfo->s_keystroke = NULL;    free(inpinfo->suggest_skeystroke);    inpinfo->suggest_skeystroke = NULL;    free(inpinfo->s_selkey);    inpinfo->s_selkey = NULL;    free(inpinfo->mcch_grouping);    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->mkey_list)    {	free(iccf->mkey_list);	iccf->mkey_list = NULL;    }}/*------------------------------------------------------------------------*/static void *get_input_content(gen_inp_conf_t *cf, unsigned int idx){    if (idx >= cf->header.n_input_content)    {	return NULL;    }    unsigned int offset, offset_len;    /* 完全使用磁碟 I/O */    if (cf->direct_mode)    {	unsigned int ofs[2];	/* 表格起始位置 + (索引值 x 4) */	unsigned int idx_offset = cf->header.offset_table_offset + (idx << 2);	unsigned int offsetsize = sizeof(unsigned int) << 1;	/* 移動讀取指標 */	if (gzseek(cf->zfp, idx_offset, SEEK_SET) < 0)	{	    return NULL;	}	/* 讀入輸入資料偏移位置 */	if (gzread(cf->zfp, &ofs, offsetsize) != offsetsize)	{	    return NULL;	}	offset = ofs[0];	offset_len = ofs[1] - offset;	if (gzseek(cf->zfp, offset, SEEK_SET) < 0)	{	    return NULL;	}    }    else /* Offset Table 已經讀入記憶體內 */    {	offset = cf->offset_tbl[idx] - cf->offset_tbl[0];	offset_len = cf->offset_tbl[idx+1] - offset - cf->offset_tbl[0];    }    /* 配置記憶體 */    /* 讀入真正的輸入資料 */    void *icr = oxim_malloc(offset_len, False);    if (cf->direct_mode)    {	if (gzread(cf->zfp, icr, offset_len) != offset_len)	{	    free(icr);	    icr = NULL;	}    }    else    {	memcpy(icr, cf->input_content+offset, offset_len);    }    return icr;}static intcmp_icvalue(gen_inp_conf_t *cf, char *keystroke, unsigned int idx, int wildcmp){    static char buf[256];    unsigned char keystroke_len = strlen(keystroke);    void *icr = get_input_content(cf, idx);    unsigned char key_len;    int cmp;    if (!icr)    {	return -1;    }    memcpy(&key_len, icr, 1);    strncpy(buf, icr+2, key_len);    buf[key_len] = '\0';    if (wildcmp)    {	cmp = strcmp_wild(keystroke, buf);    }    else    {	cmp = strcmp(buf, keystroke);    }    free(icr);    if (cmp > 0)	cmp = 1;    else if (cmp < 0)	cmp = -1;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?