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