*****************************************************************************
*
* IMS_example.c
*
* This is an example of how to write an Input Method Server for X11R6.
* The only protocol being used in here is Xi18n and the transport mechanism
* is X.
*
* In this example, there are only 26 composed characters, which are
* formed by 2 consecutive key inputs which are equal. These key inputs
* should be from a-z, case insensitive. The lookup string
* will be found from an array, which is some kind of small-scale dictionary.
*
* You should load Iso-latin 1 keymap files in order to work properly for
* this example.
*
* You can start this example using four of the languages:
* Korean, Traditional Chinese, Simplied Chinese and Japanese
*
* To start this IMServer, set the xnllanguage resource properly, for example,
* if you want to input Korean text, you should set the session language to
* Korean, or simply start as
* $IMS_example -xnllanguage "ko_KR.deckorean"
*
* To connect a client to this IMS, simply start up this IMS as a background
* job, then start the client with the correct language setting and XMODIFIERS
* environment. There are 4 modifiers that can be set according to locales :
* "zh_tw_exam", "zh_cn_exam", "ko_kr_exam", ja_jp_exam". For example,
*
* $define XMODIFIERS "@im=ko_kr_exam"
* $mc decw$cardfiler -xnllanguage "ko_KR.deckorean"
*/
#include
#include
#ifdef VMS
#include "DIMsDef.h"
/* #include */
#else
#include
#endif
static char my_dictionary[26][2] = {0xa1, 0xa1,
0xa1, 0xa2,
0xa1, 0xa3,
0xa1, 0xa4,
0xa1, 0xa5,
0xa1, 0xa6,
0xa1, 0xa7,
0xa1, 0xa8,
0xa1, 0xa9,
0xa1, 0xaa,
0xa1, 0xab,
0xa1, 0xac,
0xa1, 0xad,
0xa1, 0xae,
0xa1, 0xaf,
0xa1, 0xb1,
0xa1, 0xb2,
0xa1, 0xb3,
0xa1, 0xb4,
0xa1, 0xb5,
0xa1, 0xb6,
0xa1, 0xb7,
0xa1, 0xb8,
0xa1, 0xb9,
0xa1, 0xba,
0xa1, 0xbb};
typedef struct {
char data[1];
int num_char;
} MyDataRec, *MyData; /* This is the input context specific data */
static int CreateICCallback(w, client_data, widget_data)
Widget w;
Opaque *client_data;
Opaque **widget_data;
{
MyData my_data = (MyData)XtMalloc(sizeof(MyDataRec));
if (!my_data)
return 0; /* fail */
my_data->num_char = 0;
*widget_data = (Opaque *)my_data;
return 1; /* success */
}
static int DestroyICCallback(w, client_data, widget_data)
Widget w;
Opaque *client_data;
{
MyData my_data = (MyData)DIMsUserData(w);
if (my_data)
XtFree((char *)my_data);
return 1; /* success */
}
static int GetFilterEventsCallback(w, client_data, mask)
Widget w;
Opaque *client_data;
unsigned long **mask;
{
*mask = (unsigned long *) XtMalloc(sizeof(unsigned long));
/* Since this IMS supports root-window style only, so just KeyPress
events are necessary */
**mask = (unsigned long)(KeyPressMask);
return 1;
}
static int ProcessEventCallback(w, client_data, event, send_back)
Widget w;
Opaque *client_data;
XEvent *event;
Boolean *send_back;
{
MyData my_data = (MyData)DIMsUserData(w);
Display *dpy = XtDisplay(w);
*send_back = True;
switch (event->type)
{
case KeyPress :
{
KeyCode keycode = event->xkey.keycode;
KeySym keysym;
char second_char;
XTextProperty text_property;
char *text_list[1];
char text[3];
keysym = XKeycodeToKeysym( dpy, keycode, 0 );
if ((keysym >= XK_A && keysym <= XK_Z) ||
(keysym >= XK_a && keysym <=XK_z))
{
if (my_data->num_char)
{
if (keysym >= XK_a)
second_char = keysym - XK_a;
else
second_char = keysym - XK_A;
if (second_char == my_data->data[0])
{ /* two consecutive key are equal, send commit string */
text[0] = my_dictionary[second_char][0];
text[1] = my_dictionary[second_char][1];
text[2] = '\0';
text_list[0] = text;
XmbTextListToTextProperty(dpy, text_list, 1,
XCompoundTextStyle, &text_property);
DIMsCommit(w, (char *)text_property.value,
strlen((char *)text_property.value)+1);
XtFree((char *)text_property.value);
*send_back = False; /* the key is used by IMS,
no need to return to client */
}
my_data->num_char = 0; /* reset to 0*/
} else {
my_data->num_char = 1;
if (keysym >= XK_a)
my_data->data[0] = keysym - XK_a;
else
my_data->data[0] = keysym - XK_A;
*send_back = False;
}
}
break;
}
default :
break;
}
return 1;
}
IgnorXErrors(dpy, event)
Display *dpy;
XErrorEvent *event;
{
return 0;
}
main(argc, argv)
int argc;
char **argv;
{
Widget toplevel;
XtAppContext app_context;
DIMsClassCtx ctx;
char *zh_tw_server_strings[] = {"_XIM_zh_TW@zh_tw_exam"};
char *zh_cn_server_strings[] = {"_XIM_zh_CN@zh_cn_exam"};
char *ko_kr_server_strings[] = {"_XIM_ko_KR@ko_kr_exam"};
char *ja_jp_server_strings[] = {"_XIM_ja_JP@ja_jp_exam"};
XIMStyle support_styles[1] = {XIMPreeditNothing | XIMStatusNothing};
DIMsLocaleInfoRec locale;
DIMsStringListRec server_names;
DIMsSupportStylesRec im_styles;
Cardinal n;
Arg al[40];
DIMsVersionRec im_version;
XtSetLanguageProc(NULL, NULL, NULL);
toplevel = XtAppInitialize(&app_context, "example", NULL, 0,
&argc, argv, NULL, NULL, 0);
/* set up DIMs Class */
/* This example targets to work for 4 locales: zh_TW, ja_JP, zh_CN, ko_KR.
Therefore many DIMs class contexts are created */
/* create contexts for locales zh_TW, ja_JP, zh_CN, ko_KR */
locale.language = "zh_TW";
locale.num_support_codesets = 0;
locale.support_codesets = NULL;
server_names.num_of_strings = 1;
server_names.string_names = zh_tw_server_strings;
im_styles.num_support_styles = 1;
im_styles.support_styles = support_styles;
n = 0;
XtSetArg( al[n], DIMsNlocale, &locale);n++;
XtSetArg( al[n], DIMsNserverName, &server_names);n++;
/* use Xi18n protocol */
im_version.highest_major_version = 3;
im_version.highest_minor_version = 0;
im_version.lowest_major_version = 3;
im_version.lowest_minor_version = 0;
XtSetArg( al[n], DIMsNversion, &im_version);n++;
XtSetArg( al[n], DIMsNsupportStyles, &im_styles);n++;
XtSetArg( al[n], DIMsNcreateICCb, CreateICCallback);n++;
XtSetArg( al[n], DIMsNdestroyICCb, DestroyICCallback);n++;
XtSetArg( al[n], DIMsNprocessEventCb, ProcessEventCallback);n++;
XtSetArg( al[n], DIMsNgetFilterEventsCb, GetFilterEventsCallback);n++;
XtSetArg( al[n], DIMsNtransport, "X/");n++;
ctx = DIMsClassCtxCreate(NULL, "zh_tw_xi18n_exam", al, n);
locale.language = "zh_CN";
server_names.string_names = zh_cn_server_strings;
XtSetArg( al[0], DIMsNlocale, &locale);
XtSetArg( al[1], DIMsNserverName, &server_names);
ctx = DIMsClassCtxCreate(ctx, "zh_cn_xi18n_exam", al, n);
locale.language = "ko_KR";
server_names.string_names = ko_kr_server_strings;
XtSetArg( al[0], DIMsNlocale, &locale);
XtSetArg( al[1], DIMsNserverName, &server_names);
ctx = DIMsClassCtxCreate(ctx, "ko_kr_xi18n_exam", al, n);
locale.language = "ja_JP";
server_names.string_names = ja_jp_server_strings;
XtSetArg( al[0], DIMsNlocale, &locale);
XtSetArg( al[1], DIMsNserverName, &server_names);
ctx = DIMsClassCtxCreate(ctx, "ja_jp_xi18n_exam", al, n);
XSetErrorHandler(IgnorXErrors);
/* Initialize IMSSL */
DIMsSLInitialize(toplevel, ctx);
/* Realize widget hierrachy */
XtRealizeWidget(toplevel);
/* Initialize protocol layer */
DIMsProtoInit(toplevel, app_context);
XtAppMainLoop(app_context);
}
|