/* # skkinput (Simple Kana-Kanji Input)
 *
 * This file is part of skkinput.
 * Copyright (C) 2002
 * Takashi SAKAMOTO (PXG01715@nifty.ne.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 skkinput; see the file COPYING.  If not, write to
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 */
/*
 *	on-demand-synchronous-mode で動作することを仮定している。
 */
//#include "AfxWin.h"
//#include "local.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/keysym.h>
//#include "skkinput.h"
#include "XIMClientP.h"
#include "XIMServer.h"
#include "XIMInputContext.h"
#include "XIMInputMethod.h"
#include "XIMData.h"
//#include "dispatch.h"
#include "commondef.h"
#include "MyDispatch.h"
#include "kanji.h"

extern int string2ctext  (struct myChar*, unsigned char*) ;
extern int string2ctextn (struct myChar*, int, unsigned char*) ;

#define	SKKIME_SEE_ENCODING_NEGOTIATION_DETAIL	(1)

typedef struct tagXIMAttribute {
	const char*		m_pName ;
	unsigned int	m_uValueType ;
	Boolean			m_fEnableCreate ;
	Boolean			m_fEnableNormal ;
	Boolean			(*m_pSetter)(Widget, XIMInputMethod*, XIMInputContext*, XIMData*, int, int) ;
	Boolean			(*m_pGetter)(Widget, XIMInputMethod*, XIMInputContext*, XIMData*, int*, int, XIMPacket*) ;
}	XIMAttribute ;

/* ///////////////////////////////////////////////////////////////////////
 */

#define	DEFGETTER(name)	static Boolean name(Widget, XIMInputMethod*, XIMInputContext*, XIMData*, int*, int, XIMPacket*)
#define	DEFSETTER(name)	static Boolean name(Widget, XIMInputMethod*, XIMInputContext*, XIMData*, int, int)
DEFGETTER (ximClient_getImValueQueryInputStyle) ;
DEFGETTER (ximClient_getIcValueInputStyle) ;	
DEFGETTER (ximClient_getIcValueClientWindow) ; 
DEFGETTER (ximClient_getIcValueFocusWindow) ; 
DEFGETTER (ximClient_getIcValueResetState) ; 
DEFGETTER (ximClient_getIcValueFilterEvents) ; 
DEFGETTER (ximClient_getIcValuePreeditState) ; 
DEFGETTER (ximClient_getIcValuePreeditAttributes) ; 
DEFGETTER (ximClient_getIcValueStatusAttributes) ; 
DEFGETTER (ximClient_getIcValueArea) ; 
DEFGETTER (ximClient_getIcValueAreaNeeded) ; 
DEFGETTER (ximClient_getIcValueSpotLocation) ; 
DEFGETTER (ximClient_getIcValueColormap) ; 
DEFGETTER (ximClient_getIcValueStdColormap) ; 
DEFGETTER (ximClient_getIcValueForeground) ; 
DEFGETTER (ximClient_getIcValueBackground) ; 
DEFGETTER (ximClient_getIcValueBackgroundPixmap) ; 
DEFGETTER (ximClient_getIcValueLineSpacing) ; 
DEFGETTER (ximClient_getIcValueCursor) ; 
DEFGETTER (ximClient_getIcValueFontSet) ; 
#if defined (not_yet)
DEFGETTER (ximClient_getIcValueHotKey) ; 
DEFGETTER (ximClient_getIcValueHotKeyState) ; 
#endif

DEFSETTER (ximClient_setIcValueInputStyle) ;
DEFSETTER (ximClient_setIcValueClientWindow) ;
DEFSETTER (ximClient_setIcValueFocusWindow) ;
DEFSETTER (ximClient_setIcValueResetState) ;
DEFSETTER (ximClient_setIcValuePreeditState) ;
DEFSETTER (ximClient_setIcValuePreeditAttributes) ;
DEFSETTER (ximClient_setIcValueStatusAttributes) ;
DEFSETTER (ximClient_setIcValueArea) ;
DEFSETTER (ximClient_setIcValueAreaNeeded) ;
DEFSETTER (ximClient_setIcValueSpotLocation) ;
DEFSETTER (ximClient_setIcValueColormap) ;
DEFSETTER (ximClient_setIcValueStdColormap) ;
DEFSETTER (ximClient_setIcValueForeground) ;
DEFSETTER (ximClient_setIcValueBackground) ;
DEFSETTER (ximClient_setIcValueBackgroundPixmap) ;
DEFSETTER (ximClient_setIcValueFontSet) ;
DEFSETTER (ximClient_setIcValueLineSpacing) ;
DEFSETTER (ximClient_setIcValueCursor) ;
#if defined (not_yet)
DEFSETTER (ximClient_setIcValueHotKey) ;
DEFSETTER (ximClient_setIcValueHotKeyState) ;
#endif
#undef	DEFGETTER
#undef	DEFSETTER

static	XIMAttribute	srSupportedInputMethodAttributes []	= {
	{	XNQueryInputStyle,		XIM_VALUE_TYPE_XIMSTYLES,	 False,	False,
		NULL,					ximClient_getImValueQueryInputStyle, },
} ;

enum {
	XIM_ATTRIBUTEID_QUERYINPUTSTYLE	= 0,
	MAX_NUMBER_OF_XIM_ATTRIBUTEID,
} ;

static	XIMAttribute	srSupportedInputContextAttributes []	= {
	{	XNInputStyle,			XIM_VALUE_TYPE_LONG,
		True,					False,
		ximClient_setIcValueInputStyle,
		ximClient_getIcValueInputStyle,	},
	{	XNClientWindow, 		XIM_VALUE_TYPE_WINDOW,
		True,					True,
		ximClient_setIcValueClientWindow,
		ximClient_getIcValueClientWindow, },
	{	XNFocusWindow, 			XIM_VALUE_TYPE_WINDOW,
		True,					True,
		ximClient_setIcValueFocusWindow,
		ximClient_getIcValueFocusWindow, },
	{	XNFilterEvents, 		XIM_VALUE_TYPE_LONG,
		False,					False,
		0,				
		ximClient_getIcValueFilterEvents, },
	{	XNResetState,			XIM_VALUE_TYPE_XIMRESETSTATE,
		True,					True,
		ximClient_setIcValueResetState,
		ximClient_getIcValueResetState, },
	{	XNPreeditState,			XIM_VALUE_TYPE_XIMPREEDITSTATE,
		True,					True,
		ximClient_setIcValuePreeditState,
		ximClient_getIcValuePreeditState, },
	{	XNPreeditAttributes, 	XIM_VALUE_TYPE_NESTEDLIST,
		True,					True,
		ximClient_setIcValuePreeditAttributes,
		ximClient_getIcValuePreeditAttributes, },
	{	XNStatusAttributes,		XIM_VALUE_TYPE_NESTEDLIST,
		True,					True,
		ximClient_setIcValueStatusAttributes,
		ximClient_getIcValueStatusAttributes, },
	{	XNArea,					XIM_VALUE_TYPE_XRECTANGLE,
		True,					True,
		ximClient_setIcValueArea,
		ximClient_getIcValueArea, },
	{	XNAreaNeeded,			XIM_VALUE_TYPE_XRECTANGLE,
		True,					True,
		ximClient_setIcValueAreaNeeded,
		ximClient_getIcValueAreaNeeded, },
	{	XNSpotLocation,			XIM_VALUE_TYPE_XPOINT,
		True,					True,
		ximClient_setIcValueSpotLocation,
		ximClient_getIcValueSpotLocation, },
	{	XNColormap,				XIM_VALUE_TYPE_LONG,
		True,					True,
		ximClient_setIcValueColormap,
		ximClient_getIcValueColormap, },
	{	XNStdColormap,			XIM_VALUE_TYPE_LONG,
		True,					True,
		ximClient_setIcValueStdColormap,
		ximClient_getIcValueStdColormap, },
	{	XNForeground,			XIM_VALUE_TYPE_LONG,
		True,					True,
		ximClient_setIcValueForeground,
		ximClient_getIcValueForeground, },
	{	XNBackground,			XIM_VALUE_TYPE_LONG,
		True,					True,
		ximClient_setIcValueBackground,
		ximClient_getIcValueBackground, },
	{	XNBackgroundPixmap,		XIM_VALUE_TYPE_LONG,
		True,					True,
		ximClient_setIcValueBackgroundPixmap,
		ximClient_getIcValueBackgroundPixmap, },
	{	XNFontSet,			XIM_VALUE_TYPE_XFONTSET,
		True,					True,
		ximClient_setIcValueFontSet,
		ximClient_getIcValueFontSet, },
	{	XNLineSpace,			XIM_VALUE_TYPE_LONG,
		True,					True,
		ximClient_setIcValueLineSpacing,
		ximClient_getIcValueLineSpacing, },
	{	XNCursor,				XIM_VALUE_TYPE_LONG,
		True,					True,
		ximClient_setIcValueCursor,
		ximClient_getIcValueCursor, },
	{	XNSeparatorofNestedList,	XIM_VALUE_TYPE_SEPARATOR,
		False,					False,
		NULL,					NULL, },
#if defined (not_yet)
	/*
	 *	dynamic flow model だと HOT_KEY の切り替えは困難…。
	 *	static flow model だったら、実行可能だけど…。
	 *	X Input Method Protocol Specification の動作モデルでは
	 *	filter-event-mask を切り替えているようだけど…
	 *	filter-event-mask を設定してしまったら、Server に Event が来ないし
	 *	Client も処理したように見えるんですが。
	 *	Focus Window に細工をしろということ？
	 */
	{	XNHotKey,				XIM_VALUE_TYPE_HOTKEYTRIGGERS,
		True,					True,
		ximClient_setIcValueHotKey,
		ximClient_getIcValueHotKey, },
	{	XNHotKeyState,			XIM_VALUE_TYPE_HOTKEYSTATE,
		True,					True,
		ximClient_setIcValueHotKeyState,
		ximClient_getIcValueHotKeyState, },
#endif
} ;

enum {
	XIC_ATTRIBUTEID_INPUTSTYLE	= 0,
	XIC_ATTRIBUTEID_CLIENTWINDOW,
	XIC_ATTRIBUTEID_FOCUSWINDOW,
	XIC_ATTRIBUTEID_FILTEREVENTS,
	XIC_ATTRIBUTEID_RESETSTATE,
	XIC_ATTRIBUTEID_PREEDITSTATE,
	XIC_ATTRIBUTEID_PREEDITATTRIBUTES,
	XIC_ATTRIBUTEID_STATUSATTRIBUTES,
	XIC_ATTRIBUTEID_AREA,
	XIC_ATTRIBUTEID_AREANEEDED,
	XIC_ATTRIBUTEID_SPOTLOCATION,
	XIC_ATTRIBUTEID_COLORMAP,
	XIC_ATTRIBUTEID_STDCOLORMAP,
	XIC_ATTRIBUTEID_FOREGROUND,
	XIC_ATTRIBUTEID_BACKGROUND,
	XIC_ATTRIBUTEID_BACKGROUNDPIXMAP,
	XIC_ATTRIBUTEID_FONTSET,
	XIC_ATTRIBUTEID_LINESPACE,
	XIC_ATTRIBUTEID_CURSOR,
	XIC_ATTRIBUTEID_SEPARATOR,
	MAX_NUMBER_OF_XIC_ATTRIBUTEID,
} ;

#define	PREEDITATTRIBUTES_MASK			(1L << 0)
#define	STATUSATTRIBUTES_MASK			(1L << 1)
#define	XIC_CREATE_MASK					(1L << 2)

#define	FORWARDEVENT_SYNC_MASK			(1L << 0)
#define	FORWARDEVENT_FILTER_MASK		(1L << 1)
#define	FORWARDEVENT_LOOKUPSTRING_MASK	(1L << 2)

#define offset(field)  XtOffsetOf(XIMClientRec, ximClient.field)
#define goffset(field) XtOffsetOf(WidgetRec, core.field)

static XtResource	srXIMClientResources [] = {
	{	XtNwidth,				XtCWidth,
		XtRDimension,			sizeof (Dimension),
		goffset (width),		XtRImmediate,	(XtPointer) 1, },
	{	XtNheight,				XtCHeight,
		XtRDimension,			sizeof (Dimension),
		goffset (height),		XtRImmediate,	(XtPointer) 1, },
	{	XtNmappedWhenManaged,	XtCMappedWhenManaged,
		XtRBoolean,				sizeof (Boolean),
		goffset (mapped_when_managed),	XtRImmediate,	(XtPointer)False, },
	{	XtNclientWindow,		XtCClientWindow,
		XtRWindow,				sizeof (Window),
		offset (m_wndClient),	XtRImmediate,	(XtPointer) None, },
	{	XtNdestroyCallback,			XtCCallback,
		XtRCallback,				sizeof (XtCallbackList),
		offset (m_lstCbkDestroy),	XtRCallback,		(XtPointer) NULL, },
	{	XtNprotocolWidget,		XtCProtocolWidget,
		XtRWidget,				sizeof (Widget),
		offset (m_wgProtocol),	XtRImmediate,	(XtPointer) NULL, },
} ;

#undef offset
#undef goffset

static	void		ximClient_onInitialize	(Widget, Widget, ArgList, Cardinal*) ;
static	void		ximClient_onRealize		(Widget, XtValueMask*, XSetWindowAttributes*) ;
static	Boolean		ximClient_onSetValues	(Widget, Widget, Widget, ArgList, Cardinal*) ;
static	void		ximClient_onDestroy		(Widget) ;

static	void		ximClient_onClientMessage	(Widget, XEvent*, String*, Cardinal*) ;
#if 0
static	int			ximClient_onClientDestroy	(void*, XEvent*) ;
#endif

static	Boolean		ximClient_getMessage8				(Widget, const CARD8*, int) ;
static	Boolean		ximClient_getMessage32				(Widget, Atom) ;
static	void		ximClient_dispatchMessage			(Widget) ;
static	Boolean		ximClient_writeMessage				(Widget, XIMPacket*) ;
static	Boolean		ximClient_writeMessageWithEvent		(Widget, const BYTE*, int) ;
static	Boolean		ximClient_writeMessageWithProperty	(Widget, const BYTE*, int) ;
static	Boolean		ximClient_initialState			(Widget) ;
static	Boolean		ximClient_authorizationOk		(Widget) ;
static	Boolean		ximClient_authorizationNg		(Widget) ;
static	Boolean		ximClient_authorizationState	(Widget) ;
static	Boolean		ximClient_connectedState		(Widget) ;

static	Boolean		ximClient_setIcValues	(Widget, XIMInputMethod*, XIMInputContext*, XIMData*, int, int) ;
static	Boolean		ximClient_getIcValues	(Widget, XIMInputMethod*, XIMInputContext*, XIMData*, int*, int, XIMPacket*) ;
static	void		ximClient_writeSyncReply		(Widget, int, XIMInputContext*) ;
static	void		ximClient_makePacketSync		(XIMPacket*) ;
static	void		ximClient_flushSpooledPacket	(Widget, XIMInputContext*) ;
#if defined (DEBUG) || 0
static	void		dumpBuf (const BYTE*, int) ;
#endif

#define	DEFONXIMFUNC(funcname)	static Boolean	funcname (Widget, int, int, int, XIMData*)
DEFONXIMFUNC (ximClient_onXimOpen) ;
DEFONXIMFUNC (ximClient_onXimTriggerNotify) ;
DEFONXIMFUNC (ximClient_onXimEncodingNegotiation) ;
DEFONXIMFUNC (ximClient_onXimQueryExtension) ;
DEFONXIMFUNC (ximClient_onXimSetImValues) ;
DEFONXIMFUNC (ximClient_onXimGetImValues) ;
DEFONXIMFUNC (ximClient_onXimCreateIc) ;
DEFONXIMFUNC (ximClient_onXimSetIcValues) ;
DEFONXIMFUNC (ximClient_onXimGetIcValues) ;
DEFONXIMFUNC (ximClient_onXimSetIcFocus) ;
DEFONXIMFUNC (ximClient_onXimUnsetIcFocus) ;
DEFONXIMFUNC (ximClient_onXimDestroyIc) ;
DEFONXIMFUNC (ximClient_onXimResetIc) ;
DEFONXIMFUNC (ximClient_onXimForwardEvent) ;
DEFONXIMFUNC (ximClient_onXimSync) ;
DEFONXIMFUNC (ximClient_onXimSyncReply) ;
DEFONXIMFUNC (ximClient_onXimStrConversionReply) ;
DEFONXIMFUNC (ximClient_onXimPreeditStartReply) ;
DEFONXIMFUNC (ximClient_onXimPreeditCaretReply) ;
DEFONXIMFUNC (ximClient_onXimClose) ;
DEFONXIMFUNC (ximClient_onXimDisconnect) ;
DEFONXIMFUNC (ximClient_onXimError) ;
DEFONXIMFUNC (ximClient_onXimExtForwardKeyEvent) ;
DEFONXIMFUNC (ximClient_onXimExtMove) ;
#undef DEFONXIMFUNC

static	Boolean		ximClient_putInputMethodAttribute	(XIMPacket*, int) ;
static	Boolean		ximClient_putInputContextAttribute	(XIMPacket*, int) ;
static	Boolean		ximClient_putAttributeCommon(XIMPacket*, int, XIMAttribute*) ;
static	Boolean		ximClient_putTriggerKey		(Widget, XIMPacket*, const XIMHotKeyTrigger*) ;
static	Boolean		ximClient_writeErrorMessage (Widget, int, int, int, const char*) ;
static	Boolean		ximClient_badProtocol		(Widget, const char*) ;
static	Boolean		ximClient_setForwardEvent	(Widget, XIMInputMethod*, XIMInputContext*, Boolean) ;
static	Boolean		ximClient_registerInputMethod	(Widget, XIMInputMethod*) ;
static	Boolean		ximClient_unregisterInputMethod	(Widget, XIMInputMethod*) ;
static	XIMInputMethod*		ximClient_findInputMethod	(Widget, CARD16) ;
static	XIMInputContext*	ximClient_findInputContext	(Widget, XIMInputMethod*, CARD16) ;
static	void		ximClient_destroyAllInputMethods	(Widget) ;
static	Boolean		ximClient_createXEvent		(Widget, unsigned long, const xEvent*, XEvent*) ;
static	Boolean		ximClient_supportedEncodingp	(const char*, int) ;


static XtActionsRec		srXIMClientActionsTable [] = {
	{	"on-client-message",			ximClient_onClientMessage, },
} ;

static char	sstrXIMClientTranslations []	= 
"<Message>:                              on-client-message()" ;

XIMClientClassRec	ximClientClassRec = {
    {	/* core fields 			*/
		/* superclass			*/	&widgetClassRec,
		/* class_name			*/	"XIMClient",
		/* size					*/	sizeof (XIMClientRec),
		/* class_initialize		*/	NULL,
		/* class_part_initialize*/	NULL,
		/* class_inited			*/	FALSE,
		/* initialize			*/	ximClient_onInitialize,
		/* initialize_hook		*/	NULL,
		/* realize				*/	ximClient_onRealize,
		/* actions				*/	srXIMClientActionsTable,
		/* num_actions			*/	XtNumber (srXIMClientActionsTable),
		/* resources			*/	srXIMClientResources,
		/* num_resources		*/	XtNumber (srXIMClientResources),
		/* xrm_class			*/	NULLQUARK,
		/* compress_motion		*/	TRUE,
		/* compress_exposure	*/	TRUE,
		/* compress_enterleave	*/	TRUE,
		/* visible_interest		*/	FALSE,
		/* destroy				*/	ximClient_onDestroy,
		/* resize				*/	NULL,
		/* expose				*/	NULL,
		/* set_values			*/	ximClient_onSetValues,
		/* set_values_hook		*/	NULL,
		/* set_values_almost	*/	XtInheritSetValuesAlmost,
		/* get_values_hook		*/	NULL,
		/* accept_focus			*/	NULL,
		/* version				*/	XtVersion,
		/* callback_private		*/	NULL,
		/* tm_table				*/	sstrXIMClientTranslations,
		/* query_geometry		*/	XtInheritQueryGeometry,
    }, {
		/* dummy				*/	0,
	}
} ;

WidgetClass ximClientWidgetClass = (WidgetClass)&ximClientClassRec ;

void
ximClient_onInitialize (
	register Widget		greq,
	register Widget		gnew,
	register ArgList	args,
	register Cardinal*	num_args)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gnew ;
	register Display*			pDisplay	= XtDisplay (gnew) ;

	TVarbuffer_Initialize (&wgThis->ximClient.m_vbufAuthProtocolNameList, sizeof (char)) ;
	TQueue_Initialize (&wgThis->ximClient.m_queInputMessage, sizeof (CARD8)) ;
	wgThis->ximClient.m_fBigEndian		= False ;
	wgThis->ximClient.m_pDispatcher		= NULL ;
	wgThis->ximClient.m_nAuthProtocol	= 0 ;
	wgThis->ximClient.m_uInputMethodID	= 1 ;
	wgThis->ximClient.m_lstInputMethod	= NULL ;

#define MakeAtom(s)	XInternAtom(pDisplay,s,False)
	wgThis->ximClient.m_atProtocol	= MakeAtom ("_XIM_PROTOCOL") ;
	wgThis->ximClient.m_atMoreData	= MakeAtom ("_XIM_MOREDATA") ;
	wgThis->ximClient.m_atReadWrite	= MakeAtom ("_XIM_SKKCOMM") ;
#undef MakeAtom
	return ;
}

Boolean
ximClient_onSetValues (
	register Widget		gwCurrent,
	register Widget		gwRequest,
	register Widget		gwNeww,
	register ArgList	args,
	register Cardinal*	num_args)
{
/*
	register XIMClientWidget	curw	= (XIMClientWidget) gwCurrent ;
	register XIMClientWidget	reqw	= (XIMClientWidget) gwRequest ;
	register XIMClientWidget	neww	= (XIMClientWidget) gwNeww ;
*/
	return	False ;
}

void
ximClient_onRealize (
	register Widget					gw,
	register XtValueMask*			pValueMask,
	register XSetWindowAttributes*	pXSWA)
{
	//register Display*			pDisplay	= XtDisplay (gw) ;
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;
	register CoreWidgetClass	super	= (CoreWidgetClass) XtClass (gw)->core_class.superclass ;

	(*super->core_class.realize)(gw, pValueMask, pXSWA) ;

	if (wgThis->ximClient.m_wndClient == None) {
		XtDestroyWidget (gw) ;
		return ;
	}
	//AfxRegisterWindow (pDisplay, wgThis->ximClient.m_wndClient, DestroyNotify, StructureNotifyMask, gw, ximClient_onClientDestroy) ;
	wgThis->ximClient.m_pDispatcher	= ximClient_initialState ;
#if defined (DEBUG_MEMORY)
	debug_touch () ;
#endif
	return ;
}

