Mercurial > kinput2.yaz
diff lib/CcWnn.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 | 983aff0dcf18 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/CcWnn.c Mon Mar 08 04:44:30 2010 +0900 @@ -0,0 +1,2788 @@ +#ifndef lint +static char *rcsid = "$Id: CcWnn.c,v 1.59 2002/01/10 15:51:47 ishisone Exp $"; +#endif +/* + * 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 + */ + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Atoms.h> +#if XtSpecificationRelease > 4 +#include <X11/Xfuncs.h> +#endif +#include "CcWnnP.h" +#include "CachedAtom.h" +#include "IOECall.h" + +#define DEBUG_VAR debug_CcWnn +#include "DebugPrint.h" + +static XtResource resources[] = { +#define offset(field) XtOffset(CcWnnObject, ccWnn.field) + { XtNconfirmFunc, XtCFunction, XtRPointer, sizeof(int (*)()), + offset(confirmfunc), XtRPointer, (XtPointer)NULL }, + { XtNconfirmData, XtCConfirmData, XtRPointer, sizeof(XtPointer), + offset(confirmdata), XtRPointer, (XtPointer)NULL }, + { XtNjserver, XtCJserver, XtRString, sizeof(String), + offset(jservername), XtRString, NULL }, + { XtNjserver2nd, XtCJserver, XtRString, sizeof(String), + offset(jservername2), XtRString, NULL }, + { XtNwnnEnvname, XtCWnnEnvname, XtRString, sizeof(String), + offset(wnnenvname), XtRString, NULL }, + { XtNwnnEnvrc, XtCWnnEnvrc, XtRString, sizeof(String), + offset(wnnenvrcfile), XtRString, NULL }, + { XtNwnnEnvrc4, XtCWnnEnvrc, XtRString, sizeof(String), + offset(wnnenvrcfile4), XtRString, NULL }, + { XtNwnnEnvrc6, XtCWnnEnvrc, XtRString, sizeof(String), + offset(wnnenvrcfile6), XtRString, NULL }, + { XtNwnnOverrideEnv, XtCWnnOverrideEnv, XtRBoolean, sizeof(Boolean), + offset(wnnoverrideenv), XtRString, "false" }, + { XtNccdef, XtCCcdef, XtRString, sizeof(String), + offset(ccdeffile), XtRString, NULL }, + { XtNwnnEnv, XtCWnnEnv, XtRWnnEnv, sizeof(struct wnn_buf *), + offset(wnnbuf), XtRWnnEnv, NULL}, + { XtNccRule, XtCCcRule, XtRCcRule, sizeof(ccRule), + offset(ccrule), XtRCcRule, NULL}, + { XtNsaveInterval, XtCSaveInterval, XtRInt, sizeof(int), + offset(saveinterval), XtRImmediate, 0 }, +#undef offset +}; + +static void ClassInitialize(); +static int buildSymbolList(); +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 ICString *GetAuxSegments(); +static int PreeditString(); +static int StatusString(); + +CcWnnClassRec ccWnnClassRec = { + { /* object fields */ + /* superclass */ (WidgetClass) &inputConvClassRec, + /* class_name */ "CcWnn", + /* widget_size */ sizeof(CcWnnRec), + /* 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, + /* GetConvetedString */ ConvertedString, + /* ClearConversion */ ClearConversion, + /* GetAuxSegments */ GetAuxSegments, + /* SupportMultipleObjects */ True, + /* GetTriggerKeys */ XtInheritGetTriggerKeys, + /* num_trigger_keys */ 0, + /* trigger_keys */ NULL, + /* GetPreeditString */ PreeditString, + /* GetStatusString */ StatusString, + /* NoMoreObjects */ False, + }, + { /* ccWnn fields */ + /* foo */ 0, + } +}; + +WidgetClass ccWnnObjectClass = (WidgetClass)&ccWnnClassRec; + +/* cconv function table */ +static char *fepfunctbl[] = { + "convert", + "convert-or-fix1", + "convert-or-space", + "convert-or-sendback", + "convert-s", + "unconvert", + "next", + "next-s", + "previous", + "previous-s", + "forward", + "backward", + "move-top", + "move-bottom", + "clear", + "expand", + "expand-s", + "shrink", + "shrink-s", + "expand-noconv", + "expand-noconv-s", + "shrink-noconv", + "shrink-noconv-s", + "fix", + "fix2", + "fix-or-cr", + "fix-or-sendback", + "to-hankaku", + "to-zenkaku", + "to-hiragana", + "to-katakana", + "backspace", + "delete", + "kill-line", + "carriage-return", + "fix-and-write", + "beep", + "jiscode-begin", + "jiscode-end", + "kutencode-begin", + "kutencode-end", + "symbol-input", + "end-conversion", + "send-back", + "convert-move-top-or-sendback", + "convert-move-top-or-space", + "clear-or-cancel", + "backspace-or-cancel", + "delete-or-cancel", + "convert-next-or-move-top-or-sendback", + "convert-next-or-move-top-or-space", + "select", + "select-s", + "register", +}; +#define FTSIZE (sizeof(fepfunctbl) / sizeof(char *)) + +static void convert(); +static void convert_f1(); +static void convert_sb(); +static void convert_sp(); +static void convert_s(); +static void convert_mt_sb(); +static void convert_mt_sp(); +static void unconvert(); +static void egg_select(); +static void egg_select_s(); + +static void move_forward(); +static void move_backward(); +static void move_top(); +static void move_bottom(); + +static void cand_next(); +static void cand_next_s(); +static void cand_next_mt_sb(); +static void cand_next_mt_sp(); +static void cand_prev(); +static void cand_prev_s(); + +static void expand_cl(); +static void expand_cl_s(); +static void shrink_cl(); +static void shrink_cl_s(); +static void expand_cl2(); +static void expand_cl2_s(); +static void shrink_cl2(); +static void shrink_cl2_s(); + +static void clear_buffer(); +static void clear_c(); + +static void sel_top(); +static void sel_bottom(); +static void sel_forward(); +static void sel_backward(); +static void sel_next(); +static void sel_prev(); +static void sel_select(); +static void sel_abort(); + +static void fix(); +static void fix1(); +static void fix_cr(); +static void fix_sb(); + +static void hankaku(); +static void zenkaku(); + +static void hiragana(); +static void katakana(); + +static void backspace(); +static void backspace_c(); +static void delete(); +static void delete_c(); +static void kill_line(); + +static void bell(); +static void beep(); +static void carriageret(); +static void jiscode_begin(); +static void jiscode_end(); +static void kuten_begin(); +static void kuten_end(); + +static void sym_input(); +static void convend(); +static void send_back(); +static void register_word(); + +/* cconv function dispatch table */ +static void (*functable[][3])() = { +/* Function Name Normal-mode selection-mode symbol-mode */ +/* convert */ convert, sel_forward, beep, +/* convert-or-fix1 */ convert_f1, sel_forward, beep, +/* convert-or-sendback*/convert_sb, sel_forward, beep, +/* convert-or-space */ convert_sp, sel_forward, beep, +/* convert-s */ convert_s, sel_forward, beep, +/* unconvert */ unconvert, beep, beep, +/* next */ cand_next, sel_next, sel_next, +/* next-s */ cand_next_s, sel_next, sel_next, +/* previous */ cand_prev, sel_prev, sel_prev, +/* previous-s */ cand_prev_s, sel_prev, sel_prev, +/* forward */ move_forward, sel_forward, sel_forward, +/* backward */ move_backward, sel_backward, sel_backward, +/* move-top */ move_top, sel_top, sel_top, +/* move-bottom */ move_bottom, sel_bottom, sel_bottom, +/* clear */ clear_buffer, clear_buffer, clear_buffer, +/* expand */ expand_cl, expand_cl, beep, +/* expand-s */ expand_cl_s, expand_cl_s, beep, +/* shrink */ shrink_cl, shrink_cl, beep, +/* shrink-s */ shrink_cl_s, shrink_cl_s, beep, +/* expand-noconv */ expand_cl2, expand_cl2, beep, +/* expand-noconv-s */ expand_cl2_s, expand_cl2_s, beep, +/* shrink-noconv */ shrink_cl2, shrink_cl2, beep, +/* shrink-noconv-s */ shrink_cl2_s, shrink_cl2_s, beep, +/* fix */ fix, fix, fix, +/* fix2 */ fix, fix, fix, +/* fix-or-cr */ fix_cr, sel_select, sel_select, +/* fix-or-sendback */ fix_sb, sel_select, sel_select, +/* to-hankaku */ hankaku, hankaku, beep, +/* to-zenkaku */ zenkaku, zenkaku, beep, +/* to-hiragana */ hiragana, hiragana, beep, +/* to-katakana */ katakana, katakana, beep, +/* backspace */ backspace, backspace, backspace, +/* delete */ delete, delete, delete, +/* kill-line */ kill_line, kill_line, kill_line, +/* carriage-return */ carriageret, sel_select, sel_select, +/* fix-and-write */ fix, beep, beep, +/* beep */ bell, bell, bell, +/* jiscode-begin */ jiscode_begin, beep, beep, +/* jiscode-end */ jiscode_end, beep, beep, +/* kutencode-begin */ kuten_begin, beep, beep, +/* kutencode-end */ kuten_end, beep, beep, +/* symbol-input */ sym_input, beep, sel_abort, +/* end-conversion */ convend, convend, convend, +/* send-back */ send_back, send_back, send_back, +/* convert-move-..sb*/ convert_mt_sb, sel_forward, beep, +/* convert-move-..sp*/ convert_mt_sp, sel_forward, beep, +/* clear-or-cancel */ clear_c, clear_c, clear_c, +/* backspace-or-cancel */ backspace_c, backspace_c, backspace_c, +/* delete-or-cancel */ delete_c, delete_c, delete_c, +/* convert-next-..sb */ cand_next_mt_sb, sel_forward, beep, +/* convert-next-..sp */ cand_next_mt_sp, sel_forward, beep, +/* select */ egg_select, beep, beep, +/* select-s */ egg_select_s, beep, beep, +/* register */ register_word, beep, beep, +}; + +static ICString *SymbolList; +static int NumSymbols; + +static void ccInitialize(); +static void jcInitialize(); +static void createEnvError(); +static int createConfirm(); + +static int funcDispatch(); +static void defAction(); +static void insChar(); +static void delChar(); +static void autoFix(); + +static void startSelection(); +static void moveSelection(); +static int endSelection(); +static int insertSelection(); + +static int getSymbol(); + +static void normalState(); + +static void allocCandlist(); +static void allocStrdata(); +static void getAllCandidates(); + +static void addObject(); +static void deleteObject(); +static void serverDead(); + +static void saveData(); +static void restoreData(); + +static void ioeCallback(); + +static CcWnnObject findSelectionObj(); + +static Boolean convertSelection(); +static void saveYomiAndKanji(); + +static void +ClassInitialize() +{ + /* symbollist $B$r@_Dj(B */ + NumSymbols = buildSymbolList(&SymbolList); + /* I/O error $B%3!<%k%P%C%/4X?t$N@_Dj(B */ + XIOESet(ioeCallback, (XPointer)NULL); +} + +static int +buildSymbolList(listp) +ICString **listp; +{ + static struct symgroup { + int first; + int last; + } symgroups[] = { + { 0xa1a1, 0xa2ae }, /* '$B!!(B' - '$B".(B' */ + { 0xa2ba, 0xa2c1 }, /* '$B":(B' - '$B"A(B' */ + { 0xa2ca, 0xa2d0 }, /* '$B"J(B' - '$B"P(B' */ + { 0xa2dc, 0xa2ea }, /* '$B"\(B' - '$B"j(B' */ + { 0xa2f2, 0xa2f9 }, /* '$B"r(B' - '$B"y(B' */ + { 0xa2fe, 0xa2fe }, /* '$B"~(B' */ + { 0xa4ee, 0xa4ee }, /* '$B$n(B' */ + { 0xa4f0, 0xa4f1 }, /* '$B$p(B', '$B$q(B' */ + { 0xa5ee, 0xa5ee }, /* '$B%n(B' */ + { 0xa5f0, 0xa5f1 }, /* '$B%p(B', '$B%q(B' */ + { 0xa5f4, 0xa5f6 }, /* '$B%t(B', '$B%u(B', '$B%v(B' */ + { 0xa6a1, 0xa6b8 }, /* '$B&!(B' - '$B&8(B' */ + { 0xa6c1, 0xa6d8 }, /* '$B&A(B' - '$B&X(B' */ + { 0xa7a1, 0xa7c1 }, /* '$B'!(B' - '$B'A(B' */ + { 0xa7d1, 0xa7f1 }, /* '$B'Q(B' - '$B'q(B' */ + { 0xa8a1, 0xa8c0 }, /* '$B(!(B' - '$B(@(B' */ + { -1, -1 } + }; + struct symgroup *sgp; + Cardinal nsyms; + ICString *symlist, *sp; + wchar *buf, *p; + + for (nsyms = 0, sgp = symgroups; sgp->first > 0; sgp++) { +#define LINEAR_INDEX(c) (((((c)>>8)&0x7f)*94)+((c)&0x7f)) + nsyms += LINEAR_INDEX(sgp->last) - LINEAR_INDEX(sgp->first) + 1; + } + + symlist = (ICString *)XtMalloc(nsyms * sizeof(ICString)); + buf = (wchar *)XtMalloc(nsyms * sizeof(wchar)); + + sp = symlist; + p = buf; + for (sgp = symgroups; sgp->first > 0; sgp++) { + int i; +#define NEXT_CHAR(c) ((((c)&0xff)>0xfd)?(((c)&0xff00)+0x1a1):((c)+1)) + for (i = sgp->first; i <= sgp->last; i = NEXT_CHAR(i)) { + sp->nchars = 1; + sp->nbytes = sizeof(wchar); + sp->data = (char *)p; + sp->attr = ICAttrNormalString; + sp++; + *p++ = i; + } + } + + *listp = symlist; + return nsyms; +} + +static int +InputEvent(w, event) +Widget w; +XEvent *event; +{ + CcWnnObject obj = (CcWnnObject)w; + int sendback; + int ret = 0; + wchar *curmode; + + if (event->type != KeyPress /*&& event->type != KeyRelease*/) return 0; + + /* $B%$%Y%s%H$r%/%i%$%"%s%H$KAw$jJV$9$+$I$&$+$NH=Dj$=$N(B 1 */ + sendback = (NumSegments(w) == 0 && obj->ccWnn.state == normal_state); + + obj->ccWnn.sendbackevent = False; + obj->ccWnn.fixperformed = False; + obj->ccWnn.textchanged = False; + + /* + * $B$b$7!"(Bwnnbuf $B$,L$3MF@$G$"$k$+(B ($B$3$s$J$3$H$O!"$"$j$($J$$$H;W$&$,(B)$B!"(B + * jserver $B$,;`$s$@$J$I$NM}M3$G(B jserver $B$H$N@\B3$,@Z$l$F$$$k$J$i$P!":F(B + * $B=i4|2=!J:F@\B3!K$r9T$J$&!#(B + */ + if (obj->ccWnn.wnnbuf == NULL || !jcIsConnect(obj->ccWnn.wnnbuf)) { + jcInitialize(obj); + /* $B:F@\B3$r;n$_$F$b!"$^$@@\B3$G$-$F$$$J$$$H$-$O!"%(%i!<$rJV$9(B */ + if (obj->ccWnn.wnnbuf == NULL || !jcIsConnect(obj->ccWnn.wnnbuf)) { + bell(obj); + return -1; + } + } + + wnn_errorno = 0; + curmode = ccGetModePrompt(obj->ccWnn.ccbuf); + + (void)ccConvchar(obj->ccWnn.ccbuf, (XKeyPressedEvent *)event); + + /* + * $B%(%i!<HV9f$r%A%'%C%/$7!"(Bjserver $B$,;`$s$G$$$l$P4D6-$r(B destroy $B$7(B + * $B:F$S@\B3$r;n$_$k(B + */ + if (wnn_errorno == WNN_JSERVER_DEAD) { + XtAppWarning(XtWidgetToApplicationContext((Widget)w), + "ccWnn Object: jserver died"); + /* $B$b$7$bF~NOCf$NJ8;zNs$,$"$l$P$H$C$F$*$/(B */ + saveData(obj); + serverDead(); + /* secondary jserver $B$,;XDj$5$l$F$$$l$P:F@\B3$r;n$_$k(B */ + if (obj->ccWnn.jservername2 != NULL) jcInitialize(obj); + if (obj->ccWnn.wnnbuf == NULL || !jcIsConnect(obj->ccWnn.wnnbuf)) { + bell(obj); + ret = -1; + } + } + + /* $B%F%-%9%H$NJQ2=$r%A%'%C%/$9$k(B */ + if (obj->ccWnn.textchanged) { + XtCallCallbackList(w, obj->inputConv.textchangecallback, + (XtPointer)NULL); + obj->ccWnn.textchanged = False; + } + /* $BF~NO%b!<%I$r%A%'%C%/$9$k(B */ + if (wstrcmp(ccGetModePrompt(obj->ccWnn.ccbuf), curmode)) { + sendback = 0; + XtCallCallbackList(w, obj->inputConv.modechangecallback, + (XtPointer)NULL); + } + /* $B%$%Y%s%H$r%/%i%$%"%s%H$KAw$jJV$9$+$I$&$+$NH=Dj$=$N(B 2 */ + if (NumSegments(w) != 0 || + obj->ccWnn.state != normal_state || + obj->ccWnn.fixperformed) { + sendback = 0; + } + if (ret == 0 && (obj->ccWnn.sendbackevent || sendback)) ret = 1; + + return ret; +} + +static ICString * +GetMode(w) +Widget w; +{ + CcWnnObject obj = (CcWnnObject)w; + wchar *mode; + static ICString icstr; + + mode = ccGetModePrompt(obj->ccWnn.ccbuf); + icstr.data = (char *)mode; + icstr.nchars = wstrlen(mode); + icstr.nbytes = icstr.nchars * sizeof(wchar); + icstr.attr = ICAttrNormalString; + + return &icstr; +} + +static int +CursorPos(w, nsegp, ncharp) +Widget w; +Cardinal *nsegp; +Cardinal *ncharp; +{ + CcWnnObject obj = (CcWnnObject)w; + jcConvBuf *jcbuf = obj->ccWnn.jcbuf; + Cardinal nseg, nchar; + + if (jcbuf == NULL || jcIsConverted(jcbuf, jcbuf->curClause)) return 0; + + nseg = jcbuf->curClause; + nchar = jcDotOffset(jcbuf); + + if (nseg >= jcbuf->nClause) { + if (nseg == 0) { + nchar = 0; + } else { + jcClause *cinfo = jcbuf->clauseInfo; + nseg--; + nchar = cinfo[nseg + 1].dispp - cinfo[nseg].dispp; + } + } + + if (nsegp) *nsegp = nseg; + if (ncharp) *ncharp = nchar; + + return 1; +} + +static int +NumSegments(w) +Widget w; +{ + CcWnnObject obj = (CcWnnObject)w; + + return (obj->ccWnn.jcbuf != NULL) ? obj->ccWnn.jcbuf->nClause : 0; +} + +static ICString * +GetSegment(w, n) +Widget w; +Cardinal n; +{ + CcWnnObject obj = (CcWnnObject)w; + jcConvBuf *jcbuf = obj->ccWnn.jcbuf; + jcClause *cinfo = jcbuf->clauseInfo; + static ICString seg; + + if (jcbuf == NULL || n >= jcbuf->nClause) return NULL; + seg.data = (char *)cinfo[n].dispp; + seg.nchars = cinfo[n + 1].dispp - cinfo[n].dispp; + seg.nbytes = seg.nchars * sizeof(wchar); + seg.attr = cinfo[n].conv ? ICAttrConverted : ICAttrNotConverted; + if (n == jcbuf->curClause) { + seg.attr |= ICAttrCurrentSegment; + } else if (jcbuf->curLCStart <= n && n < jcbuf->curLCEnd) { + seg.attr |= ICAttrCurrentSubSegment; + } + 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; +{ + CcWnnObject obj = (CcWnnObject)w; + + switch (obj->ccWnn.state) { + case selection_l_state: + case selection_s_state: + *n = obj->ccWnn.numcand; + return obj->ccWnn.candlist; + case symbol_state: + *n = obj->ccWnn.numsymbols; + return obj->ccWnn.symbollist; + default: + *n = 0; + return NULL; /* no item available */ + } + /* NOTREACHED */ +} + +static int +SelectItem(w, n) +Widget w; +int n; +{ + CcWnnObject obj = (CcWnnObject)w; + int ret = 0; + + if (obj->ccWnn.state == normal_state) return -1; + + if (obj->ccWnn.jcbuf == NULL) { + ret = -1; + } else if (n >= 0) { + ret = insertSelection(obj, n); + if (obj->ccWnn.textchanged) { + XtCallCallbackList((Widget)obj, + obj->inputConv.textchangecallback, + (XtPointer)NULL); + obj->ccWnn.textchanged = False; + } + } + + obj->ccWnn.state = normal_state; + return ret; +} + +static int +ConvertedString(w, encoding, format, length, string) +Widget w; +Atom *encoding; +int *format; +int *length; +XtPointer *string; +{ + CcWnnObject obj = (CcWnnObject)w; + jcConvBuf *jcbuf = obj->ccWnn.jcbuf; + wchar *wbuf, *wp; + int len, wlen; + extern int convJWStoCT(); + + if (jcbuf == NULL) return -1; + + wlen = jcbuf->displayEnd - jcbuf->displayBuf; + if (wlen == 0) return -1; + + /* + * jcbuf $B$KF~$C$F$$$kJQ49%F%-%9%H$O(B null $B%?!<%_%M!<%H$5$l$F$$$J$$$N$G(B + * $B$^$:%3%T!<$7$F(B null $B%?!<%_%M!<%H$9$k(B + */ + wbuf = (wchar *)XtMalloc((wlen + 1) * sizeof(wchar)); + (void)bcopy((char *)jcbuf->displayBuf, (char *)wbuf, + sizeof(wchar) * wlen); + wbuf[wlen] = 0; + + /* + * CcWnn $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); + + /* wbuf $B$r(B free $B$7$F$*$/(B */ + XtFree((char *)wbuf); + + return 0; +} + +static int +ClearConversion(w) +Widget w; +{ + CcWnnObject obj = (CcWnnObject)w; + + if (obj->ccWnn.jcbuf == NULL) { + return 0; /* not -1, because it's already cleared */ + } + clear_buffer(obj); + XtCallCallbackList(w, obj->inputConv.textchangecallback, (XtPointer)NULL); + return 0; +} + +/* ARGSUSED */ +static ICString * +GetAuxSegments(w, n, ns, nc) +Widget w; +Cardinal *n, *ns, *nc; +{ + /* CcWnn doesn't use AuxPanel */ + XtAppWarning(XtWidgetToApplicationContext(w), + "ccWnn Object: GetAuxSegments shouldn't be called"); + return NULL; +} + +/* ARGSUSED */ +static void +Initialize(req, new, args, num_args) +Widget req; +Widget new; +ArgList args; +Cardinal *num_args; +{ + CcWnnObject obj = (CcWnnObject)new; + + obj->ccWnn.ccrule = NULL; + obj->ccWnn.jcbuf = NULL; + obj->ccWnn.state = normal_state; + obj->ccWnn.selectionending = False; + obj->ccWnn.textchanged = False; + obj->ccWnn.symbollist = SymbolList; + obj->ccWnn.numsymbols = NumSymbols; + obj->ccWnn.cursymbol = 0; + obj->ccWnn.candlist = NULL; + obj->ccWnn.candlistsize = 0; + obj->ccWnn.numcand = 0; + obj->ccWnn.strdata = NULL; + obj->ccWnn.strdatasize = 0; + obj->ccWnn.inputmode = OTHERS; + obj->ccWnn.pendingdata = NULL; + obj->ccWnn.fixcount = 0; + obj->ccWnn.selwidget = NULL; + obj->ccWnn.selyomi = obj->ccWnn.selkanji = NULL; + + /* $BJQ49$N=i4|2=(B */ + obj->ccWnn.createrule = False; + obj->ccWnn.createenv = False; + ccInitialize(obj); + jcInitialize(obj); + + addObject(obj); +} + +static void +ccInitialize(obj) +CcWnnObject obj; +{ + extern char *getenv(); + + if (obj->ccWnn.createrule) { + ccDestroyBuf(obj->ccWnn.ccbuf); + obj->ccWnn.ccbuf = NULL; + } + if (obj->ccWnn.ccrule == NULL) { + if (obj->ccWnn.ccdeffile == NULL) { + obj->ccWnn.ccdeffile = getenv("CC_DEF"); + if (obj->ccWnn.ccdeffile == NULL) { + obj->ccWnn.ccdeffile = DEF_CCDEF_FILE; + } + } + obj->ccWnn.ccrule = ccParseRule(obj->ccWnn.ccdeffile, XtWarning); + obj->ccWnn.createrule = True; + } + + if (obj->ccWnn.ccrule == NULL) { + XtAppError(XtWidgetToApplicationContext((Widget)obj), + "CcWnn Object: cconv initialization failed."); + } + + obj->ccWnn.ccbuf = ccCreateBuf(obj->ccWnn.ccrule, 16, + fepfunctbl, FTSIZE, + defAction, insChar, delChar, + funcDispatch, autoFix, NULL, (caddr_t)obj); +} + +static CcWnnObject current_obj = NULL; + +static void +jcInitialize(obj) +CcWnnObject obj; +{ + if (obj->ccWnn.createenv) { + (void)jcDestroyBuffer(obj->ccWnn.jcbuf, 0); + obj->ccWnn.jcbuf = NULL; + obj->ccWnn.createenv = False; + } + + if (obj->ccWnn.wnnbuf == NULL || !jcIsConnect(obj->ccWnn.wnnbuf)) { + if (obj->ccWnn.wnnbuf != NULL) { + jcClose(obj->ccWnn.wnnbuf); + obj->ccWnn.wnnbuf = NULL; + } + if (obj->ccWnn.wnnenvname == NULL) obj->ccWnn.wnnenvname = ""; + if (obj->ccWnn.wnnenvrcfile == NULL) obj->ccWnn.wnnenvrcfile = ""; + if (obj->ccWnn.wnnenvrcfile4 == NULL) { + obj->ccWnn.wnnenvrcfile4 = obj->ccWnn.wnnenvrcfile; + } + if (obj->ccWnn.wnnenvrcfile6 == NULL) { + obj->ccWnn.wnnenvrcfile6 = obj->ccWnn.wnnenvrcfile; + } + + /* + * jllib $B$N%3!<%k%P%C%/$G$O!"%/%i%$%"%s%H!&%G!<%?$rEO$;$J$$$N(B + * $B$G!"3P$($F$*$/!#(B + */ + current_obj = obj; + obj->ccWnn.wnnbuf = jcOpen2(obj->ccWnn.jservername, + obj->ccWnn.wnnenvname, + obj->ccWnn.wnnoverrideenv, + obj->ccWnn.wnnenvrcfile4, + obj->ccWnn.wnnenvrcfile6, + createEnvError, + createConfirm, + 30); + /* wnnbuf $B$,3MF@$G$-$J$1$l$P!"$=$N$^$^%j%?!<%s(B */ + if (obj->ccWnn.wnnbuf == NULL) { + XtAppWarning(XtWidgetToApplicationContext((Widget)obj), + "ccWnn Object: can't open jserver"); + return; + } + + /* jserver $B$H@\B3$5$l$F$$$J$1$l$P!"%;%+%s%@%j$r;n$7$F$_$k(B */ + if (!jcIsConnect(obj->ccWnn.wnnbuf) + && obj->ccWnn.jservername2 != NULL) { + jcClose(obj->ccWnn.wnnbuf); + current_obj = obj; + obj->ccWnn.wnnbuf = jcOpen2(obj->ccWnn.jservername2, + obj->ccWnn.wnnenvname, + obj->ccWnn.wnnoverrideenv, + obj->ccWnn.wnnenvrcfile4, + obj->ccWnn.wnnenvrcfile6, + createEnvError, + createConfirm, + 30); + if (obj->ccWnn.wnnbuf == NULL) { + XtAppWarning(XtWidgetToApplicationContext((Widget)obj), + "ccWnn Object: can't open jserver"); + return; + } + } + obj->ccWnn.createenv = True; + if (!jcIsConnect(obj->ccWnn.wnnbuf)) { + XtAppWarning(XtWidgetToApplicationContext((Widget)obj), + "ccWnn Object: can't connect to jserver"); + } + } + /* $B@\B3$G$-$J$/$F$b%P%C%U%!$O:n$C$F$*$/(B */ + obj->ccWnn.jcbuf = jcCreateBuffer(obj->ccWnn.wnnbuf, 10, 80); + if (obj->ccWnn.pendingdata) restoreData(obj); +} + +static void +createEnvError(s) +char *s; +{ + if (current_obj != NULL) + XtAppWarning(XtWidgetToApplicationContext((Widget)current_obj), s); +} + +static int +createConfirm(s) +char *s; +{ + if (current_obj != NULL && current_obj->ccWnn.confirmfunc != NULL) + return (*current_obj->ccWnn.confirmfunc)((Widget)current_obj, s); + return 1; +} + +static void +Destroy(w) +Widget w; +{ + CcWnnObject obj = (CcWnnObject)w; + + /* $B%P%C%U%!$N2rJ|(B */ + if (obj->ccWnn.ccbuf) ccDestroyBuf(obj->ccWnn.ccbuf); + if (obj->ccWnn.jcbuf) jcDestroyBuffer(obj->ccWnn.jcbuf, 1); + + /* $B$b$7(B Initialize() $BCf$G%k!<%k(B/$B4D6-$r:n$C$?$N$G$"$l$P2rJ|$9$k(B */ + if (obj->ccWnn.createrule) ccFreeRule(obj->ccWnn.ccrule); + if (obj->ccWnn.createenv) jcClose(obj->ccWnn.wnnbuf); + + if (obj->ccWnn.candlist) XtFree((char *)obj->ccWnn.candlist); + if (obj->ccWnn.strdata) XtFree((char *)obj->ccWnn.strdata); + + if (obj->ccWnn.pendingdata) XtFree((char *)obj->ccWnn.pendingdata); + + if (obj->ccWnn.selwidget) XtDestroyWidget(obj->ccWnn.selwidget); + if (obj->ccWnn.selyomi) XtFree(obj->ccWnn.selyomi); + if (obj->ccWnn.selkanji) XtFree(obj->ccWnn.selkanji); + + deleteObject(obj); +} + +/* ARGSUSED */ +static Boolean +SetValues(cur, req, wid, args, num_args) +Widget cur; +Widget req; +Widget wid; +ArgList args; +Cardinal *num_args; +{ + CcWnnObject old = (CcWnnObject)cur; + CcWnnObject new = (CcWnnObject)wid; + + if (old->ccWnn.ccdeffile != new->ccWnn.ccdeffile || + old->ccWnn.wnnbuf != new->ccWnn.wnnbuf || + old->ccWnn.ccrule != new->ccWnn.ccrule) { + XtAppWarning(XtWidgetToApplicationContext(wid), + "ccWnn Object: can't change resource by XtSetValues()"); + } + return False; +} + + +/* + * cconv function dispatcher + */ + +/* ARGSUSED */ +static int +funcDispatch(func, str, nbytes, w) +int func; +unsigned char *str; +int nbytes; +caddr_t w; +{ + CcWnnObject obj = (CcWnnObject)w; + + obj->ccWnn.cont = True; + if (func < 0 || func >= FTSIZE) return True; + + wnn_errorno = 0; + + switch (obj->ccWnn.state) { + case selection_s_state: + case selection_l_state: + (*functable[func][1])(obj); + break; + case symbol_state: + (*functable[func][2])(obj); + break; + default: + (*functable[func][0])(obj); + break; + } + + return obj->ccWnn.cont; +} + +/* ARGSUSED */ +static void +defAction(str, nbytes, w) +unsigned char *str; +int nbytes; +caddr_t w; +{ + if (nbytes > 0) beep((CcWnnObject)w); +} + +#define ZERO 0xa3b0 +#define NINE 0xa3b9 +#define SmallA 0xa3e1 +#define SmallF 0xa3e6 +#define LargeA 0xa3c1 +#define LargeF 0xa3c6 +static int +toHex(c) +int c; +{ + if ('0' <= c && c <= '9') + return c - '0'; + if ('a' <= c && c <= 'f') + return c + 10 - 'a'; + if ('A' <= c && c <= 'F') + return c + 10 - 'A'; + if (ZERO <= c && c <= NINE) + return c - ZERO; + if (SmallA <= c && c <= SmallF) + return c + 10 - SmallA; + if (LargeA <= c && c <= LargeF) + return c + 10 - LargeA; + return -1; +} + +static int +toHex4(s) +wchar *s; +{ + int c, h, cnt, hex; + + hex = 0; + cnt = 0; + while (cnt < 4 && (c = *s++)) { + if ((h = toHex(c)) < 0) + return -1; + hex = hex * 16 + h; + cnt++; + } + if (cnt != 4) + return -1; + + return hex; +} + +static int +toKuten(s) +wchar *s; +{ + int i, c, d[4]; + + for (i = 0; i < 4 && (c = *s++); i++) { + if ((d[i] = toHex(c)) < 0 || d[i] >= 10) + return(-1); + } + if (i != 4) + return(-1); + return((((d[0] * 10 + d[1]) << 8) | (d[2] * 10 + d[3])) + 0x2020); +} + +static void +insChar(c, cldata) +int c; +caddr_t cldata; +{ + CcWnnObject obj = (CcWnnObject)cldata; + jcConvBuf *jcbuf = obj->ccWnn.jcbuf; + ccBuf ccbuf = obj->ccWnn.ccbuf; + wchar context[17]; + int h; + + normalState(obj); + + if (jcIsConverted(jcbuf, jcbuf->curClause)) { + (void)jcBottom(jcbuf); + } + + switch (obj->ccWnn.inputmode) { + case KUTEN_MODE: + case JIS_MODE: + /* $B%X%-%5$+$I$&$+$N%F%9%H(B */ + if ((h = toHex(c)) < 0 || (obj->ccWnn.inputmode == KUTEN_MODE && h >= 10)) { + beep(obj); + ccContextDelete(ccbuf); + break; + } + ccContextGet(ccbuf, context); + if (wstrlen(context) == 4) { + /* convert to KANJI */ + c = obj->ccWnn.inputmode == KUTEN_MODE ? toKuten(context): toHex4(context); + if (c < 0x2121 || 0x7e7e < c || (c & 0xff) < 0x21 || + 0x7e < (c & 0xff)) { + beep(obj); + break; + } + /* $B#3J8;z:o=|(B -- $B#4J8;zL\$O$^$@A^F~$7$F$$$J$$(B */ + jcDeleteChar(jcbuf, 1); + jcDeleteChar(jcbuf, 1); + jcDeleteChar(jcbuf, 1); + (void)jcInsertChar(jcbuf, c | 0x8080); + obj->ccWnn.textchanged = True; + /* $B%3%s%F%-%9%H$N%/%j%"(B */ + ccContextClear(ccbuf); + break; + } + /* fall thru */ + case OTHERS: + (void)jcInsertChar(jcbuf, c); + obj->ccWnn.textchanged = True; + break; + } +} + +static void +delChar(cldata) +caddr_t cldata; +{ + CcWnnObject obj = (CcWnnObject)cldata; + + if (obj->ccWnn.state != normal_state) { + beep(obj); + return; + } + ccContextDelete(obj->ccWnn.ccbuf); + jcDeleteChar(obj->ccWnn.jcbuf, 1); + obj->ccWnn.textchanged = True; +} + +static void +autoFix(cldata) +caddr_t cldata; +{ + CcWnnObject obj = (CcWnnObject)cldata; + + switch (obj->ccWnn.state) + { + case selection_s_state: + case selection_l_state: + case symbol_state: + fix(obj); + break; + default: + + if (jcIsConverted(obj->ccWnn.jcbuf, 0)) + fix(obj); + break; + } +} + +/* + * cconv functions + */ + +/* some convenient macros */ +#define JCBUF(obj) ((obj)->ccWnn.jcbuf) +#define CCBUF(obj) ((obj)->ccWnn.ccbuf) +#define HINT(obj) ((obj)->ccWnn.textchanged) + +/* $BJQ49%U%!%s%/%7%g%s72(B + * convert + * convert-sp + * convert-s + * unconvert + */ + +static void +convert_general(obj, small) +CcWnnObject obj; +int small; +{ + jcConvBuf *jcbuf = JCBUF(obj); + + if (jcbuf->curClause == jcbuf->nClause) { + (void)jcMove(jcbuf, small, JC_BACKWARD); + HINT(obj) = True; + } + + if (jcIsConverted(jcbuf, jcbuf->curClause)) { + startSelection(obj, small); + return; + } + + if (jcConvert(jcbuf, small, 0, 1) < 0) beep(obj); + ccContextClear(CCBUF(obj)); + HINT(obj) = True; +} + +static void +convert(obj) +CcWnnObject obj; +{ + convert_general(obj, 0); +} + +static void +convert_sb(obj) +CcWnnObject obj; +{ + if (JCBUF(obj)->nClause == 0) { + send_back(obj); + fix(obj); + } else { + convert_general(obj, 0); + } +} + +static void +convert_sp(obj) +CcWnnObject obj; +{ + if (JCBUF(obj)->nClause == 0) { + insChar(' ', (caddr_t)obj); + fix(obj); + } else { + convert_general(obj, 0); + } +} + +static void +convert_mt(obj) +CcWnnObject obj; +{ + jcConvBuf *jcbuf = JCBUF(obj); + if (jcbuf->nClause == 0) { + send_back(obj); + fix(obj); + } else { + int nc = jcbuf->nClause - 1; + convert_general(obj, 0); + if (!jcIsConverted(jcbuf, jcbuf->curClause)) { + int i; + move_top(obj); + if (nc < jcbuf->nClause) + for (i = 0; i < nc; i++) + move_forward(obj); + } + } +} + +static void +convert_f1(obj) +CcWnnObject obj; +{ + jcConvBuf *jcbuf = JCBUF(obj); + + if (0 < jcbuf->nClause && jcIsConverted(jcbuf, 0)) { + fix1(obj); + } else { + convert_general(obj, 0); + } +} + +static void +convert_mt_sb(obj) +CcWnnObject obj; +{ + jcConvBuf *jcbuf = JCBUF(obj); + if (jcbuf->nClause == 0) { + send_back(obj); + fix(obj); + } else { + int nc = jcbuf->nClause - 1; + convert_general(obj, 0); + if (!jcIsConverted(jcbuf, jcbuf->curClause)) { + int i; + move_top(obj); + if (nc < jcbuf->nClause) + for (i = 0; i < nc; i++) + move_forward(obj); + } + } +} + +static void +convert_mt_sp(obj) +CcWnnObject obj; +{ + jcConvBuf *jcbuf = JCBUF(obj); + if (jcbuf->nClause == 0) { + insChar(' ', (caddr_t)obj); + fix(obj); + } else { + int nc = jcbuf->nClause - 1; + convert_general(obj, 0); + if (!jcIsConverted(jcbuf, jcbuf->curClause)) { + int i; + move_top(obj); + if (nc < jcbuf->nClause) + for (i = 0; i < nc; i++) + move_forward(obj); + } + } +} + +static void +convert_s(obj) +CcWnnObject obj; +{ + convert_general(obj, 1); +} + +static void +unconvert(obj) +CcWnnObject obj; +{ + if (jcUnconvert(JCBUF(obj)) < 0) beep(obj); + ccContextClear(CCBUF(obj)); + HINT(obj) = True; +} + +static void +select_general(obj, small) +CcWnnObject obj; +int small; +{ + jcConvBuf *jcbuf = JCBUF(obj); + + if (jcbuf->curClause == jcbuf->nClause) { + (void)jcMove(jcbuf, small, JC_BACKWARD); + HINT(obj) = True; + } + + if (jcIsConverted(jcbuf, jcbuf->curClause)) { + startSelection(obj, small); + obj->ccWnn.cont = False; /* $B<!$N4X?t$O8F$P$J$$(B */ + } +} + + +static void +egg_select(obj) +CcWnnObject obj; +{ + select_general(obj, 0); +} + + +static void +egg_select_s(obj) +CcWnnObject obj; +{ + select_general(obj, 1); +} + +/* $B%+!<%=%k0\F0%U%!%s%/%7%g%s72(B + * move_forward + * move_backward + * move_top + * move_bottom + */ + +static void +move_general(obj, direction) +CcWnnObject obj; +int direction; +{ + int status = -1; + + switch (direction) { + case ICMoveLeftMost: + status = jcTop(JCBUF(obj)); + break; + case ICMoveRightMost: + status = jcBottom(JCBUF(obj)); + break; + case ICMoveRight: + status = jcMove(JCBUF(obj), 1, JC_FORWARD); + break; + case ICMoveLeft: + status = jcMove(JCBUF(obj), 1, JC_BACKWARD); + break; + } + + if (status < 0) beep(obj); + + ccContextClear(CCBUF(obj)); + + HINT(obj) = True; +} + +static void +move_forward(obj) +CcWnnObject obj; +{ + move_general(obj, ICMoveRight); +} + +static void +move_backward(obj) +CcWnnObject obj; +{ + move_general(obj, ICMoveLeft); +} + +static void +move_top(obj) +CcWnnObject obj; +{ + move_general(obj, ICMoveLeftMost); +} + +static void +move_bottom(obj) +CcWnnObject obj; +{ + move_general(obj, ICMoveRightMost); +} + + +/* $B8uJd@ZBX$(%U%!%s%/%7%g%s72(B + * cand_next + * cand_next_s + * cand_prev + * cand_prev_s + */ + +static void +cand_general(obj, small, type) +CcWnnObject obj; +int small; +int type; +{ + if (jcNext(JCBUF(obj), small, type) < 0) beep(obj); + ccContextClear(CCBUF(obj)); + HINT(obj) = True; +} + +static void +cand_next(obj) +CcWnnObject obj; +{ + cand_general(obj, 0, JC_NEXT); +} + +static void +cand_next_mt(obj) +CcWnnObject obj; +{ + jcConvBuf *jcbuf = JCBUF(obj); + if (jcIsConverted(jcbuf, jcbuf->curClause)) + cand_general(obj, 0, JC_NEXT); + else + convert_mt(obj); +} + +static void +cand_next_mt_sb(obj) +CcWnnObject obj; +{ + jcConvBuf *jcbuf = JCBUF(obj); + if (jcIsConverted(jcbuf, jcbuf->curClause)) + cand_general(obj, 0, JC_NEXT); + else + convert_mt_sb(obj); +} + +static void +cand_next_mt_sp(obj) +CcWnnObject obj; +{ + jcConvBuf *jcbuf = JCBUF(obj); + if (jcIsConverted(jcbuf, jcbuf->curClause)) + cand_general(obj, 0, JC_NEXT); + else + convert_mt_sp(obj); +} + +static void +cand_next_s(obj) +CcWnnObject obj; +{ + cand_general(obj, 1, JC_NEXT); +} + +static void +cand_prev(obj) +CcWnnObject obj; +{ + cand_general(obj, 0, JC_PREV); +} + +static void +cand_prev_s(obj) +CcWnnObject obj; +{ + cand_general(obj, 1, JC_PREV); +} + + +/* $BJ8@aD9JQ99%U%!%s%/%7%g%s72(B + * expand_cl + * expand_cl_s + * expand_cl2 + * expand_cl2_s + * shrink_cl + * shrink_cl_s + * shrink_cl2 + * shrink_cl2_s + */ + +static void +expand_shrink_general(obj, shrink, small, conv) +CcWnnObject obj; +int shrink; +int small; +int conv; +{ + int status; + + normalState(obj); + + if (shrink) { + status = jcShrink(JCBUF(obj), small, conv); + } else { + status = jcExpand(JCBUF(obj), small, conv); + } + if (status < 0) beep(obj); + + ccContextClear(CCBUF(obj)); + HINT(obj) = True; +} + +static void +expand_cl(obj) +CcWnnObject obj; +{ + expand_shrink_general(obj, 0, 0, 1); +} + +static void +expand_cl_s(obj) +CcWnnObject obj; +{ + expand_shrink_general(obj, 0, 1, 1); +} + +static void +shrink_cl(obj) +CcWnnObject obj; +{ + expand_shrink_general(obj, 1, 0, 1); +} + +static void +shrink_cl_s(obj) +CcWnnObject obj; +{ + expand_shrink_general(obj, 1, 1, 1); +} + +static void +expand_cl2(obj) +CcWnnObject obj; +{ + expand_shrink_general(obj, 0, 0, 0); +} + +static void +expand_cl2_s(obj) +CcWnnObject obj; +{ + expand_shrink_general(obj, 0, 1, 0); +} + +static void +shrink_cl2(obj) +CcWnnObject obj; +{ + expand_shrink_general(obj, 1, 0, 0); +} + +static void +shrink_cl2_s(obj) +CcWnnObject obj; +{ + expand_shrink_general(obj, 1, 1, 0); +} + + +/* $BJQ49%P%C%U%!%/%j%"%U%!%s%/%7%g%s(B + * clear_buffer + */ + +static void +clear_buffer(obj) +CcWnnObject obj; +{ + normalState(obj); + if (jcClear(JCBUF(obj)) < 0) beep(obj); + ccContextClear(CCBUF(obj)); + HINT(obj) = True; +} + +static void +cancel(obj) +CcWnnObject obj; +{ + if (jcCancel(JCBUF(obj)) < 0) beep(obj); + ccContextClear(CCBUF(obj)); + move_bottom(obj); + HINT(obj) = True; +} + + +static void +clear_c(obj) +CcWnnObject obj; +{ + switch (obj->ccWnn.state) + { + case selection_s_state: + case selection_l_state: + endSelection(obj, False); + cancel(obj); + break; + case symbol_state: + clear_buffer(obj); + break; + default: + if (jcIsConverted(JCBUF(obj), JCBUF(obj)->curClause)) + cancel(obj); + else + clear_buffer(obj); + break; + } +} + +/* $B8uJd0\F0%U%!%s%/%7%g%s72(B + * sel_next + * sel_prev + * sel_top + * sel_bottom + * sel_forward + * sel_backward + */ + +static void +sel_top(obj) +CcWnnObject obj; +{ + moveSelection(obj, ICMoveLeftMost); +} + +static void +sel_bottom(obj) +CcWnnObject obj; +{ + moveSelection(obj, ICMoveRightMost); +} + +static void +sel_forward(obj) +CcWnnObject obj; +{ + moveSelection(obj, ICMoveRight); +} + +static void +sel_backward(obj) +CcWnnObject obj; +{ + moveSelection(obj, ICMoveLeft); +} + +static void +sel_next(obj) +CcWnnObject obj; +{ + moveSelection(obj, ICMoveDown); +} + +static void +sel_prev(obj) +CcWnnObject obj; +{ + moveSelection(obj, ICMoveUp); +} + +static void +sel_select(obj) +CcWnnObject obj; +{ + endSelection(obj, False); +} + +static void +sel_abort(obj) +CcWnnObject obj; +{ + endSelection(obj, True); +} + +static void +fix(obj) +CcWnnObject obj; +{ + jcConvBuf *jcbuf = JCBUF(obj); + + normalState(obj); + ccContextClear(CCBUF(obj)); + + if (jcbuf->nClause > 0) { + obj->ccWnn.fixperformed = True; + + if (jcFix(jcbuf) < 0) { + beep(obj); + return; + } + + /* $B<-=q%;!<%V$N=hM}(B */ + obj->ccWnn.fixcount++; + if (obj->ccWnn.saveinterval > 0 && + obj->ccWnn.fixcount >= obj->ccWnn.saveinterval) { + jcSaveDic(jcbuf); + obj->ccWnn.fixcount = 0; + } + + /* $B3NDj$N=hM}(B */ + XtCallCallbackList((Widget)obj, obj->inputConv.fixcallback, + (XtPointer)NULL); /* ??? */ + + HINT(obj) = True; + } + + /* $B%P%C%U%!$r%/%j%"$9$k(B */ + jcClear(jcbuf); +} + +static void +fix1(obj) +CcWnnObject obj; +{ + jcConvBuf *jcbuf = JCBUF(obj); + + normalState(obj); + ccContextClear(CCBUF(obj)); + + if (jcbuf->nClause > 0) { + obj->ccWnn.fixperformed = True; + + if (jcFix1(jcbuf) < 0) { /* $B$3$3$@$1$,(B fix(obj) $B$H0c$&$H$3$m(B */ + beep(obj); + return; + } + + /* $B<-=q%;!<%V$N=hM}(B */ + obj->ccWnn.fixcount++; + if (obj->ccWnn.saveinterval > 0 && + obj->ccWnn.fixcount >= obj->ccWnn.saveinterval) { + jcSaveDic(jcbuf); + obj->ccWnn.fixcount = 0; + } + + /* $B3NDj$N=hM}(B */ + XtCallCallbackList((Widget)obj, obj->inputConv.fixcallback, + (XtPointer)NULL); /* ??? */ + + HINT(obj) = True; + } + + /* $B%P%C%U%!$r%/%j%"$9$k(B */ + jcClear(jcbuf); +} + +static void +fix_cr(obj) +CcWnnObject obj; +{ + if (JCBUF(obj)->nClause == 0) { + carriageret(obj); + } else { + fix(obj); + } +} + + +static void +fix_sb(obj) +CcWnnObject obj; +{ + if (JCBUF(obj)->nClause == 0) { + send_back(obj); + } else { + fix(obj); + } +} + + +static void +to_hankaku(start, end, res) +wchar *start; +wchar *end; +wchar *res; +{ + static unsigned short hiratohan[] = { /* $BA43Q$+$J(B <-> $BH>3Q$+$J(B */ +#define D (0xde<<8) /* $BBy2;(B */ +#define H (0xdf<<8) /* $BH>By2;(B */ + /* a */ 0xa7, 0xb1, 0xa8, 0xb2, 0xa9, 0xb3, 0xaa, 0xb4, 0xab, 0xb5, + /* k */ 0xb6, 0xb6|D, 0xb7, 0xb7|D, 0xb8, 0xb8|D, + 0xb9, 0xb9|D, 0xba, 0xba|D, + /* s */ 0xbb, 0xbb|D, 0xbc, 0xbc|D, 0xbd, 0xbd|D, + 0xbe, 0xbe|D, 0xbf, 0xbf|D, + /* t */ 0xc0, 0xc0|D, 0xc1, 0xc1|D, 0xaf, 0xc2, 0xc2|D, + 0xc3, 0xc3|D, 0xc4, 0xc4|D, + /* n */ 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, + /* h */ 0xca, 0xca|D, 0xca|H, 0xcb, 0xcb|D, 0xcb|H, 0xcc, 0xcc|D, + 0xcc|H, 0xcd, 0xcd|D, 0xcd|H, 0xce, 0xce|D, 0xce|H, + /* m */ 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, + /* y */ 0xac, 0xd4, 0xad, 0xd5, 0xae, 0xd6, + /* r */ 0xd7, 0xd8, 0xd9, 0xda, 0xdb, + /* w */ 0xdc, 0xdc, 0xb2, 0xb4, 0xa6, + /* n */ 0xdd +#undef D +#undef H + }; + static struct symzenhan { + unsigned short zen; + unsigned char han; + } kigoutohan[] = { /* $BA43Q5-9f(B -> $BH>3Q5-9f(B */ + 0xa1a1, 0x20, 0xa1a2, 0xa4, 0xa1a3, 0xa1, 0xa1a4, 0x2c, + 0xa1a5, 0x2e, 0xa1a6, 0xa5, 0xa1a7, 0x3a, 0xa1a8, 0x3b, + 0xa1a9, 0x3f, 0xa1aa, 0x21, 0xa1ab, 0xde, 0xa1ac, 0xdf, + 0xa1b0, 0x5e, 0xa1b2, 0x5f, 0xa1bc, 0xb0, 0xa1bf, 0x2f, + 0xa1c1, 0x7e, 0xa1c3, 0x7c, 0xa1c6, 0x60, 0xa1c7, 0x27, + 0xa1c8, 0x22, 0xa1c9, 0x22, 0xa1ca, 0x28, 0xa1cb, 0x29, + 0xa1cc, 0x5b, 0xa1cd, 0x5d, 0xa1ce, 0x5b, 0xa1cf, 0x5d, + 0xa1d0, 0x7b, 0xa1d1, 0x7d, 0xa1d6, 0xa2, 0xa1d7, 0xa3, + 0xa1dc, 0x2b, 0xa1dd, 0x2d, 0xa1e1, 0x3d, 0xa1e3, 0x3c, + 0xa1e4, 0x3e, 0xa1ef, 0x5c, 0xa1f0, 0x24, 0xa1f3, 0x25, + 0xa1f4, 0x23, 0xa1f5, 0x26, 0xa1f6, 0x2a, 0xa1f7, 0x40, + }; +#define KIGOUSIZE (sizeof(kigoutohan) / sizeof(struct symzenhan)) + register int c; + + while (start < end) { + c = *start++; + if (0xa1a1 <= c && c <= 0xa1fe) { /* symbol */ + register struct symzenhan *hi = kigoutohan + KIGOUSIZE; + register struct symzenhan *lo = kigoutohan; + register struct symzenhan *m; + register int dif; + + while (lo <= hi) { + m = lo + (hi - lo) / 2; + if ((dif = c - m->zen) == 0) break; + if (dif < 0) { + hi = m - 1; + } else { + lo = m + 1; + } + } + *res++ = (lo > hi) ? c : m->han; + } else if (0xa3b0 <= c && c <= 0xa3b9) { /* Numeric */ + *res++ = c - 0xa3b0 + '0'; + } else if (0xa3c1 <= c && c <= 0xa3da) { /* A-Z */ + *res++ = c - 0xa3c1 + 'A'; + } else if (0xa3e1 <= c && c <= 0xa3fa) { /* a-z */ + *res++ = c - 0xa3e1 + 'a'; + } else if (0xa4a1 <= c && c <= 0xa4f3) { /* $B$R$i$,$J(B */ + c = hiratohan[c - 0xa4a1]; + *res++ = c & 0xff; + if (c & 0xff00) *res++ = c >> 8; + } else if (0xa5a1 <= c && c <= 0xa5f3) { /* $B$+$?$+$J(B */ + c = hiratohan[c - 0xa5a1]; + *res++ = c & 0xff; + if (c & 0xff00) *res++ = c >> 8; + } else { + *res++ = c; + } + } + *res = 0; /* NULL terminate */ +} + +static void +to_zenkaku(start, end, res) +wchar *start; +wchar *end; +wchar *res; +{ + static wchar hantozen[] = { /* $BH>3Q(B $B"M(B $BA43QJQ49I=(B */ + /* C0 */ + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + /* ASCII */ + 0xa1a1, 0xa1aa, 0xa1c9, 0xa1f4, 0xa1f0, 0xa1f3, 0xa1f5, 0xa1c7, + 0xa1ca, 0xa1cb, 0xa1f6, 0xa1dc, 0xa1a4, 0xa1dd, 0xa1a5, 0xa1bf, + 0xa3b0, 0xa3b1, 0xa3b2, 0xa3b3, 0xa3b4, 0xa3b5, 0xa3b6, 0xa3b7, + 0xa3b8, 0xa3b9, 0xa1a7, 0xa1a8, 0xa1e3, 0xa1e1, 0xa1e4, 0xa1a9, + 0xa1f7, 0xa3c1, 0xa3c2, 0xa3c3, 0xa3c4, 0xa3c5, 0xa3c6, 0xa3c7, + 0xa3c8, 0xa3c9, 0xa3ca, 0xa3cb, 0xa3cc, 0xa3cd, 0xa3ce, 0xa3cf, + 0xa3d0, 0xa3d1, 0xa3d2, 0xa3d3, 0xa3d4, 0xa3d5, 0xa3d6, 0xa3d7, + 0xa3d8, 0xa3d9, 0xa3da, 0xa1ce, 0xa1ef, 0xa1cf, 0xa1b0, 0xa1b2, + 0xa1c6, 0xa3e1, 0xa3e2, 0xa3e3, 0xa3e4, 0xa3e5, 0xa3e6, 0xa3e7, + 0xa3e8, 0xa3e9, 0xa3ea, 0xa3eb, 0xa3ec, 0xa3ed, 0xa3ee, 0xa3ef, + 0xa3f0, 0xa3f1, 0xa3f2, 0xa3f3, 0xa3f4, 0xa3f5, 0xa3f6, 0xa3f7, + 0xa3f8, 0xa3f9, 0xa3fa, 0xa1d0, 0xa1c3, 0xa1d1, 0xa1c1, 0x007f, + /* C1 */ + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + /* KANA */ + 0xa1a1, 0xa1a3, 0xa1d6, 0xa1d7, 0xa1a2, 0xa1a6, 0xa5f2, 0xa5a1, + 0xa5a3, 0xa5a5, 0xa5a7, 0xa5a9, 0xa5e3, 0xa5e5, 0xa5e7, 0xa5c3, + 0xa1bc, 0xa5a2, 0xa5a4, 0xa5a6, 0xa5a8, 0xa5aa, 0xa5ab, 0xa5ad, + 0xa5af, 0xa5b1, 0xa5b3, 0xa5b5, 0xa5b7, 0xa5b9, 0xa5bb, 0xa5bd, + 0xa5bf, 0xa5c1, 0xa5c4, 0xa5c6, 0xa5c8, 0xa5ca, 0xa5cb, 0xa5cc, + 0xa5cd, 0xa5ce, 0xa5cf, 0xa5d2, 0xa5d5, 0xa5d8, 0xa5db, 0xa5de, + 0xa5df, 0xa5e0, 0xa5e1, 0xa5e2, 0xa5e4, 0xa5e6, 0xa5e8, 0xa5e9, + 0xa5ea, 0xa5eb, 0xa5ec, 0xa5ed, 0xa5ef, 0xa5f3, 0xa1ab, 0xa1ac, + /* undefined */ + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, + 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff, + }; + register int c; + + while (start < end) { + c = *start++; + if ((0x20 <= c && c <= 0x7e) || (0xa1 <= c && c <= 0xdf)) { + *res++ = hantozen[c]; + } else { + *res++ = c; + } + } + *res = 0; /* NULL terminate */ +} + +static void +zenkaku_hankaku(obj, hankaku) +CcWnnObject obj; +int hankaku; +{ + jcConvBuf *jcbuf = JCBUF(obj); + + normalState(obj); + + if (jcbuf->curClause != jcbuf->nClause) { + jcClause *cinfo = jcbuf->clauseInfo; + wchar *ks = cinfo[jcbuf->curLCStart].kanap; + wchar *ke = cinfo[jcbuf->curLCEnd].kanap; + wchar buf[256]; + + if (hankaku) { + to_hankaku(ks, ke, buf); + } else { + to_zenkaku(ks, ke, buf); + } + if (jcChangeClause(jcbuf, buf) < 0) beep(obj); + } + ccContextClear(CCBUF(obj)); + HINT(obj) = True; +} + +static void +zenkaku(obj) +CcWnnObject obj; +{ + zenkaku_hankaku(obj, 0); +} + +static void +hankaku(obj) +CcWnnObject obj; +{ + zenkaku_hankaku(obj, 1); +} + +static void +hiragana_katakana(obj, type) +CcWnnObject obj; +int type; +{ + normalState(obj); + + if (jcKana(JCBUF(obj), 0, type) < 0) beep(obj); + ccContextClear(CCBUF(obj)); + HINT(obj) = True; +} + +static void +hiragana(obj) +CcWnnObject obj; +{ + hiragana_katakana(obj, JC_HIRAGANA); +} + +static void +katakana(obj) +CcWnnObject obj; +{ + hiragana_katakana(obj, JC_KATAKANA); +} + + +static void +backspace(obj) +CcWnnObject obj; +{ + switch (obj->ccWnn.state) { + case selection_l_state: + endSelection(obj, False); + (void)jcMove(JCBUF(obj), 0, JC_FORWARD); + break; + case selection_s_state: + endSelection(obj, False); + (void)jcMove(JCBUF(obj), 1, JC_FORWARD); + break; + case symbol_state: + endSelection(obj, False); + break; + } + ccContextDelete(CCBUF(obj)); + if (jcDeleteChar(JCBUF(obj), 1) < 0) beep(obj); + HINT(obj) = True; +} + +static void +backspace_c(obj) +CcWnnObject obj; +{ + switch (obj->ccWnn.state) { + case selection_s_state: + case selection_l_state: + endSelection(obj, False); + cancel(obj); + break; + case symbol_state: + backspace(obj); + break; + default: + if (jcIsConverted(JCBUF(obj), 0)) + cancel(obj); + else + backspace(obj); + break; + } +} + +static void +delete(obj) +CcWnnObject obj; +{ + normalState(obj); + if (jcDeleteChar(JCBUF(obj), 0) < 0) beep(obj); + ccContextClear(CCBUF(obj)); + HINT(obj) = True; +} + +static void +delete_c(obj) +CcWnnObject obj; +{ + switch (obj->ccWnn.state) { + case selection_s_state: + case selection_l_state: + endSelection(obj, False); + cancel(obj); + break; + case symbol_state: + delete(obj); + break; + default: + if (jcIsConverted(JCBUF(obj), JCBUF(obj)->curClause)) + cancel(obj); + else + delete(obj); + break; + } +} + +static void +kill_line(obj) +CcWnnObject obj; +{ + normalState(obj); + if (jcKillLine(JCBUF(obj)) < 0) beep(obj); + ccContextClear(CCBUF(obj)); + HINT(obj) = True; +} + +static void +bell(obj) +CcWnnObject obj; +{ + XBell(XtDisplayOfObject((Widget)obj), 0); +} + +static void +beep(obj) +CcWnnObject obj; +{ + if (JCBUF(obj)->nClause == 0) return; + bell(obj); +} + +static void +jiscode_begin(obj) +CcWnnObject obj; +{ + obj->ccWnn.inputmode = JIS_MODE; +} + +static void +jiscode_end(obj) +CcWnnObject obj; +{ + obj->ccWnn.inputmode = OTHERS; +} + +static void +kuten_begin(obj) +CcWnnObject obj; +{ + obj->ccWnn.inputmode = KUTEN_MODE; +} + +static void +kuten_end(obj) +CcWnnObject obj; +{ + obj->ccWnn.inputmode = OTHERS; +} + +static void +carriageret(obj) +CcWnnObject obj; +{ + insChar('\r', (caddr_t)obj); + fix(obj); +} + + +static void +convend(obj) +CcWnnObject obj; +{ + fix(obj); + /* $B%$%Y%s%H$rAw$jJV$5$J$$$h$&$K(B fixperformed $B$r%;%C%H$7$F$*$/(B */ + obj->ccWnn.fixperformed = True; + XtCallCallbackList((Widget)obj, obj->inputConv.endcallback, + (XtPointer)NULL); +} + + +static void +send_back(obj) +CcWnnObject obj; +{ + obj->ccWnn.sendbackevent = True; +} + + +static void +register_word(obj) +CcWnnObject obj; +{ + Widget w = obj->ccWnn.selwidget; + Display *dpy; + + TRACE(("register_word()\n")); + if (w == NULL) { + /* + * $B%&%#%s%I%&$r;H$$$?$$$N$G!"<+J,$G(B widget $B$r0l$D:n$k!#(B + * nonwidget $B$r?F$K$7$F(B widget $B$r:n@.$9$k$3$H$O2DG=$J$h$&$K(B + * $B;W$($k$N$@$,!"$J$<$+$G$-$J$$$_$?$$$J$N$G!"$^$:$O(B widget $B$G$"$k(B + * $B?F$rC5$7$F!"$=$3$K:n$k$3$H$K$9$k!#(B + */ + Widget p = XtParent((Widget)obj); + + while (p != NULL) { + if (XtIsWidget(p)) break; + p = XtParent(p); + } + if (p == NULL) { + DPRINT(("register_word(): cannot find widget parent\n")); + return; + } + + TRACE(("register_word(): creating core widget\n")); + w = XtVaCreateWidget("for_selection", coreWidgetClass, p, + XtNwidth, 1, XtNheight, 1, NULL); + XtRealizeWidget(w); + obj->ccWnn.selwidget = w; + } + saveYomiAndKanji(obj); + if (obj->ccWnn.selyomi == NULL && obj->ccWnn.selkanji == NULL) return; + + dpy = XtDisplay(w); + XtOwnSelection(w, CachedInternAtom(dpy, CCWNN_REGISTER_ATOM, False), + XtLastTimestampProcessed(dpy), + convertSelection, NULL, NULL); +} + +static void +sym_input(obj) +CcWnnObject obj; +{ + ICSelectionControlArg arg; + + if (obj->ccWnn.state != normal_state) { + beep(obj); + return; + } + obj->ccWnn.state = symbol_state; + + arg.command = ICSelectionStart; + arg.u.selection_kind = ICSelectionSymbols; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); + + arg.command = ICSelectionSet; + arg.u.current_item = obj->ccWnn.cursymbol; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); +} + +static int +getSymbol(obj, n) +CcWnnObject obj; +int n; +{ + int c; + + if (n < 0 || n >= obj->ccWnn.numsymbols) return -1; + + c = *(wchar *)(obj->ccWnn.symbollist[n].data); + + return c; +} + +static void +startSelection(obj, small) +CcWnnObject obj; +int small; +{ + ICSelectionControlArg arg; + int ncand, curcand; + + if (obj->ccWnn.state != normal_state) { + beep(obj); + return; + } + + if (jcCandidateInfo(JCBUF(obj), small, &ncand, &curcand) < 0) { + beep(obj); + return; + } + + getAllCandidates(obj, ncand); + + obj->ccWnn.numcand = ncand; + obj->ccWnn.curcand = curcand; + obj->ccWnn.state = small ? selection_s_state : selection_l_state; + + 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 = curcand; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); +} + +static void +moveSelection(obj, dir) +CcWnnObject obj; +int dir; +{ + ICSelectionControlArg arg; + + if (obj->ccWnn.state == normal_state) return; + arg.command = ICSelectionMove; + arg.u.dir = dir; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); +} + +static int +endSelection(obj, abort) +CcWnnObject obj; +int abort; +{ + ICSelectionControlArg arg; + int selected; + int ret = 0; + + if (obj->ccWnn.selectionending) return 0; + + if (obj->ccWnn.state == normal_state) return -1; + + arg.command = ICSelectionEnd; + arg.u.current_item = -1; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); + + if (!abort && (selected = arg.u.current_item) >= 0) { + ret = insertSelection(obj, selected); + } + obj->ccWnn.state = normal_state; + + return ret; +} + +static int +insertSelection(obj, selected) +CcWnnObject obj; +int selected; +{ + int state = obj->ccWnn.state; + int ret = 0; + + HINT(obj) = True; + + obj->ccWnn.selectionending = True; + if (state == symbol_state) { + int c = getSymbol(obj, selected); + if (c < 0) return -1; + obj->ccWnn.cursymbol = selected; + ccContextAppend(CCBUF(obj), c); + insChar(c, (caddr_t)obj); + } else { + obj->ccWnn.curcand = selected; + ret = jcSelect(JCBUF(obj), selected); + } + obj->ccWnn.selectionending = False; + + return ret; +} + +static void +normalState(obj) +CcWnnObject obj; +{ + switch (obj->ccWnn.state) { + case selection_l_state: + case selection_s_state: + /* $B8uJdA*BrCf$G$"$l$P%+%l%s%H$N8uJd$rA*Br$7$FA*Br%b!<%I$+$iH4$1$k(B */ + case symbol_state: + /* $B5-9fF~NOCf$G$"$l$P%+%l%s%H$N5-9f$rA*Br$7$F5-9f%b!<%I$+$iH4$1$k(B */ + endSelection(obj, False); + break; + } +} + +static void +allocCandlist(obj, n) +CcWnnObject obj; +int n; +{ + ICString *p; + + if (n <= obj->ccWnn.candlistsize) return; + + if (obj->ccWnn.candlistsize == 0) { + p = (ICString *)XtMalloc(n * sizeof(ICString)); + } else { + p = (ICString *)XtRealloc((char *)obj->ccWnn.candlist, + n * sizeof(ICString)); + } + + obj->ccWnn.candlist = p; + obj->ccWnn.candlistsize = n; +} + +static void +allocStrdata(obj, nchars) +CcWnnObject obj; +Cardinal nchars; +{ + wchar *p; + + if (nchars <= obj->ccWnn.strdatasize) return; + + if (obj->ccWnn.strdatasize == 0) { + if (nchars < 256) nchars = 256; + p = (wchar *)XtMalloc(nchars * sizeof(wchar)); + } else { + if (nchars - obj->ccWnn.strdatasize < 256) + nchars = obj->ccWnn.strdatasize + 256; + p = (wchar *)XtRealloc((char *)obj->ccWnn.strdata, + nchars * sizeof(wchar)); + } + + obj->ccWnn.strdata = p; + obj->ccWnn.strdatasize = nchars; +} + +static void +getAllCandidates(obj, ncand) +CcWnnObject obj; +int ncand; +{ + ICString *strp; + Cardinal nchars; + wchar *p; + int i; + wchar buf[256]; + + allocCandlist(obj, ncand); + + nchars = 0; + for (i = 0, strp = obj->ccWnn.candlist; i < ncand; i++, strp++) { + (void)jcGetCandidate(obj->ccWnn.jcbuf, i, buf); + strp->nchars = wstrlen(buf); + strp->nbytes = strp->nchars * sizeof(wchar); + strp->attr = ICAttrNormalString; + allocStrdata(obj, nchars + strp->nchars); + (void)bcopy((char *)buf, (char *)(obj->ccWnn.strdata + nchars), + strp->nbytes); + nchars += strp->nchars; + } + + p = obj->ccWnn.strdata; + for (i = 0, strp = obj->ccWnn.candlist; i < ncand; i++, strp++) { + strp->data = (char *)p; + p += strp->nchars; + } +} + +/* + * keeping list of objects + */ +typedef struct _oblist_ { + CcWnnObject obj; + struct _oblist_ *next; +} ObjRec; + +static ObjRec *ObjList = NULL; + +static void +addObject(obj) +CcWnnObject obj; +{ + ObjRec *objp = XtNew(ObjRec); + + objp->obj = obj; + objp->next = ObjList; + ObjList = objp; +} + +static void +deleteObject(obj) +CcWnnObject 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 +serverDead() +{ + ObjRec *objp = ObjList; + + while (objp != NULL) { + if (objp->obj->ccWnn.wnnbuf != NULL + && !jcIsConnect(objp->obj->ccWnn.wnnbuf) + && wnn_errorno == WNN_JSERVER_DEAD) { + if (objp->obj->ccWnn.jcbuf != NULL) { + (void)jcDestroyBuffer(objp->obj->ccWnn.jcbuf, 0); + objp->obj->ccWnn.jcbuf = NULL; + } + (void)jcClose(objp->obj->ccWnn.wnnbuf); + objp->obj->ccWnn.wnnbuf = NULL; + if (objp->obj->ccWnn.ccbuf != NULL) { + ccContextClear(objp->obj->ccWnn.ccbuf); + } + } + objp = objp->next; + } +} + +static void +saveData(obj) +CcWnnObject obj; +{ + wchar *wbuf; + int len; + jcConvBuf *jcbuf = obj->ccWnn.jcbuf; + + len = jcbuf->kanaEnd - jcbuf->kanaBuf; + if (len <= 0) return; + + wbuf = (wchar *)XtMalloc((len + 1) * sizeof(wchar)); + (void)bcopy((char *)jcbuf->kanaBuf, (char *)wbuf, + sizeof(wchar) * (len + 1)); + wbuf[len] = 0; + obj->ccWnn.pendingdata = wbuf; +} + +static void +restoreData(obj) +CcWnnObject obj; +{ + wchar *wp = obj->ccWnn.pendingdata; + + if (wp == NULL) return; + + while (*wp != 0) { + jcInsertChar(obj->ccWnn.jcbuf, (int)*wp++); + } + XtFree((char *)obj->ccWnn.pendingdata); + + obj->ccWnn.pendingdata = NULL; + obj->ccWnn.textchanged = True; +} + +/* ARGSUSED */ +static void +ioeCallback(dummy) +XPointer dummy; +{ + ObjRec *objp = ObjList; + + /* + * I/O Error callback function. + * Does minimum cleanup -- i.e. saving dictionaries. + */ + while (objp != NULL) { + if (objp->obj->ccWnn.jcbuf != NULL) { + jcSaveDic(objp->obj->ccWnn.jcbuf); + } + objp = objp->next; + } +} + +static CcWnnObject +findSelectionObj(w) +Widget w; +{ + ObjRec *objp = ObjList; + + while (objp != NULL) { + if (objp->obj->ccWnn.selwidget == w) return objp->obj; + objp = objp->next; + } + return NULL; +} + +/* 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; +{ + CcWnnObject obj = (CcWnnObject)w; + jcConvBuf *jcbuf = obj->ccWnn.jcbuf; + jcClause *cinfo = jcbuf->clauseInfo; + wchar *wbuf, *wp; + int len, wlen; + extern int convJWStoCT(); + + if (jcbuf == NULL) return -1; + if (segn < jcbuf->nClause && + offset >= (cinfo[segn + 1].dispp - cinfo[segn].dispp)) { + /* $B%;%0%a%s%H$N:G8e(B */ + ++segn; + offset = 0; + } + if (segn >= jcbuf->nClause || + offset >= (cinfo[segn + 1].dispp - cinfo[segn].dispp)) { + /* $B:o=|$5$l$?(B */ + *encoding = XA_COMPOUND_TEXT(XtDisplayOfObject(w)); + *format = 8; + *length = 0; + *string = (XtPointer)XtMalloc(1); + return 0; + } + + wlen = (cinfo[jcbuf->nClause].dispp - cinfo[segn].dispp) - offset; + + /* + * jcbuf $B$KF~$C$F$$$kJQ49%F%-%9%H$O(B null $B%?!<%_%M!<%H$5$l$F$$$J$$$N$G(B + * $B$^$:%3%T!<$7$F(B null $B%?!<%_%M!<%H$9$k(B + */ + wbuf = (wchar *)XtMalloc((wlen + 1) * sizeof(wchar)); + (void)bcopy((char *)(cinfo[segn].dispp + offset), (char *)wbuf, sizeof(wchar) * wlen); + wbuf[wlen] = 0; + + /* + * CcWnn $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; + + /* + * CcWnn $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; +} + +static Boolean +convertSelection(w, selp, targetp, typep, valp, lenp, formatp) +Widget w; +Atom *selp; +Atom *targetp; +Atom *typep; +XtPointer *valp; +unsigned long *lenp; +int *formatp; +{ + CcWnnObject obj = findSelectionObj(w); + int len; + char *s, *data; + Atom t = *targetp; + + TRACE(("CcWnn:convertSelection()\n")); + + if (obj == NULL) { + DPRINT(("CcWnn:convertSelection(): cannot find selection object\n")); + return False; + } + + /* $B%+%l%s%HJ8@a$NFI$_$^$?$O4A;z$rJV$9(B */ + if (t == CachedInternAtom(XtDisplay(w), CCWNN_YOMI_ATOM, True) || + t == CachedInternAtom(XtDisplay(w), "TEXT", True)) { + data = obj->ccWnn.selyomi; + } else if (t == CachedInternAtom(XtDisplay(w), CCWNN_KANJI_ATOM, True)) { + data = obj->ccWnn.selkanji; + } else { + DPRINT(("CcWnn:convertSelection(): unknown target %s\n", + CachedGetAtomName(XtDisplay(w), t))); + return False; + } + + if (data != NULL) { + len = strlen(data); + s = XtMalloc(len + 1); + strcpy(s, data); + } else { + len = 0; + s = XtMalloc(1); + *s = '\0'; + } + + TRACE(("CcWnn:convertSelection(): sending yomi/kanji\n")); + *typep = XA_COMPOUND_TEXT(XtDisplay(w)); + *valp = (XtPointer)s; + *lenp = len; + *formatp = 8; + return True; +} + +static void +saveYomiAndKanji(obj) +CcWnnObject obj; +{ + jcConvBuf *jcbuf = JCBUF(obj); + int clnum = jcbuf->curClause; + jcClause *cinfo = jcbuf->clauseInfo; + wchar wbuf[1024]; + int wlen; + int len; + + TRACE(("CcWnn:saveYomiAndKanji()\n")); + + if (obj->ccWnn.selyomi != NULL) { + XtFree(obj->ccWnn.selyomi); + obj->ccWnn.selyomi = NULL; + } + if (obj->ccWnn.selkanji != NULL) { + XtFree(obj->ccWnn.selkanji); + obj->ccWnn.selkanji = NULL; + } + + /* $B%+%l%s%HJ8@a$NFI$_$H4A;z$r<hF@(B */ + if (clnum == jcbuf->nClause) clnum--; + if (clnum < 0) return; + + /* $BFI$_(B */ + wlen = cinfo[clnum + 1].kanap - cinfo[clnum].kanap; + memcpy(wbuf, cinfo[clnum].kanap, wlen * sizeof(wchar)); + wbuf[wlen] = 0; + len = convJWStoCT(wbuf, (unsigned char *)NULL, 0); + obj->ccWnn.selyomi = XtMalloc(len + 1); + convJWStoCT(wbuf, obj->ccWnn.selyomi, 0); + + /* $B4A;z(B */ + wlen = cinfo[clnum + 1].dispp - cinfo[clnum].dispp; + memcpy(wbuf, cinfo[clnum].dispp, wlen * sizeof(wchar)); + wbuf[wlen] = 0; + len = convJWStoCT(wbuf, (unsigned char *)NULL, 0); + obj->ccWnn.selkanji = XtMalloc(len + 1); + convJWStoCT(wbuf, obj->ccWnn.selkanji, 0); +}