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