2
Copyright (c) 2008 uim Project http://uim.freedesktop.org/
6
Redistribution and use in source and binary forms, with or without
7
modification, are permitted provided that the following conditions
10
1. Redistributions of source code must retain the above copyright
11
notice, this list of conditions and the following disclaimer.
12
2. Redistributions in binary form must reproduce the above copyright
13
notice, this list of conditions and the following disclaimer in the
14
documentation and/or other materials provided with the distribution.
15
3. Neither the name of authors nor the names of its contributors
16
may be used to endorse or promote products derived from this software
17
without specific prior written permission.
19
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
20
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
23
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37
#include <sys/param.h>
43
#include "uim-scm-abbrev.h"
44
#include "uim-helper.h"
45
#include "uim-notify.h"
49
#ifndef MAXHOSTNAMELEN
50
#define MAXHOSTNAMELEN 256
56
static int uim_sj3_is_open = 0;
58
struct uim_sj3_error {
65
uim_sj3_make_error_pair(char *sym, char *str)
67
char error_str[BUFSIZ];
69
snprintf(error_str, sizeof(error_str), "%s%s", _("In uim-sj3, "), _(str));
70
uim_notify_fatal(error_str);
75
uim_sj3_make_single_error(char *sym, char *str)
77
return CONS(MAKE_SYM("error"), LIST1(uim_sj3_make_error_pair(sym, str)));
80
#define uim_sj3_server_down_error() uim_sj3_make_single_error("*SJ3-SERVER-DOWN-ERROR*" , N_("Serverdown."))
81
#define uim_sj3_undefined_error() uim_sj3_make_single_error("*SJ3-UNDEFINED-ERROR*" , N_("Undefined error."))
82
#define uim_sj3_internal_error() uim_sj3_make_single_error("*SJ3-UIM-INTERNAL-ERROR*", N_("Internal error."))
85
uim_sj3_select_error(int errno, const struct uim_sj3_error *error)
87
uim_lisp ret_ = uim_scm_null();
89
while (error->error_sym != NULL) {
90
if (errno & error->errno)
91
ret_ = CONS(uim_sj3_make_error_pair(error->error_sym, error->error_str), ret_);
96
return uim_sj3_internal_error();
98
return ret_ = CONS(MAKE_SYM("error"),
99
uim_scm_callf("reverse", "o", ret_));
103
const static struct uim_sj3_error uim_sj3_open_error[] = {
104
{ SJ3_NORMAL_END, "*SJ3-NORMAL-END*" , N_("Normal end.") },
105
{ SJ3_SERVER_DEAD, "*SJ3-SERVER-DEAD*" , N_("Server is dead.") },
106
{ SJ3_CONNECT_ERROR, "*SJ3-CONNECT-ERROR*" , N_("Connect failed.") },
107
{ SJ3_ALREADY_CONNECTED, "*SJ3-ALREADY-CONNECTED*", N_("Already connected.") },
108
{ SJ3_CANNOT_OPEN_MDICT, "*SJ3-CANNOT-OPEN-MDICT*", N_("Cannot open main dictionary file.") },
109
{ SJ3_CANNOT_OPEN_UDICT, "*SJ3-CANNOT-OPEN-UDICT*", N_("Cannot open user dictionary file.") },
110
{ SJ3_CANNOT_OPEN_STUDY, "*SJ3-CANNOT-OPEN-STUDY*", N_("Cannot open study file.") },
111
{ SJ3_CANNOT_MAKE_UDIR, "*SJ3-CANNOT-MAKE-UDIR*", N_("Cannot make user dictionary directory.") },
112
{ SJ3_CANNOT_MAKE_UDICT, "*SJ3-CANNOT-MAKE-UDICT*", N_("Cannot make user dictionary file.") },
113
{ SJ3_CANNOT_MAKE_STUDY, "*SJ3-CANNOT-MAKE-STUDY*", N_("Cannot make study file.")},
118
uim_sj3_open(uim_lisp sname_, uim_lisp uname_)
120
char sname[MAXHOSTNAMELEN];
121
char uname[MAXLOGNAME];
124
if (strlcpy(sname, REFER_C_STR(sname_), sizeof(sname)) >= sizeof(sname))
125
return uim_sj3_make_single_error("*SJ3-SERVER-NAME-TOO-LONG*", N_("Server name is too long."));
127
if (strlcpy(uname, REFER_C_STR(uname_), sizeof(uname)) >= sizeof(uname))
128
return uim_sj3_make_single_error("*SJ3-USER-NAME-TOO-LONG*", N_("User name is too long."));
130
ret = sj3_open(sname, uname);
137
return uim_sj3_select_error(ret, uim_sj3_open_error);
141
uim_sj3_open_with_list(uim_lisp sname_, uim_lisp uname_, uim_lisp dict_list_)
143
char sname[MAXHOSTNAMELEN];
144
char uname[MAXLOGNAME];
148
int **err_index = NULL;
153
if (strlcpy(sname, REFER_C_STR(sname_), sizeof(sname)) >= sizeof(sname))
154
return uim_sj3_make_single_error("*SJ3-SERVER-NAME-TOO-LONG*", N_("Server name is too long."));
156
if (strlcpy(uname, REFER_C_STR(uname_), sizeof(uname)) >= sizeof(uname))
157
return uim_sj3_make_single_error("*SJ3-USER-NAME-TOO-LONG*", N_("User name is too long."));
159
dict_num = uim_scm_length(dict_list_);
161
dict_list = uim_malloc(sizeof(char *) * dict_num);
163
for (i = 0; i < dict_num; i++) {
164
dict_list[i] = uim_strdup(REFER_C_STR(CAR(dict_list_)));
165
dict_list_ = CDR(dict_list_);
168
ret = sj3_open_with_list(sname, uname, dict_num, dict_list, err_num, err_index);
171
for (i = 0; i < dict_num; i++)
174
return uim_sj3_select_error(ret, uim_sj3_open_error);
177
ret_ = uim_scm_null();
178
for (i = 0; i < *err_num; i++)
179
ret_ = CONS(MAKE_STR(dict_list[*err_index[i]]), ret_);
181
for (i = 0; i < dict_num; i++)
185
return uim_scm_callf("reverse", "o", ret_);
189
const static struct uim_sj3_error uim_sj3_close_error[] = {
190
{ SJ3_NORMAL_END, "*SJ3-NORMAL-END*" , N_("Normal end.") },
191
{ SJ3_SERVER_DEAD, "*SJ3-SERVER-DEAD*" , N_("Server is dead.") },
192
{ SJ3_DISCONNECT_ERROR, "*SJ3-DISCONNECT-ERROR*" , N_("Server is disconnected.") },
193
{ SJ3_NOT_CONNECTED, "*SJ3-NOT-CONNECTED*" , N_("Server is not connected.") },
194
{ SJ3_NOT_OPENED_MDICT, "*SJ3-NOT-OPENED-MDICT*" , N_("Main dictionary file is not opened.") },
195
{ SJ3_NOT_OPENED_UDICT, "*SJ3-NOT-OPENED-UDICT*" , N_("User dictionary file is not opened.") },
196
{ SJ3_NOT_OPENED_STUDY, "*SJ3-NOT-OPENED-STUDY*" , N_("Study file is not opened.") },
197
{ SJ3_CLOSE_MDICT_ERROR, "*SJ3-CLOSE-MDICT-ERROR*", N_("Main dictionary file cannot close.") },
198
{ SJ3_CLOSE_UDICT_ERROR, "*SJ3-CLOSE-UDICT-ERROR*", N_("User dictionary file cannot close.") },
199
{ SJ3_CLOSE_STUDY_ERROR, "*SJ3-CLOSE-STUDY-ERROR*", N_("Study file cannot close.") },
215
return uim_sj3_select_error(ret, uim_sj3_close_error);
219
* return: (kanji ((bunsetu-yomi1 bunsetu-kanji1) (bunsetu-yomi2 bunsetu-kanji2) ...))
222
uim_sj3_getkan(uim_lisp yomi_)
224
const char *yomi = REFER_C_STR(yomi_);
226
struct bunsetu bun[BUFSIZ / 2];
229
uim_lisp ret_ = uim_scm_f();
231
if (255 < strlen(yomi))
232
return uim_sj3_make_single_error("*SJ3-YOMI-STRING-TOO-LONG*", N_("Yomi string is too long."));
234
bunsetu_cnt = sj3_getkan_euc((unsigned char *)yomi, bun, (unsigned char *)kanji, sizeof(kanji));
236
if (bunsetu_cnt == -1)
237
return uim_sj3_server_down_error();
239
if (bun[bunsetu_cnt - 1].destlen == 0) /* too large? */
240
return uim_sj3_make_single_error("*SJ3-TOO-SHORT-BUFFER-SIZE*", N_("Buffer size is too short."));
242
if (bunsetu_cnt == 0)
245
ret_ = uim_scm_null();
246
for (i = 0; i < bunsetu_cnt; i++) {
250
yomi_str = uim_malloc(bun[i].srclen + 1);
251
strlcpy(yomi_str, (const char *)bun[i].srcstr, bun[i].srclen + 1);
253
kanji_str = uim_malloc(bun[i].destlen + 1);
255
strlcpy(kanji_str, (const char *)bun[i].deststr, bun[i].destlen + 1);
257
ret_ = CONS(LIST3(MAKE_STR(yomi_str),
259
MAKE_PTR(&bun[i].dcid)),
266
ret_ = uim_scm_callf("reverse", "o", ret_);
267
return CONS(MAKE_STR(kanji), ret_);
271
uim_sj3_douoncnt(uim_lisp yomi_)
273
const char *yomi = REFER_C_STR(yomi_);
276
if (63 < strlen(yomi))
277
return uim_sj3_make_single_error("*SJ3-YOMI-STRING-TOO-LONG*", N_("Yomi string is too long."));
279
ret = sj3_douoncnt_euc((unsigned char *)yomi);
281
return uim_sj3_server_down_error();
283
return MAKE_INT(ret);
287
uim_sj3_getdouon(uim_lisp yomi_)
289
const char *yomi = REFER_C_STR(yomi_);
291
struct douon douon[BUFSIZ];
293
uim_lisp ret_ = uim_scm_f();
295
if (255 < strlen(yomi))
296
return uim_sj3_make_single_error("*SJ3-YOMI-STRING-TOO-LONG*", N_("Yomi string is too long."));
298
douon_cnt = sj3_getdouon_euc((unsigned char *)yomi, douon);
300
return uim_sj3_server_down_error();
302
ret_ = uim_scm_null();
303
for (i = 0; i < douon_cnt; i++)
304
ret_ = CONS(LIST2(MAKE_STR((char *)douon[i].ddata), MAKE_PTR(&douon[i].dcid)), ret_);
305
return uim_scm_callf("reverse", "o", ret_);
309
uim_sj3_getnthdouon(uim_lisp yomi_, uim_lisp nth_)
311
const char *yomi = REFER_C_STR(yomi_);
313
struct douon douon[BUFSIZ];
314
int nth = C_INT(nth_);
316
if (255 < strlen(yomi))
317
return uim_sj3_make_single_error("*SJ3-YOMI-STRING-TOO-LONG*", N_("Yomi string is too long."));
319
douon_cnt = sj3_getdouon_euc((unsigned char *)yomi, douon);
321
return uim_sj3_server_down_error();
325
return LIST2(MAKE_STR((char *)douon[nth].ddata), MAKE_PTR(&douon[nth].dcid));
329
uim_sj3_gakusyuu(uim_lisp dcid_)
331
struct studyrec *dcid = C_PTR(dcid_);
334
ret = sj3_gakusyuu(dcid);
337
return uim_sj3_server_down_error();
342
return uim_sj3_undefined_error();
346
uim_sj3_gakusyuu2(uim_lisp yomi1_, uim_lisp yomi2_, uim_lisp dcid_)
348
const char *yomi1 = REFER_C_STR(yomi1_);
350
struct studyrec *dcid;
354
/* split bunsetu |yomi1yomi2| -> |yomi1|yomi2| */
355
yomi2 = REFER_C_STR(yomi2_);
358
/* merge bunsetu |yomi1|yomi2| -> |yomi1| */
363
ret = sj3_gakusyuu2_euc((unsigned char *)yomi1, (unsigned char *)yomi2, dcid);
366
return uim_sj3_server_down_error();
371
return uim_sj3_undefined_error();
375
const static struct {
378
} uim_sj3_hinsi[] = {
379
{ "sj3-hinshi-nrmnoun", SJ3_H_NRMNOUN },
380
{ "sj3-hinshi-pronoun", SJ3_H_PRONOUN },
381
{ "sj3-hinshi-lname", SJ3_H_LNAME },
382
{ "sj3-hinshi-fname", SJ3_H_FNAME },
383
{ "sj3-hinshi-locname", SJ3_H_LOCNAME },
384
{ "sj3-hinshi-prefic", SJ3_H_PREFIC },
385
{ "sj3-hinshi-rentai", SJ3_H_RENTAI },
386
{ "sj3-hinshi-conjunc", SJ3_H_CONJUNC },
387
{ "sj3-hinshi-subnum", SJ3_H_SUBNUM },
388
{ "sj3-hinshi-numeral", SJ3_H_NUMERAL },
389
{ "sj3-hinshi-prefix", SJ3_H_PREFIX },
390
{ "sj3-hinshi-postfix", SJ3_H_POSTFIX },
391
{ "sj3-hinshi-adverb", SJ3_H_ADVERB },
392
{ "sj3-hinshi-adject", SJ3_H_ADJECT },
393
{ "sj3-hinshi-adjverb", SJ3_H_ADJVERB },
394
{ "sj3-hinshi-silverb", SJ3_H_SILVERB },
395
{ "sj3-hinshi-zilverb", SJ3_H_ZILVERB },
396
{ "sj3-hinshi-oneverb", SJ3_H_ONEVERB },
397
{ "sj3-hinshi-kaverb", SJ3_H_KAVERB },
398
{ "sj3-hinshi-gaverb", SJ3_H_GAVERB },
399
{ "sj3-hinshi-saverb", SJ3_H_SAVERB },
400
{ "sj3-hinshi-taverb", SJ3_H_TAVERB },
401
{ "sj3-hinshi-naverb", SJ3_H_NAVERB },
402
{ "sj3-hinshi-baverb", SJ3_H_BAVERB },
403
{ "sj3-hinshi-maverb", SJ3_H_MAVERB },
404
{ "sj3-hinshi-raverb", SJ3_H_RAVERB },
405
{ "sj3-hinshi-waverb", SJ3_H_WAVERB },
406
{ "sj3-hinshi-single", SJ3_H_SINGLE },
410
const static struct uim_sj3_error uim_sj3_touroku_syoukyo_error[] = {
411
{ SJ3_DICT_ERROR, "*SJ3-DICT-ERROR*" , N_("Dictionary error.") },
412
{ SJ3_DICT_LOCKED, "*SJ3-DICT-LOCKED*" , N_("Dictionary is locked.") },
413
{ SJ3_BAD_YOMI_STR, "*SJ3-BAD-YOMI-STR*" , N_("Invalid yomi string.") },
414
{ SJ3_BAD_KANJI_STR, "*SJ3-BAD-KANJI-STR*" , N_("Invalid kanji string.") },
415
{ SJ3_BAD_HINSI_CODE, "*SJ3-BAD-HINSI-CODE*", N_("Invalid hinsi code.") },
416
{ SJ3_WORD_EXIST, "*SJ3-WORD-EXIST*" , N_("Word exist.") },
417
{ SJ3_DOUON_FULL, "*SJ3-DOUON-FULL*" , N_("Douon is full.") },
418
{ SJ3_DICT_FULL, "*SJ3-DICT-FULL*" , N_("Dictionary is full.") },
419
{ SJ3_INDEX_FULL, "*SJ3-INDEX-FULL*" , N_("Index is full.") },
420
{ SJ3_TOUROKU_FAILED, "*SJ3-TOUROKU-FAILED*", N_("Touroku failed.") },
421
{ SJ3_WORD_NOT_EXIST, "*SJ3-WORD-NOT-EXIST*", N_("Word does not exist.") },
422
{ SJ3_SYOUKYO_FAILED, "*SJ3-SYOUKYO-FAILED*", N_("Syoukyo failed.") },
427
uim_sj3_touroku(uim_lisp yomi_, uim_lisp kanji_, uim_lisp hinsi_)
429
const char *yomi = REFER_C_STR(yomi_);
430
const char *kanji = REFER_C_STR(kanji_);
431
const char *hinsi_str = REFER_C_STR(hinsi_);
435
if (31 < strlen(yomi) || 31 < strlen(kanji))
436
return uim_sj3_make_single_error("*SJ3-KANJI-STRING-TOO-LONG*", N_("Kanji string is too long."));
439
if (uim_sj3_hinsi[i].name == NULL)
440
return uim_sj3_internal_error();
441
if (strcmp(uim_sj3_hinsi[i].name, hinsi_str) == 0)
446
ret = sj3_touroku_euc((unsigned char*)yomi, (unsigned char*)kanji, uim_sj3_hinsi[i].val);
449
return uim_sj3_server_down_error();
454
return uim_sj3_select_error(ret, uim_sj3_touroku_syoukyo_error);
458
uim_sj3_syoukyo(uim_lisp yomi_, uim_lisp kanji_, uim_lisp hinsi_)
460
const char *yomi = REFER_C_STR(yomi_);
461
const char *kanji = REFER_C_STR(kanji_);
462
const char *hinsi_str = REFER_C_STR(hinsi_);
466
if (31 < strlen(yomi) || 31 < strlen(kanji))
467
return uim_sj3_make_single_error("*SJ3-KANJI-STRING-TOO-LONG*", N_("Kanji string is too long."));
470
if (uim_sj3_hinsi[i].name == NULL)
471
return uim_sj3_internal_error();
472
if (strcmp(uim_sj3_hinsi[i].name, hinsi_str) == 0)
477
ret = sj3_syoukyo_euc((unsigned char*)yomi, (unsigned char*)kanji, uim_sj3_hinsi[i].val);
480
return uim_sj3_server_down_error();
485
return uim_sj3_select_error(ret, uim_sj3_touroku_syoukyo_error);
489
uim_sj3_lockserv(void)
493
ret = sj3_lockserv();
496
return uim_sj3_server_down_error();
501
return uim_sj3_undefined_error();
505
uim_sj3_unlockserv(void)
509
ret = sj3_unlockserv();
512
return uim_sj3_server_down_error();
517
return uim_sj3_undefined_error();
521
uim_plugin_instance_init(void)
523
uim_scm_init_proc2("sj3-lib-open", uim_sj3_open);
524
uim_scm_init_proc3("sj3-lib-open-with-list", uim_sj3_open_with_list);
525
uim_scm_init_proc0("sj3-lib-close", uim_sj3_close);
526
uim_scm_init_proc1("sj3-lib-getkan", uim_sj3_getkan);
527
uim_scm_init_proc1("sj3-lib-douoncnt", uim_sj3_douoncnt);
528
uim_scm_init_proc1("sj3-lib-getdouon", uim_sj3_getdouon);
529
uim_scm_init_proc2("sj3-lib-get-nth-douon", uim_sj3_getnthdouon);
530
uim_scm_init_proc1("sj3-lib-gakusyuu", uim_sj3_gakusyuu);
531
uim_scm_init_proc3("sj3-lib-gakusyuu2", uim_sj3_gakusyuu2);
532
uim_scm_init_proc3("sj3-lib-touroku", uim_sj3_touroku);
533
uim_scm_init_proc3("sj3-lib-syoukyo", uim_sj3_syoukyo);
534
uim_scm_init_proc0("sj3-lib-lockserv", uim_sj3_lockserv);
535
uim_scm_init_proc0("sj3-lib-unlockserv", uim_sj3_unlockserv);
539
uim_plugin_instance_quit(void)