void
ximClient_onDestroy (
	register Widget		gw)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;

	XtCallCallbacks (gw, XtNdestroyCallback, gw) ;

	//AfxUnregisterWindow (wgThis->ximClient.m_wndClient, DestroyNotify, StructureNotifyMask, gw, ximClient_onClientDestroy) ;

	/*	全ての InputMethod を破棄する。*/
	ximClient_destroyAllInputMethods (gw) ;

	TQueue_Uninitialize (&wgThis->ximClient.m_queInputMessage) ;
	TVarbuffer_Uninitialize (&wgThis->ximClient.m_vbufAuthProtocolNameList) ;
#if defined (DEBUG_MEMORY)
	debug_dumpmemory (1) ;
#endif
	return ;
}

void
ximClient_onClientMessage (
	register Widget		gw,
	register XEvent*	pXEvent,
	register String*	params,
	register Cardinal*	num_params)
{
	register XIMClientWidget		wgThis	= (XIMClientWidget) gw ;
	register XClientMessageEvent*	pEvent	= (XClientMessageEvent*)&pXEvent->xclient ;
	register Boolean	fResult ;

	if (XtWindow (gw) != pEvent->window)
		return ;

	switch (pEvent->format) {
	case	8:
		if (pEvent->message_type != wgThis->ximClient.m_atProtocol &&
			pEvent->message_type != wgThis->ximClient.m_atMoreData)
			return ;
		fResult	= ximClient_getMessage8 (gw, (CARD8 *)pEvent->data.b, XTRANSPORT_UNIT_SIZE) ;
#if defined (DEBUG)
		fprintf (stderr, "ximClient_getMessage8 (): %d\n", fResult) ;
#endif
		break ;
	case	32:
		if (pEvent->message_type != wgThis->ximClient.m_atProtocol)
			return ;
		fResult	= ximClient_getMessage32 (gw, (Atom)pEvent->data.l [1]) ;
#if defined (DEBUG)
		fprintf (stderr, "ximClient_getMessage32 (): %d\n", fResult) ;
#endif
		break ;
	default:
		return ;
	}
	if (fResult) 
		ximClient_dispatchMessage (gw) ;
	return ;
}

#if 0
int
ximClient_onClientDestroy (
	register void*		pClosure,
	register XEvent*	pEvent)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) pClosure ;
#if defined (DEBUG)
	fprintf (stderr, "ximClient_onClientDestroy (%p, %p)\n", pClosure, pEvent) ;
#endif
	XtDestroyWidget ((Widget)wgThis) ;
	return	0 ;
}
#endif

void
ximClient_dispatchMessage (
	register Widget		gw)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;

	assert (wgThis->ximClient.m_pDispatcher != NULL) ;

#if defined (DEBUG) || 0
	{
		register TQueue*		pQueue	= &wgThis->ximClient.m_queInputMessage ;
		register const BYTE*	pBuffer	= TQueue_GetData  (pQueue) ;
		register int			nUsage	= TQueue_GetUsage (pQueue) ;
		fprintf (stderr, "** input (%d) **\n", nUsage) ;
		dumpBuf (pBuffer, nUsage) ;
	}
#endif

	while ((wgThis->ximClient.m_pDispatcher)(gw)) 
		;
	return ;
}

Boolean
ximClient_getMessage8 (
	register Widget			gw,
	register const CARD8*	pData,
	register int			nData)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;

	return	TQueue_In (&wgThis->ximClient.m_queInputMessage, pData, nData) ;
}

Boolean
ximClient_getMessage32 (
	register Widget		gw,
	register Atom		atProperty)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register Display*			pDisplay	= XtDisplay (gw) ;
	register Window				window		= XtWindow (gw) ;
	register TQueue*			pQueue ;
	Atom				atActualType ;
	int					iActualFormat ;
	long				lOffset ;
	unsigned long		ulRemain ;
	unsigned long		ulItems ;
	char* 				pData ;
	Boolean				fRetvalue ;

	lOffset		= 0 ;
	fRetvalue	= True ;
	pQueue		= &wgThis->ximClient.m_queInputMessage ;
  
	do {
		XGetWindowProperty (pDisplay, window, atProperty, lOffset, 1000, True, AnyPropertyType, &atActualType, &iActualFormat, &ulItems, &ulRemain, (unsigned char **)&pData) ;
		if (!pData)
			break ;
		if (iActualFormat != 8){
			fRetvalue	= False ;
		} else {
			fRetvalue	= TQueue_In (pQueue, pData, ulItems) ;
			lOffset		+= ulItems ;
		}
		XFree (pData) ;
		pData	= 0 ;
	} while (fRetvalue && ulRemain > 0) ;
	
	return	fRetvalue ;
}

/*
 *
 */
Boolean
ximClient_writeMessage (
	register Widget		gw,
	register XIMPacket*	pPacket)
{
	//register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register XIMInputContext*	pInputContext ;
	register const BYTE*		pPacketData ;
	register int				nPacketSize ;
	
	pInputContext	= XIMPacket_GetInputContext (pPacket) ;
#if defined (DEBUG) || 0
	{
		register XIMPacketSyncMode	uMode	= XIMPacket_GetSyncMode (pPacket) ;
		fprintf (stderr, "IC(%p), Mode(%x), ", pInputContext, uMode) ;
		XIMPacket_Show (pPacket) ;
	}
#endif
	if (pInputContext != NULL) {
		register XIMPacketSyncMode	uMode	= XIMPacket_GetSyncMode (pPacket) ;

		switch (uMode) {
			register unsigned		uSyncMode ;

			/*	強制スプールパケットの処理。*/
		case	XIMPS_SPOOL_PREEDIT_START:
		case	XIMPS_SPOOL_PREEDIT_CARET:
		case	XIMPS_SPOOL_PREEDIT:
		case	XIMPS_SPOOL:
#if defined (DEBUG) || 0
			fprintf (stderr, " ---> spool\n") ;
#endif
			return	XIMInputContext_SpoolPacket (pInputContext, pPacket) ;

			/*	同期待ちを要求するパケットを受けとった場合の処理。*/
		case	XIMPS_SYNC_NORMAL:
		case	XIMPS_SYNC_PREEDIT_CARET:
		case	XIMPS_SYNC_PREEDIT_START:
			uSyncMode	= XIMInputContext_GetSyncMode (pInputContext) ;
			if ((uSyncMode & XIMSyncAny) != 0) {
#if defined (DEBUG) || 0
				fprintf (stderr, " ---> spool\n") ;
#endif
				return	XIMInputContext_SpoolPacket (pInputContext, pPacket) ;
			}
			XIMInputContext_SetSyncMode (pInputContext, 1 << (uMode - XIMPS_SPOOL)) ;
			break ;

		case	XIMPS_NO:
		default:
			break ;
		}
	}

#if defined (DEBUG) || 0
	fprintf (stderr, " ---> write\n") ;
#endif

	pPacketData	= XIMPacket_GetData (pPacket) ;
	nPacketSize	= XIMPacket_GetDataSize (pPacket) ;
#if defined (DEBUG) || 0
	fprintf (stderr, "** output (%d) **\n", nPacketSize) ;
	dumpBuf (pPacketData, nPacketSize) ;
#endif
	if (nPacketSize < XTRANSPORT_DIVIDING_SIZE) {
		return	ximClient_writeMessageWithEvent (gw, pPacketData, nPacketSize) ;
	} else {
		return	ximClient_writeMessageWithProperty (gw, pPacketData, nPacketSize) ;
	}
}

Boolean
ximClient_writeMessageWithEvent (
	register Widget			gw,
	register const BYTE*	pPacketData,
	register int			nPacketSize)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register Display*		pDisplay ;
	register Window			wndClient ;
	XEvent					xev ;

#if defined (DEBUG)
	fprintf (stderr, "ximClient_writeMessageE(%lx): ",
			 wgThis->ximClient.m_wndClient) ;
	XIMPacket_Show (pPacket) ;
#endif
	pDisplay	= XtDisplay (gw) ;
	wndClient	= wgThis->ximClient.m_wndClient ;
	while (nPacketSize > XTRANSPORT_UNIT_SIZE) {
		xev.type					= ClientMessage ;
		xev.xclient.display			= pDisplay ;
		xev.xclient.window			= wndClient ;
		xev.xclient.format			= 8 ;
		xev.xclient.message_type	= wgThis->ximClient.m_atMoreData ;
		memcpy (xev.xclient.data.b, pPacketData, XTRANSPORT_UNIT_SIZE) ;
		XSendEvent (pDisplay, wndClient, False, NoEventMask, &xev) ;
		pPacketData	+= XTRANSPORT_UNIT_SIZE ;
		nPacketSize	-= XTRANSPORT_UNIT_SIZE ;
	}
	if (0 < nPacketSize && nPacketSize <= XTRANSPORT_UNIT_SIZE) {
		xev.type					= ClientMessage ;
		xev.xclient.message_type	= wgThis->ximClient.m_atProtocol ;
		xev.xclient.display			= pDisplay ;
		xev.xclient.window			= wndClient ;
		xev.xclient.format			= 8 ;
		memset (xev.xclient.data.b, 0, XTRANSPORT_UNIT_SIZE) ;
		memcpy (xev.xclient.data.b, pPacketData, nPacketSize) ;
		XSendEvent (pDisplay, wndClient, False, NoEventMask, &xev) ;
	}
	XFlush (pDisplay) ;
	return	True ;
}

Boolean
ximClient_writeMessageWithProperty (
	register Widget			gw,
	register const BYTE*	pPacketData,
	register int			nPacketSize)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register Display*	pDisplay ;
	register Window		wndClient ;
	XEvent		xev ;

#if defined (DEBUG)
	fprintf (stderr, "ximClient_writeMessageP(%lx): ",
			 wgThis->ximClient.m_wndClient) ;
	XIMPacket_Show (pPacket) ;
#endif
	pDisplay	= XtDisplay (gw) ;
	wndClient	= wgThis->ximClient.m_wndClient ;
	XChangeProperty (pDisplay, wndClient, wgThis->ximClient.m_atReadWrite, XA_STRING, 8, PropModeAppend, pPacketData, nPacketSize) ;
	xev.type					= ClientMessage ;
	xev.xclient.display			= pDisplay ;
	xev.xclient.window			= wndClient ;
	xev.xclient.message_type	= wgThis->ximClient.m_atProtocol ;
	xev.xclient.format			= 32 ;
	xev.xclient.data.l [0]		= nPacketSize ;
	xev.xclient.data.l [1]		= wgThis->ximClient.m_atReadWrite ;
	XSendEvent (pDisplay, wndClient, False, NoEventMask, &xev) ;
	XFlush (pDisplay) ;
	return	True ;
}

/*
 *(関数)
 *	virtual bool	CXIMClient::initialState () ;
 *(機能)
 *	X Input Method Protocol Server と Client が接続するまでのメッセージの処理
 *	を行う。ただ…送られて来たメッセージが XIM_CONNECT 以外だった場合には
 *	サーバには何処までのデータを捨てたら良いのかさっぱり分からないことになる。
 *	「Endian の情報を送ろう！」つー発想よりも先に「この順番で入れる！」という
 *	htons みたいな手法を用意する方がどれ程まともかということが分かる一瞬である。
 *	X lib に patch を当てたいかも。
 *(コメント)
 *	XIM … やっぱりゴミか？
 *(返り値)
 *	True		処理の継続
 *	false		データ不足による処理の中断
 *	エラーは別に XIM_ERROR メッセージを投げるので…大丈夫だと思う。
 */
Boolean
ximClient_initialState (
	register Widget			gw)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register TQueue*			pQueue ;
	XIMData		imData ;
	register int		nMajorOpCode, nMinorOpCode, nLength, nUsage ;
	register CARD8		byByteOrder ;
	register CARD16		woClientMajorProtocolVersion ;
	register CARD16		woClientMinorProtocolVersion ;
	register CARD16		woClientAuthProtocolNameLen ;

	/*init-status*/
	/*	Wait XIM_CONNECT*/
	pQueue	= &wgThis->ximClient.m_queInputMessage ;
	XIMData_Initialize (&imData, TQueue_GetData (pQueue), False) ;
	nUsage	= TQueue_GetUsage (pQueue) ;

	/*
	 *	ヘッダ情報 + Endian 情報だけでも無いとまずい。
	 *	実際にどの程度のデータで1パケットを構成しているのかはエンディアンが分からな
	 *	ければとれない。
	 *※	CARD16 なので。
	 */
	if (nUsage < (int)(XIM_HEADER_SIZE + 8))
		return	False ;
	nMajorOpCode	= XIMData_GetCard8  (&imData) ;
	nMinorOpCode	= XIMData_GetCard8  (&imData) ;
	nLength			= XIMData_GetCard16 (&imData) ;
#if defined (DEBUG)
	fprintf (stderr, "InitialState1 (Major: %d, Minor: %d, Length: %d) / Usage: %d\n", nMajorOpCode, nMinorOpCode, nLength, nUsage) ;
#endif
	
	if (nMajorOpCode != XIM_CONNECT){
		int	nTmpLength ;
		/*
		 *	この段階では Client の Endian が不明なので、受け取ったパケットのサイズすら不明。
		 *	ただ不正な命令が来たということしか分からない。
		 *	仕方がないからキューをフラッシュするが、消し過ぎる可能性が否定できない。
		 *	はっきり言って、X INPUT METHOD PROTOCOL の手落ちだと思う。
		 */
		nTmpLength		= ((nLength & 0x00FF) << 8) | ((nLength >> 8) & 0x00FF) ;
		if (nTmpLength < nLength)
			nLength		= nTmpLength ;
		if ((int)(nLength * 4 + XIM_HEADER_SIZE) <= nUsage){
			TQueue_Out (pQueue, NULL, XIM_HEADER_SIZE + nLength * 4) ;
			//this->authorizationNg () ;
			return	True ;
		} else {
			return	False ;
		}
	}
	//	Recieve XIM_CONNECT
	byByteOrder	= XIMData_GetCard8 (&imData) ;
	if (byByteOrder == XIM_BIGENDIAN){
		wgThis->ximClient.m_fBigEndian	= True ;
		nLength		= ((nLength & 0x00FF) << 8) | ((nLength >> 8) & 0x00FF) ;
	} else {
		wgThis->ximClient.m_fBigEndian	= False ;
	}
	XIMData_SetEndian (&imData, wgThis->ximClient.m_fBigEndian) ;
#if defined (DEBUG)
	fprintf (stderr, "InitialState2 (Major: %d, Minor: %d, Length: %d)\n", nMajorOpCode, nMinorOpCode, nLength) ;
#endif

	/*
	 *	ここに来てはじめて nLength が分かったので、データがそろっているか
	 *	チェックできる。
	 */
	if (nUsage < (int)(nLength * 4 + XIM_HEADER_SIZE))
		return	False ;
	
	XIMData_Forward8 (&imData, 1) ;
	woClientMajorProtocolVersion	= XIMData_GetCard16 (&imData) ;
	woClientMinorProtocolVersion	= XIMData_GetCard16 (&imData) ;
	woClientAuthProtocolNameLen		= XIMData_GetCard16 (&imData) ;
	
	if (woClientMajorProtocolVersion > XIM_PROTOCOL_MAJOR_VERSION ||
		(woClientMajorProtocolVersion == XIM_PROTOCOL_MAJOR_VERSION &&
		 woClientMinorProtocolVersion >  XIM_PROTOCOL_MINOR_VERSION)){
		//	Server NG
		TQueue_Out (pQueue, NULL, XIM_HEADER_SIZE + nLength * 4) ;
		return	ximClient_authorizationNg (gw) ;
	}
	//	Client は Authorization を要求している。
	if (woClientAuthProtocolNameLen > 0){
		register TVarbuffer*	pvbuf ;
		register int			nLength ;

		pvbuf	= &wgThis->ximClient.m_vbufAuthProtocolNameList ;
		TVarbuffer_Clear (pvbuf) ;
		while (woClientAuthProtocolNameLen > 0){
			nLength	= XIMData_GetCard16 (&imData) ;
			//	NUL Terminate する STRING に変換しているが…これがまずいような事態は発生するか？
			if (! (TVarbuffer_Add (pvbuf, (const char*)XIMData_GetHead (&imData), nLength)) ||
				! (TVarbuffer_Add (pvbuf, "\0", 1))) {
				return	False ;
			}
			XIMData_Forward8 (&imData, nLength) ;
			woClientAuthProtocolNameLen	-- ;
		}
		wgThis->ximClient.m_nAuthProtocol	= 0 ;
		
		//	Send XIM_AUTH_REQUIRED
		wgThis->ximClient.m_pDispatcher	= ximClient_authorizationState ;
	} else {
		//	Send XIM_CONNECT_REPLY
		wgThis->ximClient.m_pDispatcher	= ximClient_connectedState ;
		ximClient_authorizationOk (gw) ;
	}
	TQueue_Out (pQueue, NULL, XIM_HEADER_SIZE + nLength * 4) ;
#if defined (DEBUG)
	fprintf (stderr, "InitialState / Queue = %d\n", TQueue_GetUsage (pQueue)) ;
#endif
	return	True ;
}

/*
 *(関数)
 *	virtual bool	CXIMClient::authorizationState () ;
 *(機能)
 *	Server と Client の接続における認証ステージ。
 *(備考)
 *	ここでは Endian が確定しているので楽。
 *	しかしながら、結局認証ってどうやるの？の部分が X library の方で
 *	実装されていない上に X Input Method Protocol version 1.0 仕様書
 *	とやらにどうするのかが書かれてもいないので、実装は不可能だと思う。
 *	「もともとの何がしたいの？」が分かれば…何とかできるのかもしれ
 *	ないけれども。
 *(返り値)
 *	True		処理の継続
 *	false		データ不足による処理の中断
 *	エラーは別に XIM_ERROR メッセージを投げるので…大丈夫だと思う。
 */
Boolean
ximClient_authorizationState (
	register Widget		gw)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register TQueue*	pQueue ;
	XIMData				imData ;
	register int		nMajorOpCode, nMinorOpCode, nLength, nUsage ;

	pQueue	= &wgThis->ximClient.m_queInputMessage ;
	nUsage	= TQueue_GetUsage (pQueue) ;
	if (nUsage < (int)(XIM_HEADER_SIZE))
		return	False ;

	XIMData_Initialize (&imData, TQueue_GetData (pQueue), wgThis->ximClient.m_fBigEndian) ;
	nMajorOpCode	= XIMData_GetCard8  (&imData) ;
	nMinorOpCode	= XIMData_GetCard8  (&imData) ;
	nLength			= XIMData_GetCard16 (&imData) ;
	if (nUsage < (int)(XIM_HEADER_SIZE + nLength * 4))
		return	False ;

	//	Wait XIM_AUTH_REPLY or XIM_AUTH_NEXT
	if (nMajorOpCode != XIM_AUTH_REPLY && nMajorOpCode != XIM_AUTH_NEXT){
		TQueue_Out (pQueue, NULL, XIM_HEADER_SIZE + nLength * 4) ;
		//	Server NG
		return	ximClient_authorizationNg (gw) ;
	}
	if (nMajorOpCode == XIM_AUTH_REPLY){
		//	server_check にするにも AUTH の実装はどうあるべきか…資料が無い。
		TQueue_Out (pQueue, NULL, XIM_HEADER_SIZE + nLength * 4) ;
		return	ximClient_authorizationNg (gw) ;
	} else {
		//	Send XIM_AUTH_REQUIRED
		TQueue_Out (pQueue, NULL, XIM_HEADER_SIZE + nLength * 4) ;
	}
	return	True ;
}

Boolean
ximClient_authorizationOk (
	register Widget		gw)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register XIMPacket*	pPacket ;

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
#if defined (DEBUG) || 0
	fprintf (stderr, "XIMClient_authorizationOk ()\n") ;
#endif
	XIMPacket_SetHeader (pPacket, XIM_CONNECT_REPLY, 0) ;
	XIMPacket_AddCard16 (pPacket, XIM_PROTOCOL_MAJOR_VERSION) ;
	XIMPacket_AddCard16 (pPacket, XIM_PROTOCOL_MINOR_VERSION) ;
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return	True ;
}

/*
 *(関数)
 *	virtual bool	CXIMClient::authorizationNg () ;
 *(機能)
 *	認証に失敗した旨を client に伝える。
 */
Boolean
ximClient_authorizationNg (
	register Widget		gw)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register XIMPacket*	pPacket ;

#if defined (DEBUG) || 0
	fprintf (stderr, "XIMClient_authorizationNg ()\n") ;
#endif
	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_AUTH_NG, 0) ;
	ximClient_writeMessage (gw, pPacket) ;
	wgThis->ximClient.m_pDispatcher	= ximClient_initialState ;
	return	True ;
}

/*
 *
 */
#define	DEFINE_IMVFUNCTION(functionname,string)	Boolean	functionname (Widget gw, int nMajorOpCode, int nMinorOpCode, int nLength, XIMData* pData) \
{ \
    return	ximClient_badProtocol (gw, (string)) ;	\
}	// End of definition

