1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * Copyright (C) 2006 Kouhei Sutou <kou@cozmixng.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307 USA
19 *
20 * $Id: tomoe-dict.c 1534 2007-06-20 11:53:14Z ikezoe $
21 */
22
23 #include "tomoe-dict.h"
24 #include "tomoe-module.h"
25 #include "tomoe-candidate.h"
26
27 static GList *dicts = NULL;
28 static gchar *module_dir = NULL;
29
tomoe_dict_init(void)30 void tomoe_dict_init (void)
31 {
32 }
33
tomoe_dict_quit(void)34 void tomoe_dict_quit (void)
35 {
36 tomoe_dict_unload ();
37 tomoe_dict_set_default_module_dir (NULL);
38 }
39
40 const gchar *
tomoe_dict_get_default_module_dir(void)41 tomoe_dict_get_default_module_dir (void)
42 {
43 return module_dir;
44 }
45
46 void
tomoe_dict_set_default_module_dir(const gchar * dir)47 tomoe_dict_set_default_module_dir (const gchar *dir)
48 {
49 if (module_dir)
50 g_free (module_dir);
51 module_dir = NULL;
52
53 if (dir)
54 module_dir = g_strdup (dir);
55 }
56
57 static const gchar *
_tomoe_dict_module_dir(void)58 _tomoe_dict_module_dir (void)
59 {
60 const gchar *dir;
61
62 if (module_dir)
63 return module_dir;
64
65 dir = g_getenv ("TOMOE_DICT_MODULE_DIR");
66 if (dir)
67 return dir;
68
69 return DICT_MODULEDIR;
70 }
71
72 void
tomoe_dict_load(const gchar * base_dir)73 tomoe_dict_load (const gchar *base_dir)
74 {
75 if (!base_dir)
76 base_dir = _tomoe_dict_module_dir ();
77
78 dicts = g_list_concat (tomoe_module_load_modules (base_dir), dicts);
79 }
80
81 TomoeModule *
tomoe_dict_load_module(const gchar * name)82 tomoe_dict_load_module (const gchar *name)
83 {
84 TomoeModule *module;
85
86 module = tomoe_module_find (dicts, name);
87 if (module)
88 return module;
89
90 module = tomoe_module_load_module (_tomoe_dict_module_dir (), name);
91 if (module) {
92 if (g_type_module_use (G_TYPE_MODULE (module))) {
93 dicts = g_list_prepend (dicts, module);
94 g_type_module_unuse (G_TYPE_MODULE (module));
95 }
96 }
97
98 return module;
99 }
100
101 void
tomoe_dict_unload(void)102 tomoe_dict_unload (void)
103 {
104 g_list_foreach (dicts, (GFunc) tomoe_module_unload, NULL);
105 g_list_free (dicts);
106 dicts = NULL;
107 }
108
109 GList *
tomoe_dict_get_registered_types(void)110 tomoe_dict_get_registered_types (void)
111 {
112 return tomoe_module_collect_registered_types (dicts);
113 }
114
115 GList *
tomoe_dict_get_log_domains(void)116 tomoe_dict_get_log_domains (void)
117 {
118 return tomoe_module_collect_log_domains (dicts);
119 }
120
121 #define tomoe_dict_init init
G_DEFINE_ABSTRACT_TYPE(TomoeDict,tomoe_dict,G_TYPE_OBJECT)122 G_DEFINE_ABSTRACT_TYPE (TomoeDict, tomoe_dict, G_TYPE_OBJECT)
123 #undef tomoe_dict_init
124
125 static void
126 tomoe_dict_class_init (TomoeDictClass *klass)
127 {
128 klass->get_name = NULL;
129 klass->register_char = NULL;
130 klass->unregister_char = NULL;
131 klass->get_char = NULL;
132 klass->search = NULL;
133 klass->flush = NULL;
134 klass->is_editable = NULL;
135 klass->is_available = NULL;
136 klass->get_available_private_utf8 = NULL;
137 }
138
139 static void
init(TomoeDict * dict)140 init (TomoeDict *dict)
141 {
142 }
143
144 /**
145 * tomoe_dict_new:
146 * @name: The name of dictionary type.
147 * @first_property: the name of the first property.
148 * @... : the value of the first property, followed optionally by more name/value pairs, followed by NULL
149 *
150 * Create a new #TomoeDict.
151 *
152 * Return value: a new #TomoeDict.
153 */
154 TomoeDict *
tomoe_dict_new(const gchar * name,const gchar * first_property,...)155 tomoe_dict_new (const gchar *name, const gchar *first_property, ...)
156 {
157 TomoeModule *module;
158 GObject *dict;
159 va_list var_args;
160
161 module = tomoe_dict_load_module (name);
162 g_return_val_if_fail (module != NULL, NULL);
163
164 va_start (var_args, first_property);
165 dict = tomoe_module_instantiate (module, first_property, var_args);
166 va_end (var_args);
167
168 return TOMOE_DICT (dict);
169 }
170
171 /**
172 * tomoe_dict_get_name:
173 * @dict: a #TomoeDict.
174 *
175 * Get the dictionary name.
176 *
177 * Return value: the name of the dictionary.
178 */
179 const gchar *
tomoe_dict_get_name(TomoeDict * dict)180 tomoe_dict_get_name (TomoeDict *dict)
181 {
182 TomoeDictClass *klass;
183
184 g_return_val_if_fail (TOMOE_IS_DICT (dict), NULL);
185
186 klass = TOMOE_DICT_GET_CLASS (dict);
187 if (klass->get_name)
188 return klass->get_name (dict);
189 else
190 return NULL;
191 }
192
193 /**
194 * tomoe_dict_register_char:
195 * @dict: a TomoeDict object.
196 * @chr: a #TomoeChar object to register.
197 *
198 * Register a #TomoeChar object.
199 *
200 * Return value: TRUE if success.
201 */
202 gboolean
tomoe_dict_register_char(TomoeDict * dict,TomoeChar * chr)203 tomoe_dict_register_char (TomoeDict *dict, TomoeChar *chr)
204 {
205 TomoeDictClass *klass;
206
207 g_return_val_if_fail (TOMOE_IS_DICT (dict), FALSE);
208
209 if (!tomoe_dict_is_editable (dict)) {
210 g_warning ("the dictionary isn't editable.");
211 return FALSE;
212 }
213
214 klass = TOMOE_DICT_GET_CLASS (dict);
215 if (klass->register_char) {
216 gboolean need_to_set_utf8, success;
217
218 need_to_set_utf8 = !tomoe_char_get_utf8 (chr);
219 if (need_to_set_utf8) {
220 gchar *utf8;
221 utf8 = tomoe_dict_get_available_private_utf8 (dict);
222 if (!utf8) {
223 g_warning ("there is no available PUA(Private Use Area)");
224 return FALSE;
225 }
226 tomoe_char_set_utf8 (chr, utf8);
227 g_free (utf8);
228 }
229 success = klass->register_char (dict, chr);
230 if (!success && need_to_set_utf8)
231 tomoe_char_set_utf8 (chr, NULL);
232 return success;
233 } else {
234 return FALSE;
235 }
236 }
237
238 /**
239 * tomoe_dict_unregister_char:
240 * @dict: a TomoeDict object.
241 * @utf8: UTF-8 encoded value of the character.
242 *
243 * Unregister a #TomoeChar object which has utf8 code point.
244 *
245 * Return value: TRUE if success.
246 */
247 gboolean
tomoe_dict_unregister_char(TomoeDict * dict,const gchar * utf8)248 tomoe_dict_unregister_char (TomoeDict *dict, const gchar *utf8)
249 {
250 TomoeDictClass *klass;
251
252 g_return_val_if_fail (TOMOE_IS_DICT (dict), FALSE);
253
254 if (!tomoe_dict_is_editable (dict)) {
255 g_warning ("the dictionary isn't editable.");
256 return FALSE;
257 }
258
259 klass = TOMOE_DICT_GET_CLASS (dict);
260 if (klass->unregister_char)
261 return klass->unregister_char (dict, utf8);
262 else
263 return FALSE;
264 }
265
266 /**
267 * tomoe_dict_get_char:
268 * @dict: a TomoeDict object.
269 * @utf8: UTF-8 encoded value of the character.
270 *
271 * Get a #TomoeChar object which has utf8 code point
272 *
273 * Return value: a #TomoeChar object.
274 */
275 TomoeChar *
tomoe_dict_get_char(TomoeDict * dict,const gchar * utf8)276 tomoe_dict_get_char (TomoeDict *dict, const gchar *utf8)
277 {
278 TomoeDictClass *klass;
279
280 g_return_val_if_fail (TOMOE_IS_DICT (dict), NULL);
281
282 klass = TOMOE_DICT_GET_CLASS (dict);
283 if (klass->get_char)
284 return klass->get_char (dict, utf8);
285 else
286 return FALSE;
287 }
288
289 GList *
tomoe_dict_search(TomoeDict * dict,TomoeQuery * query)290 tomoe_dict_search (TomoeDict *dict, TomoeQuery *query)
291 {
292 TomoeDictClass *klass;
293
294 g_return_val_if_fail (TOMOE_IS_DICT (dict), NULL);
295
296 klass = TOMOE_DICT_GET_CLASS (dict);
297 if (klass->search)
298 return klass->search (dict, query);
299 else
300 return NULL;
301 }
302
303 gboolean
tomoe_dict_flush(TomoeDict * dict)304 tomoe_dict_flush (TomoeDict *dict)
305 {
306 TomoeDictClass *klass;
307
308 g_return_val_if_fail (TOMOE_IS_DICT (dict), FALSE);
309
310 klass = TOMOE_DICT_GET_CLASS (dict);
311 if (klass->flush)
312 return klass->flush (dict);
313 else
314 return FALSE;
315 }
316
317 gboolean
tomoe_dict_copy(TomoeDict * src_dict,TomoeDict * dest_dict)318 tomoe_dict_copy (TomoeDict *src_dict, TomoeDict *dest_dict)
319 {
320 g_return_val_if_fail (TOMOE_IS_DICT (src_dict), FALSE);
321 g_return_val_if_fail (TOMOE_IS_DICT (dest_dict), FALSE);
322
323 if (!tomoe_dict_is_editable (dest_dict)) {
324 g_warning ("destination dictionary isn't editable.");
325 return FALSE;
326 }
327
328 if (TOMOE_DICT_GET_CLASS (src_dict)->copy)
329 return TOMOE_DICT_GET_CLASS (src_dict)->copy (src_dict, dest_dict);
330
331 return tomoe_dict_plain_copy (src_dict, dest_dict);
332 }
333
334 gboolean
tomoe_dict_plain_copy(TomoeDict * src_dict,TomoeDict * dest_dict)335 tomoe_dict_plain_copy (TomoeDict *src_dict, TomoeDict *dest_dict)
336 {
337 TomoeQuery *query;
338 GList *cands = NULL, *node;
339
340 g_return_val_if_fail (TOMOE_IS_DICT (src_dict), FALSE);
341 g_return_val_if_fail (TOMOE_IS_DICT (dest_dict), FALSE);
342
343 if (!tomoe_dict_is_available (src_dict)) {
344 g_warning ("source dictionary isn't available.");
345 return FALSE;
346 }
347 if (!tomoe_dict_is_editable (dest_dict)) {
348 g_warning ("destination dictionary isn't editable.");
349 return FALSE;
350 }
351
352 query = tomoe_query_new ();
353
354 cands = tomoe_dict_search (dest_dict, query);
355 for (node = cands; node; node = g_list_next (node)) {
356 TomoeChar *chr = tomoe_candidate_get_char (TOMOE_CANDIDATE (node->data));
357 tomoe_dict_unregister_char (dest_dict, tomoe_char_get_utf8 (chr));
358 }
359
360 if (cands) {
361 g_list_foreach (cands, (GFunc) g_object_unref, NULL);
362 g_list_free (cands);
363 }
364
365 cands = tomoe_dict_search (src_dict, query);
366 for (node = cands; node; node = g_list_next (node)) {
367 TomoeChar *chr = tomoe_candidate_get_char (TOMOE_CANDIDATE (node->data));
368 TomoeChar *new_chr = tomoe_char_dup (chr);
369 tomoe_dict_register_char (dest_dict, new_chr);
370 g_object_unref (new_chr);
371 }
372
373 if (cands) {
374 g_list_foreach (cands, (GFunc) g_object_unref, NULL);
375 g_list_free (cands);
376 }
377
378 g_object_unref (query);
379
380 return TRUE;
381 }
382
383 gboolean
tomoe_dict_is_editable(TomoeDict * dict)384 tomoe_dict_is_editable (TomoeDict *dict)
385 {
386 TomoeDictClass *klass;
387
388 g_return_val_if_fail (TOMOE_IS_DICT (dict), FALSE);
389
390 klass = TOMOE_DICT_GET_CLASS (dict);
391 if (klass->is_editable)
392 return klass->is_editable (dict);
393 else
394 return FALSE;
395 }
396
397 gboolean
tomoe_dict_is_available(TomoeDict * dict)398 tomoe_dict_is_available (TomoeDict *dict)
399 {
400 TomoeDictClass *klass;
401
402 g_return_val_if_fail (TOMOE_IS_DICT (dict), FALSE);
403
404 klass = TOMOE_DICT_GET_CLASS (dict);
405 if (klass->is_available)
406 return klass->is_available (dict);
407 else
408 return FALSE;
409 }
410
411 gchar *
tomoe_dict_get_available_private_utf8(TomoeDict * dict)412 tomoe_dict_get_available_private_utf8 (TomoeDict *dict)
413 {
414 TomoeDictClass *klass;
415
416 g_return_val_if_fail (TOMOE_IS_DICT (dict), NULL);
417
418 klass = TOMOE_DICT_GET_CLASS (dict);
419 if (klass->get_available_private_utf8) {
420 return klass->get_available_private_utf8 (dict);
421 } else {
422 g_warning ("%s backend doesn't support PUA(Private Use Area)",
423 tomoe_dict_get_name (dict));
424 return NULL;
425 }
426 }
427
428 /*
429 vi:ts=4:nowrap:ai:expandtab
430 */
431