Tizen 2.1 base
[platform/core/uifw/anthy.git] / src-worddic / word_dic.c
1 /*
2  * Anthy¤Î¼­½ñ¥é¥¤¥Ö¥é¥ê¤ÎÃæ¿´
3  *
4  * anthy_get_seq_ent_from_xstr()¤Ç¼­½ñ¤ò¤Ò¤¯
5  *
6  * Copyright (C) 2000-2007 TABATA Yusuke
7  * Copyright (C) 2005-2006 YOSHIDA Yuichi
8  *
9  */
10 /*
11   This library is free software; you can redistribute it and/or
12   modify it under the terms of the GNU Lesser General Public
13   License as published by the Free Software Foundation; either
14   version 2 of the License, or (at your option) any later version.
15
16   This library is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19   Lesser General Public License for more details.
20
21   You should have received a copy of the GNU Lesser General Public
22   License along with this library; if not, write to the Free Software
23   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
24  */
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include <anthy/anthy.h>
29 #include <anthy/dic.h>
30 #include <anthy/conf.h>
31 #include <anthy/record.h>
32 #include <anthy/alloc.h>
33 #include <anthy/logger.h>
34 #include <anthy/xchar.h>
35 #include <anthy/feature_set.h>
36 #include <anthy/textdict.h>
37
38 #include <anthy/diclib.h>
39
40 #include "dic_ent.h"
41 #include "dic_personality.h"
42 #include "dic_main.h"
43
44 /**/
45 static int dic_init_count;
46
47 /* ¼­½ñ */
48 /* Á´personality¤Ç¶¦Í­¤µ¤ì¤ë¥Õ¥¡¥¤¥ë¼­½ñ */
49 static struct word_dic *master_dic_file;
50
51 /* ³Æ¥Ñ¡¼¥½¥Ê¥ê¥Æ¥£¤´¤È¤Î¼­½ñ */
52 struct mem_dic *anthy_current_personal_dic_cache;/* ¥­¥ã¥Ã¥·¥å */
53 /**/
54 struct record_stat *anthy_current_record;
55
56 struct seq_ent *
57 anthy_validate_seq_ent(struct seq_ent *seq, xstr *xs, int is_reverse)
58 {
59   if (!seq) {
60     return NULL;
61   }
62   if (seq->nr_dic_ents == 0 && seq->nr_compound_ents == 0) {
63     /* Ìµ¸ú¤Ê¥¨¥ó¥È¥ê¤òºîÀ®¤·¤¿¤Î¤Çcache¤«¤éºï½ü */
64     anthy_mem_dic_release_seq_ent(anthy_current_personal_dic_cache,
65                                   xs, is_reverse);
66     return NULL;
67   }
68
69   return seq;
70 }
71
72 struct seq_ent *
73 anthy_cache_get_seq_ent(xstr *xs, int is_reverse)
74 {
75   struct seq_ent *seq;
76
77   /* ¥­¥ã¥Ã¥·¥åÃæ¤Ë´û¤Ë¤¢¤ì¤Ð¤½¤ì¤òÊÖ¤¹ */
78   seq = anthy_mem_dic_find_seq_ent_by_xstr(anthy_current_personal_dic_cache,
79                                            xs, is_reverse);
80   if (seq) {
81     return seq;
82   }
83
84   /* ¥­¥ã¥Ã¥·¥åÃæ¤Ë̵¤¤¤Î¤Ç³ÎÊÝ */
85   return anthy_mem_dic_alloc_seq_ent_by_xstr(anthy_current_personal_dic_cache,
86                                              xs, is_reverse);
87 }
88
89 int
90 anthy_dic_check_word_relation(int from, int to)
91 {
92   return anthy_word_dic_check_word_relation(master_dic_file, from, to);
93 }
94
95 static seq_ent_t
96 do_get_seq_ent_from_xstr(xstr *xs, int is_reverse)
97 {
98   struct seq_ent *seq;
99   /* ¥­¥ã¥Ã¥·¥å¤«¤é¼è¤ê½Ð¤¹ */
100   seq = anthy_cache_get_seq_ent(xs, is_reverse);
101   seq = anthy_validate_seq_ent(seq, xs, is_reverse);
102   if (!seq) {
103     /* ¿ô»ú¤Ê¤É¤Î¼­½ñ¤Ë̵¤¤Ê¸»úÎó¤ò¸¡º÷¤¹¤ë */
104     return anthy_get_ext_seq_ent_from_xstr(xs, is_reverse);
105   }
106   return seq;
107 }
108
109 static xstr *
110 convert_vu(xstr *xs)
111 {
112   int i, v = 0;
113   int j;
114
115     /* ¡Ö¥ô¡×¤Î½Ð¸½¤ò¿ô¤¨¤ë */
116   for (i = 0; i < xs->len; i++) {
117     if (xs->str[i] == KK_VU) {
118       v++;
119     }
120   }
121   if (v > 0) {
122     xstr *nx = malloc(sizeof(xstr));
123     nx->len = xs->len + v;
124     nx->str = malloc(sizeof(xchar)*nx->len);
125     j = 0;
126     /* ¡Ö¥ô¡×¤ò¡Ö¤¦¡«¡×¤ËÊÑ´¹¤·¤Ä¤Ä¥³¥Ô¡¼¤¹¤ë */
127     for (i = 0; i < xs->len; i++) {
128       if (xs->str[i] == KK_VU) {
129         nx->str[j] = HK_U;
130         j++;
131         nx->str[j] = HK_DDOT;
132         j++;
133       } else {
134         nx->str[j] = xs->str[i];
135         j++;
136       }
137     }
138     return nx;
139   }
140   return NULL;
141 }
142
143 seq_ent_t
144 anthy_get_seq_ent_from_xstr(xstr *xs, int is_reverse)
145 {
146   struct seq_ent *se;
147
148   if (!xs) {
149     return NULL;
150   }
151   if (!is_reverse) {
152     xstr *nx = convert_vu(xs);
153     /* ¡Ö¥ô¡×¤Îº®¤¶¤Ã¤¿½çÊÑ´¹¤Î¾ì¹ç¡¢¡Ö¤¦¡«¡×¤Ëľ¤·¤Æ¸¡º÷¤¹¤ë
154      *   ¾å°Ì¤Î¥ì¥¤¥ä¡¼¤Ç¤Ï¥æ¡¼¥¶¤ÎÍ¿¤¨¤¿Ê¸»úÎó¤ò¤½¤Î¤Þ¤ÞÊÝ»ý¤¹¤ë¤³¤È¤¬
155      *   ´üÂÔ¤µ¤ì¤ë¤Î¤Ç¡¢ÊÑ´¹¤Ï¤³¤³¤Ç¹Ô¤Ê¤¦¡£
156      */
157     if (nx) {
158       se = do_get_seq_ent_from_xstr(nx, 0);
159       anthy_free_xstr(nx);
160       return se;
161     }
162   }
163   /* ¡Ö¥ô¡×¤¬½Ð¸½¤·¤Ê¤¤¡¢¤â¤·¤¯¤ÏµÕÊÑ´¹¤Î¾ì¹ç */
164   return do_get_seq_ent_from_xstr(xs, is_reverse);
165 }
166
167 static void
168 gang_elm_dtor(void *p)
169 {
170   struct gang_elm *ge = p;
171   free(ge->key);
172 }
173
174 static int
175 find_gang_elm(allocator ator, struct gang_elm *head, xstr *xs)
176 {
177   char *str = anthy_xstr_to_cstr(xs, ANTHY_UTF8_ENCODING);
178   struct gang_elm *ge;
179   for (ge = head->tmp.next; ge; ge = ge->tmp.next) {
180     if (!strcmp(ge->key, str)) {
181       free(str);
182       return 0;
183     }
184   }
185   ge = anthy_smalloc(ator);
186   ge->xs = *xs;
187   ge->key = str;
188   ge->tmp.next = head->tmp.next;
189   head->tmp.next = ge;
190   return 1;
191 }
192
193 static int
194 gang_elm_compare_func(const void *p1, const void *p2)
195 {
196   const struct gang_elm * const *s1 = p1;
197   const struct gang_elm * const *s2 = p2;
198   return strcmp((*s1)->key, (*s2)->key);
199 }
200
201 struct gang_scan_context {
202   /**/
203   int nr;
204   struct gang_elm **array;
205   /**/
206   int nth;
207 };
208
209 static int
210 is_ext_ent(struct seq_ent *seq)
211 {
212   if (!seq->md) {
213     return 1;
214   }
215   return 0;
216 }
217
218 static void
219 scan_misc_dic(struct gang_elm **array, int nr, int is_reverse)
220 {
221   int i;
222   for (i = 0; i < nr; i++) {
223     xstr *xs = &array[i]->xs;
224     struct seq_ent *seq;
225     seq = anthy_cache_get_seq_ent(xs, is_reverse);
226     /* ¸Ä¿Í¼­½ñ¤«¤é¤Î¼èÆÀ(texttrie(µì·Á¼°)¤È̤Ãθ켭½ñ) */
227     if (seq) {
228       anthy_copy_words_from_private_dic(seq, xs, is_reverse);
229       anthy_validate_seq_ent(seq, xs, is_reverse);
230     }
231   }
232 }
233
234 static void
235 load_word(xstr *xs, const char *n, int is_reverse)
236 {
237   struct seq_ent *seq = anthy_get_seq_ent_from_xstr(xs, 0);
238   xstr *word_xs;
239   wtype_t wt;  
240   struct word_line wl;
241   if (!seq || is_ext_ent(seq)) {
242     seq = anthy_mem_dic_alloc_seq_ent_by_xstr(anthy_current_personal_dic_cache,
243                                               xs, is_reverse);
244   }
245   if (anthy_parse_word_line(n, &wl)) {
246     return ;
247   }
248   word_xs = anthy_cstr_to_xstr(wl.word, ANTHY_UTF8_ENCODING);
249   if (anthy_type_to_wtype(wl.wt, &wt)) {
250     anthy_mem_dic_push_back_dic_ent(seq, 0, word_xs, wt,
251                                     NULL, wl.freq, 0);
252   }
253
254   anthy_free_xstr(word_xs);
255 }
256
257 static int
258 gang_scan(void *p, int offset, const char *key, const char *n)
259 {
260   struct gang_scan_context *gsc = p;
261   struct gang_elm *elm;
262   int r;
263   (void)offset;
264   while (1) {
265     if (gsc->nth >= gsc->nr) {
266       return 0;
267     }
268     elm = gsc->array[gsc->nth];
269     r = strcmp(elm->key, key);
270     if (r == 0) {
271       /* find it */
272       load_word(&elm->xs, n, 0);
273       /* go next in dictionary */
274       return 0;
275     } else if (r > 0) {
276       /* go next in dictionary */
277       return 0;
278     } else {
279       /* go next in lookup */
280       gsc->nth ++;
281     }
282   }
283   return 0;
284 }
285
286 static void
287 scan_dict(struct textdict *td, int nr, struct gang_elm **array)
288 {
289   struct gang_scan_context gsc;
290   gsc.nr = nr;
291   gsc.array = array;
292   gsc.nth = 0;
293   anthy_textdict_scan(td, 0, &gsc, gang_scan);
294 }
295
296 struct scan_arg {
297   struct gang_elm **array;
298   int nr;
299 };
300
301 static void
302 request_scan(struct textdict *td, void *arg)
303 {
304   struct scan_arg *sarg = (struct scan_arg *)arg;
305   scan_dict(td, sarg->nr, sarg->array);
306 }
307
308 static void
309 do_gang_load_dic(xstr *sentence, int is_reverse)
310 {
311   allocator ator = anthy_create_allocator(sizeof(struct gang_elm),
312                                           gang_elm_dtor);
313   int from, len;
314   xstr xs;
315   int i, nr;
316   struct gang_elm head;
317   struct gang_elm **array, *cur;
318   struct scan_arg sarg;
319   head.tmp.next = NULL;
320   nr = 0;
321   for (from = 0; from < sentence->len ; from ++) {
322     for (len = 1; len < 32 && from + len <= sentence->len; len ++) {
323       xs.str = &sentence->str[from];
324       xs.len = len;
325       nr += find_gang_elm(ator, &head, &xs);
326     }
327   }
328   array = malloc(sizeof(struct gang_elm *) * nr);
329   cur = head.tmp.next;
330   for (i = 0; i < nr; i++) {
331     array[i] = cur;
332     cur = cur->tmp.next;
333   }
334   qsort(array, nr, sizeof(struct gang_elm *), gang_elm_compare_func);
335   /**/
336   anthy_gang_fill_seq_ent(master_dic_file, array, nr, is_reverse);
337   /**/
338   scan_misc_dic(array, nr, is_reverse);
339   /* ¸Ä¿Í¼­½ñ¤«¤éÆɤà */
340   sarg.nr = nr;
341   sarg.array = array;
342   anthy_ask_scan(request_scan, (void *)&sarg);
343   /**/
344   free(array);
345   anthy_free_allocator(ator);
346 }
347
348 void
349 anthy_gang_load_dic(xstr *sentence, int is_reverse)
350 {
351   xstr *nx;
352   if (!is_reverse && (nx = convert_vu(sentence))) {
353     do_gang_load_dic(nx, is_reverse);
354     anthy_free_xstr(nx);
355   } else {
356     do_gang_load_dic(sentence, is_reverse);
357   }
358 }
359
360 /*
361  * seq_ent¤Î¼èÆÀ
362  ************************
363  * seq_ent¤Î³Æ¼ï¾ðÊó¤Î¼èÆÀ
364  */
365 int
366 anthy_get_nr_dic_ents(seq_ent_t se, xstr *xs)
367 {
368   struct seq_ent *s = se;
369   if (!s) {
370     return 0;
371   }
372   if (!xs) {
373     return s->nr_dic_ents;
374   }
375   return s->nr_dic_ents + anthy_get_nr_dic_ents_of_ext_ent(se, xs);
376 }
377
378 int
379 anthy_get_nth_dic_ent_str(seq_ent_t se, xstr *orig,
380                           int n, xstr *x)
381 {
382   if (!se || (n < 0)) { /* INDEPPAIR³Ø½¬¤Ë¤è¤ë¸ò´¹À褬¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿»þ¤ËÉÔÀµ¤Ê¥á¥â¥ê¥¢¥¯¥»¥¹¤ò¤¹¤ë¥Ð¥°¤Î½¤Àµ¡ÊÄ̾Ρ֤¤¤Á¤ª¤¯¡×¤Î·ï¡Ë */
383     x->str = NULL;      /* ÉÔÀµ¤Ê¥á¥â¥ê¥¢¥¯¥»¥¹¤ä¥á¥â¥ê¤Î¿½Å²òÊü¤ò¤¹¤ë¥Ð¥°¤Î½¤Àµ */
384     x->len = 0;
385     return -1;
386   }
387   if (n >= se->nr_dic_ents) {
388     return anthy_get_nth_dic_ent_str_of_ext_ent(se, orig,
389                                                 n - se->nr_dic_ents, x);
390   }
391   x->len = se->dic_ents[n]->str.len;
392   x->str = anthy_xstr_dup_str(&se->dic_ents[n]->str);
393   return 0;
394 }
395
396 int
397 anthy_get_nth_dic_ent_is_compound(seq_ent_t se, int nth)
398 {
399   if (!se) {
400     return 0;
401   }
402   if (nth >= se->nr_dic_ents) {
403     return 0;
404   }
405   return se->dic_ents[nth]->is_compound;
406 }
407
408 int
409 anthy_get_nth_dic_ent_freq(seq_ent_t se, int nth)
410 {
411   struct seq_ent *s = se;
412   if (!s) {
413     return 0;
414   }
415   if (!s->dic_ents) {
416     return anthy_get_nth_dic_ent_freq_of_ext_ent(se, nth);
417   }
418   if (s->nr_dic_ents <= nth) {
419     return anthy_get_nth_dic_ent_freq_of_ext_ent(se, nth - se->nr_dic_ents);
420   }
421   return s->dic_ents[nth]->freq;
422 }
423
424 int
425 anthy_get_nth_dic_ent_wtype(seq_ent_t se, xstr *xs,
426                             int n, wtype_t *w)
427 {
428   struct seq_ent *s = se;
429   if (!s) {
430     *w = anthy_wt_none;
431     return -1;
432   }
433   if (s->nr_dic_ents <= n) {
434     int r;
435     r = anthy_get_nth_dic_ent_wtype_of_ext_ent(xs, n - s->nr_dic_ents, w);
436     if (r == -1) {
437       *w = anthy_wt_none;
438     }
439     return r;
440   }
441   *w =  s->dic_ents[n]->type;
442   return 0;
443 }
444
445 int
446 anthy_get_seq_ent_pos(seq_ent_t se, int pos)
447 {
448   int i, v=0;
449   struct seq_ent *s = se;
450   if (!s) {
451     return 0;
452   }
453   if (s->nr_dic_ents == 0) {
454     return anthy_get_ext_seq_ent_pos(se, pos);
455   }
456   for (i = 0; i < s->nr_dic_ents; i++) {
457     if (anthy_wtype_get_pos(s->dic_ents[i]->type) == pos) {
458       v += s->dic_ents[i]->freq;
459       if (v == 0) {
460         v = 1;
461       }
462     }
463   }
464   return v;
465 }
466
467 int
468 anthy_get_seq_ent_ct(seq_ent_t se, int pos, int ct)
469 {
470   int i, v=0;
471   struct seq_ent *s = se;
472   if (!s) {
473     return 0;
474   }
475   if (s->nr_dic_ents == 0) {
476     return anthy_get_ext_seq_ent_ct(s, pos, ct);
477   }
478   for (i = 0; i < s->nr_dic_ents; i++) {
479     if (anthy_wtype_get_pos(s->dic_ents[i]->type)== pos &&
480         anthy_wtype_get_ct(s->dic_ents[i]->type)==ct) {
481       v += s->dic_ents[i]->freq;
482       if (v == 0) {
483         v = 1;
484       }
485     }
486   }
487   return v;
488 }
489
490 /*
491  * wt¤ÎÉÊ»ì¤ò»ý¤Äñ¸ì¤ÎÃæ¤ÇºÇÂç¤ÎÉÑÅÙ¤ò»ý¤Ä¤â¤Î¤òÊÖ¤¹
492  */
493 int
494 anthy_get_seq_ent_wtype_freq(seq_ent_t seq, wtype_t wt)
495 {
496   int i, f;
497
498   if (!seq) {
499     return 0;
500   }
501   /**/
502   if (seq->nr_dic_ents == 0) {
503     return anthy_get_ext_seq_ent_wtype(seq, wt);
504   }
505
506   f = 0;
507   /* Ã±¸ì */
508   for (i = 0; i < seq->nr_dic_ents; i++) {
509     if (seq->dic_ents[i]->order == 0 &&
510         anthy_wtype_include(wt, seq->dic_ents[i]->type)) {
511       if (f < seq->dic_ents[i]->freq) {
512         f = seq->dic_ents[i]->freq;
513       }
514     }
515   }
516   return f;
517 }
518
519 /*
520  * wt¤ÎÉÊ»ì¤ò»ý¤ÄÊ£¹ç¸ì¤ÎÃæ¤ÇºÇÂç¤ÎÉÑÅÙ¤ò»ý¤Ä¤â¤Î¤òÊÖ¤¹
521  */
522 int
523 anthy_get_seq_ent_wtype_compound_freq(seq_ent_t se, wtype_t wt)
524 {
525   int i,f;
526   struct seq_ent *s = se;
527   if (!s) {
528     return 0;
529   }
530   /**/
531   f = 0;
532   for (i = 0; i < s->nr_dic_ents; i++) {
533     if (!anthy_get_nth_dic_ent_is_compound(se, i)) {
534       continue;
535     }
536     if (anthy_wtype_include(wt, s->dic_ents[i]->type)) {
537       if (f < s->dic_ents[i]->freq) {
538         f = s->dic_ents[i]->freq;
539       }
540     }
541   }
542   return f;
543 }
544
545 int
546 anthy_get_seq_ent_indep(seq_ent_t se)
547 {
548   int i;
549   struct seq_ent *s = se;
550   if (!s) {
551     return 0;
552   }
553   if (s->nr_dic_ents == 0) {
554     return anthy_get_ext_seq_ent_indep(s);
555   }
556   for (i = 0; i < s->nr_dic_ents; i++) {
557     if (anthy_wtype_get_indep(s->dic_ents[i]->type)) {
558       return 1;
559     }
560   }
561   return 0;
562 }
563
564 int
565 anthy_has_compound_ents(seq_ent_t se)
566 {
567   if (!se) {
568     return 0;
569   }
570   return se->nr_compound_ents;
571 }
572
573 /* compund¤Ç¤Ê¤¤¸õÊä¤ò»ý¤Ã¤Æ¤¤¤ë¤« */
574 int
575 anthy_has_non_compound_ents(seq_ent_t se)
576 {
577   if (!se) {
578     return 0;
579   }
580   if (se->nr_dic_ents == 0) {
581     return 1;
582   }
583   return se->nr_dic_ents - se->nr_compound_ents;
584 }
585
586 compound_ent_t
587 anthy_get_nth_compound_ent(seq_ent_t se, int nth)
588 {
589   if (!se) {
590     return NULL;
591   }
592   if (nth >= 0 && nth < se->nr_dic_ents) {
593     return se->dic_ents[nth];
594   }
595   return NULL;
596 }
597
598 struct elm_compound {
599   int len;
600   xstr str;
601 };
602
603 /* Í×ÁǤËÂбþ¤¹¤ëÆɤߤÎŤµ¤òÊÖ¤¹ */
604 static int
605 get_element_len(xchar xc)
606 {
607   if (xc > '0' && xc <= '9') {
608     return xc - '0';
609   }
610   if (xc >= 'a' && xc <= 'z') {
611     return xc - 'a' + 10;
612   }
613   return 0;
614 }
615
616 static struct elm_compound *
617 get_nth_elm_compound(compound_ent_t ce, struct elm_compound *elm, int nth)
618 {
619   int off = 0;
620   int i, j;
621   for (i = 0; i <= nth; i++) {
622     /* nthÈÖÌܤÎÍ×ÁǤÎÀèƬ¤Ø°ÜÆ°¤¹¤ë */
623     while (!(ce->str.str[off] == '_' &&
624              get_element_len(ce->str.str[off+1]) > 0)) {
625       off ++;
626       if (off + 1 >= ce->str.len) {
627         return NULL;
628       }
629     }
630     /* ¹½Â¤ÂΤؾðÊó¤ò¼è¤ê¹þ¤à */
631     elm->len = get_element_len(ce->str.str[off+1]);
632     elm->str.str = &ce->str.str[off+2];
633     elm->str.len = ce->str.len - off - 2;
634     for (j = 0; j < elm->str.len; j++) {
635       if (elm->str.str[j] == '_') {
636         elm->str.len = j;
637         break;
638       }
639     }
640     off ++;
641   }
642   return elm;
643 }
644
645 int
646 anthy_compound_get_nr_segments(compound_ent_t ce)
647 {
648   struct elm_compound elm;
649   int i;
650   if (!ce) {
651     return 0;
652   }
653   for (i = 0; get_nth_elm_compound(ce, &elm, i); i++);
654   return i;
655 }
656
657 int
658 anthy_compound_get_nth_segment_len(compound_ent_t ce, int nth)
659 {
660   struct elm_compound elm;
661   if (get_nth_elm_compound(ce, &elm, nth)) {
662     return elm.len;
663   }
664   return 0;
665 }
666
667 int
668 anthy_compound_get_nth_segment_xstr(compound_ent_t ce, int nth, xstr *xs)
669 {
670   struct elm_compound elm;
671   if (get_nth_elm_compound(ce, &elm, nth)) {
672     if (xs) {
673       *xs = elm.str;
674       return 0;
675     }
676   }
677   return -1;
678 }
679
680 int
681 anthy_compound_get_wtype(compound_ent_t ce, wtype_t *w)
682 {
683   *w = ce->type;
684   return 0;
685 }
686
687 int
688 anthy_compound_get_freq(compound_ent_t ce)
689 {
690   return ce->freq;
691 }
692
693 /* ¥Õ¥í¥ó¥È¥¨¥ó¥É¤«¤é¸Æ¤Ð¤ì¤ë */
694 void
695 anthy_lock_dic(void)
696 {
697   anthy_priv_dic_lock();
698   anthy_priv_dic_update();
699 }
700
701 /* ¥Õ¥í¥ó¥È¥¨¥ó¥É¤«¤é¸Æ¤Ð¤ì¤ë */
702 void
703 anthy_unlock_dic(void)
704 {
705   anthy_priv_dic_unlock();
706 }
707
708
709 dic_session_t
710 anthy_dic_create_session(void)
711 {
712   return anthy_create_mem_dic();
713 }
714
715 void
716 anthy_dic_activate_session(dic_session_t d)
717 {
718   anthy_current_personal_dic_cache = d;
719 }
720
721 void
722 anthy_dic_release_session(dic_session_t d)
723 {
724   anthy_release_mem_dic(d);
725 }
726
727 void
728 anthy_dic_set_personality(const char *id)
729 {
730   anthy_current_record = anthy_create_record(id);
731   anthy_current_personal_dic_cache = anthy_create_mem_dic();
732   anthy_init_private_dic(id);
733 }
734
735
736 /** ¼­½ñ¥µ¥Ö¥·¥¹¥Æ¥à¤ò½é´ü²½
737  */
738 int
739 anthy_init_dic(void)
740 {
741   if (dic_init_count) {
742     dic_init_count ++;
743     return 0;
744   }
745   if (anthy_init_diclib() == -1) {
746     return -1;
747   }
748
749   anthy_init_wtypes();
750   anthy_init_mem_dic();
751   anthy_init_record();
752   anthy_init_ext_ent();
753   anthy_init_features();
754
755   anthy_init_word_dic();
756   master_dic_file = anthy_create_word_dic();
757   if (!master_dic_file) {
758     anthy_log(0, "Failed to create file dic.\n");
759     return -1;
760   }
761   dic_init_count ++;
762   return 0;
763 }
764
765 /** ¼­½ñ¥µ¥Ö¥·¥¹¥Æ¥à¤ò¤¹¤Ù¤Æ²òÊü
766  */
767 void
768 anthy_quit_dic(void)
769 {
770   dic_init_count --;
771   if (dic_init_count) {
772     return;
773   }
774   if (anthy_current_record) {
775     anthy_release_record(anthy_current_record);
776   }
777   anthy_release_private_dic();
778   anthy_current_record = NULL;
779   anthy_quit_mem_dic();
780   anthy_quit_diclib();
781 }
782