DEFINE_IMVFUNCTION(ximClient_onXimConnect,			"Already connected") ;
DEFINE_IMVFUNCTION(ximClient_onXimConnectReply,			"XIM_CONNECT_REPLY must be sent by IM Server") ;
DEFINE_IMVFUNCTION(ximClient_onXimDisconnectReply,		"XIM_DISCONNECT_REPLY must be sent by IM Server") ;
DEFINE_IMVFUNCTION(ximClient_onXimAuthRequired,			"Not autheraization phase.") ;
DEFINE_IMVFUNCTION(ximClient_onXimAuthReply,			"Not autheraization phase.") ;
DEFINE_IMVFUNCTION(ximClient_onXimAuthNext,			"Not autheraization phase.") ;
DEFINE_IMVFUNCTION(ximClient_onXimAuthSetup,			"Not autheraization phase.") ;
DEFINE_IMVFUNCTION(ximClient_onXimAuthNg,				"Not autheraization phase.") ;
DEFINE_IMVFUNCTION(ximClient_onXimOpenReply,			"XIM_OPEN_REPLY must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimCloseReply,			"XIM_CLOSE_REPLY must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimRegisterTriggerkeys,		"XIM_REGISTER_TGIGGERKEYS must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimTriggerNotifyReply,		"XIM_TRIGGER_NOTIFY must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimSetEventMask,			"XIM_SET_EVENT_MASK must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimEncodingNegotiationReply,	"XIM_ENCODING_NEGOTIATION_REPLY must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimQueryExtensionReply,		"XIM_QUERY_EXTENSION_REPLY must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimSetImValuesReply,		"XIM_SET_IM_VALUES_REPLY must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimGetImValuesReply,		"XIM_GET_IM_VALUES_REPLY must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimCreateIcReply,			"XIM_CREATE_IC_REPLY must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimDestroyIcReply,			"XIM_DESTORY_IC_REPLY must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimSetIcValuesReply,		"XIM_SET_IC_VALUES_REPLY must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimGetIcValuesReply,		"XIM_GET_IC_VALUES_REPLY must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimCommit,				"XIM_COMMIT must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimResetIcReply,			"XIM_RESET_IC_REPLY must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimGeometry,			"XIM_GEOMETRY must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimStrConversion,			"XIM_STR_CONVERSION must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimPreeditStart,			"XIM_PREEDIT_START must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimPreeditDraw,			"XIM_PREEDIT_DRAW must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimPreeditCaret,			"XIM_PREEDIT_CARET must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimPreeditDone,			"XIM_PREEDIT_DONE must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimStatusStart,			"XIM_STATUS_START must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimStatusDraw,			"XIM_STATUS_DRAW must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimStatusDone,			"XIM_STATUS_DONE must be sent by IM Server.") ;
DEFINE_IMVFUNCTION(ximClient_onXimPreeditState,			"XIM_PREEDITSTATE must be sent by IM Server.") ;

#undef	DEFINE_IMVFUNCTION

/*
 *(関数)
 *	virtual bool	CXIMClient::connectedState () ;
 *(機能?)
 *	認証に成功して Server と Client 間の接続が成功した時、この関数が
 *	Client のメッセージを処理するために呼び出される。
 *(返り値)
 *	True		処理の継続
 *	false		データ不足による処理の中断
 *	エラーは別に XIM_ERROR メッセージを投げるので…大丈夫だと思う。
 */
Boolean
ximClient_connectedState (
	register Widget		gw)
{
	/*
	 *	Major Operation Code に対応する処理関数のテーブル。
	 */
	static Boolean	(*operation_table[])(Widget, int, int, int, XIMData*) = {
		NULL,							ximClient_onXimConnect,		
		ximClient_onXimConnectReply,	ximClient_onXimDisconnect,
		ximClient_onXimDisconnectReply,	NULL,
		NULL,							NULL,
		NULL,							NULL,
		ximClient_onXimAuthRequired,	ximClient_onXimAuthReply,
		ximClient_onXimAuthNext,		ximClient_onXimAuthSetup,
		ximClient_onXimAuthNg,			NULL,
		NULL,							NULL,
		NULL,							NULL,
		ximClient_onXimError,			NULL,
		NULL,							NULL,
		NULL,							NULL,
		NULL,							NULL,
		NULL,							NULL,
		ximClient_onXimOpen,			ximClient_onXimOpenReply,
		ximClient_onXimClose,			ximClient_onXimCloseReply,
		ximClient_onXimRegisterTriggerkeys,	ximClient_onXimTriggerNotify,
		ximClient_onXimTriggerNotifyReply,	ximClient_onXimSetEventMask,
		ximClient_onXimEncodingNegotiation,	ximClient_onXimEncodingNegotiationReply,
		ximClient_onXimQueryExtension,	ximClient_onXimQueryExtensionReply,
		ximClient_onXimSetImValues,		ximClient_onXimSetImValuesReply,
		ximClient_onXimGetImValues,		ximClient_onXimGetImValuesReply,
		NULL,							NULL,
		NULL,							NULL,
		ximClient_onXimCreateIc,		ximClient_onXimCreateIcReply,
		ximClient_onXimDestroyIc,		ximClient_onXimDestroyIcReply,
		ximClient_onXimSetIcValues,		ximClient_onXimSetIcValuesReply,
		ximClient_onXimGetIcValues,		ximClient_onXimGetIcValuesReply,
		ximClient_onXimSetIcFocus,		ximClient_onXimUnsetIcFocus,
		ximClient_onXimForwardEvent,	ximClient_onXimSync,
		ximClient_onXimSyncReply,		ximClient_onXimCommit,
		ximClient_onXimResetIc,			ximClient_onXimResetIcReply,
		NULL,							NULL,
		NULL,							NULL,
		ximClient_onXimGeometry,		ximClient_onXimStrConversion,
		ximClient_onXimStrConversionReply,	ximClient_onXimPreeditStart,
		ximClient_onXimPreeditStartReply,	ximClient_onXimPreeditDraw,
		ximClient_onXimPreeditCaret,		ximClient_onXimPreeditCaretReply,
		ximClient_onXimPreeditDone,		ximClient_onXimStatusStart,
		ximClient_onXimStatusDraw,		ximClient_onXimStatusDone,
		ximClient_onXimPreeditState,
	} ;
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register TQueue*			pQueue ;
	XIMData			imData ;
	register int	nMajorOpCode, nMinorOpCode, nLength, nUsage ;

	/*	ヘッダデータがそろっているかどうかのチェックを行う。*/
	pQueue	= &wgThis->ximClient.m_queInputMessage ;
	nUsage	= TQueue_GetUsage (pQueue) ;
	if (nUsage < (int)XIM_HEADER_SIZE)
		return	False ;

	XIMData_Initialize (&imData, TQueue_GetData (pQueue), wgThis->ximClient.m_fBigEndian) ;
	nMajorOpCode	= XIMData_GetCard8 (&imData) ;
	nMinorOpCode	= XIMData_GetCard8 (&imData) ;
	nLength			= XIMData_GetCard16 (&imData) ;
#if defined (DEBUG) || 0
	if (nMajorOpCode > 0)
		fprintf (stderr, "ConnectedState (Major: %d, Minor: %d, Length: %d, nRead: %d/%d\n",
				 nMajorOpCode, nMinorOpCode, nLength, nUsage, XIM_HEADER_SIZE + nLength * 4) ;
#endif
	if (nUsage < (int)(XIM_HEADER_SIZE + nLength * 4))
		return	False ;

	if (nMajorOpCode == XIM_EXT_FORWARD_KEYEVENT){
		ximClient_onXimExtForwardKeyEvent (gw, nMajorOpCode, nMinorOpCode, nLength, &imData) ;
	} else if (nMajorOpCode == XIM_EXT_MOVE){
		ximClient_onXimExtMove (gw, nMajorOpCode, nMinorOpCode, nLength, &imData) ;
	} else if (nMajorOpCode < 0 || nMajorOpCode > XIM_PREEDITSTATE || !operation_table [nMajorOpCode]){
		if (nMajorOpCode)
			ximClient_badProtocol (gw, "Invalid MajorOpCode") ;
	} else {
		(operation_table [nMajorOpCode])(gw, nMajorOpCode, nMinorOpCode, nLength, &imData) ;
	}
	TQueue_Out (pQueue, NULL, XIM_HEADER_SIZE + nLength * 4) ;

	/*	次のメッセージがあるかどうか分からないので、継続実行を要求する。
	 *	エラーが発生した場合に次のメッセージってどうするの？という部分は…謎。
	 */
	return	True ;
}

/*
 *	XIM Packet を処理する member function
 */
/*
 *	XIM_OPEN: XIM library --> XIM Server
 *(コメント)
 *	XIM_OPEN Packet を処理して、XIM_OPEN_REPLY Packet を library (Client) に送り返す。
 *	この時に Input Method を作成する。
 *	1 InputMethod per 1 Client …というわけではないと思うので、ガンガン InputMethod
 *	を作る Client も存在するとは思うけど現状では 1 Client につき 1 InputMethod のよ
 *	うである。
 *	X Input Method Protocol version 1.0 とかいう I18N 以下にあるドキュメントには
 *	Dynamic Flow Control の場合には、XIM_REGISTER_TRIGGERKEYS を XIM_OPEN_REPLY の前
 *	に送ることとあるが、Xlib はそのように実装できていない。
 */
Boolean
ximClient_onXimOpen (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register XIMInputMethod*	pXimIm ;
	register XIMPacket*			pPacket ;
	register const char*		pLocaleString ;
	register int				nID ;
	register int				nKey ;
	register int				nIndexOfByteLength, nValue ;
	/*	デフォルトの変換開始キー。*/
	static const XIMHotKeyTrigger	triggerKey [] = {
		{ XK_KP_Space,	ShiftMask,	ShiftMask },
		{ XK_space,		ShiftMask,	ShiftMask },
	} ;
	register int				nHotKey ;
	const struct XrLikeKey*		pHotKey ;

	/*
	 *	(1) locale 名を取り出す。
	 */
	pLocaleString	= (const char*)XIMData_GetHead (pData) ;
  
	/*
	 *	(1.5) サポートされている locale かどうかチェックする。
	 *	ここはどうするべきか？
	 */

	/*
	 *	(2) input-method-ID を生成して、IM を作る。
	 */
	pXimIm	= XIMInputMethod_Create (gw, wgThis->ximClient.m_uInputMethodID) ;
	if (pXimIm == NULL) {
		/*
		 *	BadAlloc なのかな？ メモリが不足している場合には…？
		 *	あの仕様書からではどのエラーが具体的に何時送られるべきなのかの判断ができないのだけ
		 *	れども…
		 */
		ximClient_writeErrorMessage (gw, -1, -1, XIM_ERROR_BadAlloc, "out of memory.") ;
		return	True ;
	}
	ximClient_registerInputMethod (gw, pXimIm) ;

	/*
	 *	XIM_OPEN_REPLY Packet を client に送る。
	 *		XIM Protocol 仕様書というかなり内容の薄い資料によると、
	 *		「XIM_REGISTER_TRIGGERKEYS は XIM_OPEN_REPLY の前に送ること」
	 *		と書かれているが、
	 *		Xlib の _XimOpen を見ると、_XimWrite で XIM_OPEN を送った後は
	 *		XIM_OPEN_REPLY 以外が来ることを考えていないようである。
	 *		(間違いなく Xlib のバグ)
	 *		最新版ではどうなっているのだろうか？
	 */
	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_OPEN_REPLY, 0) ;
	XIMPacket_AddCard16 (pPacket, wgThis->ximClient.m_uInputMethodID) ;

	/*
	 *	(3) サポートしている IM Attribute を抜き出す。
	 */
	nIndexOfByteLength	= XIMPacket_GetDataSize (pPacket) ;
	XIMPacket_AddCard16 (pPacket, 0 /* byte length of IM attributes supported */) ;
	nID	= 0 ;
	while (ximClient_putInputMethodAttribute (pPacket, nID))
		nID	++ ;
#if defined (DEBUG) || 0
	fprintf (stderr, "InputMethod ... nID = %d\n", nID) ;
#endif
	nValue	= XIMPacket_GetDataSize (pPacket) - nIndexOfByteLength - 2 ;
	XIMPacket_SetCard16 (pPacket, nIndexOfByteLength, nValue) ;

	/*
	 *	(4) サポートしている IC Attribute を抜き出す。
	 */
	nIndexOfByteLength	= XIMPacket_GetDataSize (pPacket) ;
	XIMPacket_AddCard16 (pPacket, 0 /* byte length of IC attributes supported */) ;
	XIMPacket_AddCard16 (pPacket, 0 /* unused */) ;
	nID	= 0 ;
	while (ximClient_putInputContextAttribute (pPacket, nID))
		nID	++ ;
#if defined (DEBUG) || 0
	fprintf (stderr, "InputContext ... nID = %d\n", nID) ;
#endif
	nValue	= XIMPacket_GetDataSize (pPacket) - nIndexOfByteLength - 2 - 2 ;
	XIMPacket_SetCard16 (pPacket, nIndexOfByteLength, nValue) ;

	/*
	 *	(5) XIM_OPEN_REPLY パケットを生成して、送り返す。
	 */
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	
	/*	XIM_REGISTER_TRIGGERKEYS を送る。
	 *	ここは仮実装。だから Trigger Key の変更はできなくなっている。
	 */
	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_REGISTER_TRIGGERKEYS, 0) ;
	XIMPacket_AddCard16 (pPacket, wgThis->ximClient.m_uInputMethodID) ;
	XIMPacket_AddCard16 (pPacket, 0 /* unused */) ;

	nHotKey	= XIMServer_GetConversionStartKey (wgThis->ximClient.m_wgProtocol, &pHotKey) ;
#if defined (DEBUG)
	for (nKey = 0 ; nKey < nHotKey ; nKey ++) {
		fprintf (stderr, "XIMHotKeyTrigger(%lx, %x)\n",
				 pHotKey [nKey].keysym, 
				 pHotKey [nKey].modifier) ;
	}
#endif
	if (nHotKey > 0) {
		/*	on-keys list */
		XIMPacket_AddCard32 (pPacket, (CARD32)(sizeof (CARD32) * 3 * nHotKey)) ;
		for (nKey = 0 ; nKey < nHotKey ; nKey ++) {
			XIMPacket_AddCard32 (pPacket, pHotKey->keysym) ;
			XIMPacket_AddCard32 (pPacket, (unsigned long) pHotKey->modifiers) ;
			XIMPacket_AddCard32 (pPacket, (unsigned long) pHotKey->checkModifiers) ;
			pHotKey	++ ;
		}
	} else {
		XIMPacket_AddCard32 (pPacket, (CARD32)(sizeof (CARD32) * 3 * (sizeof (triggerKey) / sizeof (triggerKey [0])))) ;
		for (nKey = 0 ; nKey < nHotKey ; nKey ++) 
			ximClient_putTriggerKey (gw, pPacket, &triggerKey [nKey]) ;
	}

	/*
	 *	off-keys list
	 *	on-key と off-key が同じ場合には、X library はロクな動作をしない
	 *	ので却下…。
	 */
	XIMPacket_AddCard32 (pPacket, (CARD32)0) ;
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;

	/*
	 *	Input Method ID を 1 増やす。
	 */
	wgThis->ximClient.m_uInputMethodID	++ ;
	return	True ;
}

/*
 *(関数)
 *	virtual bool	OnXimTriggerNotify (int nMajorOpCode, int nMinorOpCode, int nLength, CXIMData* pData) ;
 *(コメント)
 *	トリガーキーが押された時に変換クライアントから送られてくるメッセージ
 *	(XIM_TRIGGER_NOTIFY)の処理関数。
 *	この場合、ON TRIGGER か OFF TRIGGER かが問題になるが、今のところ
 *	OnTrigger しかありえない。
 *	OnTrigger が来た場合に、UserInterface Window は表示され入力が開始され
 *	る。
 */
Boolean
ximClient_onXimTriggerNotify (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register CARD16				wInputMethodID ;
	register CARD16				wInputContextID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMInputContext*	pInputContext ;
	register CARD32				dwFlag ;
	register CARD32				dwIndexOfKeyList ;
	register CARD32				dwEventMask ;
	register Boolean			fRetvalue ;
	register Boolean			fStartForward ;

	wInputMethodID	= XIMData_GetCard16 (pData) ;
	wInputContextID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw, wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	pInputContext	= ximClient_findInputContext (gw, pInputMethod, wInputContextID) ;
	if (pInputContext == NULL)
		return	True ;

	/*
	 *	dwFlag
	 *		#0	on-keys list
	 *		#1	off-keys list
	 *	dwIndexOfKeyList
	 *		キーリストの内のどのキーが押されたのか。
	 *	dwEventMask
	 *		Client の XSelectInput されている Event を特定する…ことが
	 *		可能ではあるが、何にどう使うのだろうか？
	 */
	dwFlag				= XIMData_GetCard32 (pData) ;
	dwIndexOfKeyList	= XIMData_GetCard32 (pData) ;
	dwEventMask			= XIMData_GetCard32 (pData) ;

	if (!dwFlag){
		//	どのキーかは特定しないが… on-key ならば変換動作を開始する。
		fRetvalue		= XIMInputContext_StartConversion (pInputContext) ;
		fStartForward	= True ;
	} else {
		//	off-key ならば変換を動作を停止する。
		fRetvalue		= XIMInputContext_EndConversion (pInputContext) ;
		fStartForward	= False ;
	}
	if (!fRetvalue){
		/*
		 *	変換動作が開始or中止できなければ、エラーを返す。
		 */
		ximClient_writeErrorMessage (gw, wInputMethodID, wInputContextID, XIM_ERROR_BadProtocol, "Conversion error") ;
	} else {
		register XIMPacket*	pPacket ;

		pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;

		/*
		 *	ここの set-forward-event っていうのは？
		 *	忘れているなぁ…。
		 */
		ximClient_setForwardEvent (gw, pInputMethod, pInputContext, fStartForward) ;

		/*
		 *	XIM_TRIGGER_NOTIFY_REPLY メッセージをクライアントに投げる。
		 */
		XIMPacket_SetHeader (pPacket, XIM_TRIGGER_NOTIFY_REPLY, 0) ;
		XIMPacket_AddCard16 (pPacket, wInputMethodID) ;
		XIMPacket_AddCard16 (pPacket, wInputContextID) ;
		XIMPacket_SetLength (pPacket) ;
		ximClient_writeMessage (gw, pPacket) ;
		XIMPacket_Release (pPacket) ;
	}
	return	True ;
}

/*
 *(関数)
 */
Boolean
ximClient_onXimEncodingNegotiation (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register CARD16				wInputMethodID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMPacket*			pPacket ;
	register int				nByteLengthOfEncoding ;
	register int				nLenEncoding ;
	register const char*		pStrEncoding ;
	register int				nEncodingIndex ;
	register int				nCodingSystem ;

	/*
	 *	正しい input-method id かどうかをチェックする。
	 *	ここに input-method id が来る理由は input-method 毎に encoding 方法を選べる
	 *	ようにしたかったからなんでしょうねぇ…。
	 *	誰もそんなことしてくれんかったみたいだけど。(^^;;
	 *	1 Application 1 InputMethod でしかなかったってのは、まさに絵に描いた餅だったっ
	 *	てことなのかな。
	 *	ともあれ COMPOUND_TEXT しかサーバは実装していないので、input-method 側が 
	 *	encoding 情報を持っている必要なし。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw, wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	nByteLengthOfEncoding	= (int)XIMData_GetCard16 (pData) ;
	nEncodingIndex	= -1 ;
	nCodingSystem	= -1 ;
	if (nByteLengthOfEncoding > 0){
		register int	nEncoding ;
		nEncoding	= 0 ;
		while (nByteLengthOfEncoding > 0){
			nLenEncoding	= XIMData_GetCard8 (pData) ;
			nByteLengthOfEncoding	-- ;
			if (nByteLengthOfEncoding < nLenEncoding){
				ximClient_writeErrorMessage (gw, wInputMethodID, -1, XIM_ERROR_BadProtocol, "Lack of data.") ;
				return	True ;
			}
			pStrEncoding	= (const char*)XIMData_GetHead (pData) ;
#if defined (DEBUG)
			{
				TVarbuffer	vbufMsg ;
				TVarbuffer_Initialize (&vbufMsg, sizeof (char)) ;
				TVarbuffer_Add (&vbufMsg, pStrEncoding, nLenEncoding) ;
				TVarbuffer_Add (&vbufMsg, "", 1) ;	/* NUL も必要。*/
				fprintf (stderr, "OnXimEncodingNegotitation: \"%s\".\n",
						 (const char*)TVarbuffer_GetBuffer (&vbufMsg)) ;
				TVarbuffer_Uninitialize (&vbufMsg) ;
			}
#endif
			if (ximClient_supportedEncodingp (pStrEncoding, nLenEncoding)) {
				break ;
			}
			XIMData_Forward8 (pData, nLenEncoding) ;
			nByteLengthOfEncoding	-= nLenEncoding ;
			nEncoding	++ ;
		}
	}

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_ENCODING_NEGOTIATION_REPLY, 0) ;
	XIMPacket_AddCard16 (pPacket, wInputMethodID) ;
	/* 現在の実装では detailed information は存在しないので、必ず #0 となる。*/
	XIMPacket_AddCard16 (pPacket, 0) ;
	XIMPacket_AddCard16 (pPacket, nEncodingIndex) ;
	XIMPacket_AddCard16 (pPacket, 0) ;		/* unused */
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return	True ;
}

/*
 *(コメント)
 *	EXTENSION として実装されるべきものは X library を見る限りにおいて、
 *		"XIM_EXT_SET_EVENT_MASK",
 *		"XIM_EXT_FORWARD_KEYEVENT",
 *		"XIM_EXT_MOVE"
 *	の3種類のようだ。
 */
Boolean
ximClient_onXimQueryExtension (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register CARD16				wInputMethodID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMPacket*			pPacket ;
	static const char*			pExtensions [] = {
		"XIM_EXT_SET_EVENT_MASK", "XIM_EXT_FORWARD_KEYEVENT", "XIM_EXT_MOVE", 0,
	} ;
	register int				nByteLengthIndex ;
	register int				nExtensions ;
	register int				nByteLengthOfExt ;
	register const char*		pExtString ;
	register int				nExtStrLength ;
	register unsigned int		uMask ;
	register int				nExtPktSize ;

	/*
	 *	正しい input-method id かどうかをチェックする。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw, wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	nByteLengthOfExt	= XIMData_GetCard16 (pData) ;

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_QUERY_EXTENSION_REPLY, 0) ;
	XIMPacket_AddCard16 (pPacket, wInputMethodID) ;
	nByteLengthIndex	= XIMPacket_GetDataSize (pPacket) ;
	XIMPacket_AddCard16 (pPacket, 0 /* dummy */) ;

	/*
	 *	尋ねるべき EXTENSION が空だった場合にはサーバがサポートしているも
	 *	の全部を返さなければならない。
	 *	そうでなければ、クライアントが送って来たものと比較して自分とクラ
	 *	イアントの両方がサポートしているものを返す。
	 */
	if (!nByteLengthOfExt){
		for (nExtensions = 0 ; pExtensions [nExtensions] ; nExtensions ++){
			XIMPacket_AddCard8   (pPacket, XIM_EXT_SET_EVENT_MASK + nExtensions) ;
			XIMPacket_AddCard8   (pPacket, 0) ;
			nExtStrLength	= strlen (pExtensions [nExtensions]) ;
			XIMPacket_AddCard16  (pPacket, nExtStrLength) ;
			XIMPacket_AddString8 (pPacket, pExtensions [nExtensions], nExtStrLength) ;
			XIMPacket_AddPad     (pPacket, nExtStrLength) ;
		}
		/*	利用可能な Extension を記憶しておく。*/
		uMask	= XIM_EXT_SET_EVENT_MASK_MASK | XIM_EXT_FORWARD_KEYEVENT_MASK | XIM_EXT_MOVE_MASK ;
		XIMInputMethod_SetExtMask (pInputMethod, uMask) ;
	} else {
		uMask	= XIMInputMethod_GetExtMask (pInputMethod) ;
		while (nByteLengthOfExt > 0){
			nExtStrLength	= XIMData_GetCard8 (pData) ;
			pExtString		= (const char*)XIMData_GetHead (pData) ;
			for (nExtensions = 0 ; pExtensions [nExtensions] ; nExtensions ++){
				if (!strncmp (pExtString, pExtensions [nExtensions], nExtStrLength)){
#if defined (DEBUG) || 0
					fprintf (stderr, "Extension: \"%s\"/(%d)\n", pExtensions [nExtensions], nExtStrLength) ;
#endif
					XIMPacket_AddCard8   (pPacket, XIM_EXT_SET_EVENT_MASK + nExtensions) ;
					XIMPacket_AddCard8   (pPacket, 0) ;
					XIMPacket_AddCard16  (pPacket, nExtStrLength) ;
					XIMPacket_AddString8 (pPacket, pExtString, nExtStrLength) ;
					XIMPacket_AddPad     (pPacket, nExtStrLength) ;
					//	利用可能な Extension を記憶しておく。
					uMask	|= (unsigned int)1 << nExtensions ;
				}
			}
			XIMData_Forward8 (pData, nExtStrLength) ;
			nByteLengthOfExt	-= (nExtStrLength + 1) ;
		}
		XIMInputMethod_SetExtMask (pInputMethod, uMask) ;
	}

	nExtPktSize	= XIMPacket_GetDataSize (pPacket) - nByteLengthIndex - 2 ;
	XIMPacket_SetCard16 (pPacket, nByteLengthIndex, nExtPktSize) ;
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return	True ;
}

