Fix memory leak issues
[platform/core/uifw/anthy.git] / src-util / agent.c
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 };
121
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         conn->n_rbuf -= p + 1 - conn->rbuf;
579         memmove(conn->rbuf, p + 1, conn->n_rbuf);
580         if (cmd) {
581           command_queue = cmd;
582           goto AGAIN;
583         }
584       }
585     }
586
587     if (proc_connection() == -1) {
588       return NULL;
589     }
590
591   }
592 }
593
594 static void
595 write_reply(const char* buf)
596 {
597   printf("%s", buf);
598 }
599
600 static void
601 send_error(void)
602 {
603   write_reply("ERR\r\n");
604 }
605
606 static void
607 send_ok(void)
608 {
609   write_reply("OK\r\n");
610 }
611
612 static void
613 send_number10(int num)
614 {
615   char buf[20];
616
617   sprintf(buf, "%d", num);
618   write_reply(buf);
619 }
620
621 static void
622 send_string(const char* str)
623 {
624   write_reply(str);
625 }
626
627 static void
628 send_quote_string(const char* str)
629 {
630   char buf[20]; /* ¤³¤Î¤°¤é¤¤¤¢¤ì¤ÐÂçÄñÂç¾æÉ× */
631   const char *p;
632   char *q, *end;
633
634   end = buf + sizeof(buf) - 2;
635   for (q = buf, p = str; *p;) {
636     if (q >= end) {
637       *q = '\0';
638       write_reply(buf);
639       q = buf;
640     }
641
642     switch (*p) {
643     case '\"':
644     case '\\':
645       *q++ = '\\';
646       break;
647     default:
648       break;
649     }
650     
651     *q++ = *p++;
652   }
653   *q = '\0';
654   write_reply(buf);
655 }
656
657 static void
658 send_preedit(struct anthy_input_preedit* pedit)
659 {
660   send_string("(");
661   send_number10(pedit->state);
662
663   if (pedit->commit != NULL) {
664     send_string(" ((COMMIT) \"");
665     send_quote_string(pedit->commit);
666     send_string("\")");
667   }
668
669   if (pedit->cut_buf != NULL) {
670     send_string(" ((CUTBUF) \"");
671     send_quote_string(pedit->cut_buf);
672     send_string("\")");
673   }
674
675   switch (pedit->state) {
676   case ANTHY_INPUT_ST_OFF:
677   case ANTHY_INPUT_ST_NONE:
678     break;
679   case ANTHY_INPUT_ST_EDIT:
680   case ANTHY_INPUT_ST_CONV:
681   case ANTHY_INPUT_ST_CSEG:
682     {
683       struct anthy_input_segment* seg;
684
685       for (seg = pedit->segment; seg; seg = seg->next) {
686         if (seg->str == NULL) {
687           if (seg->flag & ANTHY_INPUT_SF_CURSOR)
688             send_string(" cursor");
689         } else {
690           if (seg->flag & ANTHY_INPUT_SF_CURSOR) {
691             if (seg->flag & ANTHY_INPUT_SF_ENUM)
692               send_string(" ((UL RV ENUM) \"");
693             else if (seg->flag & ANTHY_INPUT_SF_ENUM_REVERSE)
694               send_string(" ((UL RV ENUMR) \"");
695             else
696               send_string(" ((UL RV) \"");
697           } else 
698             send_string(" ((UL) \"");
699           
700           send_quote_string(seg->str);
701           send_string("\" ");
702           send_number10(seg->cand_no);
703           send_string(" ");
704           send_number10(seg->nr_cand);
705           send_string(")");
706         }
707       }
708     }
709     break;
710   }
711           
712   send_string(")\r\n");
713 }
714
715 static void
716 send_single_candidate(struct anthy_input_segment* seg)
717 {
718   send_string("(\"");
719   send_quote_string(seg->str);
720   send_string("\" ");
721   send_number10(seg->cand_no);
722   send_string(" ");
723   send_number10(seg->nr_cand);
724   send_string(")\r\n");
725 }
726
727 static void
728 free_command(struct command* cmd)
729 {
730   int i;
731
732   for (i = 0; i < cmd->n_arg; i++)
733     free(cmd->arg[i]);
734   free(cmd->arg);
735   free(cmd);
736 }
737
738 struct input_context_list {
739   int id;
740   struct anthy_input_context* ictx;
741   struct input_context_list* next;
742 };
743
744 static struct input_context_list* ictx_list = NULL;
745
746 static void
747 new_input_context(int id)
748 {
749   struct input_context_list* ictxl;
750
751   ictxl = 
752     (struct input_context_list*) malloc(sizeof (struct input_context_list));
753   ictxl->id = id;
754   ictxl->ictx = anthy_input_create_context(config);
755   ictxl->next = ictx_list;
756   ictx_list = ictxl;
757 }
758
759 static struct anthy_input_context*
760 get_current_input_context(void)
761 {
762   if (ictx_list == NULL)
763     new_input_context(0);
764
765   return ictx_list->ictx;
766 }
767
768 static void
769 cmdh_get_preedit(struct anthy_input_context* ictx)
770 {
771   struct anthy_input_preedit* pedit;
772
773   pedit = anthy_input_get_preedit(ictx);
774   send_preedit(pedit);
775   anthy_input_free_preedit(pedit);
776 }
777
778 static void
779 cmdh_select_input_context(struct command* cmd)
780 {
781   int id;
782   struct input_context_list** p;
783   
784   id = atoi(cmd->arg[0]);
785   for (p = &ictx_list; *p; p = &(*p)->next) {
786     if ((*p)->id == id) {
787       struct input_context_list* sel;
788       sel = *p;
789       *p = sel->next;
790       sel->next = ictx_list;
791       ictx_list = sel;
792       send_ok();
793       return;
794     }
795   }
796
797   new_input_context(id);
798   send_ok();
799 }
800
801 static void
802 cmdh_release_input_context(struct command* cmd)
803 {
804   struct input_context_list* sel;
805   (void)cmd;
806   if (!ictx_list) {
807       send_ok();
808     return ;
809   }
810   sel = ictx_list;
811   ictx_list = ictx_list->next;
812   anthy_input_free_context(sel->ictx);
813   free(sel);
814   send_ok();
815 }
816
817 static void
818 cmdh_change_toggle(struct command *cmd)
819 {
820   int toggle = cmd->arg[0][0];
821   int ret;
822
823   ret = anthy_input_edit_toggle_config(config, toggle);
824
825   if (ret != 0) {
826     send_error();
827     return;
828   }
829   anthy_input_change_config(config);
830   send_ok();
831 }
832
833 static void
834 cmdh_map_clear(struct command *cmd)
835 {
836   anthy_input_clear_rk_config(config, atoi(cmd->arg[0]));
837   anthy_input_change_config(config);
838   send_ok();
839 }
840
841 static void
842 cmdh_set_break_into_roman(struct command *cmd)
843 {
844   anthy_input_break_into_roman_config(config, atoi(cmd->arg[0]));
845   anthy_input_change_config(config);
846   send_ok();
847 }
848
849 static void
850 cmdh_set_preedit_mode(struct command *cmd)
851 {
852   anthy_input_preedit_mode_config(config, atoi(cmd->arg[0]));
853   anthy_input_change_config(config);
854   send_ok();
855 }
856
857 static void
858 cmdh_map_edit(struct command* cmd)
859 {
860   /* MAP,from,to */
861   int map_no = atoi(cmd->arg[0]);
862   int ret;
863
864   ret = anthy_input_edit_rk_config(config, map_no, 
865                                    cmd->arg[1], cmd->arg[2], NULL);
866
867   if (ret != 0) {
868     send_error();
869     return;
870   }
871   anthy_input_change_config(config);
872   send_ok();
873 }
874
875 static void
876 cmdh_map_select(struct anthy_input_context* ictx,
877                 struct command* cmd)
878 {
879   char* map_name;
880   int map_no;
881
882   map_name = cmd->arg[0];
883   if (strcmp(map_name, "alphabet") == 0)
884     map_no = ANTHY_INPUT_MAP_ALPHABET;
885   else if (strcmp(map_name, "hiragana") == 0)
886     map_no = ANTHY_INPUT_MAP_HIRAGANA;
887   else if (strcmp(map_name, "katakana") == 0)
888     map_no = ANTHY_INPUT_MAP_KATAKANA;
889   else if (strcmp(map_name, "walphabet") == 0)
890     map_no = ANTHY_INPUT_MAP_WALPHABET;
891   else if (strcmp(map_name, "hankaku_kana") == 0)
892     map_no = ANTHY_INPUT_MAP_HANKAKU_KANA;
893   else {
894     send_error();
895     return;
896   }
897
898   anthy_input_map_select(ictx, map_no);
899   send_ok();
900 }
901
902 static void
903 cmdh_get_candidate(struct anthy_input_context* ictx,
904                    struct command* cmd)
905 {
906   struct anthy_input_segment* seg;
907   int cand_no;
908
909   cand_no = atoi(cmd->arg[0]);
910
911   seg = anthy_input_get_candidate(ictx, cand_no);
912   if (seg == NULL)
913     send_error();
914   else {
915     send_single_candidate(seg);
916     anthy_input_free_segment(seg);
917   }
918 }
919
920 static void
921 cmdh_select_candidate(struct anthy_input_context* ictx,
922                       struct command* cmd)
923 {
924   int ret;
925   int cand_no;
926
927   cand_no = atoi(cmd->arg[0]);
928   ret = anthy_input_select_candidate(ictx, cand_no);
929   if (ret < 0) {
930     send_error();
931   } else {
932     cmdh_get_preedit(ictx);
933   }
934 }
935
936 static void
937 cmd_shift_arrow(struct anthy_input_context* ictx,
938                 struct command* cmd)
939 {
940   int lr = atoi(cmd->arg[0]);
941   anthy_input_resize(ictx, lr);
942 }
943
944 static void
945 cmd_arrow(struct anthy_input_context* ictx, struct command* cmd)
946 {
947   int lr = atoi(cmd->arg[0]);
948   anthy_input_move(ictx, lr);
949 }
950
951 static void
952 cmd_key(struct anthy_input_context* ictx, struct command* cmd)
953 {
954   anthy_input_str(ictx, cmd->arg[0]);
955 }
956
957 /*
958  * ¥³¥Þ¥ó¥É¤ò¥Ç¥£¥¹¥Ñ¥Ã¥Á¤¹¤ë
959  */
960 static void
961 dispatch_command(struct anthy_input_context* ictx, 
962                  struct command* cmd)
963 {
964   switch (cmd->cmd) {
965   case CMDH_IGNORE_ICTXT:
966     send_error();
967     break;
968   case CMDH_PRINT_CONTEXT:
969     /* Dirty implementation, would cause corrpution.*/
970     {
971       anthy_context_t ac = anthy_input_get_anthy_context(ictx); 
972       if (ac) {
973         anthy_print_context(ac);
974       }
975     }
976     break;
977   case CMDH_GETPREEDIT:
978     cmdh_get_preedit(ictx);
979     break;
980   case CMDH_SELECT_CONTEXT:
981     cmdh_select_input_context(cmd);
982     break;
983   case CMDH_RELEASE_CONTEXT:
984     cmdh_release_input_context(cmd);
985     break;
986   case CMDH_MAP_EDIT:
987     cmdh_map_edit(cmd);
988     break;
989   case CMDH_CHANGE_TOGGLE:
990     cmdh_change_toggle(cmd);
991     break;
992   case CMDH_MAP_CLEAR:
993     cmdh_map_clear(cmd);
994     break;
995   case CMDH_MAP_SELECT:
996     cmdh_map_select(ictx, cmd);
997     break;
998   case CMDH_GET_CANDIDATE:
999     cmdh_get_candidate(ictx, cmd);
1000     break;
1001   case CMDH_SELECT_CANDIDATE:
1002     cmdh_select_candidate(ictx, cmd);
1003     break;
1004   case CMDH_SET_BREAK_INTO_ROMAN:
1005     cmdh_set_break_into_roman(cmd);
1006     break;
1007   case CMDH_SET_PREEDIT_MODE:
1008     cmdh_set_preedit_mode(cmd);
1009     break;
1010     /* key commands follows */
1011
1012   case CMD_SPACE:
1013     anthy_input_space(ictx);
1014     break;
1015   case CMD_ENTER:
1016     anthy_input_commit(ictx);
1017     break;
1018   case CMD_BACKSPACE:
1019     anthy_input_erase_prev(ictx);
1020     break;
1021   case CMD_DELETE:
1022     anthy_input_erase_next(ictx);
1023     break;
1024   case CMD_UP:
1025     anthy_input_prev_candidate(ictx);
1026     break;
1027   case CMD_ESC:
1028     anthy_input_quit(ictx);
1029     break;
1030   case CMD_SHIFTARROW:
1031     cmd_shift_arrow(ictx, cmd);
1032     break;
1033   case CMD_ARROW:
1034     cmd_arrow(ictx, cmd);
1035     break;
1036   case CMD_KEY:
1037     cmd_key(ictx, cmd);
1038     break;
1039   case CMD_GOBOL:
1040     anthy_input_beginning_of_line(ictx);
1041     break;
1042   case CMD_GOEOL:
1043     anthy_input_end_of_line(ictx);
1044     break;
1045   case CMD_CUT:
1046     anthy_input_cut(ictx);
1047     break;
1048   }
1049 }
1050
1051 static void
1052 main_loop(void)
1053 {
1054   struct anthy_input_context* ictx;
1055   struct command* cmd;
1056
1057   while (1) {
1058     cmd = read_command();
1059     if (!cmd) 
1060       break;
1061     ictx = get_current_input_context();
1062
1063     dispatch_command(ictx, cmd);
1064     fflush(stdout);
1065
1066     free_command(cmd);
1067   }
1068 }
1069
1070 static void
1071 print_version(void)
1072 {
1073   printf(PACKAGE "-agent "VERSION "\n");
1074   exit(0);
1075 }
1076
1077 static void
1078 parse_args(int argc, char **argv)
1079 {
1080   int i;
1081   char *conffile = NULL, *dir = NULL, *dic = NULL;
1082
1083
1084   for (i = 1; i < argc; i++) {
1085     char *str = argv[i];
1086     if (!strcmp("--version", str)) {
1087       print_version();
1088     } else if (!strcmp("--anonymous", str)) {
1089       anonymous = 1;
1090     } else if (!strcmp("--egg", str)) {
1091       egg = 1;
1092     } else if (!strncmp("--personality=", str, 14)) {
1093       personality = &str[14];
1094     } else if (!strcmp("--utf8", str)) {
1095       use_utf8 = 1;
1096     } else if (i < argc - 1) {
1097       char *arg = argv[i+1];
1098       if (!strcmp("--dir", str)) {
1099         dir = arg;
1100         i++;
1101       } else if (!strcmp("--dic", str)) {
1102         dic = arg;
1103         i++;
1104       } else if (!strcmp("--conffile", str)) {
1105         conffile = arg;
1106         i++;
1107       }
1108     }
1109   }
1110   if (conffile) {
1111     anthy_conf_override("CONFFILE", conffile);
1112   }
1113   if (dir) {
1114     anthy_conf_override("ANTHYDIR", dir);
1115   }
1116   if (dic) {
1117     anthy_conf_override("SDIC", dic);
1118   }
1119 }
1120
1121 int
1122 main(int argc, char **argv)
1123 {
1124   parse_args(argc, argv);
1125   if (anthy_input_init()) {
1126     printf("Failed to init anthy\n");
1127     exit(0);
1128   }
1129   if (anonymous) {
1130     anthy_input_set_personality("");
1131   } else if (personality) {
1132     anthy_input_set_personality(personality);
1133   }
1134
1135   if (egg) {
1136     egg_main();
1137     anthy_quit();
1138   } else {
1139     config = anthy_input_create_config();
1140     conn = (struct connection*) malloc(sizeof(struct connection));
1141     conn->rbuf = NULL;
1142     conn->n_rbuf = 0;
1143     conn->s_rbuf = 0;
1144     conn->rfd = 0;
1145     conn->wbuf = NULL;
1146     conn->n_wbuf = 0;
1147     conn->s_wbuf = 0;
1148     conn->wfd = 1;
1149
1150     main_loop();
1151   }
1152   return 0;
1153 }