2 * ¸Ä¿Í¼½ñ¤ò°·¤¦¤¿¤á¤Î¥³¡¼¥É
4 * ¥æ¡¼¥¶¤¬ÌÀ¼¨Åª¤ËÅÐÏ¿¤·¤¿Ã±¸ì¤À¤±¤Ç¤Ê¤¯¡¢
5 * ̤Ãθì¤ò¼«Æ°Åª¤Ë³Ø½¬¤·¤Æ´ÉÍý¤¹¤ëAPI¤â»ý¤Ä¡£
7 * Copyright (C) 2000-2007 TABATA Yusuke
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <sys/types.h>
34 #include <anthy/anthy.h>
35 #include <anthy/alloc.h>
36 #include <anthy/dic.h>
37 #include <anthy/record.h>
38 #include <anthy/dicutil.h>
39 #include <anthy/conf.h>
40 #include <anthy/logger.h>
41 #include <anthy/texttrie.h>
42 #include <anthy/textdict.h>
43 #include <anthy/word_dic.h>
48 struct text_trie *anthy_private_tt_dic;
49 struct textdict *anthy_private_text_dic;
50 static struct textdict *anthy_imported_text_dic;
51 static char *imported_dic_dir;
54 static int lock_depth;
57 #define MAX_DICT_SIZE 100000000
59 /* ¸Ä¿Í¼½ñ¤Î¥Ç¥£¥ì¥¯¥È¥ê¤ÎÍ̵¤ò³Îǧ¤¹¤ë */
61 anthy_check_user_dir(void)
66 hd = anthy_conf_get_str("HOME");
67 dn = alloca(strlen(hd) + 10);
68 sprintf(dn, "%s/.anthy", hd);
69 if (stat(dn, &st) || !S_ISDIR(st.st_mode)) {
71 /*fprintf(stderr, "Anthy: Failed to open anthy directory(%s).\n", dn);*/
72 r = mkdir(dn, S_IRWXU);
74 anthy_log(0, "Failed to create profile directory\n");
77 /*fprintf(stderr, "Anthy: Created\n");*/
78 r = chmod(dn, S_IRUSR | S_IWUSR | S_IXUSR);
80 anthy_log(0, "But failed to change permission.\n");
86 init_lock_fn(const char *home, const char *id)
88 lock_fn = malloc(strlen(home) + strlen(id) + 40);
89 sprintf(lock_fn, "%s/.anthy/lock-file_%s", home, id);
92 static struct text_trie *
93 open_tt_dic(const char *home, const char *id)
96 char *buf = malloc(strlen(home) + strlen(id) + 40);
97 sprintf(buf, "%s/.anthy/private_dict_%s.tt", home, id);
98 tt = anthy_trie_open(buf, 0);
103 static struct textdict *
104 open_textdic(const char *home, const char *name, const char *id)
106 char *fn = malloc(strlen(home) + strlen(name) + strlen(id) + 10);
108 sprintf(fn, "%s/.anthy/%s%s", home, name, id);
109 td = anthy_textdict_open(fn, 0);
115 anthy_priv_dic_lock(void)
119 if (lock_depth > 1) {
123 /* ½é´ü²½¤ò¥ß¥¹¤Ã¤Æ¤ë */
128 /* ¥Õ¥¡¥¤¥ë¥í¥Ã¥¯¤ÎÊýË¡¤Ï¿¿ô¤¢¤ë¤¬¡¢¤³¤ÎÊýË¡¤Ïcygwin¤Ç¤âÆ°¤¯¤Î¤ÇºÎÍѤ·¤¿ */
129 lock_fd = open(lock_fn, O_CREAT|O_RDWR, S_IREAD|S_IWRITE);
134 lck.l_type = F_WRLCK;
135 lck.l_whence = (short) 0;
136 lck.l_start = (off_t) 0;
137 lck.l_len = (off_t) 1;
138 if (fcntl(lock_fd, F_SETLKW, &lck) == -1) {
145 anthy_priv_dic_unlock(void)
148 if (lock_depth > 0) {
159 anthy_priv_dic_update(void)
161 if (!anthy_private_tt_dic) {
165 anthy_trie_update_mapping(anthy_private_tt_dic);
168 /* seq_ent¤ËÄɲ乤ë */
170 add_to_seq_ent(const char *line, int encoding, struct seq_ent *seq)
176 if (anthy_parse_word_line(line, &wl)) {
179 xs = anthy_cstr_to_xstr(wl.word, encoding);
180 anthy_type_to_wtype(wl.wt, &wt);
181 anthy_mem_dic_push_back_dic_ent(seq, 0, xs, wt,
186 /* texttrie¤ËÅÐÏ¿¤µ¤ì¤Æ¤¤¤ë¤«¤ò¥Á¥§¥Ã¥¯¤·¡¢
187 * ÅÐÏ¿¤µ¤ì¤Æ¤¤¤ì¤Ðseq_ent¤ËÄɲ乤ë
190 copy_words_from_tt(struct seq_ent *seq, xstr *xs,
191 int encoding, const char *prefix)
196 int prefix_len = strlen(prefix);
198 if (!anthy_private_tt_dic) {
201 key = anthy_xstr_to_cstr(xs, encoding);
202 key_len = strlen(key);
203 key_buf = malloc(key_len + 12);
204 /* ¼½ñÃæ¤Ë¤Ï³Æñ¸ì¤¬¡Ö¸«½Ð¤· XXXX¡×(XXXX¤Ï¥é¥ó¥À¥à¤Êʸ»úÎó)¤ò
205 * ¥¡¼¤È¤·¤ÆÊݸ¤µ¤ì¤Æ¤¤¤ë¤Î¤ÇÎóµó¤¹¤ë
207 sprintf(key_buf, "%s%s ", prefix, key);
209 if (strncmp(&key_buf[2], key, key_len) ||
210 strncmp(&key_buf[0], prefix, prefix_len) ||
211 key_buf[key_len+2] != ' ') {
212 /* ¡Ö¸«½Ð¤· ¡×¤Ç»Ï¤Þ¤Ã¤Æ¤¤¤Ê¤¤¤Î¤ÇÂоݳ° */
215 /* ñ¸ì¤òÆɤ߽Ф·¤ÆÅÐÏ¿ */
216 v = anthy_trie_find(anthy_private_tt_dic, key_buf);
218 add_to_seq_ent(v, encoding, seq);
222 } while (anthy_trie_find_next_key(anthy_private_tt_dic,
223 key_buf, key_len + 8));
229 anthy_copy_words_from_private_dic(struct seq_ent *seq,
230 xstr *xs, int is_reverse)
235 /* ¸Ä¿Í¼½ñ¤«¤é¼è¤Ã¤Æ¤¯¤ë */
236 copy_words_from_tt(seq, xs, ANTHY_EUC_JP_ENCODING, " ");
237 copy_words_from_tt(seq, xs, ANTHY_UTF8_ENCODING, " p");
239 if (!anthy_select_section("UNKNOWN_WORD", 0) &&
240 !anthy_select_row(xs, 0)) {
243 anthy_type_to_wtype("#T35", &wt);
244 word_xs = anthy_get_nth_xstr(0);
245 anthy_mem_dic_push_back_dic_ent(seq, 0, word_xs, wt, NULL, 10, 0);
250 anthy_parse_word_line(const char *line, struct word_line *res)
253 const char *buf = line;
258 /* ÉÊ»ì¤ÈÉÑÅÙ¤òparse */
259 for (i = 0; i < 9 && *buf && *buf != '*' && *buf != ' '; buf++, i++) {
265 sscanf(buf, "%d", &res->freq);
266 buf = strchr(buf, ' ');
270 if (!buf || !(*buf)) {
281 anthy_ask_scan(void (*request_scan)(struct textdict *, void *),
287 request_scan(anthy_private_text_dic, arg);
288 request_scan(anthy_imported_text_dic, arg);
289 dir = opendir(imported_dic_dir);
293 while ((de = readdir(dir))) {
296 char *fn = malloc(strlen(imported_dic_dir) +
297 strlen(de->d_name) + 3);
301 sprintf(fn, "%s/%s", imported_dic_dir, de->d_name);
302 if (stat(fn, &st_buf)) {
306 if (!S_ISREG(st_buf.st_mode)) {
310 size += st_buf.st_size;
311 if (size > MAX_DICT_SIZE) {
315 td = anthy_textdict_open(fn, 0);
316 request_scan(td, arg);
317 anthy_textdict_close(td);
324 add_unknown_word(xstr *yomi, xstr *word)
327 if (anthy_select_section("UNKNOWN_WORD", 1)) {
330 if (!anthy_select_row(yomi, 0)) {
331 anthy_mark_row_used();
333 if (anthy_select_row(yomi, 1)) {
336 anthy_set_nth_xstr(0, word);
340 anthy_add_unknown_word(xstr *yomi, xstr *word)
342 if (!(anthy_get_xstr_type(word) & XCT_KATA) &&
343 !(anthy_get_xstr_type(word) & XCT_HIRA)) {
346 if (yomi->len < 4 || yomi->len > 30) {
350 add_unknown_word(yomi, word);
354 anthy_forget_unused_unknown_word(xstr *xs)
359 if (!anthy_private_tt_dic) {
363 v = anthy_xstr_to_cstr(xs, ANTHY_UTF8_ENCODING);
364 sprintf(key_buf, " U%s 0", v);
366 anthy_trie_delete(anthy_private_tt_dic, key_buf);
368 /* record¤ËµÏ¿¤µ¤ì¤¿Êª¤ò¾Ã¤¹ */
369 if (anthy_select_section("UNKNOWN_WORD", 0)) {
372 if (!anthy_select_row(xs, 0)) {
378 anthy_init_private_dic(const char *id)
380 const char *home = anthy_conf_get_str("HOME");
381 if (anthy_private_tt_dic) {
382 anthy_trie_close(anthy_private_tt_dic);
385 anthy_textdict_close(anthy_private_text_dic);
386 anthy_textdict_close(anthy_imported_text_dic);
391 init_lock_fn(home, id);
392 anthy_private_tt_dic = open_tt_dic(home, id);
394 anthy_private_text_dic = open_textdic(home, "private_words_", id);
395 anthy_imported_text_dic = open_textdic(home, "imported_words_", id);
396 imported_dic_dir = malloc(strlen(home) + strlen(id) + 30);
397 sprintf(imported_dic_dir, "%s/.anthy/imported_words_%s.d/", home, id);
401 anthy_release_private_dic(void)
403 if (anthy_private_tt_dic) {
404 anthy_trie_close(anthy_private_tt_dic);
405 anthy_private_tt_dic = NULL;
408 anthy_textdict_close(anthy_private_text_dic);
409 anthy_textdict_close(anthy_imported_text_dic);
410 free(imported_dic_dir);
411 anthy_private_text_dic = NULL;
412 anthy_imported_text_dic = NULL;
413 imported_dic_dir = NULL;
415 if (lock_depth > 0) {
416 /* not sane situation */