/*
 *
 */
Boolean
ximClient_onXimSetImValues (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register CARD16				wInputMethodID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMPacket*			pPacket ;
	register XIMAttribute*		pAttribute ;
	register int			nByteLengthOfImAttribute ;
	register int			wAttributeID ;
	register int			nValueLength ;
	
	/*
	 *	正しい input-method id かどうかをチェックする。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw,wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	nByteLengthOfImAttribute	= XIMData_GetCard16 (pData) ;
	if (nByteLengthOfImAttribute > 0){
		while (nByteLengthOfImAttribute > 0){
			if (nByteLengthOfImAttribute < (int)((sizeof (CARD16) + sizeof (CARD16)) / sizeof (CARD8))){
				ximClient_writeErrorMessage (gw, wInputMethodID, -1, XIM_ERROR_BadProtocol, "Lack of im-value.") ;
				return	True ;
			}
			wAttributeID		= XIMData_GetCard16 (pData) ;
			nValueLength		= XIMData_GetCard16 (pData) ;
			nByteLengthOfImAttribute	-= (sizeof (CARD16) + sizeof (CARD16)) / sizeof (CARD8) ;
			if (nValueLength <= 0){
				XIMData_Forward8 (pData, IMPAD (nValueLength)) ;
				continue ;
			}
			if (nByteLengthOfImAttribute < nValueLength){
				ximClient_writeErrorMessage (gw, wInputMethodID, -1, XIM_ERROR_BadProtocol, "Lack of im-value.") ;
				return	True ;
			}
			/*	wAttributeID と nValueLength、pData から value をがんばってデコード
			 *	して下さい。(合掌)
			 */
			if (wAttributeID < 0 || wAttributeID >= MAX_NUMBER_OF_XIM_ATTRIBUTEID){
				ximClient_writeErrorMessage (gw, wInputMethodID, -1, XIM_ERROR_BadProtocol, "Invalid Attribute-ID.") ;
				return	True ;
			}

			pAttribute		= &srSupportedInputMethodAttributes [wAttributeID] ;
			if (pAttribute->m_pSetter == NULL){
				/*
				 *	設定できない値を設定しようとした場合には当然エラーとなる…のか？
				 *	どの値も設定できるかもしれないし、設定できないかもしれない。
				 *	これは IM Server を実装する側が好きに決めて良い…と思うしかないようだ。
				 */
				ximClient_writeErrorMessage (gw, wInputMethodID, -1, XIM_ERROR_BadProtocol, "Operation: SetImValue is not permitted.") ;
				return	True ;
			}
			if (!(pAttribute->m_pSetter)(gw, pInputMethod, 0, pData, nValueLength, 0))
				return	True ;
			XIMData_Forward8 (pData, IMPAD (nValueLength)) ;
		}
	}

	/*
	 *	XIM_ERROR が送られている場合には XIM_SET_IM_VALUES_REPLY を送る必要は無いだろう…。
	 */
	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_SET_IM_VALUES_REPLY, 0) ;
	XIMPacket_AddCard16 (pPacket, wInputMethodID) ;
	XIMPacket_AddCard16 (pPacket, 0 /* unused */) ;
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return	True ;
}

Boolean
ximClient_onXimGetImValues (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register CARD16				wInputMethodID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMPacket*			pPacket ;
	register XIMAttribute*		pAttribute ;
	register int				nIndexByteLengthOfImAttributeList ;
	register int				wAttributeID ;
	int							nByteLengthOfImAttribute ;
	register int				nByteLength ;
	
	/*
	 *	正しい input-method id かどうかをチェックする。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw, wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	nByteLengthOfImAttribute	= XIMData_GetCard16 (pData) ;

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_GET_IM_VALUES_REPLY, 0) ;
	XIMPacket_AddCard16 (pPacket, wInputMethodID) ;
	nIndexByteLengthOfImAttributeList	= XIMPacket_GetDataSize (pPacket) ;
	XIMPacket_AddCard16 (pPacket, 0 /* Dummy */) ;

	if (nByteLengthOfImAttribute > 0){
		while (nByteLengthOfImAttribute > 0){
			if (nByteLengthOfImAttribute < (int)(sizeof (CARD16) / sizeof (CARD8))){
				ximClient_writeErrorMessage (gw, wInputMethodID, -1, XIM_ERROR_BadProtocol, "Lack of im-attribute.") ;
				goto	exit_func ;
			}
			wAttributeID		= XIMData_GetCard16 (pData) ;
			nByteLengthOfImAttribute	-= sizeof (CARD16) / sizeof (CARD8) ;
			if (wAttributeID < 0 || wAttributeID >= MAX_NUMBER_OF_XIM_ATTRIBUTEID){
				ximClient_writeErrorMessage (gw, wInputMethodID, -1, XIM_ERROR_BadProtocol, "Invalid attribute-ID.") ;
				goto	exit_func ;
			}
			pAttribute	= &srSupportedInputMethodAttributes [wAttributeID] ;
			if (pAttribute->m_pGetter == NULL){
				/*
				 *	取得できない値を得ようとした場合には当然エラーとなる…のか？
				 */
				ximClient_writeErrorMessage (gw, wInputMethodID, -1, XIM_ERROR_BadProtocol, "Operation: GetImValue is not permitted.") ;
				goto	exit_func ;
			}
			if (!(pAttribute->m_pGetter)(gw, pInputMethod, 0, pData, &nByteLengthOfImAttribute, 0, pPacket))
				goto	exit_func ;
		}
	}
	nByteLength	= XIMPacket_GetDataSize (pPacket) - (nIndexByteLengthOfImAttributeList + sizeof (CARD16)) ;
	XIMPacket_SetCard16 (pPacket, nIndexByteLengthOfImAttributeList, nByteLength) ;
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
  exit_func:
	XIMPacket_Release (pPacket) ;
	return	True ;
}

Boolean
ximClient_onXimCreateIc (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register CARD16				wInputMethodID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMInputContext*	pInputContext ;
	register XIMPacket*			pPacket ;
	register int				nByteLengthOfIcAttribute ;

	/*
	 *	正しい input-method id かどうかをチェックする。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw,wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	/*	input-context を作成する。*/
	pInputContext				= XIMInputMethod_CreateInputContext (pInputMethod) ;
	nByteLengthOfIcAttribute	= XIMData_GetCard16 (pData) ;
	/*	XIM_CREATE_IC に渡されている ic-attribute を設定する。*/
	if (nByteLengthOfIcAttribute > 0 &&
		!ximClient_setIcValues (gw, pInputMethod, pInputContext, pData, nByteLengthOfIcAttribute, XIC_CREATE_MASK)){
		/*	不幸にしてエラーが発生した場合には input-context を破棄する。*/
		XIMInputMethod_DestroyInputContext (pInputMethod, pInputContext) ;
		return	True ;
	}

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_CREATE_IC_REPLY, 0) ;
	XIMPacket_AddCard16 (pPacket, wInputMethodID) ;
	XIMPacket_AddCard16 (pPacket, XIMInputContext_GetID (pInputContext)) ;
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return	True ;
}

Boolean
ximClient_onXimSetIcValues (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register CARD16				wInputMethodID ;
	register CARD16				wInputContextID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMInputContext*	pInputContext ;
	register XIMPacket*			pPacket ;
	register int				nByteLengthOfIcAttribute ;

	/*
	 *	正しい input-method id かどうかをチェックする。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw, wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	/*	正しい input-context id かどうかをチェックする。*/
	wInputContextID	= XIMData_GetCard16 (pData) ;
	pInputContext	= ximClient_findInputContext (gw, pInputMethod, wInputContextID) ;
	if (pInputContext == NULL)
		return	True ;

	/*	byte length of ic-attribute を読み取る。*/
	nByteLengthOfIcAttribute	= XIMData_GetCard16 (pData) ;
	/*	unused を読み飛ばす。*/
	XIMData_Forward8 (pData, 2) ;
	/*	XIM_CREATE_IC に渡されている ic-attribute を設定する。*/
	if (nByteLengthOfIcAttribute > 0 &&
		!ximClient_setIcValues (gw, pInputMethod, pInputContext, pData, nByteLengthOfIcAttribute, 0)) {
		return	True ;
	}

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_SET_IC_VALUES_REPLY, 0) ;
	XIMPacket_AddCard16 (pPacket, wInputMethodID) ;
	XIMPacket_AddCard16 (pPacket, XIMInputContext_GetID (pInputContext)) ;
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return	True ;
}

Boolean
ximClient_onXimGetIcValues (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register CARD16				wInputMethodID ;
	register CARD16				wInputContextID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMInputContext*	pInputContext ;
	register XIMPacket*			pPacket ;
	int							nByteLengthOfIcAttribute ;
	register int				nIndexOfByteLength ;
	register int				nBodySize ;

	/*
	 *	正しい input-method id かどうかをチェックする。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw, wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	/*	正しい input-context id かどうかをチェックする。*/
	wInputContextID	= XIMData_GetCard16 (pData) ;
	pInputContext	= ximClient_findInputContext (gw, pInputMethod, wInputContextID) ;
	if (pInputContext == NULL)
		return	True ;

	nByteLengthOfIcAttribute	= XIMData_GetCard16 (pData) ;
	
	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_GET_IC_VALUES_REPLY, 0) ;
	XIMPacket_AddCard16 (pPacket, wInputMethodID) ;
	XIMPacket_AddCard16 (pPacket, wInputContextID) ;
	nIndexOfByteLength	= XIMPacket_GetDataSize (pPacket) ;
	XIMPacket_AddCard16 (pPacket, 0 /* Byte length of ic-attributes */) ;
	XIMPacket_AddCard16 (pPacket, 0 /* unused */) ;
	/*	XIM_CREATE_IC に渡されている ic-attribute を設定する。*/
	if (nByteLengthOfIcAttribute > 0 &&
		!ximClient_getIcValues (gw, pInputMethod, pInputContext, pData, &nByteLengthOfIcAttribute, 0, pPacket))
		goto	exit_func ;
	nBodySize	= XIMPacket_GetDataSize (pPacket) - nIndexOfByteLength - (sizeof (CARD16) + sizeof (CARD16)) / sizeof (CARD8) ;
	XIMPacket_SetCard16 (pPacket, nIndexOfByteLength, nBodySize) ;
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
  exit_func:
	XIMPacket_Release (pPacket) ;
	return	True ;
}

Boolean
ximClient_onXimSetIcFocus (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register CARD16				wInputMethodID ;
	register CARD16				wInputContextID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMInputContext*	pInputContext ;

	/*
	 *	正しい input-method id かどうかをチェックする。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw, wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	/*	正しい input-context id かどうかをチェックする。*/
	wInputContextID	= XIMData_GetCard16 (pData) ;
	pInputContext	= ximClient_findInputContext (gw, pInputMethod, wInputContextID) ;
	if (pInputContext == NULL)
		return	True ;

	XIMInputContext_SetFocus (pInputContext) ;
	/*	Asyncronous request なので Reply Message はない。*/
	return	True ;
}

Boolean
ximClient_onXimUnsetIcFocus (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register CARD16				wInputMethodID ;
	register CARD16				wInputContextID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMInputContext*	pInputContext ;

	/*
	 *	正しい input-method id かどうかをチェックする。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw, wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	/*	正しい input-context id かどうかをチェックする。*/
	wInputContextID	= XIMData_GetCard16 (pData) ;
	pInputContext	= ximClient_findInputContext (gw, pInputMethod, wInputContextID) ;
	if (pInputContext == NULL)
		return	True ;

	XIMInputContext_UnsetFocus (pInputContext) ;
	/*	Asyncronous request なので Reply Message はない。*/
	return	True ;
}

Boolean
ximClient_onXimDestroyIc (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register CARD16				wInputMethodID ;
	register CARD16				wInputContextID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMInputContext*	pInputContext ;
	register XIMPacket*			pPacket ;

	/*
	 *	正しい input-method id かどうかをチェックする。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw, wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	/*
	 *	正しい input-context id かどうかをチェックする。
	 */
	wInputContextID	= XIMData_GetCard16 (pData) ;
	pInputContext	= ximClient_findInputContext (gw, pInputMethod, wInputContextID) ;
	if (pInputContext == NULL)
		return	True ;

	/*	直接 XIMInputContext_Destroy を呼び出してはいけない。*/
	XIMInputMethod_DestroyInputContext (pInputMethod, pInputContext) ;

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_DESTROY_IC_REPLY, 0) ;
	XIMPacket_AddCard16 (pPacket, wInputMethodID) ;
	XIMPacket_AddCard16 (pPacket, wInputContextID) ;
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return	True ;
}

Boolean
ximClient_onXimResetIc (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register CARD16				wInputMethodID ;
	register CARD16				wInputContextID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMInputContext*	pInputContext ;
	register XIMPacket*			pPacket ;
	register int				nTextLength	= 0 ;
  
	/*
	 *	正しい input-method id かどうかをチェックする。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw,wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	/*	正しい input-context id かどうかをチェックする。*/
	wInputContextID	= XIMData_GetCard16 (pData) ;
	pInputContext	= ximClient_findInputContext (gw, pInputMethod, wInputContextID) ;
	if (pInputContext == NULL)
		return	True ;

	/*
	 *	現在まで入力されていた文字列を送るインターフェースがあるのだが、
	 *	その必要はあるのか？ 今の実装だと、勝手に入力中の文字列を取られ
	 *	るのは辛い。(こっちにはこっちの都合があるというヤツですな)
	 */
	XIMInputContext_ResetConversion (pInputContext) ;

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_RESET_IC_REPLY, 0) ;
	XIMPacket_AddCard16 (pPacket, wInputMethodID) ;
	XIMPacket_AddCard16 (pPacket, wInputContextID) ;
	XIMPacket_AddCard16 (pPacket, nTextLength) ;
	XIMPacket_AddPad (pPacket, 2 + nTextLength) ;
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return	True ;
}

Boolean
ximClient_onXimForwardEvent (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	//register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register CARD16				wInputMethodID ;
	register CARD16				wInputContextID ;
	register CARD16				wFlag ;
	register CARD16				wSerialNumber ;
	register XIMInputMethod*	pInputMethod ;
	register XIMInputContext*	pInputContext ;
	XEvent		xev ;

	/*
	 *	正しい input-method id かどうかをチェックする。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw,wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	/*	正しい input-context id かどうかをチェックする。*/
	wInputContextID	= XIMData_GetCard16 (pData) ;
	pInputContext	= ximClient_findInputContext (gw, pInputMethod, wInputContextID) ;
	if (pInputContext == NULL)
		return	True ;

	wFlag			= XIMData_GetCard16 (pData) ;
	wSerialNumber	= XIMData_GetCard16 (pData) ;

	if (wFlag & FORWARDEVENT_SYNC_MASK) {
#if defined (DEBUG) || 0
		fprintf (stderr, "[Begin] Client-Sync-Mode\n") ;
#endif
		XIMInputContext_SetSyncMode (pInputContext, XIMClientSync) ;
	}

	/*	xEvent 構造体から XEvent 構造体にデータを詰め直す。*/
	if (ximClient_createXEvent (gw, wSerialNumber, (const xEvent*)XIMData_GetHead (pData), &xev)) {
#if defined (DEBUG) || 0
		fprintf (stderr, "Forwarded Event: type(%d)\n", xev.type) ;
#endif
		if (!XIMInputContext_ForwardEvent (pInputContext, &xev))
			XIMClient_ForwardEvent (gw, pInputMethod, pInputContext, &xev) ;
	}

	/*	Sync フラグがたっていたら、XIM_SYNC_REPLY を発行する必要がある。*/
	if (wFlag & FORWARDEVENT_SYNC_MASK) {
		ximClient_writeSyncReply (gw, wInputMethodID, pInputContext) ;
		XIMInputContext_UnsetSyncMode (pInputContext, XIMClientSync) ;
#if defined (DEBUG) || 0
		fprintf (stderr, "[End] Client-Sync-Mode\n") ;
#endif
	}
	return	True ;
}

Boolean
ximClient_onXimSync (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register CARD16				wInputMethodID ;
	register CARD16				wInputContextID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMInputContext*	pInputContext ;
	register XIMPacket*			pPacket ;

	/*
	 *	正しい input-method id かどうかをチェックする。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw, wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	/*	正しい input-context id かどうかをチェックする。*/
	wInputContextID	= XIMData_GetCard16 (pData) ;
	pInputContext	= ximClient_findInputContext (gw, pInputMethod, wInputContextID) ;
	if (pInputContext == NULL)
		return	True ;

#if defined (DEBUG)
	fprintf (stderr, "XIM_SYNC : MethodID (%d), ContextID (%d)\n",
			 wInputMethodID,
			 wInputContextID) ;
#endif
	/*	SYNC を要求されても、クライアントからの SYNC REPLY が来ない限り
	 *	においてキューに入っているパケットをさばくことはできない。
	 */
	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_SYNC_REPLY, 0) ;
	XIMPacket_AddCard16 (pPacket, wInputMethodID) ;
	XIMPacket_AddCard16 (pPacket, wInputContextID) ;
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return	True ;
}

Boolean
ximClient_onXimSyncReply (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register CARD16				wInputMethodID ;
	register CARD16				wInputContextID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMInputContext*	pInputContext ;

	/*
	 *	正しい input-method id かどうかをチェックする。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw, wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	/*	正しい input-context id かどうかをチェックする。*/
	wInputContextID	= XIMData_GetCard16 (pData) ;
	pInputContext	= ximClient_findInputContext (gw, pInputMethod, wInputContextID) ;
	if (pInputContext == NULL)
		return	True ;

#if defined (DEBUG)
	fprintf (stderr, "XIM_SYNC_REPLY : MethodID (%d), ContextID (%d)\n",
			 wInputMethodID,
			 wInputContextID) ;
#endif

	/*	直前のブロックは解除される。*/
	XIMInputContext_UnsetSyncMode (pInputContext, XIMSyncNormal) ;

	/*	ブロック解除によって spool されているパケットが flush される。*/
	ximClient_flushSpooledPacket (gw, pInputContext) ;
	return	True ;
}

Boolean
ximClient_onXimStrConversionReply (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	return	True ;
}

Boolean
ximClient_onXimPreeditStartReply (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register CARD16				wInputMethodID ;
	register CARD16				wInputContextID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMInputContext*	pInputContext ;

	/*
	 *	正しい input-method id かどうかをチェックする。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw, wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	/*	正しい input-context id かどうかをチェックする。*/
	wInputContextID	= XIMData_GetCard16 (pData) ;
	pInputContext	= ximClient_findInputContext (gw, pInputMethod, wInputContextID) ;
	if (pInputContext == NULL)
		return	True ;

#if defined (DEBUG)
	fprintf (stderr, "XIM_PREEDIT_START_REPLY : MethodID (%d), ContextID (%d), Return (%d)\n",
			 wInputMethodID,
			 wInputContextID,
			 XIMData_GetCard32 (pData)) ;
#endif

	/*	直前のブロックは解除される。*/
	XIMInputContext_UnsetSyncMode (pInputContext, XIMSyncPreeditStart) ;
	
	/*	ブロック解除によって spool されているパケットが flush される。*/
	ximClient_flushSpooledPacket (gw, pInputContext) ;
	return	True ;
}

Boolean
ximClient_onXimPreeditCaretReply (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register CARD16				wInputMethodID ;
	register CARD16				wInputContextID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMInputContext*	pInputContext ;

	/*
	 *	正しい input-method id かどうかをチェックする。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw, wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	/*	正しい input-context id かどうかをチェックする。*/
	wInputContextID	= XIMData_GetCard16 (pData) ;
	pInputContext	= ximClient_findInputContext (gw, pInputMethod, wInputContextID) ;
	if (pInputContext == NULL)
		return	True ;

	/*	返される Position の値は多分使わないので、無視する。*/
#if defined (DEBUG)
	fprintf (stderr, "XIM_PREEDIT_CARET_REPLY : MethodID (%d), ContextID (%d), Position (%ld)\n",
			 wInputMethodID,
			 wInputContextID,
			 XIMData_GetCard32 (pData)) ;
#endif

	/*	直前のブロックは解除される。*/
	XIMInputContext_UnsetSyncMode (pInputContext, XIMSyncPreeditCaret) ;
	
	/*	ブロック解除によって spool されているパケットが flush される。*/
	ximClient_flushSpooledPacket (gw, pInputContext) ;
	return	True ;
}

Boolean
ximClient_onXimClose (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register CARD16				wInputMethodID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMPacket*			pPacket ;

	/*	input-method id から input-method を得る。*/
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw, wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	ximClient_unregisterInputMethod (gw, pInputMethod) ;
	XIMInputMethod_Destroy (pInputMethod) ;

	/*	XIM_CLOSE_REPLY を Library に送る。*/
	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_CLOSE_REPLY, 0) ;
	XIMPacket_AddCard16 (pPacket, wInputMethodID) ;
	XIMPacket_AddCard16 (pPacket, 0) ;
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return	True ;
}

Boolean
ximClient_onXimDisconnect (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register XIMPacket*			pPacket ;

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_DISCONNECT_REPLY, 0) ;
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;

	/*	全ての InputMethod を破棄する。*/
	ximClient_destroyAllInputMethods (gw) ;

	/*	接続前の状態 (xInitialState) に戻す。*/
	wgThis->ximClient.m_pDispatcher	= ximClient_initialState ;
	return	True ;
}

Boolean
ximClient_onXimError (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	return	True ;
}

Boolean
ximClient_onXimExtForwardKeyEvent (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	/*register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;*/
	register CARD16				wInputMethodID ;
	register CARD16				wInputContextID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMInputContext*	pInputContext ;
	XEvent						xev ;
	register CARD16				wFlag ;

	/*
	 *	正しい input-method id かどうかをチェックする。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw, wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	/*	正しい input-context id かどうかをチェックする。*/
	wInputContextID	= XIMData_GetCard16 (pData) ;
	pInputContext	= ximClient_findInputContext (gw, pInputMethod, wInputContextID) ;
	if (pInputContext == NULL)
		return	True ;

	wFlag				= XIMData_GetCard16 (pData) ;
	/*	以下は xlib にある設定を参考にしている。*/
	memset (&xev, 0, sizeof (XEvent)) ;
	xev.xkey.display	= XtDisplay (gw) ;
	xev.xkey.serial		= XIMData_GetCard16 (pData) ;
	xev.xkey.type		= XIMData_GetCard8 (pData) & 0x7F ;
	xev.xkey.keycode	= XIMData_GetCard8 (pData) ;
	xev.xkey.state		= XIMData_GetCard16 (pData) ;
	xev.xkey.time		= (Time) XIMData_GetCard32 (pData) ;
	xev.xkey.window		= (Window) XIMData_GetCard32 (pData) ;

	if (wFlag & 1) 
		XIMInputContext_SetSyncMode (pInputContext, XIMClientSync) ;

	/*	X Event を Forward する。
	 *	Forward できない場合があるのではなかろうか？(まずいのでは？)
	 */
	if (!XIMInputContext_ForwardEvent (pInputContext, &xev))
		XIMClient_ForwardEvent (gw, pInputMethod, pInputContext, &xev) ;

	/*	Synchronous ならば XIM_SYNC_REPLY を送るのは、必要な
	 *	パケットを飛ばしきった後。
	 *	だから、先に処理を実行する。*/
	if (wFlag & 1) {
		ximClient_writeSyncReply (gw, wInputMethodID, pInputContext) ;
		XIMInputContext_UnsetSyncMode (pInputContext, XIMClientSync) ;
	}
	return	True ;
}

