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 <stdlib.h>
37 #include <string.h>
38 #include <assert.h>
39 #if !UIM_USE_NOTIFY_PLUGINS
40 #include <stdarg.h>
41 #endif
42
43 #include "uim.h"
44 #include "uim-internal.h"
45 #include "uim-util.h"
46 #include "uim-iconv.h"
47 #include "uim-posix.h"
48 #include "uim-im-switcher.h"
49 #include "uim-scm.h"
50 #include "uim-scm-abbrev.h"
51 #if UIM_USE_NOTIFY_PLUGINS
52 #include "uim-notify.h"
53 #else
54 #include "gettext.h"
55 #endif
56
57
58 enum uim_result {
59 FAILED = -1,
60 OK = 0
61 };
62
63 static void fatal_error_hook(void);
64
65 static void *uim_init_internal(void *dummy);
66 struct uim_get_candidate_args {
67 uim_context uc;
68 int index;
69 int enum_hint;
70 };
71 static void *uim_get_candidate_internal(struct uim_get_candidate_args *args);
72 struct uim_delay_activating_args {
73 uim_context uc;
74 int nr;
75 int display_limit;
76 int selected_index;
77 };
78 static void *uim_delay_activating_internal(struct uim_delay_activating_args *);
79 static uim_lisp get_nth_im(uim_context uc, int nth);
80 #ifdef ENABLE_ANTHY_STATIC
81 void uim_anthy_plugin_instance_init(void);
82 void uim_anthy_plugin_instance_quit(void);
83 #endif
84 #ifdef ENABLE_ANTHY_UTF8_STATIC
85 void uim_anthy_utf8_plugin_instance_init(void);
86 void uim_anthy_utf8_plugin_instance_quit(void);
87 #endif
88
89 static uim_bool uim_initialized;
90 static uim_lisp protected0, protected1;
91
92 unsigned int uim_init_count;
93
94 /****************************************************************
95 * Core APIs *
96 ****************************************************************/
97 static void
fatal_error_hook(void)98 fatal_error_hook(void)
99 {
100 /* actual error message is already printed by the Scheme interpreter */
101 uim_fatal_error("an unhandled error raised from Scheme interpreter");
102 }
103
104 long
uim_init(void)105 uim_init(void)
106 {
107 long ret;
108 char *sys_load_path;
109
110 if (uim_initialized)
111 return OK;
112
113 uim_init_error();
114
115 if (UIM_CATCH_ERROR_BEGIN())
116 return FAILED;
117
118 sys_load_path = (uim_issetugid()) ? NULL : getenv("LIBUIM_SYSTEM_SCM_FILES");
119 uim_scm_init(sys_load_path);
120 uim_scm_set_fatal_error_hook(fatal_error_hook);
121
122 ret = (long)uim_scm_call_with_gc_ready_stack((uim_gc_gate_func_ptr)uim_init_internal, NULL);
123
124 UIM_CATCH_ERROR_END();
125
126 return ret;
127 }
128
129 static void *
uim_init_internal(void * dummy)130 uim_init_internal(void *dummy)
131 {
132 char *scm_files;
133
134 protected0 = uim_scm_f();
135 protected1 = uim_scm_f();
136 uim_scm_gc_protect(&protected0);
137 uim_scm_gc_protect(&protected1);
138
139 /* To allow (cond-expand (uim ...)) in early initialization stages,
140 * provision of the "uim" should be performed as early as possible. */
141 uim_scm_callf("provide", "s", "uim");
142
143 uim_init_im_subrs();
144 uim_init_intl_subrs();
145 uim_init_iconv_subrs();
146 uim_init_posix_subrs();
147 uim_init_util_subrs();
148 #if UIM_USE_NOTIFY_PLUGINS
149 uim_notify_init(); /* init uim-notify facility */
150 #endif
151 uim_init_notify_subrs(); /* init Scheme interface of uim-notify */
152 uim_init_key_subrs();
153 uim_init_rk_subrs();
154 uim_init_dynlib();
155 #ifdef ENABLE_ANTHY_STATIC
156 uim_anthy_plugin_instance_init();
157 #endif
158 #ifdef ENABLE_ANTHY_UTF8_STATIC
159 uim_anthy_utf8_plugin_instance_init();
160 #endif
161
162 if (uim_issetugid()) {
163 scm_files = SCM_FILES;
164 } else {
165 scm_files = getenv("LIBUIM_SCM_FILES");
166 scm_files = (scm_files) ? scm_files : SCM_FILES;
167 }
168 uim_scm_set_lib_path(scm_files);
169
170 uim_scm_require_file("init.scm");
171
172 uim_initialized = UIM_TRUE;
173
174 return (void *)OK;
175 }
176
177 void
uim_quit(void)178 uim_quit(void)
179 {
180 if (!uim_initialized)
181 return;
182
183 if (UIM_CATCH_ERROR_BEGIN()) {
184 /* Leave uim_initialized uncleared to keep libuim disabled. */
185 return;
186 }
187
188 #ifdef ENABLE_ANTHY_STATIC
189 uim_anthy_plugin_instance_quit();
190 #endif
191 #ifdef ENABLE_ANTHY_UTF8_STATIC
192 uim_anthy_utf8_plugin_instance_quit();
193 #endif
194 #if UIM_USE_NOTIFY_PLUGINS
195 uim_notify_quit();
196 #endif
197 uim_scm_callf("annotation-unload", "");
198 uim_scm_callf("dynlib-unload-all", "");
199 uim_quit_dynlib();
200 uim_scm_quit();
201 uim_initialized = UIM_FALSE;
202 }
203
204 uim_context
uim_create_context(void * ptr,const char * enc,const char * lang,const char * engine,struct uim_code_converter * conv,void (* commit_cb)(void * ptr,const char * str))205 uim_create_context(void *ptr,
206 const char *enc,
207 const char *lang,
208 const char *engine,
209 struct uim_code_converter *conv,
210 void (*commit_cb)(void *ptr, const char *str))
211 {
212 uim_context uc;
213 uim_lisp lang_, engine_;
214
215 if (UIM_CATCH_ERROR_BEGIN())
216 return NULL;
217
218 assert(uim_scm_gc_any_contextp());
219
220 uc = uim_malloc(sizeof(*uc));
221 memset(uc, 0, sizeof(*uc));
222
223 /* helper system */
224 uc->uim_fd = -1;
225
226 /* encoding handlings */
227 if (!enc)
228 enc = "UTF-8";
229 uc->client_encoding = uim_strdup(enc);
230 uc->conv_if = (conv) ? conv : uim_iconv;
231
232 /* variables */
233 uc->is_enabled = UIM_TRUE;
234
235 /* core callbacks */
236 uc->commit_cb = commit_cb;
237
238 /* foreign context objects */
239 uc->ptr = ptr;
240
241 protected0 = lang_ = (lang) ? MAKE_SYM(lang) : uim_scm_f();
242 protected1 = engine_ = (engine) ? MAKE_SYM(engine) : uim_scm_f();
243 uc->sc = uim_scm_f(); /* failsafe */
244 uc->sc = uim_scm_callf("create-context", "poo", uc, lang_, engine_);
245 uim_scm_gc_protect(&uc->sc);
246 uim_scm_callf("setup-context", "o", uc->sc);
247
248 UIM_CATCH_ERROR_END();
249
250 return uc;
251 }
252
253 void
uim_release_context(uim_context uc)254 uim_release_context(uim_context uc)
255 {
256 int i;
257
258 if (UIM_CATCH_ERROR_BEGIN())
259 return;
260
261 assert(uim_scm_gc_any_contextp());
262 assert(uc);
263
264 uim_scm_callf("release-context", "p", uc);
265 uim_scm_gc_unprotect(&uc->sc);
266 if (uc->outbound_conv)
267 uc->conv_if->release(uc->outbound_conv);
268 if (uc->inbound_conv)
269 uc->conv_if->release(uc->inbound_conv);
270 for (i = 0; i < uc->nr_modes; i++) {
271 free(uc->modes[i]);
272 uc->modes[i] = NULL;
273 }
274 free(uc->propstr);
275 free(uc->modes);
276 free(uc->client_encoding);
277 #ifdef DEBUG
278 /* prevents operating on invalidated uim_context */
279 memset(uc, 0, sizeof(*uc));
280 #endif
281 free(uc);
282
283 UIM_CATCH_ERROR_END();
284 }
285
286 void
uim_reset_context(uim_context uc)287 uim_reset_context(uim_context uc)
288 {
289 if (UIM_CATCH_ERROR_BEGIN())
290 return;
291
292 assert(uim_scm_gc_any_contextp());
293 assert(uc);
294
295 uim_scm_callf("reset-handler", "p", uc);
296
297 UIM_CATCH_ERROR_END();
298 }
299
300 void
uim_focus_in_context(uim_context uc)301 uim_focus_in_context(uim_context uc)
302 {
303 if (UIM_CATCH_ERROR_BEGIN())
304 return;
305
306 assert(uim_scm_gc_any_contextp());
307 assert(uc);
308
309 uim_scm_callf("focus-in-handler", "p", uc);
310
311 UIM_CATCH_ERROR_END();
312 }
313
314 void
uim_focus_out_context(uim_context uc)315 uim_focus_out_context(uim_context uc)
316 {
317 if (UIM_CATCH_ERROR_BEGIN())
318 return;
319
320 assert(uim_scm_gc_any_contextp());
321 assert(uc);
322
323 uim_scm_callf("focus-out-handler", "p", uc);
324
325 UIM_CATCH_ERROR_END();
326 }
327
328 void
uim_place_context(uim_context uc)329 uim_place_context(uim_context uc)
330 {
331 if (UIM_CATCH_ERROR_BEGIN())
332 return;
333
334 assert(uim_scm_gc_any_contextp());
335 assert(uc);
336
337 uim_scm_callf("place-handler", "p", uc);
338
339 UIM_CATCH_ERROR_END();
340 }
341
342 void
uim_displace_context(uim_context uc)343 uim_displace_context(uim_context uc)
344 {
345 if (UIM_CATCH_ERROR_BEGIN())
346 return;
347
348 assert(uim_scm_gc_any_contextp());
349 assert(uc);
350
351 uim_scm_callf("displace-handler", "p", uc);
352
353 UIM_CATCH_ERROR_END();
354 }
355
356 void
uim_set_preedit_cb(uim_context uc,void (* clear_cb)(void * ptr),void (* pushback_cb)(void * ptr,int attr,const char * str),void (* update_cb)(void * ptr))357 uim_set_preedit_cb(uim_context uc,
358 void (*clear_cb)(void *ptr),
359 void (*pushback_cb)(void *ptr, int attr, const char *str),
360 void (*update_cb)(void *ptr))
361 {
362 if (UIM_CATCH_ERROR_BEGIN())
363 return;
364
365 assert(uim_scm_gc_any_contextp());
366 assert(uc);
367
368 uc->preedit_clear_cb = clear_cb;
369 uc->preedit_pushback_cb = pushback_cb;
370 uc->preedit_update_cb = update_cb;
371
372 UIM_CATCH_ERROR_END();
373 }
374
375 void
uim_set_candidate_selector_cb(uim_context uc,void (* activate_cb)(void * ptr,int nr,int display_limit),void (* select_cb)(void * ptr,int index),void (* shift_page_cb)(void * ptr,int direction),void (* deactivate_cb)(void * ptr))376 uim_set_candidate_selector_cb(uim_context uc,
377 void (*activate_cb)(void *ptr,
378 int nr, int display_limit),
379 void (*select_cb)(void *ptr, int index),
380 void (*shift_page_cb)(void *ptr, int direction),
381 void (*deactivate_cb)(void *ptr))
382 {
383 if (UIM_CATCH_ERROR_BEGIN())
384 return;
385
386 assert(uim_scm_gc_any_contextp());
387 assert(uc);
388
389 uc->candidate_selector_activate_cb = activate_cb;
390 uc->candidate_selector_select_cb = select_cb;
391 uc->candidate_selector_deactivate_cb = deactivate_cb;
392 uc->candidate_selector_shift_page_cb = shift_page_cb;
393
394 UIM_CATCH_ERROR_END();
395 }
396
397 uim_candidate
uim_get_candidate(uim_context uc,int index,int accel_enumeration_hint)398 uim_get_candidate(uim_context uc, int index, int accel_enumeration_hint)
399 {
400 struct uim_get_candidate_args args;
401 uim_candidate cand;
402
403 if (UIM_CATCH_ERROR_BEGIN())
404 return NULL;
405
406 assert(uim_scm_gc_any_contextp());
407 assert(uc);
408 assert(index >= 0);
409 assert(accel_enumeration_hint >= 0);
410
411 args.uc = uc;
412 args.index = index;
413 args.enum_hint = accel_enumeration_hint;
414
415 cand = (uim_candidate)uim_scm_call_with_gc_ready_stack((uim_gc_gate_func_ptr)uim_get_candidate_internal, &args);
416
417 UIM_CATCH_ERROR_END();
418
419 return cand;
420 }
421
422 static void *
uim_get_candidate_internal(struct uim_get_candidate_args * args)423 uim_get_candidate_internal(struct uim_get_candidate_args *args)
424 {
425 uim_context uc;
426 uim_candidate cand;
427 uim_lisp triple;
428 const char *str, *head, *ann;
429
430 uc = args->uc;
431 triple = uim_scm_callf("get-candidate", "pii",
432 uc, args->index, args->enum_hint);
433 ENSURE((uim_scm_length(triple) == 3), "invalid candidate triple");
434
435 cand = uim_malloc(sizeof(*cand));
436 memset(cand, 0, sizeof(*cand));
437
438 str = REFER_C_STR(CAR(triple));
439 head = REFER_C_STR(CAR(CDR(triple)));
440 ann = REFER_C_STR(CAR(CDR(CDR((triple)))));
441 cand->str = uc->conv_if->convert(uc->outbound_conv, str);
442 cand->heading_label = uc->conv_if->convert(uc->outbound_conv, head);
443 cand->annotation = uc->conv_if->convert(uc->outbound_conv, ann);
444
445 return (void *)cand;
446 }
447
448 /* Accepts NULL candidates that produced by an error on uim_get_candidate(). */
449 const char *
uim_candidate_get_cand_str(uim_candidate cand)450 uim_candidate_get_cand_str(uim_candidate cand)
451 {
452 if (UIM_CATCH_ERROR_BEGIN())
453 return "";
454
455 assert(uim_scm_gc_any_contextp());
456 if (!cand)
457 uim_fatal_error("null candidate");
458
459 UIM_CATCH_ERROR_END();
460
461 return cand->str;
462 }
463
464 const char *
uim_candidate_get_heading_label(uim_candidate cand)465 uim_candidate_get_heading_label(uim_candidate cand)
466 {
467 if (UIM_CATCH_ERROR_BEGIN())
468 return "";
469
470 assert(uim_scm_gc_any_contextp());
471 if (!cand)
472 uim_fatal_error("null candidate");
473
474 UIM_CATCH_ERROR_END();
475
476 return cand->heading_label;
477 }
478
479 const char *
uim_candidate_get_annotation_str(uim_candidate cand)480 uim_candidate_get_annotation_str(uim_candidate cand)
481 {
482 if (UIM_CATCH_ERROR_BEGIN())
483 return "";
484
485 assert(uim_scm_gc_any_contextp());
486 if (!cand)
487 uim_fatal_error("null candidate");
488
489 UIM_CATCH_ERROR_END();
490
491 return cand->annotation;
492 }
493
494 void
uim_candidate_free(uim_candidate cand)495 uim_candidate_free(uim_candidate cand)
496 {
497 if (UIM_CATCH_ERROR_BEGIN())
498 return;
499
500 assert(uim_scm_gc_any_contextp());
501 if (!cand)
502 uim_fatal_error("null candidate");
503
504 free(cand->str);
505 free(cand->heading_label);
506 free(cand->annotation);
507 free(cand);
508
509 UIM_CATCH_ERROR_END();
510 }
511
512 int
uim_get_candidate_index(uim_context uc)513 uim_get_candidate_index(uim_context uc)
514 {
515 if (UIM_CATCH_ERROR_BEGIN())
516 return 0;
517
518 assert(uim_scm_gc_any_contextp());
519 assert(uc);
520
521 UIM_CATCH_ERROR_END();
522
523 return 0;
524 }
525
526 void
uim_set_candidate_index(uim_context uc,int nth)527 uim_set_candidate_index(uim_context uc, int nth)
528 {
529 if (UIM_CATCH_ERROR_BEGIN())
530 return;
531
532 assert(uim_scm_gc_any_contextp());
533 assert(uc);
534 assert(nth >= 0);
535
536 uim_scm_callf("set-candidate-index", "pi", uc, nth);
537
538 UIM_CATCH_ERROR_END();
539 }
540
541 void
uim_set_text_acquisition_cb(uim_context uc,int (* acquire_cb)(void * ptr,enum UTextArea text_id,enum UTextOrigin origin,int former_len,int latter_len,char ** former,char ** latter),int (* delete_cb)(void * ptr,enum UTextArea text_id,enum UTextOrigin origin,int former_len,int latter_len))542 uim_set_text_acquisition_cb(uim_context uc,
543 int (*acquire_cb)(void *ptr,
544 enum UTextArea text_id,
545 enum UTextOrigin origin,
546 int former_len, int latter_len,
547 char **former, char **latter),
548 int (*delete_cb)(void *ptr, enum UTextArea text_id,
549 enum UTextOrigin origin,
550 int former_len, int latter_len))
551 {
552 if (UIM_CATCH_ERROR_BEGIN())
553 return;
554
555 assert(uim_scm_gc_any_contextp());
556 assert(uc);
557
558 uc->acquire_text_cb = acquire_cb;
559 uc->delete_text_cb = delete_cb;
560
561 UIM_CATCH_ERROR_END();
562 }
563
564 uim_bool
uim_input_string(uim_context uc,const char * str)565 uim_input_string(uim_context uc, const char *str)
566 {
567 uim_bool ret;
568 uim_lisp consumed;
569 char *conv;
570
571 if (UIM_CATCH_ERROR_BEGIN())
572 return UIM_FALSE;
573
574 assert(uim_scm_gc_any_contextp());
575 assert(uc);
576 assert(str);
577
578 conv = uc->conv_if->convert(uc->inbound_conv, str);
579 if (conv) {
580 protected0 =
581 consumed = uim_scm_callf("input-string-handler", "ps", uc, conv);
582 free(conv);
583
584 ret = C_BOOL(consumed);
585 } else {
586 ret = UIM_FALSE;
587 }
588
589 UIM_CATCH_ERROR_END();
590
591 return ret;
592 }
593
594 /****************************************************************
595 * Optional APIs *
596 ****************************************************************/
597 void
uim_set_client_encoding(uim_context uc,const char * encoding)598 uim_set_client_encoding(uim_context uc, const char *encoding)
599 {
600 uim_lisp im_enc;
601
602 if (UIM_CATCH_ERROR_BEGIN())
603 return;
604
605 assert(uim_scm_gc_any_contextp());
606 assert(uc);
607 assert(encoding);
608
609 free(uc->client_encoding);
610 uc->client_encoding = uim_strdup(encoding);
611
612 protected0 = im_enc = uim_scm_callf("uim-context-encoding", "p", uc);
613 uim_set_encoding(uc, REFER_C_STR(im_enc));
614
615 UIM_CATCH_ERROR_END();
616 }
617
618 void
uim_set_configuration_changed_cb(uim_context uc,void (* changed_cb)(void * ptr))619 uim_set_configuration_changed_cb(uim_context uc,
620 void (*changed_cb)(void *ptr))
621 {
622 if (UIM_CATCH_ERROR_BEGIN())
623 return;
624
625 assert(uim_scm_gc_any_contextp());
626 assert(uc);
627
628 uc->configuration_changed_cb = changed_cb;
629
630 UIM_CATCH_ERROR_END();
631 }
632
633 void
uim_set_im_switch_request_cb(uim_context uc,void (* sw_app_im_cb)(void * ptr,const char * name),void (* sw_system_im_cb)(void * ptr,const char * name))634 uim_set_im_switch_request_cb(uim_context uc,
635 void (*sw_app_im_cb)(void *ptr, const char *name),
636 void (*sw_system_im_cb)(void *ptr,
637 const char *name))
638 {
639 if (UIM_CATCH_ERROR_BEGIN())
640 return;
641
642 assert(uim_scm_gc_any_contextp());
643 assert(uc);
644
645 uc->switch_app_global_im_cb = sw_app_im_cb;
646 uc->switch_system_global_im_cb = sw_system_im_cb;
647
648 UIM_CATCH_ERROR_END();
649 }
650
651 void
uim_switch_im(uim_context uc,const char * engine)652 uim_switch_im(uim_context uc, const char *engine)
653 {
654 if (UIM_CATCH_ERROR_BEGIN())
655 return;
656
657 /* related to the commit log of r1400:
658
659 We should not add the API uim_destroy_context(). We should move
660 IM-switching feature into Scheme instead. It removes the context
661 management code related to IM-switching duplicated in several IM
662 bridges. Refer the implementation of GtkIMMulticontext as example
663 of proxy-like IM-switcher. It does IM-switching without extending
664 immodule API. We should follow its design to make our API simple.
665 -- 2004-10-05 YamaKen
666 */
667 assert(uim_scm_gc_any_contextp());
668 assert(uc);
669 assert(engine);
670
671 uim_scm_callf("uim-switch-im", "py", uc, engine);
672
673 UIM_CATCH_ERROR_END();
674 }
675
676 const char *
uim_get_current_im_name(uim_context uc)677 uim_get_current_im_name(uim_context uc)
678 {
679 uim_lisp im, ret;
680 const char *name;
681
682 if (UIM_CATCH_ERROR_BEGIN())
683 return "direct";
684
685 assert(uim_scm_gc_any_contextp());
686 assert(uc);
687
688 protected0 = im = uim_scm_callf("uim-context-im", "p", uc);
689 protected1 = ret = uim_scm_callf("im-name", "o", im);
690 name = REFER_C_STR(ret);
691
692 UIM_CATCH_ERROR_END();
693
694 return name;
695 }
696
697 const char *
uim_get_default_im_name(const char * localename)698 uim_get_default_im_name(const char *localename)
699 {
700 uim_lisp ret;
701 const char *name;
702
703 if (UIM_CATCH_ERROR_BEGIN())
704 return "direct";
705
706 assert(uim_scm_gc_any_contextp());
707 assert(localename);
708
709 protected0 = ret = uim_scm_callf("uim-get-default-im-name", "s", localename);
710 name = REFER_C_STR(ret);
711
712 UIM_CATCH_ERROR_END();
713
714 return name;
715 }
716
717 const char *
uim_get_im_name_for_locale(const char * localename)718 uim_get_im_name_for_locale(const char *localename)
719 {
720 uim_lisp ret;
721 const char *name;
722
723 if (UIM_CATCH_ERROR_BEGIN())
724 return "direct";
725
726 assert(uim_scm_gc_any_contextp());
727 assert(localename);
728
729 protected0 =
730 ret = uim_scm_callf("uim-get-im-name-for-locale", "s", localename);
731 name = REFER_C_STR(ret);
732
733 UIM_CATCH_ERROR_END();
734
735 return name;
736 }
737
738 #if !UIM_USE_NOTIFY_PLUGINS
739 uim_bool
uim_notify_info(const char * msg_fmt,...)740 uim_notify_info(const char *msg_fmt, ...)
741 {
742 va_list args;
743 int ret;
744
745 va_start(args, msg_fmt);
746 fputs("libuim: [info] ", stderr);
747 ret = vfprintf(stderr, msg_fmt, args);
748 fputs("\n", stderr);
749 va_end(args);
750
751 return (ret >= 0);
752 }
753
754 uim_bool
uim_notify_fatal(const char * msg_fmt,...)755 uim_notify_fatal(const char *msg_fmt, ...)
756 {
757 va_list args;
758 int ret;
759
760 va_start(args, msg_fmt);
761 fputs("libuim: [fatal] ", stderr);
762 ret = vfprintf(stderr, msg_fmt, args);
763 fputs("\n", stderr);
764 va_end(args);
765
766 return (ret >= 0);
767 }
768
769 static uim_lisp
notify_get_plugins(void)770 notify_get_plugins(void)
771 {
772 return CONS(LIST3(MAKE_SYM("builtin"), MAKE_STR(N_("builtin")), MAKE_STR(N_("libuim builtin"))), uim_scm_null());
773 }
774
775 static uim_lisp
notify_info(uim_lisp msg_)776 notify_info(uim_lisp msg_)
777 {
778 const char *msg = REFER_C_STR(msg_);
779
780 return MAKE_BOOL(uim_notify_info("%s", dgettext(GETTEXT_PACKAGE, msg)));
781 }
782
783 static uim_lisp
notify_fatal(uim_lisp msg_)784 notify_fatal(uim_lisp msg_)
785 {
786 const char *msg = REFER_C_STR(msg_);
787
788 return MAKE_BOOL(uim_notify_fatal("%s", dgettext(GETTEXT_PACKAGE, msg)));
789 }
790
791 void
uim_init_notify_subrs(void)792 uim_init_notify_subrs(void)
793 {
794 uim_scm_init_proc0("uim-notify-get-plugins", notify_get_plugins);
795 uim_scm_init_proc1("uim-notify-info", notify_info);
796 uim_scm_init_proc1("uim-notify-fatal", notify_fatal);
797 }
798 #endif /* !UIM_USE_NOTIFY_PLUGINS */
799
800 void
uim_set_delay_candidate_selector_cb(uim_context uc,void (* delay_activate_cb)(void * ptr,int delay))801 uim_set_delay_candidate_selector_cb(uim_context uc,
802 void (*delay_activate_cb)(void *ptr,
803 int delay))
804 {
805 if (UIM_CATCH_ERROR_BEGIN())
806 return;
807
808 assert(uim_scm_gc_any_contextp());
809 assert(uc);
810
811 uc->candidate_selector_delay_activate_cb = delay_activate_cb;
812
813 UIM_CATCH_ERROR_END();
814 }
815
816 void
uim_delay_activating(uim_context uc,int * nr,int * display_limit,int * selected_index)817 uim_delay_activating(uim_context uc, int *nr, int *display_limit, int *selected_index)
818 {
819 struct uim_delay_activating_args args;
820
821 if (UIM_CATCH_ERROR_BEGIN())
822 return;
823
824 assert(uim_scm_gc_any_contextp());
825 assert(uc);
826
827 args.uc = uc;
828 args.nr = *nr;
829 args.display_limit = *display_limit;
830 args.selected_index = *selected_index;
831
832 uim_scm_call_with_gc_ready_stack((uim_gc_gate_func_ptr)uim_delay_activating_internal, &args);
833 *nr = args.nr;
834 *display_limit = args.display_limit;
835 *selected_index = args.selected_index;
836
837 UIM_CATCH_ERROR_END();
838 }
839
840 static void *
uim_delay_activating_internal(struct uim_delay_activating_args * args)841 uim_delay_activating_internal(struct uim_delay_activating_args *args)
842 {
843 uim_context uc;
844 uim_lisp triple;
845
846 uc = args->uc;
847 triple = uim_scm_callf("delay-activating-handler", "p", uc);
848 if (LISTP(triple) && uim_scm_length(triple) == 3) {
849 args->nr = C_INT(CAR(triple));
850 args->display_limit = C_INT(CAR(CDR(triple)));
851 args->selected_index = C_INT(CAR(CDR(CDR(triple))));
852 }
853 return NULL;
854 }
855
856 /****************************************************************
857 * Legacy 'mode' API *
858 ****************************************************************/
859 int
uim_get_nr_modes(uim_context uc)860 uim_get_nr_modes(uim_context uc)
861 {
862 if (UIM_CATCH_ERROR_BEGIN())
863 return 0;
864
865 assert(uim_scm_gc_any_contextp());
866 assert(uc);
867
868 UIM_CATCH_ERROR_END();
869
870 return uc->nr_modes;
871 }
872
873 const char *
uim_get_mode_name(uim_context uc,int nth)874 uim_get_mode_name(uim_context uc, int nth)
875 {
876 if (UIM_CATCH_ERROR_BEGIN())
877 return NULL;
878
879 assert(uim_scm_gc_any_contextp());
880 assert(uc);
881 assert(nth >= 0);
882 assert(nth < uc->nr_modes);
883
884 UIM_CATCH_ERROR_END();
885
886 return uc->modes[nth];
887 }
888
889 int
uim_get_current_mode(uim_context uc)890 uim_get_current_mode(uim_context uc)
891 {
892 if (UIM_CATCH_ERROR_BEGIN())
893 return 0;
894
895 assert(uim_scm_gc_any_contextp());
896 assert(uc);
897
898 UIM_CATCH_ERROR_END();
899
900 return uc->mode;
901 }
902
903 void
uim_set_mode(uim_context uc,int mode)904 uim_set_mode(uim_context uc, int mode)
905 {
906 if (UIM_CATCH_ERROR_BEGIN())
907 return;
908
909 assert(uim_scm_gc_any_contextp());
910 assert(uc);
911 assert(mode >= 0);
912
913 uc->mode = mode;
914 uim_scm_callf("mode-handler", "pi", uc, mode);
915
916 UIM_CATCH_ERROR_END();
917 }
918
919 void
uim_set_mode_cb(uim_context uc,void (* update_cb)(void * ptr,int mode))920 uim_set_mode_cb(uim_context uc, void (*update_cb)(void *ptr, int mode))
921 {
922 if (UIM_CATCH_ERROR_BEGIN())
923 return;
924
925 assert(uim_scm_gc_any_contextp());
926 assert(uc);
927
928 UIM_CATCH_ERROR_END();
929
930 uc->mode_update_cb = update_cb;
931 }
932
933 void
uim_set_mode_list_update_cb(uim_context uc,void (* update_cb)(void * ptr))934 uim_set_mode_list_update_cb(uim_context uc, void (*update_cb)(void *ptr))
935 {
936 if (UIM_CATCH_ERROR_BEGIN())
937 return;
938
939 assert(uim_scm_gc_any_contextp());
940 assert(uc);
941
942 UIM_CATCH_ERROR_END();
943
944 uc->mode_list_update_cb = update_cb;
945 }
946
947 /****************************************************************
948 * Legacy 'property list' API *
949 ****************************************************************/
950 void
uim_set_prop_list_update_cb(uim_context uc,void (* update_cb)(void * ptr,const char * str))951 uim_set_prop_list_update_cb(uim_context uc,
952 void (*update_cb)(void *ptr, const char *str))
953 {
954 if (UIM_CATCH_ERROR_BEGIN())
955 return;
956
957 assert(uim_scm_gc_any_contextp());
958 assert(uc);
959
960 uc->prop_list_update_cb = update_cb;
961
962 UIM_CATCH_ERROR_END();
963 }
964
965 /* Obsolete */
966 void
uim_set_prop_label_update_cb(uim_context uc,void (* update_cb)(void * ptr,const char * str))967 uim_set_prop_label_update_cb(uim_context uc,
968 void (*update_cb)(void *ptr, const char *str))
969 {
970 if (UIM_CATCH_ERROR_BEGIN())
971 return;
972
973 assert(uim_scm_gc_any_contextp());
974 assert(uc);
975
976 UIM_CATCH_ERROR_END();
977 }
978
979 void
uim_prop_list_update(uim_context uc)980 uim_prop_list_update(uim_context uc)
981 {
982 if (UIM_CATCH_ERROR_BEGIN())
983 return;
984
985 assert(uim_scm_gc_any_contextp());
986 assert(uc);
987
988 if (uc->propstr && uc->prop_list_update_cb)
989 uc->prop_list_update_cb(uc->ptr, uc->propstr);
990
991 UIM_CATCH_ERROR_END();
992 }
993
994 /* Obsolete */
995 void
uim_prop_label_update(uim_context uc)996 uim_prop_label_update(uim_context uc)
997 {
998 if (UIM_CATCH_ERROR_BEGIN())
999 return;
1000
1001 assert(uim_scm_gc_any_contextp());
1002 assert(uc);
1003
1004 UIM_CATCH_ERROR_END();
1005 }
1006
1007 void
uim_prop_activate(uim_context uc,const char * str)1008 uim_prop_activate(uim_context uc, const char *str)
1009 {
1010 if (UIM_CATCH_ERROR_BEGIN())
1011 return;
1012
1013 assert(uim_scm_gc_any_contextp());
1014 assert(uc);
1015 assert(str);
1016
1017 uim_scm_callf("prop-activate-handler", "ps", uc, str);
1018
1019 UIM_CATCH_ERROR_END();
1020 }
1021
1022 /****************************************************************
1023 * Legacy 'custom' API *
1024 ****************************************************************/
1025 /* Tentative name. I followed above uim_prop_update_custom, but prop
1026 would not be proper to this function. */
1027 /*
1028 * As I described in doc/HELPER-PROTOCOL, it had wrongly named by my
1029 * misunderstanding about what is the 'property' of uim. It should be
1030 * renamed along with corresponding procol names when an appropriate
1031 * time has come. -- YamaKen 2005-09-12
1032 */
1033 /** Update custom value from property message.
1034 * Update custom value from property message. The implementation
1035 * avoids arbitrary sexp evaluation for both custom symbol \a custom
1036 * and custom value \a val.
1037 */
1038 void
uim_prop_update_custom(uim_context uc,const char * custom,const char * val)1039 uim_prop_update_custom(uim_context uc, const char *custom, const char *val)
1040 {
1041 if (UIM_CATCH_ERROR_BEGIN())
1042 return;
1043
1044 assert(uim_scm_gc_any_contextp());
1045 assert(uc);
1046 assert(custom);
1047 assert(val);
1048
1049 uim_scm_callf("custom-set-handler", "pys", uc, custom, val);
1050
1051 UIM_CATCH_ERROR_END();
1052 }
1053
1054 uim_bool
uim_prop_reload_configs(void)1055 uim_prop_reload_configs(void)
1056 {
1057 if (UIM_CATCH_ERROR_BEGIN())
1058 return UIM_FALSE;
1059
1060 assert(uim_scm_gc_any_contextp());
1061
1062 /* FIXME: handle return value properly. */
1063 uim_scm_callf("custom-reload-user-configs", "");
1064
1065 UIM_CATCH_ERROR_END();
1066
1067 return UIM_TRUE;
1068 }
1069
1070 /****************************************************************
1071 * Legacy nth-index based IM management APIs *
1072 ****************************************************************/
1073 int
uim_get_nr_im(uim_context uc)1074 uim_get_nr_im(uim_context uc)
1075 {
1076 uim_lisp n_;
1077 int n;
1078
1079 if (UIM_CATCH_ERROR_BEGIN())
1080 return 0;
1081
1082 assert(uim_scm_gc_any_contextp());
1083 assert(uc);
1084
1085 protected0 = n_ = uim_scm_callf("uim-n-convertible-ims", "p", uc);
1086 n = C_INT(n_);
1087
1088 UIM_CATCH_ERROR_END();
1089
1090 return n;
1091 }
1092
1093 static uim_lisp
get_nth_im(uim_context uc,int nth)1094 get_nth_im(uim_context uc, int nth)
1095 {
1096 assert(uim_scm_gc_any_contextp());
1097 assert(uc);
1098 assert(nth >= 0);
1099
1100 return uim_scm_callf("uim-nth-convertible-im", "pi", uc, nth);
1101 }
1102
1103 const char *
uim_get_im_name(uim_context uc,int nth)1104 uim_get_im_name(uim_context uc, int nth)
1105 {
1106 uim_lisp im, str_;
1107 const char *str;
1108
1109 if (UIM_CATCH_ERROR_BEGIN())
1110 return NULL;
1111
1112 protected0 = im = get_nth_im(uc, nth);
1113 protected1 = str_ = uim_scm_callf("im-name", "o", im);
1114 str = REFER_C_STR(str_);
1115
1116 UIM_CATCH_ERROR_END();
1117
1118 return str;
1119 }
1120
1121 const char *
uim_get_im_language(uim_context uc,int nth)1122 uim_get_im_language(uim_context uc, int nth)
1123 {
1124 uim_lisp im, str_;
1125 const char *str;
1126
1127 if (UIM_CATCH_ERROR_BEGIN())
1128 return NULL;
1129
1130 protected0 = im = get_nth_im(uc, nth);
1131 protected1 = str_ = uim_scm_callf("im-lang", "o", im);
1132 str = REFER_C_STR(str_);
1133
1134 UIM_CATCH_ERROR_END();
1135
1136 return str;
1137 }
1138
1139 const char *
uim_get_im_encoding(uim_context uc,int nth)1140 uim_get_im_encoding(uim_context uc, int nth)
1141 {
1142 uim_lisp im, str_;
1143 const char *str;
1144
1145 if (UIM_CATCH_ERROR_BEGIN())
1146 return NULL;
1147
1148 protected0 = im = get_nth_im(uc, nth);
1149 protected1 = str_ = uim_scm_callf("im-encoding", "o", im);
1150 str = REFER_C_STR(str_);
1151
1152 UIM_CATCH_ERROR_END();
1153
1154 return str;
1155 }
1156
1157 const char *
uim_get_im_short_desc(uim_context uc,int nth)1158 uim_get_im_short_desc(uim_context uc, int nth)
1159 {
1160 uim_lisp im, short_desc;
1161 const char *str;
1162
1163 if (UIM_CATCH_ERROR_BEGIN())
1164 return NULL;
1165
1166 protected0 = im = get_nth_im(uc, nth);
1167 protected1 = short_desc = uim_scm_callf("im-short-desc", "o", im);
1168 str = (FALSEP(short_desc)) ? "-" : REFER_C_STR(short_desc);
1169
1170 UIM_CATCH_ERROR_END();
1171
1172 return str;
1173 }
1174