gen-inp.c

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

C
1,468
字号
		{		    have_word = True;		    unsigned int ret_len;		    char *ret_word = get_word(cf, cf->ichar[idx], &ret_len);		    if (ret_word)		    {			unsigned int ucs4;			int nbytes;			char *p = ret_word;			unsigned int utf8_len = 0;			while (ret_len && (nbytes = oxim_utf8_to_ucs4(p, &ucs4, ret_len)) > 0)			{			    utf8_len ++;			    if (utf8_len > 1)			    {				mcch_size ++;				iccf->mcch_list = oxim_realloc(iccf->mcch_list, mcch_size*sizeof(uch_t));			    }				    iccf->mcch_list[i].uch = 0;			    memcpy((char *)iccf->mcch_list[i].s, p, nbytes);			    i ++;			    p += nbytes;			    ret_len -= nbytes;			}		    	iccf->mcch_list_grouping[n_igrp].n_word = utf8_len;			n_igrp ++;			free(ret_word);		    }		}		else if (ccode_to_char(cf->ichar[idx], (char *)iccf->mcch_list[i].s))		{		    iccf->mkey_list[n_igrp] = idx;		    iccf->mcch_list_grouping[n_igrp].n_word = 1;		    i ++;		    n_igrp ++;		}		*head = idx;	    }	    else	    {		r = 1;	    }	}    }    free(ks);    iccf->n_mkey_list = n_igrp;    iccf->n_mcch_list = n_igrp;    *n_mcch = i;    if (i)    {	inpinfo->n_mcch = n_igrp;	inpinfo->mcch = iccf->mcch_list;	for (i=0 ; i < n_igrp ; i++)	{	    inpinfo->mcch_grouping[i+1] = iccf->mcch_list_grouping[i].n_word;	}	inpinfo->mcch_grouping[0] = have_word ? n_igrp : 0;    }    else    {	inpinfo->n_mcch = 0;	inpinfo->mcch_grouping[0] = 0;	free(iccf->mcch_list);	free(iccf->mcch_list_grouping);	free(iccf->mkey_list);	*head = 0;    }    return r;}static intmatch_keystroke_wild(gen_inp_conf_t *cf, 		       inpinfo_t *inpinfo, gen_inp_iccf_t *iccf){    icode_t icode[2];    unsigned int md, n_mcch;    int idx;    char *s1, *s2, *s, tmpch;    md = (cf->header.icode_mode == ICODE_MODE2) ? 1 : 0;    icode[0] = icode[1] = 0;    /*     *  Search for the first char.     */    s1 = strchr(iccf->keystroke, '*');    s2 = strchr(iccf->keystroke, '?');    if (s1 && s2)	s = (s1 < s2) ? s1 : s2;    else if (s1)	s = s1;    else	s = s2;    tmpch = *s;    *s = '\0';    oxim_keys2codes(icode, 2, iccf->keystroke);    idx = bsearch_char(cf->ic1, cf->ic2, icode[0], icode[1], 			cf->header.n_icode, md, 1, NULL);    *s = tmpch;    iccf->mcch_hidx = idx;		/* refer to head index of cf->icidx */    /*     *  Pick up the remaining chars;     */    if (pick_cch_wild(cf, iccf, &idx, 1, inpinfo, &n_mcch) == 0)    {        inpinfo->mcch_pgstate = MCCH_ONEPG;    }    else     {	inpinfo->mcch_pgstate = MCCH_BEGIN;    }    iccf->mcch_eidx = idx;		/* refer to end index of cf->icidx */    return (n_mcch) ? 1 : 0;}static intmatch_keystroke_normal(gen_inp_conf_t *cf, 		       inpinfo_t *inpinfo, gen_inp_iccf_t *iccf){    icode_t icode[2];    unsigned int size, md, n_ich=0, n_igrp=0, mcch_size;    int idx, end_idx;    uch_t *mcch = NULL;    word_group_t *mcch_grouping = NULL;    size = cf->header.n_icode;    md = (cf->header.icode_mode == ICODE_MODE2) ? 1 : 0;    icode[0] = icode[1] = 0;    /*     *  Search for the first char.     */    oxim_keys2codes(icode, 2, iccf->keystroke);    if ((idx = bsearch_char(cf->ic1, cf->ic2, 		icode[0], icode[1], size, md, 0, &end_idx)) == -1)	return 0;    /*     *  Search for all the chars with the same keystroke.     */    mcch_size = end_idx - idx + 1; /* 總共幾筆紀錄 */    /* 預先配置記憶體 */    mcch = oxim_malloc(mcch_size*sizeof(uch_t), False);    mcch_grouping = oxim_malloc(mcch_size*sizeof(word_group_t), False);    while(idx <= end_idx)    {    	mcch_grouping[n_igrp].n_idx = n_ich;	if (cf->ichar[idx] & WORD_MASK)	{	    unsigned int ret_len;	    char *ret_word = get_word(cf, cf->ichar[idx], &ret_len);	    if (ret_word)	    {		unsigned int ucs4;		int nbytes;		char *p = ret_word;		unsigned int utf8_len = 0;		while (ret_len && (nbytes = oxim_utf8_to_ucs4(p, &ucs4, ret_len)) > 0)		{		    utf8_len ++;		    if (utf8_len > 1)		    {			mcch_size ++;			mcch = oxim_realloc(mcch, mcch_size*sizeof(uch_t));		    }			    mcch[n_ich].uch = 0;		    memcpy((char *)mcch[n_ich].s, p, nbytes);		    n_ich ++;		    p += nbytes;		    ret_len -= nbytes;		}	    	mcch_grouping[n_igrp].n_word = utf8_len;		n_igrp ++;		free(ret_word);	    }	}	else if (ccode_to_char(cf->ichar[idx], (char *)mcch[n_ich].s))	{	    mcch_grouping[n_igrp].n_word = 1;	    n_ich ++;	    n_igrp ++;	}        idx ++;    }    if (iccf->n_mcch_list)    {	free(iccf->mcch_list);	free(iccf->mcch_list_grouping);    }    iccf->mcch_list = mcch;    iccf->mcch_list_grouping = mcch_grouping;    iccf->n_mcch_list = n_igrp;    iccf->mcch_hidx = 0;	/* refer to index of iccf->mcch_list */    fillpage(cf, inpinfo, iccf, 0);    return 1;}static int match_keystroke(gen_inp_conf_t *cf, inpinfo_t *inpinfo, gen_inp_iccf_t *iccf)/* return: 1: success, 0: false */{    int ret;    inpinfo->n_mcch = 0;    if (! (iccf->mode & INPINFO_MODE_INWILD))	ret = match_keystroke_normal(cf, inpinfo, iccf);    else	ret = match_keystroke_wild(cf, inpinfo, iccf);    if (inpinfo->n_mcch > 1 && (iccf->mode & INPINFO_MODE_SPACE))	iccf->mode &= ~(INPINFO_MODE_SPACE);    return ret;}/*------------------------------------------------------------------------*/static voidget_correct_skeystroke(gen_inp_conf_t *cf,		inpinfo_t *inpinfo, gen_inp_iccf_t *iccf, int idx, uch_t *cch){    unsigned int i=0, j, klist[2];    int n_klist, ks_size, keycode;    char *ks;    if (idx < iccf->n_mkey_list)    {	i = iccf->mkey_list[idx];    }    else    {	inpinfo->suggest_skeystroke[0].uch = 0;	return;    }    ks_size = cf->header.n_max_keystroke + 1;    ks = oxim_malloc(ks_size, 0);    n_klist = (cf->header.icode_mode == ICODE_MODE1) ? 1 : 2;    klist[0] = cf->ic1[i];    if (cf->header.icode_mode == ICODE_MODE2)	klist[1] = cf->ic2[i];    oxim_codes2keys(klist, n_klist, ks, ks_size);    if (strcmp_wild(iccf->keystroke, ks) == 0)    {	for (j=0; ks[j] != '\0'; j++)	{	    keycode = oxim_key2code(ks[j]);	    inpinfo->suggest_skeystroke[j].uch =			cf->header.keyname[keycode].uch;	}	inpinfo->suggest_skeystroke[j].uch = 0;    }    else	inpinfo->suggest_skeystroke[0].uch = 0;    free(ks);}static voidcommit_char(gen_inp_conf_t *cf, inpinfo_t *inpinfo, gen_inp_iccf_t *iccf, int idx){    static char cch_s[1024];    char *s=NULL;    int i;    unsigned int grp_idx = (iccf->mode & INPINFO_MODE_INWILD) ? idx : iccf->mcch_hidx + idx;    word_group_t wg = iccf->mcch_list_grouping[grp_idx];    uch_t *mcch = iccf->mcch_list + wg.n_idx;    uch_t *cch = mcch;    ushort_t cch_len = wg.n_word;    cch_s[0] = '\0';    while (cch_len--)    {	strcat(cch_s, (char *)mcch->s);	mcch ++;    }    inpinfo->cch = cch_s;    /* 只有單一字元才需要提示字根 */    if (wg.n_word == 1)    {	if (! (s = strchr(iccf->keystroke,'*')) &&		! (s = strchr(iccf->keystroke,'?')))	{	    for (i=0; i<=inpinfo->keystroke_len; i++)	    inpinfo->suggest_skeystroke[i].uch = inpinfo->s_keystroke[i].uch;	}	else	{	    get_correct_skeystroke(cf, inpinfo, iccf, idx, cch);	}    }    else    {	inpinfo->suggest_skeystroke[0].uch = 0;    }    inpinfo->keystroke_len = 0;    inpinfo->s_keystroke[0].uch = 0;    inpinfo->n_mcch = 0;    inpinfo->cch_publish.uch = cch->uch;    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 (match_keystroke(cf, inpinfo, iccf))    {        if (inpinfo->n_mcch == 1)	{            commit_char(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_char(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){    int i, j, n_pg=inpinfo->n_selkey;    if (! (iccf->mode & INPINFO_MODE_INWILD))    {        int total = iccf->n_mcch_list;        switch (dir)	{        case 0:	    iccf->mcch_hidx = 0;	    break;        case 1:	    if (iccf->mcch_hidx + n_pg < total)	        iccf->mcch_hidx += n_pg;	    else	        return 0;	    break;        case -1:	    if (iccf->mcch_hidx - n_pg >= 0)	        iccf->mcch_hidx -= n_pg;	    else	        return 0;	    break;        }	/* */	uch_t *mcch = iccf->mcch_list + iccf->mcch_list_grouping[iccf->mcch_hidx].n_idx;	j = total - iccf->mcch_hidx;	i = (j >= n_pg) ? n_pg : j;	inpinfo->mcch_grouping[0] = 0;	for (j=0; j < i ; j++)	{	    inpinfo->mcch_grouping[j+1] = iccf->mcch_list_grouping[iccf->mcch_hidx+j].n_word;	    if (iccf->mcch_list_grouping[iccf->mcch_hidx+j].n_word > 1)	    {		inpinfo->mcch_grouping[0] = i;	    }	}	inpinfo->mcch = mcch;        if (iccf->mcch_hidx == 0)            inpinfo->mcch_pgstate = (i < total) ? MCCH_BEGIN : MCCH_ONEPG;        else if (total - iccf->mcch_hidx > n_pg)	    inpinfo->mcch_pgstate = MCCH_MIDDLE;        else	    inpinfo->mcch_pgstate = MCCH_END;        inpinfo->n_mcch = i;    }    else    {	int r=0, n_mcch, hidx, eidx;         switch (dir) {        case 0:	    return 0;        case 1:	    if (inpinfo->mcch_pgstate == MCCH_BEGIN ||	        inpinfo->mcch_pgstate == MCCH_MIDDLE) {		hidx = eidx = iccf->mcch_eidx + 1;        	r = pick_cch_wild(cf, iccf, &eidx, 1,			inpinfo, (unsigned int *)&n_mcch);	    }	    else		return 0;	    break;        case -1:	    if (inpinfo->mcch_pgstate == MCCH_END ||	        inpinfo->mcch_pgstate == MCCH_MIDDLE)	    {		hidx = eidx = iccf->mcch_hidx - 1;        	r = pick_cch_wild(cf, iccf, &hidx, -1,	        	inpinfo, (unsigned int *)&n_mcch);	    }	    else	    {		return 0;	    }	    break;        }        if (r == 0)	{	    if (dir == 1)                inpinfo->mcch_pgstate = MCCH_END;	    else                inpinfo->mcch_pgstate = MCCH_BEGIN;	}        else	{	    inpinfo->mcch_pgstate = MCCH_MIDDLE;	}	iccf->mcch_hidx = hidx;	iccf->mcch_eidx = eidx;    }

⌨️ 快捷键说明

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