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 + -
显示快捷键?