Mercurial > kinput2.yaz
diff lib/Canna.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 | 56c98768f86b 1f1719e33c62 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/Canna.c Mon Mar 08 04:44:30 2010 +0900 @@ -0,0 +1,1854 @@ +/* + * 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) + */ + +/* $BD>$5$J$1$l$P$J$i$J$$$H$3$m(B + + $B!&(BDestroy $B$,8F$P$l$J$$$N$G(B CloseUIContext $B$G$-$J$$!#(B + $B!&%b!<%INN0h$NBg$-$5!#(B($B$3$l$OB>$N%U%!%$%k$@$m$&$J(B) + + */ + +#ifndef lint +static char *rcsid = "$Id: Canna.c,v 1.55 1999/05/25 08:13:03 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 "CannaP.h" +#include "DebugPrint.h" + +#define _WCHAR_T /* $B$3$NDj5A$O(B jrkanji.h $B$G(B wcKanjiStatus $B$J$I$rDj5A$9$k$?$a(B */ +#define wchar_t wchar + +#include <canna/jrkanji.h> + +static XtResource resources[] = { +#define offset(field) XtOffset(CannaObject, canna.field) + { XtNcannahost, XtCCannahost, XtRString, sizeof(String), + offset(cannahost), XtRString, NULL }, + { XtNcannafile, XtCCannafile, XtRString, sizeof(String), + offset(cannafile), XtRString, NULL }, + { XtNsendReturnByString, XtCSendReturnByString, + XtRBoolean, sizeof(Boolean), + offset(sendReturnByString), XtRBoolean, False }, +#undef offset +}; + +static void ClassInitialize(); +static void Initialize(), 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 void displayPreEdit(); +static int GetTriggerKeys(); +static int PreeditString(); +static int StatusString(); + +static initializeCannaConnection(); +static toJapaneseMode(); +static void convend(); +static changeTextForCanna(); +static copyInWchar(); +static fixProcForCanna(); +static shiftRight(), shiftLeft(), shiftLeftAll(); +static ibufInitialize(), freeIBuf(); + +#ifdef KC_SETLISTCALLBACK +#ifdef CANNA_LIST_Convert +#define CANNA_LISTFUNCTYPE int +#else +#define CANNA_LISTFUNCTYPE void +#endif +static CANNA_LISTFUNCTYPE listfunc(); + +static void openSelection(); +#define SELECTION_SET 0 /* SelectionStart $B$r$7$F$bNI$$$H8@$&>pJs$r@_Dj$9$k(B */ +#define SELECTION_DO 1 /* $B<B:]$K(B SelectionStart $B$r3+;O$9$k(B */ +#else /* !KC_SETLISTCALLBACK */ +#define openSelection(x, y, z) +#endif /* !KC_SETLISTCALLBACK */ + +static ICString *GetAuxSegments(); + +CannaClassRec cannaClassRec = { + { /* object fields */ + /* superclass */ (WidgetClass) &inputConvClassRec, + /* class_name */ "Canna", + /* widget_size */ sizeof(CannaRec), + /* 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 */ GetTriggerKeys, + /* num_trigger_keys */ 0, + /* trigger_keys */ NULL, + /* GetPreeditString */ PreeditString, + /* GetStatusString */ StatusString, + /* NoMoreObjects */ False, + }, + { /* canna fields */ + /* foo */ 0, + } +}; + +WidgetClass cannaObjectClass = (WidgetClass)&cannaClassRec; + +static void fix(); + +static ICString *SymbolList; +static int NumSymbols; + +static void addObject(); +static void deleteObject(); + +static int checkIfFunctionalChar(); + +static int ignoreListfunc = 0; + +static Display *displaybell = (Display *)0; + +static void +ClassInitialize() +{ + TRACE(("CannaObjectClass initialized\n")); + /* $B2?$b$7$J$$(B */ +} + +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; +} + +static int +InputEvent(w, event) +Widget w; +XEvent *event; +{ + CannaObject obj = (CannaObject)w; + wchar buf[1024]; + char kanabuf[20]; + KeySym ks; + XComposeStatus compose_status; + wcKanjiStatus kanji_status; + int len, nbytes, functionalChar; + + /* KeyPress$B0J30$O<N$F$k(B */ + if (event->type != KeyPress /*&& event->type != KeyRelease*/) return 0; + + obj->canna.textchanged = False; + + /* $B<h$j$"$($:J8;z$KD>$7$F$7$^$&(B */ + kanabuf[0] = '\0'; + nbytes = XKanaLookup(event, kanabuf, 20, &ks, &compose_status); + + buf[0] = (wchar)kanabuf[0]; /* $B$-$?$J$$(B */ + + if (ks == XK_space && (event->xkey.state & ShiftMask)) { + void convend(); + + convend(obj); + return 0; + } + + /* $BD9$5$,%<%m$N$b$N$K4X$7$F$O$A$g$C$H5_:Q(B */ + functionalChar = checkIfFunctionalChar(event, ks, buf, 1024); + /* shift+$B"*$N$h$&$JJ8;z$@$C$?$i#1J8;z$H?t$($k(B */ + if ( !nbytes && functionalChar ) { + nbytes = 1; + } + + /* $BMW$i$J$$>l9g$OL5;k$9$k(B */ + if (nbytes == 0) return 1; + + /* $B%Y%k$rLD$i$9%G%#%9%W%l%$$N@_Dj(B */ + + displaybell = XtDisplayOfObject((Widget)obj); + + /* $B$+$J4A;zJQ49$9$k(B */ + len = wcKanjiString((int)obj, (int)buf[0], + (wchar_t *)buf, 1024, &kanji_status); + + displayPreEdit(obj, len, buf, &kanji_status); + return (kanji_status.info & KanjiThroughInfo) ? 1 : 0; +} + +static void +displayPreEdit(obj, len, buf, ks) +CannaObject obj; +int len; +wchar *buf; +wcKanjiStatus *ks; +{ + Widget w = (Widget)obj; + + if (len > 0) { /* $B3NDjJ8;z$,$"$k>l9g(B */ + if (len == 1 && (ks->info & KanjiThroughInfo) && + (obj->canna.sendReturnByString == False || + (((buf[0] & 0x7f) < (unsigned)0x20 && + buf[0] != '\r' && buf[0] != '\t') || + buf[0] == '\177'))) { + ;/* XSendEvent$B$GAw$C$F$b$i$&$h$&$JJ8;z(B($B2?$b$7$J$$(B) */ + } + else { + ks->info &= ~KanjiThroughInfo; + fixProcForCanna(obj, buf, len); + fix(obj); + } + } + + changeTextForCanna(obj, ks); + + /* $B%F%-%9%H$NJQ2=$r%A%'%C%/$9$k(B */ + if (obj->canna.textchanged) { + XtCallCallbackList(w, obj->inputConv.textchangecallback, + (XtPointer)NULL); + obj->canna.textchanged = False; + } + + /* $BF~NO%b!<%I$r%A%'%C%/$9$k(B */ + if (ks->info & KanjiModeInfo) { + XtCallCallbackList(w, obj->inputConv.modechangecallback, + (XtPointer)NULL); + } + + if (ks->info & KanjiGLineInfo) { /* $B0lMw9T$,$"$k>l9g(B */ + ICAuxControlArg arg; + + switch (obj->canna.ibuf->candstat) { + case CANNA_GLINE_Start: + arg.command = ICAuxStart; + XtCallCallbackList((Widget)obj, obj->inputConv.auxcallback, + (XtPointer)&arg); + break; + case CANNA_GLINE_End: + arg.command = ICAuxEnd; + XtCallCallbackList((Widget)obj, obj->inputConv.auxcallback, + (XtPointer)&arg); + break; + case CANNA_GLINE_Change: + arg.command = ICAuxChange; + XtCallCallbackList((Widget)obj, obj->inputConv.auxcallback, + (XtPointer)&arg); + break; + } + } + + /* $B=*$o$j$+$I$&$+%A%'%C%/$9$k(B */ + if (ks->info & KanjiModeInfo) { + wchar modeinfo[4]; + + wcKanjiControl((int)obj, KC_SETMODEINFOSTYLE, (char *)1); + wcKanjiControl((int)obj, KC_QUERYMODE, (char *)modeinfo); + wcKanjiControl((int)obj, KC_SETMODEINFOSTYLE, (char *)0); + if (modeinfo[0] - '@' == CANNA_MODE_AlphaMode) { + toJapaneseMode(obj); + convend(obj); + } + } + openSelection(obj, SELECTION_DO, 0/* dummy */); +} + +static ICString * +GetMode(w) +Widget w; +{ + CannaObject obj = (CannaObject)w; + wchar *mode; + static ICString icstr; + + icstr.nchars = obj->canna.ibuf->modelen; + if (icstr.nchars > 0) { + mode = obj->canna.ibuf->curmode; + icstr.data = (char *)mode; + icstr.nbytes = icstr.nchars * sizeof(wchar); + icstr.attr = ICAttrNormalString; + } + return &icstr; +} + +static int +CursorPos(w, nsegp, ncharp) +Widget w; +Cardinal *nsegp; +Cardinal *ncharp; +{ + CannaObject obj = (CannaObject)w; + iBuf *ib = obj->canna.ibuf; + Cardinal nseg, nchar; + int ret = 0; + + if (ib->curseg < ib->nseg) { + nseg = ib->curseg; + nchar = 0; + } + else { + nseg = ib->offset; + nchar = ib->len[0 + ib->offset]; + ret = 1; + } + if (nsegp) { + *nsegp = nseg; + } + if (ncharp) { + *ncharp = nchar; + } + + return ret; +} + +static int +NumSegments(w) +Widget w; +{ + CannaObject obj = (CannaObject)w; + iBuf *ib = obj->canna.ibuf; + + return ib->nseg; +} + +static ICString * +GetSegment(w, n) +Widget w; +Cardinal n; +{ + CannaObject obj = (CannaObject)w; + iBuf *ib = obj->canna.ibuf; + static ICString seg; + + seg.data = (char *)ib->str[n]; + seg.nchars = ib->len[n]; + seg.nbytes = seg.nchars * sizeof(wchar); + if (ib->curseg == n) { + seg.attr = ICAttrConverted | ICAttrCurrentSegment; + } + else if (n < ib->offset) { + seg.attr = ICAttrConverted; + } + else { + seg.attr = ICAttrNotConverted; + } + + 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; +{ + CannaObject obj = (CannaObject)w; + + *n = obj->canna.numcand; + return obj->canna.candlist; +} + +#define SELECTBUFSIZE 1024 + +static int +SelectItem(w, n) +Widget w; +int n; +{ + CannaObject obj = (CannaObject)w; + wcKanjiStatus ks; + wcKanjiStatusWithValue ksv; + wchar buf[SELECTBUFSIZE]; + + if (n >= 0) + *(obj->canna.cur_addr) = n; + + ksv.ks = &ks; + buf[0] = (wchar)'\r'; + ksv.buffer = buf; + ksv.n_buffer = SELECTBUFSIZE; + ksv.val = CANNA_FN_Kakutei; + { + ignoreListfunc = 1; + wcKanjiControl((int)obj, KC_DO, (char *)&ksv); + ignoreListfunc = 0; + } + displayPreEdit(obj, ksv.val, buf, ksv.ks); + return 0; +} + +static int +ConvertedString(w, encoding, format, length, string) +Widget w; +Atom *encoding; +int *format; +int *length; +XtPointer *string; +{ + CannaObject obj = (CannaObject)w; + iBuf *ib = obj->canna.ibuf; + wchar *wbuf, *wp; + int len, wlen; + extern int convJWStoCT(); + int offset = ib->offset; + + if (ib == NULL) return -1; + + if (ib->nseg == 0 || ib->offset == 0) return -1; + + wlen = ib->len[offset - 1]; + if (wlen == 0) return -1; + + wbuf = ib->str[offset - 1]; + + /* + * 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((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); + + shiftLeftAll(ib); + + return 0; +} + +static int +ClearConversion(w) +Widget w; +{ + CannaObject obj = (CannaObject)w; + + wcKanjiStatus ks; + wcKanjiStatusWithValue ksv; + wchar buf[SELECTBUFSIZE]; + + ksv.ks = &ks; + ksv.buffer = buf; + ksv.n_buffer = SELECTBUFSIZE; + wcKanjiControl((int)obj, KC_KILL, (char *)&ksv); + displayPreEdit(obj, ksv.val, buf, ksv.ks); + return 0; +} + +static ICString * +GetAuxSegments(w, n, ns, nc) +Widget w; +Cardinal *n, *ns, *nc; +{ + CannaObject obj = (CannaObject)w; + iBuf *ib = obj->canna.ibuf; + Cardinal nseg, nchar; + + if (n) { + *n = ib->ngseg; + } + + if (ib->curgseg < ib->ngseg) { + nseg = ib->curgseg; + nchar = 0; + } + else { + nseg = 0; + nchar = ib->gllen[0]; + } + if (ns) { + *ns = nseg; + } + if (nc) { + *nc = nchar; + } + + return ib->ics; +} + +/* ARGSUSED */ +static void +Initialize(req, new, args, num_args) +Widget req; +Widget new; +ArgList args; +Cardinal *num_args; +{ + CannaObject obj = (CannaObject)new; + + obj->canna.selectionending = False; + obj->canna.textchanged = False; + obj->canna.symbollist = SymbolList; + obj->canna.numsymbols = NumSymbols; + obj->canna.cursymbol = 0; + obj->canna.candlist = NULL; + obj->canna.candlistsize = 0; + obj->canna.numcand = 0; + obj->canna.lastTextLengthIsZero = False; + + ibufInitialize(obj); + + /* $BJQ49$N=i4|2=(B */ + initializeCannaConnection(obj); + + addObject(obj); +} + +static int +bell() +{ + if (displaybell) { + XBell(displaybell, 0); + } + return 0; +} + +static int nCannaContexts = 0; + +static +initializeCannaConnection(obj) +CannaObject obj; +{ + char **warn = 0; + extern (*jrBeepFunc)(); + + if (nCannaContexts == 0) { +#ifdef KC_SETSERVERNAME + if (obj->canna.cannahost != NULL) { + wcKanjiControl((int)obj, KC_SETSERVERNAME, obj->canna.cannahost); + } +#endif /* KC_SETSERVERNAME */ +#ifdef KC_SETINITFILENAME + if (obj->canna.cannafile != NULL) { + wcKanjiControl((int)obj, KC_SETINITFILENAME, obj->canna.cannafile); + } +#endif /* KC_SETINITFILENAME */ + + wcKanjiControl((int)obj, KC_INITIALIZE, (char *)&warn); + TRACE(("Canna initialized\n")); + + if (warn) { + char **p; + + for (p = warn; *p ; p++) { + XtAppWarning(XtWidgetToApplicationContext((Widget)obj), *p); + } + } + } + nCannaContexts++; + +#ifdef KC_SETAPPNAME + wcKanjiControl((int)obj, KC_SETAPPNAME, "kinput2"); +#endif + +#ifdef DONT_USE_HANKAKU_KATAKANA + /* $BH>3Q%+%?%+%J$N6X;_(B */ + wcKanjiControl((int)obj, KC_INHIBITHANKAKUKANA, (char *)1); +#endif + + /* $B0lMw9T$r#7#8%3%i%`$K@_Dj(B */ + wcKanjiControl((int)obj, KC_SETWIDTH, (char *)78); + + /* $B8uJd0lMw%3!<%k%P%C%/$r@_Dj(B */ + +#ifdef KC_SETLISTCALLBACK + { + jrListCallbackStruct lcs; + + lcs.client_data = (char *)obj; + lcs.callback_func = listfunc; + wcKanjiControl((int)obj, KC_SETLISTCALLBACK, (char *)&lcs); + } +#endif /* KC_SETLISTCALLBACK */ + + jrBeepFunc = bell; + + /* $B$5$i$KF|K\8lF~NO%b!<%I$K$7$F$*$/(B */ + toJapaneseMode(obj); +} + + +static void +Destroy(w) +Widget w; +{ + CannaObject obj = (CannaObject)w; + wcKanjiStatusWithValue ksv; + wcKanjiStatus ks; + wchar buf[512]; + int i; + + /* $B%P%C%U%!$N2rJ|(B */ + + freeIBuf(obj->canna.ibuf); + + if (obj->canna.candlist) { + for (i = 0 ; i < obj->canna.candlistsize ; i++) { + if ((obj->canna.candlist + i)->data) { + XtFree((obj->canna.candlist + i)->data); + } + } + + XtFree((char *)obj->canna.candlist); + } + + /* $B!X$+$s$J!Y$N=hM}(B */ + ksv.buffer = buf; + ksv.n_buffer = 512; + ksv.ks = &ks; + + wcKanjiControl((int)obj, KC_CLOSEUICONTEXT, (char *)&ksv); + + if (--nCannaContexts == 0) { + char **warn = 0; + + wcKanjiControl(0, KC_FINALIZE, (char *)&warn); + if (warn) { + char **p; + + for (p = warn; *p ; p++) { + XtAppWarning(XtWidgetToApplicationContext((Widget)obj), *p); + } + } + } + + deleteObject(obj); +} + +static Boolean +SetValues(cur, req, wid, args, num_args) +Widget cur; +Widget req; +Widget wid; +ArgList args; +Cardinal *num_args; +/* ARGSUSED */ +{ + CannaObject old = (CannaObject)cur; + CannaObject new = (CannaObject)wid; + + return False; +} + +static void +fix(obj) +CannaObject obj; +{ + /* $B3NDj$N=hM}(B */ + XtCallCallbackList((Widget)obj, obj->inputConv.fixcallback, + (XtPointer)NULL); /* $B!)!)!)(B */ +} + +static void +convend(obj) +CannaObject obj; +{ + XtCallCallbackList((Widget)obj, obj->inputConv.endcallback, + (XtPointer)NULL); +} + +/* + * keeping list of objects + */ +typedef struct _oblist_ { + CannaObject obj; + struct _oblist_ *next; +} ObjRec; + +static ObjRec *ObjList = NULL; + +static void +addObject(obj) +CannaObject obj; +{ + ObjRec *objp = XtNew(ObjRec); + + objp->obj = obj; + objp->next = ObjList; + ObjList = objp; +} + +static void +deleteObject(obj) +CannaObject 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; + } + } +} + +/* + * Operations to canna.ibuf + */ + +/* cfuncdef + + changeTextForCanna -- ibuf $B$NFbMF$r(B kanji_status $B$rMQ$$$F=q$-49$($k!#(B + + + $B4pK\E*$K$O8uJdJ8;zNs$H8uJd0lMw9TJ8;zNs$K4X$7$F0J2<$N=hM}$r9T$&!#(B + + (1) $B$$$:$l$NJ8;zNs$b%F%-%9%H$,H?E>$7$F$$$kItJ,$H$=$&$G$J$$ItJ,(B + $B$,B8:_$7!"H?E>$7$F$$$kItJ,$O#1%+=j$7$+B8:_$7$J$$!#(B + (2) $B$7$?$,$C$F$$$:$l$NJ8;zNs$bH?E>$7$F$$$k$H$3$m$H$=$NN>C<$KH?E>(B + $B$7$F$$$J$$ItJ,$H$,B8:_$9$k>l9g$K#3ItJ,$KJ,$+$l$k$3$H$K$J$j!"(B + $BH?E>$7$F$$$kItJ,$N0LCV$d!"H?E>$7$F$$$k2U=j$,$J$$>l9g$J$I$r(B + $B9g$o$;$F9M$($F$b#3ItJ,0J>e$KJ,$+$l$k$3$H$O$J$$!#(B + (3) $B$7$?$,$C$F!"$$$:$l$NJ8;zNs$b:GBg#3$D$N%;%0%a%s%H$KJ,$1$FI=<((B + $B%&%#%8%'%C%H$KEO$9$h$&$K$9$k!#(B + + */ + +static +changeTextForCanna(cldata, ksp) +caddr_t cldata; +wcKanjiStatus *ksp; +{ + CannaObject obj = (CannaObject)cldata; + iBuf *ibuf = obj->canna.ibuf; + int offset = ibuf->offset, i; + + if (ksp->length == 0) { + ibuf->curseg = offset; + ibuf->nseg = offset; + ibuf->len[0 + offset] = ibuf->len[1 + offset] = + ibuf->len[2 + offset] = 0; + if (!obj->canna.lastTextLengthIsZero) { + obj->canna.textchanged = True; + obj->canna.lastTextLengthIsZero = True; + } + } + else if (ksp->length > 0) { + obj->canna.lastTextLengthIsZero = False; + ibuf->len[1 + offset] = ibuf->len[2 + offset] = 0; + if (ksp->revLen > 0) { + if (ksp->revPos == 0) { + int remain = ksp->length - ksp->revLen; + + copyInWchar(ksp->echoStr, ksp->revLen, + &(ibuf->str[0 + offset]), &(ibuf->size[0 + offset]), + &(ibuf->len[0 + offset])); + ibuf->curseg = offset; + ibuf->nseg = offset + 1; + if (remain) { + copyInWchar(ksp->echoStr + ksp->revLen, remain, + &(ibuf->str[1 + offset]), &(ibuf->size[1 + offset]), + &(ibuf->len[1 + offset])); + ibuf->nseg = offset + 2; + } + } + else { + int remain = ksp->length - ksp->revPos - ksp->revLen; + + copyInWchar(ksp->echoStr, ksp->revPos, + &(ibuf->str[0 + offset]), &(ibuf->size[0 + offset]), + &(ibuf->len[0 + offset])); + copyInWchar(ksp->echoStr + ksp->revPos, ksp->revLen, + &(ibuf->str[1 + offset]), &(ibuf->size[1 + offset]), + &(ibuf->len[1 + offset])); + ibuf->curseg = offset + 1; + ibuf->nseg = offset + 2; + if (remain) { + copyInWchar(ksp->echoStr + ksp->revPos + ksp->revLen, + remain, + &(ibuf->str[2 + offset]), &(ibuf->size[2 + offset]), + &(ibuf->len[2 + offset])); + ibuf->nseg = offset + 3; + } + } + } + else { + copyInWchar(ksp->echoStr, ksp->length, + &(ibuf->str[0 + offset]), &(ibuf->size[0 + offset]), + &(ibuf->len[0 + offset])); + ibuf->len[1 + offset] = ibuf->len[2 + offset] = 0; + ibuf->nseg = offset + 1; + ibuf->curseg = offset + 1; + } + obj->canna.textchanged = True; + } + /* $B%b!<%I(B */ + if (ksp->info & KanjiModeInfo) { + int modelen = 0; + + while (ksp->mode[modelen]) modelen++; + copyInWchar(ksp->mode, modelen, + &(ibuf->curmode), &(ibuf->modesize), &(ibuf->modelen)); + } + /* $B0lMw9T(B */ + if (ksp->info & KanjiGLineInfo) { + if (ksp->gline.length == 0) { + switch (ibuf->candstat) { + case CANNA_GLINE_Empty: + case CANNA_GLINE_End: + ibuf->candstat = CANNA_GLINE_Empty; + break; + case CANNA_GLINE_Start: + case CANNA_GLINE_Change: + ibuf->candstat = CANNA_GLINE_End; + break; + } + ibuf->curgseg = 0; + ibuf->ngseg = 0; + ibuf->gllen[0] = ibuf->gllen[1] = ibuf->gllen[2] = 0; + } + else if (ksp->gline.length > 0) { + switch (ibuf->candstat) { + case CANNA_GLINE_Empty: + case CANNA_GLINE_End: + ibuf->candstat = CANNA_GLINE_Start; + break; + case CANNA_GLINE_Start: + case CANNA_GLINE_Change: + ibuf->candstat = CANNA_GLINE_Change; + break; + } + ibuf->gllen[1] = ibuf->gllen[2] = 0; + if (ksp->gline.revLen > 0) { + if (ksp->gline.revPos == 0) { + int remain = ksp->gline.length - ksp->gline.revLen; + + copyInWchar(ksp->gline.line, ksp->gline.revLen, + &(ibuf->gline[0]), &(ibuf->glsize[0]), + &(ibuf->gllen[0])); + ibuf->curgseg = 0; + ibuf->ngseg = 1; + if (remain) { + copyInWchar(ksp->gline.line + ksp->gline.revLen, remain, + &(ibuf->gline[1]), &(ibuf->glsize[1]), + &(ibuf->gllen[1])); + ibuf->ngseg = 2; + } + } + else { + int remain = ksp->gline.length + - ksp->gline.revPos - ksp->gline.revLen; + + copyInWchar(ksp->gline.line, ksp->gline.revPos, + &(ibuf->gline[0]), &(ibuf->glsize[0]), + &(ibuf->gllen[0])); + copyInWchar(ksp->gline.line + ksp->gline.revPos, ksp->gline.revLen, + &(ibuf->gline[1]), &(ibuf->glsize[1]), + &(ibuf->gllen[1])); + ibuf->curgseg = 1; + ibuf->ngseg = 2; + if (remain) { + copyInWchar(ksp->gline.line + + ksp->gline.revPos + ksp->gline.revLen, + remain, + &(ibuf->gline[2]), &(ibuf->glsize[2]), + &(ibuf->gllen[2])); + ibuf->ngseg = 3; + } + } + } + else { + copyInWchar(ksp->gline.line, ksp->gline.length, + &(ibuf->gline[0]), &(ibuf->glsize[0]), + &(ibuf->gllen[0])); + ibuf->gllen[1] = ibuf->gllen[2] = 0; + ibuf->ngseg = 1; + ibuf->curgseg = 1; + } + } + for (i = 0 ; i < ibuf->ngseg ; i++) { + ibuf->ics[i].data = (char *)ibuf->gline[i]; + ibuf->ics[i].nchars = ibuf->gllen[i]; + ibuf->ics[i].nbytes = ibuf->gllen[i] * sizeof(wchar); + ibuf->ics[i].attr = ICAttrConverted; + } + if (ibuf->curgseg < ibuf->ngseg) { + ibuf->ics[ibuf->curgseg].attr |= ICAttrCurrentSegment; + } + } +} + +/* cfuncdef + + 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 +copyInWchar(ws, wlen, wsbuf, wssize, wslen) +wchar *ws; +int wlen; +wchar **wsbuf; +int *wssize, *wslen; +{ + int i; + + if (*wssize == 0) { + if ((*wsbuf = (wchar *)XtMalloc((wlen + 1) * sizeof(wchar))) + == (wchar *)0) { + /* $B%(%i!<$@(B */ + } + else { + *wssize = wlen + 1; + } + } + if (wlen + 1 > *wssize) { + if ((*wsbuf = (wchar *)XtRealloc((char *)*wsbuf, + (wlen + 1) * sizeof(wchar))) + == (wchar *)0) { + /* $B%(%i!<$@!#$I$&$9$l$PNI$$!)(B */ + } + else { + *wssize = wlen + 1; + } + } + *wslen = wlen; + (void)bcopy(ws, *wsbuf, wlen * sizeof(wchar)); + *(*wsbuf + wlen) = (wchar)0; + + return 0; /* $B#0$OFC$K0UL#$,L5$$(B */ +} + +/* cfuncdef + + fixProcForCanna -- $B3NDj$7$?J8;z$N=hM}$r9T$&(B + + */ + +static +fixProcForCanna(cldata, fixedstr, fixedlen) +caddr_t cldata; +wchar *fixedstr; +int fixedlen; +{ + CannaObject obj = (CannaObject)cldata; + iBuf *ib = obj->canna.ibuf; + int offset = ib->offset; + + if (offset < NConvertedSegments) { + shiftRight(ib); + offset = ib->offset; + } + else { + shiftLeft(ib); + } + copyInWchar(fixedstr, fixedlen, + &(ib->str[offset - 1]), &(ib->size[offset - 1]), + &(ib->len[offset - 1])); +} + +/* cfuncdef + + shiftRight -- ibuf $B$NJ8;z%P%C%U%!$N(B offset $B0J9_$r1&$K%7%U%H$9$k(B + + */ + +static +shiftRight(ib) +iBuf *ib; +{ + int i; + wchar *tmpbuf; + int tmpsize, tmplen; + int offset = ib->offset; + + tmpbuf = ib->str[ib->nseg]; + tmpsize = ib->size[ib->nseg]; + for (i = ib->nseg ; offset < i ; i--) { + ib->str[i] = ib->str[i - 1]; + ib->size[i] = ib->size[i - 1]; + ib->len[i] = ib->len[i - 1]; + } + ib->str[offset] = tmpbuf; + ib->size[offset] = tmpsize; + ib->offset++; + ib->nseg++; + ib->curseg++; +} + +/* cfuncdef + + shiftLeft -- ibuf $B$NJ8;z%P%C%U%!$N(B offset $B0JA0$r:8$K%7%U%H$9$k(B + + */ + +static +shiftLeft(ib) +iBuf *ib; +{ + int i; + wchar *tmpbuf; + int tmpsize, tmplen; + int offset = ib->offset; + + tmpbuf = ib->str[0]; + tmpsize = ib->size[0]; + for (i = 0 ; i < offset - 1 ; i++) { + ib->str[i] = ib->str[i + 1]; + ib->size[i] = ib->size[i + 1]; + ib->len[i] = ib->len[i + 1]; + } + ib->str[offset - 1] = tmpbuf; + ib->size[offset - 1] = tmpsize; +} + +/* cfuncdef + + shiftLeftAll -- ibuf $B$NJ8;z%P%C%U%!A4BN$r:8$K%7%U%H$9$k(B + + */ + +static +shiftLeftAll(ib) +iBuf *ib; +{ + int i; + wchar *tmpbuf; + int tmpsize, tmplen; + int nseg = ib->nseg; + + tmpbuf = ib->str[0]; + tmpsize = ib->size[0]; + for (i = 0 ; i < nseg - 1 ; i++) { + ib->str[i] = ib->str[i + 1]; + ib->size[i] = ib->size[i + 1]; + ib->len[i] = ib->len[i + 1]; + } + ib->str[nseg - 1] = tmpbuf; + ib->size[nseg - 1] = tmpsize; + ib->nseg--; + ib->curseg--; + ib->offset--; +} + +/* cfuncdef + + ibufInitialize -- ibuf $B$N=i4|2==hM}(B + */ + +static +ibufInitialize(obj) +CannaObject obj; +{ + int i; + iBuf *ib; + + ib = obj->canna.ibuf = (iBuf *)XtMalloc(sizeof(iBuf)); + if (ib == 0) { + /* $B%(%i!<$@!#$I$&$9$Y(B */ + } + for (i = 0 ; i < NConvertedSegments + 3 ; i++) { + ib->size[i] = 0; + ib->len[i] = 0; + } + ib->offset = ib->curseg = ib->nseg = 0; + ib->candstat = CANNA_GLINE_Empty; + for (i = 0 ; i < 3 ; i++) { + ib->gline[i] = 0; + ib->glsize[i] = ib->gllen[i] = 0; + } + ib->modesize = 0; + ib->modelen = 0; +} + +/* cfuncdef + + freeIBuf -- ibuf $B$N(B free + + */ + +static +freeIBuf(ib) +iBuf *ib; +{ + int i; + + if (ib == 0) { + return 0; + } + for (i = 0 ; i < NConvertedSegments + 3 ; i++) { + if (ib->size[i] > 0) { + XtFree((char *)ib->str[i]); + } + } + for (i = 0 ; i < 3 ; i++) { + if (ib->glsize[i] > 0) { + XtFree((char *)ib->gline[i]); + } + } + if (ib->modesize > 0) { + XtFree((char *)ib->curmode); + } + free(ib); + return 0; +} + +static +toJapaneseMode(obj) +CannaObject obj; +{ + wcKanjiStatusWithValue ksv; + wcKanjiStatus ks; + wchar buf[1024]; + + buf[0] = '@'; + ksv.ks = &ks; + ksv.buffer = buf; + ksv.n_buffer = 1024; +#ifndef KC_DO + ksv.val = CANNA_MODE_HenkanMode; + wcKanjiControl((int)obj, KC_CHANGEMODE, (char *)&ksv); +#else + ksv.val = CANNA_FN_JapaneseMode; + wcKanjiControl((int)obj, KC_DO, (char *)&ksv); +#endif + changeTextForCanna(obj, &ks); +} + +/* checkIfFunctionalChar -- $B%7%U%H%-!<$N$h$&$KL50UL#$J%-!<$+$I$&$+$NH=JL(B + + $BCM(B: $B#1(B $B0UL#$,$"$k(B + $B#0(B $BL50UL#(B($B%b%G%#%U%!%$%"%-!<$J$I(B) +*/ + +static int +checkIfFunctionalChar(event_struct, keysym, buffer_return, n_buffer) +XKeyEvent *event_struct; +KeySym keysym; +wchar *buffer_return; +int n_buffer; +{ + int functionalChar = 0; + + switch ((int)keysym) + { + case XK_KP_F1: + case XK_KP_F2: + case XK_KP_F3: + case XK_KP_F4: + *buffer_return = CANNA_KEY_PF1 + (int)keysym - (int)XK_KP_F1; + functionalChar = 1; + break; + case XK_F1: + case XK_F2: + case XK_F3: + case XK_F4: + case XK_F5: + case XK_F6: + case XK_F7: + case XK_F8: + case XK_F9: + case XK_F10: + case XK_F11: + case XK_F12: + case XK_F13: + case XK_F14: + case XK_F15: + case XK_F16: + *buffer_return = CANNA_KEY_F1 + (int)keysym - (int)XK_F1; + functionalChar = 1; + break; + case XK_Insert: + *buffer_return = CANNA_KEY_Insert; + functionalChar = 1; + break; + case XK_Prior: + *buffer_return = CANNA_KEY_Rollup; + functionalChar = 1; + break; + case XK_Next: + *buffer_return = CANNA_KEY_Rolldown; + functionalChar = 1; + break; + case XK_Muhenkan: + if (event_struct->state & 4 /* control-shifted */) + *buffer_return = CANNA_KEY_Cntrl_Nfer; + else if (event_struct->state & 1 /* shifted */) + *buffer_return = CANNA_KEY_Shift_Nfer; + else + *buffer_return = CANNA_KEY_Nfer; + functionalChar = 1; + break; + case XK_Kanji: + if (event_struct->state & 4 /* control-shifted */) + *buffer_return = CANNA_KEY_Cntrl_Xfer; + else if (event_struct->state & 1 /* shifted */) + *buffer_return = CANNA_KEY_Shift_Xfer; + else + *buffer_return = CANNA_KEY_Xfer; + functionalChar = 1; + break; + case XK_Up: + if (event_struct->state & 4 /* control-shifted */) + *buffer_return = CANNA_KEY_Cntrl_Up; + else if (event_struct->state & 1 /* shifted */) + *buffer_return = CANNA_KEY_Shift_Up; + else + *buffer_return = CANNA_KEY_Up; + functionalChar = 1; + break; + case XK_Down: + if (event_struct->state & 4 /* control-shifted */) + *buffer_return = CANNA_KEY_Cntrl_Down; + else if (event_struct->state & 1 /* shifted */) + *buffer_return = CANNA_KEY_Shift_Down; + else + *buffer_return = CANNA_KEY_Down; + functionalChar = 1; + break; + case XK_Right: + if (event_struct->state & 4 /* control-shifted */) + *buffer_return = CANNA_KEY_Cntrl_Right; + else if (event_struct->state & 1 /* shifted */) + *buffer_return = CANNA_KEY_Shift_Right; + else + *buffer_return = CANNA_KEY_Right; + functionalChar = 1; + break; + case XK_Left: + if (event_struct->state & 4 /* control-shifted */) + *buffer_return = CANNA_KEY_Cntrl_Left; + else if (event_struct->state & 1 /* shifted */) + *buffer_return = CANNA_KEY_Shift_Left; + else + *buffer_return = CANNA_KEY_Left; + functionalChar = 1; + break; + case XK_Help: + *buffer_return = CANNA_KEY_Help; + functionalChar = 1; + break; + case XK_Home: + *buffer_return = CANNA_KEY_Home; + functionalChar = 1; + break; + } + return functionalChar; +} + +#ifdef KC_SETLISTCALLBACK + +static void +moveSelection(obj, dir) +CannaObject obj; +int dir; +{ + ICSelectionControlArg arg; + + arg.command = ICSelectionMove; + arg.u.dir = dir; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); +} + +static int +insertSelection(obj, selected) +CannaObject obj; +int selected; +{ + obj->canna.curcand = selected; + *(obj->canna.cur_addr) = selected; + + return 0; +} + +static void +endSelection(obj, abort) +CannaObject obj; +int abort; +{ + ICSelectionControlArg arg; + int selected; + + if (ignoreListfunc) return; /* SelectItem $B$G=hM}$5$l$k$N$G$3$3$OITMW(B */ + arg.command = ICSelectionEnd; + arg.u.current_item = -1; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); + + if (!abort && (selected = arg.u.current_item) >= 0) { + insertSelection(obj, selected); + } +} + +#ifdef CANNA_LIST_Query +static void +querySelection(obj) +CannaObject obj; +{ + ICSelectionControlArg arg; + int selected; + + if (ignoreListfunc) return; /* SelectItem $B$G=hM}$5$l$k$N$G$3$3$OITMW(B */ + arg.command = ICSelectionGet; + arg.u.current_item = -1; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); + + if ((selected = arg.u.current_item) >= 0) { + insertSelection(obj, selected); + } +} +#endif + +static void +openSelection(obj, func, curitem) +CannaObject obj; +int func; /* $B0lHV>e$r8+$h(B */ +int curitem; +{ + ICSelectionControlArg arg; + static int current = 0; + static int doit = 0; + + if (func == SELECTION_SET) { + current = curitem; + doit = 1; + } + else if (func == SELECTION_DO && doit) { + doit = 0; + arg.command = ICSelectionStart; + arg.u.selection_kind = ICSelectionCandidates; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); + + /* set current item */ + arg.command = ICSelectionSet; + arg.u.current_item = current; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); + } +} + +static void getAllCandidates(); + +/* listfunc -- $B8uJd0lMw%b!<%I$K$J$C$?;~$K8F$S=P$5$l$k4X?t(B + * + * obj : KC_SETLISTCALLBACK $B$G@_Dj$7$?%/%i%$%"%s%H%G!<%?(B + * func : $B8uJd0lMw5!G=$N8GM-$N5!G=$rI=$9#I#D(B + * items : Start $B$N;~$K$O8uJd0lMw$NA4%"%$%F%`$,F~$k(B + * nitems : $B!7(B $BA4%"%$%F%`$N?t$,F~$k(B + * cur_item : $B!7(B $B%+%l%s%H%"%$%F%`HV9f$r3JG<$9$k%"%I%l%9$,F~$k(B + */ + +static CANNA_LISTFUNCTYPE +listfunc(obj, func, items, nitems, cur_item) +CannaObject obj; +int func; +wchar **items; +int nitems, *cur_item; +{ + ICSelectionControlArg arg; + int i; + wchar **p; + + switch (func) { + case CANNA_LIST_Start: + getAllCandidates(obj, nitems, items); + obj->canna.numcand = nitems; + obj->canna.curcand = *cur_item; + obj->canna.cur_addr = cur_item; + openSelection(obj, SELECTION_SET, *cur_item); + break; + case CANNA_LIST_Select: + endSelection(obj, False); + break; + case CANNA_LIST_Quit: + endSelection(obj, True); + break; +#ifdef CANNA_LIST_Query + case CANNA_LIST_Query: + querySelection(obj); + break; +#endif +#ifdef CANNA_LIST_Convert + case CANNA_LIST_Convert: +#endif + case CANNA_LIST_Forward: + moveSelection(obj, ICMoveRight); + break; + case CANNA_LIST_Backward: + moveSelection(obj, ICMoveLeft); + break; + case CANNA_LIST_Next: + moveSelection(obj, ICMoveDown); + break; + case CANNA_LIST_Prev: + moveSelection(obj, ICMoveUp); + break; + case CANNA_LIST_BeginningOfLine: + moveSelection(obj, ICMoveLeftMost); + break; + case CANNA_LIST_EndOfLine: + moveSelection(obj, ICMoveRightMost); + break; +#ifdef CANNA_LIST_Insert + case CANNA_LIST_Insert: + return 0; +#endif + } +#ifdef CANNA_LIST_Convert + return 1; +#endif +} + +static void +allocCandlist(obj, n) +CannaObject obj; +int n; +{ + ICString *p; + int i; + + if (n <= obj->canna.candlistsize) return; + + if (obj->canna.candlistsize == 0) { + p = (ICString *)XtMalloc(n * sizeof(ICString)); + } else { + p = (ICString *)XtRealloc((char *)obj->canna.candlist, + n * sizeof(ICString)); + } + for (i = obj->canna.candlistsize ; i < n ; i++) { + p[i].nbytes = p[i].nchars = (unsigned short)0; + p[i].data = (char *)0; + p[i].attr = 0; + } + + obj->canna.candlist = p; + obj->canna.candlistsize = n; +} + +static void +getAllCandidates(obj, ncand, items) +CannaObject obj; +int ncand; +wchar **items; +{ + ICString *strp; + wchar **p; + int i, bytes, chars; + + allocCandlist(obj, ncand); + + for (i = 0, strp = obj->canna.candlist, p = items ; + i < ncand; i++, strp++, p++) { + int len = 0; + + bytes = strp->nbytes; + chars = strp->nchars; + while ((*p)[len]) len++; + copyInWchar(*p, len, (wchar **)&(strp->data), &bytes, &chars); + strp->nbytes = bytes; + strp->nchars = chars; + strp->attr = ICAttrNormalString; + } +} +#endif /* KC_SETLISTCALLBACK */ + +struct _keymap { + unsigned char cannakey; + KeySym keysym; + long modifier; +} cannakeymap[] = { + {(unsigned char)'\b', XK_BackSpace, 0}, + {(unsigned char)'\t', XK_Tab, 0}, + {(unsigned char)'\n', XK_Linefeed, 0}, + {(unsigned char)'\013', XK_Clear, 0}, + {(unsigned char)'\r', XK_Return, 0}, + {(unsigned char)'\023', XK_Pause, 0}, + {(unsigned char)'\024', XK_Scroll_Lock, 0}, + {(unsigned char)'\e', XK_Escape, 0}, + {(unsigned char)CANNA_KEY_Nfer, XK_Muhenkan, 0}, + {(unsigned char)CANNA_KEY_Xfer, XK_Kanji, 0}, + {(unsigned char)CANNA_KEY_Up, XK_Up, 0}, + {(unsigned char)CANNA_KEY_Left, XK_Left, 0}, + {(unsigned char)CANNA_KEY_Right, XK_Right, 0}, + {(unsigned char)CANNA_KEY_Down, XK_Down, 0}, + {(unsigned char)CANNA_KEY_Insert, XK_Insert, 0}, + {(unsigned char)CANNA_KEY_Rollup, XK_Prior, 0}, + {(unsigned char)CANNA_KEY_Rolldown, XK_Next, 0}, + {(unsigned char)CANNA_KEY_Home, XK_Home, 0}, + {(unsigned char)CANNA_KEY_Help, XK_Help, 0}, + {(unsigned char)CANNA_KEY_KP_Key, XK_KP_Space, 0}, /* ? */ + {(unsigned char)CANNA_KEY_Shift_Nfer, XK_Muhenkan, ShiftMask}, + {(unsigned char)CANNA_KEY_Shift_Xfer, XK_Kanji, ShiftMask}, + {(unsigned char)CANNA_KEY_Shift_Up, XK_Up, ShiftMask}, + {(unsigned char)CANNA_KEY_Shift_Left, XK_Left, ShiftMask}, + {(unsigned char)CANNA_KEY_Shift_Right, XK_Right, ShiftMask}, + {(unsigned char)CANNA_KEY_Shift_Down, XK_Down, ShiftMask}, + {(unsigned char)CANNA_KEY_Cntrl_Nfer, XK_Muhenkan, ControlMask}, + {(unsigned char)CANNA_KEY_Cntrl_Xfer, XK_Kanji, ControlMask}, + {(unsigned char)CANNA_KEY_Cntrl_Up, XK_Up, ControlMask}, + {(unsigned char)CANNA_KEY_Cntrl_Left, XK_Left, ControlMask}, + {(unsigned char)CANNA_KEY_Cntrl_Right, XK_Right, ControlMask}, + {(unsigned char)CANNA_KEY_Cntrl_Down, XK_Down, ControlMask}, + {(unsigned char)CANNA_KEY_F1, XK_F1, 0}, + {(unsigned char)CANNA_KEY_F2, XK_F2, 0}, + {(unsigned char)CANNA_KEY_F3, XK_F3, 0}, + {(unsigned char)CANNA_KEY_F4, XK_F4, 0}, + {(unsigned char)CANNA_KEY_F5, XK_F5, 0}, + {(unsigned char)CANNA_KEY_F6, XK_F6, 0}, + {(unsigned char)CANNA_KEY_F7, XK_F7, 0}, + {(unsigned char)CANNA_KEY_F8, XK_F8, 0}, + {(unsigned char)CANNA_KEY_F9, XK_F9, 0}, + {(unsigned char)CANNA_KEY_F10, XK_F10, 0}, + {(unsigned char)CANNA_KEY_PF1, XK_KP_F1, 0}, + {(unsigned char)CANNA_KEY_PF2, XK_KP_F2, 0}, + {(unsigned char)CANNA_KEY_PF3, XK_KP_F3, 0}, + {(unsigned char)CANNA_KEY_PF4, XK_KP_F4, 0}, + {(unsigned char)CANNA_KEY_PF5, XK_F15, 0}, + {(unsigned char)CANNA_KEY_PF6, XK_F16, 0}, + {(unsigned char)CANNA_KEY_PF7, XK_F17, 0}, + {(unsigned char)CANNA_KEY_PF8, XK_F18, 0}, + {(unsigned char)CANNA_KEY_PF9, XK_F19, 0}, + {(unsigned char)CANNA_KEY_PF10, XK_F20, 0}, +}; + +#define NCANNAKEYMAP (sizeof(cannakeymap) / sizeof(struct _keymap)) + +/* ARGSUSED */ +static int +GetTriggerKeys(w, keys_return) +Widget w; +ICTriggerKey **keys_return; +{ + CannaObject obj = (CannaObject)w; + ICTriggerKey *keys; + unsigned char c, mkeys[256], *p, *ekeys; /* enough */ + int n; + struct _keymap *pk, *ek; + + n = wcKanjiControl((int)obj, KC_MODEKEYS, (char *)mkeys); + + *keys_return = keys = + (ICTriggerKey *)XtMalloc(2 * n * sizeof(ICTriggerKey)); + /* $B!V(B2 *$B!W$N0UL#(B: + $B0l$D$N%3!<%I$K(B2$B$D$N(B X $B$N%-!<$,B8:_$7$F$$$?$j$9$k;v$,$"$k!#(B + ($BNc(B) C-h $B"*(B Ctl<Key>h, <Key>Backspace */ + + if (keys) { + for (p = mkeys, ekeys = p + n ; p < ekeys ; p++, keys++) { + c = *p; + if (c == (unsigned char)0) { + keys->keysym = XK_space; + keys->modifiers = keys->modifiermask = ControlMask; + keys++; + keys->keysym = XK_at; + keys->modifiers = keys->modifiermask = ControlMask; + } + else if (c < ' ') { + keys->keysym = XK_quoteleft + c; + keys->modifiers = keys->modifiermask = ControlMask; + for (pk = cannakeymap, ek = cannakeymap + NCANNAKEYMAP ; + pk < ek ; pk++) { + if (c == pk->cannakey) { + keys++; + keys->keysym = pk->keysym; + keys->modifiers = keys->modifiermask = pk->modifier; + } + } + } + else if (c <= '~') { + keys->keysym = XK_space + (c - (unsigned char)' '); + keys->modifiers = keys->modifiermask = 0; + } + else if (c == 0x7f) { + keys->keysym = XK_Delete; + keys->modifiers = keys->modifiermask = 0; + } + else if ((unsigned char)0xa1 <= c && c <= (unsigned char)0xdf) { + keys->keysym = XK_kana_fullstop + (c - (unsigned char)0xa1); + keys->modifiers = keys->modifiermask = pk->modifier; + } + else { + keys--; + for (pk = cannakeymap, ek = cannakeymap + NCANNAKEYMAP ; + pk < ek ; pk++) { + if (c == pk->cannakey) { + keys++; + keys->keysym = pk->keysym; + keys->modifiers = keys->modifiermask = pk->modifier; + } + } + } + } + return n; + } + return 0; +} + +/* 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; +{ + CannaObject obj = (CannaObject)w; + iBuf *ib = obj->canna.ibuf; + int i; + wchar *wbuf, *wp; + int len, wlen; + extern int convJWStoCT(); + + if (ib == NULL) return -1; + if (segn < ib->nseg && offset >= ib->len[segn]) { + /* $B%;%0%a%s%H$N:G8e(B */ + ++segn; + offset = 0; + } + if (segn >= ib->nseg || offset >= ib->len[segn]) { + /* $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 < ib->nseg; i++) { + wlen += ib->len[i]; + } + wlen -= offset; + + wp = wbuf = (wchar *)XtMalloc((wlen + 1) * sizeof(wchar)); + len = ib->len[segn] - offset; + (void)bcopy((char *)(ib->str[segn] + offset), (char *)wp, sizeof(wchar) * len); + wp += len; + for (i = segn + 1; i < ib->nseg; i++) { + len = ib->len[i]; + (void)bcopy((char *)ib->str[i], (char *)wp, sizeof(wchar) * len); + wp += len; + } + 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 = (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; +}