xim.c#1.53

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

53
1,365
字号
/*    Copyright (C) 1999 by  XCIN 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 <time.h>#include <X11/Xlocale.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/keysym.h>#include <langinfo.h>#include <iconv.h>#include "IMdkit.h"#include "Xi18n.h"#include "oximtool.h"#include "fkey.h"#include "oxim.h"static xccore_t *xccore;static struct {    unsigned int nlocale;    unsigned int nbytes;    char 	**locale;} xim_support_locales = {0, 0, NULL};XIMS ims;static int nencodings = 0;static int *im_enc = NULL;void gui_update_winlist(void);int ic_create(XIMS ims, IMChangeICStruct *call_data, xccore_t *xccore);int ic_destroy(int icid, xccore_t *xccore);int ic_clean_all(CARD16 connect_id, xccore_t *xccore);void ic_get_values(IC *ic, IMChangeICStruct *call_data, xccore_t *xccore);void ic_set_values(IC *ic, IMChangeICStruct *call_data, xccore_t *xccore);//void check_ic_exist(int icid, xccore_t *xccore);void xim_set_trigger_keys(void);char *xim_fix_big5_bug(Display *display, char *s){    XTextProperty tp;#if 0    XmbTextListToTextProperty(display, &s, 1, XCompoundTextStyle, &tp);#else    char *codeset = nl_langinfo(CODESET);    /* X Bug ! utf8 的 "裏、碁" 無法用 Xutf8TextListToTextProperty 轉出 Big5 */    if (strcasecmp(codeset, "BIG5") == 0)    {	size_t inbytesleft  = strlen(s);	size_t outbytesleft = inbytesleft;	char *ret_string = (char *)oxim_malloc(inbytesleft+1, True);	char *inptr = s;	char *outptr = ret_string;	iconv_t cd;	cd = iconv_open("BIG5", "UTF-8");	iconv(cd, (char **)&inptr, &inbytesleft, &outptr, &outbytesleft);	iconv_close(cd);	XmbTextListToTextProperty(display, &ret_string, 1, XCompoundTextStyle, &tp);	free(ret_string);    }    else    {	Xutf8TextListToTextProperty(display, &s, 1, XCompoundTextStyle, &tp);    }#endif    return (char *)tp.value;}voidxim_preeditcallback_done(IC *ic){    IMPreeditCBStruct data;    XIMText text;    XIMFeedback feedback[256] = {0};    if (ic->preedit_length)    {	data.major_code = XIM_PREEDIT_DRAW;	data.connect_id = ic->connect_id;	data.icid = ic->id;	data.todo.draw.caret = XIMIsInvisible;	data.todo.draw.chg_first = 0;	data.todo.draw.chg_length = ic->preedit_length;	data.todo.draw.text = &text;	text.encoding_is_wchar = False;	text.feedback = feedback;	text.length = 0;	text.string.multi_byte = "";	feedback[0] = 0;	IMCallCallback(ims, (XPointer)&data);    }    data.major_code = XIM_PREEDIT_DONE;    data.connect_id = ic->connect_id;    data.icid       = ic->id;    IMCallCallback (ims, (XPointer)&data);    ic->preedit_length = 0;}void xim_update_winlist(void){    gui_update_winlist();}/*----------------------------------------------------------------------------	XIM Tool Functions.----------------------------------------------------------------------------*/static void load_support_locales(void){    unsigned int flen = strlen(oxim_sys_rcdir()) + strlen(OXIM_DEFAULT_LOCALE_LIST) + 2;    char *locale_list = oxim_malloc(flen, False);    char *locale = oxim_malloc(128, False);    sprintf(locale_list, "%s/%s", oxim_sys_rcdir(), OXIM_DEFAULT_LOCALE_LIST);    if (oxim_check_file_exist(locale_list, FTYPE_FILE))    {	gzFile *fp = oxim_open_file(locale_list, "r", OXIMMSG_WARNING);        if (fp)	{	    while (oxim_get_line(locale, 128, fp, NULL, "#\n"))	    {		if (xim_support_locales.nlocale == 0)		{		    xim_support_locales.locale = (char **)malloc(sizeof(char *));		}		else		{		    xim_support_locales.locale = (char **)realloc(xim_support_locales.locale, (xim_support_locales.nlocale+1) * sizeof(char *));		}		xim_support_locales.nbytes += strlen(locale);    		xim_support_locales.locale[xim_support_locales.nlocale++] = strdup(locale);	    }	}	gzclose(fp);    }    else    {	oxim_perr(OXIMMSG_ERROR, N_("File: '%s' Not exist.\n"), locale_list);    }    free(locale);    free(locale_list);}struct commit_buf_s {    int slen, size;    char *str;} commit_buf;static voidxim_commit(IC *ic){    char *cch_str_list[1];    char *value;    IMCommitStruct call_data;    if (commit_buf.slen == 0)	return;    DebugLog(1, ("commit str (%u,%u): %s\n",		ic->id, ic->connect_id, commit_buf.str));    char *outstring = NULL;    char *charset = nl_langinfo(CODESET);    if (!strcasecmp(charset, "UTF-8"))    {	if (ic->imc->inp_state & IM_OUTSIMP)	{	    outstring = oxim_output_filter(commit_buf.str, True);	}	else if (ic->imc->inp_state & IM_OUTTRAD)	{	    outstring = oxim_output_filter(commit_buf.str, False);	}    }    value = xim_fix_big5_bug(xccore->display, (outstring ? outstring : commit_buf.str));    bzero(&call_data, sizeof(call_data));    call_data.major_code = XIM_COMMIT;    call_data.icid = ic->id;    call_data.connect_id = ic->connect_id;    call_data.flag = XimLookupChars;    call_data.commit_string = value;    IMCommitString(ims, (XPointer)(&call_data));    XFree(value);    commit_buf.slen = 0;    if (outstring)    {	free(outstring);    }}void xim_commit_string(IC *ic, char *str){    int cch_len;    if (ic->ic_rec.input_style & XIMPreeditCallbacks)    {	xim_preeditcallback_done(ic);    }    if (!str)    {	str = ic->imc->cch;	cch_len = strlen(str);    }    else    {        cch_len = strlen(str);        if (ic->imc->cch_size < cch_len+1)	{	    ic->imc->cch_size = cch_len+1;	    ic->imc->cch = oxim_realloc(ic->imc->cch, ic->imc->cch_size);        }        strcpy(ic->imc->cch, str);    }#if 1    if (commit_buf.size-commit_buf.slen < cch_len+1)    {	commit_buf.size = commit_buf.slen+cch_len+1;	commit_buf.str = oxim_realloc(commit_buf.str, commit_buf.size);    }    strcpy(commit_buf.str+commit_buf.slen, str);    commit_buf.slen += cch_len;    xim_commit(ic);#else    // 將字串拆成單一字元送出,避免某些 client 端 buffer 不夠(如 wine)    char *p = str;    unsigned int ucs4;#endif}intxim_connect(IC *ic){    IMPreeditStateStruct call_data;    if ((ic->ic_state & IC_CONNECT))	return True;    call_data.major_code = XIM_PREEDIT_START;    call_data.minor_code = 0;    call_data.connect_id = (CARD16)(ic->connect_id);    call_data.icid = (CARD16)(ic->id);    ic->ic_state |= IC_CONNECT;    return IMPreeditStart(ims, (XPointer)&call_data);}intxim_disconnect(IC *ic){    IMTriggerNotifyStruct call_data;    if (! (ic->ic_state & IC_CONNECT))	return True;    if (ic->ic_rec.input_style & XIMPreeditCallbacks)        xim_preeditcallback_done(ic);    call_data.connect_id = (CARD16)(ic->connect_id);    call_data.icid = (CARD16)(ic->id);    ic->ic_state &= ~IC_CONNECT;    return IMPreeditEnd(ims, (XPointer)(&call_data));}static intprocess_IMKEY(IC *ic, keyinfo_t *keyinfo, unsigned int ret){    char *cch = NULL;    IM_Context_t *imc = ic->imc;    if (ret == 0) {	/* This is IMKEY_ABSORB */	return True;    }    if ((ret & IMKEY_COMMIT) && imc->inpinfo.cch)    {	/* Send the result to IM lib. */	xim_commit_string(ic, imc->inpinfo.cch);    }    if (keyinfo)    {	if (!cch)	{	    if ((ret & IMKEY_SHIFTESC))	    {		if ((imc->inp_state & IM_2BYTES))		{		    cch = fullchar_ascii(&(imc->inpinfo), 1, keyinfo);		}		else		{		    cch = halfchar_ascii(&(imc->inpinfo), 1, keyinfo);		}		if (!cch)		{		    ret |= IMKEY_IGNORE;		}	    }	    if ((ret & IMKEY_FALLBACKPHR))	    {		ret |= IMKEY_IGNORE;	    }	}	if (cch)	{	    xim_commit_string(ic, cch);	    ret &= ~IMKEY_IGNORE;	}    }    if (! (ret & IMKEY_IGNORE))    {	/* The key will not be processed further more, and will not be	   forewared back to XIM client. */	return True;    }    return False;}/*----------------------------------------------------------------------------	IM Context Handlers.----------------------------------------------------------------------------*/voidcall_xim_init(IC *ic, int reset){    IM_Context_t *imc = ic->imc;    if (imc->imodp && ! (imc->inp_state & IM_CINPUT))    {	if (reset)	{	    imc->imodp->xim_init(imc->imodp->conf, &(imc->inpinfo));	}    }    imc->inp_state |= (IM_CINPUT | IM_XIMFOCUS);}voidcall_xim_end(IC *ic, int ic_delete, int clear){    unsigned int ret, i;    IM_Context_t *imc = ic->imc;    if (imc->imodp && (imc->inp_state & IM_CINPUT))    {	if (clear)	{	    ret = imc->imodp->xim_end(imc->imodp->conf, &(imc->inpinfo));	    if (! ic_delete && ret)		process_IMKEY(ic, NULL, ret);	}    }    if (! ic_delete)    {	imc->inp_state &= ~(IM_CINPUT | IM_XIMFOCUS);    }}intchange_IM(IC *ic, int inp_num){    static int first_call;    imodule_t *imodp=NULL;    int reset_inpinfo, nextim_english=0;    IM_Context_t *imc = ic->imc;/* *  Check if the module of the desired IM has been loaded or not. */    if (inp_num < 0 || inp_num >= oxim_get_NumberOfIM())	nextim_english = 1;    else if (! (imodp = OXIM_IMGet(inp_num)))	return False;    if (first_call == 0) {	/* in order to let xim_init() take effect */	reset_inpinfo = 1;	first_call = 1;    }    else if ((xccore->oxim_mode & OXIM_SINGLE_IMC) &&	     ((int)(imc->inp_num) == inp_num || nextim_english)) {	/* switch to / from English IM && do not change IM */	reset_inpinfo = 0;    }    else	reset_inpinfo = 1;/* *  The switch_out() xim_end() will only be called when really change IM. */    if (imc->imodp && imodp != imc->imodp)    {	call_xim_end(ic, 0, reset_inpinfo);    }     if (nextim_english) {    /* This will switch to English mode. */	imc->imodp = NULL;        if ((xccore->oxim_mode & OXIM_IM_FOCUS))	    xccore->oxim_mode &= ~(OXIM_RUN_IM_FOCUS);	return True;    }/* *  Initialize the new IM for this IC. */    imc->imodp = imodp;    imc->inp_num = inp_num;    if ((xccore->oxim_mode & OXIM_IM_FOCUS))    {	xccore->oxim_mode |= OXIM_RUN_IM_FOCUS;	xccore->im_focus = imc->inp_num;    }    call_xim_init(ic, reset_inpinfo);    if ((xccore->oxim_mode & OXIM_SHOW_CINPUT)) {	imc->s_imodp = imc->imodp;	imc->sinp_num = imc->inp_num;    }    else {

⌨️ 快捷键说明

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