(mlang__init): Handle extra chars.
[m17n/m17n-lib.git] / src / language.c
1 /* language.c -- language module.
2    Copyright (C) 2003, 2004
3      National Institute of Advanced Industrial Science and Technology (AIST)
4      Registration Number H15PRO112
5
6    This file is part of the m17n library.
7
8    The m17n library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public License
10    as published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12
13    The m17n library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public
19    License along with the m17n library; if not, write to the Free
20    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21    02111-1307, USA.  */
22
23 #include <config.h>
24 #include <stdlib.h>
25 #include "m17n.h"
26 #include "m17n-misc.h"
27 #include "internal.h"
28 #include "language.h"
29 #include "symbol.h"
30 #include "plist.h"
31
32 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
33
34 static MSymbol M_script_lang_list;
35
36 \f
37 /* Internal API */
38
39 int
40 mlang__init ()
41 {
42   MDatabase *mdb;
43   MPlist *plist, *pl;
44
45   Mlanguage = msymbol ("language");
46   msymbol_put (Mlanguage, Mtext_prop_serializer,
47                (void *) msymbol__serializer);
48   msymbol_put (Mlanguage, Mtext_prop_deserializer,
49                (void *) msymbol__deserializer);
50   Miso639_2 = msymbol ("iso639-2");
51   Miso639_1 = msymbol ("iso639-1");
52   M_script_lang_list = msymbol_as_managing_key ("  script-lang-list");
53
54   mdb = mdatabase_find (msymbol ("standard"), Mlanguage,
55                         msymbol ("iso639"), Mnil);
56   if (! mdb)
57     return 0;
58   if (! (plist = mdatabase_load (mdb)))
59     MERROR (MERROR_DB, -1);
60
61   MPLIST_DO (pl, plist)
62     {
63       MPlist *p;
64       MSymbol code3, code2, lang;
65       MText *native, *extra;
66
67       if (! MPLIST_PLIST_P (pl))
68         continue;
69       p = MPLIST_PLIST (pl);
70       if (! MPLIST_SYMBOL_P (p))
71         continue;
72       code3 = MPLIST_SYMBOL (p);
73       p = MPLIST_NEXT (p);
74       if (! MPLIST_SYMBOL_P (p))
75         continue;
76       code2 = MPLIST_SYMBOL (p);
77       p = MPLIST_NEXT (p);
78       if (! MPLIST_SYMBOL_P (p))
79         continue;
80       lang = MPLIST_SYMBOL (p);
81       msymbol_put (code3, Mlanguage, lang);
82       p = MPLIST_NEXT (p);      
83       native = MPLIST_MTEXT_P (p) ? MPLIST_MTEXT (p) : NULL;
84       if (native)
85         {
86           msymbol_put (code3, Mtext, native);
87           p = MPLIST_NEXT (p);
88           extra = MPLIST_MTEXT_P (p) ? MPLIST_MTEXT (p) : NULL;
89           if (extra)
90             mtext_put_prop (native, 0, mtext_nchars (native), Mtext, extra);
91         }
92       if (code2 != Mnil)
93         {
94           msymbol_put (code3, Miso639_1, code2);
95           msymbol_put (code2, Mlanguage, lang);
96           msymbol_put (code2, Miso639_2, code3);
97           if (native)
98             msymbol_put (code2, Mtext, native);
99         }
100     }
101   M17N_OBJECT_UNREF (plist);
102   return 0;
103 }
104
105 void
106 mlang__fini (void)
107 {
108 }
109
110
111 /** Return a plist of languages that use SCRIPT.  If SCRIPT is Mnil,
112     return a plist of all languages.  Each element of the plist has
113     3-letter language code as a key and 2-letter language code as a
114     value.  A caller must unref the returned value when finished.  */
115
116 MPlist *
117 mlanguage__list (MSymbol script)
118 {
119   MDatabase *mdb;
120   MPlist *language_list, *plist, *pl;
121
122   if (script)
123     {
124       if ((language_list = msymbol_get (script, M_script_lang_list)))
125         {
126           M17N_OBJECT_REF (language_list);
127           return language_list;
128         }
129       mdb = mdatabase_find (msymbol ("unicode"), Mscript, Mlanguage, Mnil);
130       if (! mdb
131           || ! (plist = mdatabase_load (mdb)))
132         MERROR (MERROR_DB, NULL);
133       MPLIST_DO (pl, plist)
134         {
135           MPlist *p, *lang_list;
136           MSymbol code3, code2;
137
138           if (! MPLIST_PLIST_P (pl))
139             continue;
140           p = MPLIST_PLIST (pl);
141           if (! MPLIST_SYMBOL_P (p))
142             continue;
143           lang_list = mplist ();
144           if (MPLIST_SYMBOL (p) == script)
145             language_list = lang_list;
146           msymbol_put (MPLIST_SYMBOL (p), M_script_lang_list, lang_list);
147           MPLIST_DO (p, MPLIST_NEXT (p))
148             if (MPLIST_SYMBOL_P (p))
149               {
150                 code2 = MPLIST_SYMBOL (p);
151                 if (MSYMBOL_NAMELEN (code2) == 2)
152                   code3 = msymbol_get (code2, Miso639_2);
153                 else
154                   code3 = code2, code2 = Mnil;
155                 if (code3 != Mnil)
156                   mplist_push (lang_list, code3, code2);
157               }
158           M17N_OBJECT_UNREF (lang_list);
159         }
160       M17N_OBJECT_UNREF (plist);
161       if (language_list)
162         M17N_OBJECT_REF (language_list);
163       else
164         {
165           language_list = mplist ();
166           msymbol_put (script, M_script_lang_list, language_list);
167         }
168     }
169   else
170     {
171       mdb = mdatabase_find (msymbol ("standard"), Mlanguage,
172                             msymbol ("iso639"), Mnil);
173       if (! mdb
174           || ! (plist = mdatabase_load (mdb)))
175         MERROR (MERROR_DB, NULL);
176       MPLIST_DO (pl, plist)
177         {
178           MPlist *p;
179           MSymbol code3, code2;
180
181           if (! MPLIST_PLIST_P (pl))
182             continue;
183           p = MPLIST_PLIST (pl);
184           if (! MPLIST_SYMBOL_P (p))
185             continue;
186           code3 = MPLIST_SYMBOL (p);
187           p = MPLIST_NEXT (p);
188           if (! MPLIST_SYMBOL_P (p))
189             continue;
190           code2 = MPLIST_SYMBOL (p);
191           mplist_push (language_list, code3, code2);
192         }
193       M17N_OBJECT_UNREF (plist);
194     }
195   return language_list;
196 }
197
198 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
199 \f
200
201 /* External API */
202
203 MSymbol Miso639_1, Miso639_2;