Mercurial > freewnn
view Xwnmo/xwnmo/ximdispt.c @ 3:ed4bb01eb317
- suppress warnings.
- partially fixed comparison between pointer and 0.
author | Yoshiki Yazawa <yaz@cc.rim.or.jp> |
---|---|
date | Thu, 13 Dec 2007 19:53:14 +0900 |
parents | bbc77ca4def5 |
children |
line wrap: on
line source
/* * $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 */