(ft_open, ft_encapsulate): Set rfont->id.
[m17n/m17n-lib.git] / src / language.c
1 /* language.c -- language (and script) module.
2    Copyright (C) 2003, 2004, 2006
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_SYMBOL_P (p)
321           && otf_tag == MPLIST_SYMBOL (p))
322         {
323           script = MPLIST_SYMBOL (pl);
324           break;
325         }
326     }
327   return script;
328 }
329
330 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
331 \f
332
333 /* External API */
334
335 MSymbol Miso639_1, Miso639_2;
336
337 /*=*/
338
339 /***en
340     @brief List 3-letter language codes.
341
342     The mlanguage_list () funciton returns a well-formed plist whose
343     keys are #Msymbol and values are symbols whose names are ISO639-2
344     3-letter language codes.
345
346     @return
347     This function returns a plist.  The caller should free it by
348     m17n_object_unref ().
349
350     @seealso
351     mscript_list ().  */
352
353 /***ja
354     @brief 3ʸ»ú¸À¸ì¥³¡¼¥É¤ò¥ê¥¹¥È¤¹¤ë.
355
356     ´Ø¿ô mlanguage_list () ¤Ï¡¢À°·Á¼° (well-formed) plist ¤òÊÖ¤¹¡£³Æ¥­¡¼
357     ¤Ï #Msymbol ¤Ç¤¢¤ê¡¢¸Ä¡¹¤ÎÃͤϠISO639-2 ¤ËÄê¤á¤é¤ì¤¿3ʸ»ú¸À¸ì¥³¡¼
358     ¥É¤ò̾Á°¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
359
360     @return
361     ¤³¤Î´Ø¿ô¤¬ÊÖ¤¹ plist ¤Ï¡¢¸Æ¤Ó½Ð¤·Â¦¤¬ m17n_object_unref () ¤ò»È¤Ã
362     ¤Æ²òÊü¤¹¤ëɬÍפ¬¤¢¤ë¡£
363
364     @seealso
365     mscript_list ().  */
366
367 MPlist *
368 mlanguage_list (void)
369 {
370   MPlist *plist, *pl, *p, *p0;
371
372   if (! language_list
373       && init_language_list () < 0)
374     return NULL;
375   plist = pl = mplist ();
376   MPLIST_DO (p, language_list)
377     {
378       p0 = MPLIST_PLIST (p);
379       pl = mplist_add (pl, Msymbol, MPLIST_VAL (p0));
380     }
381   return plist;
382 }
383
384 /*=*/
385
386 /***en
387     @brief Get a language code.
388
389     The mlanguage_code () function returns a symbol whose name is the
390     ISO639 language code of $LANGUAGE. $LANGUAGE is a symbol whose
391     name is an ISO639-2 3-letter language code, an ISO639-1 2-letter
392     language codes, or an English word.
393
394     $LEN specifies the type of the returned language code.  If it is
395     3, an ISO639-2 3-letter language code is returned.  If it is 2, an
396     ISO639-1 2-letter language code is returned when defined;
397     otherwise #Mnil is returned.  If it is 0, a 2-letter code is
398     returned when defined; otherwise a 3-letter code is returned.
399
400     @return
401     If the information is available, this function returns a non-#Mnil
402     symbol.  Otherwise, it returns #Mnil.
403
404     @seealso
405     mlanguage_name_list (), mlanguage_text ().  */
406
407 /***ja
408     @brief ¸À¸ì¥³¡¼¥É¤òÆÀ¤ë.
409
410     ´Ø¿ô mlanguage_code () ¤Ï¡¢$LANGUAGE ¤ËÂбþ¤·¤¿ ISO-639 ¸À¸ì¥³¡¼¥É
411     ¤¬Ì¾Á°¤Ç¤¢¤ë¤è¤¦¤Ê¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£$LANGUAGE ¤Ï¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¤½¤Î
412     Ì¾Á°¤Ï¡¢ISO639-2 3ʸ»ú¸À¸ì¥³¡¼¥É¡¢ISO639-1 2ʸ»ú¸À¸ì¥³¡¼¥É¡¢±Ñ¸ì̾¡¢
413     ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
414
415     $LEN ¤ÏÊÖ¤µ¤ì¤ë¸À¸ì¥³¡¼¥É¤Î¼ïÎà¤ò·èÄꤹ¤ë¡£$LEN ¤¬3¤Î¾ì¹ç¤Ï 
416     ISO639-2 3ʸ»ú¸À¸ì¥³¡¼¥É¤¬ÊÖ¤µ¤ì¤ë¡£2¤Î¾ì¹ç¤Ï¡¢¤â¤·ÄêµÁ¤µ¤ì¤Æ¤¤¤ì
417     ¤Ð ISO639-1 2ʸ»ú¸À¸ì¥³¡¼¥É¤¬¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð #Mnil ¤¬ÊÖ¤µ¤ì¤ë¡£0 
418     ¤Î¾ì¹ç¤Ï¡¢¤â¤·ÄêµÁ¤µ¤ì¤Æ¤¤¤ì¤Ð2ʸ»ú¥³¡¼¥É¤¬¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð3ʸ»ú¥³¡¼
419     ¥É¤¬ÊÖ¤µ¤ì¤ë¡£
420
421     @return
422     ¤â¤·¾ðÊó¤¬ÆÀ¤é¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï #Mnil °Ê³°¤Î¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£¤½¤¦
423     ¤Ç¤Ê¤±¤ì¤Ð #Mnil ¤òÊÖ¤¹¡£
424
425     @seealso
426     mlanguage_name (), mlanguage_text ().  */
427
428 MSymbol
429 mlanguage_code (MSymbol language, int len)
430 {
431   MPlist *plist = mlanguage__info (language);
432   MSymbol code;
433
434   if (! plist)
435     return Mnil;
436   if (! MPLIST_SYMBOL_P (plist))
437     return Mnil;
438   code = MPLIST_SYMBOL (plist);
439   if (len == 3)
440     return code;
441   plist = MPLIST_NEXT (plist);
442   return ((MPLIST_SYMBOL_P (plist) && MPLIST_SYMBOL (plist) != Mnil)
443           ? MPLIST_SYMBOL (plist)
444           : len == 0 ? code : Mnil);
445 }
446
447 /*=*/
448
449 /***en
450     @brief Return the language names written in the specified language.
451
452     The mlanguage_name_list () function returns a plist of LANGUAGE's
453     names written in TARGET language.  SCRIPT and TERRITORY, if not #Mnil,
454     specifies which script and territory to concern at first.
455
456     LANGUAGE and TARGET must be a symbol whose name is an ISO639-2
457     3-letter language code or an ISO639-1 2-letter language codes.
458     TARGET may be #Mnil, in which case, the language of the current
459     locale is used.  If locale is not set or is C, English is used.
460
461     SCRIPT and TERRITORY must be a symbol whose name is a script and
462     territory name of a locale (e.g. "TW", "SG") respectively.
463
464     @return
465     If the translation is available, this function returns a non-empty
466     plist.  The first element has key #MText and the value is an
467     M-text of a translated language name.  If the succeeding elements
468     also have key #MText, their values are M-texts of alternate
469     translations.
470
471     If no translation is available, @c NULL is returned.
472
473     The returned plist should not be modified nor freed.
474
475     @seealso
476     mlanguage_code (), mlanguage_text ().  */
477
478 MPlist *
479 mlanguage_name_list (MSymbol language, MSymbol target,
480                      MSymbol script, MSymbol territory)
481 {
482   MPlist *plist, *pl;
483   MSymbol language2, target2;
484
485   plist = mlanguage__info (language);
486   if (! plist)
487     return NULL;
488   language = MPLIST_SYMBOL (plist);
489   language2 = MPLIST_SYMBOL (MPLIST_NEXT (plist));
490   if (target != Mnil)
491     {
492       plist = mlanguage__info (target);
493       if (! plist)
494         return NULL;
495       target = MPLIST_SYMBOL (plist);
496       target2 = MPLIST_SYMBOL (MPLIST_NEXT (plist));
497     }
498   else
499     {
500       MLocale *locale = mlocale_set (LC_MESSAGES, NULL);
501
502       if (! locale)
503         {
504           target = msymbol ("eng");
505           target2 = msymbol ("en");
506           script = territory = Mnil;
507         }
508       else
509         {
510           target = mlocale_get_prop (locale, Mlanguage);
511           plist = mlanguage__info (target);
512           if (! plist)
513             return NULL;
514           target = MPLIST_SYMBOL (plist);
515           target2 = MPLIST_SYMBOL (MPLIST_NEXT (plist));
516           script = mlocale_get_prop (locale, Mscript);
517           territory = mlocale_get_prop (locale, Mterritory);
518         }
519     }
520
521   /* Now both LANGUAGE and TARGET are 3-letter codes.  */
522   if (! langname_list)
523     langname_list = mplist ();
524   plist = mplist__assq (langname_list, target);
525   if (plist)
526     plist = MPLIST_PLIST (plist);
527   else
528     plist = load_lang_name (target, target2);
529
530   /* PLIST = (TARGET (SCRIPT (TERRITORY ...) (LANG-CODE NAME ...) ...) ...) */
531   plist = MPLIST_NEXT (plist);
532   if (MPLIST_TAIL_P (plist))
533     return NULL;
534
535   MPLIST_DO (pl, plist)
536     {
537       MPlist *p = MPLIST_PLIST (pl), *p0;
538
539       if (MPLIST_SYMBOL (p) == script
540           && (territory == Mnil
541               || mplist_find_by_value (MPLIST_PLIST (MPLIST_NEXT (p)),
542                                        territory))
543           && (p = MPLIST_NEXT (MPLIST_NEXT (p)))
544           && ((p0 = mplist__assq (p, language))
545               || (p0 = mplist__assq (p, language2))))
546         {
547           plist = p0;
548           break;
549         }
550     }
551   if (MPLIST_TAIL_P (pl))
552     {
553       MPLIST_DO (pl, plist)
554         {
555           MPlist *p = MPLIST_NEXT (MPLIST_PLIST (pl)), *p0;
556
557           if ((territory == Mnil
558                || mplist_find_by_value (MPLIST_VAL (p), territory))
559               && (p = MPLIST_NEXT (MPLIST_NEXT (p)))
560               && ((p0 = mplist__assq (p, language))
561                   || (p0 = mplist__assq (p, language2))))
562             {
563               plist = p0;
564               break;
565             }
566         }
567       if (MPLIST_TAIL_P (pl))
568         {
569           MPLIST_DO (pl, plist)
570             {
571               MPlist *p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (pl))), *p0;
572
573               if ((p0 = mplist__assq (p, language))
574                   || (p0 = mplist__assq (p, language2)))
575                 {
576                   plist = p0;
577                   break;
578                 }
579             }
580           if (MPLIST_TAIL_P (pl))
581             return NULL;
582         }
583     }
584
585   plist = MPLIST_NEXT (MPLIST_PLIST (plist));
586   if (territory != Mnil)
587     {
588       MPLIST_DO (pl, MPLIST_NEXT (plist))
589         if (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == territory)
590           break;
591       if (! MPLIST_TAIL_P (pl)
592           && (pl = MPLIST_NEXT (pl))
593           && MPLIST_MTEXT_P (pl))
594         return pl;
595     }
596   MPLIST_DO (plist, plist)
597     if (MPLIST_MTEXT_P (plist))
598       break;
599   return (MPLIST_MTEXT_P (plist) ? plist : NULL);
600 }
601
602 /*=*/
603
604 /***en
605     @brief Return the language name written in that language.
606
607     The mlanguage_text () function returns, in the form of M-text, the
608     language name of $LANGUAGE written in $LANGUAGE.  If the
609     representative characters of the language are known, the
610     characters of the returned M-text has a text property whose key is
611     #Mtext and whose value is an M-text that contains the
612     representative characters.
613
614     @return
615     If the information is available, this function returns an M-text
616     that should not be modified nor freed.  Otherwise, it returns @c
617     NULL.
618
619     @seealso
620     mlanguage_code (), mlanguage_name ().  */
621
622 /***ja
623     @brief Í¿¤¨¤é¤ì¤¿¸À¸ì¼«¿È¤Ç½ñ¤«¤ì¤¿¸À¸ì̾¤òÊÖ¤¹.
624
625     ´Ø¿ô mlanguage_text () ¤Ï¡¢¸À¸ì $LANGUAGE ¤Ç½ñ¤«¤ì¤¿ $LANGUAGE ¤Î
626     Ì¾Á°¤ò M-text ¤Î·Á¼°¤ÇÊÖ¤¹¡£¤½¤Î¸À¸ì¤ÎÂåɽŪ¤Êʸ»ú¤¬¤ï¤«¤Ã¤Æ¤¤¤ë¾ì
627     ¹ç¤Ï¡¢ÊÖ¤µ¤ì¤ë M-text ¤Î³Æʸ»ú¤Ë¡¢¥­¡¼¤¬ #Mtext ¤ÇÃͤ¬¤½¤ÎÂåɽŪ¤Ê
628     Ê¸»ú¤ò´Þ¤à M-text ¤Ç¤¢¤ë¤è¤¦¤Ê¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬Éղ䵤ì¤ë¡£
629
630     @return
631     µá¤á¤ë¾ðÊó¤¬ÆÀ¤é¤ì¤¿¾ì¹ç¡¢¤³¤Î´Ø¿ô¤¬ÊÖ¤¹ M-text ¤òÊѹ¹¤·¤¿¤ê²òÊü¤·
632     ¤¿¤ê¤·¤Æ¤Ï¤¤¤±¤Ê¤¤¡£¾ðÊó¤¬ÆÀ¤é¤ì¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï @c NULL ¤¬ÊÖ¤µ¤ì¤ë¡£
633
634     @seealso
635     mlanguage_code (), mlanguage_name ().  */
636
637 MText *
638 mlanguage_text (MSymbol language)
639 {
640   MPlist *plist = mlanguage__info (language);
641   MText *mt;
642
643   if (! plist)
644     return NULL;
645   plist = MPLIST_NEXT (plist);
646   if (MPLIST_TAIL_P (plist))
647     return NULL;
648   plist = MPLIST_NEXT (plist);
649   if (MPLIST_TAIL_P (plist))
650     return NULL;
651   plist = MPLIST_NEXT (plist);            
652   if (! MPLIST_MTEXT_P (plist))
653     return NULL;
654   mt = MPLIST_MTEXT (plist);
655   if (mtext_nchars (mt) == 0)
656     return NULL;
657   plist = MPLIST_NEXT (plist);
658   if (MPLIST_MTEXT_P (plist)
659       && ! mtext_get_prop (mt, 0, Mtext))
660     mtext_put_prop (mt, 0, mtext_nchars (mt), Mtext, MPLIST_MTEXT (plist));
661   return mt;
662 }
663
664 /***en
665     @brief List script names.
666
667     The mscript_list () funciton returns a well-formed plist whose
668     keys are #Msymbol and values are symbols whose names are script
669     names.
670
671     @return
672     This function returns a plist.  The caller should free it by
673     m17n_object_unref ().
674
675     @seealso
676     mscript_language_list (), mlanguage_list ().  */
677
678 /***ja
679     @brief ¥¹¥¯¥ê¥×¥È̾¤ò¥ê¥¹¥È¤¹¤ë.
680
681     ´Ø¿ô mscript_list () ¤Ï¡¢À°·Á¼° (well-formed) plist ¤òÊÖ¤¹¡£³Æ¥­¡¼
682     ¤Ï #Msymbol ¤Ç¤¢¤ê¡¢¸Ä¡¹¤ÎÃͤϥ¹¥¯¥ê¥×¥È̾¤ò̾Á°¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢
683     ¤ë¡£
684
685     @return
686     ¤³¤Î´Ø¿ô¤¬ÊÖ¤¹ plist ¤Ï¡¢¸Æ¤Ó½Ð¤·Â¦¤¬ m17n_object_unref () ¤ò»È¤Ã
687     ¤Æ²òÊü¤¹¤ëɬÍפ¬¤¢¤ë¡£
688
689     @seealso
690     mscript_language_list (), mlanguage_list ().  */
691
692 MPlist *
693 mscript_list (void)
694 {
695   MPlist *plist, *pl, *p, *p0;
696
697   if (! script_list
698       && init_script_list () < 0)
699     return NULL;
700   plist = pl = mplist ();
701   MPLIST_DO (p, script_list)
702     {
703       p0 = MPLIST_PLIST (p);
704       pl = mplist_add (pl, Msymbol, MPLIST_VAL (p0));
705     }
706   return plist;
707 }
708
709 /*=*/
710
711 /***en
712     @brief List languages that use a specified script.
713
714     The mscript_language_list () function lists languages that use
715     $SCRIPT.  $SCRIPT is a symbol whose name is the lower-cased
716     version of a script name that appears in the Unicode Character
717     Database.
718
719     @return
720
721     This function returns a well-formed plist whose keys are #Msymbol
722     and values are symbols whose names are ISO639-1 2-letter codes (or
723     ISO639-2 3-letter codes, if the former is not available).  The
724     caller should not modify nor free it.  If the m17n library does
725     not know about $SCRIPT, it returns @ c NULL.
726
727     @seealso
728     mscript_list (), mlanguage_list ().  */
729
730 /***ja
731     @brief Í¿¤¨¤é¤ì¤¿¥¹¥¯¥ê¥×¥È¤òÍѤ¤¤ë¸À¸ì¤ò¥ê¥¹¥È¤¹¤ë.
732
733     ´Ø¿ô mscript_language_list () ¤Ï¡¢$SCRIPT ¤òÍѤ¤¤ë¸À¸ì¤ò¥ê¥¹¥È¤¹¤ë¡£
734     $SCRIPT ¤Ï¥·¥ó¥Ü¥ë¤Ç¡¢¤½¤Î̾Á°¤Ï Unicode Character Database ¤Ë¼¨¤µ
735     ¤ì¤Æ¤¤¤ë¥¹¥¯¥ê¥×¥È̾¤ò¤¹¤Ù¤Æ¾®Ê¸»ú¤Ë¤·¤¿¤â¤Î¤Ç¤¢¤ë¡£
736
737     @return 
738     ¤³¤Î´Ø¿ô¤Ï¡¢À°·Á¼° (well-formed) plist ¤òÊÖ¤¹¡£³Æ¥­¡¼¤Ï 
739     #Msymbol ¤Ç¤¢¤ê¡¢¸Ä¡¹¤ÎÃͤϠISO639-1 ¤ËÄê¤á¤é¤ì¤¿2ʸ»ú¸À¸ì¥³¡¼¥É
740     (ÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ï ISO639-2 ¤ËÄê¤á¤é¤ì¤¿3ʸ»ú¸À¸ì¥³¡¼¥É) ¤ò̾
741     Á°¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£ÊÖ¤µ¤ì¤ë plist ¤ÏÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ
742     ¤Ï¤Ê¤é¤Ê¤¤¡£$SCRIPT ¤¬Ì¤ÃΤξì¹ç¤Ï @c NULL ¤¬ÊÖ¤µ¤ì¤ë¡£
743
744     @seealso
745     mscript_list (), mlanguage_list ().  */
746     
747
748 MPlist *
749 mscript_language_list (MSymbol script)
750 {
751   MPlist *plist = mscript__info (script);
752
753   if (plist                     /* script name */
754       && (plist = MPLIST_NEXT (plist)) /* language list */
755       && MPLIST_PLIST_P (plist))
756     return MPLIST_PLIST (plist);
757   return NULL;
758 }
759
760 /*** @} */
761 /*=*/
762 /***en
763     @name Obsolete functions
764 */
765 /***ja
766     @name Obsolete ¤Ê´Ø¿ô
767 */
768 /*** @{ */
769
770 /***en
771     @brief Get an English language name.
772
773     This function is obsolete.  Use mlanguage_name_list () instead.
774
775     The mlanguage_name () function returns a symbol whose name is an
776     English name of $LANGUAGE.  $LANGUAGE is a symbol whose name is an
777     ISO639-2 3-letter language code, an ISO639-1 2-letter language
778     codes, or an English word.
779
780     @return
781     If the information is available, this function returns a non-#Mnil
782     symbol.  Otherwise, it returns #Mnil.
783
784     @seealso
785     mlanguage_code (), mlanguage_text ().  */
786
787 /***ja
788     @brief ¸À¸ì¤Î±Ñ¸ì̾¤òÆÀ¤ë.
789
790     ´Ø¿ô mlanguage_name () ¤Ï¡¢$LANGUAGE ¤Î±Ñ¸ì̾¤ò̾Á°¤È¤¹¤ë¤è¤¦¤Ê¥·
791     ¥ó¥Ü¥ë¤òÊÖ¤¹¡£$LANGUAGE ¤Ï¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¤½¤Î̾Á°¤Ï¡¢ISO639-2 3ʸ
792     »ú¸À¸ì¥³¡¼¥É¡¢ISO639-1 2ʸ»ú¸À¸ì¥³¡¼¥É¡¢±Ñ¸ì̾¡¢¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
793
794     @return
795     µá¤á¤Æ¤¤¤ë¾ðÊó¤¬ÆÀ¤é¤ì¤ë¤Ê¤é¡¢¤³¤Î´Ø¿ô¤Ï #Mnil °Ê³°¤Î¥·¥ó¥Ü¥ë¤òÊÖ
796     ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð #Mnil ¤òÊÖ¤¹¡£
797
798     @seealso
799     mlanguage_code (), mlanguage_text ().  */
800
801 MSymbol
802 mlanguage_name (MSymbol language)
803 {
804   MPlist *plist = mlanguage__info (language);
805   MText *mt;
806   char *str;
807
808   if (! plist)                  /* 3-letter code */
809     return Mnil;
810   plist = MPLIST_NEXT (plist);  /* 2-letter code */
811   if (MPLIST_TAIL_P (plist))
812     return Mnil;
813   plist = MPLIST_NEXT (plist);  /* english name */
814   if (! MPLIST_MTEXT_P (plist))
815     return Mnil;
816   mt = MPLIST_MTEXT (plist);
817   str = alloca (mtext_nbytes (mt));
818   memcpy (str, MTEXT_DATA (mt), mtext_nbytes (mt));
819   str[0] = tolower (str[0]);
820   return msymbol__with_len (str, mtext_nbytes (mt));
821 }
822
823 /*=*/
824
825 /*
826   Local Variables:
827   coding: euc-japan
828   End:
829 */