Boolean
ximClient_onXimExtMove (
	register Widget		gw,
	register int		nMajorOpCode,
	register int		nMinorOpCode,
	register int		nLength,
	register XIMData*	pData)
{
	register CARD16				wInputMethodID ;
	register CARD16				wInputContextID ;
	register XIMInputMethod*	pInputMethod ;
	register XIMInputContext*	pInputContext ;
	XPoint		pos ;

	/*
	 *	正しい input-method id かどうかをチェックする。
	 */
	wInputMethodID	= XIMData_GetCard16 (pData) ;
	pInputMethod	= ximClient_findInputMethod (gw, wInputMethodID) ;
	if (pInputMethod == NULL)
		return	True ;

	/*	正しい input-context id かどうかをチェックする。*/
	wInputContextID	= XIMData_GetCard16 (pData) ;
	pInputContext	= ximClient_findInputContext (gw, pInputMethod, wInputContextID) ;
	if (pInputContext == NULL)
		return	True ;

	pos.x	= XIMData_GetCard16 (pData) ;
	pos.y	= XIMData_GetCard16 (pData) ;
	XIMInputContext_SetSpotLocation (pInputContext, &pos) ;
	return	True ;
}

/* ////////////////////////////////////////////////////////////////////////
 */

/*
 *(関数)
 *	virtual bool	putInputMethodAttribute (XIMPacket* pPacket, int nID) ;
 *(機能)
 *	nID で attributeID を指定された attribute を XIMATTR の形に直してパケットに流し込む。
 *(返り値)
 *	true or falase
 *(備考)
 *	いきなり流し込みます。それ以外の利用は考えていなかったりして。
 *	char* の配列に入れるとか…って、パケットにする以外にこんな使いにくい形式にすること
 *	あるの？
 */
Boolean
ximClient_putInputMethodAttribute (
	register XIMPacket*		pPacket,
	register int			nID)
{
	assert (pPacket != NULL) ;
	if (nID < 0 || nID >= sizeof (srSupportedInputMethodAttributes) / sizeof (srSupportedInputMethodAttributes [0]))
		return	False ;

	return	ximClient_putAttributeCommon (pPacket, nID, &srSupportedInputMethodAttributes [nID]) ;
}

Boolean
ximClient_putInputContextAttribute (
	register XIMPacket*		pPacket,
	register int			nID)
{
	assert (pPacket != NULL) ;
	if (nID < 0 || nID >= sizeof (srSupportedInputContextAttributes) / sizeof (srSupportedInputContextAttributes [0]))
		return	False ;

	return	ximClient_putAttributeCommon (pPacket, nID, &srSupportedInputContextAttributes [nID]) ;
}

Boolean
ximClient_putAttributeCommon (
	register XIMPacket*		pPacket,
	register int			nID,
	register XIMAttribute*	pAttribute)
{
	register int	nLength ;

	assert (pPacket != NULL) ;
	assert (pAttribute != NULL) ;

	nLength	= strlen (pAttribute->m_pName) ;
	XIMPacket_AddCard16  (pPacket, (CARD16)nID);
	XIMPacket_AddCard16  (pPacket, (CARD16)pAttribute->m_uValueType) ;
	XIMPacket_AddCard16  (pPacket, (CARD16)nLength) ;
	XIMPacket_AddString8 (pPacket, pAttribute->m_pName, nLength) ;
	XIMPacket_AddPad     (pPacket, 2 + nLength) ;
	return	True ;
}

Boolean
ximClient_putTriggerKey (
	register Widget			gw,
	register XIMPacket*		pPacket,
	register const XIMHotKeyTrigger*	pTriggerkey)
{
	assert (pPacket != NULL) ;
	assert (pTriggerkey != NULL) ;

	XIMPacket_AddCard32 (pPacket, (CARD32)pTriggerkey->keysym) ;
	XIMPacket_AddCard32 (pPacket, (CARD32)pTriggerkey->modifier) ;
	XIMPacket_AddCard32 (pPacket, (CARD32)pTriggerkey->modifier_mask) ;
	return	True ;
}

Boolean
ximClient_writeErrorMessage (
	register Widget			gw,
	register int			nInputMethodID,
	register int			nInputContextID,
	register int			nErrorCode,
	register const char*	pString)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;
	register XIMPacket*			pPacket ;
	register int				nLength ;

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	nLength	= (pString)? strlen (pString) : 0 ;

	XIMPacket_SetHeader (pPacket, XIM_ERROR, 0) ;
	XIMPacket_AddCard16 (pPacket, nInputMethodID) ;
	XIMPacket_AddCard16 (pPacket, nInputContextID) ;
	XIMPacket_AddBitmask16 (pPacket, ((nInputMethodID >= 0)? 1 : 0) | ((nInputContextID >= 0)? 2 : 0)) ;
	XIMPacket_AddCard16 (pPacket, nErrorCode) ;
	XIMPacket_AddCard16 (pPacket, nLength) ;
	XIMPacket_AddCard16 (pPacket, 0) ;
	XIMPacket_AddString8 (pPacket, pString, nLength) ;
	XIMPacket_AddPad (pPacket, nLength) ;
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return	True ;
}

/*
 *(機能)
 *	XIM_ERROR の内、#13 Bad Protocol を library (client) へと送る。
 *	Bad Protocol が一番柔軟かな？ エラー処理に使うのなら…情報が少ないと思うけど…。
 */
Boolean
ximClient_badProtocol (
	register Widget			gw,
	register const char*	pString)
{
	return	ximClient_writeErrorMessage (gw, -1, -1, XIM_ERROR_BadProtocol, pString) ;
}

/*
 *(関数)
 *	virtual bool	CXIMClient::setForwardEvent (XIMInputMethod* pInputMethod, CXIMInputContext* pInputContext, bool fEnable) ;
 *(機能)
 *	Client からこちらに投げて欲しい X EVENT を設定するに用いる関数。
 *	Extension がかかっているかどうかで、XIM_EXT_SET_EVENT_MASK を使うか XIM_SET_EVENT_MASK を
 *	使うかが決定される。
 */
Boolean
ximClient_setForwardEvent (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register Boolean			fEnable)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;
	register XIMPacket*			pPacket ;

#if defined (DEBUG) || 0
	fprintf (stderr, "ximClient_setForwardEvent (%p, %d, %d)\n",
			 gw,
			 XIMInputMethod_GetID (pInputMethod),
			 XIMInputContext_GetID (pInputContext)) ;
#endif
	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;

	/*	ここで forward の開始/終了処理が入る。*/
	if (XIMInputMethod_GetExtMask (pInputMethod) & XIM_EXT_SET_EVENT_MASK_MASK){
		XIMPacket_SetHeader (pPacket, XIM_EXT_SET_EVENT_MASK, 0) ;
		XIMPacket_AddCard16 (pPacket, XIMInputMethod_GetID (pInputMethod)) ;
		XIMPacket_AddCard16 (pPacket, XIMInputContext_GetID (pInputContext)) ;

		/*
		 *	filter-event-mask がかかっている Event は Client 側からは Server に処理
		 *	されたように、Server からは無かったように見える。
		 */
		XIMPacket_AddCard32 (pPacket, NoEventMask) ;
		/*
		 *	intercept-event-mask, select-event-mask を使うことで X Input Method Protocol
		 *	Client の XSelectInput する X EVENT をコントロールすることができる。
		 *	
		 *	current-event-mask := 今現在の Client の event-mask
		 *	next-event-mask    := current-event-mask & ~intercept-event-mask | select-event-mask
		 *
		 *	となる。
		 */

		/* intercept-event-mask */
		XIMPacket_AddCard32 (pPacket, NoEventMask) ;
		/* select-event-mask */
		XIMPacket_AddCard32 (pPacket, NoEventMask) ;
		/* forward-event-mask */
		XIMPacket_AddCard32 (pPacket, fEnable? (KeyPressMask | KeyReleaseMask) : NoEventMask) ;
		/* synchronous-event-mask */
#if defined (USE_ASYNC_XIM)
		XIMPacket_AddCard32 (pPacket, NoEventMask) ;
#else
		XIMPacket_AddCard32 (pPacket, fEnable? (KeyPressMask | KeyReleaseMask) : NoEventMask) ;
#endif
	} else {
		XIMPacket_SetHeader (pPacket, XIM_SET_EVENT_MASK, 0) ;
		XIMPacket_AddCard16 (pPacket, XIMInputMethod_GetID (pInputMethod)) ;
		XIMPacket_AddCard16 (pPacket, XIMInputContext_GetID (pInputContext)) ;
		/* forward-event-mask */
		XIMPacket_AddCard32 (pPacket, fEnable? (KeyPressMask | KeyReleaseMask) : NoEventMask) ;
		/* synchronous-event-mask */
#if defined (USE_ASYNC_XIM)
		XIMPacket_AddCard32 (pPacket, NoEventMask) ;
#else
		XIMPacket_AddCard32 (pPacket, fEnable? (KeyPressMask | KeyReleaseMask) : NoEventMask) ;
#endif
	}
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return	True ;
}

Boolean
ximClient_registerInputMethod (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;

	assert (gw != NULL) ;
	assert (pInputMethod != NULL) ;

	XIMInputMethod_SetNext (pInputMethod, wgThis->ximClient.m_lstInputMethod) ;
	wgThis->ximClient.m_lstInputMethod	= pInputMethod ;
	return	True ;
}

Boolean
ximClient_unregisterInputMethod (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;
	register XIMInputMethod*	pPrevNode ;
	register XIMInputMethod*	pNode ;
	register XIMInputMethod*	pNextNode ;

	pPrevNode	= NULL ;
	pNode		= wgThis->ximClient.m_lstInputMethod ;
	while (pNode != NULL) {
		pNextNode	= XIMInputMethod_GetNext (pNode) ;
		if (pNode == pInputMethod) {
			if (pPrevNode != NULL) {
				XIMInputMethod_SetNext (pPrevNode, pNextNode) ;
			} else {
				wgThis->ximClient.m_lstInputMethod	= pNextNode ;
			}
			return	True ;
		}
		pPrevNode	= pNode ;
		pNode		= pNextNode ;
	}
	return	False ;
}

XIMInputMethod*
ximClient_findInputMethod (
	register Widget		gw,
	register CARD16		wID)
{
	register XIMClientWidget		wgThis	= (XIMClientWidget) gw ;
	register XIMInputMethod*		pInputMethod ;

	pInputMethod	= wgThis->ximClient.m_lstInputMethod ;
	while (pInputMethod != NULL) {
		if (XIMInputMethod_GetID (pInputMethod) == wID)
			return	pInputMethod ;
		pInputMethod	= XIMInputMethod_GetNext (pInputMethod) ;
	}
	ximClient_badProtocol (gw, "Invalid input-method-ID") ;
	return	NULL ;
}

XIMInputContext*
ximClient_findInputContext (
	register Widget				gw,
	register XIMInputMethod*	pIM,
	register CARD16				wICID)
{
	register XIMInputContext*	pIC ;

	assert (gw  != NULL) ;
	assert (pIM != NULL) ;

	pIC	= XIMInputMethod_FindInputContext (pIM, wICID) ;
	if (pIC == NULL || !XIMInputContext_Alivep (pIC))
		ximClient_writeErrorMessage (gw, XIMInputMethod_GetID (pIM), -1, XIM_ERROR_BadProtocol, "Invalid inputcontext-id") ;
	return	pIC ;
}

void
ximClient_destroyAllInputMethods (
	register Widget		gw)
{
	register XIMClientWidget		wgThis	= (XIMClientWidget) gw ;
	register XIMInputMethod*		pInputMethod ;
	register XIMInputMethod*		pNextInputMethod ;

	pInputMethod	= wgThis->ximClient.m_lstInputMethod ;
	while (pInputMethod != NULL) {
		pNextInputMethod	= XIMInputMethod_GetNext (pInputMethod) ;
		XIMInputMethod_Destroy (pInputMethod) ;
		pInputMethod		= pNextInputMethod ;
	}
	wgThis->ximClient.m_lstInputMethod	= NULL ;
	return ;
}

Boolean
ximClient_createXEvent (
	register Widget			gw,
	register unsigned long	ulSerialNumber,
	register const xEvent*	pSrc,
	register XEvent*		pDest)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;
	register int				nType ;

	nType	= pSrc->u.u.type & 0x7f ;
	if (nType != KeyPress && nType != KeyRelease)
		return	False ;

	pDest->type				= nType ;
	pDest->xany.send_event	= ((pSrc->u.u.type & 0x80) != 0) ;
	pDest->xany.display		= XtDisplay (gw) ;
	pDest->xkey.display		= XtDisplay (gw) ;

	if (wgThis->ximClient.m_fBigEndian) {
#define	GET_BIGCARD32(ptr)	(((CARD32)*((CARD8*)(ptr)) << 24) | ((CARD32)*((CARD8*)(ptr) + 1) << 16) | ((CARD32)*((CARD8*)(ptr) + 2) << 8) | ((CARD32)*((CARD8*)(ptr) + 3) << 0))
#define	GET_BIGCARD16(ptr)	(((CARD16)*((CARD8*)(ptr)) << 8) | ((CARD16)*((CARD8*)(ptr) + 1) << 0))
		pDest->xany.serial		= (ulSerialNumber << 16) | GET_BIGCARD16 (&pSrc->u.u.sequenceNumber) ;
		pDest->xkey.root		= GET_BIGCARD32 (&pSrc->u.keyButtonPointer.root) ;
		pDest->xkey.window 		= GET_BIGCARD32 (&pSrc->u.keyButtonPointer.event) ;
		pDest->xkey.subwindow 	= GET_BIGCARD32 (&pSrc->u.keyButtonPointer.child) ;
		pDest->xkey.time 		= GET_BIGCARD32 (&pSrc->u.keyButtonPointer.time) ;
		pDest->xkey.x 			= GET_BIGCARD16 (&pSrc->u.keyButtonPointer.eventX) ;
		pDest->xkey.y 			= GET_BIGCARD16 (&pSrc->u.keyButtonPointer.eventY) ;
		pDest->xkey.x_root 		= GET_BIGCARD16 (&pSrc->u.keyButtonPointer.rootX) ;
		pDest->xkey.y_root 		= GET_BIGCARD16 (&pSrc->u.keyButtonPointer.rootY) ;
		pDest->xkey.state		= GET_BIGCARD16 (&pSrc->u.keyButtonPointer.state) ;
#undef	GET_BIGCARD32
#undef	GET_BIGCARD16
	} else {
#define	GET_LITTLECARD32(ptr)	(((CARD32)*((CARD8*)(ptr)) << 0) | ((CARD32)*((CARD8*)(ptr) + 1) << 8) | ((CARD32)*((CARD8*)(ptr) + 2) << 16) | ((CARD32)*((CARD8*)(ptr) + 3) << 24))
#define	GET_LITTLECARD16(ptr)	(((CARD16)*((CARD8*)(ptr)) << 0) | ((CARD16)*((CARD8*)(ptr) + 1) << 8))
		pDest->xany.serial		= (ulSerialNumber << 16) | GET_LITTLECARD16 (&pSrc->u.u.sequenceNumber) ;
		pDest->xkey.root		= GET_LITTLECARD32 (&pSrc->u.keyButtonPointer.root) ;
		pDest->xkey.window 		= GET_LITTLECARD32 (&pSrc->u.keyButtonPointer.event) ;
		pDest->xkey.subwindow 	= GET_LITTLECARD32 (&pSrc->u.keyButtonPointer.child) ;
		pDest->xkey.time 		= GET_LITTLECARD32 (&pSrc->u.keyButtonPointer.time) ;
		pDest->xkey.x 			= GET_LITTLECARD16 (&pSrc->u.keyButtonPointer.eventX) ;
		pDest->xkey.y 			= GET_LITTLECARD16 (&pSrc->u.keyButtonPointer.eventY) ;
		pDest->xkey.x_root 		= GET_LITTLECARD16 (&pSrc->u.keyButtonPointer.rootX) ;
		pDest->xkey.y_root 		= GET_LITTLECARD16 (&pSrc->u.keyButtonPointer.rootY) ;
		pDest->xkey.state		= GET_LITTLECARD16 (&pSrc->u.keyButtonPointer.state) ;
#undef	GET_LITTLECARD32
#undef	GET_LITTLECARD16
	}
	pDest->xkey.same_screen	= pSrc->u.keyButtonPointer.sameScreen ;
	pDest->xkey.keycode 	= pSrc->u.u.detail ;
	return	True ;
}

/* //////////////////////////////////////////////////////////////////////
 */
/*
 *(関数)
 *	virtual bool	getImValueQueryInputStyle (
 *		XIMInputMethod* pInputMethod,
 *		CXIMInputContext* pInputContext,
 *		int nAttributeID,
 *		XIMPacket* pPacket
 *	) ;
 *(機能)
 *	InputMethod がサポートしている XIMStyle を得、パケットに詰めて
 *	返す。
 *(返り値)
 *	true	無事に値がとれた場合
 *	false	エラーが発生した場合
 *(備考)
 *	恐らくエラーを返すことはなかろう。
 */
Boolean
ximClient_getImValueQueryInputStyle (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod, 
	register XIMInputContext* 	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				nMode,
	register XIMPacket*			pPacket)
{
	const XIMInputStyle*		pQueryInputStyle ;
	register int				nInputStyle ;
	register int				nValueLength ;

	/*	InputMethod からサポートしている Style を得る。*/
	nInputStyle		= XIMInputMethod_GetQueryInputStyle (pInputMethod, &pQueryInputStyle) ;
	/*	Attribute-ID をパケットに詰める。*/
	XIMPacket_AddCard16 (pPacket, (CARD16)XIM_ATTRIBUTEID_QUERYINPUTSTYLE) ;
	if (pQueryInputStyle != NULL && nInputStyle > 0){
		//	XIMStyles をパケットに詰める。
		nValueLength	= (nInputStyle * sizeof (CARD32) + sizeof (CARD16) * 2) / sizeof (CARD8) ;
		XIMPacket_AddCard16 (pPacket, nValueLength) ;
		XIMPacket_AddCard16 (pPacket, nInputStyle) ;
		XIMPacket_AddCard16 (pPacket, 0 /* unused */) ;
		while (nInputStyle > 0){
			XIMPacket_AddCard32 (pPacket, pQueryInputStyle->m_uXIMStyle) ;
			pQueryInputStyle	++ ;
			nInputStyle			-- ;
		}
	} else {
		nValueLength	= 0 ;
	}
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

/* ///////////////////////////////////////////////////////////////////////
 */

/*
 *
 */
Boolean
ximClient_getIcValues (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod, 
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnLength,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register XIMAttribute*		pAttribute ;
	register int				nMethodID, nContextID ;
	register int				nAttributeID ;
	int							nLength ;

	nLength		= *pnLength ;
	nMethodID	= XIMInputMethod_GetID (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;
	while (nLength > 0){
		if (nLength < (int)(sizeof (CARD16) / sizeof (CARD8))){
			ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "Lack of data.") ;
			return	False ;
		}
		nAttributeID	= XIMData_GetCard16 (pData) ;
		nLength			-= sizeof (CARD16) / sizeof (CARD8) ;
		if (nAttributeID < 0 || nAttributeID >= MAX_NUMBER_OF_XIC_ATTRIBUTEID){
			ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "Invalid attribute-ID.") ;
			return	False ;
		}

		/*(注意)
		 *	Separator を発見した場合には親のリストへと戻る。
		 */
		if (nAttributeID == XIC_ATTRIBUTEID_SEPARATOR){
			if (iMode & (PREEDITATTRIBUTES_MASK | STATUSATTRIBUTES_MASK))
				break ;
			ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "Unexpected separator of nested list.") ;
			return	False ;
		}
		pAttribute		= &srSupportedInputContextAttributes [nAttributeID] ;
		if (pAttribute->m_pGetter == NULL){
			ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "Operation: GetIcValue is not permitted.") ;
			return	False ;
		}

		/*(注意)
		 *	NestedList の長さは設定されない。それ込みの長さが ListOfXICATTR として
		 *	与えられている。
		 */
		if (!(pAttribute->m_pGetter)(gw, pInputMethod, pInputContext, pData, &nLength, iMode, pPacket))
			return	False ;
	}
	*pnLength	= nLength ;
	return	True ;
}

/*
 *(関数)
 *	virtual bool	getIcValueInputStyle (
 *		XIMInputMethod* pInputMethod,
 *		CXIMInputContext* pInputContext,
 *		int nAttributeID,
 *		XIMPacket* pPacket
 *	) ;
 *(機能)
 *	InputContext の InputStyle をパケットに詰めて返す。
 *(返り値)
 *	true	無事に値がとれた場合
 *	false	エラーが発生した場合
 *(備考)
 *	恐らくエラーを返すことはなかろう。
 *	SetValue なら BadValue とか考えられるのだけれども。
 */
Boolean
ximClient_getIcValueInputStyle (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register XIMStyle	imstyle ;
	register int		nValueLength ;

	imstyle	= XIMInputContext_GetInputStyle (pInputContext) ;
	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_INPUTSTYLE) ;
	nValueLength	= (int)(sizeof (CARD32) / sizeof (CARD8)) ;
	XIMPacket_AddCard16 (pPacket, nValueLength) ;
	XIMPacket_AddCard32 (pPacket, (CARD32)imstyle) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

/*
 *(関数)
 *	virtual bool	getIcValueClientWindow (
 *		XIMInputMethod* pInputMethod,
 *		CXIMInputContext* pInputContext,
 *		int nAttributeID,
 *		XIMPacket* pPacket
 *	) ;
 *(機能)
 *	InputContext が割り当てられている Client Window の Window ID (?)
 *	をパケットに詰めて返す。
 *(返り値)
 *	true	無事に値がとれた場合
 *	false	エラーが発生した場合
 *(備考)
 *	恐らくエラーを返すことはなかろう。
 *	SetValue なら BadValue とか考えられるのだけれども。
 */
Boolean
ximClient_getIcValueClientWindow (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register Window		winClient ;
	register int		nValueLength ;

	/*	Attribute-ID をパケットに詰める。*/
	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_CLIENTWINDOW) ;
	winClient	= XIMInputContext_GetClientWindow (pInputContext) ;
	nValueLength	= (int)(sizeof (CARD32) / sizeof (CARD8)) ;
	XIMPacket_AddCard16 (pPacket, nValueLength) ;
	XIMPacket_AddCard32 (pPacket, (CARD32)winClient) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

