diff lib/imlib/imrequest.c @ 0:92745d501b9a

initial import from kinput2-v3.1
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Mon, 08 Mar 2010 04:44:30 +0900
parents
children 1f9e9cb00c6c
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/imlib/imrequest.c	Mon Mar 08 04:44:30 2010 +0900
@@ -0,0 +1,1452 @@
+#ifndef lint
+static char *rcsid = "$Id: imrequest.c,v 1.19 2002/01/27 11:33:37 ishisone Exp $";
+#endif
+/*
+ * Copyright (c) 1994  Software Research Associates, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Software Research Associates not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  Software Research
+ * Associates makes no representations about the suitability of this software
+ * for any purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * Author:  Makoto Ishisone, Software Research Associates, Inc., Japan
+ */
+
+/* in order to include xEvent definition */
+#define NEED_EVENTS
+#include <X11/Xproto.h>
+
+#include "im.h"
+#include "imreq.h"
+
+/*
+ * Request handle functions
+ */
+static void ximDisconnectProc _Pt_((IMConnection *, int, int, int));
+static void ximErrorProc _Pt_((IMConnection *, int, int, int));
+static void ximOpenProc _Pt_((IMConnection *, int, int, int));
+static void ximCloseProc _Pt_((IMConnection *, int, int, int));
+static void ximTriggerNotifyProc _Pt_((IMConnection *, int, int, int));
+static void ximEncodingNegotiationProc _Pt_((IMConnection *, int, int, int));
+static void ximQueryExtensionProc _Pt_((IMConnection *, int, int, int));
+static void ximSetIMValuesProc _Pt_((IMConnection *, int, int, int));
+static void ximGetIMValuesProc _Pt_((IMConnection *, int, int, int));
+static void ximCreateICProc _Pt_((IMConnection *, int, int, int));
+static void ximDestroyICProc _Pt_((IMConnection *, int, int, int));
+static void ximSetICValuesProc _Pt_((IMConnection *, int, int, int));
+static void ximGetICValuesProc _Pt_((IMConnection *, int, int, int));
+static void ximSetICFocusProc _Pt_((IMConnection *, int, int, int));
+static void ximUnsetICFocusProc _Pt_((IMConnection *, int, int, int));
+static void ximForwardEventProc _Pt_((IMConnection *, int, int, int));
+static void ximExtForwardKeyeventProc _Pt_((IMConnection *, int, int, int));
+static void ximSyncProc _Pt_((IMConnection *, int, int, int));
+static void ximSyncReplyProc _Pt_((IMConnection *, int, int, int));
+static void ximResetICProc _Pt_((IMConnection *, int, int, int));
+static void ximExtMoveProc _Pt_((IMConnection *, int, int, int));
+
+static void ximAlreadyConnectedProc _Pt_((IMConnection *, int, int, int));
+static void ximShouldNotBeSentProc _Pt_((IMConnection *, int, int, int));
+static void ximAuthPhaseProc _Pt_((IMConnection *, int, int, int));
+static void ximNopProc _Pt_((IMConnection *, int, int, int));
+
+/*
+ * Core request table
+ */
+static IMRequest coreRequestTbl[] = {
+    { "CONNECT", XIM_CONNECT, 0, ximAlreadyConnectedProc },
+    { "CONNECT-REPLY", XIM_CONNECT_REPLY, 0, ximShouldNotBeSentProc },
+    { "DISCONNECT", XIM_DISCONNECT, 0, ximDisconnectProc },
+    { "DISCONNECT-REPLY", XIM_DISCONNECT_REPLY, 0, ximShouldNotBeSentProc },
+    { "AUTH-REQUIRED", XIM_AUTH_REQUIRED, 0, ximAuthPhaseProc },
+    { "AUTH-REPLY", XIM_AUTH_REPLY, 0, ximAuthPhaseProc },
+    { "AUTH-NEXT", XIM_AUTH_NEXT, 0, ximAuthPhaseProc },
+    { "AUTH-SETUP", XIM_AUTH_SETUP, 0, ximShouldNotBeSentProc },
+    { "AUTH-NG", XIM_AUTH_NG, 0, ximAuthPhaseProc },
+    { "ERROR", XIM_ERROR, 0, ximErrorProc },
+    { "OPEN", XIM_OPEN, 0, ximOpenProc },
+    { "OPEN-REPLY", XIM_OPEN_REPLY, 0, ximShouldNotBeSentProc },
+    { "CLOSE", XIM_CLOSE, 0, ximCloseProc },
+    { "CLOSE-REPLY", XIM_CLOSE_REPLY, 0, ximShouldNotBeSentProc },
+    { "SET-EVENT-MASK", XIM_SET_EVENT_MASK, 0, ximShouldNotBeSentProc },
+    { "REGISTER-TRIGGERKEYS", XIM_REGISTER_TRIGGERKEYS, 0,
+	  ximShouldNotBeSentProc },
+    { "TRIGGER-NOTIFY", XIM_TRIGGER_NOTIFY, 0, ximTriggerNotifyProc },
+    { "TRIGGER-NOTIFY-REPLY", XIM_TRIGGER_NOTIFY_REPLY, 0,
+	  ximShouldNotBeSentProc },
+    { "ENCODING-NEGOTIATION", XIM_ENCODING_NEGOTIATION, 0,
+	  ximEncodingNegotiationProc },
+    { "ENCODING-NEGOTIATION-REPLY", XIM_ENCODING_NEGOTIATION_REPLY, 0,
+	  ximShouldNotBeSentProc },
+    { "QUERY-EXTENSION", XIM_QUERY_EXTENSION, 0, ximQueryExtensionProc },
+    { "QUERY-EXTENSION-REPLY", XIM_QUERY_EXTENSION_REPLY, 0,
+	  ximShouldNotBeSentProc },
+    { "SET-IM-VALUES", XIM_SET_IM_VALUES, 0, ximSetIMValuesProc },
+    { "SET-IM-VALUES-REPLY", XIM_SET_IM_VALUES_REPLY, 0,
+	  ximShouldNotBeSentProc },
+    { "GET-IM-VALUES", XIM_GET_IM_VALUES, 0, ximGetIMValuesProc },
+    { "GET-IM-VALUES-REPLY", XIM_GET_IM_VALUES_REPLY, 0,
+	  ximShouldNotBeSentProc },
+    { "CREATE-IC", XIM_CREATE_IC, 0, ximCreateICProc },
+    { "CREATE-IC-REPLY", XIM_CREATE_IC_REPLY, 0, ximShouldNotBeSentProc },
+    { "DESTROY-IC", XIM_DESTROY_IC, 0, ximDestroyICProc },
+    { "DESTROY-IC-REPLY", XIM_DESTROY_IC_REPLY, 0, ximShouldNotBeSentProc },
+    { "SET-IC-VALUES", XIM_SET_IC_VALUES, 0, ximSetICValuesProc },
+    { "SET-IC-VALUES-REPLY", XIM_SET_IC_VALUES_REPLY, 0,
+	  ximShouldNotBeSentProc },
+    { "GET-IC-VALUES", XIM_GET_IC_VALUES, 0, ximGetICValuesProc },
+    { "GET-IC-VALUES-REPLY", XIM_GET_IC_VALUES_REPLY, 0,
+	  ximShouldNotBeSentProc },
+    { "SET-IC-FOCUS", XIM_SET_IC_FOCUS, 0, ximSetICFocusProc },
+    { "UNSET-IC-FOCUS", XIM_UNSET_IC_FOCUS, 0, ximUnsetICFocusProc },
+    { "FORWARD-EVENT", XIM_FORWARD_EVENT, 0, ximForwardEventProc },
+    { "SYNC", XIM_SYNC, 0, ximSyncProc },
+    { "SYNC-REPLY", XIM_SYNC_REPLY, 0, ximSyncReplyProc },
+    { "COMMIT", XIM_COMMIT, 0, ximShouldNotBeSentProc },
+    { "RESET-IC", XIM_RESET_IC, 0, ximResetICProc },
+    { "RESET-IC-REPLY", XIM_RESET_IC_REPLY, 0, ximShouldNotBeSentProc },
+    { "GEOMETRY", XIM_GEOMETRY, 0, ximShouldNotBeSentProc },
+    { "STR-CONVERSION", XIM_STR_CONVERSION, 0, ximShouldNotBeSentProc },
+    { "STR-CONVERSION-REPLY", XIM_STR_CONVERSION_REPLY, 0,
+	  ximShouldNotBeSentProc },
+    { "PREEDIT-START", XIM_PREEDIT_START, 0, ximShouldNotBeSentProc },
+    { "PREEDIT-START-REPLY", XIM_PREEDIT_START_REPLY, 0,
+	  ximNopProc },
+    { "PREEDIT-DRAW", XIM_PREEDIT_DRAW, 0, ximShouldNotBeSentProc },
+    { "PREEDIT-CARET", XIM_PREEDIT_CARET, 0, ximShouldNotBeSentProc },
+    { "PREEDIT-CARET-REPLY", XIM_PREEDIT_CARET_REPLY, 0,
+	  ximNopProc },
+    { "PREEDIT-DONE", XIM_PREEDIT_DONE, 0, ximShouldNotBeSentProc },
+    { "PREEDITSTATE", XIM_PREEDITSTATE, 0, ximShouldNotBeSentProc },
+    { "STATUS-START", XIM_STATUS_START, 0, ximShouldNotBeSentProc },
+    { "STATUS-DRAW", XIM_STATUS_DRAW, 0, ximShouldNotBeSentProc },
+    { "STATUS-DONE", XIM_STATUS_DONE, 0, ximShouldNotBeSentProc },
+    { NULL, 0, 0, NULL },
+};
+
+/*
+ * Extension request table
+ */
+static IMRequest extRequestTbl[] = {
+    { "XIM_EXT_SET_EVENT_MASK", XIM_EXT_SET_EVENT_MASK, 0,
+	  ximShouldNotBeSentProc, XIM_EXT_SET_EVENT_MASK_MASK },
+    { "XIM_EXT_FORWARD_KEYEVENT", XIM_EXT_FORWARD_KEYEVENT, 0,
+	  ximExtForwardKeyeventProc, XIM_EXT_FORWARD_KEYEVENT_MASK },
+    { "XIM_EXT_MOVE", XIM_EXT_MOVE, 0,
+	  ximExtMoveProc, XIM_EXT_MOVE_MASK },
+    { NULL, 0, 0, NULL },
+};
+
+/*
+ * Request dispatch table (global)
+ */
+IMRequest *IMMainDispatchTable[256];
+
+
+static void compileTbl _Pt_((IMRequest *req));
+static char *ecode2str _Pt_((int code));
+static void putTriggerkeyList _Pt_((IMIM *imp));
+static int findCtext _Pt_((IMConnection *conn, int arglen));
+static IMRequest *getExtension _Pt_((char *name));
+static void putExtension _Pt_((IMConnection *conn, IMRequest *req));
+static void swapData _Pt_((char *data, char *format));
+static int getEvent _Pt_((IMConnection *conn, unsigned int serial,
+			  int offset, XEvent *ev));
+static void postponeEvent _Pt_((IMIC *icp, int synchronous, XEvent *ev));
+static void handleForwardedEvent _Pt_((IMIC *icp, int synchronous, XEvent *ev));
+static void processPendingEvents _Pt_((IMIC *icp,
+				       IMPendingEvent *pending_event));
+
+
+/*- compileTbl: assemble IMMainDispatchTbl -*/
+static void
+compileTbl(req)
+IMRequest *req;
+{
+    while (req->name != NULL) {
+	req->next = IMMainDispatchTable[req->major];
+	IMMainDispatchTable[req->major] = req;
+	req++;
+    }
+}
+
+/*- ximDisconnectProc: handle XIM_DISCONNECT request -*/
+/* ARGSUSED */
+static void
+ximDisconnectProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIM *imp = conn->im_list;
+    IMIM *imp_next;
+
+    TRACE(("ximDisconnectProc(#%d)\n", conn->serial));
+
+    if (arglen != 0) {
+	DPRINT(("ximDisconnectProc: arglen != 0\n"));
+	IMSendBadLength(conn, 0, 0);
+	return;
+    }
+
+    while (imp != NULL) {
+	imp_next = imp->next;
+	IMDestroyIM(imp);
+	imp = imp_next;
+    }
+    IMSendSimpleRequest(conn, XIM_DISCONNECT_REPLY, 0);
+    IMSchedule(conn, SCHED_CLOSE);
+}
+
+/*- ecode2str: error code to error name string converter -*/
+static char *
+ecode2str(code)
+int code;
+{
+    char *s;
+
+    switch (code) {
+    case IMBadAlloc:		s = "BadAlloc"; break;
+    case IMBadStyle:		s = "BadStyle"; break;
+    case IMBadClientWindow:	s = "BadClientWindow"; break;
+    case IMBadFocusWindow:	s = "BadFocusWindow"; break;
+    case IMBadArea:		s = "BadArea"; break;
+    case IMBadSpotLocation:	s = "BadSpotLocation"; break;
+    case IMBadColormap:		s = "BadColormap"; break;
+    case IMBadAtom:		s = "BadAtom"; break;
+    case IMBadPixel:		s = "BadPixel"; break;
+    case IMBadPixmap:		s = "BadPixmap"; break;
+    case IMBadName:		s = "BadName"; break;
+    case IMBadCursor:		s = "BadCursor"; break;
+    case IMBadProtocol:		s = "BadProtocol"; break;
+    case IMBadForeground:	s = "BadForeground"; break;
+    case IMBadBackground:	s = "BadBackground"; break;
+    case IMLocaleNotSupported:	s = "LocaleNotSupported"; break;
+    case IMBadSomething:	s = "BadSomething"; break;
+    default:			s = "? (undefined error code)"; break;
+    }
+    return s;
+}
+
+/*- ximErrorProc: handle XIM_Error messsage -*/
+/* ARGSUSED */
+static void
+ximErrorProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    unsigned int imid, icid;
+    int flag;
+    int code;
+    int msg_len;
+    char msg[256 + 1];
+
+    TRACE(("ximErrorProc(#%d)\n", conn->serial));
+
+    if (arglen < 10) {
+	DPRINT(("corrupted XIM_ERROR message (arglen < 10) received\n"));
+	return;
+    }
+    imid = IMGetC16(conn, 0);
+    icid = IMGetC16(conn, 2);
+    flag = IMGetC16(conn, 4);
+    code = IMGetC16(conn, 6);
+    msg_len = IMGetC16(conn, 8);
+    if (msg_len > 0) {
+	if (msg_len + 12 > arglen) {
+	    DPRINT(("corrupted XIM_ERROR message (message too long) received\n"));
+	    return;
+	}
+	if (msg_len > 256) msg_len = 256;
+	IMGetString(conn, 12, msg, msg_len);
+    }
+    if (DEBUG_CONDITION) {
+	printf("** XIM_ERROR message received:\n");
+	if (flag & 1) {
+	    printf("\t input-method ID: %d\n", imid);
+	} else {
+	    printf("\t input-method ID: N/A\n");
+	}
+	if (flag & 2) {
+	    printf("\tinput-context ID: %d\n", icid);
+	} else {
+	    printf("\tinput-context ID: N/A\n");
+	}
+	printf("\t      error code: %s\n", ecode2str(code));
+	printf("\t   error message: %s\n", msg);
+    }
+}
+
+/*- putTriggerkeyList: put trigger key list on the output stream -*/
+static void
+putTriggerkeyList(imp)
+IMIM *imp;
+{
+    IMConnection *conn = imp->connection;
+    IMTriggerKey *triggers;
+    int num_triggers;
+    int i;
+
+    triggers = IMTriggerKeys(imp, &num_triggers);
+
+    IMPutC32(conn, (unsigned long)(12 * num_triggers));
+    for (i = 0; i < num_triggers; i++) {
+	IMPutC32(conn, triggers[i].keysym);
+	IMPutC32(conn, (unsigned long)triggers[i].modifiers);
+	IMPutC32(conn, (unsigned long)triggers[i].check_modifiers);
+    }
+}
+
+/*- ximOpenProc: handle XIM_OPEN request -*/
+/* ARGSUSED */
+static void
+ximOpenProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    int locale_len;
+    char localename[256 + 1];
+    int offset;
+    IMConverter *icp;
+    IMIM *imp;
+
+    TRACE(("ximOpenProc(#%d)\n", conn->serial));
+
+    if (arglen < 1) {
+	DPRINT(("ximOpenProc: arglen < 1\n"));
+	IMSendBadLength(conn, 0, 0);
+	return;
+    }
+
+    locale_len = IMGetC8(conn, 0);
+    if (arglen < locale_len + 1) {
+	DPRINT(("ximOpenProc: locale too long\n"));
+	IMSendBadLength(conn, 0, 0);
+	return;
+    }
+
+    bcopy(IMBUFDATA(IM_INBUF(conn)) + 1, localename, locale_len);
+    localename[locale_len] = '\0';
+    TRACE(("\tlocalename: %s\n", localename));
+
+    if ((icp = IMGetConverter(conn->proto_widget, localename)) == NULL) {
+	DPRINT(("ximOpenProc: unsupported locale %s\n", localename));
+	IMSendError(conn, IMLocaleNotSupported, 0, 0, "unknown locale");
+	return;
+    }
+
+    imp = IMCreateIM(conn, icp);
+
+    /*
+     * Send open reply message.
+     */
+    offset = IMPutHeader(conn, XIM_OPEN_REPLY, 0, 0);
+    IMPutC16(conn, imp->id);
+    IMPutIMAttrList(imp);
+    IMPutICAttrList(imp);
+    IMFinishRequest(conn, offset);
+
+    /*
+     * Notify conversion trigger keys.
+     *
+     * Note:
+     * The spec says that XIM_REGISTER_TRIGGERKEYS message should
+     * be sent to the client bofore XIM_OPEN_REPLY message, in
+     * order to use dynamic event flow model.  However, this
+     * does not work with current Xlib implementation.  So we
+     * send XIM_REGISTER_TRIGGERKEYS just after XIM_OPEN_REPLY,
+     * which works fine.
+     */
+    offset = IMPutHeader(conn, XIM_REGISTER_TRIGGERKEYS, 0, 0);
+    IMPutC16(conn, imp->id);
+    IMPutC16(conn, 0);
+    putTriggerkeyList(imp);
+    IMFinishRequest(conn, offset);
+}
+
+/*- ximCloseProc: handle XIM_CLOSE request -*/
+/* ARGSUSED */
+static void
+ximCloseProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIM *imp;
+
+    TRACE(("ximCloseProc(#%d)\n", conn->serial));
+
+    if ((imp = IMGetIM(conn, arglen)) == NULL) return;
+    if (arglen != 4) {
+	DPRINT(("ximCloseProc: arglen != 4\n"));
+	IMSendBadLength(conn, imp->id, 0);
+	return;
+    }
+
+    IMPutHeader(conn, XIM_CLOSE_REPLY, 0, 4);
+    IMPutC16(conn, imp->id);
+    IMPutPad(conn);
+    IMSchedule(conn, SCHED_WRITE);
+
+    IMDestroyIM(imp);
+}
+
+/*- ximTriggerNotifyProc: handle XIM_TRIGGER_NOTIFY request -*/
+/* ARGSUSED */
+static void
+ximTriggerNotifyProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIC *icp;
+    int flag;
+    int key_index;
+    int num_triggers;
+
+    TRACE(("ximTriggerNotifyProc(#%d)\n", conn->serial));
+
+    if ((icp = IMGetIC(conn, arglen)) == NULL) return;
+
+    if (arglen != 16) {
+	DPRINT(("ximTriggerNotifyProc: arglen != 16\n"));
+	IMSendBadLength(conn, icp->im->id, icp->id);
+	return;
+    }
+
+    flag = (int)IMGetC32(conn,  4);
+    key_index = (int)IMGetC32(conn, 8);
+    TRACE(("\tflag=%d, index=%d\n", flag, key_index));
+
+    /*
+     * Check flag and index.  Since kinput2 does not
+     * specifiy off-keys, any off-key notifications
+     * are invalid.
+     * The current Xlib implementation (as of pl4)
+     * specifies incorrect key_index, so index check
+     * is turned off until the bug is fixed.
+     */
+
+    (void)IMTriggerKeys(icp->im, &num_triggers);
+    if (flag != 0
+#ifndef XIM_BC
+	 || key_index >= num_triggers
+#endif /* XIM_BC */
+	) {
+	/* invalid parameter */
+	DPRINT(("ximTriggerNotifyProc: invalid trigger spec.\n"));
+	IMSendError(conn, IMBadSomething, icp->im->id, icp->id,
+		    "invalid trigger key specification");
+	return;
+    }
+
+    /*
+     * If we are already in conversion mode, do nothing special.
+     */
+    if (!(icp->state & IC_CONVERTING)) {
+	/*
+	 * Start conversion.
+	 */
+	if (IMStartConversion(icp) < 0) return;
+    }
+
+    /*
+     * Send XIM_TRIGGER_NOTIFY_REPLY request.
+     */
+    (void)IMPutHeader(conn, XIM_TRIGGER_NOTIFY_REPLY, 0, 4);
+    IMPutC16(conn, icp->im->id);
+    IMPutC16(conn, icp->id);
+    IMSchedule(conn, SCHED_WRITE);
+}
+
+/*- findCtext: look up COMPOUND_TEXT from encoding list -*/
+static int
+findCtext(conn, arglen)
+IMConnection *conn;
+int arglen;
+{
+    int offset, name_end;
+    int encoding_index;
+    unsigned int name_bytes;
+
+    offset = 2;
+    name_bytes = IMGetC16(conn, offset);
+    offset += 2;
+    name_end = offset + name_bytes;
+    if (name_end > arglen) return -2;
+
+    /*
+     * Examine encodings listed by name.
+     */
+    encoding_index = 0;
+    while (offset < name_end) {
+	char str_buf[256 + 1];
+	int str_len;
+
+	str_len = IMGetC8(conn, offset++);
+	IMGetString(conn, offset, str_buf, str_len);
+	if (!strcmp(str_buf, "COMPOUND_TEXT")) {
+	    return encoding_index;
+	}
+	offset += str_len;
+	encoding_index++;
+    }
+
+    /*
+     * Encodings listed by detailed data follow, but
+     * I have no idea what they are.
+     */
+    return -1;
+}
+
+/*- ximEncodingNegotiationProc: handle XIM_ENCODING_NEGOTIATION request -*/
+/* ARGSUSED */
+static void
+ximEncodingNegotiationProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIM *imp;
+    int encoding_index;
+
+    TRACE(("ximEncodingNegotiationProc(#%d)\n", conn->serial));
+
+    if ((imp = IMGetIM(conn, arglen)) == NULL) return;
+
+    if (arglen < 8) {
+	DPRINT(("ximEncodingNegotiationProc: arglen < 8\n"));
+	IMSendBadLength(conn, imp->id, 0);
+	return;
+    }
+
+    /*
+     * Always use COMPOUND_TEXT.
+     */
+    if ((encoding_index = findCtext(conn, arglen)) < -1) {
+	/* bad argument error */
+	DPRINT(("ximEncodingNegotiationProc: encoding list corrupted\n"));
+	IMSendError(conn, IMBadSomething, imp->id, 0,
+		    "corrupted argument");
+	return;
+    }
+    TRACE(("\tselected encoding index: %d\n", encoding_index));
+
+    (void)IMPutHeader(conn, XIM_ENCODING_NEGOTIATION_REPLY, 0, 8);
+    IMPutC16(conn, imp->id);
+    IMPutC16(conn, 0);
+    IMPutI16(conn, encoding_index);
+    IMPutPad(conn);
+    IMSchedule(conn, SCHED_WRITE);
+}
+
+/*- getExtension: search named extension -*/
+static IMRequest *
+getExtension(name)
+char *name;
+{
+    IMRequest *req = extRequestTbl;
+
+    while (req->name != NULL) {
+	if (!strcmp(req->name, name)) return req;
+	req++;
+    }
+    return NULL;
+}
+
+/*- putExtension: put extension information on the output stream -*/
+static void
+putExtension(conn, req)
+IMConnection *conn;
+IMRequest *req;
+{
+    int text_length;
+
+    text_length = strlen(req->name);
+    IMPutC8(conn, req->major);
+    IMPutC8(conn, req->minor);
+    IMPutC16(conn, (unsigned int)text_length);
+    IMPutString(conn, req->name, text_length);
+    IMPutPad(conn);
+}
+
+/*- ximQueryExtensionProc: handle XIM_QUERY_EXTENSION request -*/
+/* ARGSUSED */
+static void
+ximQueryExtensionProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIM *imp;
+    int ext_len;
+    int cur_off;
+    int req_offset;
+    int size_offset;
+    int list_start, list_end;
+
+    TRACE(("ximQueryExtensionProc(#%d)\n", conn->serial));
+
+    if ((imp = IMGetIM(conn, arglen)) == NULL) return;
+    if (arglen < 4) {
+	DPRINT(("ximQueryExtensionProc: arglen < 4\n"));
+	IMSendBadLength(conn, imp->id, 0);
+	return;
+    }
+    ext_len = IMGetC16(conn, 2);
+    if (4 + ext_len > arglen) {
+	DPRINT(("ximQueryExtensionProc: extension list too long\n"));
+	IMSendBadLength(conn, imp->id, 0);
+	return;
+    }
+    cur_off = 4;
+
+    req_offset = IMPutHeader(conn, XIM_QUERY_EXTENSION_REPLY, 0, 0);
+    IMPutC16(conn, imp->id);
+    size_offset = IMWritePos(conn);
+    IMPutC16(conn, 0);		/* dummy. overwritten afterwards */
+
+    list_start = IMWritePos(conn);
+
+    if (ext_len == 0) {
+	IMRequest *ext_req = extRequestTbl;
+
+	while (ext_req->name != NULL) {
+	    putExtension(conn, ext_req);
+	    ext_req++;
+	}
+
+    } else {
+	IMRequest *ext_req;
+
+	while (ext_len > 1) {
+	    int str_len;
+	    char ext_name[256 + 1];
+
+	    str_len = IMGetC8(conn, cur_off);
+	    cur_off++;
+
+	    if (str_len + 1 > ext_len) {
+		DPRINT(("ximQueryExtensionProc: extension name too long\n"));
+		IMCancelRequest(conn, req_offset);
+		/* BadString */
+		IMSendBadLength(conn, imp->id, 0);
+		return;
+	    }
+
+	    IMGetString(conn, cur_off, ext_name, str_len);
+	    TRACE(("\tclient queries %s extension\n", ext_name));
+
+	    if ((ext_req = getExtension(ext_name)) != NULL) {
+		putExtension(conn, ext_req);
+		imp->mask |= ext_req->mask;
+	    }
+	    cur_off += str_len;
+	    ext_len -= str_len + 1;
+	}
+    }
+
+    list_end = IMWritePos(conn);
+    IMRewriteC16(conn, size_offset, (unsigned int)(list_end - list_start));
+
+    IMFinishRequest(conn, req_offset);
+}
+
+/*- ximSetIMValuesProc: handle XIM_SET_IM_VALUES request -*/
+/* ARGSUSED */
+static void
+ximSetIMValuesProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIM *imp;
+    char *attr;
+    int attr_len;
+
+    TRACE(("ximSetIMValuesProc(#%d)\n", conn->serial));
+
+    if ((imp = IMGetIM(conn, arglen)) == NULL) return;
+    if (arglen < 4) {
+	DPRINT(("ximSetIMValuesProc: arglen < 4\n"));
+	IMSendBadLength(conn, imp->id, 0);
+	return;
+    }
+
+    attr_len = IMGetC16(conn, 2);
+    attr = IMBUFDATA(IM_INBUF(conn)) + 4;
+
+    if (arglen < attr_len + 4) {
+	DPRINT(("ximSetIMValuesProc: attribute len too long\n"));
+	IMSendBadLength(conn, imp->id, 0);
+	return;
+    }
+
+    if (IMSetIMValues(imp, attr, attr_len, major) < 0) return;
+
+    (void)IMPutHeader(conn, XIM_SET_IM_VALUES_REPLY, 0, 4);
+    IMPutC16(conn, imp->id);
+    IMPutPad(conn);
+    IMSchedule(conn, SCHED_WRITE);
+}
+
+/*- ximGetIMValuesProc: handle XIM_GET_IM_VALUES request -*/
+/* ARGSUSED */
+static void
+ximGetIMValuesProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIM *imp;
+    char *attr;
+    int attr_len;
+    int offset;
+
+    TRACE(("ximGetIMValuesProc(#%d)\n", conn->serial));
+
+    if ((imp = IMGetIM(conn, arglen)) == NULL) return;
+    if (arglen < 4) {
+	DPRINT(("ximGetIMValuesProc: arglen < 4\n"));
+	IMSendBadLength(conn, imp->id, 0);
+	return;
+    }
+
+    attr_len = IMGetC16(conn, 2);
+    attr = IMBUFDATA(IM_INBUF(conn)) + 4;
+    if (arglen < attr_len + 4 || attr_len % 2 == 1) {
+	DPRINT(("ximGetIMValuesProc: attr_len too long or an odd number\n"));
+	IMSendBadLength(conn, imp->id, 0);
+	return;
+    }
+
+    offset = IMPutHeader(conn, XIM_GET_IM_VALUES_REPLY, 0, 0);
+    IMPutC16(conn, imp->id);
+
+    if (IMGetIMValues(imp, attr, attr_len, offset) < 0) return;
+
+    IMFinishRequest(conn, offset);
+}
+
+/*- ximCreateICProc: handle XIM_CREATE_IC request -*/
+/* ARGSUSED */
+static void
+ximCreateICProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIM *imp;
+    IMIC *icp;
+    char *attr_data;
+    int attr_len;
+
+    TRACE(("ximCreateICProc(#%d)\n", conn->serial));
+
+    if ((imp = IMGetIM(conn, arglen)) == NULL) return;
+    if (arglen < 4) {
+	/* BadArglen */
+	DPRINT(("ximCreateICProc: arglen < 4\n"));
+	IMSendBadLength(conn, imp->id, 0);
+	return;
+    }
+
+    attr_len = IMGetC16(conn, 2);
+    attr_data = IMBUFDATA(IM_INBUF(conn)) + 4;
+    if (arglen < attr_len + 4) {
+	DPRINT(("ximCreateICProc: attr_len too long\n"));
+	IMSendBadLength(conn, imp->id, 0);
+	return;
+    }
+    icp = IMCreateIC(imp);
+    if (IMSetICValues(icp, attr_data, attr_len, major) < 0) {
+	IMDestroyIC(icp);
+	return;
+    }
+    IMSendRequestWithIC(conn, XIM_CREATE_IC_REPLY, 0, icp);
+
+    IMStatusStart(icp);
+}
+
+/*- ximDestroyICProc: handle XIM_DESTROY_IC request -*/
+/* ARGSUSED */
+static void
+ximDestroyICProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIC *icp;
+    unsigned int imid, icid;
+
+    TRACE(("ximDestroyICProc(#%d)\n", conn->serial));
+
+    if ((icp = IMGetIC(conn, arglen)) == NULL) return;
+    if (arglen != 4) {
+	DPRINT(("ximDestroyICProc: arglen != 4\n"));
+	IMSendBadLength(conn, icp->im->id, icp->id);
+	return;
+    }
+
+    /* Save ID of IM/IC before IMDestroyIC()     */
+    imid = icp->im->id;
+    icid = icp->id;
+
+    IMStatusDone(icp);
+
+    IMDestroyIC(icp);
+
+    /* IMSendRequestWithIC(conn, XIM_DESTROY_IC_REPLY, 0, icp); */
+    IMPutHeader(conn, XIM_DESTROY_IC_REPLY, 0, 4);
+    IMPutC16(conn, imid);
+    IMPutC16(conn, icid);
+    IMSchedule(conn, SCHED_WRITE);
+}
+
+/*- ximSetICValuesProc: handle XIM_SET_IC_VALUES request -*/
+/* ARGSUSED */
+static void
+ximSetICValuesProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIC *icp;
+    char *attr;
+    int attr_len;
+
+    TRACE(("ximSetICValuesProc(#%d)\n", conn->serial));
+
+    if ((icp = IMGetIC(conn, arglen)) == NULL) return;
+    if (arglen < 8) {
+	DPRINT(("ximSetICValuesProc: arglen < 8\n"));
+	IMSendBadLength(conn, icp->im->id, icp->id);
+	return;
+    }
+
+    attr_len = IMGetC16(conn, 4);
+    attr = IMBUFDATA(IM_INBUF(conn)) + 8;
+
+    if (arglen < attr_len + 8) {
+	DPRINT(("ximSetICValuesProc: attr_len too long\n"));
+	IMSendBadLength(conn, icp->im->id, icp->id);
+	return;
+    }
+
+    if (IMSetICValues(icp, attr, attr_len, major) < 0) return;
+
+    IMSendRequestWithIC(conn, XIM_SET_IC_VALUES_REPLY, 0, icp);
+}
+
+/*- ximGetICValuesProc: handle XIM_GET_IC_VALUES request -*/
+/* ARGSUSED */
+static void
+ximGetICValuesProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIC *icp;
+    char *attr;
+    int attr_len;
+    int offset;
+
+    TRACE(("ximGetICValuesProc(#%d)\n", conn->serial));
+
+    if ((icp = IMGetIC(conn, arglen)) == NULL) return;
+    if (arglen < 6) {
+	DPRINT(("ximGetICValuesProc: arglen < 6\n"));
+	IMSendBadLength(conn, icp->im->id, icp->id);
+	return;
+    }
+
+    attr_len = IMGetC16(conn, 4);
+    attr = IMBUFDATA(IM_INBUF(conn)) + 6;
+    if (arglen < attr_len + 6 || attr_len % 2 == 1) {
+	DPRINT(("ximGetICValuesProc: attr_len too long or an odd number\n"));
+	IMSendBadLength(conn, icp->im->id, icp->id);
+	return;
+    }
+
+    offset = IMPutHeader(conn, XIM_GET_IC_VALUES_REPLY, 0, 0);
+    IMPutC16(conn, icp->im->id);
+    IMPutC16(conn, icp->id);
+
+    if (IMGetICValues(icp, attr, attr_len, offset) < 0) return;
+
+    IMFinishRequest(conn, offset);
+}
+
+/*- ximSetICFocusProc: handle XIM_SET_IC_FOCUS request -*/
+/* ARGSUSED */
+static void
+ximSetICFocusProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIC *icp;
+
+    TRACE(("ximSetICFocusProc(#%d)\n", conn->serial));
+
+    if ((icp = IMGetIC(conn, arglen)) == NULL) return;
+    if (arglen != 4) {
+	DPRINT(("ximSetICFocusProc: arglen != 4\n"));
+	IMSendBadLength(conn, icp->im->id, icp->id);
+	return;
+    }
+    IMStatusStart(icp);
+    IMSetFocus(icp);
+}
+
+/*- ximUnsetICFocusProc: handle XIM_UNSET_IC_FOCUS request -*/
+/* ARGSUSED */
+static void
+ximUnsetICFocusProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIC *icp;
+
+    TRACE(("ximUnsetICFocusProc(#%d)\n", conn->serial));
+
+    if ((icp = IMGetIC(conn, arglen)) == NULL) return;
+    if (arglen != 4) {
+	DPRINT(("ximUnsetICFocusProc: arglen != 4\n"));
+	IMSendBadLength(conn, icp->im->id, icp->id);
+	return;
+    }
+    IMUnsetFocus(icp);
+    IMStatusDone(icp);
+}
+
+/*- swapData: do byte swapping -*/
+static void
+swapData(data, format)
+char *data;
+char *format;
+{
+    unsigned char *p = (unsigned char *)data;
+    int x;
+    int f;
+
+#define SWAPB(b1, b2)	x = b1; b1 = b2; b2 = x
+    while ((f = *format++) != '\0') {
+	switch (f) {
+	case 'x':
+	    p++;
+	    break;
+	case 'l':
+	    SWAPB(p[0], p[3]);
+	    SWAPB(p[1], p[2]);
+	    p += 4;
+	    break;
+	case 's':
+	    SWAPB(p[0], p[1]);
+	    p += 2;
+	    break;
+	}
+    }
+#undef SWAPB
+}
+
+
+/*- getEvent: read a wire event and convert it to XEvent format -*/
+static int
+getEvent(conn, serial, offset, ev)
+IMConnection *conn;
+unsigned int serial;
+int offset;
+XEvent *ev;
+{
+    IMBuffer *ibp = IM_INBUF(conn);
+    xEvent wire_event;
+    int swap_needed;
+    int one = 1;
+    char *onep = (char *)&one;
+
+    /*
+     * Get wire event from input buffer.
+     */
+    bcopy(IMBUFDATA(ibp) + offset, (char *)&wire_event, sizeof(wire_event));
+
+    /*
+     * Do we need byte swapping?
+     */
+    if (*onep == 0) {	/* big endian */
+	swap_needed = (conn->byte_order == ORDER_LITTLE);
+    } else {		/* little endian */
+	swap_needed = (conn->byte_order == ORDER_BIG);
+    }
+
+#define SWAPEV(format)	if (swap_needed) swapData((char *)&wire_event, format)
+
+    /*
+     * Get common part of the wire event.
+     */
+    SWAPEV("xxs");
+    ev->type = wire_event.u.u.type & 0x7f;
+    ev->xany.serial = (serial << 16) | wire_event.u.u.sequenceNumber;
+    ev->xany.display = XtDisplay(conn->proto_widget);
+    ev->xany.send_event = wire_event.u.u.type > 127;
+
+    /*
+     * Convert wire format to XEvent format.
+     */
+    switch (ev->type) {
+    case KeyPress:
+    case KeyRelease:
+	SWAPEV("xxxxllllsssssxx");
+#define WIRE	wire_event.u.keyButtonPointer
+	ev->xkey.window = WIRE.event;
+	ev->xkey.root = WIRE.root;
+	ev->xkey.subwindow = WIRE.child;
+	ev->xkey.time =  WIRE.time;
+	ev->xkey.x = cvtINT16toInt(WIRE.eventX);
+	ev->xkey.y = cvtINT16toInt(WIRE.eventY);
+	ev->xkey.x_root = cvtINT16toInt(WIRE.rootX);
+	ev->xkey.y_root = cvtINT16toInt(WIRE.rootY);
+	ev->xkey.state = WIRE.state;
+	ev->xkey.keycode = wire_event.u.u.detail;
+	ev->xkey.same_screen = WIRE.sameScreen;
+#undef WIRE
+	break;
+    case ButtonPress:
+    case ButtonRelease:
+	SWAPEV("xxxxllllsssssxx");
+#define WIRE	wire_event.u.keyButtonPointer
+	ev->xbutton.window = WIRE.event;
+	ev->xbutton.root = WIRE.root;
+	ev->xbutton.subwindow = WIRE.child;
+	ev->xbutton.time = WIRE.time;
+	ev->xbutton.x = cvtINT16toInt(WIRE.eventX);
+	ev->xbutton.y = cvtINT16toInt(WIRE.eventY);
+	ev->xbutton.x_root = cvtINT16toInt(WIRE.rootX);
+	ev->xbutton.y_root = cvtINT16toInt(WIRE.rootY);
+	ev->xbutton.state = WIRE.state;
+	ev->xbutton.button = wire_event.u.u.detail;
+	ev->xbutton.same_screen = WIRE.sameScreen;
+#undef WIRE
+	break;
+    case MotionNotify:
+	SWAPEV("xxxxllllsssssxx");
+#define WIRE	wire_event.u.keyButtonPointer
+	ev->xmotion.window = WIRE.event;
+	ev->xmotion.root = WIRE.root;
+	ev->xmotion.subwindow = WIRE.child;
+	ev->xmotion.time = WIRE.time;
+	ev->xmotion.x = cvtINT16toInt(WIRE.eventX);
+	ev->xmotion.y = cvtINT16toInt(WIRE.eventY);
+	ev->xmotion.x_root = cvtINT16toInt(WIRE.rootX);
+	ev->xmotion.y_root = cvtINT16toInt(WIRE.rootY);
+	ev->xmotion.state = WIRE.state;
+	ev->xmotion.is_hint = wire_event.u.u.detail;
+	ev->xmotion.same_screen = WIRE.sameScreen;
+#undef WIRE
+	break;
+    default:
+	/*
+	 * For now, this function deals only Key/Pointer events.
+	 */
+	return 0;
+    }
+#undef SWAPEV
+
+    return 1;		/* success */
+}
+
+/*- postponeEvent: record events for delayed processing -*/
+static void
+postponeEvent(icp, synchronous, ev)
+IMIC *icp;
+int synchronous;
+XEvent *ev;
+{
+    IMPendingEvent *pending;
+
+    pending = XtNew(IMPendingEvent);
+    pending->ic = icp;
+    pending->synchronous = synchronous;
+    bcopy((char *)ev, (char *)&pending->event, sizeof(XEvent));
+    pending->next = icp->pending_events;
+    icp->pending_events = pending;
+}
+
+/*- handleForwardedEvent: deal with forwarded events -*/
+static void
+handleForwardedEvent(icp, synchronous, ev)
+IMIC *icp;
+int synchronous;
+XEvent *ev;
+{
+    IMConnection *conn = icp->im->connection;
+
+    TRACE(("handleForwardedEvent()\n"));
+
+    icp->state |= IC_FORWARDING;
+
+    if (icp->state & IC_SYNCING) {
+	/*
+	 * We are waiting for SYNC_REPLY message.
+	 * Postpone event processing.
+	 */
+	DDPRINT(2, ("forward event processing suspended\n"));
+	postponeEvent(icp, synchronous, ev);
+	return;
+    }
+
+    IMForwardEvent(icp, ev);
+
+#ifdef notyet
+    if (synchronous) {
+	if (!(icp->state & IC_CONVERTING)) {
+	    /*
+	     * Stop forwarding key events.
+	     */
+	    IMStopForwarding(icp);
+	}
+	/*
+	 * All the processing is done.  Send XIM_SYNC_REPLY.
+	 */
+	IMSendRequestWithIC(conn, XIM_SYNC_REPLY, 0, icp);
+    } else {
+	int cur_pos2;
+
+	cur_pos2 = IMWritePos(conn);
+	if (!(icp->state & IC_CONVERTING)) {
+	    /*
+	     * Stop forwarding key events.
+	     */
+	    IMStopForwarding(icp);
+	    /*
+	     * Put dummy commit request (for setting sync flag).
+	     */
+	}
+    }
+#else
+    /*
+     * Currently, kinput2 supports only full synchronous method.
+     */
+    if (!(icp->state & IC_CONVERTING)) {
+	/*
+	 * Stop forwarding key events.
+	 */
+	IMStopForwarding(icp);
+    }
+    /*
+     * All the processing is done.  Send XIM_SYNC_REPLY.
+     */
+    if (icp->state & IC_FORWARDING) {
+	icp->state &= ~IC_FORWARDING;
+	IMSendRequestWithIC(conn, XIM_SYNC_REPLY, 0, icp);
+    }
+#endif
+}
+
+/*- ximForwardEventProc: handle XIM_FORWARD_EVENT request -*/
+/* ARGSUSED */
+static void
+ximForwardEventProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIC *icp;
+    int synchronous;
+    unsigned int serial;
+    XEvent event;
+
+    TRACE(("ximForwardEventProc(#%d)\n", conn->serial));
+
+    if ((icp = IMGetIC(conn, arglen)) == NULL) return;
+    if (arglen != 40) {
+	DPRINT(("ximForwardEventProc: arglen != 40\n"));
+	IMSendBadLength(conn, icp->im->id, icp->id);
+	return;
+    }
+
+    synchronous = IMGetC16(conn, 4) & 1;
+    serial = IMGetC16(conn, 6);
+ 
+    if (getEvent(conn, serial, 8, &event)) {
+	handleForwardedEvent(icp, synchronous, &event);
+    }
+}
+
+/*- ximExtForwardKeyeventProc: handle XIM_EXT_FORWARD_KEYEVENT_MASK request -*/
+/* ARGSUSED */
+static void
+ximExtForwardKeyeventProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIC *icp;
+    int synchronous;
+    int type;
+    unsigned int serial;
+    XEvent event;
+
+    TRACE(("ximExtForwardKeyeventProc(#%d)\n", conn->serial));
+
+    if ((icp = IMGetIC(conn, arglen)) == NULL) return;
+
+    if (!(icp->im->mask & XIM_EXT_FORWARD_KEYEVENT_MASK)) {
+	DPRINT(("ximExtForwardKeyeventProc: ext_forward_keyevent disabled\n"));
+	IMSendBadProtocol(conn, "ext_forward_keyevent extension not enabled");
+	return;
+    }
+
+    if (arglen != 16) {
+	DPRINT(("ximExtForwardKeyeventProc: arglen != 16\n"));
+	IMSendBadLength(conn, icp->im->id, icp->id);
+	return;
+    }
+
+    synchronous = IMGetC16(conn, 4) & 1;
+    serial = IMGetC16(conn, 6);
+    type = IMGetC8(conn, 8);
+    if (type != KeyPress && type != KeyRelease) {
+	/* Badtype */
+	IMSendError(conn, IMBadSomething, icp->im->id, icp->id,
+		    "forwarded event is invalid type");
+	return;
+    }
+
+    event.type = type;
+    event.xkey.serial = serial;			/* ??? */
+    event.xkey.keycode = IMGetC8(conn, 9);
+    event.xkey.state = IMGetC16(conn, 10);
+    event.xkey.time =  IMGetC32(conn, 12);
+    event.xkey.window = IMGetC32(conn, 16);
+    event.xkey.root = icp->client_profile.root;
+    event.xkey.subwindow = None;
+    event.xkey.x = 0;
+    event.xkey.y = 0;
+    event.xkey.x_root = 0;
+    event.xkey.y_root = 0;
+    event.xkey.same_screen = True;
+
+    handleForwardedEvent(icp, synchronous, &event);
+}
+
+/*- ximSyncProc: handle XIM_SYNC request -*/
+/* ARGSUSED */
+static void
+ximSyncProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIC *icp;
+
+    TRACE(("ximSyncProc(#%d)\n", conn->serial));
+
+    if ((icp = IMGetIC(conn, arglen)) == NULL) return;
+    if (arglen != 4) {
+	DPRINT(("ximSyncProc: arglen != 4\n"));
+	IMSendBadLength(conn, icp->im->id, icp->id);
+	return;
+    }
+    IMSendRequestWithIC(conn, XIM_SYNC_REPLY, 0, icp);
+}
+
+/*- processPendingEvents: process pending events forwarded by the client -*/
+static void
+processPendingEvents(icp, pending_event)
+IMIC *icp;
+IMPendingEvent *pending_event;
+{
+    /*
+     * Pending events list is in reverse order.
+     * Processing is done from the tail of the list, using
+     * recursive call.
+     */
+    if (pending_event == NULL) return;
+    processPendingEvents(icp, pending_event->next);
+    pending_event->next = NULL;
+    handleForwardedEvent(icp, pending_event->synchronous,
+			 &pending_event->event);
+    XtFree((char *)pending_event);
+}
+
+/*- ximSyncReplyProc: handle XIM_SYNC_REPLY message -*/
+/* ARGSUSED */
+static void
+ximSyncReplyProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIC *icp;
+
+    TRACE(("ximSyncReplyProc(#%d)\n", conn->serial));
+
+    if ((icp = IMGetIC(conn, arglen)) == NULL) return;
+    if (arglen != 4) {
+	DPRINT(("ximSyncReplyProc: arglen != 4\n"));
+	return;
+    }
+    if (icp->state & IC_SYNCING) {
+	icp->state &= ~IC_SYNCING;
+	processPendingEvents(icp, icp->pending_events);
+    }
+}
+
+/*- ximResetICProc: handle XIM_RESET_IC message -*/
+/* ARGSUSED */
+static void
+ximResetICProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIC *icp;
+    char *text = NULL;
+    int offset;
+    int text_length;
+
+    TRACE(("ximResetICProc(#%d)\n", conn->serial));
+
+    if ((icp = IMGetIC(conn, arglen)) == NULL) return;
+    if (arglen != 4) {
+	DPRINT(("ximResetICProc: arglen != 4\n"));
+	IMSendBadLength(conn, icp->im->id, icp->id);
+	return;
+    }
+    icp->state |= IC_RESETTING;
+    text_length = IMResetIC(icp, &text);
+
+    offset = IMPutHeader(conn, XIM_RESET_IC_REPLY, 0, 0);
+    IMPutC16(conn, icp->im->id);
+    IMPutC16(conn, icp->id);
+    IMPutC16(conn, (unsigned int)text_length);
+    if (text_length > 0) IMPutString(conn, text, text_length);
+    IMFinishRequest(conn, offset);
+    if (text != NULL) XtFree(text);
+    icp->state &= ~IC_RESETTING;
+}
+
+/*- ximExtMoveProc: handle XIM_EXT_MOVE request -*/
+/* ARGSUSED */
+static void
+ximExtMoveProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    IMIC *icp;
+    int x, y;
+
+    TRACE(("ximExtMoveProc(#%d)\n", conn->serial));
+
+    if ((icp = IMGetIC(conn, arglen)) == NULL) return;
+    x = IMGetI16(conn, 4);
+    y = IMGetI16(conn, 6);
+    IMMoveLocation(icp, x, y);
+}
+
+/*- ximAlreadyConnectedProc: handle duplicate XIM_CONNECT request -*/
+/* ARGSUSED */
+static void
+ximAlreadyConnectedProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    TRACE(("ximAlreadyConnectedProc(#%d)\n", conn->serial));
+
+    DPRINT(("connection #%d sent multiple XIM_CONNECT request\n",
+	    conn->serial));
+    IMSendBadProtocol(conn, "duplicate XIM_CONNECT message");
+}
+
+/*- ximShouldNotBeSentProc: handle requests which clients should not send -*/
+/* ARGSUSED */
+static void
+ximShouldNotBeSentProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    TRACE(("ximShouldNotBeSentProc(#%d)\n", conn->serial));
+
+    DPRINT(("connection #%d sent invalid request\n", conn->serial))
+    IMSendBadProtocol(conn, "Clients should not send this request");
+}
+
+/*- ximAuthPhaseProc: handle requests for authentication -*/
+/* ARGSUSED */
+static void
+ximAuthPhaseProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    TRACE(("ximAuthPhaseProc(#%d)\n", conn->serial));
+
+    DPRINT(("connection #%d sends auth-related request\n", conn->serial));
+    IMSendBadProtocol(conn, "not authentication phase");
+}
+
+/*- ximNopProc: nop -*/
+/* ARGSUSED */
+static void
+ximNopProc(conn, major, minor, arglen)
+IMConnection *conn;
+int major;
+int minor;
+int arglen;
+{
+    TRACE(("ximNopProc(#%d)\n", conn->serial));
+
+    /* do nothing */
+}
+
+/*
+ * Public Function
+ */
+
+/*- IMCompileReq: initialize IMMainDispatchTable -*/
+void
+IMCompileReq()
+{
+    static int compiled = 0;
+
+    if (compiled) return;
+    compileTbl(coreRequestTbl);
+    compileTbl(extRequestTbl);
+    compiled = 1;
+}