diff lib/Xsj3clib/mode.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/mode.c	Mon Mar 08 04:44:30 2010 +0900
@@ -0,0 +1,1194 @@
+#ifndef lint
+static char *rcsid = "$Id: mode.c,v 2.6 1993/01/06 10:58:18 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"
+
+extern Xsj3cCVServerIF      serverIF[SERVER_NUM];
+
+Xsj3cEvent                  _Xsj3cModeChange();
+Xsj3cEvent                  _Xsj3cModeClear();
+Xsj3cEvent                  Xsj3cModeConv();
+
+void                        _Xsj3cHiraToZKata();
+void                        _Xsj3cHankakuToHira();
+void                        _Xsj3cHankakuToZKata();
+void                        _Xsj3cHKataToHira();
+void                        _Xsj3cHKataToZKata();
+void                        _Xsj3cZKanaToHKata();
+void                        _Xsj3cZKataToHira();
+void                        _Xsj3cHAlphaToZAlpha();
+void                        _Xsj3cHAlphaToZKana();
+void                        _Xsj3cHAlphaToHKata();
+void                        _Xsj3cZAlphaToHAlpha();
+
+static void                 _Xsj3cLowerToUpper();
+static void                 _Xsj3cUpperToLower();
+static void                 _Xsj3cRKConvs();
+static void                 _Xsj3cKRConvs();
+
+/*
+ * _Xsj3cModeChange()
+ *
+ * Change current character mode to apointed mode(secound argument)
+ */
+Xsj3cEvent
+_Xsj3cModeChange(buf, mode, conv)
+    Xsj3cBuf        buf;
+    Xsj3csMode      mode;
+    Xsj3cFlag       conv;
+{
+    Xsj3cEvent      ret;
+    unsigned char  *mbs;
+
+    if (buf->convmode != SelectModeMask) {
+        if (conv) {
+            Xsj3cSeg        seg = buf->input[buf->curseg];
+
+            if ((mbs = (unsigned char *)
+                    malloc(seg->size * 2 * sizeof(wchar))) == NULL)
+                Xsj3cError("Cannot allocate for mode conversion buffer");
+            _Xsj3cwPStomPS(buf, mbs, seg->yomi);
+            if ((ret = Xsj3cModeConv(buf, mbs, mode, seg->size))
+                    & KEY_TEXT_CHANGE) {
+                seg->num = _Xsj3cmPStowPSn(buf, seg->yomi, mbs, seg->size);
+                if (seg->num > seg->size - YBUFSIZ) {
+                    Xsj3cResizeSegment(seg, seg->size * 2);
+                    seg->num = _Xsj3cmPStowPS(buf, seg->yomi, mbs);
+                }
+                seg->cur = seg->num;
+                _Xsj3cStoreYomi(buf, seg, 0);
+                seg->change = OFF;
+                seg->cursegmode = mode;
+            }
+            free(mbs);
+        } else {
+            if (buf->inputmode != mode) {
+                buf->dispmode = buf->inputmode = mode;
+                return (_Xsj3cModeClear(buf));
+            } else {
+#ifdef THROUGH_CONT
+                return (KEY_NULL);
+#else /* THROUGH_CONT */
+                if (buf->cntrlsame)
+                    return (KEY_NULL);
+                else
+                    return (KEY_TEXT_CHANGE); /* dummy  */
+#endif /* THROUGH_CONT */
+            }
+        }
+        return ret;
+    } else {
+        return (KEY_BELL);
+    }
+}
+
+/*
+ * _Xsj3cModeClear() 
+ *  Clear romaji/kana buffer after changing mode.
+ */
+Xsj3cEvent
+_Xsj3cModeClear(buf)
+    Xsj3cBuf            buf;
+{
+    register Xsj3cSeg   seg = buf->input[buf->curseg];
+
+    if (!seg)
+        return (KEY_MODE_CHANGE);
+    *seg->str = '\0';
+    seg->sp = seg->str;
+    seg->n_roma = 0;
+    seg->n_kana = -1;
+    *seg->oldstr = '\0';
+    seg->oldlen = 0;
+    seg->value = 0;
+    seg->change = OFF;
+    seg->cursegmode = MODE_HIRA;
+    if (buf->flushaconv)
+        return (KEY_MODE_CHANGE|KEY_TEXT_CLEAR);
+    else
+        return (KEY_MODE_CHANGE);
+}
+
+/*
+ * Xsj3cModeConv()
+ *  Convert current segment to appointed character mode.
+ */
+Xsj3cEvent
+Xsj3cModeConv(buf, string, postmode, size)
+    Xsj3cBuf        buf;
+    unsigned char  *string;
+    Xsj3csMode      postmode;
+    int             size;
+{
+    Xsj3cEvent      ret = KEY_NULL;
+    unsigned char   *tmp1,   *tmp2;
+
+    if ((tmp1 = (unsigned char *)malloc(size * 2 * sizeof(wchar))) == NULL)
+        Xsj3cError("Cannot allocate for mode conversion buffer");
+    if ((tmp2 = (unsigned char *)malloc(size * 2 * sizeof(wchar))) == NULL)
+        Xsj3cError("Cannot allocate for mode conversion buffer");
+
+    switch (postmode) {
+    case MODE_HIRA:
+        _Xsj3cZKanaToHKata(buf, tmp2, string);
+        _Xsj3cHKataToHira(buf, tmp1, tmp2);
+        _Xsj3cKRConvs(buf, tmp2, tmp1);
+        _Xsj3cRKConvs(buf, tmp1, tmp2);
+        if (buf->alphaconv)
+            _Xsj3cHankakuToHira(buf, string, tmp1);
+        else
+            _Xsj3cZKataToHira(buf, string, tmp1);
+        ret = KEY_TEXT_CHANGE;
+        break;
+
+    case MODE_ZKATA:
+        _Xsj3cZKanaToHKata(buf, tmp2, string);
+        _Xsj3cHKataToHira(buf, tmp1, tmp2);
+        _Xsj3cKRConvs(buf, tmp2, tmp1);
+        _Xsj3cRKConvs(buf, tmp1, tmp2);
+        if (buf->alphaconv) {
+            _Xsj3cHiraToZKata(buf, tmp2, tmp1);
+            _Xsj3cHAlphaToZAlpha(buf, string, tmp2);
+        } else
+            _Xsj3cHiraToZKata(buf, string, tmp1);
+        ret = KEY_TEXT_CHANGE;
+        break;
+
+    case MODE_HKATA:
+        _Xsj3cHKataToHira(buf, tmp1, string);
+        _Xsj3cKRConvs(buf, tmp2, tmp1);
+        _Xsj3cRKConvs(buf, tmp1, tmp2);
+        _Xsj3cZKanaToHKata(buf, string, tmp1);
+        ret = KEY_TEXT_CHANGE;
+        break;
+
+    case MODE_HALPHA:
+        _Xsj3cZAlphaToHAlpha(buf, tmp2, string);
+        _Xsj3cRKConvs(buf, tmp1, tmp2);
+        _Xsj3cZKanaToHKata(buf, tmp2, tmp1);
+        _Xsj3cHKataToHira(buf, tmp1, tmp2);
+        _Xsj3cKRConvs(buf, string, tmp1);
+        ret = KEY_TEXT_CHANGE;
+        break;
+
+    case MODE_ZALPHA:
+        _Xsj3cZAlphaToHAlpha(buf, tmp2, string);
+        _Xsj3cRKConvs(buf, tmp1, tmp2);
+        _Xsj3cZKanaToHKata(buf, tmp2, tmp1);
+        _Xsj3cHKataToHira(buf, tmp1, tmp2);
+        _Xsj3cKRConvs(buf, tmp2, tmp1);
+        _Xsj3cHAlphaToZAlpha(buf, string, tmp2);
+        ret = KEY_TEXT_CHANGE;
+        break;
+
+    case MODE_HANKAKU:
+        _Xsj3cZKanaToHKata(buf, tmp1, string);
+        strcpy(string, tmp1);
+        ret = KEY_TEXT_CHANGE;
+        break;
+
+    case MODE_ZENKAKU:
+        _Xsj3cHankakuToZKata(buf, tmp1, string);
+        strcpy(string, tmp1);
+        ret = KEY_TEXT_CHANGE;
+        break;
+
+    case MODE_UPPER:
+        _Xsj3cLowerToUpper(buf, string);
+        ret = KEY_TEXT_CHANGE;
+        break;
+
+    case MODE_LOWER:
+        _Xsj3cUpperToLower(buf, string);
+        ret = KEY_TEXT_CHANGE;
+        break;
+
+    default:
+        ret = KEY_BELL;
+        break;
+    }
+    free(tmp1);
+    free(tmp2);
+    return (ret);
+}
+
+/*
+ * _Xsj3cRKConvs()
+ *  Convert romaji to kana in 3rd argument and set to 2nd argument.
+ */
+static void
+_Xsj3cRKConvs(buf, yomi, alpha)
+    Xsj3cBuf                buf;
+    unsigned char          *yomi;
+    unsigned char          *alpha;
+{
+    unsigned char          *p;
+    register unsigned char *q,     *yp,     *t;
+    register int            i = 0,  rlen = 0,       tflg = 0,   value;
+    unsigned char           rbuf[RBUFSIZ];      
+    unsigned char           ybuf[YBUFSIZ];  
+    
+    yp = yomi;
+    p = rbuf;
+    rlen = 0;
+
+    while (*alpha != '\0') {
+        if (iskan1(*alpha, serverIF[buf->server].lang)
+                && iskan2(*(alpha + 1), serverIF[buf->server].lang)) {
+            *yp++ = *alpha++;
+            *yp++ = *alpha++;
+            i++;
+            continue;
+        } else if (!isascii(*alpha)) {
+            *yp++ = *alpha++;
+            i++;
+            continue;
+        }
+        if (i) {
+            rlen = 0;
+            p = rbuf;
+            i = 0;
+        } 
+
+        *p = *alpha++;
+        *(p + 1) = '\0';
+        if (*alpha == '\0') {
+            t = buf->rkdouble;
+            while (*t != '\0') {
+                if (p > rbuf && *(p - 1) == *t) {
+                    break;
+                } else if (*t == *p) {
+                    *(p + 1) = *p;
+                    *(p + 2) = '\0';
+                    tflg++;
+                    break;
+                }
+                t++;
+            }
+        }
+        if ((value = _Xsj3cRomaConv(buf->rktable, rbuf, ybuf)) > 0) {
+            q = ybuf;
+            yp -= rlen;
+            while (*q != '\0') {
+                *yp++ = *q++;
+            }
+            p = rbuf;
+            rlen = 0;
+            while (*p != '\0' && !tflg) {
+                *yp++ = *p++;
+                rlen++;
+            }
+        } else if (value < 0) {
+            if ((value = _Xsj3cRomaConv(buf->rktable, p, ybuf)) > 0) {
+                q = ybuf;
+                while (*q != '\0') {
+                    *yp++ = *q++;
+                }
+                rlen = 0;
+                while (*p != '\0' && !tflg) {
+                    *yp++ = *p++;
+                    rlen++;
+                }
+            } else if (value < 0) {
+                *yp++ = *p;
+                rlen = 0;
+                p = rbuf;
+            } else {
+                *yp++ = *p;
+                q = rbuf;
+                *q++ = *p++;
+                *q = '\0';
+                rlen = 1;
+            }
+        } else {
+            *yp++ = *p++;
+            if (rlen++ > 3) { /* non-convert limit = 4: you can change this */
+                rlen = 0;
+                p = rbuf;
+            }
+        }
+    }
+    *yp = '\0';
+}
+
+static void
+_Xsj3cKRConvs(buf, roma, kana)
+    Xsj3cBuf                buf;
+    register unsigned char *roma;
+    register unsigned char *kana;
+{
+    register unsigned char  c,  *p, *q, *r, *sp, *t, *d;
+    register wchar          s;
+    register Xsj3cRKTable  *rktp;
+    register Xsj3cHKTable  *hktp;
+    register Xsj3cZHTable  *zhtp;
+    register int            ylen,   plen,   rlen,   i,  cont = 0;
+    register int            zenflg = 0, plosflg = 0;
+    unsigned char           tyomi[KANABUFSIZ];
+    unsigned char           tmp[RBUFSIZ];
+
+    p = tyomi;
+    while ((c = *kana++) != '\0') {
+        if (iskan1(c, serverIF[buf->server].lang)
+                && iskan2(*kana, serverIF[buf->server].lang)) {
+            s = (c << 8) + *kana;
+            if (iskata(s, serverIF[buf->server].lang)) {
+                for (hktp = buf->hktable; hktp != NULL; hktp = hktp->next) {
+                    if (c == *hktp->zkata)
+                        if (*kana == *(hktp->zkata + 1))
+                            break;
+                }
+                if (hktp != NULL) {
+                    *p++ = *hktp->hira;
+                    *p++ = *(hktp->hira + 1);
+                } else {
+                    *p++ = c;
+                    *p++ = *kana;
+                    Xsj3cWarning("wrong sjhk table");
+                }
+
+            } else if (!ishira(s, serverIF[buf->server].lang)) {
+                for (zhtp = buf->zhtable; zhtp != NULL; zhtp = zhtp->next) {
+                    if (c == *zhtp->zkana) 
+                        if (*kana == *(zhtp->zkana + 1))
+                            break;
+                }
+                if (zhtp != NULL) {
+                    *p++ = *zhtp->halpha;
+                } else {
+                    for (zhtp = buf->zhtable; zhtp != NULL; zhtp = zhtp->next) {
+                        if (c == *zhtp->zalpha) {
+                            if (*kana == *(zhtp->zalpha + 1))
+                                break;
+                        }
+                    }
+                    if (zhtp != NULL) {
+                        *p++ = *zhtp->halpha;
+                    } else {
+                        Xsj3cWarning("can't convert to halpha %#x",s);
+                        *p++ = c;
+                        *p++ = *kana;
+                    }
+                }
+            } else {
+                *p++ = c;
+                *p++ = *kana;
+            }
+            kana++;
+        } else {
+            *p++ = c;
+        }
+    }
+    *p = '\0';
+    p = tyomi;
+    plen = strlen(tyomi);
+
+    while ((c = *p) != '\0') {
+        if (iskan1(c, serverIF[buf->server].lang)
+                && iskan2(*(p + 1), serverIF[buf->server].lang)) {
+            /* Multi-byte character */
+            q = tmp;
+            *q = '\0';
+            ylen = 0;
+            for (rktp = buf->rktable; rktp->next != NULL; rktp = rktp->next) {
+                if (ylen < rktp->ylen) {
+                    if (plen >= rktp->ylen
+                            && !strncmp(rktp->yomi, p, rktp->ylen)) {
+                        ylen = rktp->ylen;
+                        plosflg = 0;
+                        if (*(sp = rktp->str) != '\0') {
+                            /* Leaving any character case */
+                            if (t = buf->plosive) {
+                                while (*t != '\0') {
+                                    if (*t++ == *sp) {
+                                        plosflg = 1;
+                                        break;
+                                    }
+                                }
+                                if (plosflg) {
+                                    if (*(p + 2) == '\0') {
+                                        /* Last of the segment: */
+                                        /* continue to search   */
+                                        plosflg = 0;
+                                        ylen = 0;
+                                        continue;
+                                    } else if (iskan1(*(p + 2),
+                                            serverIF[buf->server].lang)
+                                            && iskan2(*(p + 3),
+                                            serverIF[buf->server].lang)) {
+                                        /* Next character is zvowel: */
+                                        /* continue to search        */
+                                        if (iszvowel((*(p + 2) << 8) | *(p + 3),
+                                                serverIF[buf->server].lang)){
+                                            plosflg = 0;
+                                            ylen = 0;
+                                            continue;
+                                        }
+                                    } else if (isvowel(*(p + 2))) {
+                                        /* Next character is vowel:  */
+                                        /* continue to search        */
+                                        plosflg = 0;
+                                        ylen = 0;
+                                        continue;
+                                    }
+                                }
+                            }
+                            strcpy(tmp, rktp->roma);
+                            /* Reduce leaved character */
+                            i = 1;
+                            while (*(++sp) != '\0')
+                                i++;
+                            r = (q + rktp->rlen);
+                            while (*(--sp) == *(--r) && (--i));
+                            *r = '\0';  
+                        } else if (d = buf->rkdouble) {
+                            /* Double defined by a same character case */
+                            strcpy(tmp, rktp->roma);
+                            while (*d != '\0') {
+                                if (*d++ == *q) {
+                                    if (*q == *(q + 1)) {
+                                        /* Last of the segment */
+                                        if (*(p + 2) == '\0')
+                                            *(q + 1) = '\0';
+                                    } else if (*(q + 1) == '\0') {
+                                        /* Single case: continue to search */
+                                        ylen = 0;
+                                    }
+                                    break;
+                                }
+                            }
+                        } else {
+                            strcpy(tmp, rktp->roma);
+                        }
+                    }
+                } 
+            }
+            if (ylen > 0) {
+                /* Succeeded in converting.    */
+                if (!zenflg && !plosflg && !isvowel(*q)
+                        && p > tyomi && (t = buf->plosive)) {
+                    /* Same as plosive table first character */
+                    if (*t == *(p - 1))
+                        cont++;
+                }
+                if (plosflg) {
+                    cont++;
+                } else if (cont && !isvowel(*q)) {
+                    /* Correct consonant character of previous plosive */
+                    sp = roma;
+                    while (cont--)
+                        *(--sp) = *q;
+                    cont = 0;
+                } else if (cont) {
+                    cont = 0;
+                }
+                /* Copy characters to output string */
+                plen -= ylen;
+                p += ylen;
+                while (*q != '\0') 
+                    *roma++ = *q++;
+            } else {
+                /* Failed to convert.       */
+                cont = 0;
+                /* Normal japanese character(except gaiji) is 2byte. */
+                *roma++ = *p++;
+                *roma++ = *p++;
+                plen -= 2;
+            }
+            zenflg++;
+        } else {
+            /* Non multi-byte character */
+            sp = p;
+            while (*sp != '\0' && !(iskan1(*sp, serverIF[buf->server].lang)
+                    && iskan2(*(sp + 1), serverIF[buf->server].lang))) {
+                sp++;
+            }
+            ylen = sp - p;
+            i = 0;
+            for (rktp = buf->rktable; rktp->next != NULL; rktp = rktp->next) {
+                if (rktp->rlen > i) {
+                    r = p;
+                    t = rktp->roma;
+                    while (r < sp && *r++ == *t++)
+                        ;
+                    if ((rlen = r - p) > i)
+                        i = rlen;
+                }
+            }
+            if (i > 0) {
+                if (!zenflg && !plosflg && !isvowel(*p) && p > tyomi
+                        && (t = buf->plosive)) {
+                    /* Same as plosive table first character */
+                    if (*t == *(p - 1))
+                        cont++;
+                }
+                if (cont && !isvowel(*p)) {
+                    /* Correct consonant character of previous plosive */
+                    sp = roma;
+                    while (cont--)
+                        *(--sp) = *p;
+                    cont = 0;
+                } else if (cont) {
+                    cont = 0;
+                }
+            } 
+            /* Copy characters to output string */
+            plen -= ylen;
+            while (ylen--)
+                *roma++ = *p++;
+            zenflg = 0;
+            plosflg = 0;
+        }
+    }
+    *roma = '\0';
+
+    if (!zenflg && (r = buf->plosive)) {
+        p--;
+        while (*r != '\0') {
+            if (*r == *p) {
+                t = buf->plosive;
+                while (*t != '\0') {
+                    if (p > tyomi && *t == *p && *t == *(p - 1)) {
+                        cont++;
+                        break;
+                    }
+                    t++;
+                }
+                break;
+            }
+            r++;
+        }
+        if (*r != '\0') {
+            /* Correct consonant character of previous plosive */
+            sp = (--roma);
+            while (cont--)
+                *(--sp) = *p;
+        }
+    } else if (zenflg && cont && plosflg) {
+        q = tmp;
+        if (*q != '\0') {
+            /* Correct consonant character of previous plosive */
+            sp = (--roma);
+            while (cont--) {
+                if (!isvowel(*(--sp)))
+                    *sp = *q;
+            }
+        }
+    }
+}
+
+void
+_Xsj3cHiraToZKata(buf, dest, src)
+    Xsj3cBuf                    buf;
+    register unsigned char     *dest,  *src;
+{
+    register wchar              s;
+    register unsigned char      c;
+    register Xsj3cHKTable      *hktp;
+    register Xsj3cZHTable      *zhtp;
+
+    while ((c = *src++) != '\0') {
+        if (iskan1(c, serverIF[buf->server].lang)
+                && iskan2(*src, serverIF[buf->server].lang)) {
+            s = (c << 8) + *src;
+            if (ishira(s, serverIF[buf->server].lang)) {
+                for (hktp = buf->hktable; hktp != NULL; hktp = hktp->next) {
+                    if (c == *hktp->hira)
+                        if (*src == *(hktp->hira + 1))
+                            break;
+                }
+                if (hktp != NULL) {
+                    *dest++ = *hktp->zkata;
+                    *dest++ = *(hktp->zkata + 1);
+                } else {
+                    *dest++ = c;
+                    *dest++ = *src;
+                    Xsj3cWarning("wrong sjhk table");
+                }
+            } else {
+                *dest++ = c;
+                *dest++ = *src;
+            }
+            src++;
+        } else if (isdakuten(c)) {
+            for (zhtp = buf->zhtable; zhtp != NULL; zhtp = zhtp->next) {
+                if (c == *zhtp->hkata)
+                    break;
+            }
+            if (zhtp != NULL) {
+                *dest++ = *zhtp->zkana;
+                *dest++ = *(zhtp->zkana + 1);
+            } else {
+                *dest++ = c;
+            }
+        } else {
+            *dest++ = c;
+        }
+    }
+    *dest = '\0';
+}
+
+void
+_Xsj3cHankakuToHira(buf, dest, src)
+    Xsj3cBuf                    buf;
+    register unsigned char     *dest,  *src;
+{
+    register unsigned char      c;
+    register Xsj3cHKTable      *hktp;
+    register Xsj3cZHTable      *zhtp;
+    register int                len;
+    unsigned char               tmp[RBUFSIZ];
+
+    while ((c = *src++) != '\0') {
+        if (iskan1(c, serverIF[buf->server].lang)
+                && iskan2(*src, serverIF[buf->server].lang)) {
+            *dest++ = c;
+            *dest++ = *src++;
+            continue;
+        }
+        if (iskana(c)) {
+            len = 0;
+            for (hktp = buf->hktable; hktp != NULL; hktp = hktp->next) {
+                if (len < hktp->hlen && c == *hktp->hkata) {
+                    if (hktp->hlen > 1) {
+                        if (iskana(*src) && *src == *(hktp->hkata + 1)) {
+                            src++;
+                            len = hktp->hlen;
+                            strcpy(tmp, hktp->hira);
+                        }
+                    } else {
+                        len = 1;
+                        strcpy(tmp, hktp->hira);
+                    }
+                }
+            }
+            if (len) {
+                strcpy(dest, tmp);
+                dest += strlen(tmp);
+            } else {
+                for (zhtp = buf->zhtable; zhtp != NULL; zhtp = zhtp->next) {
+                    if (c == *zhtp->hkata)
+                        break;
+                }
+                if (zhtp != NULL) {
+                    *dest++ = *zhtp->zkana;
+                    *dest++ = *(zhtp->zkana + 1);
+                } else {
+                    *dest++ = c;
+                }
+            }
+        } else {
+            for (zhtp = buf->zhtable; zhtp != NULL; zhtp = zhtp->next) {
+                if (c == *zhtp->hkata)
+                    break;
+            }
+            if (zhtp != NULL) {
+                *dest++ = *zhtp->zkana;
+                *dest++ = *(zhtp->zkana + 1);
+            } else {
+                *dest++ = c;
+            }
+        }
+    }
+    *dest = '\0';
+}
+
+void
+_Xsj3cHankakuToZKata(buf, dest, src)
+    Xsj3cBuf                    buf;
+    register unsigned char     *dest,  *src;
+{
+    register unsigned char      c;
+    register Xsj3cHKTable      *hktp;
+    register Xsj3cZHTable      *zhtp;
+    register int                len;
+    unsigned char               tmp[RBUFSIZ];
+
+    while ((c = *src++) != '\0') {
+        if (iskan1(c, serverIF[buf->server].lang)
+                && iskan2(*src, serverIF[buf->server].lang)) {
+            *dest++ = c;
+            *dest++ = *src++;
+            continue;
+        }
+        if (iskana(c)) {
+            len = 0;
+            for (hktp = buf->hktable; hktp != NULL; hktp = hktp->next) {
+                if (len < hktp->hlen && c == *hktp->hkata) {
+                    if (hktp->hlen > 1) {
+                        if (iskana(*src) && *src == *(hktp->hkata + 1)) {
+                            src++;
+                            strcpy(tmp, hktp->zkata);
+                            len = hktp->hlen;
+                        }
+                    } else {
+                        strcpy(tmp, hktp->zkata);
+                        len = hktp->hlen;
+                    }
+                }
+            }
+            if (len) {
+                strcpy(dest, tmp);
+                dest += strlen(tmp);
+            } else {
+                for (zhtp = buf->zhtable; zhtp != NULL; zhtp = zhtp->next) {
+                    if (c == *zhtp->hkata)
+                        break;
+                }
+                if (zhtp != NULL) {
+                    *dest++ = *zhtp->zkana;
+                    *dest++ = *(zhtp->zkana + 1);
+                } else {
+                    *dest++ = c;
+                }
+            }
+        } else {
+            for (zhtp = buf->zhtable; zhtp != NULL; zhtp = zhtp->next) {
+                if (c == *zhtp->hkata)
+                    break;
+            }
+            if (zhtp != NULL) {
+                *dest++ = *zhtp->zkana;
+                *dest++ = *(zhtp->zkana + 1);
+            } else {
+                *dest++ = c;
+            }
+        }
+    }
+    *dest = '\0';
+}
+
+void
+_Xsj3cHKataToHira(buf, dest, src)
+    Xsj3cBuf                    buf;
+    register unsigned char     *dest,  *src;
+{
+    register unsigned char      c;
+    register Xsj3cHKTable      *hktp;
+    register Xsj3cZHTable      *zhtp;
+    register int                len;
+    unsigned char               tmp[RBUFSIZ];
+
+    while ((c = *src++) != '\0') {
+        if (iskan1(c, serverIF[buf->server].lang)
+                && iskan2(*src, serverIF[buf->server].lang)) {
+            *dest++ = c;
+            *dest++ = *src++;
+            continue;
+        }
+        if (iskana(c)) {
+            len = 0;
+            for (hktp = buf->hktable; hktp != NULL; hktp = hktp->next) {
+                if (len < hktp->hlen && c == *hktp->hkata) {
+                    if (hktp->hlen > 1) {
+                        if (iskana(*src) && *src == *(hktp->hkata + 1)) {
+                            src++;
+                            len = hktp->hlen;
+                            strcpy(tmp, hktp->hira);
+                        }
+                    } else {
+                        len = 1;
+                        strcpy(tmp, hktp->hira);
+                    }
+                }
+            }
+            if (len) {
+                strcpy(dest, tmp);
+                dest += strlen(tmp);
+            } else {
+                for (zhtp = buf->zhtable; zhtp != NULL; zhtp = zhtp->next) {
+                    if (c == *zhtp->hkata)
+                        break;
+                }
+                if (zhtp != NULL) {
+                    *dest++ = *zhtp->zkana;
+                    *dest++ = *(zhtp->zkana + 1);
+                } else {
+                    *dest++ = c;
+                }
+            }
+        } else {
+            *dest++ = c;
+        }
+    }
+    *dest = '\0';
+}
+
+void
+_Xsj3cHKataToZKata(buf, dest, src)
+    Xsj3cBuf                    buf;
+    register unsigned char     *dest,  *src;
+{
+    register unsigned char      c;
+    register Xsj3cHKTable      *hktp;
+    register Xsj3cZHTable      *zhtp;
+    register int                len;
+    unsigned char               tmp[RBUFSIZ];
+
+    while ((c = *src++) != '\0') {
+        if (iskan1(c, serverIF[buf->server].lang)
+                && iskan2(*src, serverIF[buf->server].lang)) {
+            *dest++ = c;
+            *dest++ = *src++;
+            continue;
+        }
+        if (iskana(c)) {
+            len = 0;
+            for (hktp = buf->hktable; hktp != NULL; hktp = hktp->next) {
+                if (len < hktp->hlen && c == *hktp->hkata) {
+                    if (hktp->hlen > 1) {
+                        if (iskana(*src) && *src == *(hktp->hkata + 1)) {
+                            src++;
+                            strcpy(tmp, hktp->zkata);
+                            len = hktp->hlen;
+                        }
+                    } else {
+                        strcpy(tmp, hktp->zkata);
+                        len = hktp->hlen;
+                    }
+                }
+            }
+            if (len) {
+                strcpy(dest, tmp);
+                dest += strlen(tmp);
+            } else {
+                for (zhtp = buf->zhtable; zhtp != NULL; zhtp = zhtp->next) {
+                    if (c == *zhtp->hkata)
+                        break;
+                }
+                if (zhtp != NULL) {
+                    *dest++ = *zhtp->zkana;
+                    *dest++ = *(zhtp->zkana + 1);
+                } else {
+                    *dest++ = c;
+                }
+            }
+        } else {
+            *dest++ = c;
+        }
+    }
+    *dest = '\0';
+}
+
+
+void
+_Xsj3cZKanaToHKata(buf, dest, src)
+    Xsj3cBuf                    buf;
+    register unsigned char     *dest,  *src;
+{
+    register unsigned char      c;
+    register wchar              s;
+    register Xsj3cHKTable      *hktp;
+    register Xsj3cZHTable      *zhtp;
+
+    while ((c = *src++) != '\0') {
+        if (iskan1(c, serverIF[buf->server].lang)
+                && iskan2(*src, serverIF[buf->server].lang)) {
+            s = (c << 8) + *src;
+            if (ishira(s, serverIF[buf->server].lang)) {
+                for (hktp = buf->hktable; hktp != NULL; hktp = hktp->next) {
+                    if (c == *hktp->hira)
+                        if (*src == *(hktp->hira + 1))
+                            break;
+                }
+                if (hktp != NULL) {
+                    *dest++ = *hktp->hkata;
+                    if (hktp->hlen > 1)
+                        *dest++ = *(hktp->hkata + 1);
+                } else {
+                    *dest++ = c;
+                    *dest++ = *src;
+                    Xsj3cWarning("wrong sjhk table");
+                }
+            } else if (iskata(s, serverIF[buf->server].lang)) {
+                for (hktp = buf->hktable; hktp != NULL; hktp = hktp->next) {
+                    if (c == *hktp->zkata)
+                        if (*src == *(hktp->zkata + 1))
+                            break;
+                }
+                if (hktp != NULL) {
+                    *dest++ = *hktp->hkata;
+                    if (hktp->hlen > 1)
+                        *dest++ = *(hktp->hkata + 1);
+                } else {
+                    *dest++ = c;
+                    *dest++ = *src;
+                    Xsj3cWarning("wrong sjhk table");
+                }
+            } else {
+                for (zhtp = buf->zhtable; zhtp != NULL; zhtp = zhtp->next) {
+                    if (c == *zhtp->zkana)
+                        if (*src == *(zhtp->zkana + 1))
+                            break;
+                }
+                if (zhtp != NULL) {
+                    *dest++ = *zhtp->hkata;
+                } else {
+                    for (zhtp = buf->zhtable; zhtp != NULL; zhtp = zhtp->next) {
+                        if (c == *zhtp->zalpha)
+                            if (*src == *(zhtp->zalpha + 1))
+                                break;
+                    }
+                    if (zhtp != NULL) {
+                        *dest++ = *zhtp->hkata;
+                    } else {
+                        *dest++ = c;
+                        *dest++ = *src;
+                    }
+                }
+            }
+            src++;
+        } else {
+            *dest++ = c;
+        }
+    }
+    *dest = '\0';
+}
+
+void
+_Xsj3cZKataToHira(buf, dest, src)
+    Xsj3cBuf                    buf;
+    register unsigned char     *dest,  *src;
+{
+    register wchar              s;
+    register unsigned char      c;
+    register Xsj3cHKTable      *hktp;
+    register Xsj3cZHTable      *zhtp;
+
+    while ((c = *src++) != '\0') {
+        if (iskan1(c, serverIF[buf->server].lang)
+                && iskan2(*src, serverIF[buf->server].lang)) {
+            s = (c << 8) + *src;
+            if (iskata(s, serverIF[buf->server].lang)) {
+                for (hktp = buf->hktable; hktp != NULL; hktp = hktp->next) {
+                    if (c == *hktp->zkata)
+                        if (*src == *(hktp->zkata + 1))
+                            break;
+                }
+                if (hktp != NULL) {
+                    *dest++ = *hktp->hira;
+                    *dest++ = *(hktp->hira + 1);
+                } else {
+                    *dest++ = c;
+                    *dest++ = *src;
+                    Xsj3cWarning("wrong sjhk table");
+                }
+            } else {
+                *dest++ = c;
+                *dest++ = *src;
+            }
+            src++;
+        } else if (isdakuten(c)) {
+            for (zhtp = buf->zhtable; zhtp != NULL; zhtp = zhtp->next) {
+                if (c == *zhtp->hkata)
+                    break;
+            }
+            if (zhtp != NULL) {
+                *dest++ = *zhtp->zkana;
+                *dest++ = *(zhtp->zkana + 1);
+            } else {
+                *dest++ = c;
+            }
+        } else {
+            *dest++ = c;
+        }
+    }
+    *dest = '\0';
+}
+
+void
+_Xsj3cHAlphaToZAlpha(buf, dest, src)
+    Xsj3cBuf                    buf;
+    register unsigned char     *dest,  *src;
+{
+    register unsigned char      c;
+    register Xsj3cZHTable      *zhtp;
+
+    while ((c = *src++) != '\0') {
+        if (iskan1(c, serverIF[buf->server].lang)
+                && iskan2(*src, serverIF[buf->server].lang)) {
+            *dest++ = c;
+            *dest++ = *src++;
+            continue;
+        }
+        for (zhtp = buf->zhtable; zhtp != NULL; zhtp = zhtp->next) {
+            if (c == *zhtp->halpha)
+                break;
+        }
+        if (zhtp != NULL) {
+            *dest++ = *zhtp->zalpha;
+            *dest++ = *(zhtp->zalpha + 1);
+        } else {
+            *dest++ = c;
+        }
+    }
+    *dest = '\0';
+}
+
+void
+_Xsj3cHAlphaToZKana(buf, dest, src)
+    Xsj3cBuf                    buf;
+    register unsigned char     *dest,  *src;
+{
+    register unsigned char      c;
+    register Xsj3cZHTable      *zhtp;
+
+    while ((c = *src++) != '\0') {
+        if (iskan1(c, serverIF[buf->server].lang)
+                && iskan2(*src, serverIF[buf->server].lang)) {
+            *dest++ = c;
+            *dest++ = *src++;
+            continue;
+        }
+        for (zhtp = buf->zhtable; zhtp != NULL; zhtp = zhtp->next) {
+            if (c == *zhtp->halpha)
+                break;
+        }
+        if (zhtp != NULL) {
+            *dest++ = *zhtp->zkana;
+            *dest++ = *(zhtp->zkana + 1);
+        } else {
+            *dest++ = c;
+        }
+    }
+    *dest = '\0';
+}
+
+void
+_Xsj3cHAlphaToHKata(buf, dest, src)
+    Xsj3cBuf                    buf;
+    register unsigned char     *dest,  *src;
+{
+    register unsigned char      c;
+    register Xsj3cHKTable      *hktp;
+
+    while ((c = *src++) != '\0') {
+        if (iskan1(c, serverIF[buf->server].lang)
+                && iskan2(*src, serverIF[buf->server].lang)) {
+            *dest++ = c;
+            *dest++ = *src++;
+            continue;
+        }
+        for (hktp = buf->hktable; hktp != NULL; hktp = hktp->next) {
+            if (c == *hktp->halpha)
+                break;
+        }
+        if (hktp != NULL) {
+            *dest++ = *hktp->hkata;
+        } else {
+            *dest++ = c;
+        }
+    }
+    *dest = '\0';
+}
+
+void
+_Xsj3cZAlphaToHAlpha(buf, dest, src)
+    Xsj3cBuf                    buf;
+    register unsigned char     *dest,  *src;
+{
+    register unsigned char      c;
+    register Xsj3cZHTable      *zhtp;
+
+    while ((c = *src++) != '\0') {
+        if (iskan1(c, serverIF[buf->server].lang)
+                && iskan2(*src, serverIF[buf->server].lang)) {
+            for (zhtp = buf->zhtable; zhtp != NULL; zhtp = zhtp->next) {
+                if (c == *zhtp->zalpha)
+                    if (*src == *(zhtp->zalpha + 1))
+                        break;
+            }
+            if (zhtp != NULL) {
+                *dest++ = *zhtp->halpha;
+            } else {
+                *dest++ = c;
+                *dest++ = *src;
+            }
+            src++;
+        } else {
+            *dest++ = c;
+        }
+    }
+    *dest = '\0';
+}
+
+static void
+_Xsj3cLowerToUpper(buf, str)
+    Xsj3cBuf                    buf;
+    register unsigned char     *str;
+{
+    register unsigned char      c;
+    register wchar              s;
+
+    while ((c = *str++) != '\0') {
+        if (iskan1(c, serverIF[buf->server].lang)
+                && iskan2(*str, serverIF[buf->server].lang)) {
+            s = (c << 8) + *str;
+            if (iszlower(s, serverIF[buf->server].lang)) {
+                s -= 0x21;
+                *(str - 1) = (s >> 8);
+                *str++ = (s & 0xff);
+            } else {
+                str++;
+            }
+            continue;
+        }
+        if (islower(c)) {
+            *(str - 1) = toupper(c);
+        }
+    }
+}
+
+static void
+_Xsj3cUpperToLower(buf, str)
+    Xsj3cBuf                    buf;
+    register unsigned char     *str;
+{
+    register unsigned char      c;
+    register wchar              s;
+
+    while ((c = *str++) != '\0') {
+        if (iskan1(c, serverIF[buf->server].lang)
+                && iskan2(*str, serverIF[buf->server].lang)) {
+            s = (c << 8) + *str;
+            if (iszupper(s, serverIF[buf->server].lang)) {
+                s += 0x21;
+                *(str - 1) = (s >> 8);
+                *str++ = (s & 0xff);
+            } else {
+                str++;
+            }
+            continue;
+        }
+        if (isupper(c)) {
+            *(str - 1) = tolower(c);
+        }
+    }
+}