xim.c#1.53

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

53
1,365 行
字号
		xccore->oxim_mode &= ~OXIM_RUN_2B_FOCUS;	    }	    else {		xccore->oxim_mode |= OXIM_IM_FOCUS;		if ((imc->inp_state & IM_CINPUT))		    xccore->oxim_mode |= OXIM_RUN_IM_FOCUS;		else		    xccore->oxim_mode |= OXIM_RUN_2B_FOCUS;		xccore->im_focus = imc->inp_num;	    }	    break;	case FKEY_QPHRASE:	    if ((str = oxim_qphrase_str(minor_code)))	    {                xim_commit_string(ic, str);	    }	    break;	case FKEY_XCINSW:	    gui_xcin_style_switch();	    break;	}	if (! (imc->inp_state & IM_CINPUT) && ! (imc->inp_state & IM_2BYTES) && !(imc->inp_state & IM_OUTSIMP) && !(imc->inp_state & IM_OUTTRAD))	    return 0;	return 1;    }/* *  Forward key to the IM module. */    if ((imc->inp_state & IM_CINPUT)) {	imc->inpinfo.zh_ascii = ((imc->inp_state & IM_2BYTES)) ?		(ubyte_t)1 : (ubyte_t)0;        ret = imc->imodp->keystroke(imc->imodp->conf,&(imc->inpinfo), keyinfo);	if (process_IMKEY(ic, keyinfo, ret) == True)	    return 1;    }    if ((imc->inp_state & IM_2BYTES)) {	char *cch;	if ((keyinfo->keystate & Mod1Mask) != Mod1Mask &&	    (keyinfo->keystate & ControlMask) != ControlMask &&            (cch = fullchar_keystroke(&(imc->inpinfo), keyinfo->keysym))) {	    xim_commit_string(ic, cch);	    return 1;	}    }    /*     * 變態設計 :-P     *     * Forward 程序執行到這裡,表示這個按鍵沒有被處理,準備轉送出去,     * 但因為有些別的程序不知為何,又把這個按鍵 forward 回來(如 gedit),     * 形成互相 forward,無止無盡 :-(     *     * 只好在這裡加以處理,作法是檢視上一次 forward 與這一次的時間差     * 精度為百萬分之一秒(沒有人可以打字那麼快吧!),如果在一定的時間     * 之內(1% 秒),就視為重複 forward,此時就吃掉這個按鍵,不再 forward。     */    static float last_time = 0;    if (keyinfo->keystr_len == 0)    {	struct timeval tp;	float now_time, time_use;	if (gettimeofday(&tp, NULL) == 0)	{	    now_time = (1000000 * tp.tv_sec) + tp.tv_usec;	    time_use = now_time - last_time;	    last_time = now_time;	    if (time_use < 3000) /* 0.3% 秒 */	    {		return 1;	    }	}    }    return -1;}static intxim_forward_handler(XIMS ims, IMForwardEventStruct *call_data, int *icid){    IC *ic=NULL;    int ret;    XKeyEvent *kev;    keyinfo_t keyinfo;    *icid = call_data->icid;    DebugLog(2, ("XIM_FORWARD_EVENT: icid=%d\n", *icid));    if ((xccore->oxim_mode & OXIM_RUN_EXIT))    {	return True;    }    if (! (ic = ic_find(call_data->icid)))    {	return False;    }    kev = &call_data->event.xkey;    keyinfo.keytype = kev->type;    keyinfo.keystate = kev->state;    keyinfo.keystr_len = XLookupString(kev, keyinfo.keystr, 16, 				&(keyinfo.keysym), NULL);    keyinfo.keystr[(keyinfo.keystr_len >= 0) ? keyinfo.keystr_len : 0] = 0;    //printf("Keysym=%x\n", keyinfo.keysym);    if (keyinfo.keytype != KeyPress)    {	return True;    }    ret = forward_keys_handler(ic, &keyinfo);    if (ret == 0)    {	xim_disconnect(ic);    }    else if (ret == -1)    {	IMForwardEvent(ims, (XPointer)call_data);    }    return True;}static intxim_set_ic_values_handler(XIMS ims, IMChangeICStruct *call_data, int *icid){    IC *ic;    *icid = call_data->icid;    DebugLog(2, ("XIM_SET_IC_VALUES: icid=%d\n", *icid));    if ((xccore->oxim_mode & OXIM_RUN_EXIT))	return True;    if (! (ic = ic_find(call_data->icid)))	return False;    ic_set_values(ic, call_data, xccore);    return True;}static intxim_get_ic_values_handler(XIMS ims, IMChangeICStruct *call_data, int *icid){    IC *ic;    *icid = call_data->icid;    DebugLog(2, ("XIM_GET_IC_VALUES: icid=%d\n", *icid));    if ((xccore->oxim_mode & OXIM_RUN_EXIT))	return True;    if (! (ic = ic_find(call_data->icid)))	return False;    ic_get_values(ic, call_data, xccore);    return True;}#define MAX_XIM_SYNC_CHECK	5static intxim_sync_reply_handler(XIMS ims, IMSyncXlibStruct *call_data, int *icid){    static int n_check=0;    *icid = call_data->icid;/* *  This is the main controlling process to terminate oxim, which is a really *  involved and complicated process. * *  There are 2 ways to terminate oxim. 1. Use "kill" command in the shell. *  2. Click the "kill" button of the oxim window. In the OverTheSpot style, *  every action of the XIM client it will use XSetICValues() to send its *  spot location to oxim, and oxim *must* reply it. So when the termination *  occures, oxim have to ensure that it has replied all the XSetICValues() *  request to the current IC on focus, and then actually exits. * *  So, when terminating, oxim will send XIM_SYNC to the on-focus IC and wait *  for its response. This is the dummy event which is just giving the time *  for the XIM client to send its XSetICValues() request to oxim in time *  such that oxim can reply it. However, oxim cannot assume that the client *  will always send the XSetICValues() request everytime when it is going to *  exit or how many requests the client will send. So, we use the method *  that oxim tries to send several XIM_SYNC one by one, and expect a centain *  number of response from the client. In the amount of the response, the *  client may send its XSetICValues() request *in time* (if it needs) such *  that oxim can response to it. * *  For case 1 of termination, note that the "kill" signal is received by the *  sighandler() of the main program, but not in the X event loop. In this *  case we cannot send the XIM_SYNC in the sighandler(), because outside the *  X event loop the XIM_SYNC request will be queued somewhere and cannot be *  processed immediately. Hence in sighandler() XIM_SYNC we only set the *  special flag OXIM_RUN_KILL to inform oxim this circumstance. When backing *  the X event loop, oxim will check for this flag and send the XIM_SYNC *  request to the client. * *  For case 2 since it is already in the X event loop, so it can send the *  XIM_SYNC request directly (in gui_main*() when the oxim main window is *  being killed). * *  All the XIM_SYNC request is sent by xim_close() function. When it is *  called, it will check if the client window is really exist, and set the *  special flag OXIM_RUN_EXIT to denote the situation that oxim is exiting. *  Then in the xim_sync_reply_handler() it will decide when the oxim can *  actually exit, determined by the number of the XIM_SYNC reply. If oxim *  can actually exit, the flag OXIM_RUN_EXITALL is set. */    if ((xccore->oxim_mode & OXIM_RUN_EXIT)) {	n_check ++;	DebugLog(2, ("XIM_SYNC_REPLY: icid=%d, n_check=%d\n", *icid, n_check));	if (n_check < MAX_XIM_SYNC_CHECK) {	    IC *ic = ic_find(call_data->icid);	    xim_close(ic);	}	else	    xccore->oxim_mode |= OXIM_RUN_EXITALL;    }    return True;}static int im_protocol_handler(XIMS ims, IMProtocol *call_data){    int ret, icid=-1;    switch (call_data->major_code) {    case XIM_OPEN:              ret = xim_open_handler(ims, &(call_data->imopen));	break;    case XIM_CLOSE:             ret = xim_close_handler(ims, &(call_data->imclose));	break;    case XIM_CREATE_IC:         ret = xim_create_ic_handler(ims, &(call_data->changeic), &icid);	break;    case XIM_DESTROY_IC:        ret = xim_destroy_ic_handler(ims, &(call_data->destroyic), &icid);	break;    case XIM_SET_IC_FOCUS:         ret = xim_set_focus_handler(ims, &(call_data->changefocus), &icid);	break;    case XIM_UNSET_IC_FOCUS:         ret = xim_unset_focus_handler(ims, &(call_data->changefocus), &icid);	break;    case XIM_TRIGGER_NOTIFY:        ret = xim_trigger_handler(ims, &(call_data->triggernotify), &icid);	break;    case XIM_FORWARD_EVENT:         ret = xim_forward_handler(ims, &(call_data->forwardevent), &icid);	break;    case XIM_SET_IC_VALUES:         ret = xim_set_ic_values_handler(ims, &(call_data->changeic), &icid);	break;    case XIM_GET_IC_VALUES:         ret = xim_get_ic_values_handler(ims, &(call_data->changeic), &icid);	break;    case XIM_SYNC_REPLY:	ret = xim_sync_reply_handler(ims, &(call_data->sync_xlib), &icid);	break;    case XIM_RESET_IC:        DebugLog(2, ("XIM_RESET_IC\n"));	ret = True;	break;/* *  Not implement yet. */    case XIM_PREEDIT_START_REPLY:        DebugLog(2, ("XIM_PREEDIT_START_REPLY\n"));	ret = True;	break;    case XIM_PREEDIT_CARET_REPLY:        DebugLog(2, ("XIM_PREEDIT_CARET_REPLY\n"));	ret = True;	break;    default:	DebugLog(2, ("XIM Unknown\n"));	ret = False;	break;    }    if (xccore->oxim_mode & OXIM_RUN_KILL) {	xccore->oxim_mode &= ~OXIM_RUN_KILL;	xim_close(xccore->ic);    }    gui_update_winlist();    return ret;}/*----------------------------------------------------------------------------	XIM Initialization.----------------------------------------------------------------------------*/#define XIM_TCP_PORT 9010enum trans_type {    TRANSPORT_X,     TRANSPORT_LOCAL,     TRANSPORT_TCP};/* Supported Encodings */static XIMEncoding zhEncodings[] = {    "COMPOUND_TEXT",    "UTF8_STRING",    NULL};static XIMStyle defaultStyles[] ={    XIMPreeditPosition|XIMStatusNothing,    /* OverTheSpot */    XIMPreeditPosition|XIMStatusArea,    /* OverTheSpot */    XIMPreeditPosition|XIMStatusNone,    /* OverTheSpot */    XIMPreeditPosition|XIMStatusCallbacks,    /* OverTheSpot */    XIMPreeditCallbacks|XIMStatusNothing,   /* OnTheSpotQT */    XIMPreeditCallbacks|XIMStatusArea,    XIMPreeditCallbacks|XIMStatusNone,    XIMPreeditCallbacks|XIMStatusCallbacks, /* OnTheSpot */    XIMPreeditNothing|XIMStatusNothing,     /* Root */    XIMPreeditNothing|XIMStatusArea,    XIMPreeditNothing|XIMStatusNone,    XIMPreeditNothing|XIMStatusCallbacks,    XIMPreeditArea|XIMStatusArea,	    /* OffTheSpot */    XIMPreeditArea|XIMStatusNothing,    XIMPreeditArea|XIMStatusNone,    XIMPreeditArea|XIMStatusCallbacks};void xim_init(xccore_t *core){    char transport[128], xim_name[128];    unsigned int transport_type;    XIMTriggerKeys on_keys;    XIMEncodings encodings;    int i;    transport_type = TRANSPORT_X;    xccore = core;/*    if (transport_type == TRANSPORT_LOCAL) {        char hostname[64];        char *address = "/tmp/.ximsock";        gethostname(hostname, 64);        sprintf(transport, "local/%s:%s", hostname, address);    }     else if (transport_type == TRANSPORT_TCP) {        char hostname[64];        int port_number = XIM_TCP_PORT;        gethostname(hostname, 64);        sprintf(transport, "tcp/%s:%d", hostname, port_number);    }     else */    strcpy(transport, "X/");    check_funckey();    xccore->input_styles.count_styles = (sizeof(defaultStyles) / sizeof(XIMStyle));    xccore->input_styles.supported_styles = defaultStyles;    encodings.count_encodings = sizeof(zhEncodings)/sizeof(XIMEncoding) - 1;    encodings.supported_encodings = zhEncodings;    make_trigger_keys(&on_keys);    if (xccore->xim_name[0] == '\0') {	strncpy(xim_name, "oxim", sizeof(xim_name));    }    else	strncpy(xim_name, xccore->xim_name, sizeof(xim_name));    /*------------------------*/    load_support_locales();    char *support_locales = oxim_malloc((xim_support_locales.nlocale * 2) + xim_support_locales.nbytes, True);    for (i=0; i < xim_support_locales.nlocale; i++)    {	if (i)	{	    strcat(support_locales, ",");	}	strcat(support_locales, xim_support_locales.locale[i]);    }    /*-----------------------------*/    ims = IMOpenIM(xccore->display,                   IMServerWindow,    xccore->window,                   IMModifiers,       "Xi18n",                   IMServerName,      xim_name,                   IMLocale,          (support_locales ? support_locales : xccore->lc_ctype),                   IMServerTransport, transport,                   IMInputStyles,     &(xccore->input_styles),                   IMEncodingList,    &encodings,                   IMProtocolHandler, im_protocol_handler,                   IMFilterEventMask, KeyPressMask | KeyReleaseMask,                   NULL);    if (support_locales)	free(support_locales);    if (ims == 0)	oxim_perr(OXIMMSG_ERROR,		N_("IMOpenIM() with name \"%s\" transport \"%s\" failed.\n"),		xim_name, transport);    else {	xccore->oxim_mode |= OXIM_RUN_INIT;	xccore->oxim_mode |= OXIM_SHOW_CINPUT;	oxim_perr(OXIMMSG_NORMAL,		N_("XIM server \"%s\" transport \"%s\"\n"),		xim_name, transport);	oxim_perr(OXIMMSG_EMPTY, "\n");	xim_set_trigger_keys();    }}void xim_set_trigger_keys(void){    XIMTriggerKeys on_keys;    make_trigger_keys(&on_keys);    IMSetIMValues(ims, IMOnKeysList, &on_keys, NULL);}voidxim_close(IC *ic){    IMSyncXlibStruct pass_data;    DebugLog(2, ("xim_close\n"));    xccore->oxim_mode |= (OXIM_RUN_EXIT | OXIM_ICCHECK_OFF);    if (ic && gui_check_window(ic->ic_rec.client_win) == True) {	DebugLog(2, ("xim_close sent\n"));	pass_data.major_code = XIM_SYNC;	pass_data.minor_code = 0;	pass_data.connect_id = ic->connect_id;	pass_data.icid = ic->id;	IMSyncXlib(ims, (XPointer)&pass_data);	XSync(xccore->display, False);    }    else	xccore->oxim_mode |= OXIM_RUN_EXITALL;}voidxim_terminate(void){    if (ims)	IMCloseIM(ims);    if (xccore)	XSync(xccore->display, False);}

⌨️ 快捷键说明

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