summaryrefslogtreecommitdiff
path: root/src-util/rkhelper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src-util/rkhelper.c')
-rw-r--r--src-util/rkhelper.c442
1 files changed, 442 insertions, 0 deletions
diff --git a/src-util/rkhelper.c b/src-util/rkhelper.c
new file mode 100644
index 0000000..c99bd08
--- /dev/null
+++ b/src-util/rkhelper.c
@@ -0,0 +1,442 @@
+/*
+ * ローマ字から平仮名(正確にはキーの列から文字)の表(rk_map)の
+ * カスタマイズを管理する
+ *
+ * Copyright (C) 2001-2002 UGAWA Tomoharu
+ * Copyright (C) 2002 Tabata Yusuke
+ *
+ * Funded by IPA未踏ソフトウェア創造事業 2001
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "rkconv.h"
+#include "rkhelper.h"
+
+static const char* rk_default_symbol[128] = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ " ", "!", "”", "#", "$", "%", "&", "’",
+ "(", ")", "*", "+", "、", "ー", "。", "/",
+ "0", "1", "2", "3", "4", "5", "6", "7",
+ "8", "9", ":", ";", "<", "=", ">", "?",
+
+ "@", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, "「", "\", "」", "^", "_",
+ "‘", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, "{", "|", "}", "〜", NULL
+};
+
+struct rk_conf_ent {
+ char *lhs;
+ char *rhs;
+ struct rk_conf_ent *next;
+};
+
+struct rk_option {
+ int enable_default;
+ char toggle; /* 英数との一時的な切替えに使うシンボル */
+ /*
+ * 配列はそれぞれリストの先頭になる
+ * リストの先頭は一文字のエントリが入る
+ */
+ struct rk_conf_ent hiragana_symbol[128]; /* ひらがなとの対応 */
+ struct rk_conf_ent katakana_symbol[128]; /* カタカナとの対応 */
+ struct rk_conf_ent hankaku_kana_symbol[128]; /* カタカナとの対応 */
+};
+
+#include "rkmap.h"
+
+struct rk_option *
+anthy_input_create_rk_option()
+{
+ struct rk_option *opt;
+ int i;
+
+ opt = malloc(sizeof(struct rk_option));
+ opt->enable_default = 1;
+ opt->toggle = '/';
+ for (i = 0; i < 128; i++) {
+ opt->hiragana_symbol[i].rhs = NULL;
+ opt->hiragana_symbol[i].lhs = NULL;
+ opt->hiragana_symbol[i].next = NULL;
+ opt->katakana_symbol[i].rhs = NULL;
+ opt->katakana_symbol[i].lhs = NULL;
+ opt->katakana_symbol[i].next = NULL;
+ opt->hankaku_kana_symbol[i].rhs = NULL;
+ opt->hankaku_kana_symbol[i].lhs = NULL;
+ opt->hankaku_kana_symbol[i].next = NULL;
+ }
+ return opt;
+}
+
+int
+anthy_input_free_rk_option(struct rk_option *opt)
+{
+ int err;
+
+ err = anthy_input_do_clear_rk_option(opt, 1);
+ free(opt);
+
+ return err;
+}
+
+static struct rk_conf_ent *
+find_rk_conf_ent(struct rk_option *opt, int map,
+ const char *key, int force)
+{
+ int c = key[0];
+ struct rk_conf_ent *tab = NULL;
+ struct rk_conf_ent *sym = NULL;
+
+ if (c == 0) {
+ return NULL;
+ }
+
+ if (map == RKMAP_HIRAGANA) {
+ tab = opt->hiragana_symbol;
+ }
+ if (map == RKMAP_KATAKANA) {
+ tab = opt->katakana_symbol;
+ }
+ if (map == RKMAP_HANKAKU_KANA) {
+ tab = opt->hankaku_kana_symbol;
+ }
+ if (!tab) {
+ return NULL;
+ }
+ if (strlen(key) == 1) {
+ sym = &tab[c];
+ } else {
+ /* 2文字以上 */
+ for (sym = tab[c].next; sym; sym = sym->next) {
+ if (!strcmp(sym->lhs, key)) {
+ break;
+ }
+ }
+ }
+ if (!sym && force) {
+ /* メモリ確保してつなぐ */
+ sym = malloc(sizeof(struct rk_conf_ent));
+ sym->rhs = NULL;
+ sym->lhs = NULL;
+ sym->next = tab[c].next;
+ tab[c].next = sym;
+ }
+ if (sym && !sym->lhs) {
+ sym->lhs = strdup(key);
+ }
+ return sym;
+}
+
+/*
+ * opt 変更対象のoption
+ * map RKMAP_*
+ * from 変換もとの文字
+ * to 変換先の文字列
+ * follow follow集合
+ */
+int
+anthy_input_do_edit_rk_option(struct rk_option* opt, int map,
+ const char* from, const char* to, const char *follow)
+{
+ struct rk_conf_ent *tab;
+ (void)follow;
+
+ tab = find_rk_conf_ent(opt, map, from, 1);
+ if (!tab) {
+ return -1;
+ }
+
+ if (tab->rhs) {
+ free(tab->rhs);
+ }
+ if (to == NULL) {
+ tab->rhs = NULL;
+ } else {
+ tab->rhs = strdup(to);
+ }
+ return 0;
+}
+
+static void
+free_rk_conf_ent(struct rk_conf_ent *e)
+{
+ if (e->lhs) {
+ free(e->lhs);
+ e->lhs = NULL;
+ }
+ if (e->rhs) {
+ free(e->rhs);
+ e->rhs = NULL;
+ }
+ e->next = NULL;
+}
+
+int
+anthy_input_do_clear_rk_option(struct rk_option* opt,
+ int use_default)
+{
+ int i;
+
+ opt->enable_default = use_default;
+ for (i = 0; i < 128; i++) {
+ /* 各文字に対して */
+ struct rk_conf_ent *tab, *tmp;
+ /* ひらがなのリストを解放 */
+ for (tab = opt->hiragana_symbol[i].next; tab;) {
+ tmp = tab;
+ tab = tab->next;
+ free_rk_conf_ent(tmp);
+ free(tmp);
+ }
+ /* カタカナのリストを解放 */
+ for (tab = opt->katakana_symbol[i].next; tab;) {
+ tmp = tab;
+ tab = tab->next;
+ free_rk_conf_ent(tmp);
+ free(tmp);
+ }
+ /* 先頭の一文字のエントリも忘れずに解放 */
+ free_rk_conf_ent(&opt->katakana_symbol[i]);
+ free_rk_conf_ent(&opt->hiragana_symbol[i]);
+ }
+ return 0;
+}
+
+int
+anthy_input_do_edit_toggle_option(struct rk_option* opt,
+ char toggle)
+{
+ opt->toggle = toggle;
+ return 0;
+}
+
+static void
+rkrule_set(struct rk_rule* r,
+ const char* lhs, const char* rhs, const char* follow)
+{
+ r->lhs = lhs;
+ r->rhs = rhs;
+ r->follow = follow;
+}
+
+struct rk_map*
+make_rkmap_ascii(struct rk_option* opt)
+{
+ struct rk_rule var_part[130];
+ struct rk_rule* complete_rules;
+ struct rk_map* map;
+ struct rk_rule* p;
+ char work[2*128];
+ char* w;
+ int c;
+
+ (void)opt;
+ p = var_part;
+ w = work;
+ for (c = 0; c < 128; c++) {
+ if (rk_default_symbol[c]) {
+ w[0] = c;
+ w[1] = '\0';
+ rkrule_set(p++, w, w, NULL);
+ w += 2;
+ }
+ }
+ p->lhs = NULL;
+
+ complete_rules = rk_merge_rules(rk_rule_alphabet, var_part);
+ map = rk_map_create(complete_rules);
+ rk_rules_free(complete_rules);
+
+ return map;
+}
+
+struct rk_map*
+make_rkmap_wascii(struct rk_option* opt)
+{
+ (void)opt;
+ return rk_map_create(rk_rule_walphabet);
+}
+
+struct rk_map*
+make_rkmap_shiftascii(struct rk_option* opt)
+{
+ struct rk_rule var_part[130];
+ struct rk_rule* complete_rules;
+ struct rk_map* map;
+ struct rk_rule* p;
+ char work[2*128 + 3];
+ char* w;
+ int c;
+ int toggle_char = opt->toggle;
+
+ p = var_part;
+ w = work;
+ for (c = 0; c < 128; c++) {
+ if (rk_default_symbol[c]) {
+ if (c == toggle_char) {
+ /* トグルする文字の場合 */
+ w[0] = c;
+ w[1] = '\0';
+ rkrule_set(p++, w, "\xff" "o", NULL);
+ w[2] = c;
+ w[3] = c;
+ w[4] = '\0';
+ rkrule_set(p++, w + 2, w, NULL);
+ w += 5;
+ } else {
+ /* 普通の文字の場合 */
+ w[0] = c;
+ w[1] = '\0';
+ rkrule_set(p++, w, w, NULL);
+ w += 2;
+ }
+ }
+ }
+ p->lhs = NULL;
+
+ complete_rules = rk_merge_rules(rk_rule_alphabet, var_part);
+ map = rk_map_create(complete_rules);
+ rk_rules_free(complete_rules);
+
+ return map;
+}
+
+static int
+count_rk_rule_ent(struct rk_option *opt, int map_no)
+{
+ int i , c;
+ struct rk_conf_ent *head;
+ struct rk_conf_ent *ent;
+
+ if (map_no == RKMAP_HIRAGANA) {
+ head = opt->hiragana_symbol;
+ } else if (map_no == RKMAP_HANKAKU_KANA) {
+ head = opt->katakana_symbol;
+ } else {
+ head = opt->hankaku_kana_symbol;
+ }
+
+ c = 128;
+ for (i = 0; i < 128; i++) {
+ for (ent = head[i].next; ent; ent = ent->next) {
+ if (ent->lhs) {
+ c++;
+ }
+ }
+ }
+ return c;
+}
+
+/*
+ * デフォルトのルールとカスタマイズされたルールをマージして
+ * rk_mapを作る。
+ */
+static struct rk_map*
+make_rkmap_hirakata(const struct rk_rule* rule,
+ struct rk_option *opt, int map_no)
+{
+ struct rk_conf_ent *tab;
+ struct rk_rule* rk_var_part;
+ struct rk_rule* complete_rules;
+ struct rk_rule* p;
+ struct rk_map* map;
+ int toggle = opt->toggle;
+ char *work;
+ char* w;
+ int c;
+ int nr_rule;
+ char buf[2];
+
+ nr_rule = count_rk_rule_ent(opt, map_no);
+
+ rk_var_part = alloca(sizeof(struct rk_rule) *(nr_rule + 2));
+ work = alloca(2*128 + 8);
+ p = rk_var_part;
+ w = work;
+
+ /* 一文字のものをrk_var_partに書き込んでいく */
+ /* トグルの場合 */
+ buf[0] = toggle;
+ buf[1] = 0;
+ w[0] = toggle;
+ w[1] = '\0';
+ w[2] = '\xff';
+ w[3] = '0' + RKMAP_SHIFT_ASCII;
+ w[4] = '\0';
+ rkrule_set(p++, w, w + 2, NULL);
+ w[5] = toggle;
+ w[6] = toggle;
+ w[7] = '\0';
+ tab = find_rk_conf_ent(opt, map_no, buf, 0);
+ if (tab && tab->rhs) {
+ rkrule_set(p++, w + 5, tab->rhs, NULL);
+ } else {
+ rkrule_set(p++, w + 5, rk_default_symbol[toggle], NULL);
+ }
+ w += 8;
+ /* トグル以外 */
+ for (c = 0; c < 128; c++) {
+ if (c != toggle) {
+ buf[0] = c;
+ buf[1] = 0;
+ /* 一文字のもの */
+ w[0] = c;
+ w[1] = '\0';
+ tab = find_rk_conf_ent(opt, map_no, buf, 0);
+ if (tab && tab->rhs) {
+ /* カスタマイズ済のがある */
+ rkrule_set(p++, w, tab->rhs, NULL);
+ } else if (rk_default_symbol[c]) {
+ /* 記号など */
+ rkrule_set(p++, w, rk_default_symbol[c], NULL);
+ }
+ w += 2;
+ /* 二文字以上のもの */
+ if (tab) {
+ for (tab = tab->next; tab; tab = tab->next) {
+ rkrule_set(p++, tab->lhs, tab->rhs, NULL);
+ }
+ }
+ }
+ }
+ p->lhs = NULL;
+
+ if (opt->enable_default) {
+ complete_rules = rk_merge_rules(rule, rk_var_part);
+ map = rk_map_create(complete_rules);
+ rk_rules_free(complete_rules);
+ } else {
+ map = rk_map_create(rk_var_part);
+ }
+
+ return map;
+}
+
+struct rk_map*
+make_rkmap_hiragana(struct rk_option* opt)
+{
+ return make_rkmap_hirakata(rk_rule_hiragana,
+ opt, RKMAP_HIRAGANA);
+}
+
+struct rk_map*
+make_rkmap_katakana(struct rk_option* opt)
+{
+ return make_rkmap_hirakata(rk_rule_katakana,
+ opt, RKMAP_KATAKANA);
+}
+
+struct rk_map *
+make_rkmap_hankaku_kana(struct rk_option *opt)
+{
+ return make_rkmap_hirakata(rk_rule_hankaku_kana,
+ opt, RKMAP_HANKAKU_KANA);
+}