
1: /* 2: * 標準入出力でコマンドを受けたり,変換結果を送るなどの通信を 3: * アプリケーション(おもにEmacs)と行うことにより,アプリケーションに 4: * Anthyによる入力機能を容易かつ安全に追加できる. 5: * 6: * Funded by IPA未踏ソフトウェア創造事業 2002 2/26 7: * Copyright (C) 2001-2002 UGAWA Tomoharu 8: * Copyright (C) 2002-2004 TABATA Yusuke, 9: */ 10: /* 11: * *マルチコンテキストの扱いを決めかねている 12: * *入出力にstdioを使うかfdを使うか決めかねている 13: */ 14: 15: #include <sys/time.h> 16: #include <sys/types.h> 17: #include <unistd.h> 18: #include <string.h> 19: #include <stdio.h> 20: #include <stdlib.h> 21: #include <ctype.h> 22: #include <assert.h> 23: 24: #include <anthy/anthy.h> 25: #include <anthy/input.h> 26: 27: #include "rkconv.h" 28: 29: #include <config.h> 30: 31: extern void egg_main(void); 32: 33: /* 何回次候補を押すと候補の列挙を一覧モードに切替えるか? */ 34: #define DEFAULT_ENUM_CAND_LIMIT 3 35: 36: 37: /* キーに対応する定数 */ 38: #define KEY_SHIFT 0x00010000 39: #define KEY_CTRL 0x00020000 40: #define KEY_ALT 0x00040000 41: 42: #define KEY_SPACE ' ' 43: #define KEY_OPAR '(' 44: #define KEY_CPAR ')' 45: 46: #define KEY_ENTER 0x00000100 47: #define KEY_DELETE 0x00000200 48: #define KEY_LEFT 0x00000300 49: #define KEY_RIGHT 0x00000400 50: #define KEY_ESC 0x00000500 51: #define KEY_BACKSPACE 0x00000600 52: #define KEY_UP 0x00000700 53: #define KEY_DOWN 0x00000800 54: 55: #define KEY_CTRL_A (KEY_CTRL | 'A') 56: #define KEY_CTRL_E (KEY_CTRL | 'E') 57: #define KEY_CTRL_J (KEY_CTRL | 'J') 58: #define KEY_CTRL_K (KEY_CTRL | 'K') 59: #define KEY_CTRL_H (KEY_CTRL | 'H') 60: #define KEY_CTRL_D (KEY_CTRL | 'D') 61: #define KEY_SHIFT_LEFT (KEY_SHIFT | KEY_LEFT) 62: #define KEY_SHIFT_RIGHT (KEY_SHIFT | KEY_RIGHT) 63: 64: #define BUF_GROW_SIZE 4096 65: 66: #define MAX(a,b) ((a) > (b) ? (a) : (b)) 67: 68: 69: /* 70: * コマンドにはキーが押されたことを示す普通のコマンドと 71: * 高水準な命令のハイレベルコマンドがある. 72: */ 73: enum { 74: /* ハイレベルコマンド */ 75: CMDH_IGNORE_ICTXT, CMDH_GETPREEDIT, CMDH_SELECT_CONTEXT, 76: CMDH_RELEASE_CONTEXT, CMDH_MAP_EDIT, CMDH_MAP_SELECT, 77: CMDH_GET_CANDIDATE, CMDH_SELECT_CANDIDATE, CMDH_CHANGE_TOGGLE, 78: CMDH_MAP_CLEAR, CMDH_SET_BREAK_INTO_ROMAN, 79: CMDH_SET_PREEDIT_MODE, CMDH_PRINT_CONTEXT, 80: 81: /* キーコマンド */ 82: CMD_SPACE = 1000, 83: CMD_ENTER, 84: CMD_BACKSPACE, 85: CMD_DELETE, 86: CMD_UP, 87: CMD_ESC, 88: CMD_SHIFTARROW, 89: CMD_ARROW, 90: CMD_KEY, 91: CMD_GOBOL, 92: CMD_GOEOL, 93: CMD_CUT 94: }; 95: 96: struct high_level_command_type { 97: const char* name; 98: int cmd; 99: int n_arg; 100: int opt_arg; 101: } high_level_command_type[] = { 102: /* コンテキストの情報を表示する */ 103: {"PRINT_CONTEXT", CMDH_PRINT_CONTEXT, 0, 0}, 104: /* トグルに使うキーを変更する */ 105: {"CHANGE_TOGGLE", CMDH_CHANGE_TOGGLE, 1, 0}, 106: /* コンテキストを選択する */ 107: {"SELECT_CONTEXT", CMDH_SELECT_CONTEXT, 1, 0}, 108: {"RELEASE_CONTEXT", CMDH_RELEASE_CONTEXT, 0, 0}, 109: {"MAP_CLEAR", CMDH_MAP_CLEAR, 1, 0}, 110: {"MAP_EDIT", CMDH_MAP_EDIT, 3, 0}, 111: {"MAP_SELECT", CMDH_MAP_SELECT, 1, 0}, 112: {"GET_CANDIDATE", CMDH_GET_CANDIDATE, 1, 0}, 113: {"SELECT_CANDIDATE", CMDH_SELECT_CANDIDATE, 1, 0}, 114: /* バックスペースでローマ字に戻る */ 115: {"BREAK_INTO_ROMAN", CMDH_SET_BREAK_INTO_ROMAN, 1, 0}, 116: /**/ 117: {"SET_PREEDIT_MODE", CMDH_SET_PREEDIT_MODE, 1, 0}, 118: /**/ 119: {NULL, -1, 0, 0} 120: };guest: anthy/9100e/src-util/agent.c:96-120 on Fri Feb 29 19:14:21 +0900 2008121: 122: struct command { 123: int cmd; 124: char** arg; 125: int n_arg; 126: struct command* next; 127: }; 128: 129: struct connection { 130: char* rbuf; 131: int n_rbuf; 132: int s_rbuf; 133: int rfd; 134: 135: char* wbuf; 136: int n_wbuf; 137: int s_wbuf; 138: int wfd; 139: }; 140: 141: static void send_error(void); 142: 143: static struct connection* conn; 144: static struct anthy_input_config* config; 145: static struct command* command_queue; 146: static int daemon_sock = -1; 147: static int anonymous; 148: static int egg; 149: static char *personality; 150: int use_utf8; 151: 152: static char * 153: encode_command_arg(char *a) 154: { 155: int i, j, len; 156: char *s; 157: 158: len = strlen(a); 159: s = malloc(len + 1); 160: for(i = 0,j = 0; i < len; i++) { 161: if (a[i] != '\\') { 162: s[j] = a[i]; 163: j++; 164: continue; 165: } 166: /* バックスラッシュ */ 167: i++; 168: switch (a[i]) { 169: case 0: 170: case '\\': 171: s[j] = '\\'; 172: j++; 173: break; 174: case '\"': 175: s[j] = '\"'; 176: j++; 177: break; 178: case 'X': 179: { 180: char buf[5]; 181: unsigned char *p; 182: int num; 183: /* ToBeDone エラーチェック */ 184: strncpy(buf, &a[i+1], 4); 185: i+= 5; 186: sscanf(buf, "%x", (unsigned int *)&num); 187: p = (unsigned char *)buf; 188: p[0] = num & 255; 189: p[1] = num >> 8; 190: j += sprintf(&s[j], "%c%c", buf[1] , buf[0]); 191: } 192: break; 193: } 194: } 195: s[j] = 0; 196: 197: return s; 198: } 199: 200: static int 201: ensure_buffer(char** buf, int* size, int to_size) 202: { 203: if (*size < to_size) { 204: *buf = (char*) realloc(*buf, to_size); 205: if (*buf == NULL) { 206: return -1; 207: } 208: *size = to_size; 209: } 210: return 0; 211: } 212: 213: static void 214: kill_connection(struct connection* conn) 215: { 216: (void) conn; 217: exit(0); 218: } 219: 220: static struct command * 221: make_command0(int no) 222: { 223: struct command* cmd; 224: 225: cmd = (struct command*) malloc(sizeof(struct command)); 226: cmd->cmd = no; 227: cmd->n_arg = 0; 228: cmd->arg = NULL; 229: cmd->next = NULL; 230: 231: return cmd; 232: } 233: 234: static struct command * 235: make_command1(int no, const char* arg1) 236: { 237: struct command* cmd; 238: 239: cmd = (struct command*) malloc(sizeof(struct command)); 240: cmd->cmd = no; 241: cmd->n_arg = 1; 242: cmd->arg = (char**) malloc(sizeof(char*) * 1); 243: cmd->arg[0] = strdup(arg1); 244: cmd->next = NULL; 245: 246: return cmd; 247: } 248: 249: static struct key_name_table { 250: const char* name; 251: int code; 252: int is_modifier; 253: } key_name_table[] = { 254: {"shift", KEY_SHIFT, 1}, 255: {"ctrl", KEY_CTRL, 1}, 256: {"alt", KEY_ALT, 1}, 257: 258: {"space", KEY_SPACE, 0}, 259: {"opar", KEY_OPAR, 0}, 260: {"cpar", KEY_CPAR, 0}, 261: {"enter", KEY_ENTER, 0}, 262: {"esc", KEY_ESC, 0}, 263: {"backspace", KEY_BACKSPACE, 0}, 264: {"delete", KEY_DELETE, 0}, 265: {"left", KEY_LEFT, 0}, 266: {"right", KEY_RIGHT, 0}, 267: {"up", KEY_UP, 0}, 268: 269: {NULL, 0, 0} 270: }; 271: 272: /* 273: * エンコードされたキーの情報を取得する 274: */ 275: static int 276: read_encoded_key(char** buf) 277: { 278: char* p; 279: char* str; 280: 281: int key = 0; 282: 283: /* 閉じ括弧を探す */ 284: for (p = *buf + 1; *p; p++) { 285: if (*p == ')') { 286: break; 287: } 288: } 289: 290: if (*p == '\0') { 291: *buf = p; 292: return '\0'; 293: } 294: 295: str = *buf + 1; 296: *p = '\0'; 297: *buf = p + 1; 298: 299: p = strtok(str, " \t\r"); 300: if (!p) { 301: return '\0'; 302: } 303: 304: do { 305: if (p[1] == '\0') { 306: return key | *p; 307: } else { 308: struct key_name_table* e; 309: 310: for (e = key_name_table; e->name; e++) { 311: if (strcmp(e->name, p) == 0) { 312: key |= e->code; 313: if (e->is_modifier == 0) { 314: return key; 315: } 316: } 317: } 318: } 319: } while((p = strtok(NULL, " \t\r"))); 320: 321: return '\0'; 322: } 323: 324: static struct high_level_command_type * 325: find_command_type(char *str) 326: { 327: struct high_level_command_type* cmdn; 328: for (cmdn = high_level_command_type; cmdn->name; cmdn++) { 329: if (!strcmp(str, cmdn->name)) { 330: return cmdn; 331: } 332: } 333: return NULL; 334: } 335: 336: /* ハイレベルコマンドをパースする */ 337: static struct command * 338: make_hl_command(char *buf) 339: { 340: /* high-level command */ 341: struct high_level_command_type* cmdn; 342: struct command* cmd = NULL; 343: char* p; 344: int i; 345: 346: /* コマンドの種類を調べる */ 347: p = strtok(buf, " \t\r"); 348: if (!p) { 349: return NULL; 350: } 351: cmdn = find_command_type(p); 352: if (!cmdn) { 353: return NULL; 354: } 355: 356: /* コマンドを作る */ 357: cmd = (struct command*) malloc(sizeof(struct command)); 358: cmd->cmd = cmdn->cmd; 359: cmd->n_arg = cmdn->n_arg; 360: if (cmd->n_arg > 0) { 361: cmd->arg = (char**) malloc(sizeof(char*) * cmd->n_arg); 362: } else { 363: cmd->arg = NULL; 364: } 365: for (i = 0; i < cmd->n_arg; i++) { 366: p = strtok(NULL, " \t\r"); 367: if (!p) { 368: while (i-- > 0) 369: free(cmd->arg[i]); 370: free(cmd->arg); 371: free(cmd); 372: return NULL; 373: } 374: cmd->arg[i] = encode_command_arg(p); 375: } 376: while ((p = strtok(NULL, " \t\r"))) { 377: if (!p) { 378: break; 379: } 380: cmd->n_arg++; 381: cmd->arg = (char**) realloc(cmd->arg, sizeof(char*) * cmd->n_arg); 382: cmd->arg[cmd->n_arg - 1] = encode_command_arg(p); 383: } 384: cmd->next = NULL; 385: return cmd; 386: } 387: 388: /* 普通のコマンドをパースする */ 389: static struct command * 390: make_ll_command(char *buf) 391: { 392: struct command* cmd_head = NULL; 393: struct command* cmd = NULL; 394: char* p; 395: 396: for (p = buf; *p; ) { 397: struct command* cmd0 = NULL; 398: int c; 399: 400: if (isspace((int)(unsigned char) *p)) { 401: p++; 402: continue; 403: } else if (*p == '(') { 404: c = read_encoded_key(&p); 405: } else { 406: c = *p++; 407: } 408: 409: switch (c) { 410: case '\0': 411: break; 412: case KEY_SPACE: 413: cmd0 = make_command0(CMD_SPACE); 414: break; 415: case KEY_CTRL_J: 416: case KEY_ENTER: 417: case KEY_DOWN: 418: cmd0 = make_command0(CMD_ENTER); 419: break; 420: case KEY_BACKSPACE: 421: case KEY_CTRL_H: 422: cmd0 = make_command0(CMD_BACKSPACE); 423: break; 424: case KEY_DELETE: 425: case KEY_CTRL_D: 426: cmd0 = make_command0(CMD_DELETE); 427: break; 428: case KEY_SHIFT_LEFT: 429: cmd0 = make_command1(CMD_SHIFTARROW, "-1"); 430: break; 431: case KEY_SHIFT_RIGHT: 432: cmd0 = make_command1(CMD_SHIFTARROW, "1"); 433: break; 434: case KEY_LEFT: 435: cmd0 = make_command1(CMD_ARROW, "-1"); 436: break; 437: case KEY_RIGHT: 438: cmd0 = make_command1(CMD_ARROW, "1"); 439: break; 440: case KEY_UP: 441: cmd0 = make_command0(CMD_UP); 442: break; 443: case KEY_ESC: 444: cmd0 = make_command0(CMD_ESC); 445: break; 446: case KEY_CTRL_A: 447: cmd0 = make_command0(CMD_GOBOL); 448: break; 449: case KEY_CTRL_E: 450: cmd0 = make_command0(CMD_GOEOL); 451: break; 452: case KEY_CTRL_K: 453: cmd0 = make_command0(CMD_CUT); 454: break; 455: default: 456: if ((c & 0xffffff80) == 0) { 457: /* ASCII文字 */ 458: char str[2]; 459: 460: str[0] = (char)c; 461: str[1] = '\0'; 462: /* cmd_key */ 463: cmd0 = make_command1(CMD_KEY, str); 464: } 465: break; 466: } 467: 468: if (cmd0) { 469: if (cmd) { 470: cmd->next = cmd0; 471: } else { 472: cmd_head = cmd0; 473: } 474: cmd = cmd0; 475: } 476: } /* for (p) */ 477: 478: if (cmd) { 479: cmd->next = make_command0(CMDH_GETPREEDIT); 480: } else { 481: cmd_head = make_command0(CMDH_GETPREEDIT); 482: } 483: 484: return cmd_head; 485: } 486: 487: static struct command* 488: make_command(char* buf) 489: { 490: 491: if (*buf == ' ') { 492: /* ハイレベルコマンド */ 493: struct command *cmd; 494: cmd = make_hl_command(buf); 495: if (!cmd) { 496: send_error(); 497: } 498: return cmd; 499: } 500: return make_ll_command(buf); 501: } 502: 503: static int 504: proc_connection(void) 505: { 506: fd_set rfds; 507: fd_set wfds; 508: int max_fd; 509: int ret; 510: 511: max_fd = -1; 512: FD_ZERO(&rfds); 513: FD_ZERO(&wfds); 514: if (daemon_sock >= 0) { 515: max_fd = daemon_sock; 516: FD_SET(daemon_sock, &rfds); 517: } 518: max_fd = MAX(conn->rfd, max_fd); 519: FD_SET(conn->rfd, &rfds); 520: if (conn->n_wbuf > 0) { 521: max_fd = MAX(conn->wfd, max_fd); 522: FD_SET(conn->wfd, &wfds); 523: } 524: 525: if (max_fd == -1) 526: return -1; 527: 528: ret = select(max_fd + 1, &rfds, &wfds, NULL, NULL); 529: if (ret < 0) { 530: return -1; 531: } 532: 533: if (conn->n_wbuf > 0 && FD_ISSET(conn->wfd, &wfds)) { 534: ret = write(conn->wfd, conn->wbuf, conn->n_wbuf); 535: if (ret <= 0) { 536: kill_connection (conn); 537: } else { 538: conn->n_wbuf -= ret; 539: if (conn->n_wbuf > 0) { 540: memmove(conn->wbuf, conn->wbuf + ret, conn->n_wbuf); 541: } 542: } 543: } 544: 545: if (FD_ISSET(conn->rfd, &rfds)) { 546: ensure_buffer(&conn->rbuf, &conn->s_rbuf, 547: conn->n_rbuf + BUF_GROW_SIZE); 548: ret = read(conn->rfd, 549: conn->rbuf + conn->n_rbuf, conn->s_rbuf - conn->n_rbuf); 550: if (ret <= 0) { 551: kill_connection (conn); 552: } else { 553: conn->n_rbuf += ret; 554: } 555: } 556: return 0; 557: } 558: 559: static struct command * 560: read_command(void) 561: { 562: struct command* cmd; 563: 564: AGAIN: 565: if (command_queue != NULL) { 566: cmd = command_queue; 567: command_queue = cmd->next; 568: return cmd; 569: } 570: 571: while (1) { 572: 573: char* p; 574: for (p = conn->rbuf; p < conn->rbuf + conn->n_rbuf; p++) { 575: if (*p == '\n') { 576: *p = '\0'; 577: cmd = make_command(conn->rbuf); 578:ハイレベルコマンドの文字列定義