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 #include <config.h>
34
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <anthy/anthy.h>
39
40 #include "uim.h"
41 #include "uim-scm.h"
42 #include "uim-scm-abbrev.h"
43 #include "dynlib.h"
44
45
46 #ifdef ENABLE_ANTHY_STATIC
47 void uim_anthy_plugin_instance_init(void);
48 void uim_anthy_plugin_instance_quit(void);
49 #endif
50
51 static uim_bool initialized;
52 static uim_lisp context_list;
53
54 static void
validate_segment_index(anthy_context_t ac,int i)55 validate_segment_index(anthy_context_t ac, int i)
56 {
57 int err;
58 struct anthy_conv_stat cs;
59
60 err = anthy_get_stat(ac, &cs);
61 if (err)
62 uim_fatal_error("anthy_get_stat() failed");
63 if (!(0 <= i && i < cs.nr_segment))
64 ERROR_OBJ("invalid segment index", MAKE_INT(i));
65 }
66
67 static anthy_context_t
get_anthy_context(uim_lisp ac_)68 get_anthy_context(uim_lisp ac_)
69 {
70 anthy_context_t ac;
71
72 ac = C_PTR(ac_);
73 if (!ac)
74 uim_fatal_error("NULL anthy_context_t");
75
76 return ac;
77 }
78
79 static uim_lisp
anthy_version()80 anthy_version()
81 {
82 return MAKE_STR(anthy_get_version_string());
83 }
84
85 static uim_lisp
init_anthy_lib(void)86 init_anthy_lib(void)
87 {
88 if (!initialized) {
89 if (anthy_init() == -1)
90 uim_fatal_error("anthy_init() failed");
91
92 initialized = UIM_TRUE;
93 }
94
95 return uim_scm_t();
96 }
97
98 static uim_lisp
create_context(void)99 create_context(void)
100 {
101 anthy_context_t ac;
102 uim_lisp ac_;
103
104 ac = anthy_create_context();
105 if (!ac)
106 uim_fatal_error("anthy_create_context() failed");
107
108 ac_ = MAKE_PTR(ac);
109 context_list = uim_scm_callf("cons", "oo", ac_, context_list);
110
111 return ac_;
112 }
113
114
115 static uim_lisp
release_context(uim_lisp ac_)116 release_context(uim_lisp ac_)
117 {
118 anthy_context_t ac;
119
120 context_list = uim_scm_callf("delete!", "oo", ac_, context_list);
121
122 ac = get_anthy_context(ac_);
123 anthy_release_context(ac);
124 uim_scm_nullify_c_ptr(ac_);
125
126 return uim_scm_f();
127 }
128
129 static uim_lisp
set_string(uim_lisp ac_,uim_lisp str_)130 set_string(uim_lisp ac_, uim_lisp str_)
131 {
132 anthy_context_t ac;
133 const char *str;
134
135 ac = get_anthy_context(ac_);
136 str = REFER_C_STR(str_);
137 anthy_set_string(ac, str);
138
139 return uim_scm_f();
140 }
141
142 static uim_lisp
get_nr_segments(uim_lisp ac_)143 get_nr_segments(uim_lisp ac_)
144 {
145 anthy_context_t ac;
146 struct anthy_conv_stat cs;
147 int err;
148
149 ac = get_anthy_context(ac_);
150 err = anthy_get_stat(ac, &cs);
151 if (err)
152 uim_fatal_error("anthy_get_stat() failed");
153
154 return MAKE_INT(cs.nr_segment);
155 }
156
157 static uim_lisp
get_nr_candidates(uim_lisp ac_,uim_lisp seg_)158 get_nr_candidates(uim_lisp ac_, uim_lisp seg_)
159 {
160 anthy_context_t ac;
161 int seg, err;
162 struct anthy_segment_stat ss;
163
164 ac = get_anthy_context(ac_);
165 seg = C_INT(seg_);
166
167 validate_segment_index(ac, seg);
168
169 err = anthy_get_segment_stat(ac, seg, &ss);
170 if (err)
171 uim_fatal_error("anthy_get_segment_stat() failed");
172
173 return MAKE_INT(ss.nr_candidate);
174 }
175
176 static uim_lisp
get_nth_candidate(uim_lisp ac_,uim_lisp seg_,uim_lisp nth_)177 get_nth_candidate(uim_lisp ac_, uim_lisp seg_, uim_lisp nth_)
178 {
179 anthy_context_t ac;
180 int seg, nth, buflen;
181 char *buf;
182 uim_lisp buf_;
183
184 ac = get_anthy_context(ac_);
185 seg = C_INT(seg_);
186 nth = C_INT(nth_);
187
188 buflen = anthy_get_segment(ac, seg, nth, NULL, 0);
189 if (buflen == -1)
190 uim_fatal_error("anthy_get_segment() failed");
191
192 buf = uim_malloc(buflen + 1);
193 buflen = anthy_get_segment(ac, seg, nth, buf, buflen + 1);
194 if (buflen == -1) {
195 free(buf);
196 uim_fatal_error("anthy_get_segment() failed");
197 }
198 buf_ = MAKE_STR_DIRECTLY(buf);
199
200 return buf_;
201 }
202
203 static uim_lisp
get_unconv_candidate(uim_lisp ac_,uim_lisp seg_)204 get_unconv_candidate(uim_lisp ac_, uim_lisp seg_)
205 {
206 uim_lisp nth_;
207
208 nth_ = MAKE_INT(NTH_UNCONVERTED_CANDIDATE);
209 return get_nth_candidate(ac_, seg_, nth_);
210 }
211
212 static uim_lisp
get_segment_length(uim_lisp ac_,uim_lisp seg_)213 get_segment_length(uim_lisp ac_, uim_lisp seg_)
214 {
215 anthy_context_t ac;
216 int seg, err;
217 struct anthy_segment_stat ss;
218
219 ac = get_anthy_context(ac_);
220 seg = C_INT(seg_);
221
222 validate_segment_index(ac, seg);
223
224 err = anthy_get_segment_stat(ac, seg, &ss);
225 if (err)
226 uim_fatal_error("anthy_get_segment_stat() failed");
227
228 return MAKE_INT(ss.seg_len);
229 }
230
231 static uim_lisp
resize_segment(uim_lisp ac_,uim_lisp seg_,uim_lisp delta_)232 resize_segment(uim_lisp ac_, uim_lisp seg_, uim_lisp delta_)
233 {
234 anthy_context_t ac;
235 int seg, delta;
236
237 ac = get_anthy_context(ac_);
238 seg = C_INT(seg_);
239 delta = C_INT(delta_);
240
241 anthy_resize_segment(ac, seg, delta);
242 return uim_scm_f();
243 }
244
245 static uim_lisp
commit_segment(uim_lisp ac_,uim_lisp seg_,uim_lisp nth_)246 commit_segment(uim_lisp ac_, uim_lisp seg_, uim_lisp nth_)
247 {
248 anthy_context_t ac;
249 int seg, nth;
250
251 ac = get_anthy_context(ac_);
252 seg = C_INT(seg_);
253 nth = C_INT(nth_);
254
255 anthy_commit_segment(ac, seg, nth);
256 return uim_scm_f();
257 }
258
259 static uim_lisp
set_prediction_src_string(uim_lisp ac_,uim_lisp str_)260 set_prediction_src_string(uim_lisp ac_, uim_lisp str_)
261 {
262 #ifdef HAS_ANTHY_PREDICTION
263 anthy_context_t ac;
264 const char *str;
265
266 ac = get_anthy_context(ac_);
267 str = REFER_C_STR(str_);
268
269 anthy_set_prediction_string(ac, str);
270 #endif
271 return uim_scm_f();
272 }
273
274 static uim_lisp
get_nr_predictions(uim_lisp ac_)275 get_nr_predictions(uim_lisp ac_)
276 {
277 #ifdef HAS_ANTHY_PREDICTION
278 anthy_context_t ac;
279 struct anthy_prediction_stat ps;
280 int err;
281
282 ac = get_anthy_context(ac_);
283
284 err = anthy_get_prediction_stat(ac, &ps);
285 if (err)
286 uim_fatal_error("anthy_get_prediction_stat() failed");
287 return MAKE_INT(ps.nr_prediction);
288 #else
289 return uim_scm_f();
290 #endif
291 }
292
293 static uim_lisp
get_nth_prediction(uim_lisp ac_,uim_lisp nth_)294 get_nth_prediction(uim_lisp ac_, uim_lisp nth_)
295 {
296 #ifdef HAS_ANTHY_PREDICTION
297 anthy_context_t ac;
298 int nth, buflen;
299 char *buf;
300 uim_lisp buf_;
301
302 ac = get_anthy_context(ac_);
303 nth = C_INT(nth_);
304
305 buflen = anthy_get_prediction(ac, nth, NULL, 0);
306 if (buflen == -1)
307 uim_fatal_error("anthy_get_prediction() failed");
308
309 buf = uim_malloc(buflen + 1);
310 buflen = anthy_get_prediction(ac, nth, buf, buflen + 1);
311 if (buflen == -1) {
312 free(buf);
313 uim_fatal_error("anthy_get_prediction() failed");
314 }
315 buf_ = MAKE_STR_DIRECTLY(buf);
316
317 return buf_;
318 #else
319 return uim_scm_f();
320 #endif
321 }
322
323 static uim_lisp
commit_nth_prediction(uim_lisp ac_,uim_lisp nth_)324 commit_nth_prediction(uim_lisp ac_, uim_lisp nth_)
325 {
326 #ifdef HAS_ANTHY_COMMIT_PREDICTION
327 anthy_context_t ac;
328 int nth, err;
329
330 ac = get_anthy_context(ac_);
331 nth = C_INT(nth_);
332
333 err = anthy_commit_prediction(ac, nth);
334
335 return MAKE_BOOL(!err);
336 #else
337 return uim_scm_f();
338 #endif
339 }
340
341 #ifndef ENABLE_ANTHY_STATIC
342 void
uim_plugin_instance_init(void)343 uim_plugin_instance_init(void)
344 #else
345 void
346 uim_anthy_plugin_instance_init(void)
347 #endif
348 {
349 context_list = uim_scm_null();
350 uim_scm_gc_protect(&context_list);
351
352 uim_scm_eval_c_string("(require-extension (srfi 1))"); /* for delete! */
353
354 uim_scm_init_proc0("anthy-lib-init", init_anthy_lib);
355 uim_scm_init_proc0("anthy-lib-alloc-context", create_context);
356 uim_scm_init_proc1("anthy-lib-free-context", release_context);
357 uim_scm_init_proc2("anthy-lib-set-string", set_string);
358 uim_scm_init_proc1("anthy-lib-get-nr-segments",get_nr_segments);
359 uim_scm_init_proc2("anthy-lib-get-nr-candidates", get_nr_candidates);
360 uim_scm_init_proc3("anthy-lib-get-nth-candidate", get_nth_candidate);
361 uim_scm_init_proc2("anthy-lib-get-unconv-candidate", get_unconv_candidate);
362 uim_scm_init_proc2("anthy-lib-get-segment-length", get_segment_length);
363 uim_scm_init_proc3("anthy-lib-resize-segment", resize_segment);
364 uim_scm_init_proc3("anthy-lib-commit-segment", commit_segment);
365 uim_scm_init_proc0("anthy-lib-get-anthy-version", anthy_version);
366 uim_scm_init_proc2("anthy-lib-set-prediction-src-string", set_prediction_src_string);
367 uim_scm_init_proc1("anthy-lib-get-nr-predictions", get_nr_predictions);
368 uim_scm_init_proc2("anthy-lib-get-nth-prediction", get_nth_prediction);
369 uim_scm_init_proc2("anthy-lib-commit-nth-prediction",
370 commit_nth_prediction);
371 }
372
373 #ifndef ENABLE_ANTHY_STATIC
374 void
uim_plugin_instance_quit(void)375 uim_plugin_instance_quit(void)
376 #else
377 void
378 uim_anthy_plugin_instance_quit(void)
379 #endif
380 {
381 if (initialized) {
382 uim_scm_callf("for-each", "vo", "anthy-lib-free-context", context_list);
383 context_list = uim_scm_null();
384 uim_scm_gc_unprotect(&context_list);
385
386 anthy_quit();
387 initialized = UIM_FALSE;
388 }
389 }
390