(linenum→info "unix/slp.c:2238")

anthy/9100e/src-util/rkhelper.c

    1: /*
    2:  * ローマ字から平仮名(正確にはキーの列から文字)の表(rk_map)の
    3:  * カスタマイズを管理する
    4:  *
    5:  * Copyright (C) 2001-2002 UGAWA Tomoharu
    6:  * Copyright (C) 2002 Tabata Yusuke
    7:  *
    8:  * Funded by IPA未踏ソフトウェア創造事業 2001
    9:  */
   10: 
   11: #include <string.h>
   12: #include <stdlib.h>
   13: #include "rkconv.h"
   14: #include "rkhelper.h"
   15: 
   16: static const char* rk_default_symbol[128] = {
   17:   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
   18:   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   19:   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   20:   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   21:   " ", "!", "”", "#", "$", "%", "&", "’", 
   22:   "(", ")", "*", "+", "、", "ー", "。", "/",
   23:   "0", "1", "2", "3", "4", "5", "6", "7",
   24:   "8", "9", ":", ";", "<", "=", ">", "?",
   25: 
   26:   "@", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   27:   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   28:   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   29:   NULL, NULL, NULL, "「", "\", "」", "^", "_",
   30:   "‘", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   31:   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   32:   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
   33:   NULL, NULL, NULL, "{", "|", "}", "〜", NULL
   34: };
   35: 
   36: struct rk_conf_ent {
   37:   char *lhs;
   38:   char *rhs;
   39:   struct rk_conf_ent *next;
   40: };
   41: 
   42: struct rk_option {
   43:   int enable_default;
   44:   char toggle; /* 英数との一時的な切替えに使うシンボル */
   45:   /*
   46:    * 配列はそれぞれリストの先頭になる
   47:    * リストの先頭は一文字のエントリが入る
   48:    */
   49:   struct rk_conf_ent hiragana_symbol[128]; /* ひらがなとの対応 */
   50:   struct rk_conf_ent katakana_symbol[128]; /* カタカナとの対応 */
   51:   struct rk_conf_ent hankaku_kana_symbol[128]; /* カタカナとの対応 */
   52: };
   53: 
   54: #include "rkmap.h"
   55: 
   56: struct rk_option *
   57: anthy_input_create_rk_option()
   58: {
   59:   struct rk_option *opt;
   60:   int i;
   61: 
   62:   opt = malloc(sizeof(struct rk_option));
   63:   opt->enable_default = 1;
   64:   opt->toggle = '/';
   65:   for (i = 0; i < 128; i++) {
   66:     opt->hiragana_symbol[i].rhs = NULL;
   67:     opt->hiragana_symbol[i].lhs = NULL;
   68:     opt->hiragana_symbol[i].next = NULL;
   69:     opt->katakana_symbol[i].rhs = NULL;
   70:     opt->katakana_symbol[i].lhs = NULL;
   71:     opt->katakana_symbol[i].next = NULL;
   72:     opt->hankaku_kana_symbol[i].rhs = NULL;
   73:     opt->hankaku_kana_symbol[i].lhs = NULL;
   74:     opt->hankaku_kana_symbol[i].next = NULL;
   75:   }
   76:   return opt;
   77: }
   78: 
   79: int
   80: anthy_input_free_rk_option(struct rk_option *opt)
   81: {
   82:   int err;
   83: 
   84:   err = anthy_input_do_clear_rk_option(opt, 1);
   85:   free(opt);
   86: 
   87:   return err;
   88: }
   89: 
   90: static struct rk_conf_ent *
   91: find_rk_conf_ent(struct rk_option *opt, int map,
   92:                  const char *key, int force)
   93: {
   94:   int c = key[0];
   95:   struct rk_conf_ent *tab = NULL;
   96:   struct rk_conf_ent *sym = NULL;
   97: 
   98:   if (c == 0) {
   99:     return NULL;
  100:   }
  101: 
  102:   if (map == RKMAP_HIRAGANA) {
  103:     tab = opt->hiragana_symbol;
  104:   }
  105:   if (map == RKMAP_KATAKANA) {
  106:     tab = opt->katakana_symbol;
  107:   }
  108:   if (map == RKMAP_HANKAKU_KANA) {
  109:     tab = opt->hankaku_kana_symbol;
  110:   }
  111:   if (!tab) {
  112:     return NULL;
  113:   }
  114:   if (strlen(key) == 1) {
  115:     sym = &tab[c];
  116:   } else {
  117:     /* 2文字以上 */
  118:     for (sym = tab[c].next; sym; sym = sym->next) {
  119:       if (!strcmp(sym->lhs, key)) {
  120:         break;
  121:       }
  122:     }
  123:   }
  124:   if (!sym && force) {
  125:     /* メモリ確保してつなぐ */
  126:     sym = malloc(sizeof(struct rk_conf_ent));
  127:     sym->rhs = NULL;
  128:     sym->lhs = NULL;
  129:     sym->next = tab[c].next;
  130:     tab[c].next = sym;
  131:   }
  132:   if (sym && !sym->lhs) {
  133:     sym->lhs = strdup(key);
  134:   }
  135:   return sym;
  136: }
  137: 
  138: /*
  139:  * opt 変更対象のoption
  140:  * map RKMAP_*
  141:  * from 変換もとの文字
  142:  * to 変換先の文字列
  143:  * follow follow集合
  144:  */
  145: int
  146: anthy_input_do_edit_rk_option(struct rk_option* opt, int map, 
  147:                               const char* from, const char* to, const char *follow)
  148: {
  149:   struct rk_conf_ent *tab;
  150:   (void)follow;
  151: 
  152:   tab = find_rk_conf_ent(opt, map, from, 1);
  153:   if (!tab) {
  154:     return -1;
  155:   }
  156: 
  157:   if (tab->rhs) {
  158:     free(tab->rhs);
  159:   }
  160:   if (to == NULL) {
  161:     tab->rhs = NULL;
  162:   } else {
  163:     tab->rhs = strdup(to);
  164:   }
  165:   return 0;
  166: }
  167: 
  168: static void
  169: free_rk_conf_ent(struct rk_conf_ent *e)
  170: {
  171:   if (e->lhs) {
  172:     free(e->lhs);
  173:     e->lhs = NULL;
  174:   }
  175:   if (e->rhs) {
  176:     free(e->rhs);
  177:     e->rhs = NULL;
  178:   }
  179:   e->next = NULL;
  180: }
  181: 
  182: int
  183: anthy_input_do_clear_rk_option(struct rk_option* opt,
  184:                                int use_default)
  185: {
  186:   int i;
  187: 
  188:   opt->enable_default = use_default;
  189:   for (i = 0; i < 128; i++) {
  190:     /* 各文字に対して */
  191:     struct rk_conf_ent *tab, *tmp;
  192:     /* ひらがなのリストを解放 */
  193:     for (tab = opt->hiragana_symbol[i].next; tab;) {
  194:       tmp = tab;
  195:       tab = tab->next;
  196:       free_rk_conf_ent(tmp);
  197:       free(tmp);
  198:     }
  199:     /* カタカナのリストを解放 */
  200:     for (tab = opt->katakana_symbol[i].next; tab;) {
  201:       tmp = tab;
  202:       tab = tab->next;
  203:       free_rk_conf_ent(tmp);
  204:       free(tmp);
  205:     }
  206:     /* 先頭の一文字のエントリも忘れずに解放 */
  207:     free_rk_conf_ent(&opt->katakana_symbol[i]);
  208:     free_rk_conf_ent(&opt->hiragana_symbol[i]);
  209:   }
  210:   return 0;
  211: }
  212: 
  213: int
  214: anthy_input_do_edit_toggle_option(struct rk_option* opt,
  215:                                   char toggle)
  216: {
  217:   opt->toggle = toggle;
  218:   return 0;
  219: }
  220: 
  221: static void
  222: rkrule_set(struct rk_rule* r,
  223:            const char* lhs, const char* rhs, const char* follow)
  224: {
  225:   r->lhs = lhs;
  226:   r->rhs = rhs;
  227:   r->follow = follow;
  228: }
  229: 
  230: struct rk_map*
  231: make_rkmap_ascii(struct rk_option* opt)
  232: {
  233:   struct rk_rule var_part[130];
  234:   struct rk_rule* complete_rules;
  235:   struct rk_map* map;
  236:   struct rk_rule* p;
  237:   char work[2*128];
  238:   char* w;
  239:   int c;
  240:   
  241:   (void)opt;
  242:   p = var_part;
  243:   w = work;
  244:   for (c = 0; c < 128; c++) {
  245:     if (rk_default_symbol[c]) {
  246:       w[0] = c;
  247:       w[1] = '\0';
  248:       rkrule_set(p++, w, w, NULL);
  249:       w += 2;
  250:     }
  251:   }
  252:   p->lhs = NULL;
  253: 
  254:   complete_rules = rk_merge_rules(rk_rule_alphabet, var_part);
  255:   map = rk_map_create(complete_rules);
  256:   rk_rules_free(complete_rules);
  257: 
  258:   return map;
  259: }
  260: 
  261: struct rk_map*
  262: make_rkmap_wascii(struct rk_option* opt)
  263: {
  264:   (void)opt;
  265:   return rk_map_create(rk_rule_walphabet);
  266: }
  267: 
  268: struct rk_map*
  269: make_rkmap_shiftascii(struct rk_option* opt)
  270: {
  271:   struct rk_rule var_part[130];
  272:   struct rk_rule* complete_rules;
  273:   struct rk_map* map;
  274:   struct rk_rule* p;
  275:   char work[2*128 + 3];
  276:   char* w;
  277:   int c;
  278:   int toggle_char = opt->toggle;
  279:   
  280:   p = var_part;
  281:   w = work;
  282:   for (c = 0; c < 128; c++) {
  283:     if (rk_default_symbol[c]) {
  284:       if (c == toggle_char) {
  285:         /* トグルする文字の場合 */
  286:         w[0] = c;
  287:         w[1] = '\0';
  288:         rkrule_set(p++, w, "\xff" "o", NULL);
  289:         w[2] = c;
  290:         w[3] = c;
  291:         w[4] = '\0';
  292:         rkrule_set(p++, w + 2, w, NULL);
  293:         w += 5;        
  294:       } else {
  295:         /* 普通の文字の場合 */
  296:         w[0] = c;
  297:         w[1] = '\0';
  298:         rkrule_set(p++, w, w, NULL);
  299:         w += 2;
  300:       }
  301:     }
  302:   }
  303:   p->lhs = NULL;
  304: 
  305:   complete_rules = rk_merge_rules(rk_rule_alphabet, var_part);
  306:   map = rk_map_create(complete_rules);
  307:   rk_rules_free(complete_rules);
  308: 
  309:   return map;
  310: }
  311: 
  312: static int
  313: count_rk_rule_ent(struct rk_option *opt, int map_no)
  314: {
  315:   int i , c;
  316:   struct rk_conf_ent *head;
  317:   struct rk_conf_ent *ent;
  318: 
  319:   if (map_no == RKMAP_HIRAGANA) {
  320:     head = opt->hiragana_symbol;
  321:   } else if (map_no == RKMAP_HANKAKU_KANA) {
  322:     head = opt->katakana_symbol;
  323:   } else {
  324:     head = opt->hankaku_kana_symbol;
  325:   }
  326: 
  327:   c = 128;
  328:   for (i = 0; i < 128; i++) {
  329:     for (ent = head[i].next; ent; ent = ent->next) {
  330:       if (ent->lhs) {
  331:         c++;
  332:       }
  333:     }
  334:   }
  335:   return c;
  336: }
  337: 
  338: /*
  339:  * デフォルトのルールとカスタマイズされたルールをマージして
  340:  * rk_mapを作る。
  341:  */
  342: static struct rk_map*
  343: make_rkmap_hirakata(const struct rk_rule* rule,
  344:                     struct rk_option *opt, int map_no)
  345: {
  346:   struct rk_conf_ent *tab;
  347:   struct rk_rule* rk_var_part;
  348:   struct rk_rule* complete_rules;
  349:   struct rk_rule* p;
  350:   struct rk_map* map;
  351:   int toggle = opt->toggle;
  352:   char *work;
  353:   char* w;
  354:   int c;
  355:   int nr_rule;
  356:   char buf[2];
  357: 
  358:   nr_rule = count_rk_rule_ent(opt, map_no);
  359: 
  360:   rk_var_part = alloca(sizeof(struct rk_rule) *(nr_rule + 2));
  361:   work = alloca(2*128 + 8);
  362:   p = rk_var_part;
  363:   w = work;
  364: 
  365:   /* 一文字のものをrk_var_partに書き込んでいく */
  366:   /* トグルの場合 */
  367:   buf[0] = toggle;
  368:   buf[1] = 0;
  369:   w[0] = toggle;
  370:   w[1] = '\0';
  371:   w[2] = '\xff';
  372:   w[3] = '0' + RKMAP_SHIFT_ASCII;
  373:   w[4] = '\0';
  374:   rkrule_set(p++, w, w + 2, NULL);
  375:   w[5] = toggle;
  376:   w[6] = toggle;
  377:   w[7] = '\0';
  378:   tab = find_rk_conf_ent(opt, map_no, buf, 0);
  379:   if (tab && tab->rhs) {
  380:     rkrule_set(p++, w + 5, tab->rhs, NULL);
  381:   } else {
  382:     rkrule_set(p++, w + 5, rk_default_symbol[toggle], NULL);
  383:   }
  384:   w += 8;
  385:   /* トグル以外 */
  386:   for (c = 0; c < 128; c++) {
  387:     if (c != toggle) {
  388:       buf[0] = c;
  389:       buf[1] = 0;
  390:       /* 一文字のもの */
  391:       w[0] = c;
  392:       w[1] = '\0';
  393:       tab = find_rk_conf_ent(opt, map_no, buf, 0);
  394:       if (tab && tab->rhs) {
  395:         /* カスタマイズ済のがある */
  396:         rkrule_set(p++, w, tab->rhs, NULL);
  397:       } else if (rk_default_symbol[c]) {
  398:         /* 記号など */
  399:         rkrule_set(p++, w, rk_default_symbol[c], NULL);
  400:       }
  401:       w += 2;
  402:       /* 二文字以上のもの */
  403:       if (tab) {
  404:         for (tab = tab->next; tab; tab = tab->next) {
  405:           rkrule_set(p++, tab->lhs, tab->rhs, NULL);
  406:         }
  407:       }
  408:     }
  409:   }
  410:   p->lhs = NULL;
  411: 
  412:   if (opt->enable_default) {
  413:     complete_rules = rk_merge_rules(rule, rk_var_part);
  414:     map = rk_map_create(complete_rules);
  415:     rk_rules_free(complete_rules);
  416:   } else {
  417:     map = rk_map_create(rk_var_part);
  418:   }
  419: 
  420:   return map;
  421: }
  422: 
  423: struct rk_map*
  424: make_rkmap_hiragana(struct rk_option* opt)
  425: {
  426:   return make_rkmap_hirakata(rk_rule_hiragana,
  427:                              opt, RKMAP_HIRAGANA);
  428: }
  429: 
  430: struct rk_map*
  431: make_rkmap_katakana(struct rk_option* opt)
  432: {
  433:   return make_rkmap_hirakata(rk_rule_katakana,
  434:                              opt, RKMAP_KATAKANA);
  435: }
  436: 
  437: struct rk_map *
  438: make_rkmap_hankaku_kana(struct rk_option *opt)
  439: {
  440:   return make_rkmap_hirakata(rk_rule_hankaku_kana,
  441:                              opt, RKMAP_HANKAKU_KANA);
  442: }
Syntax (Markdown)