diff lib/Atok.c @ 0:92745d501b9a

initial import from kinput2-v3.1
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Mon, 08 Mar 2010 04:44:30 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/Atok.c	Mon Mar 08 04:44:30 2010 +0900
@@ -0,0 +1,1851 @@
+/*
+ * Copyright (c) 1990  Software Research Associates, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Software Research Associates not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  Software Research
+ * Associates makes no representations about the suitability of this software
+ * for any purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * Author:  Makoto Ishisone, Software Research Associates, Inc., Japan
+ */
+
+/* Copyright 1991 NEC Corporation, Tokyo, Japan.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of NEC Corporation
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.  NEC 
+ * Corporation makes no representations about the suitability of this
+ * software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * NEC CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN 
+ * NO EVENT SHALL NEC CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 
+ * OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 
+ * PERFORMANCE OF THIS SOFTWARE. 
+ *
+ * Author: Akira Kon, NEC Corporation.  (kon@d1.bs2.mt.nec.co.jp)
+ */
+
+/* 
+ * Copyright 1999 Justsystem Corporation, Japan.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Justsystem Corporation
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.  Justsystem 
+ * Corporation makes no representations about the suitability of this
+ * software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * Author: Atsushi Irisawa
+ */
+
+#ifndef lint
+static char *rcsid = "$Id: Atok.c,v 1.3 1999/08/24 08:59:35 ishisone Exp $";
+#endif
+
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/Xmu/Atoms.h>
+#define XK_KATAKANA
+#include <X11/keysym.h>
+#if XtSpecificationRelease > 4
+#include <X11/Xfuncs.h>
+#endif
+#include "AtokP.h"
+#include "key_def.h"
+#include "DebugPrint.h"
+
+#define _WCHAR_T
+#define wchar_t wchar
+
+#ifdef SVR4
+#define bzero(p, l)	memset(p, 0, l)
+#else
+#if defined(SYSV) || defined(USG)
+#define OVERLAP_BCOPY
+extern char *memset();
+#define bzero(p, l)	memset(p, 0, l)
+#endif
+#endif
+
+static XtResource resources[] = {
+#define offset(field) XtOffset(AtokObject, atok.field)
+    { XtNAtokServer, XtCAtokServer, XtRString, sizeof(String),
+	offset(atokserver), XtRString, NULL },
+    { XtNConfFile, XtCConfFile, XtRString, sizeof(String),
+	offset(conffile), XtRString, NULL },
+    { XtNStyleFile, XtCStyleFile, XtRString, sizeof(String),
+	offset(stylefile), XtRString, NULL },
+    { XtNPort, XtCPort, XtRString, sizeof(String),
+	offset(port), XtRString, NULL },
+#undef offset
+};
+
+static void ClassInitialize();
+static void Initialize();
+static void Destroy();
+static Boolean SetValues();
+static int InputEvent();
+static ICString *GetMode();
+static int CursorPos();
+static int NumSegments();
+static ICString *GetSegment();
+static int CompareSegment();
+static ICString *GetItemList();
+static int SelectItem();
+static int ConvertedString();
+static int ClearConversion();
+static ICString *GetAuxSegments();
+static int PreeditString();
+static int StatusString();
+
+AtokClassRec atokClassRec = {
+  { /* object fields */
+    /* superclass		*/	(WidgetClass) &inputConvClassRec,
+    /* class_name		*/	"Atok",
+    /* widget_size		*/	sizeof(AtokRec),
+    /* class_initialize		*/	ClassInitialize,
+    /* class_part_initialize	*/	NULL,
+    /* class_inited		*/	FALSE,
+    /* initialize		*/	Initialize,
+    /* initialize_hook		*/	NULL,
+    /* obj1			*/	NULL,
+    /* obj2			*/	NULL,
+    /* obj3			*/	0,
+    /* resources		*/	resources,
+    /* num_resources		*/	XtNumber(resources),
+    /* xrm_class		*/	NULLQUARK,
+    /* obj4			*/	FALSE,
+    /* obj5			*/	FALSE,
+    /* obj6			*/	FALSE,
+    /* obj7			*/	FALSE,
+    /* destroy			*/	Destroy,
+    /* obj8			*/	NULL,
+    /* obj9			*/	NULL,
+    /* set_values		*/	SetValues,
+    /* set_values_hook		*/	NULL,
+    /* obj10			*/	NULL,
+    /* get_values_hook		*/	NULL,
+    /* obj11			*/	NULL,
+    /* version			*/	XtVersion,
+    /* callback_private		*/	NULL,
+    /* obj12			*/	NULL,
+    /* obj13			*/	NULL,
+    /* obj14			*/	NULL,
+    /* extension		*/	NULL
+  },
+  { /* inputConv fields */
+    /* InputEvent		*/	InputEvent,
+    /* GetMode			*/	GetMode,
+    /* CursorPos		*/	CursorPos,
+    /* NumSegments		*/	NumSegments,
+    /* GetSegment		*/	GetSegment,
+    /* CompareSegment		*/	CompareSegment,
+    /* GetItemList		*/	GetItemList,
+    /* SelectItem		*/	SelectItem,
+    /* GetConvertedString	*/	ConvertedString,
+    /* ClearConversion		*/	ClearConversion,
+    /* GetAuxSegments		*/	GetAuxSegments,
+    /* SupportMultipleObjects	*/	True,
+    /* GetTriggerKeys		*/	XtInheritGetTriggerKeys,
+    /* num_trigger_keys		*/	0,
+    /* trigger_keys		*/	NULL,
+    /* GetPreeditString		*/	PreeditString,
+    /* GetStatusString		*/	StatusString,
+    /* NoMoreObjects		*/	False,
+  },
+  { /* atok fields */
+    /* foo			*/	0,
+  }
+};
+
+WidgetClass atokObjectClass = (WidgetClass)&atokClassRec;
+
+static int bell();
+static void fix();
+static void fixProcForAtok();
+static void convend();
+
+static void addObject();
+static void deleteObject();
+
+static void atokDisplay();
+static int atokCandDisplay();
+static int atokAuxDisplay();
+
+static void moveLeft();
+static void moveRight();
+static void setSelection();
+static void moveSelection();
+static void querySelection();
+static void endSelection();
+static void insertSelection();
+static int allocCandList();
+static int changeTextForAtok();
+static int changeTextForAtokAUX();
+static void startSelection();
+static int makeCandList();
+
+static void copyInWchar();
+
+static Display *displaybell = (Display *)0;
+
+static int clientID = -1;
+static int nAtokContexts = 0;
+static int ceSock = -1;
+
+
+static void
+ClassInitialize()
+{
+    DPRINT(( "ATOK Class Initialize\n" ));
+    TRACE(("AtokObjectClass initialized\n"));
+    /* $B2?$b$7$J$$(B */
+}
+
+/* ARGSUSED */
+static void
+Initialize(req, new, args, num_args)
+Widget req;
+Widget new;
+ArgList args;
+Cardinal *num_args;
+{
+    AtokObject obj = (AtokObject)new;
+    AtokObject objX = (AtokObject)req;
+    int sock;
+    menuAux *orgMenuAux;
+    char buf[256];
+    int isConnect = 1;
+    int i;
+
+    bzero((char *)&obj->atok, sizeof(obj->atok));
+
+    obj->atok.textchanged = False;
+    obj->atok.nbr_of_cand = 0;
+    obj->atok.cand_lists_ics = NULL;
+    obj->atok.cur_cand = 0;
+
+    for (i = 0; i < NBR_OF_PART; i++) {
+	obj->atok.aux_ics[i].data = (char *)NULL;
+	obj->atok.aux_ics[i].nchars = 0;
+	obj->atok.aux_ics[i].nbytes = 0;
+	obj->atok.aux_length[i] = 0;
+	obj->atok.aux_size[i] = 0;
+    }
+
+    if (objX->atok.atokserver)
+	obj->atok.atokserver = objX->atok.atokserver;
+    if (objX->atok.port)
+	obj->atok.port = objX->atok.port;
+    if (objX->atok.conffile)
+	obj->atok.conffile = objX->atok.conffile;
+
+    /* $BF~NO%P%C%U%!$r:n@.$9$k!#(B*/
+    obj->atok.comm = (_XatokRecPtr)XtMalloc(sizeof(_XatokRec));
+    bzero((char *)obj->atok.comm, sizeof(_XatokRec));
+    obj->atok.comm->echoLen = 0;
+    /* obj->atok.sock = ceSock; */
+
+    if (!nAtokContexts) {
+	ceSock = atokConnect(obj->atok.atokserver,
+			     obj->atok.port,
+			     obj->atok.conffile,
+			     obj->atok.stylefile,
+			     /*
+			     obj->atok.conffile ?
+				obj->atok.conffile : "atok12.conf",
+			     obj->atok.stylefile ?
+				obj->atok.stylefile : "atok12.sty",
+			     */
+			     obj->atok.comm);
+	if (ceSock < 0) {
+	    XtAppWarning(XtWidgetToApplicationContext((Widget)obj),
+			 "Cannot connect to ATOK server");
+	    /* exit(0); */
+	    XtFree((char *)obj->atok.comm);
+	    obj->atok.comm = (_XatokRecPtr)NULL;
+	    return;
+	}
+	isConnect = 0;
+	obj->atok.comm->sock = ceSock;
+	clientID = obj->atok.comm->NETrqst.clntid;
+    }
+
+    obj->atok.comm->sock = ceSock;
+
+    addObject(obj, ceSock, clientID, isConnect);
+
+    orgMenuAux = getMenuInstance();
+    obj->atok.comm->menuAux = auxMenuCopy(orgMenuAux);
+    obj->atok.comm->curAux = obj->atok.comm->menuAux;
+    XtCallCallbackList((Widget) obj, obj->inputConv.modechangecallback,
+		       (XtPointer)NULL);
+    nAtokContexts++;
+}
+
+static void
+Destroy(w)
+Widget w;
+{
+    AtokObject obj = (AtokObject)w;
+
+    if (obj->atok.comm) XtFree((char *)obj->atok.comm);
+    deleteObject(obj);
+}
+
+/* ARGSUSED */
+static Boolean SetValues(cur, req, wid, args, num_args)
+Widget cur;
+Widget req;
+Widget wid;
+ArgList args;
+Cardinal *num_args;
+{
+    AtokObject old = (AtokObject)cur;
+    AtokObject new = (AtokObject)wid;
+
+    return False;
+}
+
+
+static int
+XKanaLookup(event_struct, buffer_return, bytes_buffer,
+	    keysym, status_return)
+XKeyEvent *event_struct;
+char *buffer_return;
+int bytes_buffer;
+KeySym *keysym;
+XComposeStatus *status_return;
+{
+  int res;
+  res = XLookupString(event_struct, buffer_return, bytes_buffer,
+		      keysym, status_return);
+  if (!res && XK_overline <= *keysym && *keysym <= XK_semivoicedsound) {
+    buffer_return[0] = (unsigned long)(*keysym) & 0xff;
+    res = 1;
+  }
+  return res;
+}
+
+
+/*
+ * Kinput2 API Functions
+ */
+
+static int
+InputEvent(w, event)
+Widget w;
+XEvent *event;
+{
+    AtokObject obj = (AtokObject)w;
+    wchar wbuf[BUFSIZ*4];	/* $B3NDjJ8;zNs$N%P%C%U%!(B */
+    int wlen;			/* $B3NDjJ8;zNs$ND9$5(B */
+    unsigned char kbuf[BUFSIZ];	/* $B%-!<F~NO%G!<%?(B */
+    int nbytes;			/* $B%-!<F~NO$ND9$5(B  */
+    KeySym ks;			/* X$B$N%-!<%7%s%\%k(B */
+    XComposeStatus comp_status;		
+    WORD aajcode;		/* AAJCODE */
+    int kanjiStatus;
+    int enableStatus;
+    int changeStatus;
+    int elseEvent;
+    int status;
+    int isThrue = 0;
+
+    DPRINT(( "\n### NEW EVENT \n" ));
+
+    /* KeyPress$B0J30$O<N$F$k(B */
+    if (event->type != KeyPress /*&& event->type != KeyRelease*/) return 0;
+
+    obj->atok.textchanged = False;
+
+    /*
+     * AtokServer $B$,(B $B:F5/F0$5$l$?$P$"$$$J$I!"%3%M%/%7%g%s$,$-$l$F$$$k>l9g$,(B
+     * $B$"$k$N$G(B $B:FEY%3%M%/%7%g%s$rD%$C$F$_$k!#(B
+     */
+    if (obj->atok.comm == NULL) {
+	/* return -1; /* $B@\B3$G$-$F$$$J$$$H$-$O!"%(%i!<$rJV$9(B */
+	return 1; /* $B@\B3$G$-$F$$$J$$$H$-$O!"L5;k$9$k(B */
+    }
+
+    /* X $B$N%-!<%$%Y%s%H$r<hF@$9$k!#(B*/
+    kbuf[0] = '\0';
+    nbytes = XKanaLookup((XKeyEvent*)event, kbuf, sizeof(kbuf), &ks,
+			 &comp_status);
+
+    wbuf[0] = (wchar)kbuf[0]; /* $B$-$?$J$$(B */
+
+    DPRINT(("nbytes %d\n", nbytes));
+
+    /* $BMW$i$J$$>l9g$OL5;k$9$k(B */
+    if (nbytes == 0 && ks & 0xff00 == 0) return 1;
+
+    /* $B%Y%k$rLD$i$9%G%#%9%W%l%$$N@_Dj(B */
+    displaybell = XtDisplayOfObject((Widget)obj);
+
+    /*
+     * $B8uJd%&%#%s%I%&$,(BACTIVE $B$K$J$C$F$$$?>l9g$N8uJd$N0\F0$O(B
+     * Kinput2 $B$h$j(B Callback $B$,8F$S=P$5$l$:!"A*Br$5$l$F$$$kHV9f$,(B
+     * $B<hF@$G$-$J$$$N$G!"$3$3$G0lEY(B $BA*Br$5$l$F$$$kHV9f$r<hF@$9$k!#(B
+     */
+    if (obj->atok.comm->convStatus & M_CAND) {
+	querySelection(obj);
+    }
+
+    /*
+     * $B%-!<F~NO$r85$K(B AAJCODE$B$KJQ49$7!"(BCE$B$X$N%j%/%(%9%H$r9T$&!#(B
+     * $B%j%/%(%9%H7k2L$K4p$E$$$F!"I=<($d%b!<%I$rJQ99$9$k!#(B
+     * $B3NDjJ8;zNs$,$"$C$?>l9g$K$O!"%j%?!<%s$H$7$F!"$=$NJ8;zNs$ND9$5$,(B
+     * $BJV$C$F$/$k!#(B
+     * $B$3$l0J9_$N=hM}$O(B $B2hLL$KI=<($9$k$?$a$NJ*$G$"$k!#(B
+     */
+    wlen = XatokEventControl(obj->atok.comm, event, ks, kbuf, nbytes,
+			     &aajcode, &kanjiStatus, &enableStatus,
+			     &changeStatus, &elseEvent);
+
+    if (!aajcode) {
+	/* Can't convertsion to AAJ CODE */
+	return 0;
+    }
+
+    if (obj->atok.comm->convStatus == M_NOKEYCONV) {
+	convend(obj);
+	return 0;
+    }
+		
+    /*
+     * $B$3$3$+$i2<$O(B kanjiStatus $B$G;XDj$5$l$F$$$k%b!<%I$N=hM}$r(B
+     * $B9T$$!"2hLL$KI=<($9$k!#(B
+     * $B8uJd0lMw!"!"<-=q!"3NDj$J$I$K2r$l$k!#(B
+     *
+     * $BDL>o$N%-!<F~NO$N>l9g(B
+     * $B8uJd0lMwI=<(Cf$N>l9g(B
+     * $B<-=q%f!<%F%#%j%F%#!<I=<(Cf$N>l9g(B
+     */
+    switch(kanjiStatus) {
+    case KRS_UNCHANGED: /* $B%9%k!<3NDj(B */
+	isThrue = 1 ;
+	obj->atok.comm->wlen = 0 ;
+	obj->atok.comm->wbuf[0] = aajcode ;
+	break;
+    case KRS_BACKSPACE:
+    case KRS_SOFTBACKSPACE:
+    case KRS_SOFTCARRIAGERETURN:
+    case KRS_EXTTANGO_OPEN:
+    default:
+	break;
+    }
+    status = 0;
+    if (enableStatus) {
+	if (elseEvent & EVENTB_BEEP) {
+	    bell();
+	}
+	/* $B%b!<%I$NJQ99$,$"$C$?(B */
+	if (changeStatus & ATCHANGEB_MODESTR) {
+	    XtCallCallbackList((Widget)obj, obj->inputConv.modechangecallback,
+			       (XtPointer)NULL);
+	}
+	if (changeStatus & ATCHANGEB_RESULTSTR) {
+	    /* do nothing */
+	}
+	if (changeStatus & ATCHANGEB_COMPSTR) {
+	    /* do nothing */
+	}
+	/* $B<!8uJd%&%#%s%I%&99?7(B */
+	if (changeStatus &
+	    (ATCHANGEB_RECTOPEN | ATCHANGEB_RECTCLOSE | ATCHANGEB_RECTCHANGE))
+	{
+	    /* do nothing */
+	}
+	if (changeStatus & (ATCHANGEB_SYSLSTR | ATCHANGEB_SYSLTOSYSL)) {
+	    /*
+	     * auxSyslineCtrl() $B$N(B return $B$,#00J30$N;~$O!"(B
+	     * $B%7%9%F%`9T$NI=<($,=*N;$N;~$G$"$j!"(B
+	     * $B3NDjJ8;zNs$,B8:_$9$k2DG=@-$,$"$k$N$G(B
+	     * $B%7%9%F%`9T$r>C$7$F$+$i(B
+	     * AuxDisplay()$B$r8F$S=P$9I,MW$,$"$k!#(B
+	     */
+	    status = auxSyslineCtrl(obj->atok.comm,
+				    changeStatus & ATCHANGEB_RESULTSTR);
+	    atokAuxDisplay(obj, M_SYSLINE);
+	    /*
+	    if (!status) {
+		DPRINT(("SYSLINE END\n"));
+		return 0;
+	    }
+	    */
+	}
+    }
+    /*
+     * $B$3$3$+$i2<$O(B $BI=<($N%3%s%H%m!<%k(B
+     * $BF~NO$5$l$?%-!<$K$h$j=hM}$rJ,$1$F$$$k!#(B
+     */
+    if (obj->atok.comm->convStatus & M_CAND) {
+	status = atokCandDisplay(obj, (int)aajcode);
+	if (status < 1) {
+	    return 0;
+	}
+    }
+    /* else */
+    if (obj->atok.comm->convStatus & M_AUX) {
+	status = atokAuxDisplay(obj, obj->atok.comm->convStatus);
+	if (status < 1) {
+	    return;
+	}
+    }
+    else if (obj->atok.comm->convStatus & M_SYSLINE && !status) {
+	status = auxSyslineCtrl(obj->atok.comm,
+				changeStatus & ATCHANGEB_RESULTSTR);
+	atokAuxDisplay(obj, obj->atok.comm->convStatus);
+	if (!status) {
+	    return 0;
+	}
+    }
+    else if (kanjiStatus == XKEY_DICT) {
+	/* $B<-=q%f!<%F%#%j%F%#!<I=<(;~$N%-!<F~NO(B */
+    }
+    /* $B$=$NB>$N>l9g$N%-!<F~NO(B */
+    if (obj->atok.comm->convStatus & M_KEYCONV) {
+	atokDisplay(obj, &kanjiStatus);
+    }
+
+    return isThrue;
+}
+
+static ICString	*
+GetMode(w)
+Widget w;
+{
+    AtokObject obj = (AtokObject)w;
+    _XatokRecPtr acomm = obj->atok.comm;
+    int len;
+    static ICString icstr;
+
+    if (acomm == NULL) return NULL; /* Not connected */
+
+    icstr.data = (char *)XatokGetModeStr(acomm, &len);
+    icstr.nchars = len;
+    icstr.nbytes = icstr.nchars * sizeof(wchar);
+    icstr.attr = ICAttrNormalString;
+
+    return &icstr;
+}
+
+static int
+CursorPos(w, nsegp, ncharp)
+Widget w;
+Cardinal *nsegp;
+Cardinal *ncharp;
+{
+    AtokObject obj = (AtokObject)w;
+    _XatokRecPtr acomm = obj->atok.comm;
+
+    if (acomm == NULL) return 0; /* Not connected */
+
+    return XatokGetSegmentPosition(acomm, nsegp, ncharp);
+}
+
+static int
+NumSegments(w)
+Widget w;
+{
+    AtokObject obj = (AtokObject)w;
+    _XatokRecPtr acomm = obj->atok.comm;
+
+    if (acomm == NULL) return 0; /* Not connected */
+
+    return XatokGetSegmentNumber(acomm);
+}
+
+static ICString *
+GetSegment(w, n)
+Widget w;
+Cardinal n;
+{
+    AtokObject obj = (AtokObject)w;
+    _XatokRecPtr acomm = obj->atok.comm;
+    int len;
+    int attr;
+    static ICString seg;
+
+    if (acomm == NULL) return NULL; /* Not connected */
+
+    seg.data = (char *)XatokGetSegmentRec(acomm, n, &len, &attr);
+    seg.nchars = len;
+    seg.nbytes = seg.nchars * sizeof(wchar);
+    seg.attr = attr;
+
+    return &seg;
+}
+
+/* ARGSUSED */
+static int
+CompareSegment(w, seg1, seg2, n)
+Widget w;
+ICString *seg1;
+ICString *seg2;
+Cardinal *n;
+{
+    wchar *p, *q;
+    int len, nsame;
+    int result = 0;
+
+    if (seg1->attr != seg2->attr) result |= ICAttrChanged;
+
+    len = seg1->nchars > seg2->nchars ? seg2->nchars : seg1->nchars;
+    nsame = 0;
+    p = (wchar *)seg1->data;
+    q = (wchar *)seg2->data;
+    while (nsame < len && *p++ == *q++) nsame++;
+
+    if (nsame != len || len != seg1->nchars || len != seg2->nchars)
+	result |= ICStringChanged;
+
+    if (n) *n = nsame;
+
+    return result;
+}
+
+static ICString *
+GetItemList(w, n)
+Widget w;
+Cardinal *n;
+{
+    AtokObject obj = (AtokObject)w;
+
+#ifdef CAND_PAGE
+    *n = (CAND_ROWS * CAND_COLS) + 1; /* +1 $B$O(B $B8uJd?t(B */
+#else
+    *n = obj->atok.nbr_of_cand;
+#endif /* CAND_PAGE */
+
+    return obj->atok.cand_lists_ics;
+}
+
+static int
+SelectItem(w, n)
+Widget w;
+int n;
+{
+    AtokObject obj = (AtokObject)w;
+    _XatokRecPtr acomm = obj->atok.comm;
+    int changed = FALSE;
+    int status = 0;
+
+    if (acomm == NULL) return -1; /* Not connected */
+
+    if (n >= 0) obj->atok.selected_cand = n;
+
+    /* ATOK $B$N3NDj(BFUNC$B$r8F$S=P$9!#(B */
+    if (changed) {
+	XtCallCallbackList((Widget)obj, obj->inputConv.fixcallback,
+			   (XtPointer)NULL);
+	/* ATOK $B$N%P%C%U%!$b(BFLUSH$B$9$k!#(B */
+	XtCallCallbackList((Widget)obj, obj->inputConv.textchangecallback,
+			   (XtPointer)NULL);
+    }
+
+    return status;
+}
+
+static int
+ConvertedString(w, encoding, format, length, string)
+Widget w;
+Atom *encoding;
+int *format;
+int *length;
+XtPointer *string;
+{
+    AtokObject obj = (AtokObject)w;
+    _XatokRecPtr acomm = obj->atok.comm;
+    wchar *wbuf, *wp;
+    int len, wlen;
+    extern int convJWStoCT();
+
+    if (acomm == NULL || acomm->nbr_of_seg == 0 || acomm->offset == 0)
+	return -1;
+
+    wlen = acomm->segments[acomm->offset -1].length;
+    wbuf = acomm->segments[acomm->offset -1].string;
+
+    /*
+     * Atok $B%*%V%8%'%/%H$O(B COMPOUND_TEXT $B%(%s%3!<%G%#%s%0$7$+%5%]!<%H$7$J$$(B
+     * COMPOUND_TEXT $B$KJQ49$9$k(B
+     */
+    *encoding = XA_COMPOUND_TEXT( XtDisplayOfObject(( Widget )obj ));
+    *format = 8;
+
+    /* COMPOUND_TEXT $B$O(B \r $B$,Aw$l$J$$$N$G(B \n $B$KJQ49$7$F$*$/(B */
+    for (wp = wbuf; *wp != 0; wp++ ) {
+	if (*wp == '\r') *wp = '\n';
+    }
+
+    *length = len = convJWStoCT(wbuf, (unsigned char *)NULL, 0);
+    *string = XtMalloc(len + 1);
+    (void)convJWStoCT(wbuf, (unsigned char *)*string, 0);
+
+    XatokShiftLeftAll(acomm);
+
+    return 0;
+}
+
+static int
+ClearConversion(w)
+Widget w;
+{
+    AtokObject obj = (AtokObject)w;
+    _XatokRecPtr acomm = obj->atok.comm;
+
+    if (acomm == NULL) return -1; /* Not connected */
+
+    XatokClearBuffer(acomm);
+    XtCallCallbackList((Widget)obj, obj->inputConv.textchangecallback,
+		       (XtPointer)NULL);
+    return 0;
+}
+
+static ICString *
+GetAuxSegments(w, n, ns, nc)
+Widget w;
+Cardinal *n, *ns, *nc;
+{
+    AtokObject obj = (AtokObject)w;
+    Cardinal nseg, nchar;
+
+    if (obj->atok.comm == NULL) return NULL; /* Not connected */
+
+    if (n) {
+	*n = obj->atok.aux_nseg;
+    }
+
+    if (obj->atok.aux_curseg < obj->atok.aux_nseg) {
+	nseg = obj->atok.aux_curseg;
+	nchar = 0;
+    }
+    else {
+	nseg = 0;
+	nchar = obj->atok.aux_length[0];
+    }
+    if (ns) {
+	*ns = nseg;
+    }
+    if (nc) {
+	*nc = nchar;
+    }
+
+    return obj->atok.aux_ics;
+}
+
+/* ARGSUSED */
+static int
+PreeditString(w, segn, offset, encoding, format, length, string)
+Widget w;
+int segn;
+int offset;
+Atom *encoding;
+int *format;
+int *length;
+XtPointer *string;
+{
+    AtokObject obj = (AtokObject)w;
+    _XatokRecPtr acomm = obj->atok.comm;
+    int i;
+    wchar *wbuf, *wp;
+    int	 len, wlen;
+    extern int convJWStoCT();
+
+    if (acomm == NULL) return -1;
+    if (segn < acomm->nbr_of_seg && offset >= acomm->segments[segn].length) {
+	/* $B%;%0%a%s%H$N:G8e(B */
+	++segn;
+	offset = 0;
+    }
+    if (segn >= acomm->nbr_of_seg || offset >= acomm->segments[segn].length) {
+	/* $B:o=|$5$l$?(B */
+	*encoding = XA_COMPOUND_TEXT(XtDisplayOfObject(w));
+	*format = 8;
+	*length = 0;
+	*string = (XtPointer)XtMalloc(1);
+	return 0;
+    }
+
+    wlen = 0;
+    for (i = segn; i < acomm->nbr_of_seg; i++) {
+	wlen += acomm->segments[i].length;
+    }
+    wlen -= offset;
+
+    wp = wbuf = (wchar *)XtMalloc((wlen + 1) * sizeof(wchar));
+    len = acomm->segments[segn].length - offset;
+    (void)bcopy((char *)(acomm->segments[segn].string + offset),
+		(char *)wp,
+		sizeof(wchar) * len);
+    wp += len;
+    for (i = segn + 1; i < acomm->nbr_of_seg; i++) {
+	len = acomm->segments[i].length;
+	(void)bcopy((char *)acomm->segments[i].string,
+		    (char *)wp,
+		    sizeof(wchar) * len);
+	wp += len;
+    }
+    wbuf[wlen] = 0;
+
+    /*
+     * Atok $B%*%V%8%'%/%H$O(B COMPOUND_TEXT $B%(%s%3!<%G%#%s%0$7$+%5%]!<%H$7$J$$(B
+     * COMPOUND_TEXT $B$KJQ49$9$k(B
+     */
+    *encoding = XA_COMPOUND_TEXT(XtDisplayOfObject((Widget)obj));
+    *format = 8;
+
+    /* COMPOUND_TEXT $B$O(B \r $B$,Aw$l$J$$$N$G(B \n $B$KJQ49$7$F$*$/(B */
+    for (wp = wbuf; *wp != 0; wp++) {
+	if (*wp == '\r') *wp = '\n';
+    }
+
+    *length = len = convJWStoCT(wbuf, (unsigned char *)NULL, 0);
+    *string = (XtPointer)XtMalloc(len + 1);
+    (void)convJWStoCT(wbuf, (unsigned char *)*string, 0);
+
+    /* wbuf $B$r(B free $B$7$F$*$/(B */
+    XtFree((char *)wbuf);
+
+    return 0;
+}
+
+/* ARGSUSED */
+static int
+StatusString(w, encoding, format, length, string, nchars)
+Widget w;
+Atom *encoding;
+int *format;
+int *length;
+XtPointer *string;
+int *nchars;
+{
+    ICString *seg;
+    wchar *wbuf, *wp;
+    int len, wlen;
+    extern int convJWStoCT();
+
+    seg = GetMode(w);
+    if (seg == NULL) {
+	*length = *nchars = 0;
+	return -1;
+    }
+
+    wlen = seg->nchars;
+    if (wlen <= 0) {
+	*length = *nchars = 0;
+	return -1;
+    }
+
+    /*
+     * data $B$KF~$C$F$$$kJQ49%F%-%9%H$O(B null $B%?!<%_%M!<%H$5$l$F$$$J$$$+$b(B
+     * $B$7$l$J$$$N$G!"$^$:%3%T!<$7$F(B null $B%?!<%_%M!<%H$9$k(B
+     */
+    wbuf = (wchar *)XtMalloc((wlen + 1) * sizeof(wchar));
+    (void)bcopy(seg->data, (char *)wbuf, sizeof(wchar) * wlen);
+    wbuf[wlen] = 0;
+
+    /*
+     * Canna $B%*%V%8%'%/%H$O(B COMPOUND_TEXT $B%(%s%3!<%G%#%s%0$7$+%5%]!<%H$7$J$$(B
+     * COMPOUND_TEXT $B$KJQ49$9$k(B
+     */
+    *encoding = XA_COMPOUND_TEXT(XtDisplayOfObject(w));
+    *format = 8;
+
+    /* COMPOUND_TEXT $B$O(B \r $B$,Aw$l$J$$$N$G(B \n $B$KJQ49$7$F$*$/(B */
+    for (wp = wbuf; *wp != 0; wp++) {
+	if (*wp == '\r') *wp = '\n';
+    }
+
+    *length = len = convJWStoCT(wbuf, (unsigned char *)NULL, 0);
+    *string = XtMalloc(len + 1);
+    (void)convJWStoCT(wbuf, (unsigned char *)*string, 0);
+    *nchars = seg->nchars;
+
+    /* wbuf $B$r(B free $B$7$F$*$/(B */
+    XtFree((char *)wbuf);
+
+    return 0;
+}
+
+/*
+ * Private FUNCTIONS
+ */
+
+static int
+bell()
+{
+    if (displaybell) {
+	XBell(displaybell, 0);
+    }
+    return 0;
+}
+
+static void
+fix(obj)
+AtokObject obj;
+{
+    /* $B3NDj$N=hM}(B */
+    XtCallCallbackList((Widget)obj, obj->inputConv.fixcallback,
+		       (XtPointer)NULL);	/* $B!)!)!)(B */
+}
+
+static void
+fixProcForAtok(obj, fixedstr, fixedlen)
+AtokObject obj;
+wchar *fixedstr;
+int fixedlen;
+{
+    int offset;
+    int i;
+
+    offset = obj->atok.comm->offset;
+
+    if (offset < ATOK_NSEG) {
+	XatokShiftRight(obj->atok.comm);
+	offset = obj->atok.comm->offset;
+    }
+    else {
+	XatokShiftLeft(obj->atok.comm);
+    }
+    copyInWchar(fixedstr, fixedlen,
+		&(obj->atok.comm->segments[offset-1].string),
+		&(obj->atok.comm->segments[offset-1].size),
+		&(obj->atok.comm->segments[offset-1].length));
+}
+
+/*
+ * $BJQ49=*N;(B
+ */
+static void
+convend(obj)
+AtokObject obj;
+{
+    XtCallCallbackList((Widget)obj, obj->inputConv.endcallback,
+		       (XtPointer)NULL);
+}
+
+/*
+ * keeping list of objects
+ */
+typedef struct _oblist_ {
+    AtokObject obj;
+    struct _oblist_ *next;
+} ObjRec;
+
+static ObjRec *ObjList = NULL;
+
+static void
+addObject(obj, sock, clntid, isConnect)
+AtokObject obj;
+int sock;
+int clntid;
+int isConnect;
+{
+    ObjRec *objp = XtNew(ObjRec);
+    _XatokRecPtr acomm;
+    char buf[256];
+
+    objp->obj = obj;
+    objp->next = ObjList;
+    ObjList = objp;
+
+    acomm = objp->obj->atok.comm;
+    /* bzero(acomm, sizeof(_XatokRecPtr)); */
+
+    acomm->convStatus = M_KEYCONV;	/* $B4A;zJQ49(B ON $B$N%b!<%I$K@_Dj(B */
+    /* acomm->mode.dsp = 1;	/* $B%5!<%P$+$i<hF@$9$k;v$R$i$,$J(B $B%b!<%I$K@_Dj(B */
+
+    if (isConnect) {
+	atokCEOpen(acomm->sock,
+		   clntid, objp->obj->atok.comm
+		   /*
+		   &objp->obj->atok.comm->NETrqst,
+		   &objp->obj->atok.comm->NETrslt);
+		   */
+		   );
+    }
+}
+
+static void
+deleteObject(obj)
+AtokObject obj;
+{
+    ObjRec *objp, *objp0;
+
+    for (objp0 = NULL, objp = ObjList;
+	 objp != NULL;
+	 objp0 = objp, objp = objp->next) {
+	if (objp->obj == obj) {
+	    if (objp0 == NULL) {
+		ObjList = objp->next;
+	    } else {
+		objp0->next = objp->next;
+	    }
+	    XtFree((char *)objp);
+	    return;
+	}
+    }
+}
+
+static void
+atokDisplay(obj, kstat)
+AtokObject obj;
+int *kstat;
+{
+    wchar *wbuf = obj->atok.comm->wbuf;
+    int len = obj->atok.comm->wlen;
+
+    /*
+     * len > 0 $B$N;~$O!"(B atokClntEvent $B$GJQ49$r9T$C$?7k2L!"(B
+     * $B3NDjJ8;zNs$,$"$k;~$G$"$k!#(B
+     */
+    if (len > 0) {
+	/*
+	XtCallCallbackList((Widget)obj, obj->inputConv.fixcallback,
+			   (XtPointer)NULL);
+	*/
+	fixProcForAtok(obj, wbuf, len);
+	fix(obj);
+    }
+    changeTextForAtok(obj, kstat);
+
+    /*
+     * $BI=<($9$kFbMF(B($B%F%-%9%H(B)$B$,JQ$o$C$F$$$?>l9g$K$O!"I=<($7$J$*$9!#(B
+     */
+    if ( obj->atok.textchanged ) {
+	XtCallCallbackList((Widget)obj, obj->inputConv.textchangecallback,
+			   (XtPointer)NULL);
+	obj->atok.textchanged = False;
+    }
+}
+
+static int
+atokCandDisplay(obj, aajcode)
+AtokObject obj;
+int aajcode;
+{
+    int	status = 0;
+
+    /*
+     * $B8uJd%&%$%s%I%&I=<(;~$N%-!<F~NO(B
+     * $B%-!<$O(B key.c $B$GDj5A$7$F$$$k$b$N$r;HMQ$9$k;v!#(B
+     */
+    switch( aajcode ) {
+    case XFER:
+#ifdef CAND_PAGE
+	startSelection(obj, 1);
+#else
+	startSelection(obj, 0);
+#endif
+	break;
+    case SPACE:
+    case RIGHT:
+    case CTR_F:
+#ifdef	CAND_PAGE
+	moveRight(obj, 1);
+#else
+	moveRight(obj, 0);
+#endif	
+	break;
+    case LEFT:
+    case CTR_B:
+#ifdef	CAND_PAGE
+	moveLeft(obj, 1);
+#else
+	moveLeft(obj, 0);
+#endif
+	break;
+    case UP:
+    case CTR_P:
+	moveSelection(obj, ICMoveUp);
+	break;
+    case DOWN:
+    case CTR_N:
+	moveSelection(obj, ICMoveDown);
+	break;
+    case CTR_E:
+	moveSelection(obj, ICMoveLast);
+	break;
+    case CTR_A:
+	moveSelection(obj, ICMoveFirst);
+	break;
+    case CR:
+    case VKEY|FUNC_KAKU_BUBUN:
+	endSelection(obj, FALSE, TRUE);
+	status = 1;
+	break;
+    case CTR_G:
+	endSelection(obj, TRUE, TRUE);
+	obj->atok.cur_cand = -1;
+	break;
+    case CTR_DEL:	/* 616 */
+    case EESC:
+    case FUNC_CNV_CANCL:	/* 1999/06/30 */
+	endSelection(obj, TRUE, TRUE);
+	obj->atok.cur_cand = -1;
+	status = 1;
+	break;
+    case 0:
+    default:
+	break;
+    }
+    return status;
+}
+	
+static int
+atokAuxDisplay(obj, op)
+AtokObject obj;
+opMode op;
+{
+    ICAuxControlArg arg;
+    int status = 1;
+
+    switch (obj->atok.comm->menuStatus) {
+    case ICAuxEnd :
+	if (obj->atok.comm->convStatus & op) {
+	    obj->atok.comm->convStatus ^= op;
+	}
+	obj->atok.comm->convStatus |= M_KEYCONV;
+	status = 0;
+    case ICAuxStart :
+    case ICAuxChange :
+	arg.command = obj->atok.comm->menuStatus;
+	break;
+    default :
+	return -1;
+    }
+    if (arg.command != ICAuxEnd) {
+	changeTextForAtokAUX(&obj->atok);
+    }
+
+    XtCallCallbackList((Widget)obj, obj->inputConv.auxcallback,
+		       (XtPointer)&arg);
+	
+    return status;
+}
+
+/*
+ * Utils
+ */
+/*
+ * $B8uJd0lMwI=<($N4X?t74(B
+ */
+/*
+ * $B40(B
+ */
+static void
+moveLeft(obj, cand_page)
+AtokObject obj;
+int cand_page;
+{
+    _XatokRecPtr comm;
+    int pgMax;
+    int move = TRUE;
+    ICSelectionControlArg arg;
+    int kohoNum;
+
+    if (!cand_page) {
+	moveSelection(obj, ICMoveLeft);
+	return;
+    }
+    comm = obj->atok.comm;
+
+    querySelection(obj);
+    pgMax = comm->kohoMax;
+
+    if (comm->kohoPos == 0) {
+	/*
+	 *  $B:G8e$N%Z!<%8$rI=<($7$F$$$k!#(B
+	 */
+	if (comm->kohoCurPage + 1 == comm->kohoPageNbr) {
+		/*
+		 * $B:G8e$N%Z!<%8$@$,!":G=i$N%Z!<%8$G$"$k(B
+		 * $B$7$?$,$C$FJQ99$9$k%Z!<%8$O$J$$!#(B
+		 */
+		if (comm->kohoCurPage == 0) {
+		    move = TRUE;
+		}
+		else {
+		    comm->kohoCurPage--;
+		    move = FALSE;
+		}
+	}
+	else if (comm->kohoCurPage == 0) {
+	    comm->kohoCurPage = comm->kohoPageNbr - 1;
+	    move = FALSE;
+	}
+	else  {
+	    comm->kohoCurPage--;
+	    move = FALSE;
+	}
+    }
+
+    if (move == FALSE) {
+	endSelection(obj, FALSE, FALSE);
+	kohoNum = comm->kohoNum2 > (comm->kohoCurPage + 1) * pgMax ?
+		pgMax - 1 : comm->kohoNum2 - (comm->kohoCurPage * pgMax)  - 1;
+	makeCandList(obj, obj->atok.cand_lists_ics, pgMax, pgMax + 1,
+		     comm->kohoCurPage, kohoNum, 1);
+	return;
+    }
+
+    moveSelection(obj, ICMoveLeft);
+}
+	
+static void
+moveRight(obj, cand_page)
+AtokObject obj;
+int cand_page;
+{
+    _XatokRecPtr comm;
+    int pgMax;
+    int move = TRUE;
+    int kohoNum;
+    ICSelectionControlArg arg;
+
+    if (!cand_page) {
+	moveSelection(obj, ICMoveRight);
+	return;
+    }
+    comm = obj->atok.comm;
+
+    querySelection(obj);
+    /* pgMax = CAND_COLS * CAND_ROWS; */
+    pgMax = comm->kohoMax;
+
+    if (comm->kohoPos == pgMax - 1) {
+	if (comm->kohoNum2 > (comm->kohoCurPage + 1) * pgMax) {
+	    comm->kohoCurPage++;
+	}
+	else {
+	    comm->kohoCurPage = 0;
+	}
+	move = FALSE;
+	comm->kohoPos = 0;
+    }
+    else if (comm->kohoPos == comm->kohoNum2 - (comm->kohoCurPage * pgMax) - 1)
+    {
+	/* if (comm->kohoCurPage != 0) move = FALSE; */
+	comm->kohoCurPage = 0;
+	move = FALSE;
+	comm->kohoPos = 0;
+    }
+    if (move == FALSE) {
+	endSelection(obj, FALSE, FALSE);
+	makeCandList(obj, obj->atok.cand_lists_ics, pgMax, pgMax + 1,
+		     comm->kohoCurPage, 0, 1);
+	comm->kohoPos = 0;
+	return;
+
+    }
+
+    moveSelection( obj, ICMoveRight );
+}
+		
+static void
+setSelection(obj, kohoNum)
+AtokObject obj;
+int kohoNum;
+{
+    ICSelectionControlArg arg;
+
+    /* Set current candidate */
+    arg.command = ICSelectionSet;
+    arg.u.current_item = kohoNum;	/* $B8uJd(BNO$B$r@_Dj$9$k;v(B */
+    XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
+		       (XtPointer)&arg);
+}
+
+static void
+moveSelection(obj, dir)
+AtokObject obj;
+int dir;
+{
+    ICSelectionControlArg arg;
+
+    arg.command = ICSelectionMove;
+    arg.u.dir = dir;
+    XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
+		       (XtPointer)&arg);
+    querySelection(obj);
+}
+
+static void
+querySelection(obj)
+AtokObject obj;
+{
+    ICSelectionControlArg arg;
+    arg.command = ICSelectionGet;
+    arg.u.current_item = -1;
+    XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
+		       (XtPointer)&arg);
+
+    obj->atok.selected_cand = arg.u.current_item;
+    obj->atok.comm->kohoPos = arg.u.current_item;
+}
+
+static void
+endSelection(obj, isabort, modeChange)
+AtokObject obj;
+int isabort;
+int modeChange;
+{
+    ICSelectionControlArg arg;
+    int selected;
+
+    if (modeChange) {
+	obj->atok.comm->convStatus ^= M_CAND;
+    }
+    arg.command = ICSelectionEnd;
+    arg.u.current_item = -1;
+    XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
+		       (XtPointer)&arg);
+
+    if (!isabort && (selected = arg.u.current_item) >= 0) {
+	insertSelection(obj, selected);
+    }
+}
+
+static void
+insertSelection(obj, selected)
+AtokObject obj;
+int selected;
+{
+    obj->atok.cur_cand = selected;
+    obj->atok.comm->kohoPos = selected;
+
+    /*
+     * ATOK CE $B$KA*Br$5$l$?$3$H$rDLCN$9$kI,MW$"$j(B
+     * API$B$,2r$j<!Bh(B $B%3!<%G%#%s%0(B
+     */
+    return;
+}
+
+/*
+ * $B8uJd%j%9%H$N$?$a$N%P%C%U%!$rMQ0U$9$k!#(B
+ */
+static int
+allocCandList(obj, nbr, cur)
+AtokObject obj;
+int nbr;
+int *cur;
+{
+    ICString *p;
+
+    /*
+     * $B4{$KI,MW$J%5%$%:0J>e(B $B3NJ]$5$l$F$$$k>l9g$K$O2?$b$7$J$$!#(B
+     */
+    if (nbr <= obj->atok.cand_list_size) {
+	return nbr;
+    }
+
+    /*
+     * $B$^$@(B $B3NJ]$5$l$F$$$J$$;~$K$O!"?75,$K!"4{$K(B
+     * $B3NJ]$5$l$F$$$kNN0h$r9-$2$?$$;~$K$O(B realloc $B$9$k!#(B
+     */
+    if (obj->atok.cand_list_size == 0) {
+	p = (ICString *)XtMalloc(nbr * sizeof(ICString));
+    }
+    else {
+	p = (ICString *)XtRealloc((char *)obj->atok.cand_lists_ics,
+				  nbr * sizeof(ICString));
+    }
+    obj->atok.cand_lists_ics = p;
+    obj->atok.cand_list_size = nbr;
+    *cur = 0;
+
+    return nbr;
+}
+
+/*
+ * $B%-!<F~NO8e!"(BCE$B$K$h$C$FJQ49$5$l$?%G!<%?$r2hLL$KI=<($9$k$?$a$N(B
+ * $B%3%s%H%m!<%k$r9T$&=hM}$N%a%$%s$G$"$k!#(B
+ * $BI=<(%;%0%a%s%H$N7W;;!"%,%$%I%i%$%s$J$I$NI=<(J8;zNs$N:n@.$r9T$C$F$$$k!#(B
+ *
+ * $B$3$3$G9T$&$N$OBg$-$/J,$1$F#3$D$N=hM}$G$"$k!#(B
+ *	1 $BF~NOESCf$NJ8;zNs$N(BECHO BACK
+ *	2 $BF~NO%b!<%I$,JQ49$5$l$?;~$N(B $BF~NO%b!<%II=<(J8;zNs$N@_Dj(B
+ *	3 $B0lMwI=<($7$F$$$k;~$N(B
+ */
+static int
+changeTextForAtok(obj, kstat)
+AtokObject obj;
+int *kstat;
+{
+    _XatokRecPtr acomm = obj->atok.comm;
+    int remain;
+    int offset = acomm->offset;
+    int len = acomm->echoLen;
+    int i;
+    wchar *wp;
+
+    if (len == 0) {
+	acomm->cur_seg = offset;
+	acomm->nbr_of_seg = offset;
+	acomm->segments[offset+0].length
+		= acomm->segments[offset+1].length
+		= acomm->segments[offset+2].length = 0;
+	if (*kstat == XKEY_FIX) {
+	    obj->atok.textchanged = TRUE;
+	}
+	obj->atok.textchanged = TRUE;
+    }
+    else if (len > 0) {
+	/* $B%-!<F~NO$,$"$C$?>l9g(B */
+	acomm->segments[offset+1].length
+		= acomm->segments[offset+2].length = 0;
+	if (acomm->revLen > 0) {
+	    if ( acomm->revPos == 0 ) {
+		remain = acomm->echoLen - acomm->revLen;
+		/*
+		 * REVERSE :
+		 * REVERSE : NORMAL
+		 * $BH?E>I=<($,#1%;%0%a%s%HL\$N>l9g$K$O(B
+		 * str[0] $B$KJ8;z$rB-$9(B
+		 */
+		copyInWchar(acomm->echoStr, acomm->revLen,
+			    &(acomm->segments[offset+0].string),
+			    &(acomm->segments[offset+0].size),
+			    &(acomm->segments[offset+0].length));
+		acomm->cur_seg = offset;
+		acomm->nbr_of_seg = offset + 1;
+		/*
+		 * $B#2%;%0%a%s%HL\$,B8:_$9$k>l9g$K$O!"(B
+		 * $B#2%;%0%a%s%HL\$b@_Dj$9$k!#(B
+		 */
+		if (remain) {
+		    copyInWchar(acomm->echoStr + acomm->revLen, remain,
+				&(acomm->segments[offset+1].string),
+				&(acomm->segments[offset+1].size),
+				&(acomm->segments[offset+1].length));
+		    acomm->nbr_of_seg = offset+2;
+		}
+	    }
+	    else {
+		/*
+		 * NORMAL : REVERSE
+		 * NORAML : REVERSE : NORMAL
+		 *
+		 * $B$3$3$K$/$k$H$-$O(B $B#2HVL\0J9_$J$N$G(B str0,
+		 * str1  $B$O@dBP$KB8:_$9$k!#(B
+		 * $BH?E>I=<($,$"$j!"3n$D#1%;%0%a%s%H$,%N!<%^%k(B
+		 * $BI=<($H$$$&;v$O#2%;%0%a%s%HL\$,H?E>I=<($G(B
+		 * $B$"$k!#(B
+		 */
+		remain = acomm->echoLen - acomm->revPos - acomm->revLen;
+		copyInWchar(acomm->echoStr, acomm->revPos,
+			    &(acomm->segments[offset+0].string),
+			    &(acomm->segments[offset+0].size),
+			    &(acomm->segments[offset+0].length));
+		copyInWchar(acomm->echoStr + acomm->revPos, acomm->revLen,
+			    &(acomm->segments[offset+1].string),
+			    &(acomm->segments[offset+1].size),
+			    &(acomm->segments[offset+1].length));
+		acomm->cur_seg = offset+1;
+		acomm->nbr_of_seg = offset+2;
+		/*
+		 * NORMAL : REVERSE : NORMAL $B$N>l9g(B
+		 */
+		if (remain){
+		    copyInWchar(acomm->echoStr + acomm->revPos + acomm->revLen,
+				remain,
+				&(acomm->segments[offset+2].string),
+				&(acomm->segments[offset+2].size),
+				&(acomm->segments[offset+2].length));
+		    acomm->nbr_of_seg = offset+3;
+		}
+	    }
+	}
+	else {
+	    /*
+	     * NORMAL $BI=<((BONLY
+	     */
+	    copyInWchar(acomm->echoStr, acomm->echoLen,
+			&(acomm->segments[offset+0].string),
+			&(acomm->segments[offset+0].size),
+			&(acomm->segments[offset+0].length));
+	    acomm->segments[1].length = acomm->segments[2].length = 0;
+	    acomm->nbr_of_seg = offset+1;
+	    acomm->cur_seg = offset+1;
+	}
+	obj->atok.textchanged = TRUE;
+    }
+}
+
+static int
+changeTextForAtokAUX(obj)
+AtokPart *obj;
+{
+    int remain;
+    int len;
+    int i;
+    _XatokRecPtr acomm = obj->comm;
+
+    /*
+     * $B$3$3$G(B AUX $B$KI=<($9$kJ8;z$r:n@.$9$k!#(B
+     */
+    if (obj->comm->convStatus & M_SYSLINE) {
+	auxSyslineString(acomm, acomm->curAux,
+			 acomm->aux_echoStr, &acomm->aux_echoLen,
+			 &acomm->aux_revLen, &acomm->aux_revPos);
+    }
+    else {
+	auxMenuString(acomm, acomm->curAux,
+		      acomm->aux_echoStr, &acomm->aux_echoLen,
+		      &acomm->aux_revLen, &acomm->aux_revPos);
+    }
+    /*
+     * $BI=<($9$kJ8;z$,$J$$>l9g$O%j%?!<%s$9$k!#(B
+     */
+    if ( acomm->aux_echoLen == 0 ) {
+	obj->aux_curseg = 0;
+	obj->aux_nseg = 0;
+	obj->aux_length[0] = obj->aux_length[1] = obj->aux_length[2] = 0;
+	return 0;
+    }
+    obj->aux_length[1] = obj->aux_length[2] = 0;
+    if (acomm->aux_revLen > 0) {
+	if (acomm->aux_revPos == 0) {
+	    remain = acomm->aux_echoLen - acomm->aux_revLen;
+	    copyInWchar(acomm->aux_echoStr, acomm->aux_revLen,
+			&obj->aux_string[0],
+			&obj->aux_size[0],
+			&obj->aux_length[0]);
+	    obj->aux_curseg = 0;
+	    obj->aux_nseg = 1;
+	    /*
+	     * $B#2%;%0%a%s%HL\$,B8:_$9$k>l9g$K$O!"(B
+	     * $B#2%;%0%a%s%HL\$b@_Dj$9$k!#(B
+	     */
+	    if (remain) {
+		copyInWchar(acomm->aux_echoStr + acomm->aux_revLen, remain,
+			    &obj->aux_string[1],
+			    &obj->aux_size[1],
+			    &obj->aux_length[1]);
+		obj->aux_nseg = 2;
+	    }
+	}
+	else {
+	    /*
+	     * NORMAL : REVERSE
+	     * NORAML : REVERSE : NORMAL
+	     *
+	     * $B$3$3$K$/$k$H$-$O(B $B#2HVL\0J9_$J$N$G(B str0,
+	     * str1  $B$O@dBP$KB8:_$9$k!#(B
+	     * $BH?E>I=<($,$"$j!"3n$D#1%;%0%a%s%H$,%N!<%^%k(B
+	     * $BI=<($H$$$&;v$O#2%;%0%a%s%HL\$,H?E>I=<($G(B
+	     * $B$"$k!#(B
+	     */
+	    remain = acomm->aux_echoLen - acomm->aux_revPos - acomm->aux_revLen;
+	    copyInWchar(acomm->aux_echoStr, acomm->aux_revPos,
+			&obj->aux_string[0],
+			&obj->aux_size[0],
+			&obj->aux_length[0]);
+	    copyInWchar(acomm->aux_echoStr + acomm->aux_revPos,
+			acomm->aux_revLen,
+			&obj->aux_string[1],
+			&obj->aux_size[1],
+			&obj->aux_length[1]);
+	    obj->aux_curseg = 1;
+	    obj->aux_nseg = 2;
+	    /*
+	     * NORMAL : REVERSE : NORMAL $B$N>l9g(B
+	     */
+	    if (remain) {
+		copyInWchar(acomm->aux_echoStr + acomm->aux_revPos
+							+ acomm->aux_revLen,
+			    remain,
+			    &obj->aux_string[2],
+			    &obj->aux_size[2],
+			    &obj->aux_length[2] );
+		obj->aux_nseg = 3;
+	    }
+	}
+    }
+    else {
+	/*
+	 * NORMAL $BI=<((BONLY
+	 */
+	copyInWchar(acomm->aux_echoStr, acomm->aux_echoLen,
+		    &obj->aux_string[0],
+		    &obj->aux_size[0],
+		    &obj->aux_length[0]);
+	obj->aux_length[1] = obj->aux_length[1] = 0;
+	obj->aux_nseg = 1;
+	obj->aux_curseg = 1;
+    }
+
+    for (i = 0; i < obj->aux_nseg; i++) {
+	obj->aux_ics[i].data = (char *)obj->aux_string[i];
+	obj->aux_ics[i].nchars = obj->aux_length[i];
+	obj->aux_ics[i].nbytes = obj->aux_length[i] * sizeof(wchar);
+	obj->aux_ics[i].attr = ICAttrConverted;
+    }
+    if (obj->aux_curseg < obj->aux_nseg) {
+	obj->aux_ics[obj->aux_curseg].attr |= ICAttrCurrentSegment;
+    }
+    return obj->aux_nseg;
+}
+
+/*
+ * $B8uJdJ8;zNs4X78$N%=!<%9(B
+ */
+
+/* Page */
+/*
+ * [$B4X?tL>(B]
+ *		()
+ * [$BI=Bj(B]
+ *		
+ * [$B8F=P7A<0(B]
+ *		
+ * [$B0z?t(B]
+ *		$B7?(B        : $BL>(B       $B>N(B   : IO : $B@b(B      $BL@(B
+ *	
+ *	
+ * [$BJV$jCM(B]
+ *		
+ * [$B;HMQ4X?t(B]
+ *	
+ * [$B5!G=(B]
+ *	Event $B$,H/@8$7$F!"(B CE$B$h$j(B $B8uJd%j%9%H$,<hF@$7$?8e$KI=<($r(B
+ *	 $B3+;O$9$k;~$K8F$S=P$5$l$k!#(B
+ *
+ */
+static void
+startSelection(obj, cand_page)
+AtokObject obj;
+int cand_page;
+{
+    _XatokRecPtr comm = obj->atok.comm;
+    ICString *icsp;
+    int i, n;
+    int pgMax;
+    int oldSize;
+
+    n = obj->atok.nbr_of_cand = comm->kohoNum2;
+    if (cand_page) {
+	pgMax = CAND_COLS * CAND_ROWS;
+    }
+    else {
+	pgMax = n;
+    }
+    comm->kohoMax = pgMax;
+
+    comm->kohoPageNbr = (comm->kohoNum2 + pgMax - 1) / pgMax;
+    comm->kohoCurPage = 0;		/* $B%Z!<%8$O#0$+$i;O$^$k!#(B*/
+    /* comm->kohoPos = 1;		/* ATOKCE $B$N%j%?!<%s$r@_Dj(B */
+
+    /*
+     * $B$^$:$O(B $B8uJd$r@_Dj$9$k(BICSString $B$N%a%b%j!<$r3NJ]$7$F!"(B
+     * $B=i4|2=$9$k!#(B
+     */
+    oldSize = obj->atok.cand_list_size;
+    if (cand_page) {
+	/*
+	 * $B8uJdI=<($N:GBg?t$,7h$^$C$F$$$k>l9g$O!"(B
+	 * $B8uJd$N$?$a$N(BICS $B$,<hF@$5$l$F$$$k$+!"$$$J$$$+$N>l9g$7$+$J$$(B
+	 */
+	n = pgMax + 1;		/* +1 $B$O8uJdHV9fI=<(MQ(B */
+	if (obj->atok.cand_list_size == 0) {
+	    icsp = (ICString *)XtMalloc(n * sizeof(ICString));
+	    obj->atok.cand_list_size = n;
+	    obj->atok.cand_lists_ics = icsp;
+	}
+    }
+    else {
+	if (obj->atok.cand_list_size == 0) {
+	    icsp = (ICString *)XtMalloc(n * sizeof(ICString));
+	    obj->atok.cand_list_size = n;
+	    obj->atok.cand_lists_ics = icsp;
+	}
+	else if (obj->atok.cand_list_size < n) {
+	    icsp = (ICString *)XtRealloc((char *)obj->atok.cand_lists_ics,
+					 n * sizeof(ICString));
+	    obj->atok.cand_list_size = n;
+	    obj->atok.cand_lists_ics = icsp;
+	}
+	else {
+	    icsp = obj->atok.cand_lists_ics;
+	}
+    }
+
+    /*
+     * $B<hF@$5$l$F$$$k8uJd$r@_Dj$9$k!#(B
+     */
+    icsp = obj->atok.cand_lists_ics;
+#ifdef CAND_PAGE
+    makeCandList(obj, icsp, pgMax, n, comm->kohoPos / pgMax, comm->kohoPos, 1);
+#else
+    makeCandList(obj, icsp, pgMax, n, comm->kohoPos / pgMax, comm->kohoPos, 0);
+#endif
+}
+
+static int
+makeCandList(obj, icsp, pgMax, icsNum, page, kohoNum, cand_page)
+AtokObject obj;
+ICString *icsp;	/* $BI=<(MQ%G!<%?(B */
+int pgMax;	/* $B#1%Z!<%8$N:GBg?t(B */
+int icsNum;
+int page;	/* $BI=<($9$k%Z!<%8(B */
+int kohoNum;
+int cand_page;
+{
+    _XatokRecPtr comm = obj->atok.comm;
+    int i, j, n;
+    int len, ksize, klen;
+    int bytes, chars;
+    int es;
+    unsigned char *ep;
+    wchar wbuf[BUFSIZ];
+    char euc[BUFSIZ];
+    int stNbr;
+    int maxCand = 0;
+    ICSelectionControlArg arg;
+    ICString *ticsp = icsp;	/* $BI=<(MQ%G!<%?(B */
+
+    for (i = 0; i < icsNum; i++, ticsp++) {
+	/* if (i < oldSize) continue; */
+	ticsp->nbytes = (unsigned short)0;
+	ticsp->nchars = (unsigned short)0;
+	ticsp->data = (char *)0;
+	ticsp->attr = 0;
+    }
+    stNbr = page * pgMax;
+
+    ksize = 0;
+    for(i = 0; i < stNbr; i++) {
+	ksize += comm->kohoLenPtr[i];
+    }
+    if (cand_page) {
+	n = comm->kohoNum2 - stNbr > pgMax ? pgMax : comm->kohoNum2 - stNbr;
+    }
+    else {
+	n = pgMax;
+    }
+    for (j = 0; j < n; j++) {
+	bzero(euc, sizeof(euc));
+	klen = comm->kohoLenPtr[i];
+	es = klen * 3;
+	ep = (unsigned char *)XtMalloc(es);
+	bzero(ep, es);
+	ucs2euc(&comm->kohoStrPtr[ksize], klen, ep, es, 0x0000a2ae);
+	es = strlen(ep);
+	ksize += klen;
+#ifdef CAND_PAGE
+	sprintf(euc, "%2d %s", j + 1, ep);
+#else
+	strcpy(euc, ep);
+#endif
+	es = strlen(euc);
+	es = euc2wcs(euc, es, wbuf);
+	XtFree((char *)ep);
+
+	bytes = (int)icsp->nbytes;
+	chars = (int)icsp->nchars;
+	copyInWchar(wbuf, es, (wchar **)&(icsp->data), &bytes, &chars);
+	icsp->nbytes = (unsigned short)bytes;
+	icsp->nchars = (unsigned short)chars;
+	if (chars > maxCand) {
+	    maxCand = chars;
+	}
+	icsp->attr = ICAttrNormalString;
+	icsp++;
+	i++;
+    }
+    for(; j < pgMax; j++) {
+	icsp->nbytes = (unsigned short)0;
+	icsp->nchars = (unsigned short)0;
+	icsp->attr = ICAttrNormalString;
+	icsp->data = (char *)0;
+	icsp++;
+    }
+    if (cand_page) {
+#if SHOW_PAGE
+	sprintf(euc, "%d/%d", page * pgMax + 1, comm->kohoNum2);
+#else
+	sprintf(euc, "Page %d/%d", page + 1,
+				   (comm->kohoNum2 + pgMax - 1) / pgMax);
+#endif
+	es = strlen(euc);
+	es = euc2wcs(euc, es, wbuf);
+	bytes = (int)icsp->nbytes;
+	chars = (int)icsp->nchars;
+	copyInWchar(wbuf, es, ( wchar ** )&( icsp->data ), &bytes, &chars);
+
+	icsp->nbytes = (unsigned short)bytes;
+	icsp->nchars = (unsigned short)chars;
+	icsp->attr = ICAttrNormalString;
+    }
+
+    comm->kohoCurPage = page;
+
+    arg.command = ICSelectionStart;
+    arg.u.selection_kind = ICSelectionCandidates;
+    XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
+		       (XtPointer)&arg);
+
+    /* Set current candidate */
+    arg.command = ICSelectionSet;
+    arg.u.current_item = kohoNum;	/* $B8uJd(BNO$B$r@_Dj$9$k;v(B */
+    XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback,
+		       (XtPointer)&arg);
+
+    return page;
+}
+
+
+/*
+   copyInWchar -- wchar $B$r%3%T!<$9$k!#(B
+
+	ws, wlen $B$G<($5$l$?(B wchar $BJ8;zNs$r(B wsbuf $B$N%]%$%s%H@h$N%P%C%U%!$K3J(B
+	$BG<$9$k!#(Bwsbuf $B$N%5%$%:$O(B wssize $B$N%]%$%s%H@h$K3JG<$5$l$F$$$kCM$G;X(B
+	$BDj$5$l$k$,!"$=$l$G$O>.$5$$;~$O(B copyInWchar $BFb$G(B XtRealloc $B$5$l!"?7(B
+	$B$?$K%"%m%1!<%H$5$l$?%P%C%U%!$,(B wsbuf $B$N%]%$%s%H@h$K3JG<$5$l$k!#$^$?!"(B
+	$B%P%C%U%!$N?7$?$J%5%$%:$,(B wssize $B$N%]%$%s%H@h$K3JG<$5$l$k!#F@$i$l$?(B
+	$BJ8;z?t$,(Bwslen $B$N%]%$%s%H@h$K3JG<$5$l$k!#(B
+*/
+static void
+copyInWchar(ws, wlen, wsbuf, wssize, wslen)
+wchar *ws;
+int wlen;
+wchar **wsbuf;
+int *wssize;
+int *wslen;
+{
+    int i;
+
+    if (*wssize == 0) {
+	*wsbuf = (wchar *)XtMalloc((wlen + 1) * sizeof(wchar));
+	*wssize = wlen + 1;
+    }
+    if (wlen + 1 > *wssize) {
+	*wsbuf = (wchar *)XtRealloc((char *)*wsbuf, (wlen + 1) * sizeof(wchar));
+	*wssize = wlen + 1;
+    }
+    *wslen = wlen;
+    (void)bcopy(ws, *wsbuf, wlen * sizeof(wchar));
+    *(*wsbuf + wlen) = (wchar)0;
+}
+/* Atok.c */