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 <ctype.h>
37 #include <string.h>
38 #include <stdlib.h>
39 #include <assert.h>
40
41 #include "uim-internal.h"
42 #include "uim-scm.h"
43 #include "uim-scm-abbrev.h"
44 #include "uim-im-switcher.h"
45
46
47 #define TEXT_EMPTYP(txt) (!(txt) || !(txt)[0])
48
49
50 /* this is not a uim API, so did not name as uim_retrieve_context() */
51 static uim_context
retrieve_uim_context(uim_lisp c)52 retrieve_uim_context(uim_lisp c)
53 {
54 uim_context uc;
55
56 if (CONSP(c)) /* passed as Scheme-side input context */
57 c = CAR(c);
58
59 uc = C_PTR(c);
60 assert(uc);
61
62 return uc;
63 }
64
65 /* extract Scheme IM context from Scheme-object-wrapped uim_context */
66 static uim_lisp
im_retrieve_context(uim_lisp uc_)67 im_retrieve_context(uim_lisp uc_)
68 {
69 uim_context uc;
70
71 uc = C_PTR(uc_);
72 assert(uc);
73
74 return uc->sc;
75 }
76
77 static uim_lisp
im_convertiblep(uim_lisp uc_,uim_lisp im_encoding_)78 im_convertiblep(uim_lisp uc_, uim_lisp im_encoding_)
79 {
80 uim_context uc;
81 const char *im_encoding;
82 uim_bool convertiblep;
83
84 uc = retrieve_uim_context(uc_);
85 im_encoding = REFER_C_STR(im_encoding_);
86 convertiblep = uc->conv_if->is_convertible(uc->client_encoding, im_encoding);
87
88 return MAKE_BOOL(convertiblep);
89 }
90
91 static uim_lisp
im_clear_preedit(uim_lisp uc_)92 im_clear_preedit(uim_lisp uc_)
93 {
94 uim_context uc;
95
96 uc = retrieve_uim_context(uc_);
97 if (uc->preedit_clear_cb)
98 uc->preedit_clear_cb(uc->ptr);
99
100 return uim_scm_f();
101 }
102
103 static uim_lisp
im_pushback_preedit(uim_lisp uc_,uim_lisp attr_,uim_lisp str_)104 im_pushback_preedit(uim_lisp uc_, uim_lisp attr_, uim_lisp str_)
105 {
106 uim_context uc;
107 const char *str;
108 char *converted_str;
109 int attr;
110
111 uc = retrieve_uim_context(uc_);
112 attr = C_INT(attr_);
113 str = REFER_C_STR(str_);
114
115 converted_str = uc->conv_if->convert(uc->outbound_conv, str);
116 if (uc->preedit_pushback_cb)
117 uc->preedit_pushback_cb(uc->ptr, attr, converted_str);
118 free(converted_str);
119
120 return uim_scm_f();
121 }
122
123 static uim_lisp
im_update_preedit(uim_lisp uc_)124 im_update_preedit(uim_lisp uc_)
125 {
126 uim_context uc;
127
128 uc = retrieve_uim_context(uc_);
129 if (uc->preedit_update_cb)
130 uc->preedit_update_cb(uc->ptr);
131
132 return uim_scm_f();
133 }
134
135 static uim_lisp
im_commit(uim_lisp uc_,uim_lisp str_)136 im_commit(uim_lisp uc_, uim_lisp str_)
137 {
138 uim_context uc;
139 const char *str;
140 char *converted_str;
141
142 uc = retrieve_uim_context(uc_);
143 str = REFER_C_STR(str_);
144
145 converted_str = uc->conv_if->convert(uc->outbound_conv, str);
146 if (uc->commit_cb)
147 uc->commit_cb(uc->ptr, converted_str);
148 free(converted_str);
149
150 return uim_scm_f();
151 }
152
153 static uim_lisp
im_set_encoding(uim_lisp uc_,uim_lisp enc_)154 im_set_encoding(uim_lisp uc_, uim_lisp enc_)
155 {
156 uim_context uc;
157 const char *enc;
158
159 uc = retrieve_uim_context(uc_);
160 enc = REFER_C_STR(enc_);
161
162 uim_set_encoding(uc, enc);
163
164 return uim_scm_f();
165 }
166
167 void
uim_set_encoding(uim_context uc,const char * enc)168 uim_set_encoding(uim_context uc, const char *enc)
169 {
170 assert(uc);
171 assert(enc);
172
173 if (uc->outbound_conv)
174 uc->conv_if->release(uc->outbound_conv);
175 if (uc->inbound_conv)
176 uc->conv_if->release(uc->inbound_conv);
177
178 if (!strcmp(uc->client_encoding, enc)) {
179 uc->outbound_conv = NULL;
180 uc->inbound_conv = NULL;
181 } else {
182 uc->outbound_conv = uc->conv_if->create(uc->client_encoding, enc);
183 uc->inbound_conv = uc->conv_if->create(enc, uc->client_encoding);
184 }
185 }
186
187 static uim_lisp
im_clear_mode_list(uim_lisp uc_)188 im_clear_mode_list(uim_lisp uc_)
189 {
190 uim_context uc;
191 int i;
192
193 uc = retrieve_uim_context(uc_);
194
195 for (i = 0; i < uc->nr_modes; i++) {
196 if (uc->modes[i]) {
197 free(uc->modes[i]);
198 uc->modes[i] = NULL;
199 }
200 }
201 if (uc->modes) {
202 free(uc->modes);
203 uc->modes = NULL;
204 }
205 uc->nr_modes = 0;
206
207 return uim_scm_f();
208 }
209
210 static uim_lisp
im_pushback_mode_list(uim_lisp uc_,uim_lisp str_)211 im_pushback_mode_list(uim_lisp uc_, uim_lisp str_)
212 {
213 uim_context uc;
214 const char *str;
215
216 uc = retrieve_uim_context(uc_);
217 str = REFER_C_STR(str_);
218
219 uc->modes = uim_realloc(uc->modes, sizeof(char *) * (uc->nr_modes + 1));
220 uc->modes[uc->nr_modes] = uc->conv_if->convert(uc->outbound_conv, str);
221 uc->nr_modes++;
222
223 return uim_scm_f();
224 }
225
226 static uim_lisp
im_update_mode_list(uim_lisp uc_)227 im_update_mode_list(uim_lisp uc_)
228 {
229 uim_context uc;
230
231 uc = retrieve_uim_context(uc_);
232
233 if (uc->mode_list_update_cb)
234 uc->mode_list_update_cb(uc->ptr);
235
236 return uim_scm_f();
237 }
238
239 static uim_lisp
im_update_prop_list(uim_lisp uc_,uim_lisp prop_)240 im_update_prop_list(uim_lisp uc_, uim_lisp prop_)
241 {
242 uim_context uc;
243 const char *prop;
244
245 uc = retrieve_uim_context(uc_);
246 prop = REFER_C_STR(prop_);
247
248 free(uc->propstr);
249 uc->propstr = uc->conv_if->convert(uc->outbound_conv, prop);
250
251 if (uc->prop_list_update_cb)
252 uc->prop_list_update_cb(uc->ptr, uc->propstr);
253
254 return uim_scm_f();
255 }
256
257 static uim_lisp
im_update_mode(uim_lisp uc_,uim_lisp mode_)258 im_update_mode(uim_lisp uc_, uim_lisp mode_)
259 {
260 uim_context uc;
261 int mode;
262
263 uc = retrieve_uim_context(uc_);
264 mode = C_INT(mode_);
265
266 uc->mode = mode;
267 if (uc->mode_update_cb)
268 uc->mode_update_cb(uc->ptr, mode);
269
270 return uim_scm_f();
271 }
272
273 static uim_lisp
im_activate_candidate_selector(uim_lisp uc_,uim_lisp nr_,uim_lisp display_limit_)274 im_activate_candidate_selector(uim_lisp uc_,
275 uim_lisp nr_, uim_lisp display_limit_)
276 {
277 uim_context uc;
278 int nr, display_limit;
279
280 uc = retrieve_uim_context(uc_);
281 nr = C_INT(nr_);
282 display_limit = C_INT(display_limit_);
283
284 if (uc->candidate_selector_activate_cb)
285 uc->candidate_selector_activate_cb(uc->ptr, nr, display_limit);
286
287 return uim_scm_f();
288 }
289
290 static uim_lisp
im_delay_activate_candidate_selector(uim_lisp uc_,uim_lisp delay_)291 im_delay_activate_candidate_selector(uim_lisp uc_, uim_lisp delay_)
292 {
293 uim_context uc;
294 int delay;
295
296 uc = retrieve_uim_context(uc_);
297 delay = C_INT(delay_);
298
299 if (uc->candidate_selector_delay_activate_cb)
300 uc->candidate_selector_delay_activate_cb(uc->ptr, delay);
301
302 return uim_scm_f();
303 }
304
305 static uim_lisp
im_select_candidate(uim_lisp uc_,uim_lisp idx_)306 im_select_candidate(uim_lisp uc_, uim_lisp idx_)
307 {
308 uim_context uc;
309 int idx;
310
311 uc = retrieve_uim_context(uc_);
312 idx = C_INT(idx_);
313
314 if (uc->candidate_selector_select_cb)
315 uc->candidate_selector_select_cb(uc->ptr, idx);
316
317 return uim_scm_f();
318 }
319
320
321 /* My naming sense seems bad... */
322 static uim_lisp
im_shift_page_candidate(uim_lisp uc_,uim_lisp dir_)323 im_shift_page_candidate(uim_lisp uc_, uim_lisp dir_)
324 {
325 uim_context uc;
326 int dir;
327
328 uc = retrieve_uim_context(uc_);
329 dir = (C_BOOL(dir_)) ? 1 : 0;
330
331 if (uc->candidate_selector_shift_page_cb)
332 uc->candidate_selector_shift_page_cb(uc->ptr, dir);
333
334 return uim_scm_f();
335 }
336
337 static uim_lisp
im_deactivate_candidate_selector(uim_lisp uc_)338 im_deactivate_candidate_selector(uim_lisp uc_)
339 {
340 uim_context uc;
341
342 uc = retrieve_uim_context(uc_);
343
344 if (uc->candidate_selector_deactivate_cb)
345 uc->candidate_selector_deactivate_cb(uc->ptr);
346
347 return uim_scm_f();
348 }
349
350 static uim_lisp
im_delay_activate_candidate_selector_supportedp(uim_lisp uc_)351 im_delay_activate_candidate_selector_supportedp(uim_lisp uc_)
352 {
353 uim_context uc;
354
355 uc = retrieve_uim_context(uc_);
356
357 if (uc->candidate_selector_delay_activate_cb)
358 return uim_scm_t();
359 return uim_scm_f();
360 }
361
362 static uim_lisp
im_acquire_text(uim_lisp uc_,uim_lisp text_id_,uim_lisp origin_,uim_lisp former_len_,uim_lisp latter_len_)363 im_acquire_text(uim_lisp uc_, uim_lisp text_id_, uim_lisp origin_,
364 uim_lisp former_len_, uim_lisp latter_len_)
365 {
366 uim_context uc;
367 int err, former_len, latter_len;
368 enum UTextArea text_id;
369 enum UTextOrigin origin;
370 char *former, *latter, *cv_former, *cv_latter;
371 uim_lisp former_, latter_;
372
373 uc = retrieve_uim_context(uc_);
374
375 if (!uc->acquire_text_cb)
376 return uim_scm_f();
377
378 text_id = C_INT(text_id_);
379 origin = C_INT(origin_);
380 former_len = C_INT(former_len_);
381 latter_len = C_INT(latter_len_);
382
383 err = uc->acquire_text_cb(uc->ptr, text_id, origin,
384 former_len, latter_len, &former, &latter);
385 if (err)
386 return uim_scm_f();
387
388 /* FIXME: string->list is not applied here for each text part. This
389 * interface should be revised when SigScheme has been introduced to
390 * uim. Until then, perform character separation by each input methods if
391 * needed. -- YamaKen 2006-10-07 */
392 cv_former = uc->conv_if->convert(uc->inbound_conv, former);
393 cv_latter = uc->conv_if->convert(uc->inbound_conv, latter);
394 free(former);
395 free(latter);
396 former_
397 = (TEXT_EMPTYP(cv_former)) ? uim_scm_null() : LIST1(MAKE_STR_DIRECTLY(cv_former));
398 latter_
399 = (TEXT_EMPTYP(cv_latter)) ? uim_scm_null() : LIST1(MAKE_STR_DIRECTLY(cv_latter));
400
401 return uim_scm_callf("ustr-new", "oo", former_, latter_);
402 }
403
404 static uim_lisp
im_delete_text(uim_lisp uc_,uim_lisp text_id_,uim_lisp origin_,uim_lisp former_len_,uim_lisp latter_len_)405 im_delete_text(uim_lisp uc_, uim_lisp text_id_, uim_lisp origin_,
406 uim_lisp former_len_, uim_lisp latter_len_)
407 {
408 uim_context uc;
409 int err, former_len, latter_len;
410 enum UTextArea text_id;
411 enum UTextOrigin origin;
412
413 uc = retrieve_uim_context(uc_);
414
415 if (!uc->delete_text_cb)
416 return uim_scm_f();
417
418 text_id = C_INT(text_id_);
419 origin = C_INT(origin_);
420 former_len = C_INT(former_len_);
421 latter_len = C_INT(latter_len_);
422
423 err = uc->delete_text_cb(uc->ptr, text_id, origin, former_len, latter_len);
424
425 return MAKE_BOOL(!err);
426 }
427
428 static uim_lisp
raise_configuration_change(uim_lisp uc_)429 raise_configuration_change(uim_lisp uc_)
430 {
431 uim_context uc;
432
433 uc = retrieve_uim_context(uc_);
434
435 if (uc->configuration_changed_cb)
436 uc->configuration_changed_cb(uc->ptr);
437
438 return uim_scm_t();
439 }
440
441 static uim_lisp
switch_app_global_im(uim_lisp uc_,uim_lisp name_)442 switch_app_global_im(uim_lisp uc_, uim_lisp name_)
443 {
444 uim_context uc;
445 const char *name;
446
447 uc = retrieve_uim_context(uc_);
448 name = REFER_C_STR(name_);
449
450 if (uc->switch_app_global_im_cb)
451 uc->switch_app_global_im_cb(uc->ptr, name);
452
453 return uim_scm_t();
454 }
455
456 static uim_lisp
switch_system_global_im(uim_lisp uc_,uim_lisp name_)457 switch_system_global_im(uim_lisp uc_, uim_lisp name_)
458 {
459 uim_context uc;
460 const char *name;
461
462 uc = retrieve_uim_context(uc_);
463 name = REFER_C_STR(name_);
464
465 if (uc->switch_system_global_im_cb)
466 uc->switch_system_global_im_cb(uc->ptr, name);
467
468 return uim_scm_t();
469 }
470
471 void
uim_init_im_subrs(void)472 uim_init_im_subrs(void)
473 {
474 uim_scm_init_proc1("im-retrieve-context", im_retrieve_context);
475 uim_scm_init_proc2("im-set-encoding", im_set_encoding);
476 uim_scm_init_proc2("im-convertible?", im_convertiblep);
477
478 uim_scm_init_proc2("im-commit", im_commit);
479 uim_scm_init_proc1("im-clear-preedit", im_clear_preedit);
480 uim_scm_init_proc3("im-pushback-preedit", im_pushback_preedit);
481 uim_scm_init_proc1("im-update-preedit", im_update_preedit);
482
483 uim_scm_init_proc3("im-activate-candidate-selector",
484 im_activate_candidate_selector);
485 uim_scm_init_proc2("im-select-candidate", im_select_candidate);
486 uim_scm_init_proc2("im-shift-page-candidate", im_shift_page_candidate);
487 uim_scm_init_proc1("im-deactivate-candidate-selector",
488 im_deactivate_candidate_selector);
489
490 uim_scm_init_proc2("im-delay-activate-candidate-selector",
491 im_delay_activate_candidate_selector);
492 uim_scm_init_proc1("im-delay-activate-candidate-selector-supported?",
493 im_delay_activate_candidate_selector_supportedp);
494
495 uim_scm_init_proc5("im-acquire-text-internal", im_acquire_text);
496 uim_scm_init_proc5("im-delete-text-internal", im_delete_text);
497
498 uim_scm_init_proc1("im-clear-mode-list", im_clear_mode_list);
499 uim_scm_init_proc2("im-pushback-mode-list", im_pushback_mode_list);
500 uim_scm_init_proc1("im-update-mode-list", im_update_mode_list);
501 uim_scm_init_proc2("im-update-mode", im_update_mode);
502
503 uim_scm_init_proc2("im-update-prop-list", im_update_prop_list);
504
505 uim_scm_init_proc1("im-raise-configuration-change",
506 raise_configuration_change);
507 uim_scm_init_proc2("im-switch-app-global-im", switch_app_global_im);
508 uim_scm_init_proc2("im-switch-system-global-im", switch_system_global_im);
509 }
510