4.4BSD/usr/src/contrib/X11R5-lib/lib/X/Xsi/XLocalIM.c
/*
* $XConsortium: XLocalIM.c,v 1.11 92/10/22 14:26:20 rws Exp $
*/
/*
* Copyright 1990, 1991 by OMRON Corporation
* Copyright 1991 by the Massachusetts Institute of Technology
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the names of OMRON and MIT not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. OMRON and MIT make no representations
* about the suitability of this software for any purpose. It is provided
* "as is" without express or implied warranty.
*
* OMRON AND MIT DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL OMRON OR MIT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* Author: Seiji Kuwari OMRON Corporation
* kuwa@omron.co.jp
* kuwa%omron.co.jp@uunet.uu.net
*/
#include <stdio.h>
#define NEED_EVENTS
#include "Xlibint.h"
#include "Xi18nint.h"
#include "XIMlibint.h"
#include <X11/Xos.h>
#include <X11/keysymdef.h>
#if NeedVarargsPrototypes
# include <stdarg.h>
# define Va_start(a,b) va_start(a,b)
#else
# include <varargs.h>
# define Va_start(a,b) va_start(a)
#endif
#ifndef X_NOT_POSIX
#ifdef _POSIX_SOURCE
#include <limits.h>
#else
#define _POSIX_SOURCE
#include <limits.h>
#undef _POSIX_SOURCE
#endif
#endif
#ifndef PATH_MAX
#include <sys/param.h>
#ifndef PATH_MAX
#ifdef MAXPATHLEN
#define PATH_MAX MAXPATHLEN
#else
#define PATH_MAX 1024
#endif
#endif
#endif
#ifdef X_NOT_STDC_ENV
extern char *getenv();
#endif
#if __STDC__ && !defined(NORCONST)
#define RConst const
#else
#define RConst /**/
#endif
#define offset(field) XOffsetOf(XipLocalIMRec, field)
static int compiled_resources;
static XIMResource im_resources[] = {
{ XNQueryInputStyle, sizeof(XIMStyles), offset(values.input_styles),
(unsigned short)IMResourceRead, (int)IMQueryInputStyle },
#ifdef XML
{ XNQueryLanguage, sizeof(char *), offset(values.supported_language),
(unsigned short)IMResourceRead, (int)IMQueryLanguage }
#endif /* XML */
};
#undef offset
#define offset(field) XOffsetOf(XipLocalICRec, field)
static XIMResource ic_resources[] = {
{ XNInputStyle, sizeof(XIMStyle), offset(core.input_style),
(unsigned short)IMResourceReadWrite, ICInputStyle },
{ XNClientWindow, sizeof(Window), offset(core.client_window),
(unsigned short)IMResourceReadWrite, -1 },
{ XNFocusWindow, sizeof(Window), offset(core.focus_window),
(unsigned short)IMResourceReadWrite, ICFocusWindow },
{ XNResourceName, sizeof(char *), offset(values.res_name),
(unsigned short)IMResourceReadWrite, -1 },
{ XNResourceClass, sizeof(char *), offset(values.res_class),
(unsigned short)IMResourceReadWrite, -1 },
{ XNFilterEvents, sizeof(long), offset(core.filter_events),
(unsigned short)IMResourceRead, ICFilterEvents },
{ XNPreeditAttributes, sizeof(ICAttributes *), offset(core.preedit_attr),
(unsigned short)IMResourceReadWrite, -1 },
{ XNStatusAttributes, sizeof(ICAttributes *), offset(core.status_attr),
(unsigned short)IMResourceReadWrite, -1 }
#ifdef XML
,
{ XNUsingLanguage, sizeof(char *), offset(values.using_language),
(unsigned short)IMResourceReadWrite, ICUsingLanguage },
{ XNCurrentLanguage, sizeof(char *), offset(values.current_language),
(unsigned short)IMResourceReadWrite, ICCurrentLanguage },
{ XNChangeLocaleCB, sizeof(char **), offset(values.ch_locale_cb),
(unsigned short)IMResourceReadWrite, ICChangeLocaleCB },
#endif /* XML */
};
#undef offset
#define attroffset(field) XOffsetOf(ICAttributes, field)
static XIMResource attr_resources[] = {
{ XNArea, sizeof(XRectangle), attroffset(area),
(unsigned short)IMResourceReadWrite, ICArea },
{ XNAreaNeeded, sizeof(XRectangle), attroffset(area_needed),
(unsigned short)IMResourceReadWrite, ICAreaNeeded },
{ XNSpotLocation, (sizeof(XPoint) + 4), attroffset(spot_location),
(unsigned short)IMResourceReadWrite, ICSpotLocation },
{ XNColormap, sizeof(Colormap), attroffset(colormap),
(unsigned short)IMResourceReadWrite, ICColormap },
{ XNStdColormap, sizeof(Atom), attroffset(std_colormap),
(unsigned short)IMResourceReadWrite, ICStdColormap },
{ XNForeground, sizeof(long), attroffset(foreground),
(unsigned short)IMResourceReadWrite, ICForeground },
{ XNBackground, sizeof(long), attroffset(background),
(unsigned short)IMResourceReadWrite, ICBackground },
{ XNBackgroundPixmap, sizeof(Pixmap), attroffset(background_pixmap),
(unsigned short)IMResourceReadWrite, ICBackgroundPixmap },
{ XNFontSet, sizeof(XFontSet *), attroffset(fontset),
(unsigned short)IMResourceReadWrite, ICFontSet },
{ XNLineSpace, sizeof(int), attroffset(line_space),
(unsigned short)IMResourceReadWrite, ICLineSpace },
{ XNCursor, sizeof(Cursor), attroffset(cursor),
(unsigned short)IMResourceReadWrite, ICCursor },
{ XNPreeditStartCallback, sizeof(XIMCallback), attroffset(callbacks.start),
(unsigned short)IMResourceReadWrite, -1 },
{ XNPreeditDoneCallback, sizeof(XIMCallback), attroffset(callbacks.done),
(unsigned short)IMResourceReadWrite, -1 },
{ XNPreeditDrawCallback, sizeof(XIMCallback), attroffset(callbacks.draw),
(unsigned short)IMResourceReadWrite, -1 },
{ XNPreeditCaretCallback, sizeof(XIMCallback), attroffset(callbacks.caret),
(unsigned short)IMResourceReadWrite, -1 },
{ XNStatusStartCallback, sizeof(XIMCallback), attroffset(callbacks.start),
(unsigned short)IMResourceReadWrite, -1 },
{ XNStatusDoneCallback, sizeof(XIMCallback), attroffset(callbacks.done),
(unsigned short)IMResourceReadWrite, -1 },
{ XNStatusDrawCallback, sizeof(XIMCallback), attroffset(callbacks.draw),
(unsigned short)IMResourceReadWrite, -1 }
};
#undef attroffset
#define ENTRY_CNT 256
#define BITONP(h, i) (h[i / BITSIZ] & (1 << (i % BITSIZ)))
#define BITOFP(h, i) (!BITONP(h, i))
#define BIT_UP(h, i) (h[i / BITSIZ] |= (1 << (i % BITSIZ)))
#define BITDWN(h, i) (h[i / BITSIZ] &= ~(1 << (i % BITSIZ)))
#define div_up(a, b) ((a + b - 1) / b)
#ifndef XNLSPATHDEFAULT
#define XNLSPATHDEFAULT "/usr/lib/X11/nls"
#endif
#ifndef LOCAL_CVT_TBL_DIR
#define LOCAL_CVT_TBL_DIR "/local_im_tbl/"
#endif
typedef struct {
char *name;
unsigned int mask;
} StateTbl;
static StateTbl state_tbl[] = {
{ "Lock", LockMask },
{ "Control", ControlMask },
{ "Mod1", Mod1Mask },
{ "Mod2", Mod2Mask },
{ "Mod3", Mod3Mask },
{ "Mod4", Mod4Mask },
{ "Mod5", Mod5Mask },
{ NULL, 0 }
};
typedef struct {
char *name;
Bool (*func)();
int (*init_func)();
} FuncTbl;
static int convert_on();
static int convert_off();
static int convert_on_init();
static int no_filter();
static FuncTbl func_tbl[] = {
{ "ConvertOn", convert_on, convert_on_init },
{ "ConvertOff", convert_off, NULL },
{ "NoFilter", NULL, no_filter }
};
static unsigned int
is_state(name)
register char *name;
{
register StateTbl *p;
for (p = state_tbl; p->name; p++) {
if (!strcmp(p->name, name)) return(p->mask);
}
return(0);
}
static int
parse_bslash(buf, work)
register char *buf;
register unsigned char *work;
{
register int i;
switch(*buf) {
case 'x': /* 16 */
for (buf++, *work = '\0', i = 1; i >= 0; i--, buf++) {
if (*buf >= '0' && *buf <= '9') {
*work |= ((1 << (i * 4)) * (*buf - '0'));
} else if (*buf >= 'A' && *buf <= 'F') {
*work |= ((1 << (i * 4)) * (*buf - 'A' + 10));
} else if (*buf >= 'a' && *buf <= 'f') {
*work |= ((1 << (i * 4)) * (*buf - 'a' + 10));
} else {
return(0);
}
}
return(3);
case 'o': /* 8 */
for (buf++, *work = '\0', i = 2; i >= 0; i--, buf++) {
if (*buf >= '0' && *buf <= '7') {
*work |= ((1 << (i * 3)) * (*buf - '0'));
} else {
return(0);
}
}
return(4);
case 'n': /* */
*work = '\n'; return(1);
case 't': /* */
*work = '\t'; return(1);
case 'b': /* */
*work = '\b'; return(1);
case 'r': /* */
*work = '\r'; return(1);
case 'f': /* */
*work = '\f'; return(1);
case 'e': /* */
case 'E': /* */
*work = '\033'; return(1);
case '\\': /* */
*work = '\\'; return(1);
default:
for (*work = '\0', i = 2; i >= 0; i--, buf++) {
if (*buf >= '0' && *buf <= '7') {
*work |= ((1 << (i * 3)) * (*buf - '0'));
} else {
return(*buf);
}
}
return(3);
}
}
static XipLocalKeySymTbl *
get_string(buf, tbl)
register char *buf;
XipLocalKeySymTbl *tbl;
{
XipLocalKeySymTbl work_tbl[8], *p, *t;
unsigned char work[32], *str;
register int i = 0, total = 0, ret;
for (p = work_tbl, total = 0; *buf; p++, total++, buf++) {
if ((buf = index(buf, '{')) == NULL) {
break;
}
buf++;
for ( i = 0; *buf != '}';) {
if (*buf == (char)0x5c) {
buf++;
if (!(ret = parse_bslash(buf, &work[i]))) {
return(NULL);
}
buf += ret;
i++;
} else {
work[i++] = *buf;
buf++;
}
if (!*buf) return(NULL);
}
if (i == 0) return(NULL);
work[i] = '\0';
str = (unsigned char *) Xmalloc(i + 1);
strcpy((char *)str, (char *)work);
p->str = str;
p->keysym = NoSymbol;
p->state = 0;
total++;
}
if (total < 1) return(NULL);
p->str = NULL;
p->keysym = XK_VoidSymbol;
p->state = 0;
if (tbl) {
for (i = 0, t = tbl, p = work_tbl;
t->keysym != XK_VoidSymbol && i < total; i++, t++, p++) {
t->str = p->str;
}
} else {
tbl = (XipLocalKeySymTbl *) Xmalloc((sizeof(XipLocalKeySymTbl)
* (total + 1)));
if (!tbl) return (NULL);
bcopy((char *)work_tbl, (char *)tbl,
sizeof(XipLocalKeySymTbl) * (total + 1));
}
return(tbl);
}
static XipLocalKeySymTbl *
get_keysym(buf, len)
char *buf;
int *len;
{
int cnt, total = 0;
int i;
XipLocalKeySymTbl work_tbl[8], *keysym_tbl, *p;
char *k[8];
*len = 0;
for (cnt = 0; ; cnt++) {
if ((buf = index(buf, '<')) == NULL) {
break;
}
k[cnt] = ++buf;
if (buf = index(buf, '>')) {
*buf = '\0';
buf++;
}
}
if (cnt < 1)
return (NULL);
for (i = 0, p = work_tbl, total = 0; i < cnt; i++, p++) {
if (p->state = is_state(k[i])) {
i++;
}
if ((p->keysym = XStringToKeysym(k[i])) == 0) {
fprintf(stderr,
"Can't convert to KeySym \"%s\".", k[i]);
return (NULL);
}
p->str = NULL;
total++;
}
p->keysym = XK_VoidSymbol;
p->str = NULL;
total++;
keysym_tbl = (XipLocalKeySymTbl *) Xmalloc((sizeof(XipLocalKeySymTbl)
* total));
if (!keysym_tbl)
return (NULL);
bcopy((char *)work_tbl, (char *)keysym_tbl,
sizeof(XipLocalKeySymTbl) * total);
*len = (total - 1);
return (keysym_tbl);
}
static int
is_comment(c)
char c;
{
if (c == '#')
return (1);
return (0);
}
static int
is_command(c)
char c;
{
if (c != '<' && c != '{')
return (1);
return (0);
}
static int
is_keysym(c)
char c;
{
if (c == '<')
return (1);
return (0);
}
static int
is_state_command(xcvt, f, t)
XipLocalCvt *xcvt;
char *f, *t;
{
if (!*f || !*t) return(0);
if (!strcmp(f, "InitialState"))
if (!strcmp(t, "OnState"))
xcvt->off = False;
else if (!strcmp(t, "OffState"))
xcvt->off = True;
else return(0);
return(1);
}
static FuncTbl *
get_command(name)
char *name;
{
register FuncTbl *p;
for (p = func_tbl; p->name; p++) {
if (!strcmp(p->name, name)) {
return(p);
}
}
fprintf(stderr, "Sorry, \"%s\" is not a supported command.\n", name);
fprintf(stderr, "XIM supported commands are \n");
for (p = func_tbl; p->name; p++) {
fprintf(stderr, " %s \n", p->name);
}
return(NULL);
}
static Bool
convert_on(xcvt)
XipLocalCvt *xcvt;
{
xcvt->off = False;
return(1);
}
static Bool
convert_off(xcvt)
XipLocalCvt *xcvt;
{
xcvt->off = True;
return(True);
}
static int
convert_on_init(xcvt, tbl, len)
XipLocalCvt *xcvt;
XipLocalCvtTbl *tbl;
int len;
{
register XipLocalKeySymTbl *to, *from, *p;
p = (XipLocalKeySymTbl *) Xmalloc(sizeof(XipLocalKeySymTbl) * (len + 1));
if (!p) return(-1);
for (to = p, from = tbl->fromkey; len > 0; to++, from++, len--) {
to->keysym = from->keysym;
to->state = from->state;
}
to->keysym = XK_VoidSymbol;
to->state = 0;
xcvt->off_tbl.to.func = tbl->to.func;
xcvt->off_tbl.com = True;
xcvt->off_tbl.fromkey = p;
return(0);
}
static int
no_filter(xcvt, tbl, len)
XipLocalCvt *xcvt;
XipLocalCvtTbl *tbl;
int len;
{
XipLocalNestedKeySym *nested_keysym;
nested_keysym = (XipLocalNestedKeySym *)
Xmalloc(sizeof(XipLocalNestedKeySym));
if (!nested_keysym) return(-1);
nested_keysym->keysym = tbl->fromkey->keysym;
nested_keysym->next = xcvt->no_filter;
xcvt->no_filter = nested_keysym;
return(1);
}
static Bool
is_nofilter(xcvt, keysym)
XipLocalCvt *xcvt;
KeySym keysym;
{
XipLocalNestedKeySym *p;
for (p = xcvt->no_filter; p; p = p->next) {
if (p->keysym == keysym) return(True);
}
return(False);
}
static FILE *
open_convert_file(lang, filename)
char *lang;
char *filename;
{
FILE *fp;
char nlspath[PATH_MAX];
char *path;
char *dir;
char *env;
if ((env = getenv("XNLSPATH")) == NULL) {
env = XNLSPATHDEFAULT;
}
path = nlspath;
strcpy(path, env);
while (1) {
if (path == NULL) {
fprintf(stderr, "%s \"%s\".\n%s%s%s.\n",
"XIM: Couldn't find any convert table for lang", lang,
"Please, create xnls_dir", LOCAL_CVT_TBL_DIR, lang);
return(NULL);
}
dir = path;
if ((dir = index(dir, ':')) != NULL) {
*dir++ = '\0';
}
strcpy(filename, path);
strcat(filename, LOCAL_CVT_TBL_DIR);
strcat(filename, lang);
if (fp = fopen(filename, "r")) {
return(fp);
}
path = dir;
}
}
static XipLocalCvt *
_XipLocalCvtSetUp(xlc)
XLocale xlc;
{
char filename[PATH_MAX];
char tmp_buf[32], *p;
FILE *fp;
char buf[256], tobuf[256], frombuf[256], tostr[256];
int cnt = 0;
int len;
int k;
XipLocalCvt *cvt;
KeySym bs;
FuncTbl *func_tbl;
int line = 0;
int ret;
strcpy(tmp_buf, xlc->xlc_db->lc_name);
for (p = tmp_buf; *p && *p != '@'; p++);
if (*p) *p = '\0';
if(CHANGE_MAX < div_up(ENTRY_CNT, BITSIZ)){
fprintf(stderr, "XIM: %s%s%d%s",
"Sorry, please set CHANGE_MAX(in file ",
"Xi18nint.h) larger than ",
div_up(ENTRY_CNT, BITSIZ) - 1,
",\r\nand recompile.\r\n");
return(NULL);
}
if(!(fp = open_convert_file(tmp_buf, filename))) return(NULL);
if (!(cvt = (XipLocalCvt *) Xmalloc(sizeof(XipLocalCvt)))) {
fprintf(stderr, "XIM: Malloc failed\n");
goto _err_ret2;
}
if (!(cvt->tbl = (XipLocalCvtTbl *) Xmalloc(sizeof(XipLocalCvtTbl) * ENTRY_CNT))) {
fprintf(stderr, "XIM: Malloc failed\n");
goto _err_ret1;
}
cnt = 0;
cvt->nmax = 0;
cvt->no_filter = NULL;
cvt->off = False;
while(fgets(buf, BUFSIZ, fp)) {
line++;
if(is_comment(*buf) ||
(k = sscanf(buf, "%s %s %s", frombuf, tobuf, tostr)) <= 0)
continue;
if (k < 2) {
goto _err_ret;
}
if(!(cvt->tbl[cnt].fromkey = get_keysym(frombuf, &len))){
if (!is_state_command(cvt, frombuf, tobuf))
goto _err_ret;
continue;
}
if (len > cvt->nmax) cvt->nmax = len;
if (is_command(*tobuf)) {
if(!(func_tbl = get_command(tobuf))) {
goto _err_ret;
}
cvt->tbl[cnt].to.func = func_tbl->func;
cvt->tbl[cnt].com = True;
if (func_tbl->init_func) {
if ((ret = (*func_tbl->init_func)(cvt, &cvt->tbl[cnt], len))
== -1)
goto _err_ret;
else if (ret == 0)
continue;
}
} else {
if (is_keysym(*tobuf)) {
if(!(cvt->tbl[cnt].to.tokey = get_keysym(tobuf, &len))){
goto _err_ret;
}
if (k > 2) {
if(!(get_string(tostr, cvt->tbl[cnt].to.tokey))){
goto _err_ret;
}
}
} else {
if(!(cvt->tbl[cnt].to.tokey = get_string(tobuf, NULL))){
goto _err_ret;
}
}
cvt->tbl[cnt].com = False;
}
cnt++;
}
cvt->cnt = cnt;
cvt->buf = (XipLocalKeySymTbl *) Xmalloc(sizeof(XipLocalKeySymTbl)
* (cvt->nmax + 1));
cvt->buf_cnt = 0;
cvt->bs = ((bs = XStringToKeysym("BackSpace"))? bs: 0x8);
fclose(fp);
return(cvt);
_err_ret:
fprintf(stderr, "XIM: Error occurred at line %d in file \"%s\".\n",
line, filename);
Xfree(cvt->tbl);
_err_ret1:
Xfree(cvt);
_err_ret2:
fclose(fp);
return(NULL);
}
static XipLocalCvt *
_XipLocalDupCvt(cvt)
XipLocalCvt *cvt;
{
XipLocalCvt *new;
if (!(new = (XipLocalCvt *) Xmalloc(sizeof(XipLocalCvt)))) {
return(NULL);
}
new->tbl = cvt->tbl;
new->off_tbl = cvt->off_tbl;
new->no_filter = cvt->no_filter;
new->bs = cvt->bs;
new->cnt = cvt->cnt;
new->nmax = cvt->nmax;
new->buf = (XipLocalKeySymTbl *) Xmalloc(sizeof(XipLocalKeySymTbl)
* (new->nmax + 1));
new->buf_cnt = 0;
new->off = cvt->off;
return(new);
}
static void
_XipLocalFreeCvt(cvt)
XipLocalCvt *cvt;
{
register int i, j;
XipLocalCvtTbl *tbl;
tbl = cvt->tbl;
for (i = 0; i < cvt->cnt; i++, tbl++) {
Xfree((*tbl).fromkey);
if ((*tbl).com != True) {
for (j = 0; (*tbl).to.tokey[j].str; j++)
Xfree((*tbl).to.tokey[j].str);
Xfree((*tbl).to.tokey);
}
}
Xfree(cvt->tbl);
Xfree(cvt);
}
/*
* Close the connection to the input manager, and free the private data
*/
static Status
_XipLocalCloseIM(supim)
XIM supim;
{
XipLocalIM im = (XipLocalIM)supim;
_XlcFreeLocale(im->xlc);
if (im->xcvt) _XipLocalFreeCvt(im->xcvt);
return(Success);
}
static RConst XIMMethodsRec im_methods = {
_XipLocalCloseIM,
_XipLocalGetIMValues,
_XipLocalCreateIC
};
XIM
_XipLocalOpenIM(lcd, display, rdb, res_name, res_class)
XLCd lcd;
Display *display;
XrmDatabase rdb;
char *res_name;
char *res_class;
{
XipLocalIM xim;
XLocale xlc = ((XsiLCd)lcd)->xlc;
XipLocalCvt *xcvt;
XIMStyle *supported_styles;
if ((xcvt = _XipLocalCvtSetUp(xlc)) == NULL) return(NULL);
/*
* Attempt to allocate a XIM structure. Return NULL if allocation
* failed.
*/
if ((xim = (XipLocalIM)Xmalloc(sizeof(XipLocalIMRec))) == NULL) {
return(NULL);
}
xim->methods = (XIMMethods)&im_methods;
xim->core.lcd = lcd;
xim->core.ic_chain = NULL;
xim->core.display = display;
xim->core.rdb = rdb;
xim->core.res_name = res_name;
xim->core.res_class = res_class;
if (!compiled_resources) {
_XIMCompileResourceList(im_resources, XIMNumber(im_resources));
_XIMCompileResourceList(ic_resources, XIMNumber(ic_resources));
_XIMCompileResourceList(attr_resources, XIMNumber(attr_resources));
compiled_resources = 1;
}
xim->resources = (XIMrmResourceList)im_resources;
xim->num_resources = XIMNumber(im_resources);
xim->core.ic_resources = (XIMrmResourceList)ic_resources;
xim->core.ic_num_resources = XIMNumber(ic_resources);
xim->core.ic_attr_resources = (XIMrmResourceList)attr_resources;
xim->core.ic_num_attr_resources = XIMNumber(attr_resources);
if ((supported_styles = (XIMStyle *)Xmalloc((unsigned)(sizeof(XIMStyle))))
== NULL) {
return(NULL);
}
supported_styles[0] = (XIMPreeditNothing | XIMStatusNothing);
xim->values.input_styles.supported_styles = supported_styles;
xim->values.input_styles.count_styles = 1;
xim->xlc = _XlcDupLocale(xlc);
xim->xcvt = xcvt;
return((XIM)xim);
}
int
_XipLocalCallCallbacks(ic)
XipIC ic;
{
return(0);
}
static int
key_check(cvt)
XipLocalCvt *cvt;
{
int dist, base;
XipLocalKeySymTbl *code_p;
int i;
for(base = 0; cvt->buf[base].keysym != XK_VoidSymbol; base++) {
for(dist = 0; dist < cvt->cnt; dist++) {
if(BITONP(cvt->check_flg, dist) &&
cvt->tbl[dist].fromkey->keysym != XK_VoidSymbol){
code_p = cvt->tbl[dist].fromkey + base;
if((code_p->keysym == cvt->buf[base].keysym) &&
((!(code_p->state | (cvt->buf[base].state & ~ShiftMask))) ||
(code_p->state == (cvt->buf[base].state & ~ShiftMask)))) {
if((code_p + 1)->keysym == (KeySym)XK_VoidSymbol){
/* matched */
for(i = 0, base++;
(cvt->buf[i].keysym = cvt->buf[base].keysym) != XK_VoidSymbol;
i++, base++);
return(dist);
}
/* Not yet matched */
} else {
BITDWN(cvt->check_flg, dist); /* off bit vecter */
}
}
}
}
/* Check bit vercters */
for(i = 0; i < cvt->cnt / BITSIZ; i++){
if(cvt->check_flg[i]) return(-1);
}
if((cvt->cnt % BITSIZ) &&
(cvt->check_flg[i]& ~(~0 << (cvt->cnt % BITSIZ))))
return(-1); /* posiblity */
return(-2); /* Not matched */
}
static int
off_key_check(cvt)
XipLocalCvt *cvt;
{
int base;
XipLocalKeySymTbl *code_p = cvt->off_tbl.fromkey;
int i;
for(base = 0; cvt->buf[base].keysym != XK_VoidSymbol; base++) {
if((code_p->keysym == cvt->buf[base].keysym) &&
((!(code_p->state | (cvt->buf[base].state & ~ShiftMask))) ||
(code_p->state == (cvt->buf[base].state & ~ShiftMask)))) {
if((code_p + 1)->keysym == (KeySym)XK_VoidSymbol){
/* matched */
for(i = 0, base++;
(cvt->buf[i].keysym = cvt->buf[base].keysym) != XK_VoidSymbol;
i++, base++);
return(0);
}
} else {
return(-2);
}
}
return(-1); /* posiblity */
}
static void
_XipLocalClearCvt(cvt)
XipLocalCvt *cvt;
{
register int i;
for(i = 0; i < div_up(cvt->cnt, BITSIZ); cvt->check_flg[i++] = ~0);
}
Bool
_XipLocalBackEndFilter(display, window, ev, client_data)
Display *display;
Window window;
XEvent *ev;
XPointer client_data;
{
register XipLocalIC ic = (XipLocalIC)client_data;
XipLocalCvt *xcvt = ic->xcvt;
KeySym keysym;
int keycode;
int i, c; /* work */
char str[256];
XEvent dummy_ev;
if (xcvt->cnt == 0)
return(False);
if (ev->xkey.keycode == 0) {
if (_XipTypeOfNextICQueue((XipIC)ic) == XIM_KEYSYM){
if ((keycode = XKeysymToKeycode(display,
_XipKeySymOfNextICQueue((XipIC)ic))) != 0
&& _XipStringOfNextICQueue((XipIC)ic) == NULL){
ev->xkey.state = _XipStateOfNextICQueue((XipIC)ic);
ev->xkey.keycode = keycode;
_XipFreeNextICQueue((XipIC)ic);
}
}
return(False);
}
if (ic->out) ic->out = NULL;
(void)XLookupString(ev, str, 256, &keysym, NULL);
if (keysym == NoSymbol/* || nbytes < 1 */) {
return(True);
}
if (is_nofilter(xcvt, keysym)) return(False);
if (keysym == xcvt->bs) {
if (xcvt->buf_cnt == 0) {
return(False);
}
xcvt->buf[xcvt->buf_cnt - 1].keysym = xcvt->buf[xcvt->buf_cnt].keysym;
xcvt->buf[xcvt->buf_cnt - 1].state = xcvt->buf[xcvt->buf_cnt].state;
_XipLocalClearCvt(xcvt);
if (--xcvt->buf_cnt > 0) {
key_check(xcvt);
}
return(True);
}
if (xcvt->buf_cnt == 0) {
_XipLocalClearCvt(xcvt);
}
xcvt->buf[xcvt->buf_cnt].keysym = keysym;
xcvt->buf[xcvt->buf_cnt].state = ev->xkey.state;
xcvt->buf[++xcvt->buf_cnt].keysym = XK_VoidSymbol;
bcopy((char *)ev, (char *)&dummy_ev, sizeof(XEvent));
dummy_ev.type = KeyPress;
dummy_ev.xkey.state = 0;
dummy_ev.xkey.keycode = 0;
if (xcvt->off == True) {
if ((c = off_key_check(xcvt)) == 0) {
xcvt->buf_cnt = 0;
(*xcvt->off_tbl.to.func)(xcvt);
_XipLocalClearCvt(xcvt);
return(True);
}
} else {
c = key_check(xcvt);
}
switch (c) {
case -1: /* Event was filtered */
return (True);
case -2: /* No match */
for (i = 0; i < xcvt->buf_cnt; i++) {
if (_XipPutICQueue(ic, XIM_KEYSYM, 0, xcvt->buf[i].keysym,
xcvt->buf[i].state, 0, NULL) < 0)
return(False);
}
ev->xkey.state = 0;
ev->xkey.keycode = 0;
if ((keycode = XKeysymToKeycode(display,
_XipKeySymOfNextICQueue((XipIC)ic))) != 0
&& _XipStringOfNextICQueue((XipIC)ic) == NULL) {
ev->xkey.state = _XipStateOfNextICQueue((XipIC)ic);
ev->xkey.keycode = keycode;
_XipFreeNextICQueue((XipIC)ic);
}
for (i = 1; i < xcvt->buf_cnt; i++) {
XPutBackEvent(display, &dummy_ev);
}
xcvt->buf_cnt = 0;
_XipLocalClearCvt(xcvt);
return (False);
default: /* matched */
xcvt->buf_cnt = 0;
if (xcvt->tbl[c].com == True) {
if ((*xcvt->tbl[c].to.func)(xcvt) == True) {
_XipLocalClearCvt(xcvt);
return(True);
}
}
for (i = 0; xcvt->tbl[c].to.tokey[i].keysym != XK_VoidSymbol; i++) {
if (_XipPutICQueue(ic, XIM_KEYSYM, 0,
xcvt->tbl[c].to.tokey[i].keysym,
xcvt->tbl[c].to.tokey[i].state, 1,
xcvt->tbl[c].to.tokey[i].str) < 0)
return(False);
}
ev->xkey.state = 0;
ev->xkey.keycode = 0;
if ((keycode = XKeysymToKeycode(display,
_XipKeySymOfNextICQueue((XipIC)ic))) != 0
&& _XipStringOfNextICQueue((XipIC)ic) == NULL) {
ev->xkey.state = _XipStateOfNextICQueue((XipIC)ic);
ev->xkey.keycode = keycode;
_XipFreeNextICQueue((XipIC)ic);
}
for (i = 1; xcvt->tbl[c].to.tokey[i].keysym != XK_VoidSymbol; i++) {
XPutBackEvent(display, &dummy_ev);
}
xcvt->buf_cnt = 0;
_XipLocalClearCvt(xcvt);
return(False);
}
}
/*
* Free the input context.
*/
void
_XipLocalDestroyIC(supic)
XIC supic;
{
XipLocalIC ic = (XipLocalIC)supic;
XipLocalIM im = (XipLocalIM)ic->core.im;
_XUnregisterFilter(im->core.display, ic->core.focus_window,
ic->prototype_filter, (XPointer)ic);
#ifdef XML
if (ic->xlc_num > 0) {
int i;
for (i = 0; i < ic->xlc_num; i++) {
_XlcFreeLocale(ic->mb_temp[i]);
_XlcFreeLocale(ic->wc_temp[i]);
_XipLocalFreeCvt(ic->xcvt);
}
}
if (ic->values.using_language) Xfree(ic->values.using_language);
#endif /* XML */
}
static RConst XICMethodsRec ic_methods = {
_XipLocalDestroyIC,
_XipLocalSetICFocus,
_XipLocalUnsetICFocus,
_XipLocalSetICValues,
_XipLocalGetICValues,
_XipLocalmbResetIC,
_XipLocalwcResetIC,
_XipmbLookupString,
_XipwcLookupString
};
/*
* Create an input context within the input method,
* and return a pointer the input context ti the caller.
*/
XIC
_XipLocalCreateIC(supim, args)
XIM supim;
XIMArg *args;
{
XipLocalIM im = (XipLocalIM)supim;
XipLocalIC ic;
unsigned long mask = 0L;
#ifdef XML
char **nls_list, **l;
XLocale xlc;
#endif /* XML */
if ((ic = (XipLocalIC)Xcalloc(1, sizeof(XipLocalICRec))) == NULL) {
return(NULL);
}
ic->methods = (XICMethods) &ic_methods;
ic->prototype_filter = _XipLocalBackEndFilter;
ic->core.im = supim;
(void)_XipICSetValues(ic, args, &mask);
#ifdef XML
if (im->xlc != NULL) {
#endif /* XML */
ic->mb = _XlcDupLocale(im->xlc);
ic->wc = _XlcDupLocale(im->xlc);
ic->xcvt = _XipLocalDupCvt(im->xcvt);
#ifdef XML
ic->xlc_num = 0;
ic->mb_temp = NULL;
ic->wc_temp = NULL;
ic->xcvt_temp = NULL;
} else {
ic->mb = NULL;
ic->wc = NULL;
ic->xcvt_temp = NULL;
ic->xlc_num = 0;
if ((ic->mb_temp = (XLocale*)Xmalloc(sizeof(XLocale) * 32)) == NULL) {
return(NULL);
}
if ((ic->wc_temp = (XLocale*)Xmalloc(sizeof(XLocale) * 32)) == NULL) {
return(NULL);
}
if ((ic->xcvt_temp = (XipLocalCvt**)
Xmalloc(sizeof(XipLocalCvt*) * 32)) == NULL) {
return(NULL);
}
_XlcListLocale(&nls_list);
for (l = nls_list; *l; l++) {
xlc = _XlcMakeLocale(*l);
if (!xlc)
continue;
if ((ic->xcvt_temp[ic->xlc_num] = _XipLocalCvtSetUp(xlc)) == NULL){
_XlcFreeLocale(xlc);
continue;
}
ic->mb_temp[ic->xlc_num] = xlc;
ic->wc_temp[ic->xlc_num] = _XlcDupLocale(xlc);
ic->xlc_num++;
}
Xfree((char *)nls_list);
ic->mb = ic->mb_temp[0];
ic->wc = ic->wc_temp[0];
ic->xcvt = ic->xcvt_temp[0];
}
#endif /* XML */
return((XIC)ic);
}
/*
* Reset the input context.
*/
wchar_t *
_XipLocalwcResetIC(supic)
XIC supic; /* specified the input context to reset*/
{
register XipLocalIC ic = (XipLocalIC)supic;
ic->xcvt->buf_cnt = 0;
_XipLocalClearCvt(ic->xcvt);
return((wchar_t *)NULL);
}
char *
_XipLocalmbResetIC(supic)
XIC supic; /* specified the input context to reset*/
{
register XipLocalIC ic = (XipLocalIC)supic;
ic->xcvt->buf_cnt = 0;
_XipLocalClearCvt(ic->xcvt);
return(NULL);
}
/*
* Query Input Method.
*/
static char *
_IMGetValues(im, args)
register XipLocalIM im;
register XIMArg *args;
{
register XIMArg *arg;
register int i;
register XrmName Name;
register XIMrmResourceList xrmres;
unsigned int num_resources = im->num_resources;
XrmQuark query_input =
XrmPermStringToQuark(XNQueryInputStyle);
for (arg = args; arg->name && *(arg->name); arg++) {
Name = XrmStringToName(arg->name);
for (xrmres = im->resources, i = 0;
i < num_resources; i++, xrmres++) {
if (Name == xrmres->xrm_name) {
if (Name == query_input) {
char *p;
XIMStyles *styles;
int size = sizeof(XIMStyle)
* im->values.input_styles.count_styles;
int all_size = sizeof(XIMStyles) + size;
if ((p = Xmalloc((unsigned)all_size)) == NULL) {
continue;
}
styles = (XIMStyles *)p;
styles->count_styles = im->values.input_styles.count_styles;
styles->supported_styles =
(XIMStyle *)(p + sizeof(XIMStyles));
bcopy((char *)im->values.input_styles.supported_styles,
(char *)styles->supported_styles, size);
bcopy((char *)&styles, (char *)arg->value,
sizeof(XIMStyles *));
} else {
(void) _XCopyToArg((char *)im - xrmres->xrm_offset - 1,
&arg->value,
(unsigned int)xrmres->xrm_size);
}
break;
}
}
if (i >= num_resources) return(arg->name);
}
return NULL;
}
char *
_XipLocalGetIMValues(supim, args)
XIM supim;
XIMArg *args;
{
XipLocalIM im = (XipLocalIM)supim;
return(_IMGetValues(im, args));
}
/*
* Require the input manager to focus the focus window attached to the ic
* argument.
*/
void
_XipLocalSetICFocus(supic)
XIC supic;
{
XipLocalIC ic = (XipLocalIC)supic;
XipLocalIM im = ipLocalIMofIC(ic);
_XRegisterFilterByMask(im->core.display, ic->core.focus_window,
KeyPressMask, ic->prototype_filter, (XPointer)ic);
}
/*
* Require the input manager to unfocus the focus window attached to the ic
* argument.
*/
void
_XipLocalUnsetICFocus(supic)
XIC supic;
{
XipLocalIC ic = (XipLocalIC)supic;
XipLocalIM im = ipLocalIMofIC(ic);
_XUnregisterFilter(im->core.display, ic->core.focus_window,
ic->prototype_filter, (XPointer)ic);
}
char*
_XipLocalGetICValues(supic, args)
XIC supic;
XIMArg *args;
{
XipLocalIC ic = (XipLocalIC)supic;
unsigned long mask = 0L;
return(_XipICGetValues((XipIC)ic, args, &mask, 0));
}
#ifdef XML
void
_XipLocalChangeLocale(ic, lc_name)
XipLocalIC ic;
char *lc_name;
{
XLocale xlc;
int i;
for (i = 0; i < ic->xlc_num; i++) {
if ((!strcmp(lc_name, ic->mb_temp[i]->lc_lang)) ||
(!strcmp(lc_name, ic->mb_temp[i]->xlc_db->lc_name))) {
ic->mb = ic->mb_temp[i];
ic->wc = ic->wc_temp[i];
ic->xcvt = ic->xcvt_temp[i];
return;
}
}
xlc = _XlcMakeLocale(lc_name);
if (xlc) {
if ((ic->xcvt = ic->xcvt_temp[ic->xlc_num] = _XipLocalCvtSetUp(xlc))
== NULL) {
_XlcFreeLocale(xlc);
return;
}
ic->mb = ic->mb_temp[ic->xlc_num] = xlc;
ic->wc = ic->wc_temp[ic->xlc_num] = _XlcDupLocale(xlc);
ic->xlc_num++;
}
}
#endif /* XML */
char *
_XipLocalSetICValues(supic, args)
XIC supic;
XIMArg *args;
{
XipLocalIC ic = (XipLocalIC)supic;
XipLocalIM im = ipLocalIMofIC(ic);
unsigned long mask = 0L;
Window old_focus_window;
char *err = NULL;
old_focus_window = ic->core.focus_window;
err = _XipICSetValues((XipIC)ic, args, &mask);
if (err)
return(err);
if (mask & (1L << ICFocusWindow)) {
_XUnregisterFilter(im->core.display, old_focus_window,
ic->prototype_filter, (XPointer)ic);
_XRegisterFilterByMask(im->core.display, ic->core.focus_window,
KeyPressMask,
ic->prototype_filter, (XPointer)ic);
}
#ifdef XML
if (mask & (1L << ICCurrentLanguage)) {
_XipLocalChangeLocale(ic, ic->values.current_language);
}
#endif /* XML */
return(NULL);
}