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