1 /*
2
3 Copyright (c) 2003-2013 uim Project https://github.com/uim/uim
4
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16 3. Neither the name of authors nor the names of its contributors
17 may be used to endorse or promote products derived from this software
18 without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
24 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 SUCH DAMAGE.
31
32 */
33
34 #include <config.h>
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include <m17n.h>
41 #include "gettext.h"
42 #include "uim.h"
43 #include "uim-scm.h"
44 #include "uim-scm-abbrev.h"
45 #include "uim-util.h"
46 #include "dynlib.h"
47
48 static int m17nlib_ok;
49 static MConverter *converter;
50 static char buffer_for_converter[4096]; /* Currently, if preedit strings or
51 candidate strings over this buffer
52 size, they will simply ignore. */
53
54 static int nr_input_methods;
55 static struct im_ {
56 char *lang;
57 char *name;
58 MInputMethod *im;
59 } *im_array;
60
61 static int nr_input_contexts;
62 static struct ic_ {
63 MInputContext *mic;
64 char **old_candidates; /* FIXME: ugly hack for perfomance... */
65 char **new_candidates; /* FIXME: ugly hack for perfomance... */
66 int nr_candidates;
67 } *ic_array;
68
69 static MInputMethod *im_instance(int nth);
70
71 /* Utility function */
72 static char *
m17nlib_utf8_find_next_char(const char * p)73 m17nlib_utf8_find_next_char(const char *p)
74 {
75 if (*p) {
76 for (++p; (*p & 0xc0) == 0x80; ++p)
77 ;
78 }
79 return (char *)p;
80 }
81
82 static int
unused_ic_id(void)83 unused_ic_id(void)
84 {
85 int i;
86
87 for (i = 0; i < nr_input_contexts; i++) {
88 if (!ic_array[i].mic)
89 return i;
90 }
91
92 ic_array = uim_realloc(ic_array,
93 sizeof(struct ic_) * (nr_input_contexts + 1));
94 ic_array[nr_input_contexts].mic = NULL;
95 nr_input_contexts++;
96
97 return nr_input_contexts - 1;
98 }
99
100 static void
pushback_input_method(MInputMethod * im,char * lang,char * name)101 pushback_input_method(MInputMethod *im, char *lang, char *name)
102 {
103 im_array = uim_realloc(im_array,
104 sizeof(struct im_) * (nr_input_methods + 1));
105 im_array[nr_input_methods].im = im;
106 im_array[nr_input_methods].name = uim_strdup(name);
107 im_array[nr_input_methods].lang = uim_strdup(lang);
108
109 nr_input_methods++;
110 }
111
112 #if 0
113 static void
114 preedit_start_cb(MInputContext *ic, MSymbol command)
115 {
116 fprintf(stderr,"preedit start\n");
117 }
118
119 static void
120 preedit_draw_cb(MInputContext *ic, MSymbol command)
121 {
122
123 }
124
125 static void
126 preedit_done_cb(MInputContext *ic, MSymbol command)
127 {
128 /* fprintf(stderr,"preedit done\n");*/
129 }
130
131 static void
132 status_start_cb(MInputContext *ic, MSymbol command)
133 {
134 /* fprintf(stderr,"status start\n");*/
135 }
136
137 static void
138 status_draw_cb(MInputContext *ic, MSymbol command)
139 {
140 /* fprintf(stderr,"status draw\n"); */
141 }
142
143 static void
144 status_done_cb(MInputContext *ic, MSymbol command)
145 {
146 /* fprintf(stderr,"status done\n");*/
147 }
148
149 static void
150 candidates_start_cb(MInputContext *ic, MSymbol command)
151 {
152 /* fprintf(stderr,"candidates_start\n");*/
153 }
154
155 static void
156 candidates_draw_cb(MInputContext *ic, MSymbol command)
157 {
158 /* fprintf(stderr,"candidate draw\n"); */
159 }
160
161 static void
162 candidates_done_cb(MInputContext *ic, MSymbol command)
163 {
164 /* fprintf(stderr,"candidate done\n"); */
165 }
166
167 static void
168 register_callbacks(void)
169 {
170 /*
171 mplist_add(minput_default_driver.callback_list, Minput_preedit_start, (void *)preedit_start_cb);
172 mplist_add(minput_default_driver.callback_list, Minput_preedit_draw, (void *)preedit_draw_cb);
173 mplist_add(minput_default_driver.callback_list, Minput_preedit_done, (void *)preedit_done_cb);
174 mplist_add(minput_default_driver.callback_list, Minput_status_start, (void *)status_start_cb);
175 mplist_add(minput_default_driver.callback_list, Minput_status_draw, (void *)status_draw_cb);
176 mplist_add(minput_default_driver.callback_list, Minput_status_done, (void *)status_done_cb);
177 mplist_add(minput_default_driver.callback_list, Minput_candidates_start, (void *)candidates_start_cb);
178 mplist_add(minput_default_driver.callback_list, Minput_candidates_draw, (void *)candidates_draw_cb);
179 mplist_add(minput_default_driver.callback_list, Minput_candidates_done, (void *)candidates_done_cb);*/
180 }
181 #endif
182
183 static uim_lisp
init_m17nlib()184 init_m17nlib()
185 {
186 MPlist *imlist, *elm;
187
188 M17N_INIT();
189 nr_input_methods = 0;
190 nr_input_contexts = 0;
191 im_array = NULL;
192 ic_array = NULL;
193
194 imlist = mdatabase_list(msymbol("input-method"), Mnil, Mnil, Mnil);
195
196 if (!imlist) {
197 /* maybe user forgot to install m17n-db */
198 return uim_scm_f();
199 }
200
201 for (elm = imlist; mplist_key(elm) != Mnil; elm = mplist_next(elm)) {
202 MDatabase *mdb;
203 MSymbol *tag, lang, imname;
204 uim_bool is_complete_im;
205
206 mdb = mplist_value(elm);
207 tag = mdatabase_tag(mdb);
208 lang = tag[1];
209 imname = tag[2];
210 is_complete_im = (lang != Mnil && imname != Mnil); /* [uim-ja 30] */
211
212 if (is_complete_im) {
213 /* pass NULL as IM to enable lazy instantiation */
214 pushback_input_method(NULL, msymbol_name(lang), msymbol_name(imname));
215 }
216 }
217 #if 0
218 register_callbacks();
219 #endif
220 m17n_object_unref(imlist);
221 converter = mconv_buffer_converter(msymbol("utf8"), NULL, 0);
222
223 if (!converter)
224 return uim_scm_f();
225
226 m17nlib_ok = 1;
227
228 return uim_scm_t();
229 }
230
231 static char *
convert_mtext2str(MText * mtext)232 convert_mtext2str(MText *mtext)
233 {
234 mconv_rebind_buffer(converter, (unsigned char *)buffer_for_converter,
235 sizeof(buffer_for_converter)-1);
236 mconv_encode(converter, mtext);
237 buffer_for_converter[converter->nbytes] = 0;
238
239 return uim_strdup(buffer_for_converter);
240 }
241
242 static uim_lisp
compose_modep(uim_lisp id_)243 compose_modep(uim_lisp id_)
244 {
245 int id;
246 MInputContext *ic;
247
248 id = C_INT(id_);
249 ic = ic_array[id].mic;
250
251 if (!ic)
252 return uim_scm_f();
253
254 if (ic->candidate_from == ic->candidate_to
255 || ic->candidate_from > ic->candidate_to)
256 return uim_scm_f();
257 else
258 return uim_scm_t();
259 }
260
261 static uim_lisp
preedit_changedp(uim_lisp id_)262 preedit_changedp(uim_lisp id_)
263 {
264 int id;
265 MInputContext *ic;
266
267 id = C_INT(id_);
268 ic = ic_array[id].mic;
269
270 if (!ic)
271 return uim_scm_f();
272
273 if (ic->preedit_changed == 1)
274 return uim_scm_t();
275 else
276 return uim_scm_f();
277 }
278
279 static uim_lisp
get_left_of_cursor(uim_lisp id_)280 get_left_of_cursor(uim_lisp id_)
281 {
282 int id, i;
283 uim_lisp buf_;
284 char *buf, *p;
285 MInputContext *ic;
286
287 id = C_INT(id_);
288 ic = ic_array[id].mic;
289
290 if (!ic)
291 return MAKE_STR("");
292
293 if (ic->cursor_pos == 0)
294 return MAKE_STR("");
295
296 buf = convert_mtext2str(ic->preedit);
297 p = buf;
298
299 for (i = 0; i < ic->cursor_pos ;i++)
300 p = m17nlib_utf8_find_next_char(p);
301 *p = '\0';
302
303 buf_ = MAKE_STR_DIRECTLY(buf);
304
305 return buf_;
306 }
307
308 static uim_lisp
get_right_of_cursor(uim_lisp id_)309 get_right_of_cursor(uim_lisp id_)
310 {
311 int id, i;
312 uim_lisp buf_;
313 char *buf, *p;
314 MInputContext *ic;
315
316 id = C_INT(id_);
317 ic = ic_array[id].mic;
318
319 if (!ic)
320 return MAKE_STR("");
321
322 buf = convert_mtext2str(ic->preedit);
323 p = buf;
324
325 for (i = 0; i < ic->cursor_pos ;i++)
326 p = m17nlib_utf8_find_next_char(p);
327
328 buf_ = MAKE_STR(p);
329 free(buf);
330
331 return buf_;
332 }
333
334 static uim_lisp
get_left_of_candidate(uim_lisp id_)335 get_left_of_candidate(uim_lisp id_)
336 {
337 int id, i;
338 uim_lisp buf_;
339 char *buf, *p;
340 MInputContext *ic;
341
342 id = C_INT(id_);
343 ic = ic_array[id].mic;
344
345 if (!ic)
346 return MAKE_STR("");
347
348 if (ic->candidate_from == 0)
349 return MAKE_STR("");
350
351 buf = convert_mtext2str(ic->preedit);
352 p = buf;
353
354 for (i = 0; i < ic->candidate_from ;i++)
355 p = m17nlib_utf8_find_next_char(p);
356 *p = '\0';
357
358 buf_ = MAKE_STR_DIRECTLY(buf);
359
360 return buf_;
361 }
362
363 static uim_lisp
get_selected_candidate(uim_lisp id_)364 get_selected_candidate(uim_lisp id_)
365 {
366 int id, i;
367 uim_lisp buf_;
368 char *buf, *p, *start;
369 MInputContext *ic;
370
371 id = C_INT(id_);
372 ic = ic_array[id].mic;
373
374 if (!ic)
375 return MAKE_STR("");
376
377 buf = convert_mtext2str(ic->preedit);
378 p = buf;
379
380 if (!p)
381 return MAKE_STR("");
382
383 for (i = 0; i < ic->candidate_from ;i++)
384 p = m17nlib_utf8_find_next_char(p);
385 start = p;
386
387 for (i = 0; i < ic->candidate_to - ic->candidate_from ;i++)
388 p = m17nlib_utf8_find_next_char(p);
389 *p = '\0';
390
391 buf_ = MAKE_STR(start);
392 free(buf);
393
394 return buf_;
395 }
396
397 static uim_lisp
get_right_of_candidate(uim_lisp id_)398 get_right_of_candidate(uim_lisp id_)
399 {
400 int id, i;
401 uim_lisp buf_;
402 char *buf, *p;
403 MInputContext *ic;
404
405 id = C_INT(id_);
406 ic = ic_array[id].mic;
407
408 if (!ic)
409 return MAKE_STR("");
410
411 buf = convert_mtext2str(ic->preedit);
412 p = buf;
413
414 for (i = 0; i < ic->candidate_to ;i++)
415 p = m17nlib_utf8_find_next_char(p);
416
417 buf_ = MAKE_STR(p);
418 free(buf);
419
420 return buf_;
421 }
422
423 static uim_lisp
get_nr_input_methods()424 get_nr_input_methods()
425 {
426 return MAKE_INT(nr_input_methods);
427 }
428
429 static uim_lisp
get_input_method_name(uim_lisp nth_)430 get_input_method_name(uim_lisp nth_)
431 {
432 int nth;
433 char name[BUFSIZ];
434
435 nth = C_INT(nth_);
436
437 if (nth < nr_input_methods) {
438 if (!strcmp(im_array[nth].lang, "t"))
439 snprintf(name, sizeof(name), "m17n-%s", im_array[nth].name);
440 else
441 snprintf(name, sizeof(name), "m17n-%s-%s", im_array[nth].lang, im_array[nth].name);
442
443 return MAKE_STR(name);
444 }
445
446 return uim_scm_f();
447 }
448
449 static uim_lisp
get_input_method_lang(uim_lisp nth_)450 get_input_method_lang(uim_lisp nth_)
451 {
452 int nth;
453 const char *lang;
454
455 nth = C_INT(nth_);
456
457 if (nth < nr_input_methods) {
458 lang = im_array[nth].lang;
459 /* "*" is wildcard language. See langgroup-covers? and
460 * find-im-for-locale. */
461 return MAKE_STR((strcmp(lang, "t") == 0) ? "*" : lang);
462 }
463
464 return uim_scm_f();
465 }
466
467 static uim_lisp
get_input_method_short_desc(uim_lisp nth_)468 get_input_method_short_desc(uim_lisp nth_)
469 {
470 int nth;
471 char *str = NULL, *p;
472 uim_lisp ret;
473
474 nth = C_INT(nth_);
475
476 if (nth < nr_input_methods) {
477 MInputMethod *im;
478 MText *desc;
479
480 im = im_instance(nth);
481 if (!im)
482 return MAKE_STR(N_("m17n library IM open error"));
483
484 desc = minput_get_description(im->language, im->name);
485 if (desc) {
486 int i, len;
487
488 str = convert_mtext2str(desc);
489 p = strchr(str, '.');
490 if (p)
491 *p = '\0';
492 len = strlen(str);
493
494 /*
495 * Workaround for the descriptions which lack period.
496 * Also we avoid the description with non English words.
497 * See https://bugs.freedesktop.org/show_bug.cgi?id=6972
498 */
499 for (i = 0; i < len; i++) {
500 if (str[i] == '\n') {
501 str[i] = '\0';
502 break;
503 }
504 #ifdef HAVE_ISASCII
505 else if (!isascii((int)str[i])) {
506 #else
507 else if ((int)str[i] & ~0x7f) {
508 #endif
509 free(str);
510 str = NULL;
511 break;
512 }
513 }
514 m17n_object_unref(desc);
515 }
516
517 if (str) {
518 ret = MAKE_STR(str);
519 free(str);
520 } else {
521 ret = MAKE_STR(N_("An input method provided by the m17n library"));
522 }
523 } else
524 ret = uim_scm_f();
525
526 return ret;
527 }
528
529 static MInputMethod *
530 im_instance(int nth)
531 {
532 struct im_ *ent;
533
534 if (!(0 <= nth && nth < nr_input_methods))
535 return NULL;
536
537 ent = &im_array[nth];
538 if (!ent->im)
539 ent->im = minput_open_im(msymbol(ent->lang), msymbol(ent->name), NULL);
540
541 return ent->im;
542 }
543
544 static MInputMethod *
545 find_im_by_name(const char *name)
546 {
547 int i;
548 const char *im_name;
549
550 if (strncmp(name, "m17n-", 5) != 0)
551 return NULL;
552
553 im_name = &name[5];
554
555 for (i = 0; i < nr_input_methods; i++) {
556 char buf[100];
557
558 if (!strcmp(im_array[i].lang, "t"))
559 strlcpy(buf, im_array[i].name, sizeof(buf));
560 else
561 snprintf(buf, sizeof(buf), "%s-%s", im_array[i].lang, im_array[i].name);
562
563 if (!strcmp(im_name, buf))
564 return im_instance(i);
565 }
566
567 return NULL;
568 }
569
570 static uim_lisp
571 alloc_id(uim_lisp name_)
572 {
573 int id;
574 const char *name;
575 MInputMethod *im;
576
577 id = unused_ic_id();
578 name = REFER_C_STR(name_);
579
580 im = find_im_by_name(name);
581
582 if (im)
583 ic_array[id].mic = minput_create_ic(im, NULL);
584
585 ic_array[id].old_candidates = NULL;
586 ic_array[id].new_candidates = NULL;
587
588 return MAKE_INT(id);
589 }
590
591 static uim_lisp
592 free_id(uim_lisp id_)
593 {
594 int id = C_INT(id_);
595
596 if (id < nr_input_contexts) {
597 struct ic_ *ic = &ic_array[id];
598
599 if (ic->mic) {
600 minput_destroy_ic(ic->mic);
601 ic->mic = NULL;
602 }
603 }
604
605 return uim_scm_f();
606 }
607
608 static uim_lisp
609 push_symbol_key(uim_lisp id_, uim_lisp key_)
610 {
611 int id;
612 MSymbol key;
613 MInputContext *ic;
614
615 id = C_INT(id_);
616 ic = ic_array[id].mic;
617 key = msymbol(C_STR(key_));
618
619 if (key == Mnil)
620 return uim_scm_f();
621
622 if (minput_filter(ic, key, NULL) == 1)
623 return uim_scm_t();
624 else
625 return uim_scm_f();
626 }
627
628 static uim_lisp
629 get_result(uim_lisp id_)
630 {
631 MText *produced;
632 char *commit_string;
633 int consumed, id;
634 MInputContext *ic;
635 uim_lisp consumed_, commit_string_;
636
637 id = C_INT(id_);
638 ic = ic_array[id].mic;
639
640 produced = mtext();
641 consumed = minput_lookup(ic, NULL, NULL, produced);
642
643 if (consumed == -1)
644 consumed_ = uim_scm_f();
645 else
646 consumed_ = uim_scm_t();
647
648 commit_string = convert_mtext2str(produced);
649 m17n_object_unref(produced);
650 commit_string_ = MAKE_STR(commit_string);
651 free(commit_string);
652
653 return CONS(consumed_, commit_string_);
654 }
655
656 static uim_lisp
657 commit(uim_lisp id_)
658 {
659 int id;
660 MInputContext *ic;
661
662 id = C_INT(id_);
663 ic = ic_array[id].mic;
664
665 /* To avoid a bug of m17n-lib */
666 ic->candidate_to = 0;
667
668 return uim_scm_f();
669 }
670
671 static uim_lisp
672 candidate_showp(uim_lisp id_)
673 {
674 int id;
675 MInputContext *ic;
676
677 id = C_INT(id_);
678 ic = ic_array[id].mic;
679
680 if (ic->candidate_show == 1)
681 return uim_scm_t();
682
683 return uim_scm_f();
684 }
685
686 static int
687 calc_cands_num(int id)
688 {
689 int result = 0;
690 MPlist *group;
691 MInputContext *ic;
692
693 ic = ic_array[id].mic;
694
695 if (!ic || !ic->candidate_list)
696 return 0;
697
698 group = ic->candidate_list;
699
700 while (mplist_value(group) != Mnil) {
701 if (mplist_key(group) == Mtext) {
702 for (; mplist_key(group) != Mnil; group = mplist_next(group))
703 result += mtext_len(mplist_value(group));
704 } else {
705 for (; mplist_key(group) != Mnil; group = mplist_next(group))
706 result += mplist_length(mplist_value(group));
707 }
708 }
709
710 return result;
711 }
712
713 static void
714 old_cands_free(char **old_cands)
715 {
716 int i = 0;
717
718 if (old_cands) {
719 for (i = 0; old_cands[i]; i++)
720 free(old_cands[i]);
721 free(old_cands);
722 }
723 }
724
725 static uim_lisp
726 fill_new_candidates(uim_lisp id_)
727 {
728 MText *produced;
729 MPlist *group, *elm;
730 int i, id, cands_num;
731 char **new_cands;
732 MInputContext *ic;
733
734 id = C_INT(id_);
735 ic = ic_array[id].mic;
736 cands_num = calc_cands_num(id);
737
738 if (!ic || !ic->candidate_list)
739 return uim_scm_f();
740
741 group = ic->candidate_list;
742
743 old_cands_free(ic_array[id].old_candidates);
744 ic_array[id].old_candidates = ic_array[id].new_candidates;
745
746 new_cands = uim_malloc(cands_num * sizeof(char *) + 2);
747
748 if (mplist_key(group) == Mtext) {
749 for (i = 0; mplist_key(group) != Mnil; group = mplist_next(group)) {
750 int j;
751 for (j = 0; j < mtext_len(mplist_value(group)); j++, i++) {
752 produced = mtext();
753 mtext_cat_char(produced, mtext_ref_char(mplist_value(group), j));
754 new_cands[i] = convert_mtext2str(produced);
755 m17n_object_unref(produced);
756 }
757 }
758 } else {
759 for (i = 0; mplist_key(group) != Mnil; group = mplist_next(group)) {
760
761 for (elm = mplist_value(group); mplist_key(elm) != Mnil;
762 elm = mplist_next(elm),i++) {
763 produced = mplist_value(elm);
764 new_cands[i] = convert_mtext2str(produced);
765 }
766 }
767 }
768 new_cands[i] = NULL;
769
770 ic_array[id].new_candidates = new_cands;
771 ic_array[id].nr_candidates = i;
772
773 return uim_scm_t();
774 }
775
776 static uim_bool
777 same_candidatesp(char **old, char **new)
778 {
779 int i;
780
781 if (!old)
782 return UIM_FALSE;
783
784 for (i = 0; old[i] && new[i]; i++) {
785 if (strcmp(old[i], new[i]) != 0)
786 return UIM_FALSE;
787 }
788
789 return UIM_TRUE;
790 }
791
792 static uim_lisp
793 candidates_changedp(uim_lisp id_)
794 {
795 int id = C_INT(id_);
796
797 if (!same_candidatesp(ic_array[id].old_candidates,
798 ic_array[id].new_candidates))
799 return uim_scm_t();
800
801 return uim_scm_f();
802 }
803
804 static uim_lisp
805 get_nr_candidates(uim_lisp id_)
806 {
807 int id = C_INT(id_);
808
809 return MAKE_INT(calc_cands_num(id));
810 }
811
812 static uim_lisp
813 get_nth_candidate(uim_lisp id_, uim_lisp nth_)
814 {
815 int id, nth, nr;
816
817 id = C_INT(id_);
818 nth = C_INT(nth_);
819 nr = ic_array[id].nr_candidates;
820
821 if (nr >= nth)
822 return MAKE_STR(ic_array[id].new_candidates[nth]);
823 else
824 return MAKE_STR("");
825 }
826
827 static uim_lisp
828 get_candidate_index(uim_lisp id_)
829 {
830 int id;
831 MInputContext *ic;
832
833 id = C_INT(id_);
834 ic = ic_array[id].mic;
835
836 return MAKE_INT(ic->candidate_index);
837 }
838
839 void
840 uim_plugin_instance_init(void)
841 {
842 uim_scm_init_proc0("m17nlib-lib-init", init_m17nlib);
843 uim_scm_init_proc0("m17nlib-lib-nr-input-methods",
844 get_nr_input_methods);
845 uim_scm_init_proc1("m17nlib-lib-nth-input-method-lang",
846 get_input_method_lang);
847 uim_scm_init_proc1("m17nlib-lib-nth-input-method-name",
848 get_input_method_name);
849 uim_scm_init_proc1("m17nlib-lib-nth-input-method-short-desc",
850 get_input_method_short_desc);
851 uim_scm_init_proc1("m17nlib-lib-alloc-context", alloc_id);
852 uim_scm_init_proc1("m17nlib-lib-free-context", free_id);
853 uim_scm_init_proc2("m17nlib-lib-push-symbol-key", push_symbol_key);
854 uim_scm_init_proc1("m17nlib-lib-compose-mode?", compose_modep);
855 uim_scm_init_proc1("m17nlib-lib-preedit-changed?", preedit_changedp);
856 uim_scm_init_proc1("m17nlib-lib-get-left-of-cursor", get_left_of_cursor);
857 uim_scm_init_proc1("m17nlib-lib-get-right-of-cursor", get_right_of_cursor);
858 uim_scm_init_proc1("m17nlib-lib-get-left-of-candidate",
859 get_left_of_candidate);
860 uim_scm_init_proc1("m17nlib-lib-get-selected-candidate",
861 get_selected_candidate);
862 uim_scm_init_proc1("m17nlib-lib-get-right-of-candidate",
863 get_right_of_candidate);
864 uim_scm_init_proc1("m17nlib-lib-get-result", get_result);
865 uim_scm_init_proc1("m17nlib-lib-commit", commit);
866 uim_scm_init_proc1("m17nlib-lib-candidate-show?", candidate_showp);
867 uim_scm_init_proc1("m17nlib-lib-fill-new-candidates!", fill_new_candidates);
868 uim_scm_init_proc1("m17nlib-lib-candidates-changed?", candidates_changedp);
869 uim_scm_init_proc1("m17nlib-lib-get-nr-candidates", get_nr_candidates);
870 uim_scm_init_proc2("m17nlib-lib-get-nth-candidate", get_nth_candidate);
871 uim_scm_init_proc1("m17nlib-lib-get-candidate-index", get_candidate_index);
872 }
873
874 void
875 uim_plugin_instance_quit(void)
876 {
877 if (converter) {
878 mconv_free_converter(converter);
879 converter = NULL;
880 }
881 if (m17nlib_ok) {
882 M17N_FINI();
883 m17nlib_ok = 0;
884 free(im_array);
885 free(ic_array);
886 }
887 }
888