diff lib/Xsj3clib/buffer.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/buffer.c	Mon Mar 08 04:44:30 2010 +0900
@@ -0,0 +1,904 @@
+#ifndef lint
+static char *rcsid = "$Header: /net/sras32/mnt3/home/mgr/ishisone/lib/cvsroot/kinput2/src/lib/Xsj3clib/buffer.c,v 2.7 1998/07/21 09:21:15 ishisone 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 <X11/keysym.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "common.h"
+#include "util.h"
+#include "func.h"
+#include "segment.h"
+#include "table.h"
+
+Xsj3cBuf                    Xsj3cCreateBuffer();
+void                        Xsj3cFreeBuffer();
+void                        Xsj3cClearBuffer();
+void                        Xsj3cFixBuffer();
+void                        Xsj3cFlushBuffer();
+
+int                         _Xsj3cSetKeyTable();
+extern int                  _Xsj3cSetGuide();
+
+static void                 _Xsj3cFreeModeStr();
+static Xsj3cKeyTable       *_Xsj3cAllocKeyTable();
+static Xsj3cKeyTable       *_Xsj3cGetFreeKeyTable();
+static void                 _Xsj3cAddFreeKeyTable();
+static void                 _Xsj3cFreeAllKeyTable();
+static int                  _Xsj3cSetKeySym();
+static long                 _Xsj3cGetModMask();
+
+static Xsj3cKeyTable       *keynowtp = NULL,   *keymaxtp = NULL;
+static Xsj3cKeyTable       *firstkeytp = NULL, *freekeytp = NULL;
+static int                  refcount = 0;
+
+static struct _sjrcdeftable {
+    char    *key[2];
+    char    *value[10];
+} def_guide_table[] = {
+    "guide",    "hiragana",  /* $B$+$J(B  */ "\202\251\202\310",
+    "", "", "", "", "", "", "", "", "",
+    "guide",    "zkatakana", /* $BA4%+%J(B*/ "\221\123\203\112\203\151",
+    "", "", "", "", "", "", "", "", "",
+    "guide",    "hkatakana", /* $BH>%+%J(B*/ "\224\274\203\112\203\151",
+    "", "", "", "", "", "", "", "", "",
+    "guide",    "halpha",/* ABC       */ "\101\102\103",
+    "", "", "", "", "", "", "", "", "",
+    "guide",    "zalpha",/* $B#A#B#C(B    */ "\202\140\202\141\202\142",
+    "", "", "", "", "", "", "", "", "",
+    "guide",    "sjis",  /* Shift-JIS */ "\123\150\151\146\164\55\112\111\123",
+    "", "", "", "", "", "", "", "", "",
+    "guide",    "euc",   /* $B#E#U#C(B    */ "\202\144\202\164\202\142",
+    "", "", "", "", "", "", "", "", "",
+    "guide",    "jis",   /* $B#J#I#S(B    */ "\202\151\202\150\202\162",
+    "", "", "", "", "", "", "", "", "",
+    "guide",    "kuten", /* $B6hE@(B      */ "\213\346\223\137",
+    "", "", "", "", "", "", "", "", "",
+    "guide",    "toroku",   /* $BEPO?(B   */ "\223\157\230\136",
+    "", "", "", "", "", "", "", "", "",
+    "guide",    "syoukyo",  /* $B>C5n(B   */ "\217\301\213\216",
+    "", "", "", "", "", "", "", "", "",
+    "guide",    "kanji", /* $B4A;z(B      */ "\212\277\216\232",
+    "", "", "", "", "", "", "", "", "",
+    "guide",    "edit",  /* $BJT=8(B      */ "\225\322\217\127",
+    "", "", "", "", "", "", "", "", "",
+    "guide",    "candidate",/* $B0lMw(B      */ "\210\352\227\227",
+    "", "", "", "", "", "", "", "", "",
+    "guide",    "symbol",/* $B5-9f(B      */ "\213\114\215\206",
+    "", "", "", "", "", "", "", "", "",
+    "guide",    "hinsi", /* $BIJ;l(B      */ "\225\151\216\214",
+    "", "", "", "", "", "", "", "", "",
+    "guide",    "quote", /* $B0zMQ(B      */ "\210\370\227\160",
+    "", "", "", "", "", "", "", "", "",
+};
+
+static Xsj3cKeyTable defkeys[] = {
+    "henkan",   XK_Select,  FlushModeMask,  _Xsj3cConvert,      NONE,NULL,NULL,
+    "convert",  XK_Select,  FlushModeMask,  _Xsj3cConvert,      NONE,NULL,NULL,
+    "muhen",    XK_Cancel,  ConvedModeMask|ShiftMask,
+                                            _Xsj3cUnConvert,    NONE,NULL,NULL,
+    "unconvert",XK_Cancel,  ConvedModeMask|ShiftMask,
+                                            _Xsj3cUnConvert,    NONE,NULL,NULL,
+    "fix",      XK_Execute, FlushModeMask|DictModeMask,    
+                                            _Xsj3cFix,          NONE,NULL,NULL,
+    "kettei",   XK_KP_Enter,FlushModeMask,  _Xsj3cFix,          NONE,NULL,NULL,
+    "flush",    XK_Escape,  FlushModeMask,  _Xsj3cFix,          NONE,NULL,NULL,
+    "return",   XK_Return,  AllModeMask,    _Xsj3cReturn,       NONE,NULL,NULL,
+    "halpha",   XK_F6,      AllModeMask,    _Xsj3cModeHAlpha,   NONE,NULL,NULL,
+    "zalpha",   XK_F7,      AllModeMask,    _Xsj3cModeZAlpha,   NONE,NULL,NULL,
+    "hkatakana",XK_F8,      AllModeMask,    _Xsj3cModeHKata,    NONE,NULL,NULL,
+    "zkatakana",XK_F9,      AllModeMask,    _Xsj3cModeZKata,    NONE,NULL,NULL,
+    "hiragana", XK_F10,     AllModeMask,    _Xsj3cModeHira,     NONE,NULL,NULL,
+    "tohalpha", XK_F16,     FlushModeMask|ShiftMask,
+                                            _Xsj3cToHAlpha,     NONE,NULL,NULL,
+    "tozalpha", XK_F17,     FlushModeMask|ShiftMask,
+                                            _Xsj3cToZAlpha,     NONE,NULL,NULL,
+    "tohkatakana",XK_F18,   FlushModeMask|ShiftMask,
+                                            _Xsj3cToHKata,      NONE,NULL,NULL,
+    "tozkatakana",XK_F19,   FlushModeMask|ShiftMask,
+                                            _Xsj3cToZKata,      NONE,NULL,NULL,
+    "tohiragana",XK_F20,    FlushModeMask|ShiftMask,
+                                            _Xsj3cToHira,       NONE,NULL,NULL,
+    "zenkaku",  XK_F4,      FlushModeMask,  _Xsj3cZenkaku,      NONE,NULL,NULL,
+    "hankaku",  XK_F3,      FlushModeMask,  _Xsj3cHankaku,      NONE,NULL,NULL,
+    "toupper",  XK_u,       FlushModeMask|ControlMask,
+                                            _Xsj3cToUpper,      NONE,NULL,NULL,
+    "tolower",  XK_l,       FlushModeMask|ControlMask,
+                                            _Xsj3cToLower,      NONE,NULL,NULL,
+    "sjis",     XK_F15,     NoInputModeMask|FlushModeMask|ShiftMask,
+                                            _Xsj3cModeSJIS,     NONE,NULL,NULL,
+    "euc",      XK_F14,     NoInputModeMask|FlushModeMask|ShiftMask,
+                                            _Xsj3cModeEUC,      NONE,NULL,NULL,
+    "jis",      XK_F13,     NoInputModeMask|FlushModeMask|ShiftMask,
+                                            _Xsj3cModeJIS,      NONE,NULL,NULL,
+    "kuten",    XK_F12,     NoInputModeMask|FlushModeMask|ShiftMask,
+                                            _Xsj3cModeKuten,    NONE,NULL,NULL,
+    "code",     XK_F5,      NoInputModeMask|FlushModeMask,
+                                            _Xsj3cCodeRollDown, NONE,NULL,NULL,
+    "toggle",   XK_Tab,     AllModeMask,    _Xsj3cModeRollDown, NONE,NULL,NULL,
+    "modedown", XK_Tab,     AllModeMask,    _Xsj3cModeRollDown, NONE,NULL,NULL,
+    "toggleback",XK_Tab,    AllModeMask|ShiftMask,
+                                            _Xsj3cModeRollUp,   NONE,NULL,NULL,
+    "modeup",   XK_Tab,     AllModeMask|ShiftMask,
+                                            _Xsj3cModeRollUp,   NONE,NULL,NULL,
+    "nextmode", XK_Tab,     FlushModeMask|ControlMask,
+                                            _Xsj3cNextMode,     NONE,NULL,NULL,
+    "prevmode", XK_Tab,     FlushModeMask|ControlMask|ShiftMask,
+                                            _Xsj3cPrevMode,     NONE,NULL,NULL,
+    "muhenkan", XK_Cancel,  NoInputModeMask|FlushModeMask,
+                                            _Xsj3cModeToggle,   NONE,NULL,NULL,
+    "right",    XK_Right,   AllModeMask,    _Xsj3cForward,      NONE,NULL,NULL,
+    "forward",  XK_Right,   AllModeMask,    _Xsj3cForward,      NONE,NULL,NULL,
+    "left",     XK_Left,    AllModeMask,    _Xsj3cBackward,     NONE,NULL,NULL,
+    "backward", XK_Left,    AllModeMask,    _Xsj3cBackward,     NONE,NULL,NULL,
+    "top",      XK_a,       FlushModeMask|DictModeMask|ControlMask,
+                                            _Xsj3cTop,          NONE,NULL,NULL,
+    "end",      XK_e,       FlushModeMask|DictModeMask|ControlMask,
+                                            _Xsj3cEnd,          NONE,NULL,NULL,
+    "bottom",   XK_e,       FlushModeMask|DictModeMask|ControlMask,
+                                            _Xsj3cEnd,          NONE,NULL,NULL,
+    "up",       XK_Up,      SelectModeMask, _Xsj3cUp,           NONE,NULL,NULL,
+    "down",     XK_Down,    SelectModeMask, _Xsj3cDown,         NONE,NULL,NULL,
+    "first",    XK_Up,      OutputModeMask|ControlMask,
+                                            _Xsj3cFirst,        NONE,NULL,NULL,
+    "last",     XK_Down,    OutputModeMask|ControlMask,
+                                            _Xsj3cLast,         NONE,NULL,NULL,
+    "nextp",    XK_Select,  SelectModeMask, _Xsj3cNextPage,     NONE,NULL,NULL,
+    "prevp",    XK_Cancel,  SelectModeMask, _Xsj3cPrevPage,     NONE,NULL,NULL,
+    "wrap",     XK_Down,    ConvedModeMask|ShiftMask,
+                                            _Xsj3cNext,         NONE,NULL,NULL,
+    "next",     XK_Down,    ConvedModeMask|ShiftMask,
+                                            _Xsj3cNext,         NONE,NULL,NULL,
+    "wrapback", XK_Up,      ConvedModeMask|ShiftMask,
+                                            _Xsj3cPrev,         NONE,NULL,NULL,
+    "prev",     XK_Up,      ConvedModeMask|ShiftMask,
+                                            _Xsj3cPrev,         NONE,NULL,NULL,
+    "select",   XK_Execute, SelectModeMask, _Xsj3cSelect,       NONE,NULL,NULL,
+    "cancel",   XK_Escape,  SelectModeMask|DictModeMask,
+                                            _Xsj3cCancel,       NONE,NULL,NULL,
+    "cancel",   XK_Cancel,  FlushModeMask|ShiftMask,
+                                            _Xsj3cCancel,       NONE,NULL,NULL,
+    "kakucyou", XK_Up,      FlushModeMask|DictModeMask,
+                                            _Xsj3cExpand,       NONE,NULL,NULL,
+    "expand",   XK_Up,      FlushModeMask|DictModeMask,
+                                            _Xsj3cExpand,       NONE,NULL,NULL,
+    "syukusyou",XK_Down,    FlushModeMask|DictModeMask,
+                                            _Xsj3cShrink,       NONE,NULL,NULL,
+    "shrink",   XK_Down,    FlushModeMask|DictModeMask,
+                                            _Xsj3cShrink,       NONE,NULL,NULL,
+    "backspace",XK_BackSpace,FlushModeMask|SelectModeMask|DictModeMask,
+                                            _Xsj3cBackSpace,    NONE,NULL,NULL,
+    "delete",   XK_Delete,  FlushModeMask|SelectModeMask|DictModeMask,
+                                            _Xsj3cDelete,       NONE,NULL,NULL,
+    "delafter", XK_k,       FlushModeMask|ControlMask,
+                                            _Xsj3cDelAfter,     NONE,NULL,NULL,
+    "start",    XK_Kanji,   AllModeMask|ShiftMask,
+                                            _Xsj3cStart,        NONE,NULL,NULL,
+    "reconnect",XK_Kanji,   AllModeMask|ShiftMask|Mod1Mask, 
+                                            _Xsj3cReConnect,    NONE,NULL,NULL,
+    "saihenkan",XK_Select,  NoInputModeMask|ControlMask,
+                                            _Xsj3cReConvert,    NONE,NULL,NULL,
+    "recovert", XK_Select,  NoInputModeMask|ControlMask,
+                                            _Xsj3cReConvert,    NONE,NULL,NULL,
+    "edit",     XK_Select,  ConvedModeMask|Mod1Mask,
+                                            _Xsj3cEdit,         NONE,NULL,NULL,
+    "toroku",   XK_F1,      ConvedModeMask, _Xsj3cDRegBegin,    NONE,NULL,NULL,
+    "register", XK_F1,      ConvedModeMask, _Xsj3cDRegBegin,    NONE,NULL,NULL,
+    "syoukyo",  XK_F2,      ConvedModeMask, _Xsj3cDClearBegin,  NONE,NULL,NULL,
+    "eliminate",XK_F2,      ConvedModeMask, _Xsj3cDClearBegin,  NONE,NULL,NULL,
+    "symbol",   XK_Escape,  NoInputModeMask|FlushModeMask|ShiftMask, 
+                                            _Xsj3cSymbolBegin,  NONE,NULL,NULL,
+    "quote",    XK_q,       NoInputModeMask|FlushModeMask|ControlMask,
+                                            _Xsj3cQuote,        NONE,NULL,NULL,
+    "flushbefore",NoSymbol, NULL,           _Xsj3cFlushBefore,  NONE,NULL,NULL,
+    "bell",     NoSymbol,   NULL,           _Xsj3cBell,         NONE,NULL,NULL,
+    "sjrc",     NoSymbol,   NULL,           _Xsj3cSjrc,         NONE,NULL,NULL,
+    "kill",     NoSymbol,   NULL,           _Xsj3cKill,         NONE,NULL,NULL,
+    "kana",     NoSymbol,   NULL,           _Xsj3cKana,         NONE,NULL,NULL,
+    "null",     NoSymbol,   NULL,           _Xsj3cNull,         NONE,NULL,NULL,
+    "ignore",   NoSymbol,   NULL,           _Xsj3cIgnore,       NONE,NULL,NULL,
+    NULL,       NULL,       NULL,           NULL,               NONE,NULL,NULL
+};
+
+#define KEYTBMAX    (BUFSIZ/sizeof(Xsj3cKeyTable) - 1)
+
+/*
+ * _Xsj3cAllocKeyTable()
+ *  Allocate memmory for key-function conversion table.
+ */
+static Xsj3cKeyTable *
+_Xsj3cAllocKeyTable()
+{
+    register Xsj3cKeyTable  *keytp;
+
+    if (keynowtp == NULL || keynowtp > keymaxtp) {
+        keytp = (Xsj3cKeyTable *)malloc(BUFSIZ);
+        if (keytp == NULL)
+            return (NULL);
+        else
+            bzero((char *)keytp, BUFSIZ);
+        if (!firstkeytp)
+            firstkeytp = keytp;
+        keynowtp = keytp;
+        keymaxtp = keynowtp + KEYTBMAX;
+        keynowtp++;
+    } else {
+        keytp = keynowtp;
+        keynowtp++;
+    }
+    keytp->keyword = NULL;
+    keytp->ksym = NoSymbol;
+    keytp->func = NULL;
+    keytp->inputsame = 0;
+    keytp->prev = NULL;
+    keytp->next = NULL;
+    return (keytp);
+}
+
+/*
+ * _Xsj3cAddFreeKeyTable()
+ *  Add key-function conversion table to free list.
+ */
+static void
+_Xsj3cAddFreeKeyTable(keytp)
+    register Xsj3cKeyTable  *keytp;
+{
+    if (!keytp)
+        return;
+    if (freekeytp)
+        keytp->prev = freekeytp;
+    else
+        keytp->prev = NULL;
+    freekeytp = keytp;
+    keytp->keyword = NULL;
+    keytp->ksym = NoSymbol;
+    keytp->func = NULL;
+    keytp->inputsame = 0;
+    keytp->next = NULL;
+}
+
+/*
+ * _Xsj3cGetFreeKeyTable()
+ *  Get key-function conversion table from free list.
+ */
+static Xsj3cKeyTable *
+_Xsj3cGetFreeKeyTable()
+{
+    register Xsj3cKeyTable  *keytp;
+
+    if (keytp = freekeytp)
+        freekeytp = keytp->prev;
+    return (keytp);
+}
+
+static void
+_Xsj3cFreeAllKeyTable()
+{
+    register Xsj3cKeyTable  *keytp, *keytq;
+
+    keytq = firstkeytp;
+    while (keytq) {
+        keytp = keytq;
+        keytq = keytp + KEYTBMAX;
+        if (keytq);
+            keytq = keytq->next;
+        free(keytp);
+    }
+    firstkeytp = NULL;
+    freekeytp = NULL;
+}
+
+/*
+ * _Xsj3cSetKeyTable()
+ *  Read sjrc's .key.[function] entry and set key-function conversion table.
+ */
+int
+_Xsj3cSetKeyTable(buf, table)
+    Xsj3cBuf                    buf;
+    Sjrctable                   table;
+{
+    register Xsj3cKeyTable     *keytp, *keytq, *keytr;
+    Xsj3cKeyTable              *keytf,  dummy;
+    KeySym                      ksym;
+    Xsj3ccMode                  modmask;
+    Xsj3cFlag                   inputsame;
+
+    if (!_Xsj3cSetKeySym(table->value, &ksym, &modmask, &inputsame)) 
+        return 0;
+    keytp = &dummy;
+    keytp->next= buf->key;
+    while (keytp->next != NULL) {
+        keytp = keytp->next;
+        if (keytp->ksym == NoSymbol ||(keytp->ksym == ksym &&
+            (keytp->modmask & ~AllModeMask) == (modmask & ~AllModeMask)
+            && ((keytp->modmask & AllModeMask) & modmask))) {
+            keytq = keytp->next;
+            keytf = keytp;
+            if (keytp == buf->key) {    /* top of list  */
+                buf->key = keytq;
+                keytq->prev = NULL;
+            } else if (!keytq) {        /* last of list */
+                keytp = keytp->prev;
+                keytp->next = NULL;
+            } else {
+                keytp = keytp->prev;
+                keytp->next = keytq;
+                keytq->prev = keytp;
+            }
+            _Xsj3cAddFreeKeyTable(keytf);
+        } 
+    }
+    if (!table->key[1])
+        return 0;
+    else if (ksym == NoSymbol || _Xsj3cCmp(table->key[1], "ignore"))
+        return 1;
+
+    keytr = keytp;
+    keytq = defkeys;
+    while (keytq->keyword != NULL) {
+        if (_Xsj3cCmp(table->key[1], keytq->keyword)) {
+            if (!(keytp = _Xsj3cGetFreeKeyTable())) {
+                if (!(keytp = _Xsj3cAllocKeyTable())) {
+                    Xsj3cWarning("can't allocate keysym to func table");
+                    return 0;
+                }
+            }
+            keytr->next = keytp;
+            keytp->prev = keytr;
+            keytp->keyword = keytq->keyword;
+            keytp->ksym = ksym;
+            keytp->modmask = modmask;
+            keytp->func = keytq->func;
+            keytp->inputsame = inputsame;
+            keytr = keytp;
+            keytp->next = NULL;
+            if (keytp->keyword == NULL) {
+                Xsj3cWarning("keyword %s is not supported",table->key[1]);
+                return 0;
+            }
+        } 
+        keytq++;
+    }
+    return 1;
+}
+
+/*
+ * _Xsj3cSetKeySym()
+ *  Read values of the .key.[function] entry and set keysym
+ * and modifier/conversion-mode mask.
+ */
+static int
+_Xsj3cSetKeySym(string, ksym, modmask, inputsame)
+    char          **string;
+    KeySym         *ksym;
+    Xsj3ccMode     *modmask;
+    Xsj3cFlag      *inputsame;
+{
+    register char  *p;
+    int             sub,    ret;
+
+    *modmask = 0;
+    *ksym = NoSymbol;
+    p = *string;
+
+    /* ModMask and KeySym field   */
+    if (p) {
+        if(*p == '^') { /* sj2/sj3 control keybind compatibility   */
+            if (++p) {
+                if (isupper(*p)) {
+                    sub = *p - 'A';
+                    *ksym = XK_a + sub;
+                } else if (islower(*p)) {
+                    sub = *p - 'a';
+                    *ksym = XK_a + sub;
+                } else if (*p >= '\\' && *p <= '_') {
+                    sub = *p - '\\';
+                    *ksym = XK_backslash + sub;
+                } else if (*p >= '!' && *p <= '>') {
+                    sub = *p - '!';
+                    *ksym = XK_exclam + sub;
+                } else {
+                    Xsj3cWarning("wrong keybind in sjrc file");
+                }
+                *modmask = ControlMask|AllModeMask;
+            }
+        } else if(*p == 'X') { /* sjx keybind compatibility   */
+            if (!strncmp(p, "XK_", 3)) {
+                p += 3;
+                *modmask = AllModeMask;
+                *ksym = XStringToKeysym(p);
+            } else {
+                *modmask = AllModeMask;
+                Xsj3cWarning("wrong keybind in sjrc file");
+            }
+        } else if(*p == '\033') { /* escape keybind compatibility   */
+            *ksym = XK_Escape;
+            *modmask = AllModeMask;
+        } else if(*p == '\177') { /* delete keybind compatibility   */
+            *ksym = XK_Delete;
+            *modmask = AllModeMask;
+        } else if ((ret = _Xsj3cGetModMask(*string)) >= 0) {
+            *modmask = ret;
+            if (++string)
+                *ksym = XStringToKeysym(*string);
+            else
+                Xsj3cWarning("wrong keybind in sjrc file");
+        } else {
+            Xsj3cWarning("wrong keybind in sjrc file");
+        }
+    } else {
+        *modmask = AllModeMask;
+    }
+
+    /* Through function field   */
+    p = *(++string);
+    if (p) {
+        if (_Xsj3cCmp(p, "off"))
+            *inputsame = OFF;
+        else if (_Xsj3cCmp(p, "on"))
+            *inputsame = ON;
+        else
+            *inputsame = NONE;
+    } else {
+        *inputsame = NONE;
+    }
+    return 1;
+}
+
+/*
+ * _Xsj3cGetModMask()
+ *  Read strings and convert to modifier/conversion-mode mask.
+ */
+static long
+_Xsj3cGetModMask(p)
+    register char  *p;
+{
+    char            mode[256];
+    register char  *q;
+    int             ret = AllModeMask,  mask = AllModeMask;
+    Xsj3ccMode      conversion = 0;
+
+    while (*p != '\0') {
+        q = mode;
+        while (*p != '\0' && *p != '|') {
+            *q++ = *p++;
+        }
+        if (*p != '\0')
+            p++;
+        *q = '\0';
+        q = mode; 
+        if (*q == 'n') {
+            continue;
+        } else if (*q == 's') {
+            ret |= ShiftMask;
+            continue;
+        } else if (*q == 'c') {
+            ret |= ControlMask;
+            continue;
+        } else if (*q == 'm') {
+            if (*(++q) != '\0') {
+                while (*q != '\0')
+                    q++;
+                switch(*(--q)) {
+                case '1':
+                    ret |= Mod1Mask;
+                    break;
+                case '2':
+                    ret |= Mod2Mask;
+                    break;
+                case '3':
+                    ret |= Mod3Mask;
+                    break;
+                case '4':
+                    ret |= Mod4Mask;
+                    break;
+                case '5':
+                    ret |= Mod5Mask;
+                    break;
+                default:
+                    ret |= Mod1Mask;
+                    break;
+                }
+            } else 
+                ret |= Mod1Mask;
+            continue;
+        } else if (*q == 'l') {
+            ret |= LockMask;
+            continue;
+        } else if (*q == 'k') {
+            ret |= KanaMask;
+            continue;
+        } else if (*q == 'N') {
+            conversion |= NoInputModeMask;
+            continue;
+        } else if (*q == 'I') { 
+            conversion |= InputModeMask;
+            continue;
+        } else if (*q == 'i') { /* for compatibility    */
+            conversion |= InputModeMask;
+            continue;
+        } else if (*q == 'u') { /* for compatibility    */
+            conversion |= ConvedModeMask;
+            continue;
+        } else if (*q == 'U') { /* for compatibility    */
+            conversion |= ConvedModeMask;
+            continue;
+        } else if (*q == 'C') {
+            conversion |= ConvedModeMask;
+            continue;
+        } else if (*q == 'v') { /* for compatibility    */
+            conversion |= SelectModeMask;
+            continue;
+        } else if (*q == 'V') { /* for compatibility    */
+            conversion |= SelectModeMask;
+            continue;
+        } else if (*q == 'S') {
+            conversion |= SelectModeMask;
+            continue;
+        } else if (*q == 'o') { /* for compatibility    */
+            conversion |= OutputModeMask;
+            continue;
+        } else if (*q == 'O') {
+            conversion |= OutputModeMask;
+            continue;
+        } else if (*q == 'd') { /* for compatibility    */
+            conversion |= DictModeMask;
+            continue;
+        } else if (*q == 'D') {
+            conversion |= DictModeMask;
+            continue;
+        } else if (*q == 'f') { /* for compatibility    */
+            conversion |= FlushModeMask;
+            continue;
+        } else if (*q == 'F') {
+            conversion |= FlushModeMask;
+            continue;
+        } else if (*q == 'a') { /* for compatibility    */
+            conversion |= AllModeMask;
+            continue;
+        } else if (*q == 'A') {
+            conversion |= AllModeMask;
+            continue;
+        } else {
+            Xsj3cWarning("Ilegal keybind modmask %s in sjrc file",mode);
+            ret = -1;
+        }
+    }
+    if (conversion) {
+        ret &= ~mask;
+        ret |= conversion;
+    }
+    return ret;
+}
+
+/*
+ * Xsj3cCreateBuffer()
+ * Allocate Xsj3cBuf type structure and initialize all flags and buffers.
+ */
+Xsj3cBuf
+Xsj3cCreateBuffer()
+{
+    Xsj3cBuf            buf;
+    Xsj3cKeyTable      *keytp, *keytq, *keytr;
+    register int        i,      back_lang;
+
+    /*  Allocate buffer fields  */
+
+    if ((buf = (Xsj3cBuf)malloc(sizeof(Xsj3cBufRec))) == NULL) {
+        return (Xsj3cBuf)NULL;
+    }
+    bzero(buf, sizeof(Xsj3cBufRec));
+
+    /* Default definition for uninitialized field */
+
+    buf->convmode = NoInputModeMask;
+    buf->server = SERVER_SJ3;
+    if ((buf->input = (Xsj3cSeg *)calloc(BUNBUFSIZ, sizeof(Xsj3cSeg)))
+                == NULL) {
+        return (Xsj3cBuf)NULL;
+    }
+    bzero(buf->input, BUNBUFSIZ * sizeof(Xsj3cSeg));
+    buf->backup = NULL;
+    buf->current = NULL;
+    buf->segnum = 0;
+    buf->backsegnum = 0;
+    buf->curseg = 0;
+    buf->convedsegnum = 0;
+
+    buf->inputmode = MODE_HIRA;
+    buf->dispmode = MODE_HIRA;
+    
+    buf->dict = NULL;
+
+    buf->candidate = NULL;
+    buf->hinsi = NULL;
+    buf->symbol = NULL;
+
+    buf->candnum = 0;
+    buf->curcand = 0;
+    buf->cursymbol = 0;
+    buf->curhinsi = 0;
+    buf->selectstatus = SELECT_CAND;
+    buf->n_select = 0;
+    buf->candseg = 0;
+
+    buf->rktable = NULL;
+    buf->hktable = NULL;
+    buf->zhtable = NULL;
+    buf->plosive = NULL;
+    buf->rkdouble = NULL;
+
+    /* Initialize common (with sj2/sj3/sjx) flags area */
+    /* Make keysym to function hash table  */
+    for (keytp = defkeys, i = 0; keytp->keyword != NULL; keytp++) {
+        if (!(keytq = _Xsj3cGetFreeKeyTable())) {
+            if (!(keytq = _Xsj3cAllocKeyTable())) {
+                Xsj3cWarning("can't allocate keysym to func table");
+                return (Xsj3cBuf)NULL;
+            }
+        }
+        if (!i++) {
+            buf->key = keytq;
+            keytq->prev = NULL;
+        } else {
+            keytr->next = keytq;
+            keytq->prev = keytr;
+        }
+        keytq->keyword = keytp->keyword;
+        keytq->ksym = keytp->ksym;
+        keytq->modmask = keytp->modmask;
+        keytq->func = keytp->func;
+        keytq->inputsame = keytp->inputsame;
+        keytr = keytq;
+    }
+    keytq->next = NULL;
+
+    for (i = 0; i < MODE_INROT_NUM; i++) 
+        buf->inmoderot[i]= i;
+    buf->inmoderotnum = MODE_INROT_NUM;
+    for (i = 0; i < MODE_OUTROT_NUM; i++) 
+        buf->outmoderot[i]= i;
+    buf->outmoderotnum = MODE_OUTROT_NUM;
+    for (i = 0; i < MODE_CODE_NUM; i++) 
+        buf->defcode[i]= MODE_SJIS + i;
+    buf->coderotnum = MODE_CODE_NUM;
+    buf->muhenmode = MODE_HALPHA;
+    buf->togglemode = MODE_HIRA;
+    buf->dotoggle = ON;
+    buf->throughflg = 0;
+
+    buf->rcfile = NULL;
+    back_lang = in_lang;
+    in_lang = JP_SJIS;
+    for (i = 0; i < MODE_STR_NUM; i++) {
+        _Xsj3cSetGuide(buf, &def_guide_table[i]);
+    }
+    in_lang = back_lang;
+
+    buf->gakusyuu = ON;
+    buf->rkbell = OFF;
+    buf->flushaconv = OFF;
+    buf->sj3serv = NULL;
+    buf->setnormal = NULL;
+    buf->throughnext = NULL;
+
+    /* Initialize Xsj3clib original flags area   */
+    buf->sj3serv2 = NULL;
+    buf->alphaconv = OFF;
+    buf->backdisplay = OFF;
+    buf->beginlastseg = ON;
+    buf->expandkconv = SEG_CONVED;
+    buf->shrinkkconv = SEG_CONVED;
+    buf->expandmconv = SEG_NOCONV;
+    buf->shrinkmconv = SEG_NOCONV;
+    buf->shrinkall = OFF;
+    buf->flushiconv = ON;
+    buf->flushsconv = NONE;
+    buf->flusheconv = ON;
+    buf->henkanseg = ALL;
+    buf->muhenseg = ONE;
+    buf->delchange = ONE;
+    buf->flushchange = ONE;
+    for ( i = 0; i < MODE_CONV_NUM; i++) 
+        buf->modeconv[i] = SEG_CONVED;
+    buf->moveloop = OFF;
+    buf->movebyseg = SEG_CONVED;
+    buf->jumpbyseg = SEG_CONVED;
+    buf->delbyseg = SEG_CONVED;
+    buf->killbyseg = SEG_CONVED;
+    buf->muhencurlast = OFF;
+    buf->editcurlast = OFF;
+    buf->flushcurlast = OFF;
+    buf->convedunderline = ON;
+    buf->dispmodechange = OFF;
+    buf->dellastmove = ON;
+    buf->kanaonly = OFF;
+    buf->inputsame = ON;
+    buf->cntrlsame = OFF;
+    buf->selectconv = ON;
+    buf->beforeconv = OFF;
+    buf->lastdoubleconv = OFF;
+    buf->selectcount = 0;
+    buf->selectback = OFF;
+    buf->candpadding = OFF;
+
+    refcount++;
+    return (buf);
+}
+
+/*
+ * _Xsj3cFreeModeStr()
+ *  Free memory of mode guide strings.
+ */
+static void
+_Xsj3cFreeModeStr(buf)
+    Xsj3cBuf                buf;
+{
+    register int            i;
+
+    for (i = 0; i < MODE_STR_NUM; i++) {
+        if (buf->modestr[i])
+            free(buf->modestr[i]);
+        buf->modestr[i] = NULL;
+    }
+}
+
+/*
+ * Xsj3cFreeBuffer()
+ *  Free all data buffers.
+ */
+void
+Xsj3cFreeBuffer(buf)
+    Xsj3cBuf            buf;
+{
+    register int        i;
+
+    _Xsj3cFreeModeStr(buf);
+    if (!refcount)
+        _Xsj3cFreeAllKeyTable();
+    if (buf->input) {
+        for (i = 0; i < buf->segnum + 1; i++) {
+            Xsj3cFreeSegment(buf->input[i]);
+            buf->input[i] = NULL;
+        }
+        free(buf->input);
+        buf->input = NULL;
+    }
+    if (buf->backup) {
+        for (i = 0; i < buf->backsegnum + 1; i++) {
+            Xsj3cFreeSegment(buf->backup[i]);
+            buf->backup[i] = NULL;
+        }
+        free(buf->backup);
+        buf->backup = NULL;
+    }
+    free(buf);
+}
+
+/*
+ * Xsj3cClearBuffer()
+ *  Clear buffers.
+ */
+void
+Xsj3cClearBuffer(buf)
+    Xsj3cBuf            buf;
+{
+    register int        i;
+
+    for (i = 0; i < buf->segnum + 1; i++) {
+        Xsj3cFreeSegment(buf->input[i]);
+        buf->input[i] = NULL;
+    }
+    buf->convmode = InputModeMask;
+    buf->curseg = 0;
+    buf->segnum = 0;
+    buf->convedsegnum = 0;
+    buf->dispmode = buf->inputmode;
+}
+
+/*
+ * Xsj3cFixBuffer()
+ *  Fix and backup buffers.
+ */
+void
+Xsj3cFixBuffer(buf)
+    Xsj3cBuf            buf;
+{
+    register int        i;
+    int                 j;
+
+    if (buf->backup) {
+        for (i = 0; i < buf->backsegnum + 1; i++) {
+            Xsj3cFreeSegment(buf->backup[i]);
+            buf->backup[i] = NULL;
+        }
+        free(buf->backup);
+        buf->backup = NULL;
+    }
+    if (buf->convmode & InputModeMask) {
+        j = buf->input[buf->curseg]->cur - 1;
+        if (j >= 0 && buf->input[buf->curseg]->yomi[j] < 256 &&
+                iscntrl((unsigned char)buf->input[buf->curseg]->yomi[j])) {
+            unsigned char   tmp[RBUFSIZ];
+
+            _Xsj3cExtractChar(buf, buf->input[buf->curseg], tmp, 1);
+            _Xsj3cStoreYomi(buf, buf->input[buf->curseg], j);
+            if (!buf->input[buf->curseg]->num) {
+                buf->segnum--;
+                Xsj3cFreeSegment(buf->input[buf->curseg]);
+                buf->input[buf->curseg] = NULL;
+                for (i = buf->curseg; i < buf->segnum; i++) {
+                    buf->input[i] = buf->input[i + 1];
+                }
+                buf->input[buf->segnum] = NULL;
+            }
+        }
+        buf->convmode = NoInputModeMask;
+    } else if (buf->convmode & ~NoInputModeMask) {
+        j = buf->input[buf->curseg]->dnum - 1;
+        if (j >= 0 && buf->input[buf->curseg]->disp[j] < 256 &&
+            iscntrl((unsigned char)buf->input[buf->curseg]->disp[j])) {
+            buf->input[buf->curseg]->dnum--;
+            buf->input[buf->curseg]->disp[j] = '\0';
+        } 
+        if (buf->convmode != SelectModeMask) /* For symbol input    */
+            buf->convmode = NoInputModeMask;
+    }
+    buf->backup = buf->input;
+    buf->backsegnum = buf->segnum;
+    buf->input = NULL;
+    if ((buf->input = (Xsj3cSeg *)calloc(BUNBUFSIZ,
+            sizeof(Xsj3cSeg))) == NULL) {
+        Xsj3cError("Cannot allocate for input buffers");
+    }
+    buf->curseg = 0;
+    buf->segnum = 0;
+    buf->convedsegnum = 0;
+    buf->dispmode = buf->inputmode;
+}
+
+/*
+ * Xsj3cFlushBuffer()
+ *  Flush and backup buffers.
+ */
+void
+Xsj3cFlushBuffer(buf)
+    Xsj3cBuf            buf;
+{
+    register int        tmpsegnum;
+    register Xsj3cSeg  *segp;
+
+    segp = buf->backup;
+    buf->backup = buf->input;
+    buf->input = segp;
+    tmpsegnum = buf->backsegnum;
+    buf->backsegnum = buf->segnum;
+    buf->segnum = tmpsegnum;
+    buf->curseg = 0;
+    buf->convmode = InputModeMask;
+    buf->convedsegnum = 0;
+    buf->dispmode = buf->inputmode;
+}