2
canna.c: Canna for uim.
4
Copyright (c) 2003,2004 uim Project http://uim.freedesktop.org/
8
Redistribution and use in source and binary forms, with or without
9
modification, are permitted provided that the following conditions
12
1. Redistributions of source code must retain the above copyright
13
notice, this list of conditions and the following disclaimer.
14
2. Redistributions in binary form must reproduce the above copyright
15
notice, this list of conditions and the following disclaimer in the
16
documentation and/or other materials provided with the distribution.
17
3. Neither the name of authors nor the names of its contributors
18
may be used to endorse or promote products derived from this software
19
without specific prior written permission.
21
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35
#ifdef HAVE_CANNA_RK_H
43
#define MAX_CONTEXT 256
44
#define LIBCANNA_SO "libcanna.so"
50
struct canna_context {
51
char diclist[BUFSIZE];
57
int max_current_cand_num;
60
int current_segment_num;
63
static struct canna_context *context_array = NULL;
65
static int context_array_len;
66
static int rk_initialized = -1;
67
static char *cannaserver = NULL;
69
static struct canna_api {
71
/* struct rkfuncs Rk; */
72
int (*RkInitialize)(char *);
73
int (*RkCreateContext)(void);
74
int (*RkCloseContext)(int);
75
int (*RkBgnBun)(int, char *, int, int);
76
int (*RkEndBun)(int, int);
77
int (*RkFinalize)(void);
78
int (*RkGetDicList)(int, char*, int);
79
int (*RkMountDic)(int, char*, int);
81
int (*RkXfer)(int, int);
82
int (*RkEnlarge)(int);
83
int (*RkShorten)(int);
84
int (*RkGetStat)(int, RkStat*);
85
int (*RkGoTo)(int, int);
86
int (*RkGetKanji)(int, char*, int);
87
int (*RkGetKanjiList)(int, char*, int);
88
int (*RkSetServerName)(char*);
94
api.lib = dlopen(LIBCANNA_SO, RTLD_NOW);
98
api.RkInitialize = dlsym(api.lib, "RkInitialize");
99
api.RkFinalize = dlsym(api.lib, "RkFinalize");
100
api.RkGetDicList = dlsym(api.lib, "RkGetDicList");
101
api.RkMountDic = dlsym(api.lib, "RkMountDic");
102
api.RkCreateContext = dlsym(api.lib, "RkCreateContext");
103
api.RkCloseContext = dlsym(api.lib, "RkCloseContext");
104
api.RkBgnBun = dlsym(api.lib, "RkBgnBun");
105
api.RkEndBun = dlsym(api.lib, "RkEndBun");
106
api.RkGoTo = dlsym(api.lib, "RkGoTo");
107
api.RkGetKanji = dlsym(api.lib, "RkGetKanji");
108
api.RkGetKanjiList = dlsym(api.lib, "RkGetKanjiList");
109
api.RkGetStat = dlsym(api.lib, "RkGetStat");
110
api.RkXfer = dlsym(api.lib, "RkXfer");
111
api.RkNfer = dlsym(api.lib, "RkXfer");
112
api.RkEnlarge = dlsym(api.lib, "RkEnlarge");
113
api.RkShorten = dlsym(api.lib, "RkShorten");
114
if(api.RkInitialize && api.RkFinalize && api.RkGetDicList &&
115
api.RkMountDic && api.RkCreateContext && api.RkCloseContext &&
116
api.RkBgnBun && api.RkEndBun && api.RkGoTo && api.RkGetKanji &&
117
api.RkGetKanjiList && api.RkGetStat && api.RkXfer && api.RkNfer &&
118
api.RkEnlarge && api.RkShorten)
126
static struct canna_context *
127
get_canna_context(int id)
130
struct canna_context *context;
132
context = context_array;
134
if(id >= MAX_CONTEXT || id < 0)
136
for(i = 0; i < id; i++)
139
/* printf("rk_context_id: %d\n", context->rk_context_id);
140
printf("segment_num: %d\n", context->segment_num); */
145
init_canna_lib(LISP str_)
147
struct canna_context *context;
150
if (get_canna_api() == -1)
154
cannaserver = uim_get_c_string(str_);
158
context_array = malloc(sizeof(struct canna_context) * MAX_CONTEXT);
159
if(context_array == NULL)
162
context = context_array;
164
for (i = 0; i < MAX_CONTEXT; i++) {
165
context->rk_context_id = -1;
166
context->rk_mode = (RK_XFER << RK_XFERBITS) | RK_KFER;
168
context->current_cand_num = -1;
169
context->max_current_cand_num = -1;
171
context->segment_num = -1;
172
context->current_segment_num = -1;
174
context->diclist[0] = '\0';
186
struct canna_context *cc = context_array;
188
if(rk_initialized == -1) {
189
if(api.RkInitialize(cannaserver) == -1) {
190
fprintf(stderr, "%s\n", strerror(errno));
196
for(i = 0; i < MAX_CONTEXT; i++) {
197
if(cc->rk_context_id == -1) {
199
cc->rk_context_id = api.RkCreateContext();
200
dic_num = api.RkGetDicList(cc->rk_context_id,
201
cc->diclist, BUFSIZE);
204
} else if(dic_num == -1) {
205
/* invalid context number */
209
/* buf[] = "dicname1\0dicname2\0dicname3\0...dicname_n\0\0" */
211
for(j = 0; j < dic_num; j++) {
212
api.RkMountDic(cc->rk_context_id, buf, 0);
213
buflen = strlen(buf) + 1;
225
release_context(LISP id_)
227
int id = get_c_int(id_);
228
struct canna_context *cc = get_canna_context(id);
233
if(cc->rk_context_id == -1)
236
if(api.RkCloseContext(cc->rk_context_id) != -1) {
237
cc->rk_context_id = -1;
245
_reset_conversion(int id)
247
struct canna_context *cc = get_canna_context(id);
251
if(cc->segment_num >= 0) {
252
cc->segment_num = -1;
253
api.RkEndBun(cc->rk_context_id, 0);
258
_update_status(int id)
261
struct canna_context *cc = get_canna_context(id);
265
if(cc->rk_context_id == -1)
268
if(api.RkGetStat(cc->rk_context_id, &stat) == 0)
270
cc->current_segment_num = stat.bunnum;
271
cc->current_cand_num = stat.candnum;
272
cc->max_current_cand_num = stat.maxcand;
274
_reset_conversion(id);
279
_update_segment (const int id, const int segment_num)
281
int i, tmp_segment_num;
283
struct canna_context *cc = get_canna_context(id);
288
if(cc->rk_context_id == -1)
291
tmp_segment_num = segment_num;
292
if(segment_num >= cc->segment_num)
295
for(i = 0; i <= tmp_segment_num; i++) {
297
api.RkGoTo(cc->rk_context_id, i);
298
len = api.RkGetKanji(cc->rk_context_id, buf, BUFSIZE);
299
/* printf("segment: %d, buf: %s\n", i, buf); */
302
api.RkGoTo(cc->rk_context_id, tmp_segment_num);
307
begin_conversion(LISP id_, LISP str_)
309
int id = get_c_int(id_);
311
int len, segment_num, mode;
312
struct canna_context *cc = get_canna_context(id);
317
if(cc->rk_context_id == -1)
321
str = uim_get_c_string(str_);
324
segment_num = api.RkBgnBun(cc->rk_context_id, str, len, mode);
326
if(segment_num == -1) {
327
/* failed to conversion */
333
cc->segment_num = segment_num;
334
_update_segment(id, 0);
339
return intcons(cc->segment_num);
343
get_nth_candidate(LISP id_, LISP seg_, LISP nth_)
345
int id = get_c_int(id_);
346
int seg = get_c_int(seg_);
347
int nth = get_c_int(nth_);
348
struct canna_context *cc = get_canna_context(id);
355
_update_segment(id, seg);
356
if(nth > cc->max_current_cand_num)
359
api.RkXfer(cc->rk_context_id, nth);
360
len = api.RkGetKanji(cc->rk_context_id, buf, BUFSIZE);
362
/* printf("nth: %d, kanji: %s\n", nth, buf); */
363
return strcons(len, buf);
367
get_nr_segments(LISP id_)
369
int id = get_c_int(id_);
371
struct canna_context *cc = get_canna_context(id);
376
if(cc->rk_context_id == -1)
379
return intcons(cc->segment_num);
383
get_nr_candidate(LISP id_, LISP nth_)
385
int id = get_c_int(id_);
386
int nth = get_c_int(nth_);
388
struct canna_context *cc = get_canna_context(id);
393
if(cc->rk_context_id == -1)
396
api.RkGoTo(cc->rk_context_id, nth);
398
if(api.RkGetStat(cc->rk_context_id, &stat) == 0)
399
return intcons(stat.maxcand);
405
resize_segment(LISP id_, LISP s_, LISP nth_)
407
int id = get_c_int(id_);
408
int s = get_c_int(s_);
409
int nth = get_c_int(nth_);
410
struct canna_context *cc = get_canna_context(id);
415
if(cc->rk_context_id == -1)
418
api.RkGoTo(cc->rk_context_id, s);
419
api.RkNfer(cc->rk_context_id);
422
cc->segment_num = api.RkEnlarge(cc->rk_context_id);
424
cc->segment_num = api.RkShorten(cc->rk_context_id);
426
_update_segment(id, cc->current_segment_num);
432
commit_segment(LISP id_, LISP s_, LISP nth_)
434
int id = get_c_int(id_);
435
int s = get_c_int(s_);
436
int nth = get_c_int(nth_);
437
struct canna_context *cc = get_canna_context(id);
442
if(cc->rk_context_id == -1)
445
api.RkEndBun(cc->rk_context_id, 1);
446
cc->segment_num = -1;
450
reset_conversion(LISP id_)
452
int id = get_c_int(id_);
454
_reset_conversion(id);
460
true_sym = siod_true_value();
461
init_subr_1("canna-lib-init", init_canna_lib);
463
init_subr_0("canna-lib-alloc-context", create_context);
464
init_subr_1("canna-lib-release-context", release_context);
465
init_subr_3("canna-lib-get-nth-candidate", get_nth_candidate);
466
init_subr_1("canna-lib-get-nr-segments",get_nr_segments);
467
init_subr_2("canna-lib-get-nr-candidates", get_nr_candidate);
468
init_subr_3("canna-lib-resize-segment", resize_segment);
469
init_subr_2("canna-lib-begin-conversion", begin_conversion);
470
init_subr_3("canna-lib-commit-segment", commit_segment);
471
init_subr_1("canna-lib-reset-conversion", reset_conversion);
477
if(cannaserver != NULL) {
487
memset(&api, 0, sizeof(struct canna_api));
490
if(context_array != NULL) {
492
context_array = NULL;
495
#endif /* HAVE_CANNA_RK_H */