/*
 *(関数)
 *	virtual bool	getIcValueFocusWindow (
 *		XIMInputMethod* pInputMethod,
 *		CXIMInputContext* pInputContext,
 *		int nAttributeID,
 *		XIMPacket* pPacket
 *	) ;
 *(機能)
 *	InputContext が割り当てられている Focus Window の Window ID (?)
 *	をパケットに詰めて返す。
 *(返り値)
 *	true	無事に値がとれた場合
 *	false	エラーが発生した場合
 *(備考)
 *	恐らくエラーを返すことはなかろう。
 *	SetValue なら BadValue とか考えられるのだけれども。
 */
Boolean
ximClient_getIcValueFocusWindow (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register Window		winFocus ;
	register int		nValueLength ;
	/*	Attribute-ID をパケットに詰める。*/
	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_FOCUSWINDOW) ;
	winFocus		= XIMInputContext_GetFocusWindow (pInputContext) ;
	nValueLength	= (int)(sizeof (CARD32) / sizeof (CARD8)) ;
	XIMPacket_AddCard16 (pPacket, nValueLength) ;
	XIMPacket_AddCard32 (pPacket, (CARD32)winFocus) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

/*
 *(関数)
 *	virtual bool	getIcValueFilterEvents (
 *		XIMInputMethod* pInputMethod,
 *		CXIMInputContext* pInputContext,
 *		CXIMData* pData,
 *		int& nItems,
 *		int iMode,
 *		XIMPacket* pPacket
 *	) ;
 *(機能)
 *	InputContext の filter_events を返す…。filter_events とは何をする
 *	もので初期値はどうあるべきなのだろうか？
 *(返り値)
 *	true	無事に値がとれた場合
 *	false	エラーが発生した場合
 *(備考)
 *	恐らくエラーを返すことはなかろう。
 *	SetValue なら BadValue とか考えられるのだけれども。
 */
Boolean
ximClient_getIcValueFilterEvents (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register CARD32		dwFilterEvents ;
	register int		nValueLength ;

	/*	Attribute-ID をパケットに詰める。*/
	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_FILTEREVENTS) ;
	dwFilterEvents	= XIMInputContext_GetFilterEvents (pInputContext) ;
	nValueLength		= (int)(sizeof (CARD32) / sizeof (CARD8)) ;
	XIMPacket_AddCard16 (pPacket, nValueLength) ;
	XIMPacket_AddCard32 (pPacket, (CARD32)dwFilterEvents) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

Boolean
ximClient_getIcValueResetState (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register XIMResetState	ulState ;
	register int			nValueLength ;

	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_RESETSTATE) ;
	ulState			= XIMInputContext_GetResetState (pInputContext) ;
	nValueLength	= (int)(sizeof (CARD32) / sizeof (CARD8)) ;
	XIMPacket_AddCard16 (pPacket, nValueLength) ;
	XIMPacket_AddCard32 (pPacket, (CARD32)ulState) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

/*
 *
 */
Boolean
ximClient_getIcValuePreeditState (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register XIMResetState	ulState ;
	register int		nValueLength ;

	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_PREEDITSTATE) ;
	ulState				= XIMInputContext_GetPreeditState (pInputContext) ;
	nValueLength		= (int)(sizeof (CARD32) / sizeof (CARD8)) ;
	XIMPacket_AddCard16 (pPacket, nValueLength) ;
	XIMPacket_AddCard32 (pPacket, (CARD32)ulState) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

/*
 *
 */
Boolean
ximClient_getIcValuePreeditAttributes (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register int	nMethodID, nContextID ;
	register int	nIndexAttributeLength ;
	register int	nValueLength ;
	int				nItems ;

	nItems		= *pnItems ;
	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;

	/*	Nested list が更に Nest されているようなことはありえない。
	 *	…現状では、と付け加えておきましょう。(^^;;
	 */
	if (iMode & (PREEDITATTRIBUTES_MASK | STATUSATTRIBUTES_MASK)){
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "Cannot nest nested list") ;
		return	False ;
	}
	/*	Attribute-ID をパケットに詰める。*/
	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_PREEDITATTRIBUTES);
	nIndexAttributeLength	= XIMPacket_GetDataSize (pPacket) ;
	XIMPacket_AddCard16 (pPacket, 0 /* dummy */) ;
	/*	XNPreeditAttributes に属する Attribute だという指定があった。*/
	if (!ximClient_getIcValues (gw, pInputMethod, pInputContext, pData, &nItems, iMode | PREEDITATTRIBUTES_MASK, pPacket)) {
		*pnItems	= nItems ;
		return	False ;
	}
	/*	XNPreeditAttributes は XNSeparatorofNestedList で閉じる。*/
	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_SEPARATOR) ;
	XIMPacket_AddCard16 (pPacket, strlen (XNSeparatorofNestedList)) ;
	XIMPacket_AddString8 (pPacket, XNSeparatorofNestedList, strlen (XNSeparatorofNestedList)) ;
	/*	このひとまとまりで XNPreeditAttributes の Value となる。*/
	nValueLength	= XIMPacket_GetDataSize (pPacket) - nIndexAttributeLength - 2 ;
	XIMPacket_SetCard16 (pPacket, nIndexAttributeLength, (CARD16)nValueLength) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	*pnItems		= nItems ;
	return	True ;
}

/*
 *
 */
Boolean
ximClient_getIcValueStatusAttributes (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register int	nMethodID, nContextID ;
	register int	nIndexAttributeLength ;
	register int	nValueLength ;
	int				nItems ;

	nItems		= *pnItems ;
	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;

	/*	Nested list が更に Nest されているようなことはありえない。
	 *	…現状では、と付け加えておきましょう。(^^;;
	 */
	if (iMode & (PREEDITATTRIBUTES_MASK | STATUSATTRIBUTES_MASK)){
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "Cannot nest nested list") ;
		return	False ;
	}
	/*	Attribute-ID をパケットに詰める。*/
	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_STATUSATTRIBUTES);
	nIndexAttributeLength	= XIMPacket_GetDataSize (pPacket) ;
	XIMPacket_AddCard16 (pPacket, 0 /* dummy */) ;
	/*	XNPreeditAttributes に属する Attribute だという指定があった。*/
	if (!ximClient_getIcValues (gw, pInputMethod, pInputContext, pData, &nItems, iMode | STATUSATTRIBUTES_MASK, pPacket)) {
		*pnItems	= nItems ;
		return	False ;
	}
	/*	XNPreeditAttributes は XNSeparatorofNestedList で閉じる。*/
	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_SEPARATOR) ;
	XIMPacket_AddCard16 (pPacket, strlen (XNSeparatorofNestedList)) ;
	XIMPacket_AddString8 (pPacket, XNSeparatorofNestedList, strlen (XNSeparatorofNestedList)) ;
	/*	このひとまとまりで XNPreeditAttributes の Value となる。*/
	nValueLength	= XIMPacket_GetDataSize (pPacket) - nIndexAttributeLength - 2 ;
	XIMPacket_SetCard16 (pPacket, nIndexAttributeLength, (CARD16)nValueLength) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	*pnItems	= nItems ;
	return	True ;
}

Boolean
ximClient_getIcValueArea (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register int	nMethodID, nContextID ;
	register int	nValueLength ;
	XRectangle		area ;

	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;
	if (iMode & PREEDITATTRIBUTES_MASK){
		if (!XIMInputContext_GetPreeditArea (pInputContext, &area)){
			ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "No PreeditArea.") ;
			return	False ;
		}
	} else if (iMode & STATUSATTRIBUTES_MASK){
		if (!XIMInputContext_GetStatusArea (pInputContext, &area)){
			ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "No StatusArea.") ;
			return	False ;
		}
	} else {
		/*	PreeditAttribute なのか StatusAttribute なのかの判別ができない。*/
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_AREA) ;
	nValueLength	= (sizeof (INT16) + sizeof (INT16) + sizeof (CARD16) + sizeof (CARD16)) / sizeof (CARD8) ;
	XIMPacket_AddCard16 (pPacket, nValueLength) ;
	XIMPacket_AddCard16 (pPacket, area.x) ;
	XIMPacket_AddCard16 (pPacket, area.y) ;
	XIMPacket_AddCard16 (pPacket, area.width) ;
	XIMPacket_AddCard16 (pPacket, area.height) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

Boolean
ximClient_getIcValueAreaNeeded (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register int	nMethodID, nContextID ;
	register int	nValueLength ;
	XRectangle		area ;

	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;
	if (iMode & PREEDITATTRIBUTES_MASK){
		if (!XIMInputContext_GetPreeditAreaNeeded (pInputContext, &area)){
			ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "No need for PreeditArea.") ;
			return	False ;
		}
	} else if (iMode & STATUSATTRIBUTES_MASK){
		if (!XIMInputContext_GetStatusAreaNeeded (pInputContext, &area)){
			ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "No need for StatusArea.") ;
			return	False ;
		}
	} else {
		/*	PreeditAttribute なのか StatusAttribute なのかの判別ができない。*/
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_AREANEEDED) ;
	nValueLength	= (sizeof (INT16) + sizeof (INT16) + sizeof (CARD16) + sizeof (CARD16)) / sizeof (CARD8) ;
	XIMPacket_AddCard16 (pPacket, nValueLength) ;
	XIMPacket_AddCard16 (pPacket, area.x) ;
	XIMPacket_AddCard16 (pPacket, area.y) ;
	XIMPacket_AddCard16 (pPacket, area.width) ;
	XIMPacket_AddCard16 (pPacket, area.height) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

Boolean
ximClient_getIcValueSpotLocation (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register int	nMethodID, nContextID ;
	register int	nValueLength ;
	XPoint			pos ;

	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;

	if (iMode & PREEDITATTRIBUTES_MASK){
		XIMInputContext_GetSpotLocation (pInputContext, &pos) ;
	} else if (iMode & STATUSATTRIBUTES_MASK){
		/*	Status Attribute には SpotLocation はない。*/
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "No need for StatusArea.") ;
		return	False ;
	} else {
		/*	PreeditAttribute なのか StatusAttribute なのかの判別ができない。*/
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
  }

	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_SPOTLOCATION) ;
	nValueLength	= (sizeof (INT16) + sizeof (INT16)) / sizeof (CARD8) ;
	XIMPacket_AddCard16 (pPacket, nValueLength) ;
	XIMPacket_AddCard16 (pPacket, pos.x) ;
	XIMPacket_AddCard16 (pPacket, pos.y) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

Boolean
ximClient_getIcValueColormap (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register Colormap	colormap ;
	register int		nValueLength ;

	if (iMode & PREEDITATTRIBUTES_MASK){
		colormap	= XIMInputContext_GetPreeditColormap (pInputContext) ;
	} else if (iMode & STATUSATTRIBUTES_MASK){
		colormap	= XIMInputContext_GetStatusColormap (pInputContext) ;
	} else {
		register int	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
		register int	nContextID	= XIMInputContext_GetID (pInputContext) ;

		/*	PreeditAttribute なのか StatusAttribute なのかの判別ができない。*/
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_COLORMAP) ;
	nValueLength	= (sizeof (CARD32)) / sizeof (CARD8) ;
	XIMPacket_AddCard16 (pPacket, nValueLength) ;
	XIMPacket_AddCard32 (pPacket, (CARD32)colormap) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

Boolean
ximClient_getIcValueStdColormap (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register Atom		colormap ;
	register int		nValueLength ;

	if (iMode & PREEDITATTRIBUTES_MASK){
		colormap	= XIMInputContext_GetPreeditStdColormap (pInputContext) ;
	} else if (iMode & STATUSATTRIBUTES_MASK){
		colormap	= XIMInputContext_GetStatusStdColormap (pInputContext) ;
	} else {
		register int	nMethodID, nContextID ;

		nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
		nContextID	= XIMInputContext_GetID (pInputContext) ;

		/*	PreeditAttribute なのか StatusAttribute なのかの判別ができない。*/
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_STDCOLORMAP) ;
	nValueLength	= (sizeof (CARD32)) / sizeof (CARD8) ;
	XIMPacket_AddCard16 (pPacket, nValueLength) ;
	XIMPacket_AddCard32 (pPacket, (CARD32)colormap) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

Boolean
ximClient_getIcValueForeground (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register unsigned long	foreground ;
	register int			nValueLength ;

	if (iMode & PREEDITATTRIBUTES_MASK){
		foreground	= XIMInputContext_GetPreeditForeground (pInputContext) ;
	} else if (iMode & STATUSATTRIBUTES_MASK){
		foreground	= XIMInputContext_GetStatusForeground (pInputContext) ;
	} else {
		register int	nMethodID, nContextID ;

		nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
		nContextID	= XIMInputContext_GetID (pInputContext) ;
	
		/*	PreeditAttribute なのか StatusAttribute なのかの判別ができない。*/
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_FOREGROUND) ;
	nValueLength	= (sizeof (CARD32)) / sizeof (CARD8) ;
	XIMPacket_AddCard16 (pPacket, nValueLength) ;
	XIMPacket_AddCard32 (pPacket, (CARD32)foreground) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

Boolean
ximClient_getIcValueBackground (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register unsigned long	background ;
	register int			nValueLength ;

	if (iMode & PREEDITATTRIBUTES_MASK){
		background	= XIMInputContext_GetPreeditBackground (pInputContext) ;
	} else if (iMode & STATUSATTRIBUTES_MASK){
		background	= XIMInputContext_GetStatusBackground (pInputContext) ;
	} else {
		register int	nMethodID, nContextID ;

		nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
		nContextID	= XIMInputContext_GetID (pInputContext) ;

		/*	PreeditAttribute なのか StatusAttribute なのかの判別ができない。*/
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_BACKGROUND) ;
	nValueLength	= (sizeof (CARD32)) / sizeof (CARD8) ;
	XIMPacket_AddCard16 (pPacket, nValueLength) ;
	XIMPacket_AddCard32 (pPacket, (CARD32)background) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

Boolean
ximClient_getIcValueBackgroundPixmap (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register Pixmap	pixmap ;
	register int	nValueLength ;

	if (iMode & PREEDITATTRIBUTES_MASK){
		pixmap	= XIMInputContext_GetPreeditBackgroundPixmap (pInputContext) ;
	} else if (iMode & STATUSATTRIBUTES_MASK){
		pixmap	= XIMInputContext_GetStatusBackgroundPixmap (pInputContext) ;
	} else {
		register int	nMethodID, nContextID ;

		nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
		nContextID	= XIMInputContext_GetID (pInputContext) ;

		/*	PreeditAttribute なのか StatusAttribute なのかの判別ができない。*/
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_BACKGROUNDPIXMAP) ;
	nValueLength	= (sizeof (CARD32)) / sizeof (CARD8) ;
	XIMPacket_AddCard16 (pPacket, nValueLength) ;
	XIMPacket_AddCard32 (pPacket, (CARD32)pixmap) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

Boolean
ximClient_getIcValueFontSet (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register const char*	pFontSet ;
	register int			nBaseNameLength ;
	register int			nIndexValueLength ;
	register int			nValueLength ;

	if (iMode & PREEDITATTRIBUTES_MASK){
		/*	うーむ。これは要注意だ…。Font 名を Fake する必要が時としてあるかも。*/
		pFontSet	= XIMInputContext_GetPreeditFontSet (pInputContext) ;
	} else if (iMode & STATUSATTRIBUTES_MASK){
		pFontSet	= XIMInputContext_GetStatusFontSet (pInputContext) ;
	} else {
		register int	nMethodID, nContextID ;

		nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
		nContextID	= XIMInputContext_GetID (pInputContext) ;

		/*	PreeditAttribute なのか StatusAttribute なのかの判別ができない。*/
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_FONTSET) ;
	nIndexValueLength	= XIMPacket_GetDataSize (pPacket) ;
	XIMPacket_AddCard16 (pPacket, 0 /* dummy */) ;
	/*	値は、TYPE_XFONTSET */
	nBaseNameLength	= strlen (pFontSet) ;
	XIMPacket_AddCard16 (pPacket, nBaseNameLength) ;
	XIMPacket_AddString8 (pPacket, pFontSet, nBaseNameLength) ;
	XIMPacket_AddPad (pPacket, nBaseNameLength) ;
	nValueLength		= XIMPacket_GetDataSize (pPacket) - nIndexValueLength - 2 ;
	XIMPacket_SetCard16 (pPacket, nIndexValueLength, nValueLength) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

Boolean
ximClient_getIcValueLineSpacing (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register int	nLineSpacing ;
	register int	nValueLength ;

	if (iMode & PREEDITATTRIBUTES_MASK){
		nLineSpacing	= XIMInputContext_GetPreeditLineSpacing (pInputContext) ;
	} else if (iMode & STATUSATTRIBUTES_MASK){
		nLineSpacing	= XIMInputContext_GetStatusLineSpacing (pInputContext) ;
	} else {
		register int	nMethodID, nContextID ;

		nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
		nContextID	= XIMInputContext_GetID (pInputContext) ;

		/*	PreeditAttribute なのか StatusAttribute なのかの判別ができない。*/
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}

	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_LINESPACE) ;
	nValueLength	= sizeof (CARD16) / sizeof (CARD8) ;
	XIMPacket_AddCard16 (pPacket, nValueLength) ;
	XIMPacket_AddCard32 (pPacket, (CARD32)nLineSpacing) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

Boolean
ximClient_getIcValueCursor (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int*				pnItems,
	register int				iMode,
	register XIMPacket*			pPacket)
{
	register Cursor	cursor ;
	register int	nValueLength ;

	if (iMode & PREEDITATTRIBUTES_MASK){
		cursor	= XIMInputContext_GetPreeditCursor (pInputContext) ;
	} else if (iMode & STATUSATTRIBUTES_MASK){
		cursor	= XIMInputContext_GetStatusCursor (pInputContext) ;
	} else {
		register int	nMethodID, nContextID ;

		nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
		nContextID	= XIMInputContext_GetID (pInputContext) ;

		/*	PreeditAttribute なのか StatusAttribute なのかの判別ができない。*/
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	XIMPacket_AddCard16 (pPacket, (CARD16)XIC_ATTRIBUTEID_CURSOR) ;
	nValueLength	= sizeof (CARD32) / sizeof (CARD8) ;
	XIMPacket_AddCard16 (pPacket, nValueLength) ;
	XIMPacket_AddCard32 (pPacket, (CARD32)cursor) ;
	XIMPacket_AddPad (pPacket, nValueLength) ;
	return	True ;
}

Boolean
ximClient_setIcValues (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	register XIMClientWidget	wgThis		= (XIMClientWidget) gw ;
	register XIMAttribute*	pAttribute ;
	register int			nAttributeID ;
	register int			nValueLength ;
	register int			nMethodID, nContextID ;
	register const CARD8*	pHead ;
	register Boolean		fBigEndian ;

	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;
	fBigEndian	= wgThis->ximClient.m_fBigEndian ;

	while (nDataLength >= (int)((sizeof (CARD16) + sizeof (CARD16)) / sizeof (CARD8))){
		nAttributeID	= XIMData_GetCard16 (pData) ;
		nValueLength	= XIMData_GetCard16 (pData) ;
		nDataLength		-= (sizeof (CARD16) + sizeof (CARD16)) / sizeof (CARD8) ;
		/*	IC-attribute として正しい ID が送られているかどうかをチェックする。*/
		if (nAttributeID < 0 || nAttributeID >= MAX_NUMBER_OF_XIC_ATTRIBUTEID){
			ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "Invalid attribute-ID.") ;
			return	False ;
		}
		pHead		= XIMData_GetHead (pData) ;
		/*	設定すべきデータが不足している場合をチェックする。*/
		if (nDataLength < nValueLength){
			ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "Lack of value.") ;
			return	False ;
		}
		pAttribute		= &srSupportedInputContextAttributes [nAttributeID] ;

		/*
		 *	現時点で設定可能であるかを判定する…。
		 *	何時設定可能かというのも…判断に困るところはあるが。
		 */
		if (( (iMode & XIC_CREATE_MASK) && !pAttribute->m_fEnableCreate) ||
			(!(iMode & XIC_CREATE_MASK) && !pAttribute->m_fEnableNormal) ||
			pAttribute->m_pSetter == NULL){
			ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "Operation not permitted.") ;
			return	False ;
		}
#if defined (DEBUG) || 0
		fprintf (stderr, "set-ic-values: attribute = %d\n", nAttributeID) ;
#endif
		/*	値の設定…*/
		if (!((pAttribute->m_pSetter)(gw, pInputMethod, pInputContext, pData, nValueLength, iMode)))
			return	False ;
		XIMData_Initialize (pData, pHead + nValueLength + IMPAD (nValueLength), fBigEndian) ;
		nDataLength		-= (nValueLength + IMPAD (nValueLength)) ;
	}
	return	True ;
}

Boolean
ximClient_setIcValueInputStyle (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	register int		nMethodID, nContextID ;
	register XIMStyle	imstyle ;

	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;

	if (nDataLength < GET_VALUE_LENGTH (CARD32)){
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadStyle, "Bad input style") ;
		return	False ;
	}
	imstyle	= (XIMStyle) XIMData_GetCard32 (pData) ;
	if (!XIMInputContext_SetInputStyle (pInputContext, imstyle)){
		/*	失敗？？ 多分、ここには来ないと思うけど…。*/
	}

	if ((imstyle & XIMPreeditMask) == XIMPreeditArea || 
		(imstyle & XIMStatusMask)  == XIMStatusArea) {
		/*	Geometry を Query する。Focus Window がない可能性もあるので
		 *	しかけるタイミングは InputStyle を選んだ直後だろう。*/
		XIMClient_WriteXimGeometry (gw, nMethodID, nContextID) ;
	}
#if defined (DEBUG)
	fprintf (stderr, "InputStyle <- 0x%lx\n", imstyle) ;
#endif
	return	True ;
}

Boolean
ximClient_setIcValueClientWindow (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	register int			nMethodID, nContextID ;
	register Window			winClient ;

	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;

	if (nDataLength < GET_VALUE_LENGTH (CARD32)){
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadClientWindow, "Bad client window") ;
		return	False ;
	}

	winClient	= (Window) XIMData_GetCard32 (pData) ;
	if (!XIMInputContext_SetClientWindow (pInputContext, winClient)){
		//	一度しか設定できない属性なので２度３度設定しようとするとエラーになる。
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "Client window only once") ;
		return	False ;
	}
	return	True ;
}

Boolean
ximClient_setIcValueFocusWindow (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	register Window	winFocus ;

	if (nDataLength < GET_VALUE_LENGTH (CARD32)){
		register int			nMethodID, nContextID ;

		nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
		nContextID	= XIMInputContext_GetID (pInputContext) ;
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadFocusWindow, "Bad focus window") ;
		return	False ;
	}
	winFocus	= (Window) XIMData_GetCard32 (pData) ;
	if (!XIMInputContext_SetFocusWindow (pInputContext, winFocus)){
		//	失敗？？
	}
	return	True ;
}

