1 /*
2 * $Id:$
3 * Copyright (c) 2003,2004 Masahito Omote <omote@utyuuzin.net>
4 * 2005-2013 uim Project https://github.com/uim/uim
5 *
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
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.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDERS 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
31 * SUCH DAMAGE.
32 */
33
34 #include <config.h>
35
36 #include <dlfcn.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <stdlib.h>
40 #include <glib.h>
41
42 #include <anthy/anthy.h>
43 #include <anthy/dicutil.h>
44
45 #include "gettext.h"
46 #include "anthy.h"
47 #include "canna-cclass.h"
48 #include "util.h"
49
50 static uim_dict *uim_dict_anthy_open (const char *identifier);
51 static void uim_dict_anthy_close (uim_dict *dict);
52 static int uim_dict_anthy_add_word (uim_dict *dict, uim_word *word);
53 static int uim_dict_anthy_change_word (uim_dict *dict, uim_word *word);
54 static int uim_dict_anthy_remove_word (uim_dict *dict, uim_word *word);
55 static void uim_dict_anthy_refresh (uim_dict *dict);
56
57 #if 0 /* should be accessed through functions */
58 static
59 #endif
60 uim_dict_class uim_dict_class_anthy = {
61 "Anthy", /* type */
62
63 NULL, /* init */
64 NULL, /* exit */
65
66 NULL, /* list_known_dict */
67 NULL, /* default_priv_dict */
68
69 uim_dict_anthy_open, /* open */
70
71 NULL, /* is_supported */
72 NULL, /* load_file */
73 NULL, /* save_file */
74
75 uim_dict_anthy_close, /* close */
76
77 uim_dict_anthy_add_word, /* add_word */
78 uim_dict_anthy_change_word, /* change_word */
79 uim_dict_anthy_remove_word, /* remove_word */
80 uim_dict_anthy_refresh, /* refresh */
81 };
82
83 static const char *identifiers[] = {
84 N_("Anthy private dictionary"),
85 };
86
87 static int
dict_anthy_init(void)88 dict_anthy_init(void)
89 {
90 anthy_dic_util_init();
91 #if LIBANTHY_UTF8_CAPABLE
92 anthy_dic_util_set_encoding(ANTHY_UTF8_ENCODING);
93 #endif
94 return 0;
95 }
96
97 static int
dict_anthy_exit(void)98 dict_anthy_exit(void)
99 {
100 /*
101 * With anthy-7811, anthy_parse_word_lin() causes segmentation fault once
102 * anthy_dic_util_quit() and anthy_dic_util_init() have been used to restart
103 * the library. To avoid this, we don't call anthy_dic_util_quit() even when
104 * the ref_count of uim_dict_anthy become 0.
105 */
106 #if 0
107 anthy_dic_util_quit();
108 #endif
109
110 return 0;
111 }
112
113 static int
dict_anthy_read_priv_dic_list(uim_word ** head)114 dict_anthy_read_priv_dic_list(uim_word **head)
115 {
116 char phon[100], desc[100], cclass_native[100];
117 int ret = 0;
118
119 if (anthy_priv_dic_select_first_entry() == -1) {
120 *head = NULL;
121 return -1;
122 }
123
124 while (ret == 0) {
125 if (anthy_priv_dic_get_index(phon, sizeof(phon))
126 && anthy_priv_dic_get_wtype(cclass_native,
127 sizeof(cclass_native))
128 && anthy_priv_dic_get_word(desc, sizeof(desc))) {
129 gint pos;
130 const char *cclass_code = NULL;
131
132 for (pos = 0; pos < NR_POS; pos++) {
133 cclass_code = find_desc_from_code_with_type(cclass_native, pos);
134 if (cclass_code)
135 break;
136 }
137
138 #if LIBANTHY_UTF8_CAPABLE
139 {
140 gchar *cclass_code_utf8 = eucjp_to_utf8(cclass_code);
141 word_append(head, WORD_TYPE_ANTHY, "UTF-8",
142 phon, desc, cclass_code_utf8, cclass_native,
143 anthy_priv_dic_get_freq(),
144 0, NULL);
145 g_free(cclass_code_utf8);
146 }
147 #else /* EUC-JP */
148 word_append(head, WORD_TYPE_ANTHY, "EUC-JP",
149 phon, desc, cclass_code, cclass_native,
150 anthy_priv_dic_get_freq(),
151 0, NULL);
152 #endif
153 }
154 ret = anthy_priv_dic_select_next_entry();
155 }
156 return 0;
157 }
158
159 static int
dict_anthy_add_priv_dic_with_flags(char * phon,char * desc,char * cclass_code,int freq)160 dict_anthy_add_priv_dic_with_flags(char *phon, char *desc,
161 char *cclass_code, int freq)
162 {
163 int status;
164
165 if ((strlen(phon) == 0) || (strlen(desc) == 0) ||
166 (strlen(cclass_code) == 0)) {
167 return 0;
168 }
169
170 status = anthy_priv_dic_add_entry(phon, desc, cclass_code, freq);
171
172 switch (status) {
173 case ANTHY_DIC_UTIL_OK:
174 case ANTHY_DIC_UTIL_DUPLICATE:
175 status = 1;
176 break;
177 default:
178 status = 0;
179 }
180
181 return status;
182 }
183
184 static int
dict_anthy_delete_priv_dic(char * phon,char * desc,char * cclass_code)185 dict_anthy_delete_priv_dic(char *phon, char *desc, char *cclass_code)
186 {
187 int status;
188
189 status = anthy_priv_dic_add_entry(phon, desc, cclass_code, 0);
190 return status ? 0 : 1;
191 }
192
193 static uim_dict *
uim_dict_anthy_open(const char * identifier)194 uim_dict_anthy_open(const char *identifier)
195 {
196 uim_dict *dict;
197
198 if (identifier == NULL)
199 return NULL;
200
201 if (strcmp(identifier, identifiers[0]) != 0)
202 return NULL;
203
204 if (dict_anthy_init() == -1)
205 return NULL;
206
207 dict = malloc(sizeof(uim_dict));
208 if (dict == NULL)
209 return NULL;
210
211 dict->funcs = &uim_dict_class_anthy;
212 dict->identifier = strdup(identifier);
213 dict->filename = NULL;
214 #if LIBANTHY_UTF8_CAPABLE
215 dict->charset = strdup("UTF-8");
216 #else
217 dict->charset = strdup("EUC-JP");
218 #endif
219 dict->ref_count = 0; /* at this point, no window refers this */
220 dict->word_list = NULL;
221
222 dict_anthy_read_priv_dic_list(&dict->word_list);
223
224 return dict;
225 }
226
227 static void
uim_dict_anthy_close(uim_dict * dict)228 uim_dict_anthy_close(uim_dict *dict)
229 {
230 if (dict == NULL)
231 return;
232
233 word_free_list(dict->word_list);
234
235 free(dict->identifier);
236 free(dict->filename);
237 free(dict->charset);
238 free(dict);
239
240 dict_anthy_exit();
241 }
242
243 static int
uim_dict_anthy_add_word(uim_dict * dict,uim_word * word)244 uim_dict_anthy_add_word(uim_dict *dict, uim_word *word)
245 {
246 int ret;
247
248 if (dict == NULL || word == NULL)
249 return 0;
250
251 ret = dict_anthy_add_priv_dic_with_flags(word->phon, word->desc,
252 word->cclass_native, word->freq);
253
254 return ret;
255 }
256
257 static int
uim_dict_anthy_change_word(uim_dict * dict,uim_word * word)258 uim_dict_anthy_change_word(uim_dict *dict, uim_word *word)
259 {
260 return 0;
261 }
262
263 static int
uim_dict_anthy_remove_word(uim_dict * dict,uim_word * word)264 uim_dict_anthy_remove_word(uim_dict *dict, uim_word *word)
265 {
266 if (dict == NULL)
267 return 0;
268
269 return dict_anthy_delete_priv_dic(word->phon, word->desc,
270 word->cclass_native);
271 }
272
273 static void
uim_dict_anthy_refresh(uim_dict * dict)274 uim_dict_anthy_refresh(uim_dict *dict)
275 {
276 if (dict == NULL)
277 return;
278
279 dict->word_list = NULL;
280 word_free_list(dict->word_list);
281 dict_anthy_read_priv_dic_list(&dict->word_list);
282 }
283