summaryrefslogtreecommitdiff
path: root/sys/src/cmd/ktrans
diff options
context:
space:
mode:
authorJacob Moody <moody@posixcafe.org>2022-08-03 11:14:44 +0000
committerJacob Moody <moody@posixcafe.org>2022-08-03 11:14:44 +0000
commit0541a434cb9cfd1a776f1ef29de3a8a7aa1d9b99 (patch)
tree004121733d38dd829d622e988228b5213d768d96 /sys/src/cmd/ktrans
parent30794bba756772ada85b7642beddb42ffc416203 (diff)
ktrans: 新しい降り
Rewrite of ktrans to act as an overlay to kbdfs. Move map files outside of the binary in to /lib/ktrans and get our dictionaries out of /lib while we're at it. Use \n as an alias for ctrl-\ for first lookup, use ^w to clear okurigana input. This also in general changes the logic to never us to 'swallow' a character and always echo them out, using backspaces for cleaning us up.
Diffstat (limited to 'sys/src/cmd/ktrans')
-rw-r--r--sys/src/cmd/ktrans/fs.c401
-rw-r--r--sys/src/cmd/ktrans/ktrans.h2875
-rw-r--r--sys/src/cmd/ktrans/main.c915
-rw-r--r--sys/src/cmd/ktrans/mkfile1
4 files changed, 884 insertions, 3308 deletions
diff --git a/sys/src/cmd/ktrans/fs.c b/sys/src/cmd/ktrans/fs.c
new file mode 100644
index 000000000..790ff6ee6
--- /dev/null
+++ b/sys/src/cmd/ktrans/fs.c
@@ -0,0 +1,401 @@
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+
+#include "hash.h"
+#include "ktrans.h"
+
+static Channel *globalkbd;
+static char *user;
+
+char*
+parsekbd(Channel *out, char *buf, int n)
+{
+ char *p, *e;
+ Msg msg;
+
+ for(p = buf; p < buf+n;){
+ msg.code = p[0];
+ p++;
+ switch(msg.code){
+ case 'c': case 'k': case 'K':
+ break;
+ default:
+ return "malformed kbd message";
+ }
+ e = utfecpy(msg.buf, msg.buf + sizeof msg.buf, p);
+ if(e == msg.buf)
+ return "short command";
+ p += e - msg.buf;
+ p++;
+ if(send(out, &msg) == -1)
+ return nil;
+ }
+ return nil;
+}
+
+void
+kbdproc(void *a)
+{
+ char *s;
+ int fd, n;
+ char buf[128];
+
+ s = a;
+ fd = open(s, OREAD);
+ if(fd < 0){
+ fprint(2, "could not open file %s: %r", s);
+ chanclose(globalkbd);
+ return;
+ }
+ for(;;){
+ n = read(fd, buf, sizeof buf);
+ if(n < 3){
+ continue;
+ }
+ parsekbd(globalkbd, buf, n);
+ }
+}
+
+Trans*
+spawntrans(int global)
+{
+ Trans *t;
+
+ t = mallocz(sizeof *t, 1);
+ if(global)
+ t->input = globalkbd;
+ else
+ t->input = chancreate(sizeof(Msg), 0);
+ t->output = chancreate(sizeof(Msg), 0);
+ t->dict = chancreate(sizeof(Msg), 0);
+ t->done = chancreate(1, 0);
+ t->lang = chancreate(sizeof(char*), 0);
+ proccreate(keyproc, t, mainstacksize);
+ return t;
+}
+
+void
+closetrans(Trans *t)
+{
+ chanclose(t->input);
+ chanclose(t->output);
+ chanclose(t->dict);
+
+ /* wait for threads to exit */
+ recv(t->done, nil);
+ recv(t->done, nil);
+
+ chanfree(t->done);
+ chanfree(t->input);
+ chanfree(t->output);
+ chanfree(t->dict);
+ free(t);
+}
+
+enum{
+ Qroot,
+ Qkbd,
+ Qkbdin,
+ Qlang,
+};
+
+Dir dirtab[] = {
+ {.qid={Qroot, 0, QTDIR}, .mode=0555, .name="/"},
+ {.qid={Qkbd, 0, QTFILE}, .mode=0600, .name="kbd"},
+ {.qid={Qkbdin, 0, QTFILE}, .mode=0200, .name="kbdin"},
+ {.qid={Qlang, 0, QTFILE}, .mode=0600, .name="lang"},
+};
+
+static int
+dirgen(int n, Dir *dir, void*)
+{
+ n++;
+ if(n >= nelem(dirtab))
+ return -1;
+
+ *dir = dirtab[n];
+ dir->name = estrdup9p(dir->name);
+ dir->uid = estrdup9p(user);
+ dir->gid = estrdup9p(user);
+ dir->muid = estrdup9p(user);
+ return 0;
+}
+
+typedef struct Aux Aux;
+struct Aux {
+ Ref;
+ Reqqueue *q;
+ Trans *t;
+};
+
+static void
+fsattach(Req *r)
+{
+ Aux *aux;
+ Trans *t;
+ char *aname;
+
+ /*
+ * Each attach allocates a new "keyboard".
+ * The global attach argument denotes to
+ * use /dev/kbd as the source of keyboard input.
+ *
+ * Sessions include one translation
+ * process, and one read queue. Since
+ * it is common for clients to constantly be
+ * blocked on the kbd file, we need to assign it to
+ * it's own process so we can service other requests
+ * in the meantime.
+ */
+
+ aname = r->ifcall.aname;
+ if(aname != nil && strcmp(aname, "global") == 0)
+ t = spawntrans(1);
+ else
+ t = spawntrans(0);
+
+ aux = mallocz(sizeof *aux, 1);
+ aux->t = t;
+ aux->q = reqqueuecreate();
+ incref(aux);
+
+ r->fid->aux = aux;
+ r->ofcall.qid = dirtab[0].qid;
+ r->fid->qid = dirtab[0].qid;
+ respond(r, nil);
+}
+
+static void
+fsopen(Req *r)
+{
+ respond(r, nil);
+}
+
+static void
+fskbd(Req *r)
+{
+ Aux *aux;
+ Msg m;
+ char *p;
+ char buf[1+128], *bp;
+ Rune rn;
+
+ aux = r->fid->aux;
+ if(recv(aux->t->output, &m) == -1){
+ respond(r, "closing");
+ return;
+ }
+ if(m.code != 'c'){
+ bp = seprint(buf, buf + sizeof buf, "%c%s", m.code, m.buf);
+ goto Send;
+ }
+ p = m.buf;
+ bp = buf;
+ for(;bp < buf + sizeof buf;){
+ p += chartorune(&rn, p);
+ if(rn == Runeerror || rn == '\0')
+ break;
+ bp = seprint(bp, buf + sizeof buf, "c%C", rn);
+ bp++;
+ }
+ if(bp >= buf + sizeof buf){
+ while(*bp-- != '\0')
+ ;
+ bp++;
+ }
+
+Send:
+ r->ifcall.offset = 0;
+ readbuf(r, buf, (bp-buf)+1);
+ respond(r, nil);
+}
+
+static void
+fsread(Req *r)
+{
+ Aux *aux;
+ Msg m;
+ char *p;
+
+ aux = r->fid->aux;
+ switch(r->fid->qid.path){
+ case Qroot:
+ dirread9p(r, dirgen, nil);
+ respond(r, nil);
+ break;
+ case Qkbd:
+
+ reqqueuepush(aux->q, r, fskbd);
+ break;
+ case Qlang:
+ m.code = 'q';
+ m.buf[0] = '\0';
+ if(send(aux->t->input, &m) == -1){
+ respond(r, "closing");
+ break;
+ }
+ if(recv(aux->t->lang, &p) == -1){
+ respond(r, "closing");
+ break;
+ }
+ snprint(m.buf, sizeof m.buf, "%s\n", p);
+ readstr(r, m.buf);
+ respond(r, nil);
+ break;
+ default:
+ respond(r, "bad op");
+ break;
+ }
+}
+
+static void
+fswrite(Req *r)
+{
+ Aux *aux;
+ int n, lang;
+ char *err, *p;
+ Msg m;
+
+ aux = r->fid->aux;
+ n = r->ifcall.count;
+ switch(r->fid->qid.path){
+ case Qkbdin:
+ if(n < 3){
+ respond(r, "short write");
+ return;
+ }
+ err = parsekbd(aux->t->input, r->ifcall.data, n);
+ if(err != nil){
+ respond(r, err);
+ return;
+ }
+ break;
+ case Qlang:
+ if(n >= sizeof m.buf){
+ respond(r, "large write");
+ return;
+ }
+ memmove(m.buf, r->ifcall.data, n);
+ m.buf[n] = '\0';
+ p = strchr(m.buf, '\n');
+ if(p != nil)
+ *p = '\0';
+ lang = parselang(m.buf);
+ if(lang < 0){
+ respond(r, "unkonwn lang");
+ return;
+ }
+ m.buf[0] = lang;
+ m.buf[1] = '\0';
+ m.code = 'c';
+ send(aux->t->input, &m);
+ }
+ r->ofcall.count = n;
+ respond(r, nil);
+}
+
+static void
+fsstat(Req *r)
+{
+ if(dirgen(r->fid->qid.path - 1, &r->d, nil) == -1)
+ respond(r, "invalid fid");
+ else
+ respond(r, nil);
+
+}
+
+static char*
+fswalk1(Fid *fid, char *name, Qid *qid)
+{
+ int i;
+
+ if(fid->qid.path != Qroot)
+ return "walk from non root";
+
+ for(i = 0; i < nelem(dirtab); i++)
+ if(strcmp(name, dirtab[i].name) == 0){
+ *qid = dirtab[i].qid;
+ break;
+ }
+
+ if(i == nelem(dirtab))
+ return "file does not exist";
+
+ fid->qid = *qid;
+ return nil;
+}
+
+static char*
+fsclone(Fid *oldfid, Fid *newfid)
+{
+ Aux *aux;
+
+ aux = oldfid->aux;
+ incref(aux);
+ newfid->aux = aux;
+
+ return nil;
+}
+
+static void
+fidclunk(Fid *fid)
+{
+ Aux *aux;
+
+ aux = fid->aux;
+ if(decref(aux) != 0)
+ return;
+
+ closetrans(aux->t);
+ reqqueuefree(aux->q);
+}
+
+
+static Srv fs = {
+ .attach=fsattach,
+ .open=fsopen,
+ .read=fsread,
+ .write=fswrite,
+ .stat=fsstat,
+
+ .walk1=fswalk1,
+ .clone=fsclone,
+ .destroyfid=fidclunk,
+};
+
+void
+launchfs(char *srv, char *mnt, char *kbd)
+{
+ int fd;
+ char buf[128];
+
+ user = getenv("user");
+ if(user == nil)
+ user = "glenda";
+ if(kbd != nil){
+ globalkbd = chancreate(sizeof(Msg), 0);
+ proccreate(kbdproc, kbd, mainstacksize);
+ }
+
+ fd = threadpostsrv(&fs, srv);
+ if(fd < 0)
+ sysfatal("postsrv %r");
+
+ if(kbd != nil){
+ if(mount(fd, -1, mnt, MREPL, "global") < 0)
+ sysfatal("mount %r");
+
+ snprint(buf, sizeof buf, "%s/kbd", mnt);
+ if(bind(buf, "/dev/kbd", MREPL) < 0)
+ sysfatal("bind %r");
+
+ snprint(buf, sizeof buf, "%s/kbdin", mnt);
+ if(bind(buf, "/dev/kbdin", MREPL) < 0)
+ sysfatal("bind %r");
+ } else
+ if(mount(fd, -1, mnt, MREPL, "") < 0)
+ sysfatal("mount %r");
+}
diff --git a/sys/src/cmd/ktrans/ktrans.h b/sys/src/cmd/ktrans/ktrans.h
index d9f59040f..151fe666c 100644
--- a/sys/src/cmd/ktrans/ktrans.h
+++ b/sys/src/cmd/ktrans/ktrans.h
@@ -5,2868 +5,21 @@ struct Map {
char leadstomore;
};
-Hmap *hanzi;
-/* hazi is 'natural' input with explicit inference */
-
-Hmap *kata;
-Map mkata[] = {
- "a", "ア", 0,
- "-", "ー", 0,
- "i", "イ", 0,
- "u", "ウ", 0,
- "e", "エ", 0,
- "o", "オ", 0,
- "ka", "カ", 0,
- "ga", "ガ", 0,
- "ki", "キ", 0,
- "kya", "キャ", 0,
- "kyu", "キュ", 0,
- "kyo", "キョ", 0,
- "gi", "ギ", 0,
- "gya", "ギャ", 0,
- "gyu", "ギュ", 0,
- "gyo", "ギョ", 0,
- "ku", "ク", 0,
- "gu", "グ", 0,
- "ke", "ケ", 0,
- "ge", "ゲ", 0,
- "ko", "コ", 0,
- "go", "ゴ", 0,
- "sa", "サ", 0,
- "za", "ザ", 0,
- "si", "シ", 0,
- "shi", "シ", 0,
- "ji", "ジ", 0,
- "sha", "シャ", 0,
- "she", "シェ", 0,
- "shu", "シュ", 0,
- "je", "ジェ", 0,
- "sho", "ショ", 0,
- "syo", "ショ", 0,
- "ja", "ジャ", 0,
- "ju", "ジュ", 0,
- "je", "ジェ", 0,
- "jo", "ジョ", 0,
- "su", "ス", 0,
- "zu", "ズ", 0,
- "se", "セ", 0,
- "ze", "ゼ", 0,
- "so", "ソ", 0,
- "zo", "ゾ", 0,
- "ta", "タ", 0,
- "da", "ダ", 0,
- "ti", "ティ", 0,
- "chi", "チ", 0,
- "zi", "ヂ", 0,
- "cha", "チャ", 0,
- "chu", "チュ", 0,
- "tyu", "チュ", 0,
- "che", "チェ", 0,
- "cho", "チョ", 0,
- "tu", "ツ", 0,
- "tsu", "ツ", 0,
- "du", "ヅ", 0,
- "te", "テ", 0,
- "de", "デ", 0,
- "to", "ト", 0,
- "do", "ド", 0,
- "na", "ナ", 0,
- "ni", "ニ", 0,
- "nya", "ニャ", 0,
- "nyu", "ニュ", 0,
- "nyo", "ニョ", 0,
- "nu", "ヌ", 0,
- "ne", "ネ", 0,
- "no", "ノ", 0,
- "ha", "ハ", 0,
- "ba", "バ", 0,
- "pa", "パ", 0,
- "hi", "ヒ", 0,
- "hya", "ヒャ", 0,
- "hyu", "ヒュ", 0,
- "hyo", "ヒョ", 0,
- "bi", "ビ", 0,
- "bya", "ビャ", 0,
- "byu", "ビュ", 0,
- "byo", "ビョ", 0,
- "pi", "ピ", 0,
- "pya", "ピャ", 0,
- "pyu", "ピュ", 0,
- "pyo", "ピョ", 0,
- "hu", "フ", 0,
- "fu", "フ", 0,
- "bu", "ブ", 0,
- "pu", "プ", 0,
- "he", "ヘ", 0,
- "be", "ベ", 0,
- "pe", "ペ", 0,
- "ho", "ホ", 0,
- "bo", "ボ", 0,
- "po", "ポ", 0,
- "ma", "マ", 0,
- "mi", "ミ", 0,
- "mya", "ミャ", 0,
- "myu", "ミュ", 0,
- "myo", "ミョ", 0,
- "mu", "ム", 0,
- "me", "メ", 0,
- "mo", "モ", 0,
- "ya", "ヤ", 0,
- "yu", "ユ", 0,
- "yo", "ヨ", 0,
- "ra", "ラ", 0,
- "ri", "リ", 0,
- "rya", "リャ", 0,
- "ryu", "リュ", 0,
- "ryo", "リョ", 0,
- "ru", "ル", 0,
- "re", "レ", 0,
- "ro", "ロ", 0,
- "wa", "ワ", 0,
- "wi", "ヰ", 0,
- "we", "ヱ", 0,
- "wo", "ヲ", 0,
- "n", "ン", 0,
- "xn", "ン", 0,
- "v", "ヴ", 0,
- "xa", "ァ", 0,
- "xi", "ィ", 0,
- "xe", "ェ", 0,
- "xo", "ォ", 0,
- "cc", "ッ", 0,
- "dd", "ッ", 0,
- "kk", "ッ", 0,
- "pp", "ッ", 0,
- "tt", "ッ", 0,
- "tch", "ッ", 0,
- "ss", "ッ", 0,
- "xn", "ン", 0,
- "di", "ディ", 0,
- "fa", "ファ", 0,
- "fi", "フィ", 0,
- "fe", "フェ", 0,
- "fo", "フォ", 0,
- "va", "ヴァ", 0,
- "vi", "ヴィ", 0,
- "ve", "ヴェ", 0,
- "vo", "ヴォ", 0,
- ".", "。", 0,
- ",", "、", 0,
- 0
-};
-
-Hmap *hira;
-Map mhira[] = {
- "a", "あ", 0,
- "-", "ー", 0,
- "i", "い", 0,
- "u", "う", 0,
- "e", "え", 0,
- "o", "お", 0,
- "ka", "か", 0,
- "ga", "が", 0,
- "ki", "き", 0,
- "kya", "きゃ", 0,
- "kyu", "きゅ", 0,
- "kyo", "きょ", 0,
- "gi", "ぎ", 0,
- "gya", "ぎゃ", 0,
- "gyu", "ぎゅ", 0,
- "gyo", "ぎょ", 0,
- "ku", "く", 0,
- "gu", "ぐ", 0,
- "ke", "け", 0,
- "ge", "げ", 0,
- "ko", "こ", 0,
- "go", "ご", 0,
- "sa", "さ", 0,
- "za", "ざ", 0,
- "si", "し", 0,
- "shi", "し", 0,
- "sha", "しゃ", 0,
- "shu", "しゅ", 0,
- "she", "しぇ", 0,
- "sho", "しょ", 0,
- "syo", "しょ", 0,
- "zi", "ぢ", 0,
- "ja", "じゃ", 0,
- "ju", "じゅ", 0,
- "je", "じぇ", 0,
- "jo", "じょ", 0,
- "su", "す", 0,
- "zu", "ず", 0,
- "se", "せ", 0,
- "ze", "ぜ", 0,
- "so", "そ", 0,
- "zo", "ぞ", 0,
- "ta", "た", 0,
- "da", "だ", 0,
- "ti", "ち", 0,
- "chi", "ち", 0,
- "cha", "ちゃ", 0,
- "chu", "ちゅ", 0,
- "tyu", "ちゅ", 0,
- "cho", "ちょ", 0,
- "ji", "じ", 0,
- "tu", "つ", 0,
- "tsu", "つ", 0,
- "du", "づ", 0,
- "te", "て", 0,
- "de", "で", 0,
- "to", "と", 0,
- "do", "ど", 0,
- "na", "な", 0,
- "ni", "に", 0,
- "nya", "にゃ", 0,
- "nyu", "にゅ", 0,
- "nyo", "にょ", 0,
- "nu", "ぬ", 0,
- "ne", "ね", 0,
- "no", "の", 0,
- "ha", "は", 0,
- "ba", "ば", 0,
- "va", "ば", 0,
- "pa", "ぱ", 0,
- "hi", "ひ", 0,
- "hya", "ひゃ", 0,
- "hyu", "ひゅ", 0,
- "hyo", "ひょ", 0,
- "bi", "び", 0,
- "bya", "びゃ", 0,
- "byu", "びゅ", 0,
- "byo", "びょ", 0,
- "vi", "び", 0,
- "pi", "ぴ", 0,
- "pya", "ぴゃ", 0,
- "pyu", "ぴゅ", 0,
- "pyo", "ぴょ", 0,
- "hu", "ふ", 0,
- "fu", "ふ", 0,
- "bu", "ぶ", 0,
- "vu", "ぶ", 0,
- "pu", "ぷ", 0,
- "he", "へ", 0,
- "be", "べ", 0,
- "ve", "べ", 0,
- "pe", "ぺ", 0,
- "ho", "ほ", 0,
- "bo", "ぼ", 0,
- "vo", "ぼ", 0,
- "po", "ぽ", 0,
- "ma", "ま", 0,
- "mi", "み", 0,
- "mya", "みゃ", 0,
- "myu", "みゅ", 0,
- "myo", "みょ", 0,
- "mu", "む", 0,
- "me", "め", 0,
- "mo", "も", 0,
- "ya", "や", 0,
- "yu", "ゆ", 0,
- "yo", "よ", 0,
- "ra", "ら", 0,
- "ri", "り", 0,
- "rya", "りゃ", 0,
- "ryu", "りゅ", 0,
- "ryo", "りょ", 0,
- "ru", "る", 0,
- "re", "れ", 0,
- "ro", "ろ", 0,
- "wa", "わ", 0,
- "wi", "ゐ", 0,
- "we", "ゑ", 0,
- "wo", "を", 0,
- "n", "ん", 0,
- "xn", "ん", 0,
- "v", "\x80", 0,
- "xa", "ぁ", 0,
- "xi", "ぃ", 0,
- "xu", "ぅ", 0,
- "xe", "ぇ", 0,
- "xo", "ぉ", 0,
- "cc", "っ", 0,
- "dd", "っ", 0,
- "kk", "っ", 0,
- "pp", "っ", 0,
- "tt", "っ", 0,
- "ss", "っ", 0,
- ".", "。", 0,
- ",", "、", 0,
- 0,
-};
-
-Hmap *cyril;
-Map mcyril[] = {
- "YO", "Ё", 0,
- "Yo", "Ё", 0,
- "A", "А", 0,
- "B", "Б", 0,
- "V", "В", 0,
- "G", "Г", 0,
- "D", "Д", 0,
- "Ye", "Е", 0,
- "YE", "Е", 0,
- "E", "Е", 0,
- "Zh", "Ж", 0,
- "ZH", "Ж", 0,
- "Z", "З", 0,
- "I", "И", 0,
- "J", "Й", 0,
- "K", "К", 0,
- "L", "Л", 0,
- "M", "М", 0,
- "N", "Н", 0,
- "O", "О", 0,
- "P", "П", 0,
- "R", "Р", 0,
- "S", "С", 0,
- "T", "Т", 0,
- "U", "У", 0,
- "F", "Ф", 0,
- "Kh", "Х", 0,
- "KH", "Х", 0,
- "X", "Х", 0,
- "Ts", "Ц", 0,
- "TS", "Ц", 0,
- "Ch", "Ч", 0,
- "CH", "Ч", 0,
- "Sh", "Ш", 0,
- "SH", "Ш", 0,
- "Shch", "Щ", 4,
- "SHCH", "Щ", 4,
- "''", "ъ", 0,
- "Y", "Ы", 0,
- "'", "ь", 0,
- "EH", "Э", 0,
- "Eh", "Э", 0,
- "Yu", "Ю", 0,
- "YU", "Ю", 0,
- "Ya", "Я", 0,
- "YA", "Я", 0,
- "a", "а", 0,
- "b", "б", 0,
- "v", "в", 0,
- "g", "г", 0,
- "d", "д", 0,
- "ye", "е", 0,
- "e", "е", 0,
- "zh", "ж", 0,
- "z", "з", 0,
- "i", "и", 0,
- "j", "й", 0,
- "k", "к", 0,
- "l", "л", 0,
- "m", "м", 0,
- "n", "н", 0,
- "o", "о", 0,
- "p", "п", 0,
- "r", "р", 0,
- "s", "с", 0,
- "t", "т", 0,
- "u", "у", 0,
- "f", "ф", 0,
- "kh", "х", 0,
- "x", "х", 0,
- "ts", "ц", 0,
- "ch", "ч", 0,
- "sh", "ш", 0,
- "shch", "щ", 4,
- "''", "ъ", 0,
- "y", "ы", 0,
- "'", "ь", 0,
- "eh", "э", 0,
- "yu", "ю", 0,
- "ya", "я", 0,
- "yo", "ё", 0,
- 0,
-};
-
-Hmap *greek;
-Map mgreek[] = {
- "A", "Α", 0,
- "'A", "Ά", 0,
- "B", "Β", 0,
- "G", "Γ", 0,
- "D", "Δ", 0,
- "E", "Ε", 0,
- "'E", "Έ", 0,
- "Z", "Ζ", 0,
- "E!", "Η", 0,
- "'E!", "Έ", 0,
- "TH", "Θ", 0,
- "Th", "Θ", 0,
- "I", "Ι", 0,
- "'I", "Ί", 0,
- "K", "Κ", 0,
- "L", "Λ", 0,
- "M", "Μ", 0,
- "N", "Ν", 0,
- "KS", "Ξ", 0,
- "Ks", "Ξ", 0,
- "O", "Ο", 0,
- "'O", "Ό", 0,
- "P", "Π", 0,
- "R", "Ρ", 0,
- "S", "Σ", 0,
- "T", "Τ", 0,
- "U", "Υ", 0,
- "'U", "Ύ", 0,
- "F", "Φ", 0,
- "CH", "Χ", 0,
- "Ch", "Χ", 0,
- "PS", "Ψ", 0,
- "Ps", "Ψ", 0,
- "O!", "Ω", 0,
- "W", "Ω", 0,
- "'O!", "Ώ", 0,
- "'W", "Ώ", 0,
- "a", "α", 0,
- "'a", "ά", 0,
- "b", "β", 0,
- "v", "β", 0,
- "g", "γ", 0,
- "d", "δ", 0,
- "e", "ε", 0,
- "'e", "έ", 0,
- "z", "ζ", 0,
- "e!", "η", 0,
- "'e!", "ή", 0,
- "ii", "η", 0,
- "'ii", "ή", 0,
- "h", "η", 0,
- "'h", "ή", 0,
- "th", "θ", 0,
- "i", "ι", 0,
- "'i", "ί", 0,
- "k", "κ", 0,
- "l", "λ", 0,
- "m", "μ", 0,
- "n", "ν", 0,
- "ks", "ξ", 0,
- "x", "ξ", 0,
- "o", "ο", 0,
- "'o", "ό", 0,
- "p", "π", 0,
- "r", "ρ", 0,
- "s ", "ς", 0,
- "s.", "ς", 0,
- "s,", "ς", 0,
- "s\n", "ς", 0,
- "s", "σ", 0,
- "t", "τ", 0,
- "u", "υ", 0,
- "'u", "ΰ", 0,
- "y", "υ", 0,
- "'y", "ΰ", 0,
- "f", "φ", 0,
- "ch", "χ", 0,
- "ps", "ψ", 0,
- "o!", "ω", 0,
- "w", "ω", 0,
- "'o!", "ώ", 0,
- "'w", "ώ", 0,
- 0
+typedef struct Msg Msg;
+struct Msg {
+ char code;
+ char buf[64];
};
-Hmap *hangul;
-Map mhangul[] = {
- "A", "A", 0,
- "B", "ㅟ", 0,
- "C", "ㅊ", 0,
- "E", "ㄸ", 0,
- "F", "F", 0,
- "G", "G", 0,
- "H", "ㅙ", 0,
- "J", "ㅝ", 0,
- "K", "ㅘ", 0,
- "L", "ㅚ", 0,
- "M", "ㅢ", 0,
- "N", "ㅞ", 0,
- "O", "ㅒ", 0,
- "P", "ㅖ", 0,
- "Q", "ㅃ", 0,
- "R", "ㄲ", 0,
- "S", "S", 0,
- "T", "ㅆ", 0,
- "V", "V", 0,
- "W", "ㅉ", 0,
- "a", "ㅁ", 0,
- "b", "ㅠ", 0,
- "c", "c", 0,
- "d", "ㅇ", 0,
- "e", "ㄷ", 0,
- "f", "ㄹ", 0,
- "g", "ㅎ", 0,
- "h", "ㅗ", 0,
- "i", "ㅑ", 0,
- "j", "ㅓ", 0,
- "k", "ㅏ", 0,
- "l", "ㅣ", 0,
- "m", "ㅡ", 0,
- "n", "ㅜ", 0,
- "o", "ㅐ", 0,
- "p", "ㅔ", 0,
- "q", "ㅂ", 0,
- "r", "ㄱ", 0,
- "s", "ㄴ", 0,
- "t", "t", 0,
- "u", "ㅕ", 0,
- "v", "ㅍ", 0,
- "w", "ㅈ", 0,
- "x", "ㅌ", 0,
- "y", "ㅛ", 0,
- "z", "ㅋ", 0,
- "rk", "가", 0,
- "ro", "개", 0,
- "ri", "갸", 0,
- "rO", "걔", 0,
- "rj", "거", 0,
- "rp", "게", 0,
- "ru", "겨", 0,
- "rP", "계", 0,
- "rh", "고", 0,
- "rK", "과", 0,
- "rH", "괘", 0,
- "rL", "괴", 0,
- "ry", "교", 0,
- "rn", "구", 0,
- "rJ", "궈", 0,
- "rN", "궤", 0,
- "rB", "귀", 0,
- "rb", "규", 0,
- "rm", "그", 0,
- "rM", "긔", 0,
- "rl", "기", 0,
- "Rk", "까", 0,
- "Ro", "깨", 0,
- "Ri", "꺄", 0,
- "Rj", "꺼", 0,
- "Rp", "께", 0,
- "Ru", "껴", 0,
- "RP", "꼐", 0,
- "Rh", "꼬", 0,
- "RK", "꽈", 0,
- "RH", "꽤", 0,
- "RL", "꾀", 0,
- "Ry", "꾜", 0,
- "Rn", "꾸", 0,
- "RJ", "꿔", 0,
- "RN", "꿰", 0,
- "RB", "뀌", 0,
- "Rb", "뀨", 0,
- "Rm", "끄", 0,
- "Rl", "끼", 0,
- "sk", "나", 0,
- "so", "내", 0,
- "si", "냐", 0,
- "sj", "너", 0,
- "sp", "네", 0,
- "su", "녀", 0,
- "sP", "녜", 0,
- "sh", "노", 0,
- "sK", "놔", 0,
- "sL", "뇌", 0,
- "sy", "뇨", 0,
- "sn", "누", 0,
- "sJ", "눠", 0,
- "sN", "눼", 0,
- "sB", "뉘", 0,
- "sb", "뉴", 0,
- "sm", "느", 0,
- "sM", "늬", 0,
- "sl", "니", 0,
- "ek", "다", 0,
- "eo", "대", 0,
- "ei", "댜", 0,
- "ej", "더", 0,
- "ep", "데", 0,
- "eu", "뎌", 0,
- "eP", "뎨", 0,
- "eh", "도", 0,
- "eK", "돠", 0,
- "eH", "돼", 0,
- "eL", "되", 0,
- "ey", "됴", 0,
- "en", "두", 0,
- "eJ", "둬", 0,
- "eN", "뒈", 0,
- "eB", "뒤", 0,
- "eb", "듀", 0,
- "em", "드", 0,
- "eM", "듸", 0,
- "el", "디", 0,
- "Ek", "따", 0,
- "Eo", "때", 0,
- "Ej", "떠", 0,
- "Ep", "떼", 0,
- "Eu", "뗘", 0,
- "Eh", "또", 0,
- "EK", "똬", 0,
- "EH", "뙈", 0,
- "EL", "뙤", 0,
- "En", "뚜", 0,
- "EN", "뛔", 0,
- "EB", "뛰", 0,
- "Em", "뜨", 0,
- "EM", "띄", 0,
- "El", "띠", 0,
- "fk", "라", 0,
- "fo", "래", 0,
- "fi", "랴", 0,
- "fj", "러", 0,
- "fp", "레", 0,
- "fu", "려", 0,
- "fP", "례", 0,
- "fh", "로", 0,
- "fK", "롸", 0,
- "fL", "뢰", 0,
- "fy", "료", 0,
- "fn", "루", 0,
- "fJ", "뤄", 0,
- "fN", "뤠", 0,
- "fB", "뤼", 0,
- "fb", "류", 0,
- "fm", "르", 0,
- "fl", "리", 0,
- "ak", "마", 0,
- "ao", "매", 0,
- "ai", "먀", 0,
- "aj", "머", 0,
- "ap", "메", 0,
- "au", "며", 0,
- "aP", "몌", 0,
- "ah", "모", 0,
- "aK", "뫄", 0,
- "aL", "뫼", 0,
- "ay", "묘", 0,
- "an", "무", 0,
- "aJ", "뭐", 0,
- "aN", "뭬", 0,
- "aB", "뮈", 0,
- "ab", "뮤", 0,
- "am", "므", 0,
- "al", "미", 0,
- "qk", "바", 0,
- "qo", "배", 0,
- "qi", "뱌", 0,
- "qj", "버", 0,
- "qp", "베", 0,
- "qu", "벼", 0,
- "qP", "볘", 0,
- "qh", "보", 0,
- "qK", "봐", 0,
- "qH", "봬", 0,
- "qL", "뵈", 0,
- "qy", "뵤", 0,
- "qn", "부", 0,
- "qJ", "붜", 0,
- "qN", "붸", 0,
- "qB", "뷔", 0,
- "qb", "뷰", 0,
- "qm", "브", 0,
- "ql", "비", 0,
- "Qk", "빠", 0,
- "Qo", "빼", 0,
- "Qi", "뺘", 0,
- "Qj", "뻐", 0,
- "Qp", "뻬", 0,
- "Qu", "뼈", 0,
- "Qh", "뽀", 0,
- "QL", "뾔", 0,
- "Qy", "뾰", 0,
- "Qn", "뿌", 0,
- "Qb", "쀼", 0,
- "Qm", "쁘", 0,
- "Ql", "삐", 0,
- "tk", "사", 0,
- "to", "새", 0,
- "ti", "샤", 0,
- "tO", "섀", 0,
- "tj", "서", 0,
- "tp", "세", 0,
- "tu", "셔", 0,
- "tP", "셰", 0,
- "th", "소", 0,
- "tK", "솨", 0,
- "tH", "쇄", 0,
- "tL", "쇠", 0,
- "ty", "쇼", 0,
- "tn", "수", 0,
- "tJ", "숴", 0,
- "tN", "쉐", 0,
- "tB", "쉬", 0,
- "tb", "슈", 0,
- "tm", "스", 0,
- "tl", "시", 0,
- "Tk", "싸", 0,
- "To", "쌔", 0,
- "Tj", "써", 0,
- "Tp", "쎄", 0,
- "Th", "쏘", 0,
- "TK", "쏴", 0,
- "TH", "쐐", 0,
- "TL", "쐬", 0,
- "Ty", "쑈", 0,
- "Tn", "쑤", 0,
- "TJ", "쒀", 0,
- "TN", "쒜", 0,
- "TB", "쒸", 0,
- "Tm", "쓰", 0,
- "TM", "씌", 0,
- "Tl", "씨", 0,
- "dk", "아", 0,
- "do", "애", 0,
- "di", "야", 0,
- "dO", "얘", 0,
- "dj", "어", 0,
- "dp", "에", 0,
- "du", "여", 0,
- "dP", "예", 0,
- "dh", "오", 0,
- "dK", "와", 0,
- "dH", "왜", 0,
- "dL", "외", 0,
- "dy", "요", 0,
- "dn", "우", 0,
- "dJ", "워", 0,
- "dN", "웨", 0,
- "dB", "위", 0,
- "db", "유", 0,
- "dm", "으", 0,
- "dM", "의", 0,
- "dl", "이", 0,
- "wk", "자", 0,
- "wo", "재", 0,
- "wi", "쟈", 0,
- "wO", "쟤", 0,
- "wj", "저", 0,
- "wp", "제", 0,
- "wu", "져", 0,
- "wP", "졔", 0,
- "wh", "조", 0,
- "wK", "좌", 0,
- "wH", "좨", 0,
- "wL", "죄", 0,
- "wy", "죠", 0,
- "wn", "주", 0,
- "wJ", "줘", 0,
- "wN", "줴", 0,
- "wB", "쥐", 0,
- "wb", "쥬", 0,
- "wm", "즈", 0,
- "wl", "지", 0,
- "Wk", "짜", 0,
- "Wo", "째", 0,
- "Wi", "쨔", 0,
- "Wj", "쩌", 0,
- "Wp", "쩨", 0,
- "Wu", "쪄", 0,
- "Wh", "쪼", 0,
- "WK", "쫘", 0,
- "WH", "쫴", 0,
- "WL", "쬐", 0,
- "Wn", "쭈", 0,
- "WJ", "쭤", 0,
- "WB", "쮜", 0,
- "Wb", "쮸", 0,
- "Wm", "쯔", 0,
- "Wl", "찌", 0,
- "ck", "차", 0,
- "co", "채", 0,
- "ci", "챠", 0,
- "cj", "처", 0,
- "cp", "체", 0,
- "cu", "쳐", 0,
- "cP", "쳬", 0,
- "ch", "초", 0,
- "cK", "촤", 0,
- "cL", "최", 0,
- "cy", "쵸", 0,
- "cn", "추", 0,
- "cJ", "춰", 0,
- "cN", "췌", 0,
- "cB", "취", 0,
- "cb", "츄", 0,
- "cm", "츠", 0,
- "cl", "치", 0,
- "zk", "카", 0,
- "zo", "캐", 0,
- "zi", "캬", 0,
- "zj", "커", 0,
- "zp", "케", 0,
- "zu", "켜", 0,
- "zP", "켸", 0,
- "zh", "코", 0,
- "zK", "콰", 0,
- "zH", "쾌", 0,
- "zL", "쾨", 0,
- "zy", "쿄", 0,
- "zn", "쿠", 0,
- "zJ", "쿼", 0,
- "zN", "퀘", 0,
- "zB", "퀴", 0,
- "zb", "큐", 0,
- "zm", "크", 0,
- "zl", "키", 0,
- "xk", "타", 0,
- "xo", "태", 0,
- "xi", "탸", 0,
- "xj", "터", 0,
- "xp", "테", 0,
- "xu", "텨", 0,
- "xP", "톄", 0,
- "xh", "토", 0,
- "xK", "톼", 0,
- "xH", "퇘", 0,
- "xL", "퇴", 0,
- "xy", "툐", 0,
- "xn", "투", 0,
- "xJ", "퉈", 0,
- "xN", "퉤", 0,
- "xB", "튀", 0,
- "xb", "튜", 0,
- "xm", "트", 0,
- "xM", "틔", 0,
- "xl", "티", 0,
- "vk", "파", 0,
- "vo", "패", 0,
- "vi", "퍄", 0,
- "vj", "퍼", 0,
- "vp", "페", 0,
- "vu", "펴", 0,
- "vP", "폐", 0,
- "vh", "포", 0,
- "vK", "퐈", 0,
- "vL", "푀", 0,
- "vy", "표", 0,
- "vn", "푸", 0,
- "vJ", "풔", 0,
- "vB", "퓌", 0,
- "vb", "퓨", 0,
- "vm", "프", 0,
- "vl", "피", 0,
- "gk", "하", 0,
- "go", "해", 0,
- "gi", "햐", 0,
- "gj", "허", 0,
- "gp", "헤", 0,
- "gu", "혀", 0,
- "gP", "혜", 0,
- "gh", "호", 0,
- "gK", "화", 0,
- "gH", "홰", 0,
- "gL", "회", 0,
- "gy", "효", 0,
- "gn", "후", 0,
- "gJ", "훠", 0,
- "gN", "훼", 0,
- "gB", "휘", 0,
- "gb", "휴", 0,
- "gm", "흐", 0,
- "gM", "희", 0,
- "gl", "히", 0,
- "rkr", "각", 0,
- "rks", "간", 0,
- "rke", "갇", 0,
- "rkf", "갈", 0,
- "rkG", "갉", 0,
- "rkM", "갊", 0,
- "rka", "감", 0,
- "rkq", "갑", 0,
- "rkC", "값", 0,
- "rkt", "갓", 0,
- "rkT", "갔", 0,
- "rkd", "강", 0,
- "rkw", "갖", 0,
- "rkc", "갗", 0,
- "rkx", "같", 0,
- "rkv", "갚", 0,
- "rkg", "갛", 0,
- "ror", "객", 0,
- "ros", "갠", 0,
- "rof", "갤", 0,
- "roa", "갬", 0,
- "roq", "갭", 0,
- "rot", "갯", 0,
- "roT", "갰", 0,
- "rod", "갱", 0,
- "rir", "갹", 0,
- "ris", "갼", 0,
- "rif", "걀", 0,
- "rit", "걋", 0,
- "rid", "걍", 0,
- "rOs", "걘", 0,
- "rOf", "걜", 0,
- "rjr", "걱", 0,
- "rjs", "건", 0,
- "rje", "걷", 0,
- "rjf", "걸", 0,
- "rjM", "걺", 0,
- "rja", "검", 0,
- "rjq", "겁", 0,
- "rjt", "것", 0,
- "rjT", "겄", 0,
- "rjd", "겅", 0,
- "rjw", "겆", 0,
- "rjx", "겉", 0,
- "rjv", "겊", 0,
- "rjg", "겋", 0,
- "rps", "겐", 0,
- "rpf", "겔", 0,
- "rpa", "겜", 0,
- "rpq", "겝", 0,
- "rpt", "겟", 0,
- "rpT", "겠", 0,
- "rpd", "겡", 0,
- "rur", "격", 0,
- "ruR", "겪", 0,
- "rus", "견", 0,
- "rue", "겯", 0,
- "ruf", "결", 0,
- "rua", "겸", 0,
- "ruq", "겹", 0,
- "rut", "겻", 0,
- "ruT", "겼", 0,
- "rud", "경", 0,
- "rux", "곁", 0,
- "rPs", "곈", 0,
- "rPf", "곌", 0,
- "rPq", "곕", 0,
- "rPt", "곗", 0,
- "rhr", "곡", 0,
- "rhs", "곤", 0,
- "rhe", "곧", 0,
- "rhf", "골", 0,
- "rhM", "곪", 0,
- "rhN", "곬", 0,
- "rhF", "곯", 0,
- "rha", "곰", 0,
- "rhq", "곱", 0,
- "rht", "곳", 0,
- "rhd", "공", 0,
- "rhw", "곶", 0,
- "rKr", "곽", 0,
- "rKs", "관", 0,
- "rKf", "괄", 0,
- "rKM", "괆", 0,
- "rKa", "괌", 0,
- "rKq", "괍", 0,
- "rKt", "괏", 0,
- "rKd", "광", 0,
- "rHs", "괜", 0,
- "rHf", "괠", 0,
- "rHq", "괩", 0,
- "rHT", "괬", 0,
- "rHd", "괭", 0,
- "rLr", "괵", 0,
- "rLs", "괸", 0,
- "rLf", "괼", 0,
- "rLa", "굄", 0,
- "rLq", "굅", 0,
- "rLt", "굇", 0,
- "rLd", "굉", 0,
- "rys", "굔", 0,
- "ryf", "굘", 0,
- "ryq", "굡", 0,
- "ryt", "굣", 0,
- "rnr", "국", 0,
- "rns", "군", 0,
- "rne", "굳", 0,
- "rnf", "굴", 0,
- "rnG", "굵", 0,
- "rnM", "굶", 0,
- "rnF", "굻", 0,
- "rna", "굼", 0,
- "rnq", "굽", 0,
- "rnt", "굿", 0,
- "rnd", "궁", 0,
- "rnw", "궂", 0,
- "rJr", "궉", 0,
- "rJs", "권", 0,
- "rJf", "궐", 0,
- "rJT", "궜", 0,
- "rJd", "궝", 0,
- "rNt", "궷", 0,
- "rBr", "귁", 0,
- "rBs", "귄", 0,
- "rBf", "귈", 0,
- "rBa", "귐", 0,
- "rBq", "귑", 0,
- "rBt", "귓", 0,
- "rbs", "균", 0,
- "rbf", "귤", 0,
- "rmr", "극", 0,
- "rms", "근", 0,
- "rme", "귿", 0,
- "rmf", "글", 0,
- "rmG", "긁", 0,
- "rma", "금", 0,
- "rmq", "급", 0,
- "rmt", "긋", 0,
- "rmd", "긍", 0,
- "rlr", "긱", 0,
- "rls", "긴", 0,
- "rle", "긷", 0,
- "rlf", "길", 0,
- "rlM", "긺", 0,
- "rla", "김", 0,
- "rlq", "깁", 0,
- "rlt", "깃", 0,
- "rld", "깅", 0,
- "rlw", "깆", 0,
- "rlv", "깊", 0,
- "Rkr", "깍", 0,
- "RkR", "깎", 0,
- "Rks", "깐", 0,
- "Rkf", "깔", 0,
- "RkM", "깖", 0,
- "Rka", "깜", 0,
- "Rkq", "깝", 0,
- "Rkt", "깟", 0,
- "RkT", "깠", 0,
- "Rkd", "깡", 0,
- "Rkx", "깥", 0,
- "Ror", "깩", 0,
- "Ros", "깬", 0,
- "Rof", "깰", 0,
- "Roa", "깸", 0,
- "Roq", "깹", 0,
- "Rot", "깻", 0,
- "RoT", "깼", 0,
- "Rod", "깽", 0,
- "Rir", "꺅", 0,
- "Rif", "꺌", 0,
- "Rjr", "꺽", 0,
- "RjR", "꺾", 0,
- "Rjs", "껀", 0,
- "Rjf", "껄", 0,
- "Rja", "껌", 0,
- "Rjq", "껍", 0,
- "Rjt", "껏", 0,
- "RjT", "껐", 0,
- "Rjd", "껑", 0,
- "Rpr", "껙", 0,
- "Rps", "껜", 0,
- "Rpa", "껨", 0,
- "Rpt", "껫", 0,
- "Rpd", "껭", 0,
- "Rus", "껸", 0,
- "Ruf", "껼", 0,
- "Rut", "꼇", 0,
- "RuT", "꼈", 0,
- "Rux", "꼍", 0,
- "Rhr", "꼭", 0,
- "Rhs", "꼰", 0,
- "RhH", "꼲", 0,
- "Rhf", "꼴", 0,
- "Rha", "꼼", 0,
- "Rhq", "꼽", 0,
- "Rht", "꼿", 0,
- "Rhd", "꽁", 0,
- "Rhw", "꽂", 0,
- "Rhc", "꽃", 0,
- "RKr", "꽉", 0,
- "RKf", "꽐", 0,
- "RKT", "꽜", 0,
- "RKd", "꽝", 0,
- "RHr", "꽥", 0,
- "RHd", "꽹", 0,
- "RLs", "꾄", 0,
- "RLf", "꾈", 0,
- "RLa", "꾐", 0,
- "RLq", "꾑", 0,
- "RLd", "꾕", 0,
- "Rnr", "꾹", 0,
- "Rns", "꾼", 0,
- "Rnf", "꿀", 0,
- "RnF", "꿇", 0,
- "Rna", "꿈", 0,
- "Rnq", "꿉", 0,
- "Rnt", "꿋", 0,
- "Rnd", "꿍", 0,
- "Rnw", "꿎", 0,
- "RJf", "꿜", 0,
- "RJT", "꿨", 0,
- "RJd", "꿩", 0,
- "RNr", "꿱", 0,
- "RNs", "꿴", 0,
- "RNf", "꿸", 0,
- "RNa", "뀀", 0,
- "RNq", "뀁", 0,
- "RNT", "뀄", 0,
- "RBs", "뀐", 0,
- "RBf", "뀔", 0,
- "RBa", "뀜", 0,
- "RBq", "뀝", 0,
- "Rmr", "끅", 0,
- "Rms", "끈", 0,
- "RmH", "끊", 0,
- "Rmf", "끌", 0,
- "RmM", "끎", 0,
- "RmF", "끓", 0,
- "Rma", "끔", 0,
- "Rmq", "끕", 0,
- "Rmt", "끗", 0,
- "Rmd", "끙", 0,
- "Rmx", "끝", 0,
- "Rlr", "끽", 0,
- "Rls", "낀", 0,
- "Rlf", "낄", 0,
- "Rla", "낌", 0,
- "Rlq", "낍", 0,
- "Rlt", "낏", 0,
- "Rld", "낑", 0,
- "skr", "낙", 0,
- "skR", "낚", 0,
- "sks", "난", 0,
- "ske", "낟", 0,
- "skf", "날", 0,
- "skG", "낡", 0,
- "skM", "낢", 0,
- "ska", "남", 0,
- "skq", "납", 0,
- "skt", "낫", 0,
- "skT", "났", 0,
- "skd", "낭", 0,
- "skw", "낮", 0,
- "skc", "낯", 0,
- "skx", "낱", 0,
- "skg", "낳", 0,
- "sor", "낵", 0,
- "sos", "낸", 0,
- "sof", "낼", 0,
- "soa", "냄", 0,
- "soq", "냅", 0,
- "sot", "냇", 0,
- "soT", "냈", 0,
- "sod", "냉", 0,
- "sir", "냑", 0,
- "sis", "냔", 0,
- "sif", "냘", 0,
- "sia", "냠", 0,
- "sid", "냥", 0,
- "sjr", "넉", 0,
- "sjS", "넋", 0,
- "sjs", "넌", 0,
- "sjf", "널", 0,
- "sjM", "넒", 0,
- "sjA", "넓", 0,
- "sja", "넘", 0,
- "sjq", "넙", 0,
- "sjt", "넛", 0,
- "sjT", "넜", 0,
- "sjd", "넝", 0,
- "sjg", "넣", 0,
- "spr", "넥", 0,
- "sps", "넨", 0,
- "spf", "넬", 0,
- "spa", "넴", 0,
- "spq", "넵", 0,
- "spt", "넷", 0,
- "spT", "넸", 0,
- "spd", "넹", 0,
- "sur", "녁", 0,
- "sus", "년", 0,
- "suf", "녈", 0,
- "sua", "념", 0,
- "suq", "녑", 0,
- "suT", "녔", 0,
- "sud", "녕", 0,
- "suz", "녘", 0,
- "sPs", "녠", 0,
- "shr", "녹", 0,
- "shs", "논", 0,
- "shf", "놀", 0,
- "shM", "놂", 0,
- "sha", "놈", 0,
- "shq", "놉", 0,
- "sht", "놋", 0,
- "shd", "농", 0,
- "shv", "높", 0,
- "shg", "놓", 0,
- "sKs", "놘", 0,
- "sKf", "놜", 0,
- "sKT", "놨", 0,
- "sLs", "뇐", 0,
- "sLf", "뇔", 0,
- "sLa", "뇜", 0,
- "sLq", "뇝", 0,
- "sLt", "뇟", 0,
- "syr", "뇩", 0,
- "sys", "뇬", 0,
- "syf", "뇰", 0,
- "syq", "뇹", 0,
- "syt", "뇻", 0,
- "syd", "뇽", 0,
- "snr", "눅", 0,
- "sns", "눈", 0,
- "sne", "눋", 0,
- "snf", "눌", 0,
- "sna", "눔", 0,
- "snq", "눕", 0,
- "snt", "눗", 0,
- "snd", "눙", 0,
- "sJT", "눴", 0,
- "sBs", "뉜", 0,
- "sBf", "뉠", 0,
- "sBa", "뉨", 0,
- "sBq", "뉩", 0,
- "sbr", "뉵", 0,
- "sbf", "뉼", 0,
- "sba", "늄", 0,
- "sbq", "늅", 0,
- "sbd", "늉", 0,
- "smr", "늑", 0,
- "sms", "는", 0,
- "smf", "늘", 0,
- "smG", "늙", 0,
- "smM", "늚", 0,
- "sma", "늠", 0,
- "smq", "늡", 0,
- "smt", "늣", 0,
- "smd", "능", 0,
- "smw", "늦", 0,
- "smv", "늪", 0,
- "sMs", "늰", 0,
- "sMf", "늴", 0,
- "slr", "닉", 0,
- "sls", "닌", 0,
- "slf", "닐", 0,
- "slM", "닒", 0,
- "sla", "님", 0,
- "slq", "닙", 0,
- "slt", "닛", 0,
- "sld", "닝", 0,
- "slv", "닢", 0,
- "ekr", "닥", 0,
- "ekR", "닦", 0,
- "eks", "단", 0,
- "eke", "닫", 0,
- "ekf", "달", 0,
- "ekG", "닭", 0,
- "ekM", "닮", 0,
- "ekA", "닯", 0,
- "ekF", "닳", 0,
- "eka", "담", 0,
- "ekq", "답", 0,
- "ekt", "닷", 0,
- "ekT", "닸", 0,
- "ekd", "당", 0,
- "ekw", "닺", 0,
- "ekc", "닻", 0,
- "ekg", "닿", 0,
- "eor", "댁", 0,
- "eos", "댄", 0,
- "eof", "댈", 0,
- "eoa", "댐", 0,
- "eoq", "댑", 0,
- "eot", "댓", 0,
- "eoT", "댔", 0,
- "eod", "댕", 0,
- "ejr", "덕", 0,
- "ejR", "덖", 0,
- "ejs", "던", 0,
- "eje", "덛", 0,
- "ejf", "덜", 0,
- "ejM", "덞", 0,
- "ejA", "덟", 0,
- "eja", "덤", 0,
- "ejq", "덥", 0,
- "ejt", "덧", 0,
- "ejd", "덩", 0,
- "ejc", "덫", 0,
- "ejv", "덮", 0,
- "epr", "덱", 0,
- "eps", "덴", 0,
- "epf", "델", 0,
- "epa", "뎀", 0,
- "epq", "뎁", 0,
- "ept", "뎃", 0,
- "epT", "뎄", 0,
- "epd", "뎅", 0,
- "eus", "뎐", 0,
- "euf", "뎔", 0,
- "euT", "뎠", 0,
- "eud", "뎡", 0,
- "ePs", "뎬", 0,
- "ehr", "독", 0,
- "ehs", "돈", 0,
- "ehe", "돋", 0,
- "ehf", "돌", 0,
- "ehM", "돎", 0,
- "ehN", "돐", 0,
- "eha", "돔", 0,
- "ehq", "돕", 0,
- "eht", "돗", 0,
- "ehd", "동", 0,
- "ehc", "돛", 0,
- "ehx", "돝", 0,
- "eKs", "돤", 0,
- "eKf", "돨", 0,
- "eHT", "됐", 0,
- "eLs", "된", 0,
- "eLf", "될", 0,
- "eLa", "됨", 0,
- "eLq", "됩", 0,
- "eLt", "됫", 0,
- "enr", "둑", 0,
- "ens", "둔", 0,
- "enf", "둘", 0,
- "ena", "둠", 0,
- "enq", "둡", 0,
- "ent", "둣", 0,
- "end", "둥", 0,
- "eJT", "뒀", 0,
- "eNd", "뒝", 0,
- "eBs", "뒨", 0,
- "eBf", "뒬", 0,
- "eBq", "뒵", 0,
- "eBt", "뒷", 0,
- "eBd", "뒹", 0,
- "ebs", "듄", 0,
- "ebf", "듈", 0,
- "eba", "듐", 0,
- "ebd", "듕", 0,
- "emr", "득", 0,
- "ems", "든", 0,
- "eme", "듣", 0,
- "emf", "들", 0,
- "emM", "듦", 0,
- "ema", "듬", 0,
- "emq", "듭", 0,
- "emt", "듯", 0,
- "emd", "등", 0,
- "elr", "딕", 0,
- "els", "딘", 0,
- "ele", "딛", 0,
- "elf", "딜", 0,
- "ela", "딤", 0,
- "elq", "딥", 0,
- "elt", "딧", 0,
- "elT", "딨", 0,
- "eld", "딩", 0,
- "elw", "딪", 0,
- "Ekr", "딱", 0,
- "Eks", "딴", 0,
- "Ekf", "딸", 0,
- "Eka", "땀", 0,
- "Ekq", "땁", 0,
- "Ekt", "땃", 0,
- "EkT", "땄", 0,
- "Ekd", "땅", 0,
- "Ekg", "땋", 0,
- "Eor", "땍", 0,
- "Eos", "땐", 0,
- "Eof", "땔", 0,
- "Eoa", "땜", 0,
- "Eoq", "땝", 0,
- "Eot", "땟", 0,
- "EoT", "땠", 0,
- "Eod", "땡", 0,
- "Ejr", "떡", 0,
- "Ejs", "떤", 0,
- "Ejf", "떨", 0,
- "EjM", "떪", 0,
- "EjA", "떫", 0,
- "Eja", "떰", 0,
- "Ejq", "떱", 0,
- "Ejt", "떳", 0,
- "EjT", "떴", 0,
- "Ejd", "떵", 0,
- "Ejg", "떻", 0,
- "Epr", "떽", 0,
- "Eps", "뗀", 0,
- "Epf", "뗄", 0,
- "Epa", "뗌", 0,
- "Epq", "뗍", 0,
- "Ept", "뗏", 0,
- "EpT", "뗐", 0,
- "Epd", "뗑", 0,
- "EuT", "뗬", 0,
- "Ehr", "똑", 0,
- "Ehs", "똔", 0,
- "Ehf", "똘", 0,
- "Ehd", "똥", 0,
- "EKf", "똴", 0,
- "ELs", "뙨", 0,
- "Enr", "뚝", 0,
- "Ens", "뚠", 0,
- "Enf", "뚤", 0,
- "EnF", "뚫", 0,
- "Ena", "뚬", 0,
- "End", "뚱", 0,
- "EBs", "뛴", 0,
- "EBf", "뛸", 0,
- "EBa", "뜀", 0,
- "EBq", "뜁", 0,
- "EBd", "뜅", 0,
- "Emr", "뜩", 0,
- "Ems", "뜬", 0,
- "Eme", "뜯", 0,
- "Emf", "뜰", 0,
- "Ema", "뜸", 0,
- "Emq", "뜹", 0,
- "Emt", "뜻", 0,
- "EMs", "띈", 0,
- "EMf", "띌", 0,
- "EMa", "띔", 0,
- "EMq", "띕", 0,
- "Els", "띤", 0,
- "Elf", "띨", 0,
- "Ela", "띰", 0,
- "Elq", "띱", 0,
- "Elt", "띳", 0,
- "Eld", "띵", 0,
- "fkr", "락", 0,
- "fks", "란", 0,
- "fkf", "랄", 0,
- "fka", "람", 0,
- "fkq", "랍", 0,
- "fkt", "랏", 0,
- "fkT", "랐", 0,
- "fkd", "랑", 0,
- "fkw", "랒", 0,
- "fkv", "랖", 0,
- "fkg", "랗", 0,
- "for", "랙", 0,
- "fos", "랜", 0,
- "fof", "랠", 0,
- "foa", "램", 0,
- "foq", "랩", 0,
- "fot", "랫", 0,
- "foT", "랬", 0,
- "fod", "랭", 0,
- "fir", "략", 0,
- "fis", "랸", 0,
- "fit", "럇", 0,
- "fid", "량", 0,
- "fjr", "럭", 0,
- "fjs", "런", 0,
- "fjf", "럴", 0,
- "fja", "럼", 0,
- "fjq", "럽", 0,
- "fjt", "럿", 0,
- "fjT", "렀", 0,
- "fjd", "렁", 0,
- "fjg", "렇", 0,
- "fpr", "렉", 0,
- "fps", "렌", 0,
- "fpf", "렐", 0,
- "fpa", "렘", 0,
- "fpq", "렙", 0,
- "fpt", "렛", 0,
- "fpd", "렝", 0,
- "fur", "력", 0,
- "fus", "련", 0,
- "fuf", "렬", 0,
- "fua", "렴", 0,
- "fuq", "렵", 0,
- "fut", "렷", 0,
- "fuT", "렸", 0,
- "fud", "령", 0,
- "fPs", "롄", 0,
- "fPq", "롑", 0,
- "fPt", "롓", 0,
- "fhr", "록", 0,
- "fhs", "론", 0,
- "fhf", "롤", 0,
- "fha", "롬", 0,
- "fhq", "롭", 0,
- "fht", "롯", 0,
- "fhd", "롱", 0,
- "fKs", "롼", 0,
- "fKd", "뢍", 0,
- "fHT", "뢨", 0,
- "fLs", "뢴", 0,
- "fLf", "뢸", 0,
- "fLa", "룀", 0,
- "fLq", "룁", 0,
- "fLt", "룃", 0,
- "fLd", "룅", 0,
- "fys", "룐", 0,
- "fyf", "룔", 0,
- "fyq", "룝", 0,
- "fyt", "룟", 0,
- "fyd", "룡", 0,
- "fnr", "룩", 0,
- "fns", "룬", 0,
- "fnf", "룰", 0,
- "fna", "룸", 0,
- "fnq", "룹", 0,
- "fnt", "룻", 0,
- "fnd", "룽", 0,
- "fJT", "뤘", 0,
- "fBr", "뤽", 0,
- "fBs", "륀", 0,
- "fBf", "륄", 0,
- "fBa", "륌", 0,
- "fBt", "륏", 0,
- "fBd", "륑", 0,
- "fbr", "륙", 0,
- "fbs", "륜", 0,
- "fbf", "률", 0,
- "fba", "륨", 0,
- "fbq", "륩", 0,
- "fbt", "륫", 0,
- "fbd", "륭", 0,
- "fmr", "륵", 0,
- "fms", "른", 0,
- "fmf", "를", 0,
- "fma", "름", 0,
- "fmq", "릅", 0,
- "fmt", "릇", 0,
- "fmd", "릉", 0,
- "fmw", "릊", 0,
- "fmx", "릍", 0,
- "fmv", "릎", 0,
- "flr", "릭", 0,
- "fls", "린", 0,
- "flf", "릴", 0,
- "fla", "림", 0,
- "flq", "립", 0,
- "flt", "릿", 0,
- "fld", "링", 0,
- "akr", "막", 0,
- "aks", "만", 0,
- "akH", "많", 0,
- "ake", "맏", 0,
- "akf", "말", 0,
- "akG", "맑", 0,
- "akM", "맒", 0,
- "aka", "맘", 0,
- "akq", "맙", 0,
- "akt", "맛", 0,
- "akd", "망", 0,
- "akw", "맞", 0,
- "akx", "맡", 0,
- "akg", "맣", 0,
- "aor", "맥", 0,
- "aos", "맨", 0,
- "aof", "맬", 0,
- "aoa", "맴", 0,
- "aoq", "맵", 0,
- "aot", "맷", 0,
- "aoT", "맸", 0,
- "aod", "맹", 0,
- "aow", "맺", 0,
- "air", "먁", 0,
- "aif", "먈", 0,
- "aid", "먕", 0,
- "ajr", "먹", 0,
- "ajs", "먼", 0,
- "ajf", "멀", 0,
- "ajM", "멂", 0,
- "aja", "멈", 0,
- "ajq", "멉", 0,
- "ajt", "멋", 0,
- "ajd", "멍", 0,
- "ajw", "멎", 0,
- "ajg", "멓", 0,
- "apr", "멕", 0,
- "aps", "멘", 0,
- "apf", "멜", 0,
- "apa", "멤", 0,
- "apq", "멥", 0,
- "apt", "멧", 0,
- "apT", "멨", 0,
- "apd", "멩", 0,
- "aur", "멱", 0,
- "aus", "면", 0,
- "auf", "멸", 0,
- "aut", "몃", 0,
- "auT", "몄", 0,
- "aud", "명", 0,
- "auc", "몇", 0,
- "ahr", "목", 0,
- "ahS", "몫", 0,
- "ahs", "몬", 0,
- "ahf", "몰", 0,
- "ahM", "몲", 0,
- "aha", "몸", 0,
- "ahq", "몹", 0,
- "aht", "못", 0,
- "ahd", "몽", 0,
- "aKs", "뫈", 0,
- "aKT", "뫘", 0,
- "aKd", "뫙", 0,
- "aLs", "묀", 0,
- "aLf", "묄", 0,
- "aLq", "묍", 0,
- "aLt", "묏", 0,
- "aLd", "묑", 0,
- "ays", "묜", 0,
- "ayf", "묠", 0,
- "ayq", "묩", 0,
- "ayt", "묫", 0,
- "anr", "묵", 0,
- "anR", "묶", 0,
- "ans", "문", 0,
- "ane", "묻", 0,
- "anf", "물", 0,
- "anG", "묽", 0,
- "anM", "묾", 0,
- "ana", "뭄", 0,
- "anq", "뭅", 0,
- "ant", "뭇", 0,
- "and", "뭉", 0,
- "anx", "뭍", 0,
- "ang", "뭏", 0,
- "aJs", "뭔", 0,
- "aJf", "뭘", 0,
- "aJq", "뭡", 0,
- "aJt", "뭣", 0,
- "aBs", "뮌", 0,
- "aBf", "뮐", 0,
- "abs", "뮨", 0,
- "abf", "뮬", 0,
- "aba", "뮴", 0,
- "abt", "뮷", 0,
- "ams", "믄", 0,
- "amf", "믈", 0,
- "ama", "믐", 0,
- "amt", "믓", 0,
- "alr", "믹", 0,
- "als", "민", 0,
- "ale", "믿", 0,
- "alf", "밀", 0,
- "alM", "밂", 0,
- "ala", "밈", 0,
- "alq", "밉", 0,
- "alt", "밋", 0,
- "alT", "밌", 0,
- "ald", "밍", 0,
- "alc", "및", 0,
- "alx", "밑", 0,
- "qkr", "박", 0,
- "qkR", "밖", 0,
- "qkS", "밗", 0,
- "qks", "반", 0,
- "qke", "받", 0,
- "qkf", "발", 0,
- "qkG", "밝", 0,
- "qkM", "밞", 0,
- "qkA", "밟", 0,
- "qka", "밤", 0,
- "qkq", "밥", 0,
- "qkt", "밧", 0,
- "qkd", "방", 0,
- "qkx", "밭", 0,
- "qor", "백", 0,
- "qos", "밴", 0,
- "qof", "밸", 0,
- "qoa", "뱀", 0,
- "qoq", "뱁", 0,
- "qot", "뱃", 0,
- "qoT", "뱄", 0,
- "qod", "뱅", 0,
- "qox", "뱉", 0,
- "qir", "뱍", 0,
- "qis", "뱐", 0,
- "qiq", "뱝", 0,
- "qjr", "벅", 0,
- "qjs", "번", 0,
- "qje", "벋", 0,
- "qjf", "벌", 0,
- "qjM", "벎", 0,
- "qja", "범", 0,
- "qjq", "법", 0,
- "qjt", "벗", 0,
- "qjd", "벙", 0,
- "qjw", "벚", 0,
- "qpr", "벡", 0,
- "qps", "벤", 0,
- "qpe", "벧", 0,
- "qpf", "벨", 0,
- "qpa", "벰", 0,
- "qpq", "벱", 0,
- "qpt", "벳", 0,
- "qpT", "벴", 0,
- "qpd", "벵", 0,
- "qur", "벽", 0,
- "qus", "변", 0,
- "quf", "별", 0,
- "quq", "볍", 0,
- "qut", "볏", 0,
- "quT", "볐", 0,
- "qud", "병", 0,
- "qux", "볕", 0,
- "qPs", "볜", 0,
- "qhr", "복", 0,
- "qhR", "볶", 0,
- "qhs", "본", 0,
- "qhf", "볼", 0,
- "qha", "봄", 0,
- "qhq", "봅", 0,
- "qht", "봇", 0,
- "qhd", "봉", 0,
- "qKs", "봔", 0,
- "qKT", "봤", 0,
- "qHT", "뵀", 0,
- "qLr", "뵉", 0,
- "qLs", "뵌", 0,
- "qLf", "뵐", 0,
- "qLa", "뵘", 0,
- "qLq", "뵙", 0,
- "qys", "뵨", 0,
- "qnr", "북", 0,
- "qns", "분", 0,
- "qne", "붇", 0,
- "qnf", "불", 0,
- "qnG", "붉", 0,
- "qnM", "붊", 0,
- "qna", "붐", 0,
- "qnq", "붑", 0,
- "qnt", "붓", 0,
- "qnd", "붕", 0,
- "qnx", "붙", 0,
- "qnv", "붚", 0,
- "qJf", "붤", 0,
- "qJT", "붰", 0,
- "qBr", "뷕", 0,
- "qBs", "뷘", 0,
- "qBf", "뷜", 0,
- "qBd", "뷩", 0,
- "qbs", "뷴", 0,
- "qbf", "뷸", 0,
- "qba", "븀", 0,
- "qbt", "븃", 0,
- "qbd", "븅", 0,
- "qmr", "븍", 0,
- "qms", "븐", 0,
- "qmf", "블", 0,
- "qma", "븜", 0,
- "qmq", "븝", 0,
- "qmt", "븟", 0,
- "qlr", "빅", 0,
- "qls", "빈", 0,
- "qlf", "빌", 0,
- "qlM", "빎", 0,
- "qla", "빔", 0,
- "qlq", "빕", 0,
- "qlt", "빗", 0,
- "qld", "빙", 0,
- "qlw", "빚", 0,
- "qlc", "빛", 0,
- "Qkr", "빡", 0,
- "Qks", "빤", 0,
- "Qkf", "빨", 0,
- "QkM", "빪", 0,
- "Qka", "빰", 0,
- "Qkq", "빱", 0,
- "Qkt", "빳", 0,
- "QkT", "빴", 0,
- "Qkd", "빵", 0,
- "Qkg", "빻", 0,
- "Qor", "빽", 0,
- "Qos", "뺀", 0,
- "Qof", "뺄", 0,
- "Qoa", "뺌", 0,
- "Qoq", "뺍", 0,
- "Qot", "뺏", 0,
- "QoT", "뺐", 0,
- "Qod", "뺑", 0,
- "Qir", "뺙", 0,
- "Qia", "뺨", 0,
- "Qjr", "뻑", 0,
- "Qjs", "뻔", 0,
- "Qje", "뻗", 0,
- "Qjf", "뻘", 0,
- "Qja", "뻠", 0,
- "Qjt", "뻣", 0,
- "QjT", "뻤", 0,
- "Qjd", "뻥", 0,
- "Qpd", "뼁", 0,
- "Qur", "뼉", 0,
- "Qua", "뼘", 0,
- "Quq", "뼙", 0,
- "Qut", "뼛", 0,
- "QuT", "뼜", 0,
- "Qud", "뼝", 0,
- "Qhr", "뽁", 0,
- "Qhs", "뽄", 0,
- "Qhf", "뽈", 0,
- "Qha", "뽐", 0,
- "Qhq", "뽑", 0,
- "Qhd", "뽕", 0,
- "Qyd", "뿅", 0,
- "Qnr", "뿍", 0,
- "Qns", "뿐", 0,
- "Qnf", "뿔", 0,
- "Qna", "뿜", 0,
- "Qnt", "뿟", 0,
- "Qnd", "뿡", 0,
- "Qbd", "쁑", 0,
- "Qms", "쁜", 0,
- "Qmf", "쁠", 0,
- "Qma", "쁨", 0,
- "Qmq", "쁩", 0,
- "Qlr", "삑", 0,
- "Qls", "삔", 0,
- "Qlf", "삘", 0,
- "Qla", "삠", 0,
- "Qlq", "삡", 0,
- "Qlt", "삣", 0,
- "Qld", "삥", 0,
- "tkr", "삭", 0,
- "tkS", "삯", 0,
- "tks", "산", 0,
- "tke", "삳", 0,
- "tkf", "살", 0,
- "tkG", "삵", 0,
- "tkM", "삶", 0,
- "tka", "삼", 0,
- "tkq", "삽", 0,
- "tkt", "삿", 0,
- "tkT", "샀", 0,
- "tkd", "상", 0,
- "tkx", "샅", 0,
- "tor", "색", 0,
- "tos", "샌", 0,
- "tof", "샐", 0,
- "toa", "샘", 0,
- "toq", "샙", 0,
- "tot", "샛", 0,
- "toT", "샜", 0,
- "tod", "생", 0,
- "tir", "샥", 0,
- "tis", "샨", 0,
- "tif", "샬", 0,
- "tia", "샴", 0,
- "tiq", "샵", 0,
- "tit", "샷", 0,
- "tid", "샹", 0,
- "tOs", "섄", 0,
- "tOf", "섈", 0,
- "tOa", "섐", 0,
- "tOd", "섕", 0,
- "tjr", "석", 0,
- "tjR", "섞", 0,
- "tjS", "섟", 0,
- "tjs", "선", 0,
- "tje", "섣", 0,
- "tjf", "설", 0,
- "tjM", "섦", 0,
- "tjA", "섧", 0,
- "tja", "섬", 0,
- "tjq", "섭", 0,
- "tjt", "섯", 0,
- "tjT", "섰", 0,
- "tjd", "성", 0,
- "tjv", "섶", 0,
- "tpr", "섹", 0,
- "tps", "센", 0,
- "tpf", "셀", 0,
- "tpa", "셈", 0,
- "tpq", "셉", 0,
- "tpt", "셋", 0,
- "tpT", "셌", 0,
- "tpd", "셍", 0,
- "tur", "셕", 0,
- "tus", "션", 0,
- "tuf", "셜", 0,
- "tua", "셤", 0,
- "tuq", "셥", 0,
- "tut", "셧", 0,
- "tuT", "셨", 0,
- "tud", "셩", 0,
- "tPs", "셴", 0,
- "tPf", "셸", 0,
- "tPd", "솅", 0,
- "thr", "속", 0,
- "thR", "솎", 0,
- "ths", "손", 0,
- "thf", "솔", 0,
- "thM", "솖", 0,
- "tha", "솜", 0,
- "thq", "솝", 0,
- "tht", "솟", 0,
- "thd", "송", 0,
- "thx", "솥", 0,
- "tKr", "솩", 0,
- "tKs", "솬", 0,
- "tKf", "솰", 0,
- "tKd", "솽", 0,
- "tHs", "쇈", 0,
- "tHf", "쇌", 0,
- "tHa", "쇔", 0,
- "tHt", "쇗", 0,
- "tHT", "쇘", 0,
- "tLs", "쇤", 0,
- "tLf", "쇨", 0,
- "tLa", "쇰", 0,
- "tLq", "쇱", 0,
- "tLt", "쇳", 0,
- "tyr", "쇽", 0,
- "tys", "숀", 0,
- "tyf", "숄", 0,
- "tya", "숌", 0,
- "tyq", "숍", 0,
- "tyt", "숏", 0,
- "tyd", "숑", 0,
- "tnr", "숙", 0,
- "tns", "순", 0,
- "tne", "숟", 0,
- "tnf", "술", 0,
- "tna", "숨", 0,
- "tnq", "숩", 0,
- "tnt", "숫", 0,
- "tnd", "숭", 0,
- "tnc", "숯", 0,
- "tnx", "숱", 0,
- "tnv", "숲", 0,
- "tJT", "쉈", 0,
- "tNr", "쉑", 0,
- "tNs", "쉔", 0,
- "tNf", "쉘", 0,
- "tNa", "쉠", 0,
- "tNd", "쉥", 0,
- "tBr", "쉭", 0,
- "tBs", "쉰", 0,
- "tBf", "쉴", 0,
- "tBa", "쉼", 0,
- "tBq", "쉽", 0,
- "tBt", "쉿", 0,
- "tBd", "슁", 0,
- "tbr", "슉", 0,
- "tbf", "슐", 0,
- "tba", "슘", 0,
- "tbt", "슛", 0,
- "tbd", "슝", 0,
- "tmr", "슥", 0,
- "tms", "슨", 0,
- "tmf", "슬", 0,
- "tmG", "슭", 0,
- "tma", "슴", 0,
- "tmq", "습", 0,
- "tmt", "슷", 0,
- "tmd", "승", 0,
- "tlr", "식", 0,
- "tls", "신", 0,
- "tle", "싣", 0,
- "tlf", "실", 0,
- "tlF", "싫", 0,
- "tla", "심", 0,
- "tlq", "십", 0,
- "tlt", "싯", 0,
- "tld", "싱", 0,
- "tlv", "싶", 0,
- "Tkr", "싹", 0,
- "TkS", "싻", 0,
- "Tks", "싼", 0,
- "Tkf", "쌀", 0,
- "Tka", "쌈", 0,
- "Tkq", "쌉", 0,
- "TkT", "쌌", 0,
- "Tkd", "쌍", 0,
- "Tkg", "쌓", 0,
- "Tor", "쌕", 0,
- "Tos", "쌘", 0,
- "Tof", "쌜", 0,
- "Toa", "쌤", 0,
- "Toq", "쌥", 0,
- "ToT", "쌨", 0,
- "Tod", "쌩", 0,
- "Tid", "썅", 0,
- "Tjr", "썩", 0,
- "Tjs", "썬", 0,
- "Tjf", "썰", 0,
- "TjM", "썲", 0,
- "Tja", "썸", 0,
- "Tjq", "썹", 0,
- "TjT", "썼", 0,
- "Tjd", "썽", 0,
- "Tps", "쎈", 0,
- "Tpf", "쎌", 0,
- "TPs", "쏀", 0,
- "Thr", "쏙", 0,
- "Ths", "쏜", 0,
- "The", "쏟", 0,
- "Thf", "쏠", 0,
- "ThM", "쏢", 0,
- "Tha", "쏨", 0,
- "Thq", "쏩", 0,
- "Thd", "쏭", 0,
- "TKr", "쏵", 0,
- "TKs", "쏸", 0,
- "TKT", "쐈", 0,
- "THT", "쐤", 0,
- "TLs", "쐰", 0,
- "TLf", "쐴", 0,
- "TLa", "쐼", 0,
- "TLq", "쐽", 0,
- "Tnr", "쑥", 0,
- "Tns", "쑨", 0,
- "Tnf", "쑬", 0,
- "Tna", "쑴", 0,
- "Tnq", "쑵", 0,
- "Tnd", "쑹", 0,
- "TJT", "쒔", 0,
- "TBs", "쒼", 0,
- "Tbd", "쓩", 0,
- "Tmr", "쓱", 0,
- "Tms", "쓴", 0,
- "Tmf", "쓸", 0,
- "TmM", "쓺", 0,
- "TmF", "쓿", 0,
- "Tma", "씀", 0,
- "Tmq", "씁", 0,
- "TMs", "씐", 0,
- "TMf", "씔", 0,
- "TMa", "씜", 0,
- "Tlr", "씩", 0,
- "Tls", "씬", 0,
- "Tlf", "씰", 0,
- "Tla", "씸", 0,
- "Tlq", "씹", 0,
- "Tlt", "씻", 0,
- "Tld", "씽", 0,
- "dkr", "악", 0,
- "dks", "안", 0,
- "dkJ", "앉", 0,
- "dkH", "않", 0,
- "dkf", "알", 0,
- "dkG", "앍", 0,
- "dkM", "앎", 0,
- "dkF", "앓", 0,
- "dka", "암", 0,
- "dkq", "압", 0,
- "dkt", "앗", 0,
- "dkT", "았", 0,
- "dkd", "앙", 0,
- "dkx", "앝", 0,
- "dkv", "앞", 0,
- "dor", "액", 0,
- "dos", "앤", 0,
- "dof", "앨", 0,
- "doa", "앰", 0,
- "doq", "앱", 0,
- "dot", "앳", 0,
- "doT", "앴", 0,
- "dod", "앵", 0,
- "dir", "약", 0,
- "dis", "얀", 0,
- "dif", "얄", 0,
- "diA", "얇", 0,
- "dia", "얌", 0,
- "diq", "얍", 0,
- "dit", "얏", 0,
- "did", "양", 0,
- "dix", "얕", 0,
- "dig", "얗", 0,
- "dOs", "얜", 0,
- "dOf", "얠", 0,
- "dOq", "얩", 0,
- "djr", "억", 0,
- "djs", "언", 0,
- "djJ", "얹", 0,
- "dje", "얻", 0,
- "djf", "얼", 0,
- "djG", "얽", 0,
- "djM", "얾", 0,
- "dja", "엄", 0,
- "djq", "업", 0,
- "djC", "없", 0,
- "djt", "엇", 0,
- "djT", "었", 0,
- "djd", "엉", 0,
- "djw", "엊", 0,
- "djz", "엌", 0,
- "djv", "엎", 0,
- "dpr", "엑", 0,
- "dps", "엔", 0,
- "dpf", "엘", 0,
- "dpa", "엠", 0,
- "dpq", "엡", 0,
- "dpt", "엣", 0,
- "dpd", "엥", 0,
- "dur", "역", 0,
- "duR", "엮", 0,
- "dus", "연", 0,
- "duf", "열", 0,
- "duM", "엶", 0,
- "duA", "엷", 0,
- "dua", "염", 0,
- "duq", "엽", 0,
- "duC", "엾", 0,
- "dut", "엿", 0,
- "duT", "였", 0,
- "dud", "영", 0,
- "dux", "옅", 0,
- "duv", "옆", 0,
- "dug", "옇", 0,
- "dPs", "옌", 0,
- "dPf", "옐", 0,
- "dPa", "옘", 0,
- "dPq", "옙", 0,
- "dPt", "옛", 0,
- "dPT", "옜", 0,
- "dhr", "옥", 0,
- "dhs", "온", 0,
- "dhf", "올", 0,
- "dhG", "옭", 0,
- "dhM", "옮", 0,
- "dhN", "옰", 0,
- "dhF", "옳", 0,
- "dha", "옴", 0,
- "dhq", "옵", 0,
- "dht", "옷", 0,
- "dhd", "옹", 0,
- "dhc", "옻", 0,
- "dKr", "왁", 0,
- "dKs", "완", 0,
- "dKf", "왈", 0,
- "dKa", "왐", 0,
- "dKq", "왑", 0,
- "dKt", "왓", 0,
- "dKT", "왔", 0,
- "dKd", "왕", 0,
- "dHr", "왝", 0,
- "dHs", "왠", 0,
- "dHa", "왬", 0,
- "dHt", "왯", 0,
- "dHd", "왱", 0,
- "dLr", "왹", 0,
- "dLs", "왼", 0,
- "dLf", "욀", 0,
- "dLa", "욈", 0,
- "dLq", "욉", 0,
- "dLt", "욋", 0,
- "dLd", "욍", 0,
- "dyr", "욕", 0,
- "dys", "욘", 0,
- "dyf", "욜", 0,
- "dya", "욤", 0,
- "dyq", "욥", 0,
- "dyt", "욧", 0,
- "dyd", "용", 0,
- "dnr", "욱", 0,
- "dns", "운", 0,
- "dnf", "울", 0,
- "dnG", "욹", 0,
- "dnM", "욺", 0,
- "dna", "움", 0,
- "dnq", "웁", 0,
- "dnt", "웃", 0,
- "dnd", "웅", 0,
- "dJr", "웍", 0,
- "dJs", "원", 0,
- "dJf", "월", 0,
- "dJa", "웜", 0,
- "dJq", "웝", 0,
- "dJT", "웠", 0,
- "dJd", "웡", 0,
- "dNr", "웩", 0,
- "dNs", "웬", 0,
- "dNf", "웰", 0,
- "dNa", "웸", 0,
- "dNq", "웹", 0,
- "dNd", "웽", 0,
- "dBr", "윅", 0,
- "dBs", "윈", 0,
- "dBf", "윌", 0,
- "dBa", "윔", 0,
- "dBq", "윕", 0,
- "dBt", "윗", 0,
- "dBd", "윙", 0,
- "dbr", "육", 0,
- "dbs", "윤", 0,
- "dbf", "율", 0,
- "dba", "윰", 0,
- "dbq", "윱", 0,
- "dbt", "윳", 0,
- "dbd", "융", 0,
- "dbc", "윷", 0,
- "dmr", "윽", 0,
- "dms", "은", 0,
- "dmf", "을", 0,
- "dmV", "읊", 0,
- "dma", "음", 0,
- "dmq", "읍", 0,
- "dmt", "읏", 0,
- "dmd", "응", 0,
- "dmw", "읒", 0,
- "dmc", "읓", 0,
- "dmz", "읔", 0,
- "dmx", "읕", 0,
- "dmv", "읖", 0,
- "dmg", "읗", 0,
- "dMs", "읜", 0,
- "dMf", "읠", 0,
- "dMa", "읨", 0,
- "dMt", "읫", 0,
- "dlr", "익", 0,
- "dls", "인", 0,
- "dlf", "일", 0,
- "dlG", "읽", 0,
- "dlM", "읾", 0,
- "dlF", "잃", 0,
- "dla", "임", 0,
- "dlq", "입", 0,
- "dlt", "잇", 0,
- "dlT", "있", 0,
- "dld", "잉", 0,
- "dlw", "잊", 0,
- "dlv", "잎", 0,
- "wkr", "작", 0,
- "wks", "잔", 0,
- "wkH", "잖", 0,
- "wke", "잗", 0,
- "wkf", "잘", 0,
- "wkM", "잚", 0,
- "wka", "잠", 0,
- "wkq", "잡", 0,
- "wkt", "잣", 0,
- "wkT", "잤", 0,
- "wkd", "장", 0,
- "wkw", "잦", 0,
- "wor", "잭", 0,
- "wos", "잰", 0,
- "wof", "잴", 0,
- "woa", "잼", 0,
- "woq", "잽", 0,
- "wot", "잿", 0,
- "woT", "쟀", 0,
- "wod", "쟁", 0,
- "wir", "쟉", 0,
- "wis", "쟌", 0,
- "wiH", "쟎", 0,
- "wif", "쟐", 0,
- "wia", "쟘", 0,
- "wid", "쟝", 0,
- "wOs", "쟨", 0,
- "wOf", "쟬", 0,
- "wjr", "적", 0,
- "wjs", "전", 0,
- "wjf", "절", 0,
- "wjM", "젊", 0,
- "wja", "점", 0,
- "wjq", "접", 0,
- "wjt", "젓", 0,
- "wjd", "정", 0,
- "wjw", "젖", 0,
- "wpr", "젝", 0,
- "wps", "젠", 0,
- "wpf", "젤", 0,
- "wpa", "젬", 0,
- "wpq", "젭", 0,
- "wpt", "젯", 0,
- "wpd", "젱", 0,
- "wus", "젼", 0,
- "wuf", "졀", 0,
- "wua", "졈", 0,
- "wuq", "졉", 0,
- "wuT", "졌", 0,
- "wud", "졍", 0,
- "whr", "족", 0,
- "whs", "존", 0,
- "whf", "졸", 0,
- "whM", "졺", 0,
- "wha", "좀", 0,
- "whq", "좁", 0,
- "wht", "좃", 0,
- "whd", "종", 0,
- "whw", "좆", 0,
- "whc", "좇", 0,
- "whg", "좋", 0,
- "wKr", "좍", 0,
- "wKf", "좔", 0,
- "wKq", "좝", 0,
- "wKt", "좟", 0,
- "wKd", "좡", 0,
- "wHT", "좼", 0,
- "wHd", "좽", 0,
- "wLs", "죈", 0,
- "wLf", "죌", 0,
- "wLa", "죔", 0,
- "wLq", "죕", 0,
- "wLt", "죗", 0,
- "wLd", "죙", 0,
- "wyr", "죡", 0,
- "wys", "죤", 0,
- "wyd", "죵", 0,
- "wnr", "죽", 0,
- "wns", "준", 0,
- "wnf", "줄", 0,
- "wnG", "줅", 0,
- "wnM", "줆", 0,
- "wna", "줌", 0,
- "wnq", "줍", 0,
- "wnt", "줏", 0,
- "wnd", "중", 0,
- "wJT", "줬", 0,
- "wBr", "쥑", 0,
- "wBs", "쥔", 0,
- "wBf", "쥘", 0,
- "wBa", "쥠", 0,
- "wBq", "쥡", 0,
- "wBt", "쥣", 0,
- "wbs", "쥰", 0,
- "wbf", "쥴", 0,
- "wba", "쥼", 0,
- "wmr", "즉", 0,
- "wms", "즌", 0,
- "wmf", "즐", 0,
- "wma", "즘", 0,
- "wmq", "즙", 0,
- "wmt", "즛", 0,
- "wmd", "증", 0,
- "wlr", "직", 0,
- "wls", "진", 0,
- "wle", "짇", 0,
- "wlf", "질", 0,
- "wlM", "짊", 0,
- "wla", "짐", 0,
- "wlq", "집", 0,
- "wlt", "짓", 0,
- "wld", "징", 0,
- "wlw", "짖", 0,
- "wlx", "짙", 0,
- "wlv", "짚", 0,
- "Wkr", "짝", 0,
- "Wks", "짠", 0,
- "WkH", "짢", 0,
- "Wkf", "짤", 0,
- "WkA", "짧", 0,
- "Wka", "짬", 0,
- "Wkq", "짭", 0,
- "Wkt", "짯", 0,
- "WkT", "짰", 0,
- "Wkd", "짱", 0,
- "Wor", "짹", 0,
- "Wos", "짼", 0,
- "Wof", "쨀", 0,
- "Woa", "쨈", 0,
- "Woq", "쨉", 0,
- "Wot", "쨋", 0,
- "WoT", "쨌", 0,
- "Wod", "쨍", 0,
- "Wis", "쨘", 0,
- "Wid", "쨩", 0,
- "Wjr", "쩍", 0,
- "Wjs", "쩐", 0,
- "Wjf", "쩔", 0,
- "Wja", "쩜", 0,
- "Wjq", "쩝", 0,
- "Wjt", "쩟", 0,
- "WjT", "쩠", 0,
- "Wjd", "쩡", 0,
- "Wpd", "쩽", 0,
- "WuT", "쪘", 0,
- "Whr", "쪽", 0,
- "Whs", "쫀", 0,
- "Whf", "쫄", 0,
- "Wha", "쫌", 0,
- "Whq", "쫍", 0,
- "Wht", "쫏", 0,
- "Whd", "쫑", 0,
- "Whc", "쫓", 0,
- "WKr", "쫙", 0,
- "WKf", "쫠", 0,
- "WKT", "쫬", 0,
- "WHT", "쬈", 0,
- "WLs", "쬔", 0,
- "WLf", "쬘", 0,
- "WLa", "쬠", 0,
- "WLq", "쬡", 0,
- "Wyd", "쭁", 0,
- "Wnr", "쭉", 0,
- "Wns", "쭌", 0,
- "Wnf", "쭐", 0,
- "Wna", "쭘", 0,
- "Wnq", "쭙", 0,
- "Wnd", "쭝", 0,
- "WJT", "쭸", 0,
- "WJd", "쭹", 0,
- "Wma", "쯤", 0,
- "Wmt", "쯧", 0,
- "Wmd", "쯩", 0,
- "Wlr", "찍", 0,
- "Wls", "찐", 0,
- "Wlf", "찔", 0,
- "Wla", "찜", 0,
- "Wlq", "찝", 0,
- "Wld", "찡", 0,
- "Wlw", "찢", 0,
- "Wlg", "찧", 0,
- "ckr", "착", 0,
- "cks", "찬", 0,
- "ckH", "찮", 0,
- "ckf", "찰", 0,
- "cka", "참", 0,
- "ckq", "찹", 0,
- "ckt", "찻", 0,
- "ckT", "찼", 0,
- "ckd", "창", 0,
- "ckw", "찾", 0,
- "cor", "책", 0,
- "cos", "챈", 0,
- "cof", "챌", 0,
- "coa", "챔", 0,
- "coq", "챕", 0,
- "cot", "챗", 0,
- "coT", "챘", 0,
- "cod", "챙", 0,
- "cis", "챤", 0,
- "ciH", "챦", 0,
- "cif", "챨", 0,
- "cia", "챰", 0,
- "cid", "챵", 0,
- "cjr", "척", 0,
- "cjs", "천", 0,
- "cjf", "철", 0,
- "cja", "첨", 0,
- "cjq", "첩", 0,
- "cjt", "첫", 0,
- "cjT", "첬", 0,
- "cjd", "청", 0,
- "cpr", "첵", 0,
- "cps", "첸", 0,
- "cpf", "첼", 0,
- "cpa", "쳄", 0,
- "cpq", "쳅", 0,
- "cpt", "쳇", 0,
- "cpd", "쳉", 0,
- "cus", "쳔", 0,
- "cuT", "쳤", 0,
- "cPs", "쳰", 0,
- "cPd", "촁", 0,
- "chr", "촉", 0,
- "chs", "촌", 0,
- "chf", "촐", 0,
- "cha", "촘", 0,
- "chq", "촙", 0,
- "cht", "촛", 0,
- "chd", "총", 0,
- "cKs", "촨", 0,
- "cKf", "촬", 0,
- "cKd", "촹", 0,
- "cLs", "쵠", 0,
- "cLf", "쵤", 0,
- "cLa", "쵬", 0,
- "cLq", "쵭", 0,
- "cLt", "쵯", 0,
- "cLd", "쵱", 0,
- "cya", "춈", 0,
- "cnr", "축", 0,
- "cns", "춘", 0,
- "cnf", "출", 0,
- "cna", "춤", 0,
- "cnq", "춥", 0,
- "cnt", "춧", 0,
- "cnd", "충", 0,
- "cJT", "췄", 0,
- "cNs", "췐", 0,
- "cBs", "췬", 0,
- "cBf", "췰", 0,
- "cBa", "췸", 0,
- "cBq", "췹", 0,
- "cBt", "췻", 0,
- "cBd", "췽", 0,
- "cbs", "츈", 0,
- "cbf", "츌", 0,
- "cba", "츔", 0,
- "cbd", "츙", 0,
- "cmr", "측", 0,
- "cms", "츤", 0,
- "cmf", "츨", 0,
- "cma", "츰", 0,
- "cmq", "츱", 0,
- "cmt", "츳", 0,
- "cmd", "층", 0,
- "clr", "칙", 0,
- "cls", "친", 0,
- "cle", "칟", 0,
- "clf", "칠", 0,
- "clG", "칡", 0,
- "cla", "침", 0,
- "clq", "칩", 0,
- "clt", "칫", 0,
- "cld", "칭", 0,
- "zkr", "칵", 0,
- "zks", "칸", 0,
- "zkf", "칼", 0,
- "zka", "캄", 0,
- "zkq", "캅", 0,
- "zkt", "캇", 0,
- "zkd", "캉", 0,
- "zor", "캑", 0,
- "zos", "캔", 0,
- "zof", "캘", 0,
- "zoa", "캠", 0,
- "zoq", "캡", 0,
- "zot", "캣", 0,
- "zoT", "캤", 0,
- "zod", "캥", 0,
- "zir", "캭", 0,
- "zid", "컁", 0,
- "zjr", "컥", 0,
- "zjs", "컨", 0,
- "zje", "컫", 0,
- "zjf", "컬", 0,
- "zja", "컴", 0,
- "zjq", "컵", 0,
- "zjt", "컷", 0,
- "zjT", "컸", 0,
- "zjd", "컹", 0,
- "zpr", "켁", 0,
- "zps", "켄", 0,
- "zpf", "켈", 0,
- "zpa", "켐", 0,
- "zpq", "켑", 0,
- "zpt", "켓", 0,
- "zpd", "켕", 0,
- "zus", "켠", 0,
- "zuf", "켤", 0,
- "zua", "켬", 0,
- "zuq", "켭", 0,
- "zut", "켯", 0,
- "zuT", "켰", 0,
- "zud", "켱", 0,
- "zhr", "콕", 0,
- "zhs", "콘", 0,
- "zhf", "콜", 0,
- "zha", "콤", 0,
- "zhq", "콥", 0,
- "zht", "콧", 0,
- "zhd", "콩", 0,
- "zKr", "콱", 0,
- "zKs", "콴", 0,
- "zKf", "콸", 0,
- "zKa", "쾀", 0,
- "zKd", "쾅", 0,
- "zHd", "쾡", 0,
- "zLf", "쾰", 0,
- "znr", "쿡", 0,
- "zns", "쿤", 0,
- "znf", "쿨", 0,
- "zna", "쿰", 0,
- "znq", "쿱", 0,
- "znt", "쿳", 0,
- "znd", "쿵", 0,
- "zJs", "퀀", 0,
- "zJf", "퀄", 0,
- "zJd", "퀑", 0,
- "zNd", "퀭", 0,
- "zBr", "퀵", 0,
- "zBs", "퀸", 0,
- "zBf", "퀼", 0,
- "zBa", "큄", 0,
- "zBq", "큅", 0,
- "zBt", "큇", 0,
- "zBd", "큉", 0,
- "zbs", "큔", 0,
- "zbf", "큘", 0,
- "zba", "큠", 0,
- "zmr", "큭", 0,
- "zms", "큰", 0,
- "zmf", "클", 0,
- "zma", "큼", 0,
- "zmq", "큽", 0,
- "zmd", "킁", 0,
- "zlr", "킥", 0,
- "zls", "킨", 0,
- "zlf", "킬", 0,
- "zla", "킴", 0,
- "zlq", "킵", 0,
- "zlt", "킷", 0,
- "zld", "킹", 0,
- "xkr", "탁", 0,
- "xks", "탄", 0,
- "xkf", "탈", 0,
- "xkG", "탉", 0,
- "xka", "탐", 0,
- "xkq", "탑", 0,
- "xkt", "탓", 0,
- "xkT", "탔", 0,
- "xkd", "탕", 0,
- "xor", "택", 0,
- "xos", "탠", 0,
- "xof", "탤", 0,
- "xoa", "탬", 0,
- "xoq", "탭", 0,
- "xot", "탯", 0,
- "xoT", "탰", 0,
- "xod", "탱", 0,
- "xid", "턍", 0,
- "xjr", "턱", 0,
- "xjs", "턴", 0,
- "xjf", "털", 0,
- "xjM", "턺", 0,
- "xja", "텀", 0,
- "xjq", "텁", 0,
- "xjt", "텃", 0,
- "xjT", "텄", 0,
- "xjd", "텅", 0,
- "xpr", "텍", 0,
- "xps", "텐", 0,
- "xpf", "텔", 0,
- "xpa", "템", 0,
- "xpq", "텝", 0,
- "xpt", "텟", 0,
- "xpd", "텡", 0,
- "xus", "텬", 0,
- "xuT", "텼", 0,
- "xPs", "톈", 0,
- "xhr", "톡", 0,
- "xhs", "톤", 0,
- "xhf", "톨", 0,
- "xha", "톰", 0,
- "xhq", "톱", 0,
- "xht", "톳", 0,
- "xhd", "통", 0,
- "xhv", "톺", 0,
- "xKs", "퇀", 0,
- "xLs", "퇸", 0,
- "xLt", "툇", 0,
- "xLd", "툉", 0,
- "xnr", "툭", 0,
- "xns", "툰", 0,
- "xnf", "툴", 0,
- "xna", "툼", 0,
- "xnq", "툽", 0,
- "xnt", "툿", 0,
- "xnd", "퉁", 0,
- "xJT", "퉜", 0,
- "xBr", "튁", 0,
- "xBs", "튄", 0,
- "xBf", "튈", 0,
- "xBa", "튐", 0,
- "xBq", "튑", 0,
- "xBd", "튕", 0,
- "xbs", "튠", 0,
- "xbf", "튤", 0,
- "xba", "튬", 0,
- "xbd", "튱", 0,
- "xmr", "특", 0,
- "xms", "튼", 0,
- "xme", "튿", 0,
- "xmf", "틀", 0,
- "xmM", "틂", 0,
- "xma", "틈", 0,
- "xmq", "틉", 0,
- "xmt", "틋", 0,
- "xMs", "틘", 0,
- "xMf", "틜", 0,
- "xMa", "틤", 0,
- "xMq", "틥", 0,
- "xlr", "틱", 0,
- "xls", "틴", 0,
- "xlf", "틸", 0,
- "xla", "팀", 0,
- "xlq", "팁", 0,
- "xlt", "팃", 0,
- "xld", "팅", 0,
- "vkr", "팍", 0,
- "vkR", "팎", 0,
- "vks", "판", 0,
- "vkf", "팔", 0,
- "vkM", "팖", 0,
- "vka", "팜", 0,
- "vkq", "팝", 0,
- "vkt", "팟", 0,
- "vkT", "팠", 0,
- "vkd", "팡", 0,
- "vkx", "팥", 0,
- "vor", "팩", 0,
- "vos", "팬", 0,
- "vof", "팰", 0,
- "voa", "팸", 0,
- "voq", "팹", 0,
- "vot", "팻", 0,
- "voT", "팼", 0,
- "vod", "팽", 0,
- "vir", "퍅", 0,
- "vjr", "퍽", 0,
- "vjs", "펀", 0,
- "vjf", "펄", 0,
- "vja", "펌", 0,
- "vjq", "펍", 0,
- "vjt", "펏", 0,
- "vjT", "펐", 0,
- "vjd", "펑", 0,
- "vpr", "펙", 0,
- "vps", "펜", 0,
- "vpf", "펠", 0,
- "vpa", "펨", 0,
- "vpq", "펩", 0,
- "vpt", "펫", 0,
- "vpd", "펭", 0,
- "vus", "편", 0,
- "vuf", "펼", 0,
- "vua", "폄", 0,
- "vuq", "폅", 0,
- "vuT", "폈", 0,
- "vud", "평", 0,
- "vPf", "폘", 0,
- "vPq", "폡", 0,
- "vPt", "폣", 0,
- "vhr", "폭", 0,
- "vhs", "폰", 0,
- "vhf", "폴", 0,
- "vha", "폼", 0,
- "vhq", "폽", 0,
- "vht", "폿", 0,
- "vhd", "퐁", 0,
- "vKd", "퐝", 0,
- "vLs", "푄", 0,
- "vys", "푠", 0,
- "vyf", "푤", 0,
- "vyq", "푭", 0,
- "vyt", "푯", 0,
- "vnr", "푹", 0,
- "vns", "푼", 0,
- "vne", "푿", 0,
- "vnf", "풀", 0,
- "vnM", "풂", 0,
- "vna", "품", 0,
- "vnq", "풉", 0,
- "vnt", "풋", 0,
- "vnd", "풍", 0,
- "vJd", "풩", 0,
- "vBs", "퓐", 0,
- "vBf", "퓔", 0,
- "vBa", "퓜", 0,
- "vBt", "퓟", 0,
- "vbs", "퓬", 0,
- "vbf", "퓰", 0,
- "vba", "퓸", 0,
- "vbt", "퓻", 0,
- "vbd", "퓽", 0,
- "vms", "픈", 0,
- "vmf", "플", 0,
- "vma", "픔", 0,
- "vmq", "픕", 0,
- "vmt", "픗", 0,
- "vlr", "픽", 0,
- "vls", "핀", 0,
- "vlf", "필", 0,
- "vla", "핌", 0,
- "vlq", "핍", 0,
- "vlt", "핏", 0,
- "vld", "핑", 0,
- "gkr", "학", 0,
- "gks", "한", 0,
- "gkf", "할", 0,
- "gkB", "핥", 0,
- "gka", "함", 0,
- "gkq", "합", 0,
- "gkt", "핫", 0,
- "gkd", "항", 0,
- "gor", "핵", 0,
- "gos", "핸", 0,
- "gof", "핼", 0,
- "goa", "햄", 0,
- "goq", "햅", 0,
- "got", "햇", 0,
- "goT", "했", 0,
- "god", "행", 0,
- "gid", "향", 0,
- "gjr", "헉", 0,
- "gjs", "헌", 0,
- "gjf", "헐", 0,
- "gjM", "헒", 0,
- "gja", "험", 0,
- "gjq", "헙", 0,
- "gjt", "헛", 0,
- "gjd", "헝", 0,
- "gpr", "헥", 0,
- "gps", "헨", 0,
- "gpf", "헬", 0,
- "gpa", "헴", 0,
- "gpq", "헵", 0,
- "gpt", "헷", 0,
- "gpd", "헹", 0,
- "gur", "혁", 0,
- "gus", "현", 0,
- "guf", "혈", 0,
- "gua", "혐", 0,
- "guq", "협", 0,
- "gut", "혓", 0,
- "guT", "혔", 0,
- "gud", "형", 0,
- "gPs", "혠", 0,
- "gPf", "혤", 0,
- "gPq", "혭", 0,
- "ghr", "혹", 0,
- "ghs", "혼", 0,
- "ghf", "홀", 0,
- "ghB", "홅", 0,
- "gha", "홈", 0,
- "ghq", "홉", 0,
- "ght", "홋", 0,
- "ghd", "홍", 0,
- "ghx", "홑", 0,
- "gKr", "확", 0,
- "gKs", "환", 0,
- "gKf", "활", 0,
- "gKt", "홧", 0,
- "gKd", "황", 0,
- "gHr", "홱", 0,
- "gHs", "홴", 0,
- "gHt", "횃", 0,
- "gHd", "횅", 0,
- "gLr", "획", 0,
- "gLs", "횐", 0,
- "gLf", "횔", 0,
- "gLq", "횝", 0,
- "gLt", "횟", 0,
- "gLd", "횡", 0,
- "gys", "횬", 0,
- "gyf", "횰", 0,
- "gyq", "횹", 0,
- "gyt", "횻", 0,
- "gnr", "훅", 0,
- "gns", "훈", 0,
- "gnf", "훌", 0,
- "gnB", "훑", 0,
- "gna", "훔", 0,
- "gnt", "훗", 0,
- "gnd", "훙", 0,
- "gJs", "훤", 0,
- "gJf", "훨", 0,
- "gJa", "훰", 0,
- "gJd", "훵", 0,
- "gNr", "훽", 0,
- "gNs", "휀", 0,
- "gNf", "휄", 0,
- "gNd", "휑", 0,
- "gBr", "휙", 0,
- "gBs", "휜", 0,
- "gBf", "휠", 0,
- "gBa", "휨", 0,
- "gBq", "휩", 0,
- "gBt", "휫", 0,
- "gBd", "휭", 0,
- "gbr", "휵", 0,
- "gbs", "휸", 0,
- "gbf", "휼", 0,
- "gba", "흄", 0,
- "gbt", "흇", 0,
- "gbd", "흉", 0,
- "gmr", "흑", 0,
- "gms", "흔", 0,
- "gmH", "흖", 0,
- "gme", "흗", 0,
- "gmf", "흘", 0,
- "gmG", "흙", 0,
- "gma", "흠", 0,
- "gmq", "흡", 0,
- "gmt", "흣", 0,
- "gmd", "흥", 0,
- "gmx", "흩", 0,
- "gMs", "흰", 0,
- "gMf", "흴", 0,
- "gMa", "흼", 0,
- "gMq", "흽", 0,
- "gMd", "힁", 0,
- "glr", "힉", 0,
- "gls", "힌", 0,
- "glf", "힐", 0,
- "gla", "힘", 0,
- "glq", "힙", 0,
- "glt", "힛", 0,
- "gld", "힝", 0,
- 0
+typedef struct Trans Trans;
+struct Trans {
+ Channel *input;
+ Channel *output;
+ Channel *dict;
+ Channel *done;
+ Channel *lang;
};
-/* you can add other Map data here */
+void keyproc(void*);
+void launchfs(char*,char*,char*);
+int parselang(char*);
diff --git a/sys/src/cmd/ktrans/main.c b/sys/src/cmd/ktrans/main.c
index fb0cfe230..4105ad242 100644
--- a/sys/src/cmd/ktrans/main.c
+++ b/sys/src/cmd/ktrans/main.c
@@ -6,379 +6,140 @@
* okamoto@granite.cias.osakafu-u.ac.jp
*/
-/*
- * A glossary on some of the Japanese vocabulary used:
- * kana: syllabic letting, either hiragana(ひらがな) or katakana(カタカナ)
- * kanji(漢字): borrowed characters, 楽 in 楽しい
- * Okurigana(送り仮名): kana tail to kanji, しい in 楽しい
- * Joshi(助詞): particle, は in 私は
- * Jisho(辞書): dictionary
- * kouho(候補): candidate
- */
-
#include <u.h>
#include <libc.h>
+#include <ctype.h>
#include <bio.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+
#include "hash.h"
#include "ktrans.h"
-#define LSIZE 256
+static Hmap *jisho, *zidian;
+static int deflang;
+static char backspace[64];
-Rune lbuf[LSIZE]; /* hiragana buffer for key input written by send() */
-Hmap *table;
-uchar okurigana[LSIZE]; /* buffer for okurigana */
-char okuri = 0; /* buffer/flag for capital input char */
-int in, out;
-int llen, olen, joshi = 0;
-int natural = 1; /* not Japanese but English mode */
+mainstacksize = 8192*2;
-int changelang(int);
-int dotrans(Hmap*);
-int nrune(char *);
-void send(uchar *, int);
-Hmap* opendict(Hmap *, char *);
-
-void
-kbdopen(void)
+char*
+pushutf(char *dst, char *e, char *u, int nrune)
{
- int n, kinfd, koutfd, fd[2];
- char buf[128];
- int kbd;
-
- kbd = 1;
- if((kinfd = open("/dev/kbd", OREAD)) < 0){
- kbd = 0;
- if((kinfd = open("/dev/cons", OREAD)) < 0)
- sysfatal("open kbd: %r");
- }
- if(bind("#|", "/n/temp", MREPL) < 0)
- sysfatal("bind /n/temp: %r");
- if((koutfd = open("/n/temp/data1", OWRITE)) < 0)
- sysfatal("open kbd pipe: %r");
- if(bind("/n/temp/data", kbd? "/dev/kbd": "/dev/cons", MREPL) < 0)
- sysfatal("bind kbd pipe: %r");
- unmount(nil, "/n/temp");
- if(!kbd){
- in = kinfd;
- out = koutfd;
- return;
- }
- if(pipe(fd) < 0)
- sysfatal("pipe: %r");
- if(fork()){
- in = out = fd[0];
- close(fd[1]);
- close(kinfd);
- close(koutfd);
- return;
- }
- close(fd[0]);
- if(fork()){
- Biobuf b;
- long r;
-
- Binit(&b, fd[1], OREAD);
- while((r = Bgetrune(&b)) >= 0){
- n = snprint(buf, sizeof(buf), "c%C", (Rune)r)+1;
- write(koutfd, buf, n); /* pass on result */
- }
- } else
- while((n = read(kinfd, buf, sizeof(buf))) > 0){
- buf[n-1] = 0;
- if(n < 2 || buf[0] != 'c')
- write(koutfd, buf, n); /* pass on */
- else
- write(fd[1], buf+1, n-2); /* to translator */
+ Rune r;
+ char *p;
+ char *d;
+
+ if(dst >= e)
+ return dst;
+
+ d = dst;
+ p = u;
+ while(d < e-1){
+ if(isascii(*p)){
+ if((*d = *p) == '\0')
+ return d;
+ p++;
+ d++;
+ } else {
+ p += chartorune(&r, p);
+ if(r == Runeerror){
+ *d = '\0';
+ return d;
+ }
+ d += runetochar(d, &r);
}
- exits(nil);
+ if(nrune > 0 && --nrune == 0)
+ break;
+ }
+ if(d > e-1)
+ d = e-1;
+
+ *d = '\0';
+ return d;
}
-Map signalmore = {
- "_", nil, 1,
+typedef struct Str Str;
+struct Str {
+ char b[128];
+ char *p;
};
-Hmap*
-initmap(Map *m, int n)
-{
- int i, j;
- char buf[16];
- char *s;
- Map prev;
- Hmap *h;
-
- h = hmapalloc(n, sizeof(Map));
- for(i = 0; i < n; i++){
- if(m[i].roma == nil || m[i].roma[0] == '\0')
- continue;
-
- //We mark all partial strings so we know when
- //we have partial match when ingesting.
- j = 2;
- for(s = m[i].roma; *s && j <= sizeof buf; s++){
- snprint(buf, j, "%s", m[i].roma);
- prev = m[i];
- if(hmapget(h, buf, &prev) == 0){
- if(prev.leadstomore == 1 && s[1] == '\0'){
- //confict; partial & valid input
- prev = m[i];
- prev.leadstomore = 1;
- }
- }
-
- if(s[1] == '\0'){
- hmaprepl(&h, strdup(buf), &prev, nil, 1);
- } else {
- hmaprepl(&h, strdup(buf), &signalmore, nil, 1);
- }
- j++;
- }
- }
- return h;
-}
+#define strend(s) ((s)->b + sizeof (s)->b)
void
-usage(void)
+resetstr(Str *s, ...)
{
- fprint(2, "usage: %s\n", argv0);
- exits("usage");
+ va_list args;
+ va_start(args, s);
+ do {
+ s->p = s->b;
+ s->p[0] = '\0';
+ s = va_arg(args, Str*);
+ } while(s != nil);
+ va_end(args);
}
void
-main(int argc, char *argv[])
+popstr(Str *s)
{
+ while(s->p > s->b && (*--s->p & 0xC0)==0x80)
+ ;
- uchar *bp, *ep, buf[128];
- Map lkup, last;
- int wantmore;
- int n, c;
- char *jishoname, *zidianname;
- Hmap *jisho, *zidian;
-
- ARGBEGIN{
- default: usage();
- }ARGEND;
- if(argc != 0)
- usage();
-
- if((jishoname = getenv("jisho")) == nil)
- jishoname = "/lib/kanji.jisho";
- jisho = opendict(nil, jishoname);
-
- if((zidianname = getenv("zidian")) == nil)
- zidianname = "/lib/hanzi.zidian";
- zidian = opendict(nil, zidianname);
-
- hira = table = initmap(mhira, nelem(mhira));
- kata = initmap(mkata, nelem(mkata));
- greek = initmap(mgreek, nelem(mgreek));
- cyril = initmap(mcyril, nelem(mcyril));
- hangul = initmap(mhangul, nelem(mhangul));
- last = (Map){nil, nil, -1};
-
- kbdopen();
- if(fork())
- exits(nil); /* parent process will exit */
-
- bp = ep = buf;
- wantmore = 0;
- for (;;) { /* key board input loop */
- getmore:
- if (bp>=ep || wantmore) {
- if (wantmore==0)
- bp = ep = buf; /* clear all */
- n = read(in, ep, &buf[sizeof(buf)]-ep);
- if (n<=0)
- exits("");
- ep += n;
- *ep = '\0';
- }
- while (bp<ep) { /* there are input data */
- if (table == hira && natural != 1 && (*bp>'A' && *bp<='Z') && ep-bp<2
- && !strchr("EIOU", *bp)) {
- wantmore = 1;
- goto getmore;
- }
- if (!fullrune((char *)bp, ep-bp)) { /* not enough length of input */
- wantmore = 1;
- goto getmore;
- }
- wantmore = 0;
-
- if (*bp=='') { /* ^x read ktrans-jisho once more */
- jisho = opendict(jisho, jishoname);
- zidian = opendict(zidian, zidianname);
- llen = 0;
- olen = okuri = joshi = 0;
- wantmore=0;
- bp=ep=buf;
- continue;
- }
- if (*bp=='') { /* ^\ (start translation command) */
- if (table == hanzi)
- c = dotrans(zidian);
- else
- c = dotrans(jisho);
- if (c)
- *bp = c; /* pointer to translated rune */
- else
- bp++;
- continue;
- }
- if (*bp==' ') { /* ^l (no translate command) */
- bp++;
- llen = 0;
- olen = okuri = joshi = 0;
- last.kana = nil;
- continue;
- }
- if (changelang(*bp)) { /* change language mode OK */
- bp++;
- olen = okuri = joshi = 0;
- last.kana = nil;
- continue;
- }
- if (natural || *bp<=' ' || *bp>='{') { /* English mode but not ascii */
- Rune r;
- int rlen = chartorune(&r, (char *)bp);
- send(bp, rlen); /* write bp to /dev/cons */
- bp += rlen;
- last.kana = nil;
- continue;
- }
- if (table == hira && (*bp >= 'A' && *bp <= 'Z') && (*(bp+1) < 'A'
- || *(bp+1) > 'Z')) {
- *bp = okuri = tolower(*bp);
- joshi = olen = 0;
- } else if (table == hira && (*bp >= 'A' && *bp <= 'Z') &&
- (*(bp+1) >= 'A' && *(bp+1) <= 'Z')) {
- *bp = okuri = tolower(*bp);
- *(bp+1) = tolower(*(bp+1));
- joshi = 1;
- olen = 0;
- }
- if(hmapget(table, (char*)bp, &lkup) < 0){
- if(last.kana != nil){
- send((uchar*)last.kana, strlen(last.kana));
- bp += strlen(last.roma);
- } else
- send(bp++, 1);
- last.kana = nil;
- break;
- }
- /* concatinations; only advance a single character */
- if(lkup.kana != nil && strstr("ッっ", lkup.kana))
- lkup.roma = "_";
- /* partial match */
- if(lkup.kana == nil || lkup.leadstomore == 1){
- if(lkup.kana != nil)
- last = lkup;
-
- wantmore = 1;
- break;
- }
- last.kana = nil;
- send((uchar*)lkup.kana, strlen(lkup.kana));
- bp += strlen(lkup.roma);
- }
- }
+ s->p[0] = '\0';
}
-/*
- * send UTF string (p) with length (n) to stdout
- * and write rune (r) in global lbuf[] buffer
- * or okurigana[] buffer if okuri (verb or joshi) mode
- */
-void
-send(uchar *p, int n)
+Hmap*
+openmap(char *file)
{
+ Biobuf *b;
+ char *s;
+ Map map;
+ Hmap *h;
+ char *key, *val;
+ Str partial;
Rune r;
- uchar *ep;
- if (write(out, (char*)p, n) != n)
- sysfatal("write: %r");
+ h = hmapalloc(64, sizeof(Map));
+ b = Bopen(file, OREAD);
+ if(b == nil)
+ return nil;
- if (llen>LSIZE-64) {
- memmove((char*)lbuf, (char*)lbuf+64, 64*sizeof(Rune));
- llen -= 64;
- }
+ while(key = Brdstr(b, '\n', 1)){
+ if(key[0] == '\0'){
+ Err:
+ free(key);
+ continue;
+ }
- if(table != hira && table != hanzi)
- return;
- if(natural && table != hanzi)
- return;
+ val = strchr(key, '\t');
+ if(val == nil || val[1] == '\0')
+ goto Err;
- ep = p+n;
- if(okuri)
- while (olen<LSIZE && p<ep)
- okurigana[olen++] = *p++;
- else
- while (llen<LSIZE && p<ep) {
- p += chartorune(&r, (char*)p);
- if (r=='\b') {
- if (llen>0)
- llen--;
- continue;
+ *val = '\0';
+ val++;
+ resetstr(&partial, nil);
+ for(s = key; *s; s += chartorune(&r, s)){
+ partial.p = pushutf(partial.p, strend(&partial), s, 1);
+ map.leadstomore = 0;
+ if(hmapget(h, partial.b, &map) == 0){
+ if(map.leadstomore == 1 && s[1] == '\0')
+ map.leadstomore = 1;
}
- if (r==0x80) /* ignore view key */
- continue;
- lbuf[llen++] = r;
- }
-}
-
-int
-changelang(int c)
-{
- switch(c){
- case '': /* ^t (English mode) */
- natural = 1;
- table = hira;
- llen = 0;
- return 1;
- break;
-
- case '': /* ^n (Japanese hiragana mode ) */
- natural = 0;
- table = hira;
- llen = 0;
- return 1;
- break;
-
- case ' ': /* ^k (Japanese katakana mode) */
- natural = 0;
- table = kata;
- llen = 0;
- return 1;
- break;
-
- case '': /* ^r (Russian mode) */
- natural = 0;
- table = cyril;
- llen = 0;
- return 1;
- break;
-
- case '': /* ^o (Greek mode) */
- natural = 0;
- table = greek;
- llen = 0;
- return 1;
- break;
-
- case '': /* ^s (Korean mode) */
- natural = 0;
- table = hangul;
- llen = 0;
- return 1;
- break;
-
- case '': /* ^c (Chinese mode) */
- natural = 1;
- table = hanzi;
- llen = 0;
- return 1;
- break;
+ if(s[1] == '\0'){
+ map.roma = key;
+ map.kana = val;
+ hmaprepl(&h, strdup(map.roma), &map, nil, 1);
+ } else {
+ map.roma = strdup(partial.b);
+ map.leadstomore = 1;
+ map.kana = nil;
+ hmaprepl(&h, strdup(partial.b), &map, nil, 1);
+ }
+ }
}
- return 0;
+ Bterm(b);
+ return h;
}
Hmap*
@@ -404,7 +165,7 @@ opendict(Hmap *h, char *name)
free(p);
continue;
}
- dot = utfrune(p, '\t');
+ dot = strchr(p, '\t');
if(dot == nil)
goto Err;
@@ -430,136 +191,396 @@ opendict(Hmap *h, char *name)
return h;
}
-/*
- * write translated kanji runes to stdout and return last character
- * if it's not ctl-\. if the last is ctl-\, proceed with
- * translation of the next kouho
- */
+enum{
+ LangEN = '', // ^t
+ LangJP = '', // ^n
+ LangJPK = ' ', // ^k
+ LangRU = '', // ^r
+ LangEL = '', // ^o
+ LangKO = '', // ^s
+ LangZH = '', // ^c
+};
+
+Hmap *natural;
+Hmap *hira, *kata;
+Hmap *cyril;
+Hmap *greek;
+Hmap *hangul;
+Hmap *hanzi;
+
+Hmap **langtab[] = {
+ [LangEN] &natural,
+ [LangJP] &hira,
+ [LangJPK] &kata,
+ [LangRU] &cyril,
+ [LangEL] &greek,
+ [LangKO] &hangul,
+ [LangZH] &hanzi,
+};
+
+char *langcodetab[] = {
+ [LangEN] "en",
+ [LangJP] "jp",
+ [LangJPK] "jpk",
+ [LangRU] "ru",
+ [LangEL] "el",
+ [LangKO] "ko",
+ [LangZH] "zh",
+};
+
int
-dotrans(Hmap *dic)
+parselang(char *s)
{
- Rune *res, r[1];
- char v[1024], *p, tbuf[64], hirabuf[64];
- int j, lastlen, nokouho = 0;
- char ch;
int i;
- char *kouho[16];
- if (llen==0)
- return 0; /* don't use kanji transform function */
- if (okuri && joshi != 1) {
- lbuf[llen++] = (Rune)okuri;
- lbuf[llen] = 0;
- }else
- lbuf[llen] = 0;
- okurigana[olen] = 0;
-
- /*
- * search the matched index for the key word in the dict hash table, and
- * return a pointer to the matched kouho, 0 otherwise.
- */
- res = lbuf;
- for (j=0; *res != L'\0'; j += runetochar(v+j, res++))
- ;
- v[j] = '\0';
- strcpy(tbuf, v);
- strcpy(hirabuf, v); /* to remember the initial hiragana input */
+ for(i = 0; i < nelem(langcodetab); i++){
+ if(langcodetab[i] == nil)
+ continue;
+ if(strcmp(langcodetab[i], s) == 0)
+ return i;
+ }
- if (okuri && joshi != 1) /* verb mode */
- hirabuf[strlen(hirabuf) - 1] = '\0';
+ return -1;
+}
- if(hmapget(dic, v, kouho) < 0){
- llen = olen = okuri = joshi = 0;
- okurigana[0] = 0;
+int
+checklang(int *dst, int c)
+{
+ Hmap **p;
+
+ if(c >= nelem(langtab))
return 0;
- }
- for(i = 0; i < nelem(kouho) && kouho[i] != nil; i++) {
- p = kouho[i];
- lastlen = nrune(tbuf); /* number of rune chars */
-
- if (okuri && joshi != 1) /* verb mode */
- for (j=0; j<lastlen-1; j++)
- write(out, "\b", 1); /* clear hiragana input */
- else
- for (j=0; j<lastlen; j++)
- write(out, "\b", 1); /* clear hiragana input */
-
- if (okuri) {
- lastlen = nrune((char *)okurigana);
- for (j=0; j<lastlen; j++)
- write(out, "\b", 1);
- }
- write(out, p, strlen(p)); /* write kanji to stdout */
- if (okuri)
- write(out, (char *)okurigana, olen);
+ p = langtab[c];
+ if(p == nil)
+ return 0;
+
+ *dst = c;
+ return c;
+}
+
+int
+maplkup(int lang, char *s, Map *m)
+{
+ Hmap **h;
- if (read(in, &ch, 1)<=0) /* read from stdin */
- exits(nil);
+ if(lang >= nelem(langtab))
+ return -1;
- if (ch == '') { /* if next input is ^\, once again */
- if(i+1 < nelem(kouho) && kouho[i+1] != nil) { /* have next kouho */
- nokouho = 0;
- strcpy(tbuf, p);
+ h = langtab[lang];
+ if(h == nil || *h == nil)
+ return -1;
- if (okuri && joshi != 1) /* verb mode */
- for (j=0; j<nrune(tbuf); j++)
- write(out, "\b", 1);
- continue;
- } else { /* the last kouho */
- if (okuri) {
- lastlen = nrune((char *)okurigana);
- for (j=0; j<lastlen; j++)
- write(out, "\b", 1);
- }
+ return hmapget(*h, s, m);
+}
+
+static int
+emitutf(Channel *out, char *u, int nrune)
+{
+ Msg m;
+ char *e;
- for (lastlen=0; *p != 0; p += j) {
- j = chartorune(r, p);
- lastlen++;
+ m.code = 'c';
+ e = pushutf(m.buf, m.buf + sizeof m.buf, u, nrune);
+ send(out, &m);
+ return e - m.buf;
+}
+
+static void
+dictthread(void *a)
+{
+ Trans *t;
+ Msg m;
+ Rune r;
+ int n;
+ char *p;
+ Hmap *dict;
+ char *kouho[16];
+ Str line;
+ Str last;
+ Str okuri;
+ int selected;
+
+ enum{
+ Kanji,
+ Okuri,
+ Joshi,
+ };
+ int mode;
+
+ t = a;
+ dict = jisho;
+ selected = -1;
+ kouho[0] = nil;
+ mode = Kanji;
+ resetstr(&last, &line, &okuri, nil);
+
+ threadsetname("dict");
+ while(recv(t->dict, &m) != -1){
+ for(p = m.buf; *p; p += n){
+ n = chartorune(&r, p);
+ if(r != ''){
+ if(selected >= 0){
+ resetstr(&okuri, nil);
+ mode = Kanji;
+ }
+ resetstr(&last, nil);
+ selected = -1;
+ kouho[0] = nil;
+ }
+ switch(r){
+ case LangJP:
+ dict = jisho;
+ break;
+ case LangZH:
+ dict = zidian;
+ break;
+ case '':
+ if(line.b == line.p){
+ emitutf(t->output, "", 1);
+ break;
+ }
+ emitutf(t->output, backspace, utflen(line.b));
+ /* fallthrough */
+ case ' ': case ',': case '.':
+ case ' ':
+ mode = Kanji;
+ resetstr(&line, &okuri, nil);
+ break;
+ case '\b':
+ if(mode != Kanji){
+ if(okuri.p == okuri.b){
+ mode = Kanji;
+ popstr(&line);
+ }else
+ popstr(&okuri);
+ break;
+ }
+ popstr(&line);
+ break;
+ case '\n':
+ if(line.b == line.p){
+ emitutf(t->output, "\n", 1);
+ break;
+ }
+ /* fallthrough */
+ case '':
+ selected++;
+ if(selected == 0){
+ if(hmapget(dict, line.b, kouho) < 0){
+ resetstr(&line, &last, nil);
+ selected = -1;
+ break;
+ }
+ if(dict == jisho && line.p > line.b && isascii(line.p[-1]))
+ line.p[-1] = '\0';
+ }
+ if(kouho[selected] == nil){
+ /* cycled through all matches; bail */
+ emitutf(t->output, backspace, utflen(last.b));
+ emitutf(t->output, line.b, 0);
+ resetstr(&line, &last, &okuri, nil);
+ selected = -1;
+ break;
}
- for (j=0; j<lastlen; j++)
- write(out, "\b", 1);
+ if(okuri.p != okuri.b)
+ emitutf(t->output, backspace, utflen(okuri.b));
+ if(selected == 0)
+ emitutf(t->output, backspace, utflen(line.b));
+ else
+ emitutf(t->output, backspace, utflen(last.b));
- if(hirabuf[0])
- write(out, hirabuf, strlen(hirabuf));
+ emitutf(t->output, kouho[selected], 0);
+ last.p = pushutf(last.b, strend(&last), kouho[selected], 0);
+ emitutf(t->output, okuri.b, 0);
- if(okurigana[0])
- write(out, (char *)okurigana, olen);
+ resetstr(&line, nil);
+ mode = Kanji;
+ break;
+ default:
+ if(dict == zidian){
+ line.p = pushutf(line.p, strend(&line), p, 1);
+ break;
+ }
- olen = okuri = joshi = 0;
- okurigana[0] = 0;
+ if(mode == Joshi){
+ okuri.p = pushutf(okuri.p, strend(&okuri), p, 1);
+ break;
+ }
+
+ if(isupper(*p)){
+ if(mode == Okuri){
+ popstr(&line);
+ mode = Joshi;
+ okuri.p = pushutf(okuri.p, strend(&okuri), p, 1);
+ break;
+ }
+ mode = Okuri;
+ *p = tolower(*p);
+ line.p = pushutf(line.p, strend(&line), p, 1);
+ okuri.p = pushutf(okuri.b, strend(&okuri), p, 1);
+ break;
+ }
+ if(mode == Kanji)
+ line.p = pushutf(line.p, strend(&line), p, 1);
+ else
+ okuri.p = pushutf(okuri.p, strend(&okuri), p, 1);
break;
}
- } else {
- if(!nokouho && i != 0){ /* learn the previous use of the kouho */
- p = kouho[0];
- kouho[0] = kouho[i];
- kouho[i] = p;
- hmapupd(&dic, v, kouho);
- }
-
- olen = okuri = joshi = 0;
- okurigana[0] = 0;
- break;
}
}
- llen = 0;
- return ch;
+
+ send(t->done, nil);
}
-/*
- * returns the number of characters in the pointed Rune
- */
-int
-nrune(char *p)
+void
+keyproc(void *a)
{
- int n = 0;
+ Trans *t;
+ int lang;
+ Msg m;
+ Map lkup;
+ char *p;
+ int n;
Rune r;
+ char peek[UTFmax+1];
+ Str line;
+ int mode;
+
+ t = a;
+ mode = 0;
+ peek[0] = lang = deflang;
+ threadcreate(dictthread, a, mainstacksize);
+ resetstr(&line, nil);
+ if(lang == LangJP || lang == LangZH)
+ emitutf(t->dict, peek, 1);
+
+ threadsetname("key");
+ while(recv(t->input, &m) != -1){
+ if(m.code != 'c'){
+ if(m.code == 'q')
+ send(t->lang, &langcodetab[lang]);
+ else
+ send(t->output, &m);
+ continue;
+ }
+
+ for(p = m.buf; *p; p += n){
+ n = chartorune(&r, p);
+ if(checklang(&lang, r)){
+ emitutf(t->dict, " ", 1);
+ if(lang == LangJP || lang == LangZH)
+ emitutf(t->dict, p, 1);
+ resetstr(&line, nil);
+ continue;
+ }
+ if(lang == LangZH || lang == LangJP){
+ emitutf(t->dict, p, 1);
+ if(utfrune(" \n", r) != nil){
+ resetstr(&line, nil);
+ continue;
+ }
+ if(lang == LangJP && isupper(*p)){
+ *p = tolower(*p);
+ mode++;
+ } else {
+ mode = 0;
+ }
+ }
+
+ emitutf(t->output, p, 1);
+ if(lang == LangEN || lang == LangZH)
+ continue;
+ if(r == '\b'){
+ popstr(&line);
+ continue;
+ }
+
+ line.p = pushutf(line.p, strend(&line), p, 1);
+ if(maplkup(lang, line.b, &lkup) < 0){
+ resetstr(&line, nil);
+ pushutf(peek, peek + sizeof peek, p, 1);
+ if(maplkup(lang, peek, &lkup) == 0)
+ line.p = pushutf(line.p, strend(&line), p, 1);
+ continue;
+ }
+ if(lkup.kana == nil)
+ continue;
- while (*p) {
- p += chartorune(&r, p);
- n++;
+ if(!lkup.leadstomore)
+ resetstr(&line, nil);
+
+ if(lang == LangJP){
+ emitutf(t->dict, backspace, utflen(lkup.roma));
+ emitutf(t->dict, lkup.kana, 0);
+ }
+ emitutf(t->output, backspace, utflen(lkup.roma));
+ emitutf(t->output, lkup.kana, 0);
+ }
}
- return n;
+ send(t->done, nil);
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: %s [ -K ] [ -l lang ]\n", argv0);
+ exits("usage");
+}
+
+void
+threadmain(int argc, char *argv[])
+{
+
+ char *jishoname, *zidianname;
+ char *kbd, *srv, *mntpt;
+
+ kbd = "/dev/kbd";
+ srv = nil;
+ mntpt = "/mnt/ktrans";
+ deflang = LangEN;
+ ARGBEGIN{
+ case 'K':
+ kbd = nil;
+ break;
+ case 'k':
+ kbd = EARGF(usage());
+ break;
+ case 'l':
+ deflang = parselang(EARGF(usage()));
+ if(deflang < 0)
+ usage();
+ break;
+ case 's':
+ srv = EARGF(usage());
+ break;
+ case 'm':
+ mntpt = EARGF(usage());
+ break;
+ default:
+ usage();
+ }ARGEND;
+ if(argc != 0)
+ usage();
+
+ memset(backspace, '\b', sizeof backspace-1);
+ backspace[sizeof backspace-1] = '\0';
+
+ if((jishoname = getenv("jisho")) == nil)
+ jishoname = "/lib/ktrans/kanji.dict";
+ jisho = opendict(nil, jishoname);
+
+ if((zidianname = getenv("zidian")) == nil)
+ zidianname = "/lib/ktrans/wubi.dict";
+ zidian = opendict(nil, zidianname);
+
+ natural = hanzi = nil;
+ hira = openmap("/lib/ktrans/hira.map");
+ kata = openmap("/lib/ktrans/kata.map");
+ greek = openmap("/lib/ktrans/greek.map");
+ cyril = openmap("/lib/ktrans/cyril.map");
+ hangul = openmap("/lib/ktrans/hangul.map");
+
+ launchfs(srv, mntpt, kbd);
}
diff --git a/sys/src/cmd/ktrans/mkfile b/sys/src/cmd/ktrans/mkfile
index 95e21f7b2..5de77a8d0 100644
--- a/sys/src/cmd/ktrans/mkfile
+++ b/sys/src/cmd/ktrans/mkfile
@@ -6,5 +6,6 @@ HFILES=ktrans.h
OFILES=\
hash.$O\
main.$O\
+ fs.$O\
</sys/src/cmd/mkone