Boolean
ximClient_setIcValueResetState (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	register XIMResetState	ulState ;
	register Boolean		fSuccess ;

	fSuccess	= False ;
	if (nDataLength >= GET_VALUE_LENGTH (XIMResetState)){
		ulState		= (XIMResetState) XIMData_GetCard32 (pData) ;
		fSuccess	= XIMInputContext_SetResetState (pInputContext, ulState) ;
	} 
	if (!fSuccess) {
		register int	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
		register int	nContextID	= XIMInputContext_GetID (pInputContext) ;

		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "Bad reset state") ;
	}
	return	fSuccess ;
}

Boolean
ximClient_setIcValuePreeditState (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	register XIMPreeditState	ulState ;
	register Boolean			fSuccess ;

	fSuccess	= False ;
	if (nDataLength >= GET_VALUE_LENGTH (XIMPreeditState)){
		ulState		= (XIMResetState) XIMData_GetCard32 (pData) ;
		fSuccess	= XIMInputContext_SetPreeditState (pInputContext, ulState) ;
	} 
	if (!fSuccess) {
		register int	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
		register int	nContextID	= XIMInputContext_GetID (pInputContext) ;

		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "Bad preedit state") ;
	}
	return	fSuccess ;
}

Boolean
ximClient_setIcValuePreeditAttributes (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	/*
	 *	XNPreeditAttributes の場合には、その XICATTRIBUTE の value が
	 *	XICATTRIBUTE の List になっている。
	 *	List の大きさは XNPreeditAttributes の value length で与えられる。
	 */
	return	ximClient_setIcValues (gw, pInputMethod, pInputContext, pData, nDataLength, iMode | PREEDITATTRIBUTES_MASK) ;
}

Boolean
ximClient_setIcValueStatusAttributes (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	/*
	 *	XNStatusAttributes の場合には、その XICATTRIBUTE の value が
	 *	XICATTRIBUTE の List になっている。
	 *	List の大きさは XNStatusAttributes の value length で与えられる。
	 */
	return	ximClient_setIcValues (gw, pInputMethod, pInputContext, pData, nDataLength, iMode | STATUSATTRIBUTES_MASK) ;
}

Boolean
ximClient_setIcValueArea (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	register int			nMethodID, nContextID ;
	XRectangle				rect ;

	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;

	if (nDataLength < (GET_VALUE_LENGTH (CARD16) * 4)){
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadArea, "Bad area") ;
		return	False ;
	}

	rect.x	= (INT16)XIMData_GetCard16 (pData) ;
	rect.y	= (INT16)XIMData_GetCard16 (pData) ;
	rect.width	= (CARD16)XIMData_GetCard16 (pData) ;
	rect.height	= (CARD16)XIMData_GetCard16 (pData) ;
	if (iMode & PREEDITATTRIBUTES_MASK){
		if (!XIMInputContext_SetPreeditArea (pInputContext, &rect)){
			ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadArea, "Bad area") ;
			return	False ;
		}
	} else if (iMode & STATUSATTRIBUTES_MASK){
		if (!XIMInputContext_SetStatusArea (pInputContext, &rect)){
			ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadArea, "Bad area") ;
			return	False ;
		}
	} else {
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	return	True ;
}

Boolean
ximClient_setIcValueAreaNeeded (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	register int		nMethodID, nContextID ;
	XRectangle			rect ;

	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;

	if (nDataLength < (GET_VALUE_LENGTH (CARD16) * 4)){
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadArea, "Bad area needed") ;
		return	False ;
	}

	rect.x	= (INT16)XIMData_GetCard16 (pData) ;
	rect.y	= (INT16)XIMData_GetCard16 (pData) ;
	rect.width	= (CARD16)XIMData_GetCard16 (pData) ;
	rect.height	= (CARD16)XIMData_GetCard16 (pData) ;
	if (iMode & PREEDITATTRIBUTES_MASK){
		if (!XIMInputContext_SetPreeditAreaNeeded (pInputContext, &rect)){
			return	False ;
		}
	} else if (iMode & STATUSATTRIBUTES_MASK){
		if (!XIMInputContext_SetStatusAreaNeeded (pInputContext, &rect)){
			return	False ;
		}
	} else {
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	return	True ;
}

Boolean
ximClient_setIcValueSpotLocation (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	register int		nMethodID, nContextID ;
	XPoint				pos ;

	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;

	if (nDataLength < (GET_VALUE_LENGTH (CARD16) + GET_VALUE_LENGTH (CARD16))){
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadSpotLocation, "Bad spot location") ;
		return	False ;
	}

	pos.x	= (INT16)XIMData_GetCard16 (pData) ;
	pos.y	= (INT16)XIMData_GetCard16 (pData) ;
	if (iMode & PREEDITATTRIBUTES_MASK){
		if (!XIMInputContext_SetSpotLocation (pInputContext, &pos)){
			return	False ;
		}
	} else if (iMode & STATUSATTRIBUTES_MASK){
		/*
		 *	StatusAttribute には SpotLocation はない。
		 *	設定しようとすれば、それはエラーとなる。
		 */
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "StatusAttribute doesn't have attribute: SpotLocation") ;
		return	False ;
	} else {
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	return	True ;
}

Boolean
ximClient_setIcValueColormap (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	register int		nMethodID, nContextID ;
	register Colormap	colormap ;

	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;

	if (nDataLength < GET_VALUE_LENGTH (CARD32)){
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadColormap, "Bad colormap") ;
		return	False ;
	}

	colormap	= (Colormap) XIMData_GetCard32 (pData) ;
	if (iMode & PREEDITATTRIBUTES_MASK){
		if (!XIMInputContext_SetPreeditColormap (pInputContext, colormap)){
			return	False ;
		}
	} else if (iMode & STATUSATTRIBUTES_MASK){
		if (!XIMInputContext_SetStatusColormap (pInputContext, colormap)){
			return	False ;
		}
	} else {
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	return	True ;
}

Boolean
ximClient_setIcValueStdColormap (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	register int			nMethodID, nContextID ;
	register Colormap	colormap ;

	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;

	if (nDataLength < GET_VALUE_LENGTH (CARD32)){
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadColormap, "Bad standard colormap") ;
		return	False ;
	}

	colormap	= (Colormap) XIMData_GetCard32 (pData) ;
	if (iMode & PREEDITATTRIBUTES_MASK){
		if (!XIMInputContext_SetPreeditStdColormap (pInputContext, colormap)){
			return	False ;
		}
	} else if (iMode & STATUSATTRIBUTES_MASK){
		if (!XIMInputContext_SetStatusStdColormap (pInputContext, colormap)){
			return	False ;
		}
	} else {
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	return	True ;
}

Boolean
ximClient_setIcValueForeground (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	register int			nMethodID, nContextID ;
	register unsigned long	ulForeground ;

	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;

	if (nDataLength < GET_VALUE_LENGTH (CARD32)){
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadPixel, "Bad pixel") ;
		return	False ;
	}
	ulForeground	= (unsigned long) XIMData_GetCard32 (pData) ;
	if (iMode & PREEDITATTRIBUTES_MASK){
		if (!XIMInputContext_SetPreeditForeground (pInputContext, ulForeground)){
			return	False ;
		}
	} else if (iMode & STATUSATTRIBUTES_MASK){
		if (!XIMInputContext_SetStatusForeground (pInputContext, ulForeground)){
			return	False ;
		}
	} else {
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	return	True ;
}

Boolean
ximClient_setIcValueBackground (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	register int			nMethodID, nContextID ;
	register unsigned long	ulBackground ;

	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;

	if (nDataLength < GET_VALUE_LENGTH (CARD32)){
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadPixel, "Bad pixel") ;
		return	False ;
	}

	ulBackground	= (unsigned long) XIMData_GetCard32 (pData) ;
	if (iMode & PREEDITATTRIBUTES_MASK){
		if (!XIMInputContext_SetPreeditBackground (pInputContext, ulBackground)){
			return	False ;
		}
	} else if (iMode & STATUSATTRIBUTES_MASK){
		if (!XIMInputContext_SetStatusBackground (pInputContext, ulBackground)){
			return	False ;
		}
	} else {
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	return	True ;
}

Boolean
ximClient_setIcValueBackgroundPixmap (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	register int			nMethodID, nContextID ;
	register Pixmap			pixmap ;

	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;

	if (nDataLength < GET_VALUE_LENGTH (CARD32)){
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadPixmap, "Bad pixmap") ;
		return	False ;
	}

	pixmap	= (Pixmap)XIMData_GetCard32 (pData) ;
	if (iMode & PREEDITATTRIBUTES_MASK){
		if (!XIMInputContext_SetPreeditBackgroundPixmap (pInputContext, pixmap)){
			return	False ;
		}
	} else if (iMode & STATUSATTRIBUTES_MASK){
		if (!XIMInputContext_SetStatusBackgroundPixmap (pInputContext, pixmap)){
			return	False ;
		}
	} else {
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	return	True ;
}

Boolean
ximClient_setIcValueFontSet (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	register int			nMethodID, nContextID ;
	register const char*	pFontSetBaseName ;
	register int			nFontSetBaseNameLength ;

	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;

	/*	フォント名を抜き出す。*/
	pFontSetBaseName		= 0 ;
	nFontSetBaseNameLength	= -1 ;
	if (nDataLength >= GET_VALUE_LENGTH (CARD16)){
		nFontSetBaseNameLength	= (int)XIMData_GetCard16 (pData) ;
		nDataLength			-= GET_VALUE_LENGTH (CARD16) ;
		if (nDataLength >= nFontSetBaseNameLength)
			pFontSetBaseName	= (const char*)XIMData_GetHead (pData) ;
	}
	/*	フォント名が正しくとれたかどうかチェックする。*/
	if (nFontSetBaseNameLength <= 0){
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadName, "Bad fontset") ;
		return	False ;
	}
	if (iMode & PREEDITATTRIBUTES_MASK){
		if (!XIMInputContext_SetPreeditFontSet (pInputContext, pFontSetBaseName, nFontSetBaseNameLength)){
			return	False ;
		}
	} else if (iMode & STATUSATTRIBUTES_MASK){
		if (!XIMInputContext_SetStatusFontSet (pInputContext, pFontSetBaseName, nFontSetBaseNameLength)){
			return	False ;
		}
	} else {
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	return	True ;
}

Boolean
ximClient_setIcValueLineSpacing (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	register int		nMethodID, nContextID ;
	register long		lLineSpacing ;

	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;

	if (nDataLength < GET_VALUE_LENGTH (CARD32)){
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "Bad line spacing") ;
		return	False ;
	}

	lLineSpacing	= (long) XIMData_GetCard32 (pData) ;
	if (iMode & PREEDITATTRIBUTES_MASK){
		if (!XIMInputContext_SetPreeditLineSpacing (pInputContext, lLineSpacing)){
			ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "Bad line spacing") ;
			return	False ;
		}
	} else if (iMode & STATUSATTRIBUTES_MASK){
		if (!XIMInputContext_SetStatusLineSpacing (pInputContext, lLineSpacing)){
			ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "Bad line spacing") ;
			return	False ;
		}
	} else {
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	return	True ;
}

Boolean
ximClient_setIcValueCursor (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XIMData*			pData,
	register int				nDataLength,
	register int				iMode)
{
	register int			nMethodID, nContextID ;
	register Cursor			cursor ;

	nMethodID	= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID	= XIMInputContext_GetID (pInputContext) ;

	if (nDataLength < GET_VALUE_LENGTH (CARD32)){
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadCursor, "Bad cursor") ;
		return	False ;
	}

	cursor	= (Cursor) XIMData_GetCard32 (pData) ;
	if (iMode & PREEDITATTRIBUTES_MASK){
		if (!XIMInputContext_SetPreeditCursor (pInputContext, cursor)){
			return	False ;
		}
	} else if (iMode & STATUSATTRIBUTES_MASK){
		if (!XIMInputContext_SetStatusCursor (pInputContext, cursor)){
			return	False ;
		}
	} else {
		ximClient_writeErrorMessage (gw, nMethodID, nContextID, XIM_ERROR_BadProtocol, "PreeditAttribute or StatusAttribute?") ;
		return	False ;
	}
	return	True ;
}

Boolean
ximClient_supportedEncodingp (
	register const char*	pStrEncoding,
	register int			nStrEncoding)
{
	static const char*	srSupportedEncodings []	= {
		"COMPOUND_TEXT",	
	} ;
	register const char**	pPtr ;
	register int	i ;

	pPtr	= srSupportedEncodings ;
	for (i = 0 ; i < sizeof (srSupportedEncodings) / sizeof (srSupportedEncodings [0]) ; i ++) {
		if (!strncmp (*pPtr, pStrEncoding, nStrEncoding) &&
			*(*pPtr + nStrEncoding) == '\0')
			return	True ;
		pPtr	++ ;
	}
	return	False ;
}

void
ximClient_writeSyncReply (
	register Widget				gw,
	register int				nInputMethodID,
	register XIMInputContext*	pInputContext)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;
	register XIMPacket*			pPacket	= NULL ;
	register unsigned 			uSyncMode ;

#if 1
	while (uSyncMode = XIMInputContext_GetSyncMode (pInputContext),
		   (uSyncMode & XIMSyncAny) == 0) {
		register XIMPacketSyncMode	uPacketSync ;
		
		pPacket		= XIMInputContext_GetSpooledPacket (pInputContext) ;
		if (pPacket == NULL)
			break ;

		uPacketSync	= XIMPacket_GetSyncMode (pPacket) ;
		/*	影響を受けるのは、SYNC_NORMAL なパケットだけ。それ以外の
		 *	パケットは自分のブロックに従う。
		 */
		switch (uPacketSync) {
			register int		nPacket ;
		case	XIMPS_SPOOL:
			/*	ブロックモードであるか、後続のパケットが存在する場合には、
			 *	今投げるパケットは SYNC モードでなければならない。*/
			nPacket		= XIMInputContext_GetNumberOfSpooledPacket (pInputContext) ;
			if (nPacket > 0) {
				/*	パケットは SYNC モードに切り替わらなければならない。*/
				ximClient_makePacketSync (pPacket) ;
				break ;
			}
			/*	fall down */

		case	XIMPS_SPOOL_PREEDIT:
			/*	パケットは SYNC でなくて良い。多分、そのまま投げて
			 *	大丈夫。*/
			XIMPacket_SetSyncMode (pPacket, XIMPS_NO) ;
			break ;

		case	XIMPS_SPOOL_PREEDIT_START:
		case	XIMPS_SPOOL_PREEDIT_CARET:
			/*	spool -> sync に変更される。*/
			XIMPacket_SetSyncMode (pPacket, uPacketSync + (XIMPS_SYNC_PREEDIT_START - XIMPS_SPOOL_PREEDIT_START)) ;
			break ;

		default:
			break ;
		}
		ximClient_writeMessage (gw, pPacket) ;
		XIMPacket_Release (pPacket) ;
	}
#else
	uSyncMode	= XIMInputContext_GetSyncMode (pInputContext) ;
	if (!(uSyncMode & (XIMSyncNormal | XIMSyncPreeditStart | XIMSyncPreeditCaret))) {
		pPacket		= XIMInputContext_GetSpooledPacket (pInputContext) ;
		if (pPacket != NULL) {
			register XIMPacketSyncMode	uPacketSync	= XIMPacket_GetSyncMode (pPacket) ;

			/*	影響を受けるのは、SYNC_NORMAL なパケットだけ。それ以外の
			 *	パケットは自分のブロックに従う。
			 */
			if (uPacketSync == XIMPS_SPOOL) {
				register int				nPacket ;

				/*	ブロックモードであるか、後続のパケットが存在する場合には、
				 *	今投げるパケットは SYNC モードでなければならない。*/
				nPacket		= XIMInputContext_GetNumberOfSpooledPacket (pInputContext) ;
				if (nPacket > 0) {
					/*	パケットは SYNC モードに切り替わらなければならない。*/
					ximClient_makePacketSync (pPacket) ;
				} else {
					/*	パケットは SYNC でなくて良い。多分、そのまま投げて
					 *	大丈夫。*/
					XIMPacket_SetSyncMode (pPacket, XIMPS_NO) ;
				}
			}
			ximClient_writeMessage (gw, pPacket) ;
			XIMPacket_Release (pPacket) ;
		}
	} else {
		/*	ブロックされているのなら、SYNC_REPLY 以外のパケットを投げてはいけな
		 *	い。*/
		pPacket		= NULL ;
	}
#endif

	/*	SYNC REPLY を送出する。
	 */
	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_SYNC_REPLY, 0) ;
	XIMPacket_AddCard16 (pPacket, nInputMethodID) ;
	XIMPacket_AddCard16 (pPacket, XIMInputContext_GetID (pInputContext)) ;
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return ;
}

void
ximClient_makePacketSync (
	register XIMPacket*		pPacket)
{
	int				nMajor ;
	CARD16			uMask ;

	XIMPacket_GetHeader (pPacket, &nMajor, NULL) ;
	assert (nMajor == XIM_COMMIT ||
			nMajor == XIM_FORWARD_EVENT ||
			nMajor == XIM_EXT_FORWARD_KEYEVENT) ;

	XIMPacket_SetSyncMode (pPacket, XIMPS_SYNC_NORMAL) ;
	XIMPacket_GetCard16   (pPacket, XIM_HEADER_SIZE + 2 + 2, &uMask) ;
	XIMPacket_SetCard16   (pPacket, XIM_HEADER_SIZE + 2 + 2, uMask | 1) ;
	return ;
}

void
ximClient_flushSpooledPacket (
	register Widget				gw,
	register XIMInputContext*	pInputContext)
{
	register XIMPacket*		pPacket ;
	register unsigned int	uSyncMode ;

	while (uSyncMode = XIMInputContext_GetSyncMode (pInputContext),
		   (uSyncMode & XIMSyncAny) == 0) {
		register XIMPacketSyncMode	uPacketSync ;

		pPacket		= XIMInputContext_GetSpooledPacket (pInputContext) ;
		if (pPacket == NULL)
			break ;

		uPacketSync	= XIMPacket_GetSyncMode (pPacket) ;
		/*	影響を受けるのは、SYNC_NORMAL なパケットだけ。それ以外の
		 *	パケットは自分のブロックに従う。
		 */
		switch (uPacketSync) {
		case	XIMPS_SPOOL:
			ximClient_makePacketSync (pPacket) ;
			break ;

		case	XIMPS_SPOOL_PREEDIT:
			/*	パケットは SYNC でなくて良い。多分、そのまま投げて
			 *	大丈夫。*/
			XIMPacket_SetSyncMode (pPacket, XIMPS_NO) ;
			break ;

		case	XIMPS_SPOOL_PREEDIT_START:
		case	XIMPS_SPOOL_PREEDIT_CARET:
			/*	spool -> sync に変更される。*/
			XIMPacket_SetSyncMode (pPacket, uPacketSync + (XIMPS_SYNC_PREEDIT_START - XIMPS_SPOOL_PREEDIT_START)) ;
			break ;

		default:
			break ;
		}
		ximClient_writeMessage (gw, pPacket) ;
		XIMPacket_Release (pPacket) ;
	}
	return ;
}

/*
 */
Boolean
XIMClient_CommitString (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register struct myChar*		pText)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;
	register XIMPacket*			pPacket ;
	register int				nTextIndex, nIndex ;
	register char*				pBuffer ;
	register int				propsize ;
	register int				nMethodID, nContextID ;
	register int				nPacketSync ;
	register unsigned int		uMask, uSyncMode ;
	register struct myChar*		wptr ;

	if (pInputMethod == NULL || pInputContext == NULL || pText == NULL)
		return	False ;

	nMethodID		= XIMInputMethod_GetID  (pInputMethod) ;
	nContextID		= XIMInputContext_GetID (pInputContext) ;

#if defined (DEBUG)
	fprintf (stderr, "XIMClient_CommitString (%p), IM(%d), IC(%d), Text(%p/%d)\n",
			 gw,nMethodID, nContextID, pText, nText) ;
#endif

	/*	クライアントから SYNC_REPLY を返すことを要求されてない、or
	 *	ブロックモードにある、
	 *	この場合には、送出するパケットの同期を自前でとらないとい
	 *	けないので、SYNC MASK 付きになる。
	 */
	uSyncMode	= XIMInputContext_GetSyncMode (pInputContext) ;
	if (!(uSyncMode & XIMClientSync) ||
		(uSyncMode & (XIMSyncNormal | XIMSyncPreeditStart | XIMSyncPreeditCaret))) {
		nPacketSync	= XIMPS_SYNC_NORMAL ;
		uMask		= 1 | 2 ;
	} else {
		/*	Client に Sync-Reply を返す前なら、最初の 1 つの
		 *	パケットならブロックされていなくても良い。で、
		 *	最初の 1 つかどうかなんての判定はここではできない
		 *	ので、SYNC は無い!にしておく。
		 */
		nPacketSync	= XIMPS_SPOOL ;
		uMask		= 2 ;
	}

	for (wptr = pText ; !IS_END_OF_STRING (*wptr) ; wptr ++)
		if (IS_ASCII_EQUAL (*wptr, '\r'))
			wptr->chara = '\n' ;

	propsize = string2ctext (pText, NULL) ;
	if (propsize <= 0)
		return	False ;

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_COMMIT, 0) ;
	XIMPacket_AddCard16 (pPacket, nMethodID) ;
	XIMPacket_AddCard16 (pPacket, nContextID) ;
	XIMPacket_SetInputContext (pPacket, pInputContext) ;
	XIMPacket_SetSyncMode  (pPacket, nPacketSync) ;
	XIMPacket_AddBitmask16 (pPacket, uMask) ;

	nIndex	= XIMPacket_GetDataSize (pPacket) ;
	XIMPacket_AddCard16 (pPacket, 0 /* dummy */) ;

	nTextIndex	= XIMPacket_GetDataSize (pPacket) ;
	XIMPacket_AddCard8N (pPacket, propsize) ;
	pBuffer	= XIMPacket_GetData (pPacket) + nTextIndex ;
	string2ctext (pText, pBuffer) ;
	XIMPacket_AddPad (pPacket, propsize) ;
	XIMPacket_SetCard16 (pPacket, nIndex, propsize) ;
	XIMPacket_SetLength (pPacket) ;
	/**/
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return	True ;
}

Boolean
XIMClient_PreeditStateChange (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;
	register XIMPacket*			pPacket ;

	if (pInputMethod == NULL || pInputContext == NULL)
		return	False ;

	/*	XIM_PREEDITSTATE は Asynchronous な Message だと思う…。*/
	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_PREEDITSTATE, 0) ;
	XIMPacket_AddCard16 (pPacket, XIMInputMethod_GetID (pInputMethod)) ;
	XIMPacket_AddCard16 (pPacket, XIMInputContext_GetID (pInputContext)) ;
	XIMPacket_AddBitmask32 (pPacket, XIMInputContext_GetPreeditState (pInputContext)) ;
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return	True ;
}

Boolean
XIMClient_ControlEventFlow (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register Boolean			fEnable)
{
	if (pInputMethod == NULL || pInputContext == NULL)
		return	False ;
	ximClient_setForwardEvent (gw, pInputMethod, pInputContext, fEnable) ;
	return	True ;
}


/*
 */
