Mercurial > freewnn
diff Xwnmo/xwnmo/ximdispt.c @ 0:bbc77ca4def5
initial import
author | Yoshiki Yazawa <yaz@cc.rim.or.jp> |
---|---|
date | Thu, 13 Dec 2007 04:30:14 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Xwnmo/xwnmo/ximdispt.c Thu Dec 13 04:30:14 2007 +0900 @@ -0,0 +1,4609 @@ +/* + * $Id: ximdispt.c,v 1.2 2001/06/14 18:16:18 ura Exp $ + */ + +/* + * FreeWnn is a network-extensible Kana-to-Kanji conversion system. + * This file is part of FreeWnn. + * + * Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1999 + * + * Author: OMRON SOFTWARE Co., Ltd. <freewnn@rd.kyoto.omronsoft.co.jp> + * + * 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, 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 GNU Emacs; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Commentary: + * + * Change log: + * + * Last modified date: 8,Feb.1999 + * + * Code: + * + */ + +/* + * Author Name : Li Yuhong + * File Name : XimDispt.c + * Module Description : This module is to be corresponding to all + * protocol requests of X11R6 IM Version 1.0. + * Modification History: + * Jul 1, 1994 : initial version. + */ +#ifndef X11R5 +#include <stdio.h> +#include <X11/Xlib.h> +#ifndef NEED_EVENTS +#define NEED_EVENTS +#include <X11/Xproto.h> /* for xEvent */ +#undef NEED_EVENTS +#endif /* !NEED_EVENTS */ +#include "XIMproto.h" /* for ximICValuesReq... */ +#include "Ximprot.h" +#include "sdefine.h" +#include "xim.h" +#include "sheader.h" +#include "ext.h" + +/*--------------------------------------------------------------------* + * * + * Definition of Constant * + * * + *--------------------------------------------------------------------*/ + +/* + * name of "@im" modifier, which is compatible with R5. The reasonable name + * might be "xwnmo". + */ +#define XIM_SERVER_NAME "_XWNMO" + +#define BASE_IM_ID 0 /* valid XIMID > 0 */ +#define BUFFER_MAX 128 + +#define ICPreeditAttributes 28 /* ic attr id. */ +#define ICStatusAttributes 29 +#define ICSeparatorOfNestedList 30 + +#define XIM_EXT_SET_EVENT_MASK 128 /* extension must be >= 128 */ +#if defined(EXT_MOVE) || defined(SPOT) /* SPOT is name in Xsi R5 */ +#define XIM_EXT_MOVE 130 +#endif /* defined(EXT_MOVE) || defined(SPOT) */ + +#define NO_NEST (XIMAttrList)NULL +#define END_OF_XIMATTRLIST {0, 0, (char *)NULL, ((XIMAttrList)NULL)} + +#define XIMNoString (1L) +#define XIMNoFeedback (2L) + + +/*--------------------------------------------------------------------* + * * + * Definition of Local Data Type * + * * + *--------------------------------------------------------------------*/ + +#define PIXMAP CARD32 /* for CALLBACKS only */ + +/* + * XIM attribute structure for both IM and IC value. + */ +typedef struct _XIMAttrRec +{ + CARD16 attr_id; /* attr id */ + CARD16 type; /* type of attr */ + char *name; /* name of attr */ + struct _XIMAttrRec *nest; /* nested list */ +} +XIMAttrRec, *XIMAttrList; + +/* + * XIM client structure connected to this server. + */ +typedef struct _XIMContextRec +{ + XIMID im_id; /* IM id */ + struct _XIMContextRec *next; /* next of client */ +} +XIMContextRec, *XIMContextList; + +/* + * extension. + */ +typedef struct +{ + char *name; /* ext name */ + CARD8 major_code; /* ext major opcode */ + CARD8 minor_code; /* ext minor opcode */ +} +XIMQueryExtRec; + +#ifdef DYNAMIC_EVENT_FLOW_MODEL +/* + * just example for Dynamic Event Flow Model. + */ +typedef struct +{ + KeySym key; + KeySym modifier; + unsinged long modifier_mask; +} +TriggerKeysRec, *TriggerKeysList; + +static TriggerKeyRec trigger_keys_list[] = { + {XK_backslash, XK_Control_L, ControlMask} +} +#endif /* DYNAMIC_EVENT_FLOW_MODEL */ + + +/*--------------------------------------------------------------------* + * * + * Definition of Macro * + * * + *--------------------------------------------------------------------*/ + +/* + * assign a unique id. + */ +#define ALLOC_ID(n) (++n) + +/* + * shared CT string buffer. + */ +#define GET_SHARED_CT_BUFFER() (ct_buf) + +/* + * swap data of protocol. + */ +#define GET_CARD16(s) \ + ((CARD16)((need_byteswap() == True)? byteswap_s(s): s)) +#define GET_CARD32(s) \ + ((CARD32)((need_byteswap() == True)? byteswap_l(s): s)) + +/* + * Pad(n) for protocol data on 4-byte word boundory. + */ +#define PAD(n) ((4 - (n) % 4) % 4) + +/* + * pre-make memory for frequent allocation of Request/Reply protocol data. + */ +#define MALLOC_REQUEST(n) \ + (((n) > (sizeof buffer_request))? (CARD8 *)Malloc(n): &buffer_request[0]) +#define MALLOC_REPLY(n) \ + (((n) > (sizeof buffer_reply))? (CARD8 *)Malloc(n): &buffer_reply[0]) +#define FREE(p) \ + {if ((p) != &buffer_request[0] && (p) != &buffer_reply[0]) XFree(p);} + +#define XIM_SERIALNUMBER(serial) \ + (CARD16)(((unsigned long)serial >> 16) & 0xffff) +#define XIM_SET_SERIALNUMBER(serial) \ + (((unsigned long)serial & 0xffff) << 16) + +#define LENGTH_KEYSYM(f, k) \ + (((f)&XimLookupKeySym)? (sizeof(CARD16)+k): 0) +#define LENGTH_STRING_WITH_FLAG(f, n) \ + (((f)&XimLookupChars)? (sizeof(CARD16)+n+PAD(n)): 0) + +#define LENGTH_STRING(n) ((n > 0) ? \ + (sizeof(CARD16) + /* 2 n string length */ \ + n + /* n string */ \ + PAD(sizeof(CARD16) + n)): 0) /* p Pad(2 + n) */ +#define LENGTH_FEEDBACK(n) ((n > 0)? \ + (sizeof(CARD16) + /* 2 m byte length */ \ + sizeof(CARD16) + /* 2 unused */ \ + sizeof(CARD32) * n): 0) /* m LISTofXIMFEEDBACK */ + +#define CUR_IM_ID() (cur_x->im_id) +#define CUR_IC_ID() (cur_x->number) +#define CUR_CLIENT_EVENT() ((XEvent *)&(cur_x->cur_event)) + +#define LENGTH_TEXT(t, sl, fn) ((t == XIMTextType)? \ + (LENGTH_STRING(sl) + LENGTH_FEEDBACK(fn)): 0) +#define LENGTH_PIXMAP(t) ((t != XIMTextType)? sizeof(PIXMAP): 0) + + +/*--------------------------------------------------------------------* + * * + * Definition of Local Variable * + * * + *--------------------------------------------------------------------*/ + +static CARD8 buffer_request[BUFSIZ]; /* for protocol request */ +static CARD8 buffer_reply[BUFSIZ]; /* for protocol reply */ + +/* + * X selection atom, target and property in pre-connection. + */ +static Atom transport_target; + /* atom name of TRANSPORT target */ +static Atom locale_target; /* atom name of LOCALE target */ +static unsigned char *transport_prop; + /* string prop of TRANSPORT target */ +static unsigned char *locale_prop; /* string prop of LOCALE target */ + +/* + * comma-separated list of locales supported by this server. + */ +static unsigned char *locale_supported; + +static XIMContextList ximlist; /* list of comming IM client */ +static int cur_status; /* current protol status */ +static XIMID cur_im_id; /* current client IM id */ +static XICID cur_ic_id; /* current client IC id */ +static char cur_use_lang[BUFFER_MAX]; + /* current lang from XIM_OPEN */ + +/* + * list of IM attributes. + */ +static XIMAttrRec im_attr[] = { + {ICInputStyle, XimType_XIMStyles, XNQueryInputStyle, NO_NEST}, + END_OF_XIMATTRLIST +}; + +/* + * list of IC preedit attributes. + */ +static XIMAttrRec ic_attr_pre_area[] = { + {ICArea, XimType_XRectangle, XNArea, NO_NEST}, + {ICAreaNeeded, XimType_XRectangle, XNAreaNeeded, NO_NEST}, + {ICSpotLocation, XimType_XPoint, XNSpotLocation, NO_NEST}, + {ICColormap, XimType_CARD32, XNColormap, NO_NEST}, + {ICStdColormap, XimType_CARD32, XNStdColormap, NO_NEST}, + {ICForeground, XimType_CARD32, XNForeground, NO_NEST}, + {ICBackground, XimType_CARD32, XNBackground, NO_NEST}, + {ICBackgroundPixmap, XimType_CARD32, XNBackgroundPixmap, NO_NEST}, + {ICFontSet, XimType_XFontSet, XNFontSet, NO_NEST}, + {ICLineSpace, XimType_CARD32, XNLineSpace, NO_NEST}, + {ICCursor, XimType_CARD32, XNCursor, NO_NEST}, + {ICSeparatorOfNestedList, + XimType_SeparatorOfNestedList, + XNSeparatorofNestedList, NO_NEST}, + END_OF_XIMATTRLIST +}; + +/* + * list of IC status attributes. + */ +static XIMAttrRec ic_attr_sts_area[] = { + {ICArea, XimType_XRectangle, XNArea, NO_NEST}, + {ICAreaNeeded, XimType_XRectangle, XNAreaNeeded, NO_NEST}, + {ICColormap, XimType_CARD32, XNColormap, NO_NEST}, + {ICStdColormap, XimType_CARD32, XNStdColormap, NO_NEST}, + {ICForeground, XimType_CARD32, XNForeground, NO_NEST}, + {ICBackground, XimType_CARD32, XNBackground, NO_NEST}, + {ICBackgroundPixmap, XimType_CARD32, XNBackgroundPixmap, NO_NEST}, + {ICFontSet, XimType_XFontSet, XNFontSet, NO_NEST}, + {ICLineSpace, XimType_CARD32, XNLineSpace, NO_NEST}, + {ICCursor, XimType_CARD32, XNCursor, NO_NEST}, + {ICSeparatorOfNestedList, + XimType_SeparatorOfNestedList, + XNSeparatorofNestedList, NO_NEST}, + END_OF_XIMATTRLIST +}; + +/* + * list of IC attributes. + */ +static XIMAttrRec ic_attr[] = { + {ICInputStyle, XimType_CARD32, XNInputStyle, NO_NEST}, + {ICClientWindow, XimType_Window, XNClientWindow, NO_NEST}, + {ICFocusWindow, XimType_Window, XNFocusWindow, NO_NEST}, + {ICFilterEvents, XimType_CARD32, XNFilterEvents, NO_NEST}, + {ICPreeditAttributes, XimType_NEST, XNPreeditAttributes, ic_attr_pre_area}, + {ICStatusAttributes, XimType_NEST, XNStatusAttributes, ic_attr_sts_area}, + END_OF_XIMATTRLIST +}; + +/* + * list of extension supported. + */ +static XIMQueryExtRec extension_list[] = { + {"XIM_EXT_SET_EVENT_MASK", XIM_EXT_SET_EVENT_MASK, 0}, +#if defined(EXT_MOVE) || defined(SPOT) + {"XIM_EXT_MOVE", XIM_EXT_MOVE, 0} +#endif /* defined(EXT_MOVE) || defined(SPOT) */ +}; + +static CARD8 imattr_list[BUFSIZ]; /* packed im_attr list */ +static CARD8 icattr_list[BUFSIZ]; /* packed ic_attr list */ +static INT16 imattr_list_size; /* byte length */ +static INT16 icattr_list_size; /* byte length */ + + +/*--------------------------------------------------------------------* + * * + * Declaration of Extenal Variable and Function * + * * + *--------------------------------------------------------------------*/ + +extern XIMCmblk *cur_cblk; /* current client block */ + +extern int XmuGetHostname (); /* in SysUtil.h of Xmu */ + +/*--------------------------------------------------------------------* + * * + * Definition of Public Variable and Function * + * * + *--------------------------------------------------------------------*/ + +Atom server_id; /* atom name of this server "@im" */ + +int xim_send_nofilter (); /* used before its definition. */ + +/*--------------------------------------------------------------------* + * * + * Private Functions * + * * + *--------------------------------------------------------------------*/ + +/* + * Function Name : _WriteToClientFlush() + * Description : write data to client immediately with flush action. + * same as do_socket.c: _WriteToClient() if no flush. + * Parameter : + * p : pointer to data. + * num : byte length of data. + * Returned Value: + * >= 0 : byte length of data written to client. + * < 0 : error in writing. + */ +static int +_WriteToClientFlush (p, num) + char *p; + int num; +{ + int ret; + + if ((ret = _WriteToClient (p, num)) >= 0) + { + if (_Send_Flush () == 0) + return ret; /* success */ + } + return ret; +} + +/* + * Function Name : _XimWireToEvent() + * Description : convert xEvent to XEvent, modified from Xlibint.c: + * _XWireToEvent(). + * Parameter : + * dpy : pointer to X display. + * serial : serial number of event. + * event : pointer to data of X protocol xEvent + * re : pointer to data of XEvent, returned. + * Returned Value: + * True : conversion is successful. + * False : error. + */ +static Bool +_XimWireToEvent (dpy, serial, event, re) + register Display *dpy; /* pointer to display structure */ + register int serial; /* serial number of event */ + register xEvent *event; /* wire protocol event */ + register XEvent *re; /* pointer to where event should be reformatted */ +{ + + re->type = event->u.u.type & 0x7f; + ((XAnyEvent *) re)->serial = XIM_SET_SERIALNUMBER (serial); + ((XAnyEvent *) re)->send_event = ((event->u.u.type & 0x80) != 0); + ((XAnyEvent *) re)->display = dpy; + + /* Ignore the leading bit of the event type since it is set when a + client sends an event rather than the server. */ + + switch (event->u.u.type & 0177) + { + case KeyPress: + case KeyRelease: + { + register XKeyEvent *ev = (XKeyEvent *) re; + ev->root = event->u.keyButtonPointer.root; + ev->window = event->u.keyButtonPointer.event; + ev->subwindow = event->u.keyButtonPointer.child; + ev->time = event->u.keyButtonPointer.time; + ev->x = cvtINT16toInt (event->u.keyButtonPointer.eventX); + ev->y = cvtINT16toInt (event->u.keyButtonPointer.eventY); + ev->x_root = cvtINT16toInt (event->u.keyButtonPointer.rootX); + ev->y_root = cvtINT16toInt (event->u.keyButtonPointer.rootY); + ev->state = event->u.keyButtonPointer.state; + ev->same_screen = event->u.keyButtonPointer.sameScreen; + ev->keycode = event->u.u.detail; + } + break; + case ButtonPress: + case ButtonRelease: + { + register XButtonEvent *ev = (XButtonEvent *) re; + ev->root = event->u.keyButtonPointer.root; + ev->window = event->u.keyButtonPointer.event; + ev->subwindow = event->u.keyButtonPointer.child; + ev->time = event->u.keyButtonPointer.time; + ev->x = cvtINT16toInt (event->u.keyButtonPointer.eventX); + ev->y = cvtINT16toInt (event->u.keyButtonPointer.eventY); + ev->x_root = cvtINT16toInt (event->u.keyButtonPointer.rootX); + ev->y_root = cvtINT16toInt (event->u.keyButtonPointer.rootY); + ev->state = event->u.keyButtonPointer.state; + ev->same_screen = event->u.keyButtonPointer.sameScreen; + ev->button = event->u.u.detail; + } + break; + default: + return False; + } + return True; +} + +/* + * Function Name : _XimEventToWire() + * Description : convert XEvent to xEvent, modified from EvToWire.c: + * _XEventToWire(). + * Parameter : + * re : pointer to data of XEvent. + * event : pointer to data of X protocol xEvent, returned + * Returned Value: + * True : conversion is successful. + * False : error. + */ +static Bool +_XimEventToWire (re, event) + register XEvent *re; /* pointer to where event should be reformatted */ + register xEvent *event; /* wire protocol event */ +{ + switch (event->u.u.type = re->type) + { + case KeyPress: + case KeyRelease: + { + register XKeyEvent *ev = (XKeyEvent *) re; + event->u.keyButtonPointer.root = ev->root; + event->u.keyButtonPointer.event = ev->window; + event->u.keyButtonPointer.child = ev->subwindow; + event->u.keyButtonPointer.time = ev->time; + event->u.keyButtonPointer.eventX = ev->x; + event->u.keyButtonPointer.eventY = ev->y; + event->u.keyButtonPointer.rootX = ev->x_root; + event->u.keyButtonPointer.rootY = ev->y_root; + event->u.keyButtonPointer.state = ev->state; + event->u.keyButtonPointer.sameScreen = ev->same_screen; + event->u.u.detail = ev->keycode; + } + break; + case ButtonPress: + case ButtonRelease: + { + register XButtonEvent *ev = (XButtonEvent *) re; + event->u.keyButtonPointer.root = ev->root; + event->u.keyButtonPointer.event = ev->window; + event->u.keyButtonPointer.child = ev->subwindow; + event->u.keyButtonPointer.time = ev->time; + event->u.keyButtonPointer.eventX = ev->x; + event->u.keyButtonPointer.eventY = ev->y; + event->u.keyButtonPointer.rootX = ev->x_root; + event->u.keyButtonPointer.rootY = ev->y_root; + event->u.keyButtonPointer.state = ev->state; + event->u.keyButtonPointer.sameScreen = ev->same_screen; + event->u.u.detail = ev->button; + } + break; + default: + return False; + } + return True; +} + +/* + * get list of locale names as the format: + * "locale_1,locale_2,...,locale_n" + * and return the length of the string above. + */ +static char * +GetLocaleSupported () +{ + return (!xim->supported_language) ? "C" : xim->supported_language; +} + +/* + * Function Name : _CheckLocaleName() + * Description : check if the client locale is supported in this server. + * Parameter : + * buf : string buffer of client locale. + * loc_name : comma-separated list of locales supported in this server. + * Returned Value: + * True : it is supported. + * False : not supproted. + */ +static Bool +_CheckLocaleName (buf, loc_name) + CARD8 *buf; + char *loc_name; +{ + int str_len = (int) buf[0]; + int len; + char *ptr = (char *) locale_supported; + char *str = (char *) &buf[1]; + register char *p; + + loc_name[0] = '\0'; + for (;;) + { + for (p = ptr; ((*p != ',') && (*p)); p++); + len = (int) (p - ptr); + if ((str_len == len) && (!strncmp (str, ptr, len))) + { + (void) strncpy (loc_name, str, len); + loc_name[len] = '\0'; + return True; + } + if (!(*p)) + break; + ptr = p + 1; + } + return False; +} + +/* + * Function Name : GetIMWithId() + * Description : search a client context with IM id. + * Parameter : + * im_id : client input-method-id. + * Returned Value: + * XIMContextRec * + * : pointer to the client context found. + * NULL : not found. + */ +static XIMContextRec * +GetIMWithId (im_id) + register XIMID im_id; +{ + register XIMContextRec *im; + + for (im = ximlist; im; im = im->next) + { + if (im->im_id == im_id) + return im; + } + return (XIMContextRec *) NULL; +} + +/* + * Function Name : RemoveIMWithId() + * Description : remove a IM client context. + * Parameter : + * im_id : client input-method-id. + * Returned Value: + * True : the IM client context with im_id is removed from list + * and is freed its memory. + * False : not found with this im_id. + */ +static Bool +RemoveIMWithId (im_id) + XIMID im_id; +{ + register XIMContextRec *im, *pre_im; + + for (im = pre_im = ximlist; im; pre_im = im, im = im->next) + { + if (im->im_id == im_id) + { + if (pre_im != im) + { + pre_im->next = im->next; + } + else + { + ximlist = im->next; + } + break; + } + } + if (!im) + return False; + XFree ((char *) im); + return True; +} + +/* + * Function Name : GetICWithId() + * Description : search a client structure with IC id. + * Parameter : + * ic_id : client input-context-id. + * Returned Value: + * XIMClientRec* + * : pointer to the client structure found. + * NULL : not found. + */ +static XIMClientRec * +GetICWithId (ic_id) + register int ic_id; +{ + register XIMClientRec *xc; + + for (xc = ximclient_list; xc != NULL; xc = xc->next) + { + if (xc->number == ic_id) + return xc; + } + return (XIMClientRec *) NULL; +} + +/* + * Function Name : AddHead() + * Description : fill head data to a protocol reply which will be + * sent to client. The head data to be filed is as follows: + * CARD8 major_opcode + * CARD8 minor_opcode + * CARD16 data length in 4-byte word + * Parameter : + * reply : pointer to a protocol reply structure, which is + * to be filled head data. + * major_code : major opcode of this protocol. + * minor_code : minor opcode of this protocol. + * len : data length of protocol except head. + * Returned Value: + * > 0 : byte length of head data, always XIM_HEADER_SIZE. + */ +static int +AddHead (reply, major_code, minor_code, len) + CARD8 *reply; + CARD8 major_code; + CARD8 minor_code; + int len; +{ + CARD8 *buf_8 = reply; + CARD16 *buf_16 = (CARD16 *) (reply + sizeof (CARD8) * 2); + + buf_8[0] = major_code; + buf_8[1] = minor_code; + buf_16[0] = GET_CARD16 (len / 4); + return XIM_HEADER_SIZE; +} + +/* + * Function Name : SetClientSync() + * Description : set the client to a sync flag. + * Parameter : + * xc : pointer to a client structure. + * sync : flag of sync. + * Returned Value: + * <none> + */ +#ifdef NEED_FUNCTION + +static void +SetClientSync (xc, sync) + XIMClientRec *xc; + Bool sync; +{ + xc->sync_needed = sync; +} + +static Bool +AllSyncDone (im_id, ic_id) + XIMID im_id; + XICID im_cd; +{ + return True; +} + +static void +SyncAll (im_id, ic_id) + XIMID im_id; + XICID im_cd; +{ +} + +#else + +#define SetClientSync(xc, sync) ((xc)->sync_needed = sync) +#define AllSyncDone(im_id, ic_id) (True) +#define SyncAll(im_id, ic_id) + +#endif /* NEED_FUNCTION */ + +/* + * Function Name : ClientSyncDone() + * Description : If this client has True flag needed to do sync, do it + * and turn off the sync flag (False). + * Parameter : + * xc : pointer to a client structure. + * Returned Value: + * True : yes, sync has done. + * False : no sync. + */ +static Bool +ClientSyncDone (xc) + XIMClientRec *xc; +{ + Bool sync_done; + + sync_done = xc->sync_needed; + xc->sync_needed = False; + return sync_done; +} + +/* + * Function Name : GetAuth() + * Description : get names of authentification from IM library. + * Parameter : + * list : buffer list. + * num : number of list elements. + * length : byte length of buffer list. + * names_returned + * : auth name returned. + * Returned Value: + * True : successed. + * False : wrong auth name. + */ + + /*ARGSUSED*/ static Bool +GetAuth (list, num, length, names_return) + CARD8 *list; + int num; + int length; + char *names_return; +{ + /* it is free authentification so far. */ + return True; +} + +/* + * Function Name : CreateAttrList() + * Description : pack IM/IC attribute list to a compact data. + * Parameter : + * table : list of IM/IC attributes, end with the empty name. + * list : returned data that contains packed list of attribute. + * Returned Value: + * >= 0 : byte length of packed list. + */ +static int +CreateAttrList (table, list) + XIMAttrList table; + CARD8 *list; +{ + CARD16 *buf_16; + INT16 total = 0; + int len, i; + + for (i = 0; table[i].name; i++) + { + buf_16 = (CARD16 *) list; + len = strlen (table[i].name); + buf_16[0] = GET_CARD16 (table[i].attr_id); /* 2 attr ID */ + buf_16[1] = GET_CARD16 (table[i].type); /* 2 type */ + buf_16[2] = GET_CARD16 (len); /* 2 length */ + memcpy ((char *) &buf_16[3], table[i].name, len); /* n attr */ + len = sizeof (CARD16) + sizeof (CARD16) + sizeof (CARD16) + len + PAD (len + 2); + list += len; + total += len; + if (table[i].nest) + { + len = CreateAttrList (table[i].nest, list); + list += len; + total += len; + } + } + return total; +} + +/* + * Function Name : InitiateProtocol() + * Description : do some initial works. + * Parameter : + * <none> + * Returned Value: + * <none> + */ +static void +InitiateProtocol () +{ + ximlist = (XIMContextList) NULL; + + imattr_list_size = CreateAttrList (im_attr, imattr_list); + icattr_list_size = CreateAttrList (ic_attr, icattr_list); +} + +/* + * Function Name : CheckInputStyle() + * Description : check if the passed input style is supported. + * Parameter : + * input_style : the input style to be checked. + * Returned Value: + * True : supported. + * False : not supported. + */ +static Bool +CheckInputStyle (input_style) + INT32 input_style; +{ + int i; + + for (i = 0; i < MAX_SUPPORT_STYLE; i++) + { + if (xim->supported_style[i] == input_style) + { + return True; + } + } + return False; +} + +/* + * Function Name : ConvErrorCode() + * Description : convert error code used in Xsi R5 IM to R6 IM. + * Parameter : + * x11r5_code : error code of Xsi R5 IM. + * Returned Value: + * > 0 : errro code of R6 IM + */ +static int +ConvErrorCode (x11r5_code) + short x11r5_code; +{ + switch (x11r5_code) + { + case AllocError: + return XIM_BadAlloc; + case BadStyle: + return XIM_BadStyle; + case BadClientWindow: + return XIM_BadClientWindow; + case BadFocusWindow: + return XIM_BadFocusWindow; + case BadLanguage: + return XIM_LocaleNotSupported; + case BadSpotLocation: + return XIM_BadSpotLocation; + case BadFontSet: + return XIM_BadName; /* or XIM_BadStyle */ + default: + return XIM_BadSomething; + } +} + +/* + * Function Name : ConvAreaAttr() + * Description : convert byte data to IC attribute of Area. + * Parameter : + * value : the byte data. + * size : byte length of the data. + * ic_attr_req : contain Area attribute to be filled. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +ConvAreaAttr (value, size, ic_attr_req) + CARD8 *value; + int size; + ximICAttributesReq *ic_attr_req; +{ + CARD16 *buf_16 = (CARD16 *) value; + + if (size != (sizeof (CARD16) << 2)) + return XIM_BadAlloc; + + ic_attr_req->area_x = (INT16) GET_CARD16 (buf_16[0]); + ic_attr_req->area_y = (INT16) GET_CARD16 (buf_16[1]); + ic_attr_req->area_width = GET_CARD16 (buf_16[2]); + ic_attr_req->area_height = GET_CARD16 (buf_16[3]); + return 0; +} + +/* + * Function Name : ConvAreaNeededAttr() + * Description : convert byte data to IC attribute of AreaNeeded. + * Parameter : + * value : the byte data. + * size : byte length of the data. + * ic_attr_req : contain AreaNeeded attribute to be filled. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +ConvAreaNeededAttr (value, size, ic_attr_req) + CARD8 *value; + int size; + ximICAttributesReq *ic_attr_req; +{ + CARD16 *buf_16 = (CARD16 *) value; + + if (size != (sizeof (CARD16) << 2)) + return XIM_BadAlloc; + + ic_attr_req->areaneeded_width = GET_CARD16 (buf_16[2]); + ic_attr_req->areaneeded_height = GET_CARD16 (buf_16[3]); + return 0; +} + +/* + * Function Name : ConvSpotAttr() + * Description : convert byte data to IC attribute of Spot. + * Parameter : + * value : the byte data. + * size : byte length of the data. + * ic_attr_req : contain Spot attribute to be filled. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +ConvSpotAttr (value, size, ic_attr_req) + CARD8 *value; + int size; + ximICAttributesReq *ic_attr_req; +{ + CARD16 *buf_16 = (CARD16 *) value; + + if (size != (sizeof (CARD16) + sizeof (CARD16))) + return XIM_BadAlloc; + + ic_attr_req->spot_x = (INT16) GET_CARD16 (buf_16[0]); + ic_attr_req->spot_y = (INT16) GET_CARD16 (buf_16[1]); + return 0; +} + +/* + * Function Name : ConvFontSetAttr() + * Description : convert byte data to IC attribute of FontSet name. + * Parameter : + * value : the byte data. + * size : byte length of the data. + * ic_attr_req : contain FontSet attribute to be filled. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +ConvFontSetAttr (value, size, base_font_name) + CARD8 *value; + int size; + char **base_font_name; +{ + CARD16 *buf_16 = (CARD16 *) value; + char *fname; + int len; + + len = (int) GET_CARD16 (buf_16[0]); + if (len > size) + return XIM_BadAlloc; + if (!(fname = Malloc (len + 1))) + return XIM_BadAlloc; + (void) strncpy (fname, (char *) &buf_16[1], len); + fname[len] = '\0'; + *base_font_name = fname; + return 0; +} + +/* + * Function Name : DecodeICNestedAttributes() + * Description : decode IC nested attributes + * Parameter : + * list : list of IC attribute, packed data. + * size : byte length of list. + * ic_attr_req : IC attribute structure to be filled. + * font : base font name to be returned. The caller should + * free it after use. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +DecodeICNestedAttributes (list, size, mask, ic_attr_req, font) + CARD8 *list; + int size; + CARD32 *mask; + ximICAttributesReq *ic_attr_req; + char **font; +{ + CARD16 *buf_16; + CARD32 *buf_32; + CARD32 mask_base, mask_ret; + int ret, have_more; + int len, tmpl, attr_id; + + ret = 0; + mask_base = *mask; + mask_ret = 0; + have_more = 1; + while (size > 0 && have_more) + { + buf_16 = (CARD16 *) list; + attr_id = (int) GET_CARD16 (buf_16[0]); /* 2 attribute id */ + len = (int) GET_CARD16 (buf_16[1]); /* n length of value */ + tmpl = sizeof (CARD16) + sizeof (CARD16); + list += tmpl; + size -= tmpl; + buf_16 = (CARD16 *) list; + buf_32 = (CARD32 *) list; + switch (attr_id) + { + case ICArea: + mask_ret |= (1 << (ICArea + mask_base)); + ret = ConvAreaAttr (list, len, ic_attr_req); + break; + case ICAreaNeeded: + mask_ret |= (1 << (ICAreaNeeded + mask_base)); + ret = ConvAreaNeededAttr (list, len, ic_attr_req); + break; + case ICSpotLocation: + mask_ret |= (1 << (ICSpotLocation + mask_base)); + ret = ConvSpotAttr (list, len, ic_attr_req); + break; + case ICColormap: + mask_ret |= (1 << (ICColormap + mask_base)); + ic_attr_req->colormap = (Colormap) GET_CARD32 (buf_32[0]); + break; + case ICStdColormap: + mask_ret |= (1 << (ICStdColormap + mask_base)); + ic_attr_req->std_colormap = (Atom) GET_CARD32 (buf_32[0]); + break; + case ICForeground: + mask_ret |= (1 << (ICForeground + mask_base)); + ic_attr_req->foreground = GET_CARD32 (buf_32[0]); + break; + case ICBackground: + mask_ret |= (1 << (ICBackground + mask_base)); + ic_attr_req->background = GET_CARD32 (buf_32[0]); + break; + case ICBackgroundPixmap: + mask_ret |= (1 << (ICBackgroundPixmap + mask_base)); + ic_attr_req->pixmap = (Pixmap) GET_CARD32 (buf_32[0]); + break; + case ICFontSet: + mask_ret |= (1 << (ICFontSet + mask_base)); + ret = ConvFontSetAttr (list, len, font); + break; + case ICLineSpace: + mask_ret |= (1 << (ICLineSpace + mask_base)); + ic_attr_req->line_space = (INT16) GET_CARD32 (buf_32[0]); + break; + case ICCursor: + mask_ret |= (1 << (ICCursor + mask_base)); + ic_attr_req->cursor = (Cursor) GET_CARD32 (buf_32[0]); + break; + case ICSeparatorOfNestedList: + have_more = 0; + break; + default: + have_more = 0; + continue; + } + if (ret) + return ret; + len = len + /* n value */ + PAD (len); /* p Pad(n) */ + list += len; + size -= len; + } + *mask = mask_ret; + return 0; +} + +/* + * Function Name : DecodeICAttributes() + * Description : parse all IC attributes + * Parameter : + * list : list of IC attributes, packed data. + * size : byte length of list. + * ic_attr_req : IC attribute structure to be filled. + * pre_req : preedit attributes to be filled. + * st_req : status attributes to be filled. + * pre_font : preedit base font name to be returned. The caller should + * free it after use. + * st_font : status base font name to be returned. The caller should + * free it after use. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +DecodeICAttributes (list, size, ic_req, pre_req, st_req, pre_font, st_font) + CARD8 *list; + int size; + ximICValuesReq *ic_req; + ximICAttributesReq *pre_req; + ximICAttributesReq *st_req; + char **pre_font; + char **st_font; +{ + CARD16 *buf_16; + CARD32 *buf_32; + CARD32 mask; + int ret, len, attr_id; + int tmpl; + + ret = 0; + ic_req->mask = (CARD32) 0; + while (size > 0) + { + buf_16 = (CARD16 *) list; + attr_id = (int) GET_CARD16 (buf_16[0]); + len = (int) GET_CARD16 (buf_16[1]); + tmpl = sizeof (CARD16) + /* 2 attribute id */ + sizeof (CARD16); /* 2 value length */ + list += tmpl; + size -= tmpl; + buf_16 = (CARD16 *) list; + buf_32 = (CARD32 *) list; + switch (attr_id) + { + case ICInputStyle: + ic_req->mask |= (1 << ICInputStyle); + ic_req->input_style = (INT32) GET_CARD32 (buf_32[0]); + break; + case ICClientWindow: + ic_req->mask |= (1 << ICClientWindow); + ic_req->c_window = (Window) GET_CARD32 (buf_32[0]); + break; + case ICFocusWindow: + ic_req->mask |= (1 << ICFocusWindow); + ic_req->focus_window = (Window) GET_CARD32 (buf_32[0]); + break; + case ICFilterEvents: + ic_req->mask |= (1 << ICFilterEvents); + ic_req->filter_events = GET_CARD32 (buf_32[0]); + break; + case ICPreeditAttributes: + mask = 0; + ret = DecodeICNestedAttributes (list, len, &mask, pre_req, pre_font); + ic_req->mask |= mask; + break; + case ICStatusAttributes: + mask = StatusOffset; + ret = DecodeICNestedAttributes (list, len, &mask, st_req, st_font); + ic_req->mask |= mask; + break; + default: + ret = XIM_BadProtocol; + break; + } + if (ret) + return ret; + len = len + /* n value */ + PAD (len); /* p Pad(n) */ + list += len; + size -= len; + } + return 0; +} + +/* + * Function Name : SetClientICValues() + * Description : set IC values to a client structure. + * Parameter : + * list : list of IC attributes, packed data. + * size : byte length of list. + * xc : pointer to client structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +SetClientICValues (list, size, xc) + CARD8 *list; + int size; + XIMClientRec *xc; +{ + ximICValuesReq ic_req; + ximICAttributesReq pre_req, st_req; + XIMNestLangRec *p = (XIMNestLangRec *) NULL; + char *pre_font = (char *) NULL; + char *st_font = (char *) NULL; + int cur_is_world = 0; + int ret; + short detail; + extern int change_client (); + + /* parse IC attributes */ + ret = DecodeICAttributes (list, size, &ic_req, &pre_req, &st_req, &pre_font, &st_font); + if (ret) + return ret; + + /* refer to util: ChangeIC() */ + + ret = change_client (xc, &ic_req, &pre_req, &st_req, p, cur_is_world, pre_font, st_font, &detail); + if (pre_font) + XFree (pre_font); + if (st_font) + XFree (st_font); + if (p) + free_langlist (p); + if (ret == -1) + return ConvErrorCode (detail); + return 0; +} + +/* + * Function Name : EncodeRectangleAttr() + * Description : encode XRectangle to byte data. + * Parameter : + * rect : pointer to the rectangle structure. + * value : encoded byte data. + * size_return : returned byte length of the data. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +EncodeRectangleAttr (rect, value, size_return) + XRectangle *rect; + CARD8 *value; + int *size_return; +{ + CARD16 *buf_16 = (CARD16 *) value; + + buf_16[0] = GET_CARD16 (rect->x); + buf_16[1] = GET_CARD16 (rect->y); + buf_16[2] = GET_CARD16 (rect->width); + buf_16[3] = GET_CARD16 (rect->height); + *size_return = sizeof (CARD16) + /* 2 X */ + sizeof (CARD16) + /* 2 Y */ + sizeof (CARD16) + /* 2 width */ + sizeof (CARD16); /* 2 height */ + return 0; +} + +/* + * Function Name : EncodePointAttr() + * Description : encode XPoint to byte data. + * Parameter : + * rect : pointer to the XPoint structure. + * value : encoded byte data. + * size_return : returned byte length of the data. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +EncodePointAttr (xc, value, size_return) + XIMClientRec *xc; + CARD8 *value; + int *size_return; +{ + CARD16 *buf_16 = (CARD16 *) value; + short spot_x, spot_y; + + spot_x = xc->point.x; + spot_y = xc->point.y + FontAscent (xc->cur_xl); + buf_16[0] = GET_CARD16 (spot_x); + buf_16[1] = GET_CARD16 (spot_y); + *size_return = sizeof (CARD16) + /* 2 X */ + sizeof (CARD16); /* 2 Y */ + return 0; +} + +/* + * Function Name : EncodeFontSetAttr() + * Description : encode name of base font set to byte data. + * Parameter : + * rect : pointer to the name. + * value : encoded byte data. + * size_return : returned byte length of the data. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +EncodeFontSetAttr (base_font_name, value, size_return) + char *base_font_name; + CARD8 *value; + int *size_return; +{ + CARD16 *buf_16 = (CARD16 *) value; + int len; + + len = strlen ((char *) base_font_name); + buf_16[0] = GET_CARD16 (len); + (void) strncpy ((char *) &buf_16[1], (char *) base_font_name, len); + *size_return = sizeof (CARD16) + len + PAD (sizeof (CARD16) + len); + return 0; +} + +/* + * Function Name : EncodeICNestedAttributes() + * Description : encode IC nested attribute structure to byte data. + * Parameter : + * attr_id_list: list of IC attribute id. + * size : byte lenth of the list. + * xc : pointer to client structure. + * ic_attr : pointer to IC nested attribute structure. + * value : encoded byte data. + * size_return : returned byte length of the data. + * num_return : returned number of IC attributes. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +EncodeICNestedAttributes (attr_id_list, size, xc, ic_attr, value, size_return, num_return) + CARD8 *attr_id_list; + int size; + XIMClientRec *xc; + XIMAttributes *ic_attr; + CARD8 *value; + int *size_return; + int *num_return; +{ + CARD8 *data; + CARD16 *buf_16; + CARD32 *buf_32; + int ret, len, total, num, attr_id; + int have_more; + + ret = 0; + total = num = 0; + have_more = 1; + while (size > 0 && have_more) + { + buf_16 = (CARD16 *) attr_id_list; + attr_id = (int) GET_CARD16 (buf_16[0]); + data = value + sizeof (CARD16) + sizeof (CARD16); + buf_16 = (CARD16 *) data; + buf_32 = (CARD32 *) data; + switch (attr_id) + { + case ICArea: + ret = EncodeRectangleAttr (&(ic_attr->area), data, &len); + break; + case ICAreaNeeded: + ret = EncodeRectangleAttr (&(ic_attr->area_needed), data, &len); + break; + case ICSpotLocation: + ret = EncodePointAttr (xc, data, &len); + break; + case ICColormap: + len = sizeof (CARD32); + buf_32[0] = GET_CARD32 (ic_attr->colormap); + break; + case ICStdColormap: + len = sizeof (CARD32); + buf_32[0] = GET_CARD32 (ic_attr->std_colormap); + break; + case ICForeground: + len = sizeof (CARD32); + buf_32[0] = GET_CARD32 (ic_attr->fg); + break; + case ICBackground: + len = sizeof (CARD32); + buf_32[0] = GET_CARD32 (ic_attr->bg); + break; + case ICBackgroundPixmap: + len = sizeof (CARD32); + buf_32[0] = GET_CARD32 (ic_attr->bg_pixmap); + break; + case ICFontSet: + ret = EncodeFontSetAttr (ic_attr->fontset, data, &len); + break; + case ICLineSpace: + len = sizeof (CARD32); + buf_32[0] = GET_CARD32 (ic_attr->line_space); + break; + case ICCursor: + len = sizeof (CARD32); + buf_32[0] = GET_CARD32 (ic_attr->cursor); + break; + case ICSeparatorOfNestedList: + len = 0; + have_more = 0; + break; + default: + have_more = 0; + continue; + } + if (ret) + return ret; + buf_16 = (CARD16 *) value; + buf_16[0] = GET_CARD16 (attr_id); + buf_16[1] = GET_CARD16 (len); + len = sizeof (CARD16) + /* 2 attribute-id */ + sizeof (CARD16) + /* 2 byte length of value */ + len + /* n value */ + PAD (len); /* p Pad(n) */ + value += len; + total += len; + attr_id_list += sizeof (CARD16); + size -= sizeof (CARD16); + num++; + } + *size_return = total; + *num_return = num; + return 0; +} + +/* + * Function Name : EncodeICAttributes() + * Description : encode IC attribute structure to byte data. + * Parameter : + * attr_id_list: list of IC attribute id. + * size : byte lenth of the list. + * xc : pointer to client structure. + * value : encoded byte data. + * size_return : returned byte length of the data. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +EncodeICAttributes (attr_id_list, size, xc, value, size_return) + CARD8 *attr_id_list; + int size; + XIMClientRec *xc; + CARD8 *value; + int *size_return; +{ + CARD8 *data; + CARD16 *buf_16; + CARD32 *buf_32; + int ret, len, total, attr_id, num; + int nested_size; + + ret = 0; + total = 0; + while (size > 0) + { + buf_16 = (CARD16 *) attr_id_list; + attr_id = (int) GET_CARD16 (buf_16[0]); + data = value + sizeof (CARD16) + sizeof (CARD16); + buf_16 = (CARD16 *) data; + buf_32 = (CARD32 *) data; + switch (attr_id) + { + case ICInputStyle: + len = sizeof (CARD32); + buf_32[0] = GET_CARD32 (xc->input_style); + break; + case ICClientWindow: + len = sizeof (CARD32); + buf_32[0] = GET_CARD32 (xc->w); + break; + case ICFocusWindow: + len = sizeof (CARD32); + buf_32[0] = GET_CARD32 (xc->focus_window); + break; + case ICFilterEvents: + len = sizeof (CARD32); + buf_32[0] = GET_CARD32 (xc->filter_events); + break; + case ICPreeditAttributes: + ret = EncodeICNestedAttributes ((attr_id_list + sizeof (CARD16)), (size - sizeof (CARD16)), xc, &(xc->pe), data, &len, &num); + if (!ret) + { + nested_size = sizeof (CARD16) * num; + attr_id_list += nested_size; + size -= nested_size; + } + break; + case ICStatusAttributes: + ret = EncodeICNestedAttributes ((attr_id_list + sizeof (CARD16)), (size - sizeof (CARD16)), xc, &(xc->st), data, &len, &num); + if (!ret) + { + nested_size = sizeof (CARD16) * num; + attr_id_list += nested_size; + size -= nested_size; + } + break; + default: + ret = XIM_BadProtocol; + } + if (ret) + return ret; + buf_16 = (CARD16 *) value; + buf_16[0] = GET_CARD16 (attr_id); + buf_16[1] = GET_CARD16 (len); + len = sizeof (CARD16) + /* 2 attribute-id */ + sizeof (CARD16) + /* 2 byte length of value */ + len + /* n value */ + PAD (len); /* p Pad(n) */ + value += len; + total += len; + attr_id_list += sizeof (CARD16); + size -= sizeof (CARD16); + } + *size_return = total; + return 0; +} + +/* + * Function Name : DecodeIMAttributes() + * Description : decode IM attributes. + * Parameter : + * list : list of IM attribute, packed data. + * size : byte length of list. + * extension : not used. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ + /*ARGSUSED*/ static int +DecodeIMAttributes (list, size, extension) + CARD8 *list; + int size; + XPointer extension; /* for extenstion in future */ +{ + CARD16 *buf_16; + int ret, len, attr_id; + + ret = 0; + while (size > 0) + { + buf_16 = (CARD16 *) list; + attr_id = (int) GET_CARD16 (buf_16[0]); + len = (int) GET_CARD16 (buf_16[1]); + switch (attr_id) + { + case ICInputStyle: + /* we don't allow to set InputStyle so far. */ + ret = XIM_BadStyle; + break; + default: + /* no more supported so far */ + ret = XIM_BadSomething; + } + if (ret) + return ret; + len += sizeof (CARD16) + /* 2 attribute-id */ + sizeof (CARD16) + /* 2 n byte lenght of attr */ + len + /* n value of attr */ + PAD (len); /* p Pad(n) */ + list += len; + size -= len; + } + return 0; +} + +/* + * Function Name : SetClientIMValues() + * Description : decode IM values to client context. + * Parameter : + * value : IM values, packed data. + * size : byte length of list. + * im : client IM context. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +SetClientIMValues (value, size, im) + CARD8 *value; + int size; + XIMContextRec *im; +{ + /* no any attribute can be set so far */ + return DecodeIMAttributes (value, size, (XPointer) NULL); +} + +/* + * Function Name : EncodeInputStyleList() + * Description : encode Input Style list to byte data. + * Parameter : + * im : pointer to client IM context. + * value : encoded byte data. + * size_return : returned byte length of the data. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +EncodeInputStyleList (im, value, size_return) + XIMContextRec *im; + CARD8 *value; + int *size_return; +{ + CARD16 *buf_16 = (CARD16 *) value; + CARD32 *buf_32 = (CARD32 *) & buf_16[2]; + int num, i; + + num = MAX_SUPPORT_STYLE - 1; + buf_16[0] = GET_CARD16 (num); + for (i = 0; i <= num; i++) + { + buf_32[i] = GET_CARD32 (xim->supported_style[i]); + } + *size_return = sizeof (CARD16) + /* 2 number of list */ + sizeof (CARD16) + /* 2 unused */ + sizeof (CARD32) * MAX_SUPPORT_STYLE; + return 0; +} + +/* + * Function Name : EncodeIMAttributes() + * Description : encode IM attribute structure to byte data. + * Parameter : + * attr_id_list: list of attribute id. + * size : byte length of the list. + * im : pointer to client IM context. + * value : encoded byte data. + * size_return : returned byte length of the data. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +EncodeIMAttributes (attr_id_list, size, im, value, size_return) + CARD8 *attr_id_list; + int size; + XIMContextRec *im; + CARD8 *value; + int *size_return; +{ + CARD8 *data; + CARD16 *buf_16; + int ret, len, total, attr_id; + + ret = 0; + total = 0; + while (size > 0) + { + buf_16 = (CARD16 *) attr_id_list; + attr_id = (int) GET_CARD16 (buf_16[0]); + data = value + sizeof (CARD16) + sizeof (CARD16); + switch (attr_id) + { + case ICInputStyle: + ret = EncodeInputStyleList (im, data, &len); + break; + default: + ret = XIM_BadSomething; + } + if (ret) + return ret; + buf_16 = (CARD16 *) value; + buf_16[0] = GET_CARD16 (attr_id); + buf_16[1] = GET_CARD16 (len); + len = sizeof (CARD16) + /* 2 attribute-id */ + sizeof (CARD16) + /* 2 byte length of value */ + len + /* n value */ + PAD (len); /* p Pad(n) */ + value += len; + total += len; + attr_id_list += sizeof (CARD16); + size -= sizeof (CARD16); + } + *size_return = total; + return 0; +} + +/* + * Function Name : CreateClientIC() + * Description : create an IC context and assign a new IC id. + * Parameter : + * im_id : client input-method-id. + * list : list of IC attributes, packed data. + * size : byte length of list. + * ic_id_return: new IC id of the create IC context. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +CreateClientIC (im_id, list, size, ic_id_return) + XIMID im_id; + CARD8 *list; + int size; + XICID *ic_id_return; +{ + XIMClientRec *xc; + ximICValuesReq ic_req; + ximICAttributesReq pre_req, st_req; + char *pre_font = (char *) NULL; + char *st_font = (char *) NULL; + XIMNestLangList lc_list = (XIMNestLangList) NULL; + XIMNestLangList cur_lc = (XIMNestLangList) NULL; + XIMNestLangList p; + int have_world = 0, cur_is_world = 0; + char *use_langs, *cur_l, *c_data; + int xic, ret, i; + short detail; + extern XIMClientRec *create_client (); + + /* + * parse attributes + */ + ret = DecodeICAttributes (list, size, &ic_req, &pre_req, &st_req, &pre_font, &st_font); + if (ret) + return ret; + ic_req.max_keycode = 0; /* set 0 as default */ + + use_langs = cur_use_lang; /* use locale from XIM_OPEN */ + cur_l = (char *) NULL; /* current lang not specified yet. */ + c_data = (char *) NULL; /* default user name. */ + + /* refer to util.c: CreateIC() */ + + /* + * check resources. + */ + if (CheckInputStyle (ic_req.input_style) == False) + return XIM_BadStyle; + if ((ic_req.input_style & (XIMPreeditArea | XIMPreeditPosition)) && (!(ic_req.mask & (1 << ICFontSet)) || !pre_font || !*pre_font)) + return XIM_BadName; + if ((ic_req.input_style & XIMStatusArea) && (!(ic_req.mask & (1 << (ICFontSet + StatusOffset))) || !st_font || !*st_font)) + return XIM_BadName; + if ((ic_req.input_style & XIMPreeditPosition) && (!(ic_req.mask & (1 << ICSpotLocation)))) + return XIM_BadSpotLocation; + if (!(ic_req.input_style & XIMPreeditNothing)) + { + if ((have_world = get_langlist (use_langs, &lc_list)) < 0) + { + return XIM_BadAlloc; + } + if (!lc_list) + { + return XIM_LocaleNotSupported; + } + if (cur_l && *cur_l) + { + for (p = lc_list; p != NULL; p = p->next) + { + if (!strcmp (p->lc_name, cur_l) || (p->alias_name && !strcmp (p->alias_name, cur_l))) + break; + } + if (p == NULL) + { + if ((i = get_langlist (cur_l, &cur_lc)) < 0) + { + return XIM_BadAlloc; + } + else if (i > 0) + { + cur_is_world++; + free_langlist (cur_lc); + cur_lc = lc_list; + } + else + { + if (cur_lc) + { + cur_lc->next = lc_list; + } + else + { + cur_lc = lc_list; + } + } + } + else + { + cur_lc = p; + } + } + else + { + if (have_world == 2) + cur_is_world++; + cur_lc = lc_list; + } + } + xc = create_client (&ic_req, &pre_req, &st_req, lc_list, cur_lc, have_world, cur_is_world, pre_font, st_font, c_data, &detail); + if (pre_font) + XFree (pre_font); + if (st_font) + XFree (st_font); + if (lc_list) + free_langlist (lc_list); + if (!xc) + { + return ConvErrorCode (detail); + } + xic = xim->client_count++; + xc->number = xic; + xc->im_id = (int) im_id; + if (IsPreeditNothing (xc)) + { + check_root_mapping (xc->root_pointer); + } + + *ic_id_return = (XICID) xic; + return 0; +} + +/* + * Function Name : CreateIM() + * Description : create a new IM context and register in the list. + * Parameter : + * <none> + * Returned Value: + * > 0 : IM id of the new IM context created. + * = 0 : error + */ +static XIMID +CreateIM () +{ + static XIMID base_im_id = BASE_IM_ID; + XIMContextRec *im; + + im = (XIMContextRec *) Malloc (sizeof (XIMContextRec)); + if (!im) + { + malloc_error ("no memory to open an IM"); + return 0; + } + im->im_id = ALLOC_ID (base_im_id); + + /* add to IM list */ + im->next = ximlist; + ximlist = im; + return im->im_id; +} + +/* + * Function Name : GetCompoundTextIndex() + * Description : search the index of string named COMPOUND_TEXT in + * LISTofSTR. + * Parameter : + * list : list of string names LISTofSTR. + * size : byte length of the list. + * Returned Value: + * int : returned index in this list. If not found, it is + * the default XIM_Default_Encoding_IDX. + */ +static int +GetCompoundTextIndex (list, size) + register CARD8 *list; + register int size; +{ + register int index, len; + + /* get index of COMPOUNT_TEXT which is only supported by us. */ + index = 0; + while (size > 0) + { + len = (int) list[0]; + if (!strncmp (&list[1], "COMPOUND_TEXT", len)) + break; + index++; + list += (sizeof (CARD8) + len); + size -= (sizeof (CARD8) + len); + }; + if (size == 0) + index = XIM_Default_Encoding_IDX; /* use default */ + return index; +} + +/* + * Function Name : FindExtensionByName() + * Description : search an extension item with its name in extension + * list supported by this server. + * Parameter : + * name : ext string name. + * len : length of ext name. + * Returned Value: + * >= 0 : found item index to this list. + * = -1 : not found. + */ +static int +FindExtensionByName (name, len) + char *name; + int len; +{ + int ind; + + for (ind = 0; ind < XIMNumber (extension_list); ind++) + { + if (!strncmp (extension_list[ind].name, name, len)) + return ind; + } + return -1; +} + +/* + * Function Name : EncodeExtension() + * Description : encode an extension item to byte data. + * Parameter : + * ind : the item index to extension list. + * value : byte data to store the packed ext item. + * size_return : returned byte size of the packed ext item + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +EncodeExtension (ind, value, size_return) + int ind; + CARD8 *value; + int *size_return; +{ + CARD16 *buf_16 = (CARD16 *) & value[2]; + int len; + + len = strlen (extension_list[ind].name); + value[0] = extension_list[ind].major_code; + value[1] = extension_list[ind].minor_code; + buf_16[0] = GET_CARD16 (len); + (void) strncpy ((char *) &buf_16[1], extension_list[ind].name, len); + *size_return = sizeof (CARD8) + /* 1 major_code */ + sizeof (CARD8) + /* 1 minor_code */ + sizeof (CARD16) + /* 2 n length of name */ + len + /* n name */ + PAD (len); /* p Pad(n) */ + return 0; +} + +/* + * Function Name : GetExtensionList() + * Description : get extensions supported by the server. + * Parameter : + * list : list of extension names asked by client. + * size : byte length of the list, if it is zero, client asks + * all extensions supported by the server. + * value : the returned exension names supported by server. It is + * packed in byte. + * size_return : returned byte size of the packed ext names. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +GetExtensionList (list, size, value, size_return) + CARD8 *list; + int size; + CARD8 *value; + int *size_return; +{ + int len, ext_len, ind, total; + + total = 0; + if (size == 0) + { + for (ind = 0; ind < XIMNumber (extension_list); ind++) + { + (void) EncodeExtension (ind, value, &ext_len); + value += ext_len; + total += ext_len; + } + } + else + { + while (size > 0) + { + len = (int) list[0]; + if ((ind = FindExtensionByName ((char *) &list[1], len)) >= 0) + { + (void) EncodeExtension (ind, value, &ext_len); + value += ext_len; + total += ext_len; + } + list += (sizeof (CARD8) + len); + size -= (sizeof (CARD8) + len); + } + } + *size_return = total; + return 0; +} + +/* + * Function Name : RecvRequest() + * Description : receive a request of XIM protocol from IM library. + * Parameter : + * req : pointer to a request structure, returned. + * Returned Value: + * >=0 : byte length of request data except request head. + * < 0 : error in reading data. + */ +static int +RecvRequest (req) + XimRequestPacket *req; +{ + CARD8 *buf, *read_ptr; + CARD8 byteOrder; + int read_size; + extern char my_byteOrder; + + if (_ReadFromClient ((char *) req, XIM_HEADER_SIZE) == -1) + return -1; + if (req->length == 0) + return 0; + read_size = req->length * 4; + read_ptr = buf = MALLOC_REQUEST (read_size); + bzero ((char *) buf, read_size); + if (req->major_opcode == XIM_CONNECT) + { + _ReadFromClient ((char *) &byteOrder, 1); + if (my_byteOrder != (char) byteOrder) + cur_cblk->byteOrder = True; + else + cur_cblk->byteOrder = False; + buf[0] = byteOrder; + read_ptr = &buf[1]; + read_size--; + } + if (_ReadFromClient (read_ptr, read_size) == -1) + { + FREE (buf); + return -1; + } + req->data = buf; + return req->length * 4; +} + +/* + * Function Name : SendIdOnly() + * Description : send a request that is the format of: + * CARD16 input-method-id + * CARD16 input-context-id + * Parameter : + * im_id : client input-method-id. + * ic_id : client input-context-id. + * major_code : major opcode of this request. + * minor_code : minor opcode of this request. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +SendIdOnly (im_id, ic_id, major_code, minor_code) + XIMID im_id; + XICID ic_id; + CARD8 major_code; + CARD8 minor_code; +{ + CARD16 *buf_16; + CARD8 *reply; + int len; + + /* reply */ + len = sizeof (CARD16) + /* 2 input-method-ID */ + sizeof (CARD16); /* 2 input-context-ID */ + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, major_code, minor_code, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (im_id); + buf_16[1] = GET_CARD16 (ic_id); + if (_WriteToClientFlush (reply, len) < 0) + { + FREE (reply); + return XIM_BadSomething; + } + FREE (reply); + return 0; +} + +/* + * Function Name : SendSyncReply() + * Description : If server has not syncronized, do sync. Then + * send a XIM_SYNC_REPLY to IM library. + * Parameter : + * im_id : client input-method-id. + * ic_id : client input-context-id. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +SendSyncReply (im_id, ic_id) + XIMID im_id; + XICID ic_id; +{ + if (!AllSyncDone (im_id, ic_id)) + { + SyncAll (im_id, ic_id); + } + return SendIdOnly (im_id, ic_id, XIM_SYNC_REPLY, 0); +} + +/* + * Function Name : RecvSync() + * Description : process of client request XIM_SYNC. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvSync (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) req->data; + XIMID im_id; + XICID ic_id; + + im_id = cur_im_id = (XIMID) GET_CARD16 (buf_16[0]); /* 2 input-method-ID */ + if (!GetIMWithId (im_id)) + return XIM_BadProtocol; + + ic_id = cur_ic_id = (XICID) GET_CARD16 (buf_16[1]); /* 2 input-context-ID */ + if (!GetICWithId (ic_id)) + return XIM_BadProtocol; + + return SendSyncReply (im_id, ic_id); +} + +/* + * Function Name : RecvSyncReply() + * Description : process of client request XIM_SYNC_REPLY. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvSyncReply (req) + XimRequestPacket *req; +{ + /* no action. */ + return 0; +} + +/* + * Function Name : RecvError() + * Description : process of client request XIM_ERROR. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvError (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) req->data; + XIMID im_id; /* not used yet */ + XICID ic_id; /* not used yet */ + int eflag, ecode, esnum; + + im_id = (XIMID) GET_CARD16 (buf_16[0]); /* 2 input-method-ID */ + ic_id = (XICID) GET_CARD16 (buf_16[1]); /* 2 input-context-ID */ + eflag = (int) GET_CARD16 (buf_16[2]); /* 2 flag */ + ecode = (int) GET_CARD16 (buf_16[3]); /* 2 error code */ + esnum = (int) GET_CARD16 (buf_16[4]); /* 2 n length */ + if (esnum > 0) + { + char *emsg; + if (!(emsg = Malloc (esnum + 1))) + { + return XIM_BadAlloc; + } + (void) strncpy (emsg, (char *) &buf_16[6], esnum); + emsg[esnum] = '\0'; + print_out3 ("XIM Protocol Error: %d %s\n", ecode, emsg); + XFree (emsg); + } + else + { + print_out2 ("XIM Protocol Error: %d\n", ecode); + } + return 0; +} + +/* + * Function Name : SendError() + * Description : send error message to IM library with the request + * XIM_ERROR. + * Parameter : + * err_code : error code. + * Returned Value: + * <none> + */ +static void +SendError (err_code) + CARD16 err_code; +{ + CARD16 *buf_16; + CARD8 *reply; + int len; + + len = sizeof (CARD16) + /* 2 input-method-ID */ + sizeof (CARD16) + /* 2 input-context-ID */ + sizeof (BITMASK16) + /* 2 flag */ + sizeof (CARD16) + /* 2 error code */ + sizeof (INT16) + /* 2 byte length of error detail */ + sizeof (CARD16); /* 2 type of error detail */ +/* empty *//* n error detail */ + + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_ERROR, 0, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (cur_im_id); + buf_16[1] = GET_CARD16 (cur_ic_id); + buf_16[2] = GET_CARD16 (cur_status); + buf_16[3] = GET_CARD16 (err_code); + buf_16[4] = 0; /* no error detail */ + buf_16[5] = 0; /* no type */ + (void) _WriteToClientFlush (reply, len); + FREE (reply); +} + +/* + * Function Name : SendAuthRequired() + * Description : reply XIM_AUTH_REQUIRED as client ask auth. + * Parameter : + * auth_index : index of list of auth names. + * auth_data : auth data. + * length_data : byte length of data. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +SendAuthRequired (auth_index, auth_data, length_data) + CARD8 auth_index; + CARD8 *auth_data; + INT16 length_data; +{ + CARD8 *buf_8; + CARD16 *buf_16; + CARD8 *reply; + int len; + + len = sizeof (CARD8) + /* 1 auth-protocol_index */ + sizeof (CARD8) * 3 + /* 3 unused */ + sizeof (CARD16) + /* 2 length of auth data */ + sizeof (CARD16) + /* 2 unused */ + length_data + /* n data */ + PAD (length_data); /* p unused, p = Pad(n) */ + + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_AUTH_REQUIRED, 0, len); + buf_8 = (CARD8 *) (reply + XIM_HEADER_SIZE); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE + sizeof (CARD8) * 4); + buf_8[0] = (CARD8) auth_index; + buf_16[0] = GET_CARD16 (length_data); + if (auth_data && length_data > 0) + { + buf_8 = (CARD8 *) (reply + XIM_HEADER_SIZE + sizeof (CARD8) * 4 + sizeof (CARD16) * 2); + memcpy ((char *) buf_8, (char *) auth_data, length_data); + } + if (_WriteToClientFlush (reply, len) < 0) + { + FREE (reply); + return XIM_BadSomething; + } + FREE (reply); + return 0; +} + +/* + * Function Name : SendConnectReply() + * Description : reply connection from IM library. + * Parameter : + * major_version + * : major version of XIM protocol + * minor_version + * : minor version of XIM protocol + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +SendConnectReply (major_version, minor_version) + CARD16 major_version; + CARD16 minor_version; +{ + CARD16 *buf_16; + CARD8 *reply; + int len; + + len = sizeof (CARD16) + /* 2 server-major-protocol-version */ + sizeof (CARD16); /* 2 server-minor-protocol-version */ + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_CONNECT_REPLY, 0, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (major_version); + buf_16[1] = GET_CARD16 (minor_version); + if (_WriteToClientFlush (reply, len) < 0) + { + FREE (reply); + return XIM_BadSomething; + } + FREE (reply); + return 0; +} + +/* + * Function Name : RecvConnect() + * Description : do connection with IM client. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvConnect (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) (req->data + 2); + CARD16 major_version, minor_version, auth_num; + int len; + + len = req->length * 4; +/* we have touched in RecvRequest *//* 1 byte order */ +/* not used *//* 1 unused */ + major_version = GET_CARD16 (buf_16[0]); /* 2 major protocol version */ + minor_version = GET_CARD16 (buf_16[1]); /* 2 minor protocol version */ + auth_num = GET_CARD16 (buf_16[2]); /* 2 number of auth. names */ + + if (major_version != PROTOCOLMAJORVERSION || minor_version != PROTOCOLMINORVERSION) + return XIM_BadProtocol; + + len -= sizeof (CARD8) + sizeof (CARD8) + sizeof (CARD16) + sizeof (CARD16) + sizeof (CARD16); + + if (auth_num > 0) + { + if (GetAuth (&buf_16[3], auth_num, &len, NULL) == False) + { + return XIM_BadSomething; /* error in get auth. */ + } + return SendAuthRequired ((CARD8) 0, (CARD8 *) NULL, (INT16) 0); + } + else + { + return SendConnectReply (PROTOCOLMAJORVERSION, PROTOCOLMINORVERSION); + } +} + +/* + * Function Name : RecvDisconnect() + * Description : disconnect with IM client. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvDisconnect (req) + XimRequestPacket *req; +{ + CARD8 *reply; + int len; + extern int cur_sock; + + close_socket (cur_sock); + + /* reply */ + len = 0; /* no data */ + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_DISCONNECT_REPLY, 0, len); + if (_WriteToClientFlush (reply, len) < 0) + { + FREE (reply); + return XIM_BadSomething; + } + FREE (reply); + return 0; +} + +#ifdef DYNAMIC_EVENT_FLOW_MODEL + +/* + * Function Name : SendRegisterTriggerKeys() + * Description : ask client to register trigger keys which will + * turn on or off input method. + * Parameter : + * im_id : client input-method-id. + * Returned Value: + * <none> + */ +static void +SendRegisterTriggerKeys (im_id) + XIMID im_id; +{ + CARD8 *reply; + CARD16 *buf_16; + CARD32 *buf_32; + CARD32 onkeys[3]; + int onkeys_len; + int len; + + onkeys[0] = GET_CARD32 (trigger_keys_list[0]); + onkeys[1] = GET_CARD32 (trigger_keys_list[1]); + onkeys[2] = GET_CARD32 (trigger_keys_list[2]); + onkeys_len = sizeof (CARD32) * 3; + + /* send */ + len = sizeof (CARD16) + /* 2 input-method-ID */ + sizeof (CARD16) + /* 2 unused */ + sizeof (CARD32) + /* 4 n byte length */ + onkeys_len + /* n LISTofXIMTRIGGERKEY */ + sizeof (CARD32) + /* 4 m byte length */ + onkeys_len; /* m LISTofXIMTRIGGERKEY */ + + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_REGISTER_TRIGGERKEYS, 0, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (im_id); + buf_32 = (CARD32 *) & buf_16[2]; + buf_32[0] = GET_CARD32 (onkeys_len); + (void) memcpy ((char *) &buf_32[1], (char *) onkeys, onkeys_len); + buf_32 = (CARD32 *) (reply + sizeof (CARD16) + sizeof (CARD16) + sizeof (CARD32) + onkeys_len); + buf_32[0] = GET_CARD32 (onkeys_len); /* off keys same as on-keys */ + (void) memcpy ((char *) &buf_32[1], (char *) onkeys, onkeys_len); + (void) _WriteToClientFlush (reply, len); + FREE (reply); +} + +/* + * Function Name : ToggleHenkan() + * Description : turn on or off kanji henkan. + */ +static void +ToggleHenkan (keys_index, mask) + int keys_index; + unsigned long mask; +{ + /* not yet */ +} + +/* + * Function Name : RecvTriggerNotify() + * Description : Some trigger key has pressed by client, it means + * client asks some input method. do it. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvTriggerNotify (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) req->data; + CARD32 *buf_32; + CARD8 *reply; + XIMID im_id; + XICID ic_id; + int len; + int ret, n; + int keys_flag, keys_index; + unsigned long mask; + XIMClientRec *xc; + + im_id = cur_im_id = (XIMID) GET_CARD16 (buf_16[0]); /* 2 input-method-ID */ + if (!GetIMWithId (im_id)) + return XIM_BadProtocol; + + ic_id = cur_ic_id = (XICID) GET_CARD16 (buf_16[1]); /* 2 input-context-ID */ + if (!(xc = GetICWithId (ic_id))) + return XIM_BadProtocol; + + buf_32 = (CARD32 *) & buf_16[2]; + keys_flag = (int) GET_CARD32 (buf_32[0]); + keys_index = (int) GET_CARD32 (buf_32[1]); + mask = (unsigned long) GET_CARD32 (buf_32[2]); + + if (!keys_flag) + { + /* trigger on */ + ToggleHenkan (keys_index, mask); + } + else + { + /* trigger off */ + ToggleHenkan (keys_index, mask); + } + + /* reply */ + return SendIdOnly (im_id, ic_id, XIM_TRIGGER_NOTIFY_REPLY, 0); +} + +#endif /* DYNAMIC_EVENT_FLOW_MODEL */ + +/* + * Function Name : RecvOpen() + * Description : open an IM context for client. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvOpen (req) + XimRequestPacket *req; +{ + CARD8 *reply; + CARD16 *buf_16; + XIMID im_id; + int len; + + if (_CheckLocaleName (req->data, cur_use_lang) == False) + return XIM_LocaleNotSupported; + + if (!(im_id = CreateIM ())) + return XIM_BadAlloc; + +#ifdef DYNAMIC_EVENT_FLOW_MODEL + SendRegisterTriggerKeys (im_id); +#endif /* DYNAMIC_EVENT_FLOW_MODEL */ + + /* reply */ + len = sizeof (CARD16) + /* 2 input-method-id */ + sizeof (CARD16) + /* 2 byte length of IM attr. */ + imattr_list_size + /* n IM attr. supported */ + sizeof (CARD16) + /* 2 byte length of IC attr. */ + sizeof (CARD16) + /* 2 unused */ + icattr_list_size; /* m IC attr. supported */ + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_OPEN_REPLY, 0, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (im_id); + buf_16[1] = GET_CARD16 (imattr_list_size); + memcpy ((char *) &buf_16[2], (char *) imattr_list, imattr_list_size); + + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE + sizeof (CARD16) + sizeof (CARD16) + imattr_list_size); + buf_16[0] = GET_CARD16 (icattr_list_size); + memcpy ((char *) &buf_16[2], (char *) icattr_list, icattr_list_size); + + if (_WriteToClientFlush (reply, len) < 0) + { + FREE (reply); + return XIM_BadSomething; + } + FREE (reply); + return 0; +} + +/* + * Function Name : RecvClose() + * Description : close an IM client. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvClose (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) req->data; + CARD8 *reply; + XIMID im_id; + int len; + + im_id = cur_im_id = GET_CARD16 (buf_16[0]); /* 2 input-method-ID */ + if (RemoveIMWithId (im_id) == False) + return XIM_BadProtocol; + cur_im_id = 0; + + /* reply */ + len = sizeof (CARD16) + /* 2 input-method-ID */ + sizeof (CARD16); /* 2 unused */ + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_CLOSE_REPLY, 0, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (im_id); + if (_WriteToClientFlush (reply, len) < 0) + { + FREE (reply); + return XIM_BadSomething; + } + FREE (reply); + return 0; +} + +/* + * Function Name : RecvQueryExtension() + * Description : send extension lists supported by server as the + * client asks. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvQueryExtension (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) (req->data); + CARD8 *reply; + XIMID im_id; + CARD8 value[BUFSIZ]; + int len, value_len; + int ret, n; + + im_id = cur_im_id = (XIMID) GET_CARD16 (buf_16[0]); /* 2 input-method-ID */ + if (!GetIMWithId (im_id)) + { + return XIM_BadProtocol; + } + + /* get extetions supported by us. */ + n = GET_CARD16 (buf_16[1]); /* 2 n byte length */ + ret = GetExtensionList ((CARD8 *) & buf_16[2], n, value, &value_len); + if (ret) + return ret; + + /* reply */ + len = sizeof (CARD16) + /* 2 input-method-ID */ + sizeof (CARD16) + /* 2 n byte length */ + value_len; /* n LISTofEXT */ + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_QUERY_EXTENSION_REPLY, 0, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (im_id); + buf_16[1] = GET_CARD16 (value_len); + (void) memcpy ((char *) &buf_16[2], (char *) value, value_len); + if (_WriteToClientFlush (reply, len) < 0) + { + FREE (reply); + return XIM_BadSomething; + } + FREE (reply); + return 0; +} + +/* + * Function Name : RecvEncodingNegotiation() + * Description : decide COMPOUND_TEXT as the result of encoding + * negotiation between IM client and server. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvEncodingNegotiation (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) req->data; + CARD8 *reply; + XIMID im_id; + int len, n, index; + + im_id = cur_im_id = (XIMID) GET_CARD16 (buf_16[0]); /* 2 input-method-ID */ + if (!GetIMWithId (im_id)) + return XIM_BadProtocol; + + /* we care only the index of COMPOUNT_TEXT */ + n = GET_CARD16 (buf_16[1]); /* 2 byte length */ + index = GetCompoundTextIndex ((CARD8 *) & buf_16[2], n); + + /* reply */ + len = sizeof (CARD16) + /* 2 input-method-ID */ + sizeof (CARD16) + /* 2 category of the encoding */ + sizeof (CARD16) + /* 2 index of the encoding */ + sizeof (CARD16); /* 2 unused */ + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_ENCODING_NEGOTIATION_REPLY, 0, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (im_id); + buf_16[1] = GET_CARD16 (XIM_Encoding_NameCategory); + buf_16[2] = GET_CARD16 (index); + if (_WriteToClientFlush (reply, len) < 0) + { + FREE (reply); + return XIM_BadSomething; + } + FREE (reply); + return 0; +} + +/* + * Function Name : SendSetEventMask() + * Description : send XEvent mask to client which will foward any + * event to the server. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * <none> + */ +static void +SendSetEventMask (im_id, ic_id) + XIMID im_id; + XICID ic_id; +{ + CARD8 *reply; + CARD16 *buf_16; + CARD32 *buf_32; + int len; + + /* send */ + len = sizeof (CARD16) + /* 2 input-method-ID */ + sizeof (CARD16) + /* 2 input-context-ID */ + sizeof (BITMASK32) + /* 4 forw-event-mask */ + sizeof (BITMASK32); /* 4 sync-event-mask */ + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_SET_EVENT_MASK, 0, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (im_id); + buf_16[1] = GET_CARD16 (ic_id); + buf_32 = (CARD32 *) & buf_16[2]; + buf_32[0] = (KeyPressMask | StructureNotifyMask); + buf_32[1] = (KeyPressMask | StructureNotifyMask); + (void) _WriteToClientFlush (reply, len); + FREE (reply); +} + +/* + * Function Name : RecvCreateIC() + * Description : create an IC for the connected client. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvCreateIC (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) req->data; + XIMID im_id; + XICID ic_id; + int ret, len; + + im_id = cur_im_id = (XIMID) GET_CARD16 (buf_16[0]); /* 2 input-method-ID */ + if (!GetIMWithId (im_id)) + return XIM_BadProtocol; + + /* create IC. */ + len = (int) GET_CARD16 (buf_16[1]); + ret = CreateClientIC (im_id, (CARD8 *) & buf_16[2], len, &ic_id); + if (ret) + return ret; + cur_ic_id = ic_id; + + /* reply */ + ret = SendIdOnly (im_id, ic_id, XIM_CREATE_IC_REPLY, 0); + if (ret) + return ret; + + SendSetEventMask (im_id, ic_id); + return 0; +} + +/* + * Function Name : RecvSetICValues() + * Description : set IC values to internal client context. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvSetICValues (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) req->data; + XIMID im_id; + XICID ic_id; + int ret, n; + + XIMClientRec *xc; + + im_id = cur_im_id = (XIMID) GET_CARD16 (buf_16[0]); /* 2 input-method-ID */ + if (!GetIMWithId (im_id)) + return XIM_BadProtocol; + + ic_id = cur_ic_id = (XICID) GET_CARD16 (buf_16[1]); /* 2 input-context-ID */ + if (!(xc = GetICWithId (ic_id))) + return XIM_BadProtocol; + + n = (int) GET_CARD16 (buf_16[2]); /* 2 n byte length */ + ret = SetClientICValues ((CARD8 *) & buf_16[4], n, xc); + if (ret) + return ret; + + /* reply */ + return SendIdOnly (im_id, ic_id, XIM_SET_IC_VALUES_REPLY, 0); +} + +/* + * Function Name : RecvGetICValues() + * Description : encode IC values of client context, then send to client. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvGetICValues (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) req->data; + CARD8 *reply; + CARD8 value[BUFSIZ]; + XIMID im_id; + XICID ic_id; + int len, value_len, n; + int ret; + + XIMClientRec *xc; + + im_id = cur_im_id = (XIMID) GET_CARD16 (buf_16[0]); /* 2 input-method-ID */ + if (!GetIMWithId (im_id)) + return XIM_BadProtocol; + + ic_id = cur_ic_id = (XICID) GET_CARD16 (buf_16[1]); /* 2 input-context-ID */ + if (!(xc = GetICWithId (ic_id))) + return XIM_BadProtocol; + + n = GET_CARD16 (buf_16[2]); + ret = EncodeICAttributes ((CARD8 *) & buf_16[3], n, xc, value, &value_len); + if (ret) + return ret; + + /* reply */ + len = sizeof (CARD16) + /* 2 input-method-ID */ + sizeof (CARD16) + /* 2 input-context-ID */ + sizeof (INT16) + /* 2 byte length of ic-attr */ + sizeof (CARD16) + /* 2 unused */ + value_len; /* n list of ic-attr */ + + /* reply */ + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_GET_IC_VALUES_REPLY, 0, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (im_id); + buf_16[1] = GET_CARD16 (ic_id); + buf_16[2] = GET_CARD16 (value_len); + (void) memcpy ((char *) &buf_16[4], (char *) value, value_len); + if (_WriteToClientFlush (reply, len) < 0) + { + FREE (reply); + return XIM_BadSomething; + } + FREE (reply); + return 0; +} + +/* + * Function Name : JWMline_get() + * Description : put preedit string into a common shared CT buffer which + * can be accessed by GET_COMMON_CT_BUFFER, i.e., "ct_buf". + * Parameter : + * base : beginning position of preedit string. + * pre_len_returned + * : returned length of the string got. + * Returned Value: + * <none> + */ +static void +JWMline_get (base, pre_len_returned) + int base; + int *pre_len_returned; +{ + register XIMLangRec *xl; + register int wc_len, send_len; + register wchar *JW_buf; + + *pre_len_returned = 0; + xl = cur_p->cur_xl; + JW_buf = xl->buf + base; + send_len = wc_len = xl->max_pos - base; + if (wc_len > 0) + { + while (1) + { + send_len = wchar_to_ct (cur_p->cur_xl->xlc, JW_buf, ct_buf, wc_len, ct_buf_max); + if (send_len < -1) + { + return; + } + else if (send_len == -1) + { + if (realloc_ct_buf () < 0) + return; + } + else + { + break; + } + } + } + *pre_len_returned = ((send_len >= 0) ? send_len : 0); +} + +/* + * Function Name : ResetClientIC() + * Description : reset IC context of client. + * Parameter : + * xc : pointer to client structure. + * pre_str_filled + * : returned preedit string. + * The pre_str_filled parameter is only for readability, + * it is used in a global variable "ct_buf". + * pre_len_returned + * : length of preedit string + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ + /*ARGSUSED*/ static int +ResetClientIC (xc, pre_str_filled, pre_len_returned) + XIMClientRec *xc; + unsigned char *pre_str_filled; /* only for readable ct_buf */ + int *pre_len_returned; +{ + WnnClientRec *save_c_c; + XIMClientRec *save_cur_p, *save_cur_x; + int ret; + + /* refer to util.c: ResetIC() */ + { + save_c_c = c_c; + save_cur_p = cur_p; + save_cur_x = cur_x; + cur_x = xc; + if (IsPreeditNothing (xc)) + { + cur_p = xc->root_pointer->ximclient; + } + else + { + cur_p = cur_x; + } + c_c = cur_p->cur_xl->w_c; + ret = reset_c_b (); + JWMline_get (0, pre_len_returned); + JWMline_clear (0); + c_c = save_c_c; + cur_p = save_cur_p; + cur_x = save_cur_x; + if (ret == -1) + return XIM_BadProtocol; + } + return 0; +} + +/* + * Function Name : RecvResetIC() + * Description : reset IC context as client asks. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvResetIC (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) req->data; + CARD8 *reply; + XIMID im_id; + XICID ic_id; + int len, pre_len; + int ret; + unsigned char *pre_str; + + XIMClientRec *xc; + + im_id = cur_im_id = (XIMID) GET_CARD16 (buf_16[0]); /* 2 input-method-ID */ + if (!GetIMWithId (im_id)) + return XIM_BadProtocol; + + ic_id = cur_ic_id = (XICID) GET_CARD16 (buf_16[1]); /* 2 input-context-ID */ + if (!(xc = GetICWithId (ic_id))) + return XIM_BadProtocol; + + pre_str = GET_SHARED_CT_BUFFER (); + ret = ResetClientIC (xc, pre_str, &pre_len); + if (ret) + return ret; + + /* reply */ + len = sizeof (CARD16) + /* 2 input-method-ID */ + sizeof (CARD16) + /* 2 input-context-ID */ + sizeof (INT16) + /* 2 byte length of string */ + pre_len + /* n LISTofBYTE */ + PAD (sizeof (INT16) + pre_len); /* p Pad(2 + n) */ + + /* reply */ + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_RESET_IC_REPLY, 0, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (im_id); + buf_16[1] = GET_CARD16 (ic_id); + buf_16[2] = GET_CARD16 (pre_len); + if (pre_len > 0) + (void) memcpy ((char *) &buf_16[3], (char *) pre_str, pre_len); + + if (_WriteToClientFlush (reply, len) < 0) + { + FREE (reply); + return XIM_BadSomething; + } + FREE (reply); + return 0; +} + +/* + * Function Name : RecvDestroyIC() + * Description : destroy an IC context. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvDestroyIC (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) req->data; + XIMID im_id; + XICID ic_id; + + XIMClientRec *xc; + + im_id = cur_im_id = (XIMID) GET_CARD16 (buf_16[0]); /* 2 input-method-ID */ + if (!GetIMWithId (im_id)) + return XIM_BadProtocol; + + ic_id = cur_ic_id = (XICID) GET_CARD16 (buf_16[1]); /* 2 input-context-ID */ + if (!(xc = GetICWithId (ic_id))) + return XIM_BadProtocol; + (void) destroy_client (xc); + cur_ic_id = 0; + + /* reply */ + return SendIdOnly (im_id, ic_id, XIM_DESTROY_IC_REPLY, 0); +} + +/* + * Function Name : SetClientICFocus() + * Description : set IC focus to the specified client. + * Parameter : + * xc : pointer to client structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +SetClientICFocus (xc) + XIMClientRec *xc; +{ + register XIMInputRec *xi; + XIMClientRec *save_cur_p, *save_cur_x; + WnnClientRec *save_c_c; + + /* modified from util.c: SetICFocus() */ + { + for (xi = input_list; xi != NULL; xi = xi->next) + { + if (xi->w == xc->focus_window) + break; + } + if (xi == NULL) + { + if (!(xi = (XIMInputRec *) Malloc (sizeof (XIMInputRec)))) + { + malloc_error ("allocation of Focus data struct"); + return XIM_BadAlloc; + } + xi->w = xc->focus_window; + xi->pclient = xc; + xi->next = NULL; + add_inputlist (xi); + } + save_cur_p = cur_p; + save_cur_x = cur_x; + save_c_c = c_c; + cur_x = xc; + if (IsPreeditNothing (xc)) + { + cur_p = xc->root_pointer->ximclient; + } + else + { + cur_p = cur_x; + } + c_c = cur_p->cur_xl->w_c; + cur_rk = c_c->rk; + cur_rk_table = cur_rk->rk_table; +#ifdef CALLBACKS + if (IsPreeditPosition (xc) || IsPreeditArea (xc) || IsStatusCallbacks (xc)) + { +#else /* CALLBACKS */ + if (IsPreeditPosition (xc) || IsPreeditArea (xc)) + { +#endif /* CALLBACKS */ + reset_preedit (xc); + } +#ifdef CALLBACKS + if (IsStatusArea (xc) || IsStatusCallbacks (xc)) + { +#else /* CALLBACKS */ + if (IsStatusArea (xc)) + { +#endif /* CALLBACKS */ + visual_status (); + } + cur_p = save_cur_p; + cur_x = save_cur_x; + c_c = save_c_c; + if (c_c) + { + cur_rk = c_c->rk; + cur_rk_table = cur_rk->rk_table; + } + } + return 0; +} + +/* + * Function Name : UnsetClientICFocus() + * Description : unset IC focus to the specified client. + * Parameter : + * xc : pointer to client structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +UnsetClientICFocus (xc) + XIMClientRec *xc; +{ + register XIMInputRec *xi; + XIMClientRec *save_cur_p, *save_cur_x; + WnnClientRec *save_c_c; + + /* modified from util.c: UnsetICFocus() */ + { + for (xi = input_list; xi != NULL; xi = xi->next) + { + if (xi->w == xc->focus_window) + break; + } + if (xi == NULL) + { + return XIM_BadFocusWindow; + } + else + { + remove_inputlist (xi); + if (cur_input == xi) + cur_input = 0; + Free ((char *) xi); + save_cur_p = cur_p; + save_cur_x = cur_x; + save_c_c = c_c; + cur_x = xc; + if (IsPreeditNothing (xc)) + { + cur_p = xc->root_pointer->ximclient; + } + else + { + cur_p = cur_x; + } + c_c = cur_p->cur_xl->w_c; + cur_rk = c_c->rk; + cur_rk_table = cur_rk->rk_table; +#ifdef CALLBACKS + if (IsPreeditPosition (xc) || IsPreeditArea (xc) || IsPreeditCallbacks (xc)) + { +#else /* CALLBACKS */ + if (IsPreeditPosition (xc) || IsPreeditArea (xc)) + { +#endif /* CALLBACKS */ + invisual_window (); + } +#ifdef CALLBACKS + if (IsStatusArea (xc) || IsStatusCallbacks (xc)) + { +#else /* CALLBACKS */ + if (IsStatusArea (xc)) + { +#endif /* CALLBACKS */ + invisual_status (); + } + cur_p = save_cur_p; + cur_x = save_cur_x; + c_c = save_c_c; + if (c_c) + { + cur_rk = c_c->rk; + cur_rk_table = cur_rk->rk_table; + } + } + } + return 0; +} + +/* + * Function Name : RecvSetICFocus() + * Description : set IC focus. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvSetICFocus (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) req->data; + XIMID im_id; + XICID ic_id; + + XIMClientRec *xc; + + im_id = cur_im_id = (XIMID) GET_CARD16 (buf_16[0]); /* 2 input-method-ID */ + if (!GetIMWithId (im_id)) + return XIM_BadProtocol; + + ic_id = cur_ic_id = (XICID) GET_CARD16 (buf_16[1]); /* 2 input-context-ID */ + if (!(xc = GetICWithId (ic_id))) + return XIM_BadProtocol; + + return SetClientICFocus (xc); + + /* asynchoronous request, no reply */ +} + +/* + * Function Name : RecvUnsetICFocus() + * Description : unset IC focus. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvUnsetICFocus (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) req->data; + XIMID im_id; + XICID ic_id; + + XIMClientRec *xc; + + im_id = cur_im_id = (XIMID) GET_CARD16 (buf_16[0]); /* 2 input-method-ID */ + if (!GetIMWithId (im_id)) + return XIM_BadProtocol; + + ic_id = cur_ic_id = (XICID) GET_CARD16 (buf_16[1]); /* 2 input-context-ID */ + if (!(xc = GetICWithId (ic_id))) + return XIM_BadProtocol; + + return UnsetClientICFocus (xc); + + /* asynchoronous request, no reply */ +} + +/* + * Function Name : RecvGetIMValues() + * Description : encode IM values to byte data, then send it to client. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvGetIMValues (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) req->data; + CARD8 *reply; + XIMID im_id; + CARD8 value[BUFSIZ]; + int len, value_len, n; + int ret; + XIMContextRec *im; + + im_id = cur_im_id = (XIMID) GET_CARD16 (buf_16[0]); /* 2 input-method-ID */ + if (!(im = GetIMWithId (im_id))) + return XIM_BadProtocol; + + n = GET_CARD16 (buf_16[1]); + ret = EncodeIMAttributes ((CARD8 *) & buf_16[2], n, im, value, &value_len); + if (ret) + return ret; + + /* reply */ + len = sizeof (CARD16) + /* 2 input-method-ID */ + sizeof (INT16) + /* 2 byte length of im-attr */ + value_len; /* n list of im-attr */ + + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_GET_IM_VALUES_REPLY, 0, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (im_id); + buf_16[1] = GET_CARD16 (value_len); + (void) memcpy ((char *) &buf_16[2], (char *) value, value_len); + if (_WriteToClientFlush (reply, len) < 0) + { + FREE (reply); + return XIM_BadSomething; + } + FREE (reply); + return 0; +} + +/* + * Function Name : RecvSetIMValues() + * Description : decode IM values, then send it to client context. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvSetIMValues (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) req->data; + CARD8 *reply; + XIMID im_id; + int len, n; + int ret; + XIMContextRec *im; + + im_id = cur_im_id = (XIMID) GET_CARD16 (buf_16[0]); /* 2 input-method-ID */ + if (!(im = GetIMWithId (im_id))) + return XIM_BadProtocol; + + n = (int) GET_CARD16 (buf_16[1]); /* 2 n byte length */ + ret = SetClientIMValues ((CARD8 *) & buf_16[2], n, im); + if (ret) + return ret; + + /* reply */ + len = sizeof (CARD16) + /* 2 input-method-ID */ + sizeof (CARD16); /* 2 unused */ + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_SET_IM_VALUES_REPLY, 0, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (im_id); + if (_WriteToClientFlush (reply, len) < 0) + { + FREE (reply); + return XIM_BadSomething; + } + FREE (reply); + return 0; +} + +/* + * Function Name : SendCommit() + * Description : commit a string to client, the string is converted + * by input method, such kanji, and is encoded in CT. + * Parameter : + * im_id : client input-method-id. + * ic_id : client input-context-id. + * flag : flag of XimLookupKeySym, XimLookupChars or both. + * keysym : keysym if committed. + * ct_str : CT string if committed. + * ct_len : length of string. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +SendCommit (im_id, ic_id, flag, keysym, ct_str, ct_len) + XIMID im_id; + XICID ic_id; + int flag; + KeySym keysym; + char *ct_str; + int ct_len; +{ + CARD16 *buf_16; + CARD32 *buf_32; + CARD8 *reply; + int len; + + XIMClientRec *xc; + + if (!(xc = GetICWithId (ic_id)) || xc->im_id != im_id) + return XIM_BadProtocol; + + flag |= XimSYNCHRONUS; /* ask sync */ + + /* send */ + len = sizeof (CARD16) + /* 2 input-method-id */ + sizeof (CARD16) + /* 2 input-context-id */ + sizeof (BITMASK16) + /* 2 flag */ + LENGTH_KEYSYM (flag, sizeof (CARD32)) + /* 2+6 KeySym */ + LENGTH_STRING_WITH_FLAG (flag, ct_len); /* 2+n+Pad(2+n) string */ + + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_COMMIT, 0, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (im_id); + buf_16[1] = GET_CARD16 (ic_id); + buf_16[2] = GET_CARD16 (flag); + buf_16 = (CARD16 *) & buf_16[3]; + if (flag & XimLookupKeySym) + { + buf_32 = (CARD32 *) & buf_16[1]; + buf_32[0] = GET_CARD32 (keysym); + buf_16 = (CARD16 *) & buf_32[1]; + } + if (flag & XimLookupChars) + { + buf_16[0] = GET_CARD16 (ct_len); + (void) memcpy ((char *) &buf_16[1], ct_str, ct_len); + } + if (_WriteToClientFlush (reply, len) < 0) + { + FREE (reply); + return XIM_BadSomething; + } + FREE (reply); + + if (ClientSyncDone (xc) == True) + return SendSyncReply (im_id, ic_id); + else + return 0; +} + +/* + * Function Name : SendForwardEvent() + * Description : usually it is to send event back to client, e.g. + * when no filter in server. + * Parameter : + * im_id : client input-method-id. + * ic_id : client input-context-id. + * serial : serial number of event. + * event : pointer to XEvent. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +SendForwardEvent (im_id, ic_id, serial, event) + XIMID im_id; + XICID ic_id; + int serial; + XEvent *event; +{ + CARD16 *buf_16; + CARD8 *reply; + int len; + int flag; + + /* send */ + len = sizeof (CARD16) + /* 2 input-method-ID */ + sizeof (CARD16) + /* 2 input-context-ID */ + sizeof (BITMASK16) + /* 2 flag */ + sizeof (CARD16) + /* 2 serial number */ + sizeof (xEvent); /* n XEVENT */ + + flag = 0; /* no sync flag */ + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_FORWARD_EVENT, 0, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (im_id); + buf_16[1] = GET_CARD16 (ic_id); + buf_16[2] = GET_CARD16 (flag); + buf_16[3] = GET_CARD16 (serial); + if (_XimEventToWire (event, (xEvent *) & buf_16[4]) == False) + return XIM_BadSomething; + if (_WriteToClientFlush (reply, len) < 0) + { + FREE (reply); + return XIM_BadSomething; + } + FREE (reply); + return 0; +} + +/* + * Function Name : ExecInputMethod() + * Description : execute input method to do some henkan (conversion). + * This is referred to keyin.c: RequestDispatch() on + * the case of XIM_Event. + * Parameter : + * im_id : client input-method-id. + * ic_id : client input-context-id. + * xevp : pointer to event. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +ExecInputMethod (im_id, ic_id, xevp) + XIMID im_id; + XICID ic_id; + XEvent *xevp; +{ + int buff[32], in; + int ret; + register int i, n_bytes; + + ret = key_input (buff, xevp); + if (ret == 0) + { + /* send_nofilter() */ + return xim_send_nofilter (); + } + else if (ret > 0) + { + for (i = 0; i < ret;) + { + n_bytes = get_cswidth_by_char (in = buff[i++]); + for (; n_bytes > 1 && i < ret; n_bytes--, i++) + { + in = (in << 8) + buff[i]; + } + in_put (in); + } + } + return 0; +} + +/* + * Function Name : RecvForwardEvent() + * Description : filter event forwarded by client to execute input + * method. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvForwardEvent (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) req->data; + XIMID im_id; + XICID ic_id; + int ret; + int flag, serial; + XEvent event; + + XIMClientRec *xc; + + im_id = cur_im_id = (XIMID) GET_CARD16 (buf_16[0]); /* 2 input-method-ID */ + if (!GetIMWithId (im_id)) + return XIM_BadProtocol; + + ic_id = cur_ic_id = (XICID) GET_CARD16 (buf_16[1]); /* 2 input-context-ID */ + if (!(xc = GetICWithId (ic_id))) + return XIM_BadProtocol; + + flag = (int) GET_CARD16 (buf_16[2]); + serial = (int) GET_CARD16 (buf_16[3]); + + SetClientSync (xc, True); + + if (_XimWireToEvent (dpy, serial, (xEvent *) & buf_16[4], &event) == False) + return XIM_BadProtocol; + /* + * save event which will back to client if no filter. + */ + (void) memcpy ((char *) &(xc->cur_event), (char *) &event, sizeof (XEvent)); + + ret = ExecInputMethod (im_id, ic_id, &event); + /* + * if it is async (no XimSYNCHRONUS), force 0 returned, so no anything + * even no error is sent to client. + */ + if (ret) + return ((flag & XimSYNCHRONUS) ? ret : 0); + + if (ClientSyncDone (xc) == True) + return SendSyncReply (im_id, ic_id); + else + return 0; +} + +/* + * Function Name : RecvStrConversionReply() + * Description : send a request that is the format of: + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvStrConversionReply (req) + XimRequestPacket *req; +{ + /* don't care in this model. */ + return 0; +} + +#ifdef CALLBACKS + +/* + * Function Name : CopyText() + * Description : copy string and feedback array to byte data + * Parameter : + * bur : pointer to the byte data. + * str : string + * feedback : array of feedback. + * feedback_num: number of feedback. + * Returned Value: + * <none> + */ +static void +CopyText (buf, str, str_len, feedback, feedback_num) + CARD8 *buf; + char *str; + int str_len; + XIMFeedback *feedback; + int feedback_num; +{ + CARD16 *buf_16; + CARD32 *buf_32; + CARD32 *save_32; + BITMASK32 status = 0; + int i; + + save_32 = (CARD32 *) buf; + buf_16 = (CARD16 *) & save_32[1]; + if (str_len > 0) + { + buf_16[0] = GET_CARD16 (str_len); + (void) strncpy ((char *) &buf_16[1], str, str_len); + buf_16 = (CARD16 *) ((CARD8 *) buf_16 + sizeof (CARD16) + PAD (sizeof (CARD16) + str_len)); + } + else + { + status |= XIMNoString; + } + if (feedback_num > 0) + { + buf_16[0] = GET_CARD16 (feedback_num); + buf_32 = (CARD32 *) & buf_16[2]; + for (i = 0; i < feedback_num; i++) + { + buf_32[i] = GET_CARD32 (feedback[i]); + } + } + else + { + status |= XIMNoFeedback; + } + save_32[0] = GET_CARD32 (status); +} + +/* + * Function Name : SendPreeditDraw() + * Description : send the request of XIM_PREEDT_DRAW. + * Parameter : + * im_id : client input-method-id. + * ic_id : client input-context-id. + * caret : caret + * chg_first : first of change. + * chg_len : length of change. + * str : string. + * str_len : length of string. + * feedback : array of feedback. + * feedback_num: number of feedback. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +SendPreeditDraw (im_id, ic_id, caret, chg_first, chg_len, str, str_len, feedback, feedback_num) + XIMID im_id; + XICID ic_id; + INT32 caret; + INT32 chg_first; + INT32 chg_len; + char *str; + int str_len; + XIMFeedback *feedback; + int feedback_num; +{ + CARD8 *reply; + CARD16 *buf_16; + CARD32 *buf_32; + int len; + + /* send */ + len = sizeof (CARD16) + /* 2 input-method-ID */ + sizeof (CARD16) + /* 2 input-context-ID */ + sizeof (INT32) + /* 4 caret */ + sizeof (INT32) + /* 4 chg_first */ + sizeof (INT32) + /* 4 chg_length */ + sizeof (BITMASK32) + /* 4 status */ + LENGTH_STRING (str_len) + /* x string */ + LENGTH_FEEDBACK (feedback_num); /* x feedback array */ + + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_PREEDIT_DRAW, 0, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (im_id); + buf_16[1] = GET_CARD16 (ic_id); + buf_32 = (CARD32 *) & buf_16[2]; + buf_32[0] = GET_CARD32 (caret); + buf_32[1] = GET_CARD32 (chg_first); + buf_32[2] = GET_CARD32 (chg_len); + buf_16 = (CARD16 *) & buf_32[3]; + CopyText ((CARD8 *) & buf_32[3], str, str_len, feedback, feedback_num); + if (_WriteToClientFlush (reply, len) < 0) + { + FREE (reply); + return XIM_BadSomething; + } + FREE (reply); + return 0; +} + +/* + * Function Name : SendPreeditCaret() + * Description : send the request of XIM_PREEDIT_CARET. + * Parameter : + * im_id : client input-method-id. + * ic_id : client input-context-id. + * pos : position + * direct : direction of caret. + * style : style of caret. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +SendPreeditCaret (im_id, ic_id, pos, direct, style) + XIMID im_id; + XICID ic_id; + INT32 pos; + CARD32 direct; + CARD32 style; +{ + CARD8 *reply; + CARD16 *buf_16; + CARD32 *buf_32; + int len; + + /* send */ + len = sizeof (CARD16) + /* 2 input-method-ID */ + sizeof (CARD16) + /* 2 input-context-ID */ + sizeof (INT32) + /* 4 position */ + sizeof (CARD32) + /* 4 direction */ + sizeof (CARD32); /* 4 style */ + + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_PREEDIT_CARET, 0, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (im_id); + buf_16[1] = GET_CARD16 (ic_id); + buf_32 = (CARD32 *) & buf_16[2]; + buf_32[0] = GET_CARD32 (pos); + buf_32[1] = GET_CARD32 (direct); + buf_32[2] = GET_CARD32 (style); + if (_WriteToClientFlush (reply, len) < 0) + { + FREE (reply); + return XIM_BadSomething; + } + FREE (reply); + return 0; +} + +/* + * Function Name : SendStatusDraw() + * Description : send the request of XIM_STATUS_DRAW. + * Parameter : + * im_id : client input-method-id. + * ic_id : client input-context-id. + * st_type : type of status. + * str : string. + * str_len : length of string. + * feedback : array of feedback. + * feedback_num: number of feedback. + * pixmap : pixmap data. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +SendStatusDraw (im_id, ic_id, st_type, str, str_len, feedback, feedback_num, pixmap) + XIMID im_id; + XICID ic_id; + CARD32 st_type; + char *str; + int str_len; + XIMFeedback *feedback; + int feedback_num; + PIXMAP pixmap; +{ + CARD8 *reply; + CARD16 *buf_16; + CARD32 *buf_32; + int len; + + /* send */ + len = sizeof (CARD16) + /* 2 input-method-ID */ + sizeof (CARD16) + /* 2 input-context-ID */ + sizeof (CARD32) + /* 4 type */ + sizeof (BITMASK32) + /* 4 status */ + LENGTH_TEXT (st_type, str_len, feedback_num) + /* text */ + LENGTH_PIXMAP (st_type); /* x pixmap */ + + reply = MALLOC_REPLY (XIM_HEADER_SIZE + len); + len += AddHead (reply, XIM_STATUS_DRAW, 0, len); + buf_16 = (CARD16 *) (reply + XIM_HEADER_SIZE); + buf_16[0] = GET_CARD16 (im_id); + buf_16[1] = GET_CARD16 (ic_id); + buf_32 = (CARD32 *) & buf_16[2]; + buf_32[0] = GET_CARD32 (st_type); + if (st_type == XIMTextType) + { + CopyText ((CARD8 *) & buf_32[1], str, str_len, feedback, feedback_num); + } + else + { + buf_32[1] = GET_CARD32 (pixmap); + } + if (_WriteToClientFlush (reply, len) < 0) + { + FREE (reply); + return XIM_BadSomething; + } + FREE (reply); + return 0; +} + +/* + * Function Name : RecvPreeditStartReply() + * Description : receive a reply from client. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvPreeditStartReply (req) + XimRequestPacket *req; +{ + /* don't care. */ + return 0; +} + +/* + * Function Name : RecvPreeditCaretReply() + * Description : receive a reply from client. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +static int +RecvPreeditCaretReply (req) + XimRequestPacket *req; +{ + /* don't care. */ + return 0; +} + +#endif /* CALLBACKS */ + +#if defined(EXT_MOVE) || defined(SPOT) + +/* + * Function Name : RecvExtMove() + * Description : change only the point of spot. + * Parameter : + * req : pointer to a request structure. + * Returned Value: + * <none> + */ +static int +RecvExtMove (req) + XimRequestPacket *req; +{ + CARD16 *buf_16 = (CARD16 *) req->data; + XIMID im_id; + XICID ic_id; + short x, y; + XIMClientRec *xc; + + im_id = cur_im_id = (XIMID) GET_CARD16 (buf_16[0]); /* 2 input-method-ID */ + if (!GetIMWithId (im_id)) + return XIM_BadProtocol; + + ic_id = cur_ic_id = (XICID) GET_CARD16 (buf_16[1]); /* 2 input-context-ID */ + if (!(xc = GetICWithId (ic_id))) + return XIM_BadProtocol; + + x = (short) GET_CARD16 (buf_16[2]); + y = (short) GET_CARD16 (buf_16[3]); + if (change_spotlocation (xc, x, y) != 0) + return XIM_BadSpotLocation; + else + return 0; + + /* asynchoronous request, no reply */ +} + +#endif /* defined(EXT_MOVE) || defined(SPOT) */ + +/* + * Function Name : AppendServerToProperty() + * Description : append server id to IM_SERVERS property. + * Don't use PropModeAppend that will propagate a same + * server id more and more in the property. + * Parameter : + * disp : pointer to X display. + * win : window that holds the property. + * imserver : our server id to be appended. + * Returned Value: + * True : success. + * False : error. + */ +static Bool +AppendServerToProperty (disp, win, imserver) + Display *disp; + Window win; + Atom imserver; +{ + Atom server_atom, actual_type; + Atom *atom_list, *new_list; + int actual_format; + unsigned long nitems, bytes_after; + unsigned char *prop_return; + int i; + + server_atom = XInternAtom (disp, XIM_SERVERS, False); + (void) XGetWindowProperty (disp, win, server_atom, 0L, 1000000L, False, XA_ATOM, &actual_type, &actual_format, &nitems, &bytes_after, &prop_return); + + if (nitems > 0 && (actual_type != XA_ATOM || actual_format != 32)) + { + return False; + } + if (nitems > 0) + { + /* + * search whether our server id has been registered or not. + */ + atom_list = (Atom *) prop_return; + for (i = 0; i < nitems; i++) + { + if (atom_list[i] == imserver) + return True; + } + new_list = (Atom *) Malloc ((nitems + 1) * sizeof (Atom)); + if (!new_list) + { + malloc_error ("no memory for atom list."); + return False; + } + (void) memcpy ((char *) new_list, (char *) prop_return, nitems * sizeof (Atom)); + new_list[nitems] = imserver; + } + else + { + new_list = &imserver; + } + + /* + * append our server id to IM_SERVERS property. + */ + XChangeProperty (disp, win, server_atom, XA_ATOM, 32, PropModeReplace, (unsigned char *) new_list, (nitems + 1)); + if (nitems > 0) + { + XFree ((char *) prop_return); + XFree ((char *) new_list); + } + return True; +} + +/*--------------------------------------------------------------------* + * * + * Public Functions * + * * + *--------------------------------------------------------------------*/ + +/* + * Function Name : XimError() + * Description : take the breakpoint of error when it occurs at any time. + * Parameter : + * fd : socket id of IM client. + * Returned Value: + * <none> + */ +#if NeedFunctionPrototypes +void +XimError (int fd) +#else +void +XimError (fd) + int fd; +#endif /* NeedFunctionPrototypes */ +{ + register XIMClientRec *xc; + + for (xc = ximclient_list; xc != NULL; xc = xc->next) + { + if (xc->fd == fd) + { + (void) RemoveIMWithId ((XIMID) xc->im_id); + } + } +} + +/* + * Function Name : XimRequestDispatch() + * Description : dispatch all requests of X11 IM protocol. + * Parameter : + * <none> + * Returned Value: + * <none> + */ +#if NeedFunctionPrototypes +void +XimRequestDispatch (void) +#else +void +XimRequestDispatch () +#endif /* NeedFunctionPrototypes */ +{ + XimRequestPacket req_data; + XimRequestPacket *req = &req_data; + int ret; + + ret = cur_status = 0; + if (RecvRequest (req) < 0) + return; + + /* respond each request of protocol */ + switch (req->major_opcode) + { + case XIM_AUTH_NEXT: + ret = SendAuthRequired ((CARD8) 0, (CARD8 *) NULL, (INT16) 0); + break; + case XIM_AUTH_REPLY: + ret = SendConnectReply (PROTOCOLMAJORVERSION, PROTOCOLMINORVERSION); + break; + case XIM_CONNECT: + ret = RecvConnect (req); + break; + case XIM_DISCONNECT: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; + ret = RecvDisconnect (req); + break; + case XIM_OPEN: + cur_status = XIM_IMID_VALID; + ret = RecvOpen (req); + break; + case XIM_CLOSE: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; + ret = RecvClose (req); + break; + case XIM_ENCODING_NEGOTIATION: + cur_status = XIM_IMID_VALID; + ret = RecvEncodingNegotiation (req); + break; + case XIM_QUERY_EXTENSION: + cur_status = XIM_IMID_VALID; + ret = RecvQueryExtension (req); + break; + case XIM_SET_IM_VALUES: + cur_status = XIM_IMID_VALID; + ret = RecvSetIMValues (req); + break; + case XIM_GET_IM_VALUES: + cur_status = XIM_IMID_VALID; + ret = RecvGetIMValues (req); + break; + case XIM_CREATE_IC: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; + ret = RecvCreateIC (req); + break; + case XIM_DESTROY_IC: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; + ret = RecvDestroyIC (req); + break; + case XIM_SET_IC_VALUES: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; + ret = RecvSetICValues (req); + break; + case XIM_GET_IC_VALUES: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; + ret = RecvGetICValues (req); + break; + case XIM_SET_IC_FOCUS: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; + (void) RecvSetICFocus (req); /* asyncronous request */ + break; + case XIM_UNSET_IC_FOCUS: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; + (void) RecvUnsetICFocus (req); /* asyncronous request */ + break; + case XIM_TRIGGER_NOTIFY: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; +#ifdef DYNAMIC_EVENT_FLOW_MODEL + ret = RecvTriggerNotify (req); +#else + ret = 0; +#endif /* DYNAMIC_EVENT_FLOW_MODEL */ + break; + case XIM_FORWARD_EVENT: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; + ret = RecvForwardEvent (req); + break; + case XIM_RESET_IC: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; + ret = RecvResetIC (req); + break; + case XIM_SYNC: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; + ret = RecvSync (req); + break; + case XIM_SYNC_REPLY: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; + (void) RecvSyncReply (req); /* don't need send anything */ + break; +#ifdef CALLBACKS + case XIM_PREEDIT_START_REPLY: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; + ret = RecvPreeditStartReply (req); + break; + case XIM_PREEDIT_CARET_REPLY: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; + ret = RecvPreeditCaretReply (req); + break; +#endif /* CALLBACKS */ + case XIM_STR_CONVERSION_REPLY: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; + ret = RecvStrConversionReply (req); + break; +#if defined(EXT_MOVE) || defined(SPOT) + case XIM_EXT_MOVE: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; + (void) RecvExtMove (req); /* asyncronous request */ + break; +#endif /* defined(EXT_MOVE) || defined(SPOT) */ + case XIM_ERROR: + cur_status = XIM_IMID_VALID | XIM_ICID_VALID; + (void) RecvError (req); /* asyncronous request */ + break; + default: + ret = XIM_BadProtocol; + } + if (ret) + SendError (ret); + FREE (req->data); +} + +/* + * Function Name : XimPreConnect() + * Description : make a base for preconnection with IM client. This + * includes to create all selection atoms, names and + * properties, plus some initial steps. + * Parameter : + * port : TCP/IP port number used in this IM protocol. + * root : default root client. + * Returned Value: + * = 0 : successed. + * = -1 : error, failed to make preconnection. + */ +#if NeedFunctionPrototypes +int +XimPreConnect (unsigned short port, /* port number 38036/tcp of xwnmo */ + XIMRootRec * root) +#else +int +XimPreConnect (port, root) + unsigned short port; /* port number 38036/tcp of xwnmo */ + XIMRootRec *root; +#endif /* NeedFunctionPrototypes */ +{ + char atom_name[BUFFER_MAX]; + char hostname[BUFFER_MAX]; + int len; + + /* + * make server atom: @server=xwnmo + */ + (void) sprintf (atom_name, "%s%s", XIM_SERVER_CATEGORY, XIM_SERVER_NAME); + if ((server_id = XInternAtom (dpy, atom_name, True)) != (Atom) None) + { + if (XGetSelectionOwner (dpy, server_id) != (Window) None) + { + print_out ("Another server has been already running."); + return -1; + } + } + else + { + server_id = XInternAtom (dpy, atom_name, False); + } + + if (AppendServerToProperty (dpy, root->root_window, server_id) == False) + return -1; + + /* + * make target XIM_LOCALES: "@locale=ja,ja_JP,..." + */ + (void) strcpy (atom_name, XIM_LOCAL_CATEGORY); + locale_supported = (unsigned char *) GetLocaleSupported (); + len = strlen (atom_name); + if (!(locale_prop = (unsigned char *) Malloc (len + strlen (locale_supported) + 1))) + { + malloc_error ("allocation of locale property"); + return -1; + } + locale_target = XInternAtom (dpy, XIM_LOCALES, False); + (void) strcpy (locale_prop, atom_name); + (void) strcat (locale_prop, locale_supported); + locale_supported = locale_prop + len; + + /* + * make target XIM_TRANSPORT: "tcp/hostname:port" + */ + (void) XmuGetHostname (hostname, (sizeof hostname)); + (void) sprintf (atom_name, "%stcp/%s:%u", XIM_TRANSPORT_CATEGORY, hostname, port); + len = strlen (atom_name); + if (!(transport_prop = (unsigned char *) Malloc (len + 1))) + { + malloc_error ("allocation of transport property"); + return -1; + } + transport_target = XInternAtom (dpy, XIM_TRANSPORT, False); + (void) strcpy (transport_prop, atom_name); + + XSetSelectionOwner (dpy, server_id, root->ximclient->w, 0L); + + InitiateProtocol (); + + return 0; +} + +/* + * Function Name : XimConvertTarget() + * Description : convert a selection target and send its property + * to client. This is in preconnection phase. + * Parameter : + * dpy : pointer to X display. + * event : selection event. + * Returned Value: + * <none> + */ +#if NeedFunctionPrototypes +void +XimConvertTarget (Display * dpy, XSelectionRequestEvent * event) +#else +void +XimConvertTarget (dpy, event) + Display *dpy; + XSelectionRequestEvent *event; +#endif /* NeedFunctionPrototypes */ +{ + XSelectionEvent new; + unsigned char *string = (unsigned char *) NULL; + + bzero (&new, sizeof (XSelectionEvent)); + new.type = SelectionNotify; + new.serial = event->serial; + new.display = event->display; + new.requestor = event->requestor; + new.selection = event->selection; + new.target = event->target; + new.time = event->time; + new.property = event->property; + + if (event->selection == server_id) + { + if (event->target == locale_target) + string = locale_prop; + else if (event->target == transport_target) + string = transport_prop; + if (string) + { + XChangeProperty (dpy, event->requestor, event->property, event->target, 8, PropModeReplace, string, strlen ((char *) string)); + XFlush (dpy); + } + } + XSendEvent (dpy, event->requestor, False, NoEventMask, (XEvent *) & new); +} + +/* + * Function Name : xim_send_ct() + * Description : similar to Xsi IM send_ct(). + * Parameter : + * ct : CT string + * ct_len : length of string in byte. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +#if NeedFunctionPrototypes +int +xim_send_ct (register char *ct, register int ct_len) +#else +int +xim_send_ct (ct, ct_len) + register char *ct; + register int ct_len; +#endif /* NeedFunctionPrototypes */ +{ + return SendCommit (CUR_IM_ID (), CUR_IC_ID (), XimLookupChars, (KeySym) 0, ct, ct_len); +} + +/* + * Function Name : xim_send_keysym() + * Description : similar to Xsi IM send_keysym(). + * Parameter : + * keysym : keysym code + * str : keysym character. + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +#if NeedFunctionPrototypes +int +xim_send_keysym (KeySym keysym, char str) +#else +int +xim_send_keysym (keysym, str) + KeySym keysym; + char str; +#endif /* NeedFunctionPrototypes */ +{ + if (keysym < 0x20) + { + keysym |= 0xff00; + return SendCommit (CUR_IM_ID (), CUR_IC_ID (), XimLookupKeySym, keysym, (char *) NULL, 0); + } + else + { + str &= 0xff; + return SendCommit (CUR_IM_ID (), CUR_IC_ID (), XimLookupBoth, keysym, &str, 1); + } +} + +/* + * Function Name : xim_send_nofilter() + * Description : similar to Xsi IM send_nofilter(). + * Parameter : + * <none> + * Returned Value: + * = 0 : successed. + * > 0 : error, the number is error code. + */ +#if NeedFunctionPrototypes +int +xim_send_nofilter (void) +#else +int +xim_send_nofilter () +#endif /* NeedFunctionPrototypes */ +{ + XEvent *xev = CUR_CLIENT_EVENT (); + int serial = XIM_SERIALNUMBER (((XAnyEvent *) xev)->serial); + + return SendForwardEvent (CUR_IM_ID (), CUR_IC_ID (), serial, xev); +} + +#ifdef CALLBACKS + +/* + * Function Name : xim_send_preeditstart() + * Description : similar to Xsi IM send_preeditstart(). + * Parameter : + * <none> + * Returned Value: + * <none> + */ +#if NeedFunctionPrototypes +void +xim_send_preeditstart (void) +#else +void +xim_send_preeditstart () +#endif /* NeedFunctionPrototypes */ +{ + (void) SendIdOnly (CUR_IM_ID (), CUR_IC_ID (), XIM_PREEDIT_START, 0); +} + +/* + * Function Name : xim_send_preeditdraw() + * Description : similar to Xsi IM send_preeditdraw(). + * Parameter : + * caret : caret + * first : first of change. + * chg_len : length of change. + * str : wchar string. + * len : length of string in wchar. + * flg : flag + * Returned Value: + * <none> + */ +#if NeedFunctionPrototypes +void +xim_send_preeditdraw (int caret, int first, int chg_len, wchar * str, int len, int flg) +#else +void +xim_send_preeditdraw (caret, first, chg_len, str, len, flg) + int caret; + int first; + int chg_len; + wchar *str; + int len; + int flg; +#endif /* NeedFunctionPrototypes */ +{ + unsigned short fb = 0; + int send_len; + XIMFeedback xim_fb; + + if (str) + { + while (1) + { + send_len = wchar_to_ct (cur_p->cur_xl->xlc, str, ct_buf, len, ct_buf_max); + if (send_len < -1) + { + return; + } + else if (send_len == -1) + { + if (realloc_ct_buf () < 0) + return; + } + else + { + break; + } + } + } + else + { + send_len = 0; + } + if (flg & REV_FLAG) + fb |= XIMReverse; + if (flg & UNDER_FLAG) + fb |= XIMUnderline; + if (flg & BOLD_FLAG) + fb |= XIMHighlight; + + xim_fb = (XIMFeedback) fb; + (void) SendPreeditDraw (CUR_IM_ID (), CUR_IC_ID (), caret, first, chg_len, ct_buf, send_len, (XIMFeedback *) & xim_fb, 1); +} + +/* + * Function Name : xim_send_preeditcaret() + * Description : similar to Xsi IM send_preeditcaret(). + * Parameter : + * pos : position + * flg : flag + * Returned Value: + * <none> + */ +#if NeedFunctionPrototypes +void +xim_send_preeditcaret (int flg, int pos) +#else +void +xim_send_preeditcaret (flg, pos) + int flg; + int pos; +#endif /* NeedFunctionPrototypes */ +{ + int style; + + if (flg) + { + style = XIMIsPrimary; + } + else + { + style = XIMIsInvisible; + } + (void) SendPreeditCaret (CUR_IM_ID (), CUR_IC_ID (), pos, XIMAbsolutePosition, style); +} + +/* + * Function Name : xim_send_preeditdone() + * Description : similar to Xsi IM send_preeditdone(). + * Parameter : + * <none> + * Returned Value: + * <none> + */ +#if NeedFunctionPrototypes +void +xim_send_preeditdone (void) +#else +void +xim_send_preeditdone () +#endif /* NeedFunctionPrototypes */ +{ + (void) SendIdOnly (CUR_IM_ID (), CUR_IC_ID (), XIM_PREEDIT_DONE, 0); +} + +/* + * Function Name : xim_send_statusstart() + * Description : similar to Xsi IM send_statusstart(). + * Parameter : + * <none> + * Returned Value: + * <none> + */ +#if NeedFunctionPrototypes +void +xim_send_statusstart (void) +#else +void +xim_send_statusstart () +#endif /* NeedFunctionPrototypes */ +{ + (void) SendIdOnly (CUR_IM_ID (), CUR_IC_ID (), XIM_STATUS_START, 0); +} + +/* + * Function Name : xim_send_statusdraw() + * Description : similar to Xsi IM send_statusdraw(). + * Parameter : + * str : wchar string. + * len : length of string in wchar. + * Returned Value: + * <none> + */ +#if NeedFunctionPrototypes +void +xim_send_statusdraw (wchar * str, int len) +#else +void +xim_send_statusdraw (str, len) + wchar *str; + int len; +#endif /* NeedFunctionPrototypes */ +{ + int send_len; + + /* refer to callback.c: send_statusdraw() */ + while (1) + { + send_len = wchar_to_ct (cur_p->cur_xl->xlc, str, ct_buf, len, ct_buf_max); + if (send_len < -1) + { + return; + } + else if (send_len == -1) + { + if (realloc_ct_buf () < 0) + return; + } + else + { + break; + } + } + (void) SendStatusDraw (CUR_IM_ID (), CUR_IC_ID (), XIMTextType, ct_buf, send_len, (XIMFeedback *) NULL, 0, (PIXMAP) 0); +} + +/* + * Function Name : xim_send_statusdone() + * Description : similar to Xsi IM send_statusdone(). + * Parameter : + * <none> + * Returned Value: + * <none> + */ +#if NeedFunctionPrototypes +void +xim_send_statusdone (void) +#else +void +xim_send_statusdone () +#endif /* NeedFunctionPrototypes */ +{ + (void) SendIdOnly (CUR_IM_ID (), CUR_IC_ID (), XIM_STATUS_DONE, 0); +} + +#endif /* CALLBACKS */ + +#endif /* !X11R5 */