Mercurial > kinput2.yaz
diff lib/Xsj3clib/conv.c @ 0:92745d501b9a
initial import from kinput2-v3.1
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Mon, 08 Mar 2010 04:44:30 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/Xsj3clib/conv.c Mon Mar 08 04:44:30 2010 +0900 @@ -0,0 +1,1365 @@ +#ifndef lint +static char *rcsid = "$Id: conv.c,v 2.12 1993/09/21 09:43:15 nao Exp $"; +#endif +/* + * Copyright 1991 Sony Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 Sony not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Sony makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SONY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SONY + * 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 TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Author: Naoshi Suzuki, SONY Corporation. (nao@sm.sony.co.jp) + */ + +#include <ctype.h> +#include "common.h" +#include "sj3ctype.h" +#include "util.h" +#include "segment.h" +#include "mode.h" +#include "func.h" + +extern Xsj3cCVServerIF serverIF[SERVER_NUM]; + +unsigned char *Xsj3cGetPreeditArea(); +Xsj3cEvent Xsj3cKeyConv(); + +int _Xsj3cRomaConv(); +int _Xsj3cKanaConv(); + +static Xsj3cEvent _Xsj3cStrConv(); +static Xsj3cEvent _Xsj3cCtrlConv(); +static Xsj3cEvent _Xsj3cThrough(); +static Xsj3cEvent _Xsj3cDirect(); +static int _Xsj3cCodeConv(); + +/* + * Xsj3cGetPreeditArea() + * Get area for pre-edit string. + */ +unsigned char * +Xsj3cGetPreeditArea(buf, len) + register Xsj3cBuf buf; + register int *len; +{ + register Xsj3cSeg seg; + + if (buf->convmode == DictModeMask) { + /* $B<-=q%b!<%I$N>l9g$O<-=qFI$_MQ$NF~NO$r9T$&(B */ + seg = buf->dict->seg; + } else if (buf->convmode != SelectModeMask) { + if (buf->input[buf->curseg] + && buf->input[buf->curseg]->status == SEG_CONVED) { + /* $B8=J8@a$,JQ49:Q$_$N>l9g(B */ + + buf->convmode = ConvedModeMask; + switch (buf->flushiconv) { + case ON: + /* FlushInConversion on $B$N;~$O8=:_JQ49Cf$N(B */ + /* $BJ8$r3NDj$7$F?75,$NJ8$NF~NO$r9T$&(B */ + + if (!buf->backup) { + if ((buf->backup = (Xsj3cSeg *)calloc(BUNBUFSIZ, + sizeof(Xsj3cSeg))) == NULL) { + Xsj3cError("Cannot allocate for backup buffers"); + } + } + if (seg = buf->backup[0]) { + *seg->str = '\0'; + seg->sp = seg->str; + *seg->oldstr = '\0'; + seg->oldlen = 0; + seg->n_roma = 0; + seg->n_kana = -1; + } else + seg = buf->backup[0] = (Xsj3cSeg)Xsj3cCreateSegment(buf); + break; + case EDIT: + /* FlushInConversion edit $B$N;~$O%+%l%s%H(B */ + /* $BJ8@a$X$NF~NO$r9T$&(B */ + + if (!(seg = buf->input[buf->curseg])) { + seg = buf->input[buf->curseg] + = (Xsj3cSeg)Xsj3cCreateSegment(buf); + } else { + *seg->str = '\0'; + seg->sp = seg->str; + *seg->oldstr = '\0'; + seg->oldlen = 0; + seg->n_roma = 0; + seg->n_kana = -1; + } + break; + case OFF: + case NONE: + default: + /* FlushInConversion none/off $B$N>l9g!"?7$?$J(B*/ + /* $BJ8@a$NFI$_J8;zNs$NF~NO$r9T$&(B */ + + if (seg = buf->input[buf->segnum]) { + Xsj3cClearSegment(buf, buf->input[buf->segnum]); + } else { + seg = buf->input[buf->segnum] + = (Xsj3cSeg)Xsj3cCreateSegment(buf); + } + break; + } + } else if (buf->segnum > 0) { + /* $B8=J8@a$,L$JQ49$GF~NOJ8;z$,$"$k>l9g(B */ + + buf->convmode = InputModeMask; + if (buf->input[buf->curseg] + && (buf->input[buf->curseg]->edit & SEG_NOEDIT)) { + /* $BJ8;zF~NO$r5v$5$l$F$$$J$$J8@a$N>l9g(B */ + switch (buf->flushiconv) { + case ON: + /* FlushInConversion on $B$N;~$O8=:_JQ49Cf$N(B */ + /* $BJ8$r3NDj$7$F?75,$NJ8$NF~NO$r9T$&(B */ + + if (!buf->backup) { + if ((buf->backup = (Xsj3cSeg *)calloc(BUNBUFSIZ, + sizeof(Xsj3cSeg))) == NULL) { + Xsj3cError("Cannot allocate for backup buffers"); + } + } + if (seg = buf->backup[0]) { + *seg->str = '\0'; + seg->sp = seg->str; + *seg->oldstr = '\0'; + seg->oldlen = 0; + seg->n_roma = 0; + seg->n_kana = -1; + } else + seg = buf->backup[0] + = (Xsj3cSeg)Xsj3cCreateSegment(buf); + break; + case EDIT: + if (!(seg = buf->input[buf->curseg])) + seg = buf->input[buf->curseg] + = (Xsj3cSeg)Xsj3cCreateSegment(buf); + break; + case OFF: + case NONE: + default: + if (seg = buf->input[buf->segnum]) { + Xsj3cClearSegment(buf, buf->input[buf->segnum]); + } else + seg = buf->input[buf->segnum] + = (Xsj3cSeg)Xsj3cCreateSegment(buf); + } + } else { + /* $B%+%l%s%HJ8@a$X$NF~NO$r9T$&(B */ + + if (!(seg = buf->input[buf->curseg])) + seg = buf->input[buf->curseg] + = (Xsj3cSeg)Xsj3cCreateSegment(buf); + } + } else { + /* $BF~NOJ8;z$,$J$$>l9g(B */ + + buf->convmode = NoInputModeMask; + /* New segment(first segment) */ + if (seg = buf->input[buf->curseg]) + Xsj3cClearSegment(buf, buf->input[buf->curseg]); + else + seg = buf->input[buf->curseg] + = (Xsj3cSeg)Xsj3cCreateSegment(buf); + } + } else { + /* SelectMode */ + switch (buf->selectstatus) { + case SELECT_CAND: + /* $B8uJdA*Br$N>l9g(B */ + + switch (buf->flushsconv) { + case ON: + /* FlushSelectConversion on $B$N;~$O8=:_JQ49(B */ + /* $BCf$NJ8$r3NDj$7$F?75,$NJ8$NF~NO$r9T$&(B */ + + if (!buf->backup) { + if ((buf->backup = (Xsj3cSeg *)calloc(BUNBUFSIZ, + sizeof(Xsj3cSeg))) == NULL) { + Xsj3cError("Cannot allocate for backup buffers"); + } + } + if (seg = buf->backup[0]) { + *seg->str = '\0'; + seg->sp = seg->str; + *seg->oldstr = '\0'; + seg->oldlen = 0; + seg->n_roma = 0; + seg->n_kana = -1; + } else { + seg = buf->backup[0] = (Xsj3cSeg)Xsj3cCreateSegment(buf); + } + break; + case EDIT: + /* FlushSelectConversion edit $B$N>l9g!"L5(B */ + /* $BJQ49>uBV$K$7$F%+%l%s%HJ8@a$X$NF~NO$r9T$&(B */ + + if (!(seg = buf->input[buf->curseg])) { + seg = buf->input[buf->curseg] + = (Xsj3cSeg)Xsj3cCreateSegment(buf); + } else { + *seg->str = '\0'; + seg->sp = seg->str; + *seg->oldstr = '\0'; + seg->oldlen = 0; + seg->n_roma = 0; + seg->n_kana = -1; + } + break; + case OFF: + case NONE: + default: + /* FlushSelectConversion none/off $B$N>l9g!"(B */ + /* $B?7$?$JJ8@a$NFI$_J8;zNs$NF~NO$r9T$&(B */ + + if (seg = buf->input[buf->segnum]) { + Xsj3cClearSegment(buf, buf->input[buf->segnum]); + } else { + seg = buf->input[buf->segnum] + = (Xsj3cSeg)Xsj3cCreateSegment(buf); + } + break; + } + break; + case SELECT_HINSI: + /* $BIJ;lA*Br$N>l9g(B */ + + seg = buf->dict->seg; + break; + case SELECT_SYMBOL: + default: + /* $B5-9fA*Br$N>l9g(B */ + + if (seg = buf->input[buf->segnum]) { + Xsj3cClearSegment(buf, buf->input[buf->segnum]); + } else { + seg = buf->input[buf->segnum] + = (Xsj3cSeg)Xsj3cCreateSegment(buf); + } + break; + } + } + *len = RBUFSIZ - (seg->sp - seg->str); + buf->current = seg; + return (seg->sp); +} + +#define IsKanaKey(ks) ((unsigned)(ks) < 0xff00 && ((unsigned)(ks) & 0x0400)) +#define IsLatin1Key(ks) ((unsigned)(ks) < 0x0100) + +/* + * Xsj3cKeyConv() + * Convert string or keysym and do function. + */ +Xsj3cEvent +Xsj3cKeyConv(buf, n, mod, ks) + Xsj3cBuf buf; + int n; + unsigned long mod; + KeySym ks; +{ + register Xsj3cKeyTable *keytp; + Xsj3cSeg seg = buf->current; + Xsj3cEvent ret = KEY_NULL; + unsigned char *tmpsp; + register int i, doflg; + + /* KeySym/Modifier$B!"8=:_$NJQ49%b!<%I$H3F%U%!%s%/%7%g%s(B */ + /* $B$NBP1~%F!<%V%k$r%5!<%A$7$F9gCW$9$k$b$N$,$"$l$P%U%!%s(B */ + /* $B%/%7%g%s$r<B9T$9$k!#(B */ + for (keytp = buf->key, doflg = 0; keytp != NULL; keytp = keytp->next) { + /* KeySym */ + if (ks == keytp->ksym && + /* Modifier Key */ + (keytp->modmask & ~AllModeMask) == mod && + /* Conversion mode */ + (keytp->modmask & buf->convmode) == buf->convmode) { + /* Do function */ + doflg++; + + /* .key.func $B$NBh#3%U%#!<%k%I$,(B off $B$N;~$O%U%!%s%/%7%g%s(B */ + /* $B$N$_<B9T$7!"(Bnone $B$N;~$O(B .InputSameTime $B$N;XDj$K0MB8$9$k(B */ + /* InputSameTime off $B$N;~$O%U%!%s%/%7%g%s<B9T$9$k(B */ + if (!buf->inputsame) { + if (keytp->inputsame != ON) + goto dofunc; + } else { + if (!keytp->inputsame) + goto dofunc; + } + break; + } + } + + /* LookupString $B$N7k2L$O(B NULL terminate */ + /* $B$7$F$$$J$$$N$G(B NULL terminate $B$5$;$k(B */ + tmpsp = seg->sp; + i = n; + while(i--) { + if (iscntrl(*tmpsp)) { + if (buf->throughflg == QUOTE) { + ret |= KEY_CONTROL; + tmpsp++; + continue; + } + /* ControlSameTime off $B$N>l9g$O(B */ + /* $B%U%!%s%/%7%g%s$N$_<B9T(B */ + if (doflg && !buf->cntrlsame) + goto dofunc; + else { + ret = _Xsj3cCtrlConv(buf, *tmpsp); + if (buf->cntrlsame) + goto dofunc; + else + return (ret); + } + } + tmpsp++; + } + *tmpsp = '\0'; + + if (!n || !(IsKanaKey(ks)||(IsLatin1Key(ks)))) { + /* $B%F%-%9%H$KJQ49$G$-$J$+$C$?>l9g$O(B */ + /* $B%U%!%s%/%7%g%s$N$_<B9T(B */ + goto dofunc; + } + + switch (buf->convmode) { + case SelectModeMask: + + switch (buf->selectstatus) { + case SELECT_CAND: + /* $B8uJdA*Br$N>l9g(B */ + + switch (buf->flushsconv) { + case ON: + ret |= (KEY_SELECT_END|KEY_TEXT_CHANGE); + for (i = 1; i < buf->backsegnum + 1; i++) { + Xsj3cFreeSegment(buf->backup[i]); + buf->backup[i] = NULL; + } + seg->yomi[0] = '\0'; + seg->disp[0] = '\0'; + seg->num = 0; + seg->cur = 0; + seg->dnum = 0; + seg->status = SEG_NOCONV; + seg->cursegmode = buf->inputmode; + seg->change = OFF; + seg->edit = SEG_NOEDIT; + bzero(&seg->dcid, sizeof(seg->dcid)); + buf->backsegnum = 1; + ret |= KEY_TEXT_FLUSH; + if (buf->dispmodechange) { + buf->dispmode = buf->inputmode; + ret |= KEY_MODE_CHANGE; + } + break; + case EDIT: + ret |= (KEY_SELECT_END|KEY_TEXT_CHANGE); + if (buf->curseg == buf->segnum) + buf->segnum++; + else { + ret |= _Xsj3cUnConvSeg(buf, ONE, buf->editcurlast); + _Xsj3cStoreYomi(buf, buf->input[buf->curseg], 0); + } + break; + case OFF: + ret |= (KEY_SELECT_END|KEY_TEXT_CHANGE); + if (buf->dispmodechange) { + buf->dispmode = buf->convedsegnum ? MODE_EDIT : + buf->inputmode; + ret |= KEY_MODE_CHANGE; + } + break; + case NONE: + default: + goto dofunc; + } + break; + case SELECT_HINSI: + /* $BIJ;lA*Br$N>l9g(B */ + + ret |= (KEY_DICT_CHANGE|KEY_SELECT_ABORT); + buf->dict->status = DICT_INPUT; + if (buf->dispmodechange) { + buf->dispmode = + (buf->dict->mode == REG_STATE ? MODE_TOROKU : MODE_SYOUKYO); + ret |= KEY_MODE_CHANGE; + } + break; + case SELECT_SYMBOL: + default: + /* $B5-9fA*Br$N>l9g(B */ + goto dofunc; + } + break; + case DictModeMask: + if (buf->dict->status != DICT_INPUT) { + /* $B<-=qEPO?!?>C5n%b!<%I$G$h$_F~NO;~$G$J$$(B */ + /* $B$H$-$O$rJV$7$F$J$K$b$7$J$$!#(B */ + goto dofunc; + } + ret |= KEY_DICT_CHANGE; + seg->edit = SEG_EDIT; + ret = _Xsj3cStrConv(buf, seg, ks, n, ret); + _Xsj3cFlushDictMsg(buf); + goto dofunc; + case ConvedModeMask: + ret |= KEY_TEXT_CHANGE; + if (buf->candidate) + Xsj3cEndCandidate(buf, ON); + switch (buf->flushiconv) { + case ON: + for (i = 1; i < buf->backsegnum + 1; i++) { + Xsj3cFreeSegment(buf->backup[i]); + buf->backup[i] = NULL; + } + seg->yomi[0] = '\0'; + seg->disp[0] = '\0'; + seg->num = 0; + seg->cur = 0; + seg->dnum = 0; + seg->status = SEG_NOCONV; + seg->cursegmode = buf->inputmode; + seg->change = OFF; + seg->edit = SEG_NOEDIT; + bzero(&seg->dcid, sizeof(seg->dcid)); + buf->backsegnum = 1; + ret |= KEY_TEXT_FLUSH; + if (buf->dispmodechange) { + buf->dispmode = buf->inputmode; + ret |= KEY_MODE_CHANGE; + } + break; + case OFF: + buf->curseg = buf->segnum; + buf->segnum++; + if (buf->dispmodechange) { + buf->dispmode = + (buf->convedsegnum ? MODE_EDIT : buf->inputmode); + ret |= KEY_MODE_CHANGE; + } + break; + case EDIT: + if (buf->curseg == buf->segnum) + buf->segnum++; + else { + ret |= _Xsj3cUnConvSeg(buf, ONE, buf->editcurlast); + _Xsj3cStoreYomi(buf, seg, 0); + } + break; + case NONE: + default: + goto dofunc; + } + break; + case InputModeMask: + ret |= KEY_TEXT_CHANGE; + if (buf->input[buf->curseg]->edit & SEG_NOEDIT) { + switch (buf->flushiconv) { + case ON: + for (i = 1; i < buf->backsegnum + 1; i++) { + Xsj3cFreeSegment(buf->backup[i]); + buf->backup[i] = NULL; + } + seg->yomi[0] = '\0'; + seg->disp[0] = '\0'; + seg->num = 0; + seg->cur = 0; + seg->dnum = 0; + seg->status = SEG_NOCONV; + seg->cursegmode = buf->inputmode; + seg->change = OFF; + seg->edit = SEG_NOEDIT; + bzero(&seg->dcid, sizeof(seg->dcid)); + buf->backsegnum = 1; + ret |= KEY_TEXT_FLUSH; + break; + case OFF: + buf->curseg = buf->segnum; + buf->segnum++; + if (buf->dispmodechange) { + buf->dispmode = buf->convedsegnum ? MODE_EDIT : + buf->inputmode; + ret |= KEY_MODE_CHANGE; + } + break; + case EDIT: + if (buf->curseg == buf->segnum) + buf->segnum++; + break; + case NONE: + default: + goto dofunc; + } + } else if (buf->curseg == buf->segnum) + buf->segnum++; + break; + case NoInputModeMask: + if (buf->curseg == buf->segnum) + buf->segnum++; + if (buf->throughflg == THROUGH) { + ret |= _Xsj3cThrough(buf, seg, n); + buf->throughflg = OFF; + goto dofunc; + } + ret |= KEY_TEXT_CHANGE; + break; + default: + Xsj3cWarning ("Unknown conversion mode"); + goto dofunc; + } + + seg->edit = SEG_EDIT; + ret = _Xsj3cStrConv(buf, seg, ks, n, ret); + +dofunc: + if (doflg && !(ret & KEY_TEXT_FLUSH)) { + ret |= ((*(keytp->func))(buf)); + if (!buf->cntrlsame) + ret |= KEY_FUNC; + } + return (ret); +} + +/* + * _Xsj3cStrConv() + * Convert pre-edit strings and store results to yomi/disp buffer. + */ +static Xsj3cEvent +_Xsj3cStrConv(buf, seg, ks, n, ret) + Xsj3cBuf buf; + Xsj3cSeg seg; + KeySym ks; + int n; + Xsj3cEvent ret; +{ + register unsigned char *tmpsp; + unsigned char tmp1[YBUFSIZ]; + unsigned char tmp2[YBUFSIZ]; + unsigned char kanabuf[YBUFSIZ]; + wchar wcs[RBUFSIZ]; + register int i; + int change_pos; + int change_roma = 0; + + if (buf->throughflg == QUOTE) { + ret |= _Xsj3cDirect(buf, seg, n); + buf->throughflg = OFF; + return (ret); + } + if (seg->num > seg->size - YBUFSIZ) + Xsj3cResizeSegment(seg, seg->size + KANABUFSIZ); + + switch (buf->inputmode) { + case MODE_HIRA: + case MODE_ZKATA: + case MODE_HKATA: + /* $B$R$i$,$J!?A43Q%+%?%+%J!?H>3Q%+%?%+%JF~NO%b!<%I$N>l9g(B */ + if (IsKanaKey(ks) || (IsLatin1Key(ks) && buf->kanaonly)) { + + /* $B$+$JF~NO$N>l9g(B */ + int len; + + if (seg->n_roma) { + + /* $B$+$J%P%C%U%!(B(seg->str)$B$K%m!<%^;zF~NO;~$N(B */ + /* $BJ8;zNs$,;D$C$F$$$k>l9g$O$=$l$r:o=|$9$k(B */ + i = n; + tmpsp = seg->sp; + while (i--) { + *(tmpsp - seg->n_roma) = *tmpsp; + tmpsp++; + } + *(tmpsp - seg->n_roma) = '\0'; + seg->sp = seg->sp - seg->n_roma; + seg->n_roma = 0; + } + if (buf->inputmode == MODE_HKATA) { + + /* $BH>3Q%+%?%+%JF~NO%b!<%I$N$H$-$O(B */ + /* $BJQ49$r9T$o$J$$$GFI$_%P%C%U%!$K%3%T!<(B */ + if (IsKanaKey(ks)) + strcpy(tmp1, seg->sp); + else + _Xsj3cHAlphaToHKata(buf, tmp1, seg->sp); + seg->sp = seg->str; + *seg->oldstr= '\0'; + seg->n_kana = -1; + change_pos = seg->cur; + _Xsj3cInsertChar(buf, seg, tmp1, strlen(tmp1)); + + } else { + /* $B$R$i$,$J!?A43Q%+%?%+%JF~NO%b!<%I$N;~$OH>3Q(B */ + /* $B%+%?%+%J"*$R$i$,$J!?A43Q%+%?%+%JJQ49$r9T$&(B */ + if (IsLatin1Key(ks)) { + strcpy(tmp2, seg->sp); + _Xsj3cHAlphaToHKata(buf, seg->sp, tmp2); + } + if ((seg->value = _Xsj3cKanaConv(buf, seg, seg->str, + tmp1, buf->inputmode)) > 0) { + + /* $BH>3Q%+%?%+%J"*$R$i$,$JJQ49$,@.8y$7$?>l9g(B */ + /* $BBy2;!?H>By2;$N>l9g(B */ + seg->sp = seg->str; + if (seg->n_kana > 0) { + _Xsj3cExtractChar(buf, seg, tmp2, seg->n_kana); + strcpy(seg->oldstr, seg->str); + tmpsp = seg->oldstr; + while(*tmpsp != '\0') + tmpsp++; + *(tmpsp - seg->n_kana) = '\0'; + } else { + *seg->oldstr = '\0'; + } + seg->n_kana = 0; + } else if (seg->value == 0) { + + /* $BH>3Q%+%?%+%J"*$R$i$,$J!?A43Q%+%?%+%J(B */ + /* $BJQ49$N7k2L$,ITDj$N>l9g(B */ + if (seg->n_kana > 0) + _Xsj3cExtractChar(buf, seg, tmp2, seg->n_kana); + tmpsp = seg->sp + n - 1; + seg->sp = seg->str; + *seg->sp = *tmpsp; + *(++seg->sp) = '\0'; + seg->n_kana = 1; + *seg->oldstr = '\0'; + } else { + + /* $BH>3Q%+%?%+%J"*$R$i$,$JJQ49$,@.8y$7$?>l9g(B */ + /* $BBy2;!?H>By2;$G$J$$>l9g(B */ + if (seg->n_kana > 0) + _Xsj3cExtractChar(buf, seg, tmp2, seg->n_kana); + seg->sp = seg->str; + *seg->oldstr = '\0'; + seg->n_kana = 0; + } + change_pos = seg->cur; + len = _Xsj3cmPStowPS(buf, wcs, tmp1); + _Xsj3cInsertWchar(seg, wcs, len); + } + seg->n_roma = 0; + + } else if (IsLatin1Key(ks)) { + + /* $B%m!<%^;zF~NO$N>l9g(B */ + + if (seg->n_kana > 0) { + + /* $B%m!<%^;z%P%C%U%!(B(seg->str)$B$K$+$JF~NO;~$N(B */ + /* $BJ8;zNs$,;D$C$F$$$k>l9g$O$=$l$r:o=|$9$k(B */ + i = n; + tmpsp = seg->sp; + while (i--) { + *(tmpsp - seg->n_kana) = *tmpsp; + tmpsp++; + } + *(tmpsp - seg->n_kana) = '\0'; + seg->sp = seg->sp - seg->n_kana; + seg->n_kana = -1; + } + + /* $BF~NO%b!<%I$K4X78$J$/$+$JJQ49$r9T$&(B */ + + if ((seg->value = _Xsj3cRomaConv(buf->rktable, + seg->str, kanabuf)) > 0) { + + /* ROMA->$B$+$J(B $BJQ49$,@.8y$7$?>l9g(B */ + if (buf->alphaconv) { + /* AlphabetConversion $B%j%=!<%9$,(B on */ + /* $B$@$C$?$iA43Q$rH>3Q$KJQ49$9$k(B */ + + _Xsj3cExtractChar(buf, seg, tmp1, seg->n_roma); + _Xsj3cZAlphaToHAlpha(buf, seg->oldstr, tmp1); + } else { + _Xsj3cExtractChar(buf, seg, seg->oldstr, seg->n_roma); + } + change_pos = seg->cur; + if (buf->inputmode == MODE_HIRA) { + + /* $B$R$i$,$JF~NO%b!<%I$N$H$-$O$=$N$^$^(B */ + /* $BFI$_%P%C%U%!$K%3%T!<(B */ + seg->oldlen = _Xsj3cmPStowPS(buf, wcs, kanabuf); + } else if (buf->inputmode == MODE_ZKATA) { + + /* $BA43Q%+%?%+%JF~NO%b!<%I$N$H$-$O(B */ + /* $B$R$i$,$J$rA43Q%+%?%+%J$KJQ49(B */ + _Xsj3cHiraToZKata(buf, tmp1, kanabuf); + seg->oldlen = _Xsj3cmPStowPS(buf, wcs, tmp1); + } else { + + /* $BH>3Q%+%?%+%JF~NO%b!<%I$N;~$O$R$i$,$J(B */ + /* $B!?A43Q%+%?%+%J$rH>3Q%+%?%+%J$KJQ49(B */ + _Xsj3cZKanaToHKata(buf, tmp1, kanabuf); + seg->oldlen = _Xsj3cmPStowPS(buf, wcs, tmp1); + } + _Xsj3cInsertWchar(seg, wcs, seg->oldlen); + seg->n_roma = 0; + + /* $BJQ49$G$-$J$$J8;z$,%m!<%^;z%P%C%U%!$K;D$C$F(B */ + /* $B$$$?$i!JNc!V$C!W$KJQ49$5$l$k>l9gEy!K(B */ + /* $B$+$J%P%C%U%!$N:G8e$K$=$NJ8;z$rIUM?$9$k(B */ + if (*seg->str != '\0') { + _Xsj3cInsertChar(buf, seg, seg->str, strlen(seg->str)); + seg->sp = seg->str; + while (*seg->sp != '\0') { + seg->sp++; + seg->n_roma++; + } + change_roma = seg->n_roma; + } else { + seg->sp = seg->str; + } + + } else if (seg->value == 0) { + + /* ROMA$B"*$+$JJQ49$N7k2L$,ITDj$N>l9g(B */ + change_pos = seg->cur; + _Xsj3cInsertChar(buf, seg, seg->sp, n); + i = n; + while (i--) { + seg->sp++; + seg->n_roma++; + } + change_roma = n; + + } else { + /* ROMA$B"*$+$J(B $BJQ49$N7k2L$,IT@.8y$N>l9g(B */ + /* $B:G8e$NF~NO$,%m!<%^$+$JJQ49$N8uJd$H(B */ + /* $B$7$FM-8z$+$I$&$+D4$Y$k(B */ + + change_pos = seg->cur; + if ((seg->value = _Xsj3cRomaConv(buf->rktable, seg->sp, + kanabuf)) > 0) { + /* $B:G8e$NF~NO$,%m!<%^$+$JJQ49$N8uJd$H$7$F(B */ + /* $BM-8z$J>l9g(B */ + + if (buf->inputmode == MODE_HIRA) { + + /* $B$R$i$,$JF~NO%b!<%I$N$H$-$O$=$N$^$^(B */ + /* $BFI$_%P%C%U%!$K%3%T!<(B */ + seg->oldlen = _Xsj3cmPStowPS(buf, wcs, kanabuf); + } else if (buf->inputmode == MODE_ZKATA) { + + /* $BA43Q%+%?%+%JF~NO%b!<%I$N$H$-$O(B */ + /* $B$R$i$,$J$rA43Q%+%?%+%J$KJQ49(B */ + _Xsj3cHiraToZKata(buf, tmp1, kanabuf); + seg->oldlen = _Xsj3cmPStowPS(buf, wcs, tmp1); + } else { + + /* $BH>3Q%+%?%+%JF~NO%b!<%I$N;~$O$R$i$,$J(B */ + /* $B!?A43Q%+%?%+%J$rH>3Q%+%?%+%J$KJQ49(B */ + _Xsj3cZKanaToHKata(buf, tmp1, kanabuf); + seg->oldlen = _Xsj3cmPStowPS(buf, wcs, tmp1); + } + _Xsj3cInsertWchar(seg, wcs, seg->oldlen); + seg->n_roma = 0; + + /* $BJQ49$G$-$J$$J8;z$,%m!<%^;z%P%C%U%!$K;D$C$F(B */ + /* $B$$$?$i!JNc!V$C!W$KJQ49$5$l$k>l9gEy!K(B */ + /* $B$+$J%P%C%U%!$N:G8e$K$=$NJ8;z$rIUM?$9$k(B */ + if (*seg->str != '\0') { + _Xsj3cInsertChar(buf, seg, seg->str, strlen(seg->str)); + seg->sp = seg->str; + while (*seg->sp != '\0') { + seg->sp++; + seg->n_roma++; + } + change_roma = seg->n_roma; + } else { + seg->sp = seg->str; + } + } else if (seg->value == 0) { + /* $B%m!<%^$+$JJQ49$N8uJd$H$7$FL$Dj$N>l9g(B */ + /* $B:G8e$NF~NOJ8;z$r%m!<%^"*$+$JJQ49MQ$N(B */ + /* $B%P%C%U%!(B(seg->str)$B$K;D$9(B */ + + change_pos = seg->cur; + _Xsj3cInsertChar(buf, seg, seg->sp, n); + *seg->oldstr = '\0'; + tmpsp = seg->str; + *seg->str = *seg->sp; + seg->sp = seg->str; + i = n; + while (i--) + *tmpsp++ = *seg->sp++; + *tmpsp = '\0'; + seg->n_roma = n; + change_roma = seg->n_roma; + } else { + /* $B%m!<%^$+$JJQ49$N8uJd$H$7$FL58z$J>l9g(B */ + + _Xsj3cInsertChar(buf, seg, seg->sp, n); + *seg->oldstr = '\0'; + seg->n_roma = 0; + *seg->str = '\0'; + seg->sp = seg->str; + + /* rkbell $B%j%=!<%9$,(B on $B$K@_Dj$5$l$F(B */ + /* $B$$$k>l9g%Y%k$rLD$i$9(B */ + if (buf->rkbell) + ret |= KEY_BELL; + change_roma = n; + } + } + + /* AlphabetConversion $B%j%=!<%9$,(B on */ + /* $B$@$C$?$iH>3Q%m!<%^;z$rA43Q%m!<%^;z$KJQ49$9$k(B */ + if (buf->alphaconv && buf->inputmode != MODE_HKATA + && change_roma) { + _Xsj3cExtractChar(buf, seg, tmp1, change_roma); + _Xsj3cHAlphaToZKana(buf, tmp2, tmp1); + _Xsj3cInsertChar(buf, seg, tmp2, change_roma); + } + /* $B$+$JF~NO%b!<%I$G$J$$$H$-$O(B -1 */ + seg->n_kana = -1; + } else { + return (KEY_NULL); + } + break; + + case MODE_HALPHA: + + /* $BH>3Q%"%k%U%!%Y%C%H(B $BF~NO%b!<%I$N>l9g(B */ + if (IsKanaKey(ks)) + return (KEY_BELL); + change_pos = seg->cur; + _Xsj3cInsertChar(buf, seg, seg->sp, n); + seg->sp = seg->str; + seg->n_roma = 0; + seg->n_kana = -1; + break; + + case MODE_ZALPHA: + + /* $BA43Q%"%k%U%!%Y%C%H(B $BF~NO%b!<%I$N>l9g(B */ + if (IsKanaKey(ks)) + return (KEY_BELL); + _Xsj3cHAlphaToZAlpha(buf, tmp1, seg->sp); + seg->sp = seg->str; + change_pos = seg->cur; + _Xsj3cInsertChar(buf, seg, tmp1, n); + seg->n_roma = 0; + seg->n_kana = -1; + break; + + case MODE_SJIS: + case MODE_EUC: + case MODE_JIS: + case MODE_KUTEN: + + /* $B%3!<%IF~NO%b!<%I$N>l9g(B */ + tmpsp = seg->str; + while (*tmpsp != '\0') { + if (!isxdigit(*tmpsp) + || (buf->inputmode == MODE_KUTEN && !isdigit(*tmpsp))) + return (KEY_BELL); + tmpsp++; + } + + /* $B%3!<%I"*$R$i$,$J!?A43Q%+%?%+%J!?5-9f!?4A;z$NJQ49$r9T$&(B */ + if ((seg->value = _Xsj3cCodeConv(buf, seg->str, + kanabuf, buf->inputmode)) > 0) { + + /* $B%3!<%IJQ49$K@.8y$7$?>l9g(B */ + if (buf->alphaconv) { + /* AlphabetConversion $B%j%=!<%9$,(B on $B$@$C$?$i(B */ + /* $BA43Q?t;z$rH>3Q?t;z$KJQ49$9$k(B */ + _Xsj3cExtractChar(buf, seg, tmp1, seg->n_roma); + _Xsj3cZAlphaToHAlpha(buf, seg->oldstr, tmp1); + } else { + _Xsj3cExtractChar(buf, seg, seg->oldstr, seg->n_roma); + } + change_pos = seg->cur; + seg->oldlen = (strlen(kanabuf) + 1)/ sizeof(wchar); + _Xsj3cInsertChar(buf, seg, kanabuf, seg->oldlen); + seg->cursegmode = MODE_HIRA; + seg->n_roma = 0; + seg->sp = seg->str; + } else if (seg->value == 0) { + + /* $B%3!<%IJQ49$N7k2L$,ITDj$N>l9g(B */ + change_pos = seg->cur; + if (buf->alphaconv) { + /* AlphabetConversion $B%j%=!<%9$,(B on $B$@$C$?$i(B */ + /* $BH>3Q?t;z$rA43Q?t;z$KJQ49$9$k(B */ + _Xsj3cHAlphaToZKana(buf, tmp1, seg->sp); + _Xsj3cInsertChar(buf, seg, tmp1, n); + } else { + _Xsj3cInsertChar(buf, seg, seg->sp, n); + } + i = n; + while (i--) { + seg->n_roma++; + seg->sp++; + } + } else { + + /* $B%3!<%IJQ49$N7k2L$,<:GT$N>l9g(B */ + _Xsj3cExtractChar(buf, seg, tmp1, seg->n_roma); + change_pos = seg->cur; + seg->sp = seg->str; + seg->n_roma = 0; + if (seg->num == 0 && buf->convmode != DictModeMask) { + Xsj3cFreeSegment(seg); + seg = NULL; + buf->segnum--; + for (i = buf->curseg; i < buf->segnum; i++) { + buf->input[i] = buf->input[i + 1]; + } + buf->input[buf->segnum] = NULL; + return ret; + } + if (buf->rkbell) + ret |= KEY_BELL; + } + seg->n_kana = -1; + break; + + default: + Xsj3cWarning("Illegal current mode"); + return (KEY_BELL); + } + + /* $BI=<(MQJ8;zNs$X%3%T!<$9$k(B */ + _Xsj3cStoreYomi(buf, seg, change_pos); + return ret; +} + +/* + * _Xsj3cKanaConv() + * Kana input mode dispatch routine. + */ +int +_Xsj3cKanaConv(buf, seg, hkana, zkana, mode) + Xsj3cBuf buf; + Xsj3cSeg seg; + unsigned char *hkana, *zkana; + Xsj3csMode mode; +{ + register int len, zlen; + register wchar s; + + if (mode == MODE_HIRA) { + if (buf->alphaconv) + _Xsj3cHankakuToHira(buf, zkana, hkana); + else + _Xsj3cHKataToHira(buf, zkana, hkana); + } else { + if (buf->alphaconv) + _Xsj3cHankakuToZKata(buf, zkana, hkana); + else + _Xsj3cHKataToZKata(buf, zkana, hkana); + } + len = 0; + while (*hkana != '\0') { + hkana++; + len++; + } + if (isdakuon(*(hkana - 1))) { + return 0; + } else { + zlen = 0; + while (*zkana != '\0') { + zkana++; + zlen++; + } + if (zlen > 1) { + s = (*(zkana - 2) << 8) + (*(zkana - 1) & 0xff); + if (seg->n_kana && (iszdakuten(s, serverIF[buf->server].lang) + || !isdakuten(*(hkana - 1)))) + return -1; + else + return len; + } else { + return -1; + } + } +} + +/* + * _Xsj3cCodeConv() + * Code input mode dispatch routine. + */ +static int +_Xsj3cCodeConv(buf, code, kanji, mode) + Xsj3cBuf buf; + register unsigned char *code; + register unsigned char *kanji; + Xsj3csMode mode; +{ + register int i, j, len; + register wchar k, (*conv)(); + register unsigned char c1, c2; + unsigned char kbuf[4]; + + if ((len = strlen(code)) < 4 && (mode == MODE_EUC || mode == MODE_KUTEN)) + return CONV_UNFIXED; + else if ((len < 2 || len == 3) && (mode == MODE_SJIS || mode == MODE_JIS)) + return CONV_UNFIXED; + + k = 0; + for (j = 0; j < 4 && *code != '\0'; code++, j++) { + if (isdigit(*code)) + i = *code - '0'; + else if (islower(*code)) + i = 10 + *code - 'a'; + else if (isupper(*code)) + i = 10 + *code - 'A'; + else + return CONV_FAILED; + kbuf[j] = i; + k += i << ((3 - j) * 4); + } + switch (mode) { + case MODE_SJIS: + if (len == 4 && issjis1(c1 = (k >> 8)) && issjis2(c2 = (k & 0xff))) { + if (conv = CodeConvFunc[JP_SJIS][serverIF[buf->server].lang]) { + k = conv(k); + *kanji++ = k >> 8; + *kanji++ = k & 0xff; + *kanji = '\0'; + } else { + *kanji++ = c1; + *kanji++ = c2; + *kanji = '\0'; + } + } else if (iskana(k >> 8)) { + *kanji++ = k >> 8; + *kanji = '\0'; + } else { + if (len < 4) + return CONV_UNFIXED; + else + return CONV_FAILED; + } + break; + case MODE_EUC: + if (iseuc(k >> 8) && iseuc(k & 0xff)) { + if (conv = CodeConvFunc[JP_EUC][serverIF[buf->server].lang]) + k = conv(k); + *kanji++ = k >> 8; + *kanji++ = k & 0xff; + *kanji = '\0'; + } else if (iseuckana(k >> 8) && iskana2(k & 0xff)) { + *kanji++ = k & 0xff; + *kanji = '\0'; + } else { + return CONV_FAILED; + } + break; + case MODE_JIS: + if (len == 4 && isjis(c1 = (k >> 8)) && isjis(c2 = (k & 0xff))) { + if (conv = CodeConvFunc[JP_JIS8][serverIF[buf->server].lang]) { + k = conv(k); + *kanji++ = k >> 8; + *kanji++ = k & 0xff; + *kanji = '\0'; + } else { + *kanji++ = c1; + *kanji++ = c2; + *kanji = '\0'; + } + } else if (iskana(k >> 8)) { + *kanji++ = k >> 8; + *kanji = '\0'; + } else { + if (len < 4) + return CONV_UNFIXED; + else + return CONV_FAILED; + } + break; + case MODE_KUTEN: + conv = CodeConvFunc[JP_JIS8][serverIF[buf->server].lang]; + c1 = kbuf[0] * 10 + kbuf[1]; + c2 = kbuf[2] * 10 + kbuf[3]; + k = (c1 << 8) + c2; + k = conv(k + 0x2020); + if (iskan1(c1 = (k >> 8), serverIF[buf->server].lang) + && iskan2(c2 = (k & 0xff), serverIF[buf->server].lang)) { + *kanji++ = c1; + *kanji++ = c2; + *kanji = '\0'; + } else { + return CONV_FAILED; + } + break; + default: + Xsj3cWarning("Illegal mode"); + return CONV_FAILED; + } + + return CONV_FIXED; +} + +#define MATCH 0 +#define NOT 1 + +/* + * _Xsj3cRomaConv() + * Get roman characters from the second argument and put back hiragana or + * katakana characters to the third argument in conversion table. + * If roman characters (third argument) mach with the "roma" entry in table, + * put back the "str" entry to the third argument and the "yomi" entry + * to the third argument, then it returns number of converted roman + * characters. + * If not but any letters of roman characters is match with the "roma" + * entry in table and the number of roman characters is less than + * the number of the letters of "roma" entry, put back the same to + * the third argument and nothing to the third argument, then it returns + * zero. + * Then last (not converted case) it returns minus 1. + * Any arguments must be null('\0') terminated. + * First argument is pointer to conversion table; + */ +int +_Xsj3cRomaConv(rktable, roma, yomi) + Xsj3cRKTable *rktable; + register unsigned char *roma; + register unsigned char *yomi; +{ + Xsj3cRKTable *rktp; + register unsigned char *p, *q; + unsigned char tmp[RBUFSIZ]; + int match, result = CONV_FAILED; + register int len; + + if (!roma || (len = strlen(roma)) == 0) + return (CONV_FAILED); + for (rktp = rktable; rktp != NULL; rktp = rktp->next) { + if (!rktp->roma) { + continue; + } + p = roma; + q = rktp->roma; + if (len > rktp->rlen) { + if (*q++ == *p++) { + match = MATCH; + while (*q != '\0') { + if (*q != *p) { + match = NOT; + break; + } + q++; + p++; + } + if (match == NOT) { + continue; + } + if (result < 0) { + result = rktp->rlen; + strcpy(yomi, rktp->yomi); + strcpy(tmp, p); + } else { + continue; + } + } else { + continue; + } + } else { + if (*p++ == *q++) { + match = MATCH; + while (*p != '\0') { + if (*p++ != *q++) { + match = NOT; + break; + } + } + if (match == NOT) { + continue; + } + if (*q != '\0') { + result = CONV_UNFIXED; + continue; + } else if (result == CONV_UNFIXED) { + continue; + } else { + result = rktp->rlen; + strcpy(yomi, rktp->yomi); + strcpy(tmp, rktp->str); + } + } else { + continue; + } + } + } + if (result > 0) + strcpy(roma, tmp); + return (result); +} + +/* + * _Xsj3cCtrlConv() + * + * <NoInputMode> Through all control events. + * <InputMode> Put the control code (now only HT & NL) after current position, + * then fix all segments. + * <ConvedMode> Put the control code (now only HT & NL) after current segment, + * then fix all segments and end convertion. + * <SelectMode/DictMode> Does Nothing. + * + * DisplayModeChange on: Change the display mode string. + * ThroughNext code: + * SetNormal code: + */ +static Xsj3cEvent +_Xsj3cCtrlConv(buf, code) + Xsj3cBuf buf; + unsigned char code; +{ + unsigned char ch[2]; + register unsigned char *c; + int change_pos; + register int i; + + if (code == '\t' || code == '\n') + goto compound_text; + if (buf->throughnext) { + c = buf->throughnext; + while (*c != '\0') { + if (*c == code) { + buf->throughflg = THROUGH; + if (buf->dispmodechange) { + buf->dispmode = buf->inputmode; +#ifdef THROUGH_CONT + return (KEY_TEXT_CLEAR|KEY_CONTROL|KEY_MODE_CHANGE); + } else { + return (KEY_TEXT_CLEAR|KEY_CONTROL); +#else /* THROUGH_CONT */ + return (KEY_NULL); + } else { + return (KEY_NULL); +#endif /* THROUGH_CONT */ + } + } + c++; + } + } + if (buf->setnormal) { + c = buf->setnormal; + while (*c != '\0') { + if (*c == code) { + if (buf->dispmodechange) { + buf->dispmode = buf->inputmode; +#ifdef THROUGH_CONT + return (KEY_TEXT_FIXED|KEY_CONTROL|KEY_HENKAN_END + |KEY_MODE_CHANGE); + } else { + return (KEY_TEXT_FIXED|KEY_CONTROL|KEY_HENKAN_END); +#else /* THROUGH_CONT */ + return (KEY_NULL); + } else { + return (KEY_NULL); +#endif /* THROUGH_CONT */ + } + } + c++; + } + } + /* Through all control events by XtNunusedEventCallback */ + return (KEY_NULL); + + /* Push by compound text */ +compound_text: + switch (buf->convmode) { + case NoInputModeMask: + buf->convmode = InputModeMask; + case InputModeMask: + if (buf->segnum == buf->curseg) + buf->segnum++; + ch[0] = code; + ch[1] = '\0'; + change_pos = buf->input[buf->curseg]->cur; + _Xsj3cInsertChar(buf, buf->input[buf->curseg], ch, 1); + _Xsj3cStoreYomi(buf, buf->input[buf->curseg], change_pos); + if (buf->dispmodechange) { + buf->dispmode = buf->inputmode; + return (KEY_TEXT_FIXED|KEY_TEXT_CHANGE|KEY_MODE_CHANGE); + } else + return (KEY_TEXT_FIXED|KEY_TEXT_CHANGE); + case ConvedModeMask: + i = buf->input[buf->curseg]->dnum; + buf->input[buf->curseg]->disp[i++] = code; + buf->input[buf->curseg]->disp[i] = '\0'; + buf->input[buf->curseg]->dnum++; + if (buf->dispmodechange) { + buf->dispmode = buf->inputmode; + return (KEY_TEXT_FIXED|KEY_TEXT_CHANGE|KEY_MODE_CHANGE); + } else + return (KEY_TEXT_FIXED|KEY_TEXT_CHANGE); + case DictModeMask: + case SelectModeMask: + default: + return (KEY_NULL); + } +} + +/* + * _Xsj3cThrough() + * Store characters to yomi/disp buffer and fix. + */ +static Xsj3cEvent +_Xsj3cThrough(buf, seg, n) + Xsj3cBuf buf; + Xsj3cSeg seg; + int n; +{ + int change_pos; + + change_pos = seg->cur; + _Xsj3cInsertChar(buf, seg, seg->str, n); + _Xsj3cStoreYomi(buf, seg, change_pos); + return (KEY_TEXT_FIXED); +} + +/* + * _Xsj3cDirect() + * Store characters to yomi/disp buffer. + * + * DisplayModeChange on: Change the display mode string. + */ +static Xsj3cEvent +_Xsj3cDirect(buf, seg, n) + Xsj3cBuf buf; + Xsj3cSeg seg; + int n; +{ + Xsj3cEvent ret = KEY_TEXT_CHANGE; + int change_pos; + + change_pos = seg->cur; + _Xsj3cInsertChar(buf, seg, seg->str, n); + _Xsj3cStoreYomi(buf, seg, change_pos); + *seg->str = '\0'; + seg->sp = seg->str; + *seg->oldstr = '\0'; + seg->oldlen = 0; + seg->n_roma = 0; + seg->n_kana = -1; + if (buf->dispmodechange) { + buf->dispmode = (buf->convedsegnum == buf->segnum ? MODE_KANJI : + (buf->convedsegnum ? MODE_EDIT : buf->inputmode)); + ret |= KEY_MODE_CHANGE; + } + return (ret); +}