| Tcl/Tk 的日语化到Tcl7.6/Tk4.2,对其的汉化只须稍加改动.但是对其汉字输入方面的汉化则应有相应的汉字输入方法.Chinput-1.0便是解决问题的捷径.利用Chinput的API,稍加改动便可与原Kinput2接口.(参阅源代码和Chinput1.0
API)

★汉字输入的启动
启动延用原来的Kinput2函数界面. 启动部分包括原子的注册, 服务器的探测, 变量赋值, 然后注册回调. 输入汉字由kinput.tcl中设置的"bind"激活. "Control \"是其中之一.
int
Tk_Kinput2Start(interp, tkwin, argc, argv)
Tcl_Interp *interp; /* Current interpreter. */
Tk_Window tkwin; /* Focus window. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
int i;
char *variable;
Window twin;
if (!atom_initialized) {
hz_protocol_atom = Tk_InternAtom(tkwin, HZ_PROTOCOL_ATOM);
hz_input_atom = Tk_InternAtom(tkwin, HZ_INPUT_ATOM);
hz_output_atom = Tk_InternAtom(tkwin, HZ_OUTPUT_ATOM);
hz_query_atom = Tk_InternAtom(tkwin, HZ_QUERY_ATOM);
hz_reply_atom = Tk_InternAtom(tkwin, HZ_REPLY_ATOM);
hz_config_atom = Tk_InternAtom(tkwin, HZ_CONFIG_ATOM);
atom_initialized = 1;
}
/* in case that the server not started */
if(twin = XGetSelectionOwner(Tk_Display(tkwin), hz_protocol_atom) == None){
atom_initialized = 0;
interp->result = "hanzi input server not started!";
return TCL_ERROR;
}
/* set the global values */
ginterp = interp;
strcpy(tkvar, argv[1]);
/* register callbak */
Tk_CreateGenericHandler((Tk_GenericProc *)recvInput, (ClientData)tkwin);
return TCL_OK;
}
★回调函数
回调函数仅处理键盘信息和客户信息.
static int
recvInput(clientData, ev)
ClientData clientData;
XEvent *ev;
{
if(ev->type == KeyPress)
forwardKeyEvent(clientData, ev);
else if(ev->type == ClientMessage)
procClientMsg(clientData, ev);
}
★键盘处理
如果用户按了Escape键则结束输入. 其它按键都发送给服务器. 如果服务器中间过程死掉, 则把按键发送给自身. 其中程序注册了回调函数 recvInput 来接受服务器的信息.
static void
forwardKeyEvent(clientdata, eve)
ClientData clientdata;
XEvent *eve;
{
Tk_Window tkwin = (Tk_Window)clientdata;
Display *dpy = Tk_Display(tkwin);
Window twin;
XClientMessageEvent event;
char bf[20];
int bfsize = 20;
KeySym keysym;
XComposeStatus compose;
int charcount;
Tk_CreateGenericHandler((Tk_GenericProc *)recvInput, (ClientData)tkwin);
hz_protocol_atom = Tk_InternAtom(tkwin, HZ_PROTOCOL_ATOM);
twin = XGetSelectionOwner(dpy, hz_protocol_atom);
charcount = XLookupString((XKeyEvent *)eve, bf,
bfsize, &keysym, &compose);
/* escape to end conversion */
if(keysym == XK_Escape) {
Tk_DeleteGenericHandler((Tk_GenericProc *)recvInput,
(ClientData)tkwin);
return;
}
if(twin == None) {
event.type = ClientMessage;
event.window = Tk_WindowId(tkwin);
event.message_type=hz_output_atom;
event.format=32;
event.data.b[0] = 1;
event.data.l[1] = keysym;
event.data.l[2] = eve->xkey.state;
XSendEvent(dpy, Tk_WindowId(tkwin), False, 0, (XEvent *)&event);
XSync(dpy,False);
} else {
event.type=ClientMessage;
event.window = Tk_WindowId(tkwin);
event.message_type=hz_input_atom;
event.format=32;
event.data.l[0] = keysym;
event.data.l[1] = eve->xkey.state;
XSendEvent(dpy, twin, False, 0, (XEvent *)&event);
XSync(dpy,False);
}
}
★客户信息处理
当有客户信息时, 程序判断是否接收到了汉字转换, 然后由Tk 处理汉字输入 信息.
procClientMsg(clientData, ev)
ClientData clientData;
XEvent *ev;
{
int i, result;
char str[20];
int number;
unsigned int keycode, keystate;
Tk_Window tkwin = (Tk_Window) clientData;
result = HZprocInput(ev->xclient, &number, &keycode, &keystate, str);
if(result == -1) return -1;
if(number % 2) return -1; /* not hanzi */
Kinput2InputString(tkwin, number, str);
return 1;
}
int HZprocInput(ev, number, keycode, keystate, str)
XClientMessageEvent *ev;
int *number;
unsigned int *keycode, *keystate;
char *str;
{
int i;
char *buf = ev->data.b;
if (ev->message_type != hz_output_atom) return -1;
memset(str, '\0', 20);
strncpy(str, buf+1, ev->data.b[0]);
*number = ev->data.b[0];
if(ev->data.b[0] == 1) {
*keycode = ev->data.l[1];
if(ev->data.l[1] & 0xff00) {
*keystate = ev->data.l[2];
return 1;
}
else return 0;
} else {
return 2;
}
}
★汉字输入结束
按Escape键结束汉字输入, 此键可以由用户定义.
下载地址
tcl7.6jpcn.tar.gz (970KB)
tk4.2jpcn.tar.gz (1721KB)
|