Boolean
XIMClient_ForwardEvent (
	register Widget				gw,
	register XIMInputMethod*	pInputMethod,
	register XIMInputContext*	pInputContext,
	register XEvent*			pEvent)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;
	register XIMPacket*			pPacket ;
	register int				nPacketSync ;
	register unsigned int		uMask, uSyncMode ;

	if (pInputMethod == NULL || pInputContext == NULL ||
		pEvent == NULL || (pEvent->type != KeyPress && pEvent->type != KeyRelease))
		return	False ;

	/*	クライアントから SYNC_REPLY を返すことを要求されてない、or
	 *	ブロックモードにある、
	 *	この場合には、送出するパケットの同期を自前でとらないとい
	 *	けないので、SYNC MASK 付きになる。
	 */
	uSyncMode	= XIMInputContext_GetSyncMode (pInputContext) ;
#if defined (DEBUG)
	fprintf (stderr, "XIMClient_ForwardEvent (%d, %d, %x)\n",
			 XIMInputMethod_GetID (pInputMethod),
			 XIMInputContext_GetID (pInputContext),
			 uSyncMode) ;
#endif
	if (!(uSyncMode & XIMClientSync) ||
		(uSyncMode & (XIMSyncNormal | XIMSyncPreeditStart | XIMSyncPreeditCaret))) {
		nPacketSync	= XIMPS_SYNC_NORMAL ;
		uMask		= FORWARDEVENT_SYNC_MASK ;
	} else {
		/*	Client に Sync-Reply を返す前なら、最初の 1 つの
		 *	パケットならブロックされていなくても良い。で、
		 *	最初の 1 つかどうかなんての判定はここではできない
		 *	ので、SYNC は無い!にしておく。
		 */
		nPacketSync	= XIMPS_SPOOL ;
		uMask		= 0 ;
	}

	pPacket		= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	if (XIMInputMethod_GetExtMask (pInputMethod) & XIM_EXT_FORWARD_KEYEVENT_MASK) {
		XIMPacket_SetHeader (pPacket, XIM_EXT_FORWARD_KEYEVENT, 0) ;
		XIMPacket_AddCard16 (pPacket, XIMInputMethod_GetID (pInputMethod)) ;
		XIMPacket_AddCard16 (pPacket, XIMInputContext_GetID (pInputContext)) ;
		XIMPacket_SetInputContext (pPacket, pInputContext) ;
		XIMPacket_SetSyncMode  (pPacket, nPacketSync) ;
		XIMPacket_AddBitmask16 (pPacket, uMask) ;
		XIMPacket_AddCard16 (pPacket, (CARD16)pEvent->xkey.serial) ;
		XIMPacket_AddCard8  (pPacket, (CARD8)pEvent->xkey.type & 0x7F) ;
		XIMPacket_AddCard8  (pPacket, (CARD8)pEvent->xkey.keycode) ;
		XIMPacket_AddCard16 (pPacket, (CARD16)pEvent->xkey.state) ;
		XIMPacket_AddCard32 (pPacket, (CARD32)pEvent->xkey.time) ;
		XIMPacket_AddCard32 (pPacket, (CARD32)pEvent->xkey.window) ;
	} else {
		xEvent			xev ;
		Boolean			fSwap ;
		unsigned long	one		= 1 ;
		char*			onep	= (char *)&one ;

		if (*onep == 0) {
			fSwap	= !wgThis->ximClient.m_fBigEndian ;
		} else {
			fSwap	= wgThis->ximClient.m_fBigEndian ;
		}
#define	BIGCARD16(wValue)	((!fSwap)? (wValue) : (((wValue) & 0x00FF) << 8) | (((wValue) & 0xFF00) >> 8))
#define	BIGCARD32(dwValue)	((!fSwap)? (dwValue) : ((((dwValue) & 0x000000FFl) << 24) | (((dwValue) & 0x0000FF00l) <<  8) | (((dwValue) & 0x00FF0000l) >>  8) | (((dwValue) & 0xFF000000l) >> 24)))
		xev.u.u.type					= pEvent->type ;
		xev.u.keyButtonPointer.root		= BIGCARD32 (pEvent->xkey.root) ;
		xev.u.keyButtonPointer.event	= BIGCARD32 (pEvent->xkey.window) ;
		xev.u.keyButtonPointer.child	= BIGCARD32 (pEvent->xkey.subwindow) ;
		xev.u.keyButtonPointer.time		= BIGCARD32 (pEvent->xkey.time) ;
		xev.u.keyButtonPointer.eventX	= BIGCARD16 (pEvent->xkey.x) ;
		xev.u.keyButtonPointer.eventY	= BIGCARD16 (pEvent->xkey.y) ;
		xev.u.keyButtonPointer.rootX	= BIGCARD16 (pEvent->xkey.x_root) ;
		xev.u.keyButtonPointer.rootY	= BIGCARD16 (pEvent->xkey.y_root) ;
		xev.u.keyButtonPointer.state	= BIGCARD16 (pEvent->xkey.state) ;
		xev.u.keyButtonPointer.sameScreen	= pEvent->xkey.same_screen ;
		//xev.u.u.sequenceNumber			= BIGCARD16 ((pEvent->xany.serial & 0x0000FFFFl)) ;
		xev.u.u.detail					= pEvent->xkey.keycode ;
		if (((XAnyEvent *)pEvent)->send_event)
			xev.u.u.type				|= 0x80 ;
		xev.u.u.sequenceNumber	= ((XAnyEvent *)pEvent)->serial & ~((unsigned long)0xffff);
		xev.u.u.sequenceNumber	= BIGCARD16 (xev.u.u.sequenceNumber);
#undef	BIGCARD16
#undef	BIGCARD32

		XIMPacket_SetHeader (pPacket, XIM_FORWARD_EVENT, 0) ;
		XIMPacket_AddCard16 (pPacket, XIMInputMethod_GetID (pInputMethod)) ;
		XIMPacket_AddCard16 (pPacket, XIMInputContext_GetID (pInputContext)) ;
		XIMPacket_SetInputContext (pPacket, pInputContext) ;
		XIMPacket_SetSyncMode  (pPacket, nPacketSync) ;
		XIMPacket_AddBitmask16 (pPacket, uMask) ;
		XIMPacket_AddCard16 (pPacket, (CARD16)(pEvent->xany.serial >> 16)) ;
		XIMPacket_AddString8 (pPacket, (STRING8)&xev, sizeof (xEvent)) ;
	}
	XIMPacket_SetLength (pPacket) ;
	/**/
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return	True ;
}

void
XIMClient_WriteXimGeometry (
	register Widget		gw,
	register int		nInputMethodID,
	register int		nInputContextID)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;
	register XIMPacket*			pPacket ;

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	XIMPacket_SetHeader (pPacket, XIM_GEOMETRY, 0) ;
	XIMPacket_AddCard16 (pPacket, nInputMethodID) ;
	XIMPacket_AddCard16 (pPacket, nInputContextID) ;
	XIMPacket_SetLength (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return ;
}

void
XIMClient_WritePreeditStart (
	register Widget				gw,
	register int				nInputMethodID,
	register XIMInputContext*	pInputContext)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;
	register XIMPacket*			pPacket ;
	register unsigned int		uSyncMode ;
	register int				nInputContextID, nPacketSync ;

	assert (gw   != NULL) ;

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	if (pPacket == NULL)
		return ;

	nInputContextID	= XIMInputContext_GetID (pInputContext) ;
	XIMPacket_SetHeader   (pPacket, XIM_PREEDIT_START, 0) ;
	XIMPacket_AddCard16   (pPacket, nInputMethodID) ;
	XIMPacket_AddCard16   (pPacket, nInputContextID) ;

	XIMPacket_SetInputContext (pPacket, pInputContext) ;
	/*	この SYNC は何処までのメッセージをブロックするのだ
	 *	ろうか？ 多分、こいつの reply までは PREEDIT 系の
	 *	メッセージは停止するのだろうけど。*/
	uSyncMode	= XIMInputContext_GetSyncMode (pInputContext) ;
	if ((uSyncMode & (XIMClientSync | XIMSyncAny)) == 0) {
		nPacketSync	= XIMPS_SYNC_PREEDIT_START ;
	} else {
		nPacketSync	= XIMPS_SPOOL_PREEDIT_START ;
	}
	XIMPacket_SetSyncMode (pPacket, nPacketSync) ;
	XIMPacket_SetLength   (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return ;
}

void
XIMClient_WritePreeditDraw (
	register Widget						gw,
	register int						nInputMethodID,
	register XIMInputContext*			pInputContext,
	register const TOnTheSpotDrawArg*	pArg)
{
	register XIMClientWidget		wgThis	= (XIMClientWidget) gw ;
	register XIMPacket*				pPacket ;
	register int					nctext, nIndex ;
	register unsigned int			uMask, uSyncMode ;
	register int					nInputContextID, nPacketSync ;
	register unsigned char*			pBuffer ;
	register unsigned char*			ptr ;
	register int					nTextIndex, n ;

	assert (gw   != NULL) ;
	assert (pArg != NULL) ;

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	if (pPacket == NULL)
		return ;

	nInputContextID	= XIMInputContext_GetID (pInputContext) ;
	XIMPacket_SetHeader   (pPacket, XIM_PREEDIT_DRAW, 0) ;
	XIMPacket_AddCard16   (pPacket, nInputMethodID) ;
	XIMPacket_AddCard16   (pPacket, nInputContextID) ;
	XIMPacket_AddCard32	  (pPacket, pArg->m_nCaret) ;
	XIMPacket_AddCard32   (pPacket, pArg->m_nChgFirst) ;

	/*	2文字以上が PreeditString として表示されている状態から
	 *	ChgFirst, ChgLength で消去しようとすると KDE3.0 では消
	 *	去に失敗する。
	 *	qt の文字の数え方と im server 側の文字の数え方がずれて
	 *	いる？ 良く分からない。
	 *	qt を hack した結果、-1 が ChgLength に入っていれば、
	 *	全消去扱いになっているようなので、それを利用する(*)
	 *
	 *(*) この動作は qt ローカルな仕様な気がする。この動作にあわ
	 *	ない別なクライアントが登場した時に、どうしたものか…
	 */
#if !defined (QT_CANT_CLEAR_TEXT) && 0
	/*
	 *	Notepad.jar でバグった。(;_;)
	 */
	if (pArg->m_nText <= 0 && pArg->m_nChgFirst <= 0) {
		XIMPacket_AddCard32   (pPacket, -1) ;
	} else {
		XIMPacket_AddCard32   (pPacket, pArg->m_nChgLength) ;
	}
#else
	XIMPacket_AddCard32   (pPacket, pArg->m_nChgLength) ;
#endif

	uMask	= 0 ;
	if (pArg->m_pText == NULL ||
		pArg->m_nText <= 0 || 
		IS_END_OF_STRING (*(pArg->m_pText)))
		uMask	|= 1 | 2 ;

	XIMPacket_AddBitmask32(pPacket, uMask) ;
	nIndex	= XIMPacket_GetDataSize (pPacket) ;
	XIMPacket_AddCard16   (pPacket, 0 /* dummy */) ;
	
	nctext		= string2ctextn (pArg->m_pText, pArg->m_nText, NULL) ;
	nTextIndex	= XIMPacket_GetDataSize (pPacket) ;
	XIMPacket_AddCard8N (pPacket, nctext) ;
	pBuffer		= XIMPacket_GetData (pPacket) + nTextIndex ;
	string2ctextn (pArg->m_pText, pArg->m_nText, pBuffer) ;

	ptr			= pBuffer ;
	n			= nctext ;
	while (n -- > 0) {
		if (*ptr == '\n')
			*ptr	= '\r' ;
		ptr	++ ;
	}
	XIMPacket_SetCard16   (pPacket, nIndex, nctext) ;
#if defined (DEBUG) || 0
	fprintf (stderr, "Caret(%d), ChgFirst(%d), ChgLength(%d), Text(%d), Attribute(%d), Length(%d)\n",
			 pArg->m_nCaret,
			 pArg->m_nChgFirst,
			 pArg->m_nChgLength,
			 pArg->m_nText,
			 pArg->m_nAttribute,
			 nctext) ;
#endif
	XIMPacket_AddPad      (pPacket, nctext + 2) ;
	/*	FEEDBACK 情報 */
	if (uMask & 2) {
		XIMPacket_AddCard16 (pPacket, 0) ;
		XIMPacket_AddCard16 (pPacket, 0) ;
	} else {
		register const CARD32*	pAttribute ;
		register int			nAttribute ;

		XIMPacket_AddCard16 (pPacket, pArg->m_nAttribute * sizeof (CARD32)) ;
		XIMPacket_AddCard16 (pPacket, 0) ;
		pAttribute	= pArg->m_pAttribute ;
		nAttribute	= pArg->m_nAttribute ;
		while (nAttribute -- > 0)
			XIMPacket_AddCard32 (pPacket, *pAttribute ++) ;
	}

	XIMPacket_SetInputContext (pPacket, pInputContext) ;
	uSyncMode	= XIMInputContext_GetSyncMode (pInputContext) ;
	if ((uSyncMode & (XIMClientSync | XIMSyncAny)) == 0) {
		nPacketSync	= XIMPS_NO ;
	} else {
		nPacketSync	= XIMPS_SPOOL_PREEDIT ;
	}
	XIMPacket_SetSyncMode (pPacket, nPacketSync) ;
	XIMPacket_SetLength   (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return ;
}

void
XIMClient_WritePreeditCaret (
	register Widget				gw,
	register int				nInputMethodID,
	register XIMInputContext*	pInputContext,
	register const TOnTheSpotDrawArg*	pArg)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;
	register XIMPacket*			pPacket ;
	register unsigned int		uSyncMode ;
	register int				nInputContextID, nPacketSync ;

	assert (gw   != NULL) ;

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	if (pPacket == NULL)
		return ;

	nInputContextID	= XIMInputContext_GetID (pInputContext) ;
	XIMPacket_SetHeader   (pPacket, XIM_PREEDIT_CARET, 0) ;
	XIMPacket_AddCard16   (pPacket, nInputMethodID) ;
	XIMPacket_AddCard16   (pPacket, nInputContextID) ;
	XIMPacket_AddCard32	  (pPacket, pArg->m_nCaret) ;
	XIMPacket_AddCard32	  (pPacket, 10) ;
	XIMPacket_AddCard32	  (pPacket, 1) ;
	XIMPacket_SetInputContext (pPacket, pInputContext) ;
	uSyncMode	= XIMInputContext_GetSyncMode (pInputContext) ;
	if ((uSyncMode & (XIMClientSync | XIMSyncAny)) == 0) {
		nPacketSync	= XIMPS_SYNC_PREEDIT_CARET ;
	} else {
		nPacketSync	= XIMPS_SPOOL_PREEDIT_CARET ;
	}
	XIMPacket_SetSyncMode (pPacket, nPacketSync) ;
	XIMPacket_SetLength   (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return ;
}

void
XIMClient_WritePreeditDone (
	register Widget				gw,
	register int				nInputMethodID,
	register XIMInputContext*	pInputContext)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;
	register XIMPacket*			pPacket ;
	register unsigned int		uSyncMode ;
	register int				nInputContextID, nPacketSync ;

	assert (gw   != NULL) ;

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	if (pPacket == NULL)
		return ;

	nInputContextID	= XIMInputContext_GetID (pInputContext) ;
	XIMPacket_SetHeader   (pPacket, XIM_PREEDIT_DONE, 0) ;
	XIMPacket_AddCard16   (pPacket, nInputMethodID) ;
	XIMPacket_AddCard16   (pPacket, nInputContextID) ;

	XIMPacket_SetInputContext (pPacket, pInputContext) ;
	/*	この SYNC は何処までのメッセージをブロックするのだ
	 *	ろうか？ 多分、こいつの reply までは PREEDIT 系の
	 *	メッセージは停止するのだろうけど。*/
	uSyncMode	= XIMInputContext_GetSyncMode (pInputContext) ;
	if ((uSyncMode & (XIMClientSync | XIMSyncAny)) == 0) {
		nPacketSync	= XIMPS_NO ;
	} else {
		nPacketSync	= XIMPS_SPOOL_PREEDIT ;
	}
	XIMPacket_SetSyncMode (pPacket, nPacketSync) ;
	XIMPacket_SetLength   (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return ;
}

void
XIMClient_WriteStatusStart (
	register Widget				gw,
	register int				nInputMethodID,
	register XIMInputContext*	pInputContext)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;
	register XIMPacket*			pPacket ;
	register unsigned int		uSyncMode ;
	register int				nInputContextID, nPacketSync ;

	assert (gw   != NULL) ;

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	if (pPacket == NULL)
		return ;

	nInputContextID	= XIMInputContext_GetID (pInputContext) ;
	XIMPacket_SetHeader   (pPacket, XIM_STATUS_START, 0) ;
	XIMPacket_AddCard16   (pPacket, nInputMethodID) ;
	XIMPacket_AddCard16   (pPacket, nInputContextID) ;
#if defined (DEBUG) || 0
	fprintf (stderr, "XIMClient_WriteStatusStart (%p, %d, %d)\n",
			 gw, nInputMethodID, nInputContextID) ;
#endif

	XIMPacket_SetInputContext (pPacket, pInputContext) ;
	/*	この SYNC は何処までのメッセージをブロックするのだ
	 *	ろうか？ 多分、こいつの reply までは PREEDIT 系の
	 *	メッセージは停止するのだろうけど。*/
	uSyncMode	= XIMInputContext_GetSyncMode (pInputContext) ;
	if ((uSyncMode & (XIMClientSync | XIMSyncAny)) == 0) {
		nPacketSync	= XIMPS_NO ;
	} else {
		nPacketSync	= XIMPS_SPOOL_PREEDIT ;
	}
	XIMPacket_SetSyncMode (pPacket, nPacketSync) ;
	XIMPacket_SetLength   (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return ;
}

void
XIMClient_WriteStatusDraw (
	register Widget						gw,
	register int						nInputMethodID,
	register XIMInputContext*			pInputContext,
	register const TOnTheSpotDrawArg*	pArg)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;
	register XIMPacket*			pPacket ;
	register int				nctext, nIndex, nTextIndex, n ;
	register unsigned int		uSyncMode ;
	register int				nPacketSync, nInputContextID ;
	register unsigned char*		pBuffer ;
	register unsigned char*		ptr ;

	assert (gw   != NULL) ;
	assert (pArg != NULL) ;

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	if (pPacket == NULL)
		return ;

	nInputContextID	= XIMInputContext_GetID (pInputContext) ;
#if defined (DEBUG) || 0
	fprintf (stderr, "XIMClient_WriteStatusDraw (%p, %d, %d, len(%d))\n",
			 gw, nInputMethodID, nInputContextID, pArg->m_nText) ;
#endif
	XIMPacket_SetHeader   (pPacket, XIM_STATUS_DRAW, 0) ;
	XIMPacket_AddCard16   (pPacket, nInputMethodID) ;
	XIMPacket_AddCard16   (pPacket, nInputContextID) ;
	XIMPacket_AddCard32   (pPacket, 0) ;
	if (pArg->m_pText == NULL ||
		pArg->m_nText <= 0 ||
		IS_END_OF_STRING (*(pArg->m_pText))) {
		XIMPacket_AddCard32   (pPacket, 1 | 2) ;
	} else {
		XIMPacket_AddCard32   (pPacket, 2) ;
	}
	nIndex	= XIMPacket_GetDataSize (pPacket) ;
	XIMPacket_AddCard16   (pPacket, 0 /* dummy */) ;

	nTextIndex	= XIMPacket_GetDataSize (pPacket) ;
	nctext		= string2ctextn (pArg->m_pText, pArg->m_nText, NULL) ;
	XIMPacket_AddCard8N (pPacket, nctext) ;
	pBuffer		= XIMPacket_GetData (pPacket) + nTextIndex ;

	ptr			= pBuffer ;
	n			= nctext ;
	while (n -- > 0) {
		if (*ptr == '\n')
			*ptr	= '\r' ;
		ptr ++ ;
	}
	string2ctextn (pArg->m_pText, pArg->m_nText, pBuffer) ;
	XIMPacket_SetCard16   (pPacket, nIndex, nctext) ;
	XIMPacket_AddPad      (pPacket, nctext + 2) ;

	XIMPacket_SetInputContext (pPacket, pInputContext) ;
	uSyncMode	= XIMInputContext_GetSyncMode (pInputContext) ;
	if ((uSyncMode & (XIMClientSync | XIMSyncAny)) == 0) {
		nPacketSync	= XIMPS_NO ;
	} else {
		nPacketSync	= XIMPS_SPOOL_PREEDIT ;
	}
	XIMPacket_SetSyncMode (pPacket, nPacketSync) ;
	XIMPacket_SetLength   (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return ;
}

void
XIMClient_WriteStatusDone (
	register Widget				gw,
	register int				nInputMethodID,
	register XIMInputContext*	pInputContext)
{
	register XIMClientWidget	wgThis	= (XIMClientWidget) gw ;
	register XIMPacket*			pPacket ;
	register unsigned int		uSyncMode ;
	register int				nPacketSync, nInputContextID ;

	assert (gw   != NULL) ;

	pPacket	= XIMPacket_Create (wgThis->ximClient.m_fBigEndian) ;
	if (pPacket == NULL)
		return ;

	nInputContextID	= XIMInputContext_GetID (pInputContext) ;
	XIMPacket_SetHeader   (pPacket, XIM_STATUS_DONE, 0) ;
	XIMPacket_AddCard16   (pPacket, nInputMethodID) ;
	XIMPacket_AddCard16   (pPacket, nInputContextID) ;
#if defined (DEBUG) || 0
	fprintf (stderr, "XIMClient_WriteStatusDone (%p, %d, %d)\n",
			 gw, nInputMethodID, nInputContextID) ;
#endif

	XIMPacket_SetInputContext (pPacket, pInputContext) ;
	/*	この SYNC は何処までのメッセージをブロックするのだ
	 *	ろうか？ 多分、こいつの reply までは PREEDIT 系の
	 *	メッセージは停止するのだろうけど。*/
	uSyncMode	= XIMInputContext_GetSyncMode (pInputContext) ;
	if ((uSyncMode & (XIMClientSync | XIMSyncAny)) == 0) {
		nPacketSync	= XIMPS_NO ;
	} else {
		nPacketSync	= XIMPS_SPOOL_PREEDIT ;
	}
	XIMPacket_SetSyncMode (pPacket, nPacketSync) ;
	XIMPacket_SetLength   (pPacket) ;
	ximClient_writeMessage (gw, pPacket) ;
	XIMPacket_Release (pPacket) ;
	return ;
}

#if defined (DEBUG) || 0
void
dumpBuf (
	register const BYTE*	pData,
	register int			nData)
{
	register int	i ;

	for (i = 0 ; i < nData ; i ++) {
		if ((i % 16) == 0)
			fprintf (stderr, "\t") ;
		fprintf (stderr, "%02x ", *pData) ;
		pData	++ ;
		if ((i % 16) == 15)
			fprintf (stderr, "\n") ;
	}
	if ((nData % 16) != 0)
		fprintf (stderr, "\n") ;
	return ;
}
#endif
