Update copyright years
[m17n/m17n-lib.git] / src / language.c
1 /* language.c -- language (and script) module.
2    Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
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., 51 Franklin Street, Fifth Floor,
21    02111-1307, USA.  */
22
23 #include <config.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <locale.h>
28 #include "m17n.h"
29 #include "m17n-misc.h"
30 #include "internal.h"
31 #include "language.h"
32 #include "symbol.h"
33 #include "plist.h"
34 #include "mtext.h"
35
36 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
37
38 static MPlist *language_list;
39 static MPlist *script_list;
40 static MPlist *langname_list;
41
42 static MPlist *
43 load_lang_script_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
44 {
45   MDatabase *mdb = mdatabase_find (tag0, tag1, tag2, tag3);
46   MPlist *plist, *pl, *p;
47
48   if (! mdb
49       || ! (plist = mdatabase_load (mdb)))
50     return NULL;
51   /* Check at least if the plist is ((SYMBOL ...) ...).  */
52   for (pl = plist; ! MPLIST_TAIL_P (pl);)
53     {
54       if (! MPLIST_PLIST_P (pl))
55         mplist__pop_unref (pl);
56       else
57         {
58           p = MPLIST_PLIST (pl);
59           if (! MPLIST_SYMBOL_P (p))
60             mplist__pop_unref (pl);
61           else
62             pl = MPLIST_NEXT (pl);
63         }
64     }
65   return plist;
66 }
67
68 static int
69 init_language_list (void)
70 {
71   language_list = load_lang_script_list (msymbol ("standard"), Mlanguage,
72                                          msymbol ("iso639"), Mnil);
73   if (! language_list)
74     {
75       language_list = mplist ();
76       MERROR (MERROR_DB, -1);
77     }
78   return 0;
79 }
80
81
82 static int
83 init_script_list (void)
84 {
85   script_list = load_lang_script_list (msymbol ("standard"), Mscript,
86                                        msymbol ("unicode"), Mnil);
87   if (! script_list)
88     {
89       script_list = mplist ();
90       MERROR (MERROR_DB, -1);
91     }
92   return 0;
93 }
94
95 static MPlist *
96 load_lang_name (MSymbol target3, MSymbol target2)
97 {
98   MPlist *plist, *pl, *p;
99
100   plist = mplist ();
101   mplist_add (plist, Msymbol, target3);
102   pl = mdatabase_list (Mlanguage, Mname, target3, Mnil);
103   if (! pl && target2 != Mnil)
104     pl = mdatabase_list (Mlanguage, Mname, target2, Mnil);
105   if (pl)
106     {
107       MPLIST_DO (p, pl)
108         {
109           MDatabase *mdb = MPLIST_VAL (p);
110           MPlist *p0 = mdatabase_load (mdb), *p1, *territories;
111           MSymbol script = mdatabase_tag (mdb)[3];
112           
113           if (MPLIST_PLIST_P (p0))
114             {
115               p1 = MPLIST_PLIST (p0);
116               if (MPLIST_SYMBOL_P (p1) && MPLIST_SYMBOL (p1) == Mlanguage)
117                 {
118                   p1 = MPLIST_NEXT (MPLIST_NEXT (MPLIST_NEXT (MPLIST_NEXT (p1))));
119                   territories = p1;
120                   while (! MPLIST_TAIL_P (p1))
121                     {
122                       if (MPLIST_SYMBOL_P (p1))
123                         p1 = MPLIST_NEXT (p1);
124                       else
125                         mplist__pop_unref (p1);
126                     }
127                   M17N_OBJECT_REF (territories);
128                   mplist__pop_unref (p0);
129                 }
130               else
131                 territories = mplist ();
132               mplist_push (p0, Mplist, territories);
133               M17N_OBJECT_UNREF (territories);
134               mplist_push (p0, Msymbol, script);
135               mplist_add (plist, Mplist, p0);
136               M17N_OBJECT_UNREF (p0);
137             }
138         }
139       M17N_OBJECT_UNREF (pl);
140     }
141   mplist_push (langname_list, Mplist, plist);
142   M17N_OBJECT_UNREF (plist);
143   return plist;
144 }
145
146 \f
147 /* Internal API */
148
149 int
150 mlang__init ()
151 {
152   msymbol_put_func (Mlanguage, Mtext_prop_serializer,
153                     M17N_FUNC (msymbol__serializer));
154   msymbol_put_func (Mlanguage, Mtext_prop_deserializer,
155                     M17N_FUNC (msymbol__deserializer));
156   Miso639_2 = msymbol ("iso639-2");
157   Miso639_1 = msymbol ("iso639-1");
158
159   language_list = script_list = langname_list = NULL;
160   return 0;
161 }
162
163 void
164 mlang__fini (void)
165 {
166   M17N_OBJECT_UNREF (language_list);
167   M17N_OBJECT_UNREF (script_list);
168   M17N_OBJECT_UNREF (langname_list);
169 }
170
171 /*=*/
172
173 /***en
174     @brief Get information about a language.
175
176     The mlanguage_info () function returns a well-formed @e plist that
177     contains information about $LANGUAGE.  $LANGUAGE is a symbol whose
178     name is an ISO639-2 3-letter language code, an ISO639-1 2-letter
179     language codes, or an English word.
180
181     The format of the plist is:
182
183 @verbatim
184         (ISO639-2 [ISO639-1 | nil] ENGLISH-NAME ["NATIVE-NAME" | nil]
185                   ["REPRESENTATIVE-CHARACTERS"])
186 @endverbatim
187
188     where, ISO639-2 is a symbol whose name is 3-letter language code
189     of ISO639-2, ISO639-1 is a symbol whose name is 2-letter language
190     code of ISO639-1, ENGLISH-NAME is a symbol whose name is the
191     English name of the language, "NATIVE-NAME" is an M-text written
192     by the most natural way in the language,
193     "REPRESENTATIVE-CHARACTERS" is an M-text that contains
194     representative characters used by the language.
195
196     It is assured that the formats of both M-texts are
197     #MTEXT_FORMAT_UTF_8.
198
199     @return
200     If the information is available, this function returns a plist
201     that should not be modified nor freed.  Otherwise, it returns
202     @c NULL.
203
204     @seealso
205     mlanguage_list ()  */
206
207 MPlist *
208 mlanguage__info (MSymbol language)
209 {
210   MPlist *plist;
211
212   if (! language_list
213       && init_language_list () < 0)
214     return NULL;
215
216   MPLIST_DO (plist, language_list)
217     {
218       MPlist *pl = MPLIST_PLIST (plist);
219
220       if (MPLIST_SYMBOL (pl) == language)
221         return pl;
222       if (MPLIST_TAIL_P (pl))
223         continue;
224       pl = MPLIST_NEXT (pl);
225       if (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == language)
226         return MPLIST_PLIST (plist);
227       if (MPLIST_TAIL_P (pl))
228         continue;
229       pl = MPLIST_NEXT (pl);
230       if (MPLIST_MTEXT_P (pl))
231         {
232           MText *mt = MPLIST_MTEXT (pl);
233
234           if (mtext_nbytes (mt) == MSYMBOL_NAMELEN (language)
235               && strncasecmp ((char *) MTEXT_DATA (MPLIST_MTEXT (pl)),
236                               MSYMBOL_NAME (language),
237                               MSYMBOL_NAMELEN (language)) == 0)
238             return MPLIST_PLIST (plist);
239         }
240     }
241   return NULL;
242 }
243
244 static MPlist *
245 mscript__info (MSymbol script)
246 {
247   MPlist *plist;
248
249   if (! script_list
250       && init_script_list () < 0)
251     return NULL;
252   MPLIST_DO (plist, script_list)
253     {
254       MPlist *pl = MPLIST_PLIST (plist);
255
256       if (MPLIST_SYMBOL (pl) == script)
257         return pl;
258     }
259   return NULL;
260 }
261
262 MPlist *
263 mscript__char_list (MSymbol name)
264 {
265   MPlist *plist = mscript__info (name);
266
267   if (plist                     /* script name */
268       && (plist = MPLIST_NEXT (plist)) /* language list */
269       && ! MPLIST_TAIL_P (plist)
270       && (plist = MPLIST_NEXT (plist)) /* char list */
271       && MPLIST_PLIST_P (plist))
272     return MPLIST_PLIST (plist);
273   return NULL;
274 }
275
276 MSymbol
277 mscript__otf_tag (MSymbol script)
278 {
279   MPlist *plist = mscript__info (script);
280
281   if (plist                     /* script name */
282       && (plist = MPLIST_NEXT (plist)) /* language list */
283       && ! MPLIST_TAIL_P (plist)
284       && (plist = MPLIST_NEXT (plist)) /* char list */
285       && ! MPLIST_TAIL_P (plist)
286       && (plist = MPLIST_NEXT (plist)) /* otf tag */
287       && MPLIST_SYMBOL_P (plist))
288     return MPLIST_SYMBOL (plist);
289   return NULL;
290 }
291
292 MSymbol
293 mscript__from_otf_tag (MSymbol otf_tag)
294 {
295   MPlist *plist;
296   /* As it is expected that this function is called in a sequence with
297      the same argument, we use a cache.  */
298   static MSymbol last_otf_tag, script;
299
300   if (! script_list)
301     {
302       last_otf_tag = script = Mnil;
303       if (init_script_list () < 0)
304         return Mnil;
305     }
306   if (otf_tag == last_otf_tag)
307     return script;
308   last_otf_tag = otf_tag;
309   script = Mnil;
310   MPLIST_DO (plist, script_list)
311     {
312       MPlist *pl = MPLIST_PLIST (plist), *p;
313
314       if (pl                           /* script name */
315           && (p = MPLIST_NEXT (pl))    /* language tag */
316           && ! MPLIST_TAIL_P (p)
317           && (p = MPLIST_NEXT (p)) /* char list */
318           && ! MPLIST_TAIL_P (p)
319           && (p = MPLIST_NEXT (p)) /* otf tag */
320           && ! MPLIST_TAIL_P (p))
321         {
322           if (MPLIST_SYMBOL_P (p))
323             {
324               if (otf_tag == MPLIST_SYMBOL (p))
325                   return MPLIST_SYMBOL (pl);
326             }
327           else if (MPLIST_PLIST (p))
328             {
329               MPlist *p0;
330
331               MPLIST_DO (p0, MPLIST_PLIST (p))
332                 if (MPLIST_SYMBOL_P (p0) && otf_tag == MPLIST_SYMBOL (p0))
333                   return MPLIST_SYMBOL (pl);
334             }
335         }
336     }
337   return script;
338 }
339
340 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
341 \f
342
343 /* External API */
344
345 MSymbol Miso639_1, Miso639_2;
346
347 /*=*/
348
349 /***en
350     @brief List 3-letter language codes.
351
352     The mlanguage_list () funciton returns a well-formed plist whose
353     keys are #Msymbol and values are symbols whose names are ISO639-2
354     3-letter language codes.
355
356     @return
357     This function returns a plist.  The caller should free it by
358     m17n_object_unref ().
359
360     @seealso
361     mscript_list ().  */
362
363 /***ja
364     @brief 3ʸ»ú¸À¸ì¥³¡¼¥É¤ò¥ê¥¹¥È¤¹¤ë.
365
366     ´Ø¿ô mlanguage_list () ¤Ï¡¢À°·Á¼° (well-formed) plist ¤òÊÖ¤¹¡£³Æ¥­¡¼
367     ¤Ï #Msymbol ¤Ç¤¢¤ê¡¢¸Ä¡¹¤ÎÃͤϠISO639-2 ¤ËÄê¤á¤é¤ì¤¿3ʸ»ú¸À¸ì¥³¡¼
368     ¥É¤ò̾Á°¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
369
370     @return
371     ¤³¤Î´Ø¿ô¤¬ÊÖ¤¹ plist ¤Ï¡¢¸Æ¤Ó½Ð¤·Â¦¤¬ m17n_object_unref () ¤ò»È¤Ã
372     ¤Æ²òÊü¤¹¤ëɬÍפ¬¤¢¤ë¡£
373
374     @seealso
375     mscript_list ().  */
376
377 MPlist *
378 mlanguage_list (void)
379 {
380   MPlist *plist, *pl, *p, *p0;
381
382   if (! language_list
383       && init_language_list () < 0)
384     return NULL;
385   plist = pl = mplist ();
386   MPLIST_DO (p, language_list)
387     {
388       p0 = MPLIST_PLIST (p);
389       pl = mplist_add (pl, Msymbol, MPLIST_VAL (p0));
390     }
391   return plist;
392 }
393
394 /*=*/
395
396 /***en
397     @brief Get a language code.
398
399     The mlanguage_code () function returns a symbol whose name is the
400     ISO639 language code of $LANGUAGE. $LANGUAGE is a symbol whose
401     name is an ISO639-2 3-letter language code, an ISO639-1 2-letter
402     language codes, or an English word.
403
404     $LEN specifies the type of the returned language code.  If it is
405     3, an ISO639-2 3-letter language code is returned.  If it is 2, an
406     ISO639-1 2-letter language code is returned when defined;
407     otherwise #Mnil is returned.  If it is 0, a 2-letter code is
408     returned when defined; otherwise a 3-letter code is returned.
409
410     @return
411     If the information is available, this function returns a non-#Mnil
412     symbol.  Otherwise, it returns #Mnil.
413
414     @seealso
415     mlanguage_name_list (), mlanguage_text ().  */
416
417 /***ja
418     @brief ¸À¸ì¥³¡¼¥É¤òÆÀ¤ë.
419
420     ´Ø¿ô mlanguage_code () ¤Ï¡¢$LANGUAGE ¤ËÂбþ¤·¤¿ ISO-639 ¸À¸ì¥³¡¼¥É
421     ¤¬Ì¾Á°¤Ç¤¢¤ë¤è¤¦¤Ê¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£$LANGUAGE ¤Ï¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¤½¤Î
422     Ì¾Á°¤Ï¡¢ISO639-2 3ʸ»ú¸À¸ì¥³¡¼¥É¡¢ISO639-1 2ʸ»ú¸À¸ì¥³¡¼¥É¡¢±Ñ¸ì̾¡¢
423     ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
424
425     $LEN ¤ÏÊÖ¤µ¤ì¤ë¸À¸ì¥³¡¼¥É¤Î¼ïÎà¤ò·èÄꤹ¤ë¡£$LEN ¤¬3¤Î¾ì¹ç¤Ï 
426     ISO639-2 3ʸ»ú¸À¸ì¥³¡¼¥É¤¬ÊÖ¤µ¤ì¤ë¡£2¤Î¾ì¹ç¤Ï¡¢¤â¤·ÄêµÁ¤µ¤ì¤Æ¤¤¤ì
427     ¤Ð ISO639-1 2ʸ»ú¸À¸ì¥³¡¼¥É¤¬¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð #Mnil ¤¬ÊÖ¤µ¤ì¤ë¡£0 
428     ¤Î¾ì¹ç¤Ï¡¢¤â¤·ÄêµÁ¤µ¤ì¤Æ¤¤¤ì¤Ð2ʸ»ú¥³¡¼¥É¤¬¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð3ʸ»ú¥³¡¼
429     ¥É¤¬ÊÖ¤µ¤ì¤ë¡£
430
431     @return
432     ¤â¤·¾ðÊó¤¬ÆÀ¤é¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï #Mnil °Ê³°¤Î¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£¤½¤¦
433     ¤Ç¤Ê¤±¤ì¤Ð #Mnil ¤òÊÖ¤¹¡£
434
435     @seealso
436     mlanguage_name (), mlanguage_text ().  */
437
438 MSymbol
439 mlanguage_code (MSymbol language, int len)
440 {
441   MPlist *plist = mlanguage__info (language);
442   MSymbol code;
443
444   if (! plist)
445     return Mnil;
446   if (! MPLIST_SYMBOL_P (plist))
447     return Mnil;
448   code = MPLIST_SYMBOL (plist);
449   if (len == 3)
450     return code;
451   plist = MPLIST_NEXT (plist);
452   return ((MPLIST_SYMBOL_P (plist) && MPLIST_SYMBOL (plist) != Mnil)
453           ? MPLIST_SYMBOL (plist)
454           : len == 0 ? code : Mnil);
455 }
456
457 /*=*/
458
459 /***en
460     @brief Return the language names written in the specified language.
461
462     The mlanguage_name_list () function returns a plist of LANGUAGE's
463     names written in TARGET language.  SCRIPT and TERRITORY, if not #Mnil,
464     specifies which script and territory to concern at first.
465
466     LANGUAGE and TARGET must be a symbol whose name is an ISO639-2
467     3-letter language code or an ISO639-1 2-letter language codes.
468     TARGET may be #Mnil, in which case, the language of the current
469     locale is used.  If locale is not set or is C, English is used.
470
471     SCRIPT and TERRITORY must be a symbol whose name is a script and
472     territory name of a locale (e.g. "TW", "SG") respectively.
473
474     @return
475     If the translation is available, this function returns a non-empty
476     plist.  The first element has key #MText and the value is an
477     M-text of a translated language name.  If the succeeding elements
478     also have key #MText, their values are M-texts of alternate
479     translations.
480
481     If no translation is available, @c NULL is returned.
482
483     The returned plist should not be modified nor freed.
484
485     @seealso
486     mlanguage_code (), mlanguage_text ().  */
487
488 MPlist *
489 mlanguage_name_list (MSymbol language, MSymbol target,
490                      MSymbol script, MSymbol territory)
491 {
492   MPlist *plist, *pl;
493   MSymbol language2, target2;
494
495   plist = mlanguage__info (language);
496   if (! plist)
497     return NULL;
498   language = MPLIST_SYMBOL (plist);
499   language2 = MPLIST_SYMBOL (MPLIST_NEXT (plist));
500   if (target != Mnil)
501     {
502       plist = mlanguage__info (target);
503       if (! plist)
504         return NULL;
505       target = MPLIST_SYMBOL (plist);
506       target2 = MPLIST_SYMBOL (MPLIST_NEXT (plist));
507     }
508   else
509     {
510       MLocale *locale = mlocale_set (LC_MESSAGES, NULL);
511
512       if (! locale)
513         {
514           target = msymbol ("eng");
515           target2 = msymbol ("en");
516           script = territory = Mnil;
517         }
518       else
519         {
520           target = mlocale_get_prop (locale, Mlanguage);
521           plist = mlanguage__info (target);
522           if (! plist)
523             return NULL;
524           target = MPLIST_SYMBOL (plist);
525           target2 = MPLIST_SYMBOL (MPLIST_NEXT (plist));
526           script = mlocale_get_prop (locale, Mscript);
527           territory = mlocale_get_prop (locale, Mterritory);
528         }
529     }
530
531   /* Now both LANGUAGE and TARGET are 3-letter codes.  */
532   if (! langname_list)
533     langname_list = mplist ();
534   plist = mplist__assq (langname_list, target);
535   if (plist)
536     plist = MPLIST_PLIST (plist);
537   else
538     plist = load_lang_name (target, target2);
539
540   /* PLIST = (TARGET (SCRIPT (TERRITORY ...) (LANG-CODE NAME ...) ...) ...) */
541   plist = MPLIST_NEXT (plist);
542   if (MPLIST_TAIL_P (plist))
543     return NULL;
544
545   MPLIST_DO (pl, plist)
546     {
547       MPlist *p = MPLIST_PLIST (pl), *p0;
548
549       if (MPLIST_SYMBOL (p) == script
550           && (territory == Mnil
551               || mplist_find_by_value (MPLIST_PLIST (MPLIST_NEXT (p)),
552                                        territory))
553           && (p = MPLIST_NEXT (MPLIST_NEXT (p)))
554           && ((p0 = mplist__assq (p, language))
555               || (p0 = mplist__assq (p, language2))))
556         {
557           plist = p0;
558           break;
559         }
560     }
561   if (MPLIST_TAIL_P (pl))
562     {
563       MPLIST_DO (pl, plist)
564         {
565           MPlist *p = MPLIST_NEXT (MPLIST_PLIST (pl)), *p0;
566
567           if ((territory == Mnil
568                || mplist_find_by_value (MPLIST_VAL (p), territory))
569               && (p = MPLIST_NEXT (MPLIST_NEXT (p)))
570               && ((p0 = mplist__assq (p, language))
571                   || (p0 = mplist__assq (p, language2))))
572             {
573               plist = p0;
574               break;
575             }
576         }
577       if (MPLIST_TAIL_P (pl))
578         {
579           MPLIST_DO (pl, plist)
580             {
581               MPlist *p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (pl))), *p0;
582
583               if ((p0 = mplist__assq (p, language))
584                   || (p0 = mplist__assq (p, language2)))
585                 {
586                   plist = p0;
587                   break;
588                 }
589             }
590           if (MPLIST_TAIL_P (pl))
591             return NULL;
592         }
593     }
594
595   plist = MPLIST_NEXT (MPLIST_PLIST (plist));
596   if (territory != Mnil)
597     {
598       MPLIST_DO (pl, MPLIST_NEXT (plist))
599         if (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == territory)
600           break;
601       if (! MPLIST_TAIL_P (pl)
602           && (pl = MPLIST_NEXT (pl))
603           && MPLIST_MTEXT_P (pl))
604         return pl;
605     }
606   MPLIST_DO (plist, plist)
607     if (MPLIST_MTEXT_P (plist))
608       break;
609   return (MPLIST_MTEXT_P (plist) ? plist : NULL);
610 }
611
612 /*=*/
613
614 /***en
615     @brief Return the language name written in that language.
616
617     The mlanguage_text () function returns, in the form of M-text, the
618     language name of $LANGUAGE written in $LANGUAGE.  If the
619     representative characters of the language are known, the
620     characters of the returned M-text has a text property whose key is
621     #Mtext and whose value is an M-text that contains the
622     representative characters.
623
624     @return
625     If the information is available, this function returns an M-text
626     that should not be modified nor freed.  Otherwise, it returns @c
627     NULL.
628
629     @seealso
630     mlanguage_code (), mlanguage_name ().  */
631
632 /***ja
633     @brief Í¿¤¨¤é¤ì¤¿¸À¸ì¼«¿È¤Ç½ñ¤«¤ì¤¿¸À¸ì̾¤òÊÖ¤¹.
634
635     ´Ø¿ô mlanguage_text () ¤Ï¡¢¸À¸ì $LANGUAGE ¤Ç½ñ¤«¤ì¤¿ $LANGUAGE ¤Î
636     Ì¾Á°¤ò M-text ¤Î·Á¼°¤ÇÊÖ¤¹¡£¤½¤Î¸À¸ì¤ÎÂåɽŪ¤Êʸ»ú¤¬¤ï¤«¤Ã¤Æ¤¤¤ë¾ì
637     ¹ç¤Ï¡¢ÊÖ¤µ¤ì¤ë M-text ¤Î³Æʸ»ú¤Ë¡¢¥­¡¼¤¬ #Mtext ¤ÇÃͤ¬¤½¤ÎÂåɽŪ¤Ê
638     Ê¸»ú¤ò´Þ¤à M-text ¤Ç¤¢¤ë¤è¤¦¤Ê¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬Éղ䵤ì¤ë¡£
639
640     @return
641     µá¤á¤ë¾ðÊó¤¬ÆÀ¤é¤ì¤¿¾ì¹ç¡¢¤³¤Î´Ø¿ô¤¬ÊÖ¤¹ M-text ¤òÊѹ¹¤·¤¿¤ê²òÊü¤·
642     ¤¿¤ê¤·¤Æ¤Ï¤¤¤±¤Ê¤¤¡£¾ðÊó¤¬ÆÀ¤é¤ì¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï @c NULL ¤¬ÊÖ¤µ¤ì¤ë¡£
643
644     @seealso
645     mlanguage_code (), mlanguage_name ().  */
646
647 MText *
648 mlanguage_text (MSymbol language)
649 {
650   MPlist *plist = mlanguage__info (language);
651   MText *mt;
652
653   if (! plist)
654     return NULL;
655   plist = MPLIST_NEXT (plist);
656   if (MPLIST_TAIL_P (plist))
657     return NULL;
658   plist = MPLIST_NEXT (plist);
659   if (MPLIST_TAIL_P (plist))
660     return NULL;
661   plist = MPLIST_NEXT (plist);            
662   if (! MPLIST_MTEXT_P (plist))
663     return NULL;
664   mt = MPLIST_MTEXT (plist);
665   if (mtext_nchars (mt) == 0)
666     return NULL;
667   plist = MPLIST_NEXT (plist);
668   if (MPLIST_MTEXT_P (plist)
669       && ! mtext_get_prop (mt, 0, Mtext))
670     mtext_put_prop (mt, 0, mtext_nchars (mt), Mtext, MPLIST_MTEXT (plist));
671   return mt;
672 }
673
674 /***en
675     @brief List script names.
676
677     The mscript_list () funciton returns a well-formed plist whose
678     keys are #Msymbol and values are symbols whose names are script
679     names.
680
681     @return
682     This function returns a plist.  The caller should free it by
683     m17n_object_unref ().
684
685     @seealso
686     mscript_language_list (), mlanguage_list ().  */
687
688 /***ja
689     @brief ¥¹¥¯¥ê¥×¥È̾¤ò¥ê¥¹¥È¤¹¤ë.
690
691     ´Ø¿ô mscript_list () ¤Ï¡¢À°·Á¼° (well-formed) plist ¤òÊÖ¤¹¡£³Æ¥­¡¼
692     ¤Ï #Msymbol ¤Ç¤¢¤ê¡¢¸Ä¡¹¤ÎÃͤϥ¹¥¯¥ê¥×¥È̾¤ò̾Á°¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢
693     ¤ë¡£
694
695     @return
696     ¤³¤Î´Ø¿ô¤¬ÊÖ¤¹ plist ¤Ï¡¢¸Æ¤Ó½Ð¤·Â¦¤¬ m17n_object_unref () ¤ò»È¤Ã
697     ¤Æ²òÊü¤¹¤ëɬÍפ¬¤¢¤ë¡£
698
699     @seealso
700     mscript_language_list (), mlanguage_list ().  */
701
702 MPlist *
703 mscript_list (void)
704 {
705   MPlist *plist, *pl, *p, *p0;
706
707   if (! script_list
708       && init_script_list () < 0)
709     return NULL;
710   plist = pl = mplist ();
711   MPLIST_DO (p, script_list)
712     {
713       p0 = MPLIST_PLIST (p);
714       pl = mplist_add (pl, Msymbol, MPLIST_VAL (p0));
715     }
716   return plist;
717 }
718
719 /*=*/
720
721 /***en
722     @brief List languages that use a specified script.
723
724     The mscript_language_list () function lists languages that use
725     $SCRIPT.  $SCRIPT is a symbol whose name is the lower-cased
726     version of a script name that appears in the Unicode Character
727     Database.
728
729     @return
730
731     This function returns a well-formed plist whose keys are #Msymbol
732     and values are symbols whose names are ISO639-1 2-letter codes (or
733     ISO639-2 3-letter codes, if the former is not available).  The
734     caller should not modify nor free it.  If the m17n library does
735     not know about $SCRIPT, it returns @ c NULL.
736
737     @seealso
738     mscript_list (), mlanguage_list ().  */
739
740 /***ja
741     @brief Í¿¤¨¤é¤ì¤¿¥¹¥¯¥ê¥×¥È¤òÍѤ¤¤ë¸À¸ì¤ò¥ê¥¹¥È¤¹¤ë.
742
743     ´Ø¿ô mscript_language_list () ¤Ï¡¢$SCRIPT ¤òÍѤ¤¤ë¸À¸ì¤ò¥ê¥¹¥È¤¹¤ë¡£
744     $SCRIPT ¤Ï¥·¥ó¥Ü¥ë¤Ç¡¢¤½¤Î̾Á°¤Ï Unicode Character Database ¤Ë¼¨¤µ
745     ¤ì¤Æ¤¤¤ë¥¹¥¯¥ê¥×¥È̾¤ò¤¹¤Ù¤Æ¾®Ê¸»ú¤Ë¤·¤¿¤â¤Î¤Ç¤¢¤ë¡£
746
747     @return 
748     ¤³¤Î´Ø¿ô¤Ï¡¢À°·Á¼° (well-formed) plist ¤òÊÖ¤¹¡£³Æ¥­¡¼¤Ï 
749     #Msymbol ¤Ç¤¢¤ê¡¢¸Ä¡¹¤ÎÃͤϠISO639-1 ¤ËÄê¤á¤é¤ì¤¿2ʸ»ú¸À¸ì¥³¡¼¥É
750     (ÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ï ISO639-2 ¤ËÄê¤á¤é¤ì¤¿3ʸ»ú¸À¸ì¥³¡¼¥É) ¤ò̾
751     Á°¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£ÊÖ¤µ¤ì¤ë plist ¤ÏÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ
752     ¤Ï¤Ê¤é¤Ê¤¤¡£$SCRIPT ¤¬Ì¤ÃΤξì¹ç¤Ï @c NULL ¤¬ÊÖ¤µ¤ì¤ë¡£
753
754     @seealso
755     mscript_list (), mlanguage_list ().  */
756     
757
758 MPlist *
759 mscript_language_list (MSymbol script)
760 {
761   MPlist *plist = mscript__info (script);
762
763   if (plist                     /* script name */
764       && (plist = MPLIST_NEXT (plist)) /* language list */
765       && MPLIST_PLIST_P (plist))
766     return MPLIST_PLIST (plist);
767   return NULL;
768 }
769
770 /*** @} */
771 /*=*/
772 /***en
773     @name Obsolete functions
774 */
775 /***ja
776     @name Obsolete ¤Ê´Ø¿ô
777 */
778 /*** @{ */
779
780 /***en
781     @brief Get an English language name.
782
783     This function is obsolete.  Use mlanguage_name_list () instead.
784
785     The mlanguage_name () function returns a symbol whose name is an
786     English name of $LANGUAGE.  $LANGUAGE is a symbol whose name is an
787     ISO639-2 3-letter language code, an ISO639-1 2-letter language
788     codes, or an English word.
789
790     @return
791     If the information is available, this function returns a non-#Mnil
792     symbol.  Otherwise, it returns #Mnil.
793
794     @seealso
795     mlanguage_code (), mlanguage_text ().  */
796
797 /***ja
798     @brief ¸À¸ì¤Î±Ñ¸ì̾¤òÆÀ¤ë.
799
800     ´Ø¿ô mlanguage_name () ¤Ï¡¢$LANGUAGE ¤Î±Ñ¸ì̾¤ò̾Á°¤È¤¹¤ë¤è¤¦¤Ê¥·
801     ¥ó¥Ü¥ë¤òÊÖ¤¹¡£$LANGUAGE ¤Ï¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¤½¤Î̾Á°¤Ï¡¢ISO639-2 3ʸ
802     »ú¸À¸ì¥³¡¼¥É¡¢ISO639-1 2ʸ»ú¸À¸ì¥³¡¼¥É¡¢±Ñ¸ì̾¡¢¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
803
804     @return
805     µá¤á¤Æ¤¤¤ë¾ðÊó¤¬ÆÀ¤é¤ì¤ë¤Ê¤é¡¢¤³¤Î´Ø¿ô¤Ï #Mnil °Ê³°¤Î¥·¥ó¥Ü¥ë¤òÊÖ
806     ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð #Mnil ¤òÊÖ¤¹¡£
807
808     @seealso
809     mlanguage_code (), mlanguage_text ().  */
810
811 MSymbol
812 mlanguage_name (MSymbol language)
813 {
814   MPlist *plist = mlanguage__info (language);
815   MText *mt;
816   char *str;
817
818   if (! plist)                  /* 3-letter code */
819     return Mnil;
820   plist = MPLIST_NEXT (plist);  /* 2-letter code */
821   if (MPLIST_TAIL_P (plist))
822     return Mnil;
823   plist = MPLIST_NEXT (plist);  /* english name */
824   if (! MPLIST_MTEXT_P (plist))
825     return Mnil;
826   mt = MPLIST_MTEXT (plist);
827   str = alloca (mtext_nbytes (mt));
828   memcpy (str, MTEXT_DATA (mt), mtext_nbytes (mt));
829   str[0] = tolower (str[0]);
830   return msymbol__with_len (str, mtext_nbytes (mt));
831 }
832
833 /*=*/
834
835 /*
836   Local Variables:
837   coding: euc-japan
838   End:
839 */