mirror of
https://github.com/Stichting-MINIX-Research-Foundation/pkgsrc-ng.git
synced 2025-08-03 17:59:07 -04:00
521 lines
13 KiB
Plaintext
521 lines
13 KiB
Plaintext
$NetBSD: patch-ag,v 1.2 2006/03/14 15:11:54 rxg Exp $
|
||
|
||
--- src/Cinput/chewing/xcin_chewing.c.orig 2006-03-13 22:26:59.000000000 +0800
|
||
+++ src/Cinput/chewing/xcin_chewing.c
|
||
@@ -0,0 +1,515 @@
|
||
+/*
|
||
+ * Bridge interface between libchewing and xcin
|
||
+ */
|
||
+
|
||
+#ifdef HAVE_CONFIG_H
|
||
+# include "config.h"
|
||
+#endif
|
||
+
|
||
+#include <chewing/chewing.h>
|
||
+#include <string.h>
|
||
+
|
||
+#include <X11/Xlib.h>
|
||
+#include <X11/keysym.h>
|
||
+#include "xcintool.h"
|
||
+#include "module.h"
|
||
+
|
||
+#include <iconv.h>
|
||
+#include <langinfo.h>
|
||
+
|
||
+/* the following keystate masks are defined by xcin */
|
||
+#define CAPS_MASK (2)
|
||
+#define CTRL_MASK (4)
|
||
+
|
||
+#define XCIN_BYTE_NATIVE 2
|
||
+#define XCIN_BYTE_UTF8 3
|
||
+
|
||
+static int chewing_codeset;
|
||
+void preconvert(char *input, char *output, int n_char);
|
||
+wchar_t convert(wchar_t input);
|
||
+
|
||
+static char selKey_define[11] = "1234567890\0"; /* Default */
|
||
+static int bAddPhraseForward = 0;
|
||
+
|
||
+int MakeInpinfo(inpinfo_t *inpinfo, ChewingOutput *pgo);
|
||
+
|
||
+int CallSetConfig(inpinfo_t *inpinfo, ChewingData *pgdata)
|
||
+{
|
||
+ ConfigData config;
|
||
+ int i;
|
||
+
|
||
+ config.selectAreaLen = 40;
|
||
+ config.maxChiSymbolLen = 16;
|
||
+ config.bAddPhraseForward = bAddPhraseForward;
|
||
+
|
||
+ for (i = 0; i < 10;i++)
|
||
+ config.selKey[i] = selKey_define[i];
|
||
+
|
||
+ SetConfig(pgdata, &config);
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+static int
|
||
+ChewingInit(void *conf, char *objname, xcin_rc_t *xc)
|
||
+{
|
||
+ char *cmd[2], kb_type_str[256], *cname;
|
||
+ ChewingConf *cf = (ChewingConf *)conf ;
|
||
+
|
||
+ char *prefix = CHEWING_DATA_DIR;
|
||
+
|
||
+ /*
|
||
+ * Because libchewing uses BIG-5 encoding for all its structure
|
||
+ * so we need to check if it is UTF-8 locale and do any conv
|
||
+ */
|
||
+ chewing_codeset = (! strcasecmp(xc->locale.encoding,"utf-8")) ?
|
||
+ XCIN_BYTE_UTF8 :
|
||
+ XCIN_BYTE_NATIVE;
|
||
+ cname = (char *) calloc(3, sizeof(char) * chewing_codeset);
|
||
+
|
||
+ cmd[0] = objname ;
|
||
+ cmd[1] = "KB_TYPE" ;
|
||
+ kb_type_str[0] = '\0';
|
||
+ get_resource(xc, cmd, kb_type_str, 200, 2);
|
||
+ cf->kb_type = KBStr2Num(kb_type_str);
|
||
+
|
||
+ /* Support selection key definitions */
|
||
+ cmd[1] = "SELECTION_KEYS_DEFINE";
|
||
+ if (get_resource(xc, cmd, kb_type_str, 256, 2)) {
|
||
+ if (strlen(kb_type_str) == 10) {
|
||
+ strcpy(selKey_define, kb_type_str);
|
||
+ selKey_define[11] = '\0';
|
||
+ }
|
||
+ }
|
||
+ cmd[1] = "ADD_PHRASE_FORWARD";
|
||
+ if (get_resource(xc, cmd, kb_type_str, 256, 2)) {
|
||
+ if (atoi(kb_type_str) == 1) {
|
||
+ bAddPhraseForward = 1;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ preconvert("<22>s<EFBFBD>ŭ<EFBFBD>", cname, 6);
|
||
+ cf->inp_cname = strdup(cname);
|
||
+ cf->inp_ename = strdup("Chewing");
|
||
+
|
||
+ /* Initialize Chewing */
|
||
+ ReadTree(prefix);
|
||
+ InitChar(prefix);
|
||
+ InitDict(prefix);
|
||
+ ReadHash(prefix);
|
||
+
|
||
+ return True;
|
||
+}
|
||
+
|
||
+static int
|
||
+ChewingXimInit(void *conf, inpinfo_t *inpinfo)
|
||
+{
|
||
+ static char cchBuffer[MAX_PHONE_SEQ_LEN];
|
||
+ ChewingConf *cf = (ChewingConf *) conf;
|
||
+ int i;
|
||
+
|
||
+ inpinfo->iccf = (ChewingData *) calloc(1, sizeof(ChewingData));
|
||
+
|
||
+ InitChewing(inpinfo->iccf, cf);
|
||
+ CallSetConfig(inpinfo, (ChewingData *) inpinfo->iccf);
|
||
+
|
||
+ inpinfo->lcch = (wch_t *) calloc(MAX_PHONE_SEQ_LEN, sizeof(wch_t));
|
||
+ inpinfo->lcch_grouping = (ubyte_t *) calloc(MAX_PHONE_SEQ_LEN, sizeof(ubyte_t));
|
||
+ inpinfo->cch = cchBuffer;
|
||
+
|
||
+ inpinfo->inp_cname = cf->inp_cname;
|
||
+ inpinfo->inp_ename = cf->inp_ename;
|
||
+ inpinfo->area3_len = 2 * ZUIN_SIZE + 4;
|
||
+ inpinfo->guimode = GUIMOD_LISTCHAR | GUIMOD_SELKEYSPOT;
|
||
+ inpinfo->keystroke_len = 0;
|
||
+ inpinfo->s_keystroke = (wch_t *) calloc(3 + MAX_PHRASE_LEN, sizeof(wch_t));
|
||
+
|
||
+ inpinfo->mcch = (wch_t *) calloc(MAX_CHOICE_BUF, sizeof(wch_t));
|
||
+ inpinfo->mcch_grouping = (ubyte_t *) calloc( MAX_SELKEY, sizeof(ubyte_t));
|
||
+ inpinfo->n_mcch = 0;
|
||
+
|
||
+ inpinfo->n_lcch = 0;
|
||
+ inpinfo->edit_pos = 0;
|
||
+ inpinfo->cch_publish.wch = (wchar_t) 0;
|
||
+
|
||
+ // check_winsize(inpinfo, iccf);
|
||
+ // [yet] check winsize is under construction.
|
||
+
|
||
+ inpinfo->n_selkey = 10;
|
||
+ inpinfo->s_selkey = (wch_t *) calloc(MAX_SELKEY, sizeof(wch_t));
|
||
+
|
||
+ for (i = 0; i < 10; i++) {
|
||
+ inpinfo->s_selkey[i].wch = (wchar_t) 0;
|
||
+ inpinfo->s_selkey[i].s[0] = selKey_define[i];
|
||
+ }
|
||
+
|
||
+ return True;
|
||
+}
|
||
+
|
||
+void CommitString(inpinfo_t *inpinfo, ChewingOutput *pgo)
|
||
+{
|
||
+ int i ;
|
||
+ char *str;
|
||
+ char *output;
|
||
+ memset(inpinfo->cch, 0, sizeof(char)*MAX_PHONE_SEQ_LEN);
|
||
+ str = (char *) calloc(MAX_PHONE_SEQ_LEN,sizeof(char));
|
||
+ output = (char *) calloc(MAX_PHONE_SEQ_LEN / 2 * chewing_codeset, sizeof(char));
|
||
+ for (i = 0; i < pgo->nCommitStr; i++)
|
||
+ strcat(str, (const char *) pgo->commitStr[i].s);
|
||
+ preconvert(str, output, strlen(str));
|
||
+ strcat(inpinfo->cch, output);
|
||
+ free(str);
|
||
+ free(output);
|
||
+}
|
||
+
|
||
+static unsigned int
|
||
+ChewingXimEnd(void *conf, inpinfo_t *inpinfo)
|
||
+{
|
||
+ ChewingOutput gOut ;
|
||
+ int rtn ;
|
||
+
|
||
+ /* if preedit exists, commit the string */
|
||
+ OnKeyEnter(inpinfo->iccf, &gOut);
|
||
+
|
||
+ rtn = MakeInpinfo(inpinfo, &gOut);
|
||
+ free(inpinfo->iccf);
|
||
+ free(inpinfo->s_keystroke);
|
||
+ free(inpinfo->lcch);
|
||
+ free(inpinfo->mcch);
|
||
+ free(inpinfo->mcch_grouping);
|
||
+
|
||
+ inpinfo->iccf = NULL;
|
||
+ inpinfo->s_keystroke = NULL;
|
||
+ inpinfo->lcch = NULL;
|
||
+
|
||
+ return rtn ;
|
||
+}
|
||
+
|
||
+void ShowChoose(inpinfo_t *inpinfo, ChoiceInfo *pci, ChewingOutput *pgo)
|
||
+{
|
||
+ int i,no,k,len, kk;
|
||
+ char *output;
|
||
+
|
||
+ // for new xcin, there is no need to modify the lcch buffer
|
||
+ // instead, we put phrase to choose in mcch
|
||
+ no = pci->pageNo * pci->nChoicePerPage;
|
||
+ len = 0;
|
||
+
|
||
+ for (i = 0;i < pci->nChoicePerPage; no++,i++) {
|
||
+
|
||
+ // in the last page, no will exceed nTotalChoice
|
||
+ if( no >= pci->nTotalChoice )
|
||
+ break;
|
||
+ output = (char *) calloc(
|
||
+ strlen(pci->totalChoiceStr[no]) * chewing_codeset + 1,
|
||
+ sizeof(char));
|
||
+ preconvert(
|
||
+ pci->totalChoiceStr[no], output,
|
||
+ strlen(pci->totalChoiceStr[no]));
|
||
+ // for each char in the phrase, copy to mcch
|
||
+ for (k = 0, kk = 0; output[k] != '\0'; k += chewing_codeset, kk++) {
|
||
+ memcpy(inpinfo->mcch[len++].s, &(output[k]), chewing_codeset) ;
|
||
+ }
|
||
+ free(output);
|
||
+ // set grouping to the length of the phrase
|
||
+ inpinfo->mcch_grouping[i+1] = kk;
|
||
+ }
|
||
+ // i stores how many choices are available
|
||
+ inpinfo->mcch_grouping[0] = i;
|
||
+
|
||
+ // set pgstate according to pci->pageNo & pci->nPage
|
||
+ if( pci->nPage == 1) {
|
||
+ inpinfo->mcch_pgstate = MCCH_ONEPG;
|
||
+ }
|
||
+ else {
|
||
+ if( pci->pageNo == 0 )
|
||
+ inpinfo->mcch_pgstate = MCCH_BEGIN;
|
||
+ else if( pci->pageNo == pci->nPage - 1)
|
||
+ inpinfo->mcch_pgstate = MCCH_END;
|
||
+ else
|
||
+ inpinfo->mcch_pgstate = MCCH_MIDDLE;
|
||
+ }
|
||
+
|
||
+ inpinfo->n_mcch = len ;
|
||
+}
|
||
+
|
||
+void ShowText(inpinfo_t *inpinfo, ChewingOutput *pgo)
|
||
+{
|
||
+ int i;
|
||
+ memset(inpinfo->lcch, 0, sizeof(wch_t)*MAX_PHONE_SEQ_LEN) ;
|
||
+ for (i = 0; i < pgo->chiSymbolBufLen; i++)
|
||
+ pgo->chiSymbolBuf[i].wch = convert(pgo->chiSymbolBuf[i].wch);
|
||
+ memcpy(inpinfo->lcch, pgo->chiSymbolBuf, sizeof(wch_t) * pgo->chiSymbolBufLen) ;
|
||
+ inpinfo->n_lcch = pgo->chiSymbolBufLen ;
|
||
+}
|
||
+
|
||
+void ShowInterval(inpinfo_t *inpinfo, ChewingOutput *pgo)
|
||
+{
|
||
+ int i, k, begin, len, count, nGroup ;
|
||
+ int label[MAX_PHONE_SEQ_LEN] ;
|
||
+
|
||
+ if( pgo->chiSymbolBufLen == 0) {
|
||
+ inpinfo->lcch_grouping[0] = 0 ;
|
||
+ return ;
|
||
+ }
|
||
+
|
||
+ // set label
|
||
+ for(count=0; count<pgo->chiSymbolBufLen; count++)
|
||
+ label[count] = count ;
|
||
+
|
||
+ for(i=0; i<pgo->nDispInterval; i++) {
|
||
+ len = pgo->dispInterval[i].to - pgo->dispInterval[i].from ;
|
||
+
|
||
+ if( len > 1) {
|
||
+ for(k=pgo->dispInterval[i].from; k<pgo->dispInterval[i].to; k++)
|
||
+ label[k] = count ;
|
||
+ count++ ;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ // begin to set lcch_grouping by the label
|
||
+ nGroup = 0 ;
|
||
+ begin = 0 ;
|
||
+ for(i=1; i<pgo->chiSymbolBufLen; i++) {
|
||
+ if( label[i] != label[begin] ) {
|
||
+ inpinfo->lcch_grouping[++nGroup] = ( i - begin ) ;
|
||
+ begin = i ;
|
||
+ }
|
||
+ }
|
||
+ inpinfo->lcch_grouping[++nGroup] = ( i - begin ) ;
|
||
+ inpinfo->lcch_grouping[0] = nGroup ;
|
||
+}
|
||
+
|
||
+void ShowStateAndZuin(inpinfo_t *inpinfo, ChewingOutput *pgo)
|
||
+{
|
||
+ int i, a , len = 0;
|
||
+ memset( inpinfo->s_keystroke, 0, sizeof(wch_t)*(3 + MAX_PHRASE_LEN)) ;
|
||
+ if(pgo->bShowMsg) {
|
||
+ for(i = 0; i < pgo->showMsgLen; i++)
|
||
+ pgo->showMsg[i].wch = convert(pgo->showMsg[i].wch);
|
||
+ memcpy( inpinfo->s_keystroke, pgo->showMsg, sizeof(wch_t)*pgo->showMsgLen) ;
|
||
+ inpinfo->keystroke_len = pgo->showMsgLen ;
|
||
+ }
|
||
+ else {
|
||
+ /* if(pgo->bChiSym)
|
||
+ strcpy( (char *)inpinfo->s_keystroke[0].s, "<22><>") ;
|
||
+ else
|
||
+ strcpy( (char *)inpinfo->s_keystroke[0].s, "<22>^") ;
|
||
+
|
||
+ inpinfo->s_keystroke[1].s[0] = ' ' ;
|
||
+ for(i=0,a=2; i<ZUIN_SIZE; i++) */
|
||
+ for(i=0,a=0; i<ZUIN_SIZE; i++)
|
||
+ if(pgo->zuinBuf[i].s[0] != '\0') {
|
||
+ inpinfo->s_keystroke[a++].wch = convert(
|
||
+ pgo->zuinBuf[i].wch) ;
|
||
+ ++ len;
|
||
+ }
|
||
+ inpinfo->keystroke_len = len;
|
||
+ }
|
||
+}
|
||
+
|
||
+void SetCursor(inpinfo_t *inpinfo, ChewingOutput *pgo)
|
||
+{
|
||
+ inpinfo->edit_pos = pgo->chiSymbolCursor;
|
||
+}
|
||
+
|
||
+int MakeInpinfo(inpinfo_t *inpinfo, ChewingOutput *pgo)
|
||
+{
|
||
+ int rtnValue = 0 ;
|
||
+
|
||
+ if(pgo->keystrokeRtn & KEYSTROKE_ABSORB)
|
||
+ rtnValue |= IMKEY_ABSORB;
|
||
+ if(pgo->keystrokeRtn & KEYSTROKE_IGNORE)
|
||
+ rtnValue |= IMKEY_IGNORE;
|
||
+ if(pgo->keystrokeRtn & KEYSTROKE_BELL)
|
||
+ rtnValue |= IMKEY_BELL;
|
||
+ if(pgo->keystrokeRtn & KEYSTROKE_COMMIT) {
|
||
+ rtnValue |= IMKEY_COMMIT;
|
||
+ CommitString(inpinfo, pgo);
|
||
+ }
|
||
+
|
||
+ if(pgo->pci->nPage != 0) { // in selection mode
|
||
+ ShowChoose(inpinfo,pgo->pci,pgo);
|
||
+ inpinfo->guimode &= ~GUIMOD_LISTCHAR;
|
||
+ }
|
||
+ else { // not in selection mode
|
||
+ ShowText(inpinfo, pgo);
|
||
+ ShowInterval(inpinfo, pgo);
|
||
+ inpinfo->guimode |= GUIMOD_LISTCHAR;
|
||
+ }
|
||
+ ShowStateAndZuin(inpinfo, pgo);
|
||
+ SetCursor(inpinfo, pgo);
|
||
+ return rtnValue;
|
||
+}
|
||
+
|
||
+static unsigned int
|
||
+ChewingKeystroke(void *conf, inpinfo_t *inpinfo, keyinfo_t *keyinfo)
|
||
+{
|
||
+ KeySym keysym = keyinfo->keysym;
|
||
+ ChewingOutput gOut ;
|
||
+ int rtn ;
|
||
+ static KeySym last_key = 0;
|
||
+
|
||
+ // set Chinese / English mode by keystate
|
||
+ if( keyinfo->keystate & CAPS_MASK ) { // uppercase
|
||
+ SetChiEngMode( inpinfo->iccf, SYMBOL_MODE);
|
||
+ }
|
||
+ else { // lower case
|
||
+ SetChiEngMode( inpinfo->iccf, CHINESE_MODE);
|
||
+ }
|
||
+
|
||
+
|
||
+ // check no ctrl key was pressed
|
||
+ if(keyinfo->keystate >= 0 && !(keyinfo->keystate & CTRL_MASK ) && !(keyinfo->keystate & ShiftMask) ) {
|
||
+ switch(keysym) {
|
||
+ case XK_Escape:
|
||
+ OnKeyEsc(inpinfo->iccf, &gOut) ;
|
||
+ inpinfo->n_mcch = 0;
|
||
+ break ;
|
||
+ case XK_Return:
|
||
+ OnKeyEnter(inpinfo->iccf, &gOut) ;
|
||
+ inpinfo->n_mcch = 0;
|
||
+ break ;
|
||
+ case XK_Delete:
|
||
+ OnKeyDel(inpinfo->iccf, &gOut) ;
|
||
+ break ;
|
||
+ case XK_BackSpace:
|
||
+ OnKeyBackspace(inpinfo->iccf, &gOut) ;
|
||
+ break ;
|
||
+ case XK_Up:
|
||
+ OnKeyUp(inpinfo->iccf, &gOut);
|
||
+ break ;
|
||
+ case XK_Down:
|
||
+ OnKeyDown(inpinfo->iccf, &gOut) ;
|
||
+ break ;
|
||
+ case XK_Left:
|
||
+ OnKeyLeft(inpinfo->iccf, &gOut) ;
|
||
+ break ;
|
||
+ case XK_Right:
|
||
+ OnKeyRight(inpinfo->iccf, &gOut) ;
|
||
+ break ;
|
||
+ case XK_Home:
|
||
+ OnKeyHome(inpinfo->iccf, &gOut);
|
||
+ break;
|
||
+ case XK_End:
|
||
+ OnKeyEnd(inpinfo->iccf, &gOut);
|
||
+ break;
|
||
+
|
||
+ case XK_Tab:
|
||
+ if (last_key == XK_Tab) // double click TAB
|
||
+ OnKeyDblTab(inpinfo->iccf, &gOut);
|
||
+ else
|
||
+ OnKeyTab(inpinfo->iccf, &gOut);
|
||
+ break;
|
||
+ case XK_Caps_Lock:
|
||
+ OnKeyCapslock(inpinfo->iccf, &gOut);
|
||
+ break;
|
||
+ case ' ': /* Space */
|
||
+ OnKeySpace(inpinfo->iccf, &gOut);
|
||
+ break;
|
||
+ default:
|
||
+ OnKeyDefault(inpinfo->iccf, keysym, &gOut);
|
||
+ inpinfo->n_mcch = 0;
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ else if (keyinfo->keystate & ShiftMask) {
|
||
+ switch ( keysym ) {
|
||
+ case XK_Left:
|
||
+ OnKeyShiftLeft(inpinfo->iccf, &gOut) ;
|
||
+ break ;
|
||
+ case XK_Right:
|
||
+ OnKeyShiftRight(inpinfo->iccf, &gOut) ;
|
||
+ break;
|
||
+ default:
|
||
+ OnKeyDefault(inpinfo->iccf, keysym, &gOut);
|
||
+ inpinfo->n_mcch = 0;
|
||
+ }
|
||
+ }
|
||
+ else if (keyinfo->keystate & CTRL_MASK) { // Ctrl-key Mask
|
||
+ // We need to fill the 'gOut' variable for output.
|
||
+ if (keysym <= '9' && keysym >= '0')
|
||
+ OnKeyCtrlNum(inpinfo->iccf,keysym,&gOut);
|
||
+ else
|
||
+ OnKeyCtrlOption(inpinfo->iccf, keysym - 'a' + 1, &gOut);
|
||
+ }
|
||
+
|
||
+
|
||
+ last_key = keysym;
|
||
+ rtn = MakeInpinfo(inpinfo, &gOut);
|
||
+ return rtn ;
|
||
+}
|
||
+
|
||
+static int
|
||
+ChewingShowKeystroke(void *conf, simdinfo_t *simdinfo)
|
||
+{
|
||
+ simdinfo->s_keystroke = NULL;
|
||
+ return False;
|
||
+}
|
||
+
|
||
+/* UTF-8 support */
|
||
+void
|
||
+preconvert(char *input, char *output, int n_char)
|
||
+{
|
||
+ if (chewing_codeset == XCIN_BYTE_UTF8) {
|
||
+ const char *inptr = input;
|
||
+ size_t inbytesleft = n_char;
|
||
+ size_t outbytesleft = n_char / 2 * 3 + 1;
|
||
+
|
||
+ char *outptr = output;
|
||
+ iconv_t cd;
|
||
+
|
||
+ cd = iconv_open("UTF-8", "BIG-5");
|
||
+ iconv (cd, (char **)&inptr, &inbytesleft, &outptr, &outbytesleft);
|
||
+
|
||
+ iconv_close(cd);
|
||
+ } else
|
||
+ strncpy(output, input, n_char);
|
||
+}
|
||
+
|
||
+wchar_t
|
||
+convert(wchar_t input)
|
||
+{
|
||
+ wch_t output;
|
||
+ wch_t temp;
|
||
+
|
||
+ temp.wch = input;
|
||
+ if (chewing_codeset == XCIN_BYTE_UTF8) {
|
||
+ const char *inptr = temp.s;
|
||
+ size_t inbytesleft = 2;
|
||
+ size_t outbytesleft = 3;
|
||
+ char *outptr = output.s;
|
||
+ iconv_t cd;
|
||
+ cd = iconv_open("UTF-8", "BIG-5");
|
||
+ iconv (cd, (char **)&inptr, &inbytesleft, &outptr, &outbytesleft);
|
||
+ iconv_close(cd);
|
||
+ output.s[3] = '\0';
|
||
+ return output.wch;
|
||
+ }
|
||
+
|
||
+ return input;
|
||
+}
|
||
+
|
||
+static char zh_chewing_comments[] =
|
||
+ "Chewing : a smart phonetic input method module for XCIN.\n"
|
||
+ "By Lu-chuan Kung <lckung@iis.sinica.edu.tw>,\n"
|
||
+ "Kang-pen Chen <kpchen@iis.sinica.edu.tw>, and others.\n";
|
||
+
|
||
+static char *zh_chewing_valid_objname[] = { "chewing", NULL };
|
||
+
|
||
+module_t module_ptr = {
|
||
+ {
|
||
+ MTYPE_IM,
|
||
+ "zh_chewing", /* name */
|
||
+ MODULE_VERSION, /* version */
|
||
+ zh_chewing_comments
|
||
+ }, /* comments */
|
||
+ zh_chewing_valid_objname, /* valid_objname */
|
||
+ sizeof(ChewingConf), /* conf_size */
|
||
+ ChewingInit, /* init */
|
||
+ ChewingXimInit, /* xim_init */
|
||
+ ChewingXimEnd, /* xim_end */
|
||
+ ChewingKeystroke, /* keystroke */
|
||
+ ChewingShowKeystroke, /* show_keystroke */
|
||
+ NULL
|
||
+};
|
||
+
|