2 * Copyright (C) 2002 The Free Software Initiative of Japan
7 * ANTHY Low Level Agent
14 #include <anthy/anthy.h>
20 * S -- open -> [ ] -- new ----> [ ] -- convert --> [ ] --> get_candidates
21 * <- close -- <- release - <-- commit -- --> resize_segment
22 * <-- cancel -- --> select_candidate
27 struct anthy_context *ac;
30 int removed, inserted;
35 #define MAX_CONTEXT 16
36 static struct context contexts[MAX_CONTEXT];
40 #define INITIAL_BUFLEN 512
41 #define INITIAL_SELLEN 128
44 * Returns -1 on error.
45 * Returns >= 0 on success, and the number is context descriptor.
52 for (i = 0; i < MAX_CONTEXT; i++)
53 if (contexts[i].buflen == 0) { /* Found free one */
54 struct context *c = &contexts[i];
56 if ((c->buf = (unsigned char *)malloc (INITIAL_BUFLEN)) == NULL)
59 if ((c->selection = (int *)malloc (INITIAL_SELLEN)) == NULL) {
65 if ((c->ac = anthy_create_context ()) == NULL) {
73 anthy_context_set_encoding(c->ac, ANTHY_UTF8_ENCODING);
76 c->buflen = INITIAL_BUFLEN;
77 c->sellen = INITIAL_SELLEN;
81 /* No free context to be used */
86 release_context (int c_desc)
88 struct context *c = &contexts[c_desc];
90 anthy_release_context(c->ac);
101 static struct context *
102 c_desc_to_context (int c_desc)
104 return &contexts[c_desc];
108 get_number_of_segments (struct context *c)
110 struct anthy_conv_stat cs;
112 if (anthy_get_stat(c->ac, &cs) < 0)
115 return cs.nr_segment;
119 begin_conversion (struct context *c, const char *input)
123 if (anthy_set_string(c->ac, (char *)input) < 0)
126 seg_num = get_number_of_segments (c);
127 if (seg_num >= c->sellen) {
129 c->selection = realloc (c->selection, c->sellen);
130 if (c->selection == NULL) { /* Fatal */
136 for (i = 0; i < seg_num; i++)
143 end_conversion (struct context *c, int cancel)
150 n = get_number_of_segments (c);
151 for (seg_num = 0; seg_num < n; seg_num++) {
152 can_num = c->selection[seg_num];
153 anthy_commit_segment(c->ac, seg_num, can_num);
161 get_segment_number_of_candidates (struct context *c, int seg_num)
163 struct anthy_segment_stat ss;
165 if (anthy_get_segment_stat (c->ac, seg_num, &ss) != 0)
168 return ss.nr_candidate;
171 static const unsigned char *
172 get_segment_candidate (struct context *c, int seg_num, int cand_num)
177 len = anthy_get_segment (c->ac, seg_num, cand_num,
178 (char *)c->buf, c->buflen);
187 c->buf = realloc (c->buf, c->buflen);
188 if (c->buf == NULL) { /* Fatal */
195 static const unsigned char *
196 get_segment_yomi (struct context *c, int seg_num)
198 return get_segment_candidate (c, seg_num, NTH_UNCONVERTED_CANDIDATE);
201 static const unsigned char *
202 get_segment_converted (struct context *c, int seg_num)
204 return get_segment_candidate (c, seg_num, 0);
208 resize_segment (struct context *c, int seg_num, int inc_dec)
211 struct anthy_conv_stat cs;
213 if (anthy_get_stat(c->ac, &cs) < 0)
216 /* Replace all segments after SEG_NUM */
217 c->removed = cs.nr_segment - seg_num;
218 anthy_resize_segment(c->ac, seg_num, inc_dec?-1:1);
219 if (anthy_get_stat(c->ac, &cs) < 0)
221 c->inserted = cs.nr_segment - seg_num;
223 if (cs.nr_segment >= c->sellen) {
225 c->selection = realloc (c->selection, c->sellen);
226 if (c->selection == NULL) { /* Fatal */
231 for (i = seg_num; i < cs.nr_segment; i++)
237 /* Only valid after call of resize_segment or select_candidate */
239 get_number_of_segments_removed (struct context *c, int seg_num)
245 /* Only valid after call of resize_segment or select_candidate */
247 get_number_of_segments_inserted (struct context *c, int seg_num)
254 select_candidate (struct context *c, int seg_num, int can_num)
257 * Anthy does not have capability to affect the result of selection
264 * Record, but not call anthy_commit_segment.
266 c->selection[seg_num] = can_num;
274 const char *options = "";
276 printf ("Anthy (Version %s) [%s] : Nice to meet you.\r\n", VERSION,
282 #define ERROR_CODE_UNKNOWN 400
283 #define ERROR_CODE_UNSUPPOTED 401
288 printf ("-ERR %d Unknown command.\r\n", ERROR_CODE_UNKNOWN);
294 do_commit (const char *line)
298 int c_desc, cancel, r;
300 c_desc = strtol (line+7, &p, 10);
301 c = c_desc_to_context (c_desc);
302 cancel = strtol (p+1, &p, 10);
303 r = end_conversion (c, cancel);
305 printf ("-ERR %d commit failed.\r\n", -r);
313 output_segments (struct context *c, int seg_num, int removed, int inserted)
317 printf ("+DATA %d %d %d\r\n", seg_num, removed, inserted);
318 for (i = seg_num; i < seg_num + inserted; i++) {
321 nc = get_segment_number_of_candidates (c, i);
323 printf ("%s ", get_segment_converted (c, i));
324 printf ("%s\r\n", get_segment_yomi (c, i));
330 do_convert (const char *line)
336 c_desc = strtol (line+8, &p, 10);
337 c = c_desc_to_context (c_desc);
338 r = begin_conversion (c, p+1);
340 printf ("-ERR %d convert failed.\r\n", -r);
343 int n = get_number_of_segments (c);
344 output_segments (c, 0, 0, n);
352 do_get_candidates (const char *line)
356 int c_desc, seg_num, cand_offset, max_cands;
359 c_desc = strtol (line+15, &p, 10);
360 seg_num = strtol (p+1, &p, 10);
361 cand_offset = strtol (p+1, &p, 10);
362 max_cands = strtol (p+1, &p, 10);
364 c = c_desc_to_context (c_desc);
365 nc = get_segment_number_of_candidates (c, seg_num);
367 max = cand_offset + max_cands;
368 if (nc < cand_offset + max_cands)
371 printf ("+DATA %d %d\r\n", cand_offset, max);
372 for (i = cand_offset; i < max; i++)
373 printf ("%s\r\n", get_segment_candidate (c, seg_num, i));
381 do_new_context (const char *line)
385 /* XXX: Should check arguments */
386 if (strncmp (" INPUT=#18 OUTPUT=#18", line+11, 20) != 0) {
387 printf ("-ERR %d unsupported context\r\n", ERROR_CODE_UNSUPPOTED);
393 printf ("-ERR %d new context failed.\r\n", -r);
395 printf ("+OK %d\r\n", r);
402 do_release_context (const char *line)
408 c_desc = strtol (line+15, &p, 10);
409 r = release_context (c_desc);
411 printf ("-ERR %d release context failed.\r\n", -r);
420 do_resize_segment (const char *line)
424 int c_desc, seg_num, inc_dec, r;
426 c_desc = strtol (line+15, &p, 10);
427 seg_num = strtol (p+1, &p, 10);
428 inc_dec= strtol (p+1, &p, 10);
429 c = c_desc_to_context (c_desc);
430 r = resize_segment (c, seg_num, inc_dec);
433 printf ("-ERR %d resize failed.\r\n", -r);
435 int removed, inserted;
438 removed = get_number_of_segments_removed (c, seg_num);
439 inserted = get_number_of_segments_inserted (c, seg_num);
441 output_segments (c, seg_num, removed, inserted);
449 do_select_candidate (const char *line)
453 int c_desc, seg_num, cand_num, r;
455 c_desc = strtol (line+17, &p, 10);
456 seg_num = strtol (p+1, &p, 10);
457 cand_num = strtol (p+1, &p, 10);
458 c = c_desc_to_context (c_desc);
459 r = select_candidate (c, seg_num, cand_num);
462 printf ("-ERR %d select failed.\r\n", -r);
467 removed = get_number_of_segments_removed (c, seg_num);
472 int inserted = get_number_of_segments_inserted (c, seg_num);
474 output_segments (c, seg_num, removed, inserted);
483 do_quit (const char *line)
489 struct dispatch_table {
492 int (*func)(const char *line);
495 static struct dispatch_table dt[] = {
496 { "COMMIT", 6, do_commit },
497 { "CONVERT", 7, do_convert },
498 { "GET-CANDIDATES", 14, do_get_candidates },
499 { "NEW-CONTEXT", 11, do_new_context },
500 { "QUIT", 4, do_quit },
501 { "RELEASE-CONTEXT", 15, do_release_context },
502 { "RESIZE-SEGMENT", 14, do_resize_segment },
503 { "SELECT-CANDIDATE", 16, do_select_candidate },
507 dt_cmp (const char *line, struct dispatch_table *d)
509 return strncmp (line, d->command, d->size);
513 static char line[MAX_LINE];
515 void egg_main (void);
526 struct dispatch_table *d;
528 s = fgets (line, MAX_LINE, stdin);
530 fprintf (stderr, "null input\n");
533 if ((p = (char *)memchr(s, '\n', MAX_LINE)) == NULL) {
534 fprintf (stderr, "no newline\n");
537 if (p > s && *(p-1) == '\r')
541 d = (struct dispatch_table *)
543 sizeof (dt) / sizeof (struct dispatch_table),
544 sizeof (struct dispatch_table),
545 (int (*)(const void *, const void *))dt_cmp);