*** empty log message ***
[m17n/m17n-lib.git] / src / language.c
index 0646a61..359d0bd 100644 (file)
@@ -1,5 +1,5 @@
-/* language.c -- language module.
-   Copyright (C) 2003, 2004
+/* language.c -- language (and script) module.
+   Copyright (C) 2003, 2004, 2006
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H15PRO112
 
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H15PRO112
 
 
    You should have received a copy of the GNU Lesser General Public
    License along with the m17n library; if not, write to the Free
 
    You should have received a copy of the GNU Lesser General Public
    License along with the m17n library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    02111-1307, USA.  */
 
 #include <config.h>
 #include <stdlib.h>
    02111-1307, USA.  */
 
 #include <config.h>
 #include <stdlib.h>
+#include <string.h>
+#include <locale.h>
 #include "m17n.h"
 #include "m17n-misc.h"
 #include "internal.h"
 #include "language.h"
 #include "symbol.h"
 #include "plist.h"
 #include "m17n.h"
 #include "m17n-misc.h"
 #include "internal.h"
 #include "language.h"
 #include "symbol.h"
 #include "plist.h"
+#include "mtext.h"
 
 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
 
 
 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
 
-static MSymbol M_script_lang_list;
+static MPlist *language_list;
+static MPlist *script_list;
+static MPlist *langname_list;
+
+static MPlist *
+load_lang_script_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3)
+{
+  MDatabase *mdb = mdatabase_find (tag0, tag1, tag2, tag3);
+  MPlist *plist, *pl, *p;
+
+  if (! mdb
+      || ! (plist = mdatabase_load (mdb)))
+    return NULL;
+  /* Check at least if the plist is ((SYMBOL ...) ...).  */
+  for (pl = plist; ! MPLIST_TAIL_P (pl);)
+    {
+      if (! MPLIST_PLIST_P (pl))
+       mplist__pop_unref (pl);
+      else
+       {
+         p = MPLIST_PLIST (pl);
+         if (! MPLIST_SYMBOL_P (p))
+           mplist__pop_unref (pl);
+         else
+           pl = MPLIST_NEXT (pl);
+       }
+    }
+  return plist;
+}
+
+static int
+init_language_list (void)
+{
+  language_list = load_lang_script_list (msymbol ("standard"), Mlanguage,
+                                        msymbol ("iso639"), Mnil);
+  if (! language_list)
+    {
+      language_list = mplist ();
+      MERROR (MERROR_DB, -1);
+    }
+  return 0;
+}
+
+
+static int
+init_script_list (void)
+{
+  script_list = load_lang_script_list (msymbol ("standard"), Mscript,
+                                      msymbol ("unicode"), Mnil);
+  if (! script_list)
+    {
+      script_list = mplist ();
+      MERROR (MERROR_DB, -1);
+    }
+  return 0;
+}
 
 \f
 /* Internal API */
 
 \f
 /* Internal API */
@@ -39,165 +97,611 @@ static MSymbol M_script_lang_list;
 int
 mlang__init ()
 {
 int
 mlang__init ()
 {
-  MDatabase *mdb;
-  MPlist *plist, *pl;
-
-  Mlanguage = msymbol ("language");
-  msymbol_put (Mlanguage, Mtext_prop_serializer,
-              (void *) msymbol__serializer);
-  msymbol_put (Mlanguage, Mtext_prop_deserializer,
-              (void *) msymbol__deserializer);
+  msymbol_put_func (Mlanguage, Mtext_prop_serializer,
+                   M17N_FUNC (msymbol__serializer));
+  msymbol_put_func (Mlanguage, Mtext_prop_deserializer,
+                   M17N_FUNC (msymbol__deserializer));
   Miso639_2 = msymbol ("iso639-2");
   Miso639_1 = msymbol ("iso639-1");
   Miso639_2 = msymbol ("iso639-2");
   Miso639_1 = msymbol ("iso639-1");
-  M_script_lang_list = msymbol_as_managing_key ("  script-lang-list");
 
 
-  mdb = mdatabase_find (msymbol ("standard"), Mlanguage,
-                       msymbol ("iso639"), Mnil);
-  if (! mdb)
-    return 0;
-  if (! (plist = mdatabase_load (mdb)))
-    MERROR (MERROR_DB, -1);
+  language_list = script_list = langname_list = NULL;
+  return 0;
+}
+
+void
+mlang__fini (void)
+{
+  MPlist *pl;
+
+  M17N_OBJECT_UNREF (language_list);
+  M17N_OBJECT_UNREF (script_list);
+  if (langname_list)
+    MPLIST_DO (pl, langname_list)
+      M17N_OBJECT_UNREF (MPLIST_VAL (pl));
+  M17N_OBJECT_UNREF (langname_list);
+}
+
+/*=*/
+
+/***en
+    @brief Get information about a language.
+
+    The mlanguage_info () function returns a well-formed @e plist that
+    contains information about $LANGUAGE.  $LANGUAGE is a symbol whose
+    name is an ISO639-2 3-letter language code, an ISO639-1 2-letter
+    language codes, or an English word.
 
 
-  MPLIST_DO (pl, plist)
+    The format of the plist is:
+
+@verbatim
+        (ISO639-2 [ISO639-1 | nil] ENGLISH-NAME ["NATIVE-NAME" | nil]
+                  ["REPRESENTATIVE-CHARACTERS"])
+@endverbatim
+
+    where, ISO639-2 is a symbol whose name is 3-letter language code
+    of ISO639-2, ISO639-1 is a symbol whose name is 2-letter language
+    code of ISO639-1, ENGLISH-NAME is a symbol whose name is the
+    English name of the language, "NATIVE-NAME" is an M-text written
+    by the most natural way in the language,
+    "REPRESENTATIVE-CHARACTERS" is an M-text that contains
+    representative characters used by the language.
+
+    It is assured that the formats of both M-texts are
+    #MTEXT_FORMAT_UTF_8.
+
+    @return
+    If the information is available, this function returns a plist
+    that should not be modified nor freed.  Otherwise, it returns
+    @c NULL.
+
+    @seealso
+    mlanguage_list ()  */
+
+MPlist *
+mlanguage__info (MSymbol language)
+{
+  MPlist *plist;
+
+  if (! language_list
+      && init_language_list () < 0)
+    return NULL;
+
+  MPLIST_DO (plist, language_list)
     {
     {
-      MPlist *p;
-      MSymbol code3, code2, lang;
-      MText *native, *extra;
+      MPlist *pl = MPLIST_PLIST (plist);
 
 
-      if (! MPLIST_PLIST_P (pl))
-       continue;
-      p = MPLIST_PLIST (pl);
-      if (! MPLIST_SYMBOL_P (p))
+      if (MPLIST_SYMBOL (pl) == language)
+       return pl;
+      if (MPLIST_TAIL_P (pl))
        continue;
        continue;
-      code3 = MPLIST_SYMBOL (p);
-      p = MPLIST_NEXT (p);
-      if (! MPLIST_SYMBOL_P (p))
+      pl = MPLIST_NEXT (pl);
+      if (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == language)
+       return MPLIST_PLIST (plist);
+      if (MPLIST_TAIL_P (pl))
        continue;
        continue;
-      code2 = MPLIST_SYMBOL (p);
-      p = MPLIST_NEXT (p);
-      if (! MPLIST_SYMBOL_P (p))
-       continue;
-      lang = MPLIST_SYMBOL (p);
-      msymbol_put (code3, Mlanguage, lang);
-      p = MPLIST_NEXT (p);      
-      native = MPLIST_MTEXT_P (p) ? MPLIST_MTEXT (p) : NULL;
-      if (native)
+      pl = MPLIST_NEXT (pl);
+      if (MPLIST_MTEXT_P (pl))
        {
        {
-         msymbol_put (code3, Mtext, native);
-         p = MPLIST_NEXT (p);
-         extra = MPLIST_MTEXT_P (p) ? MPLIST_MTEXT (p) : NULL;
-         if (extra)
-           mtext_put_prop (native, 0, mtext_nchars (native), Mtext, extra);
+         MText *mt = MPLIST_MTEXT (pl);
+
+         if (mtext_nbytes (mt) == MSYMBOL_NAMELEN (language)
+             && memcmp (MTEXT_DATA (MPLIST_MTEXT (pl)),
+                        MSYMBOL_NAME (language),
+                        MSYMBOL_NAMELEN (language)) == 0)
+           return MPLIST_PLIST (plist);
        }
        }
-      if (code2 != Mnil)
+    }
+  return NULL;
+}
+
+static MPlist *
+mscript__info (MSymbol script)
+{
+  MPlist *plist;
+
+  if (! script_list
+      && init_script_list () < 0)
+    return NULL;
+  MPLIST_DO (plist, script_list)
+    {
+      MPlist *pl = MPLIST_PLIST (plist);
+
+      if (MPLIST_SYMBOL (pl) == script)
+       return pl;
+    }
+  return NULL;
+}
+
+MPlist *
+mscript__char_list (MSymbol name)
+{
+  MPlist *plist = mscript__info (name);
+
+  if (plist                    /* script name */
+      && (plist = MPLIST_NEXT (plist)) /* language list */
+      && ! MPLIST_TAIL_P (plist)
+      && (plist = MPLIST_NEXT (plist)) /* char list */
+      && MPLIST_PLIST_P (plist))
+    return MPLIST_PLIST (plist);
+  return NULL;
+}
+
+MSymbol
+mscript__otf_tag (MSymbol script)
+{
+  MPlist *plist = mscript__info (script);
+
+  if (plist                    /* script name */
+      && (plist = MPLIST_NEXT (plist)) /* language list */
+      && ! MPLIST_TAIL_P (plist)
+      && (plist = MPLIST_NEXT (plist)) /* char list */
+      && ! MPLIST_TAIL_P (plist)
+      && (plist = MPLIST_NEXT (plist)) /* otf tag */
+      && MPLIST_SYMBOL_P (plist))
+    return MPLIST_SYMBOL (plist);
+  return NULL;
+}
+
+MSymbol
+mscript__from_otf_tag (MSymbol otf_tag)
+{
+  MPlist *plist;
+  /* As it is expected that this function is called in a sequence with
+     the same argument, we use a cache.  */
+  static MSymbol last_otf_tag, script;
+
+  if (! script_list)
+    {
+      last_otf_tag = script = Mnil;
+      if (init_script_list () < 0)
+       return Mnil;
+    }
+  if (otf_tag == last_otf_tag)
+    return script;
+  last_otf_tag = otf_tag;
+  script = Mnil;
+  MPLIST_DO (plist, script_list)
+    {
+      MPlist *pl = MPLIST_PLIST (plist), *p;
+
+      if (pl                          /* script name */
+         && (p = MPLIST_NEXT (pl))    /* language tag */
+         && ! MPLIST_TAIL_P (p)
+         && (p = MPLIST_NEXT (p)) /* char list */
+         && ! MPLIST_TAIL_P (p)
+         && (p = MPLIST_NEXT (p)) /* otf tag */
+         && MPLIST_SYMBOL_P (p)
+         && otf_tag == MPLIST_SYMBOL (p))
        {
        {
-         msymbol_put (code3, Miso639_1, code2);
-         msymbol_put (code2, Mlanguage, lang);
-         msymbol_put (code2, Miso639_2, code3);
-         if (native)
-           msymbol_put (code2, Mtext, native);
+         script = MPLIST_SYMBOL (pl);
+         break;
        }
     }
        }
     }
-  M17N_OBJECT_UNREF (plist);
-  return 0;
+  return script;
 }
 
 }
 
-void
-mlang__fini (void)
+#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
+\f
+
+/* External API */
+
+MSymbol Miso639_1, Miso639_2;
+
+/*=*/
+
+/***en
+    @brief List 3-letter language codes.
+
+    The mlanguage_list () funciton returns a well-formed plist whose
+    keys are #Msymbol and values are symbols whose names are ISO639-2
+    3-letter language codes.
+
+    @return
+    This function returns a plist.  The caller should free it by
+    m17n_object_unref ().
+
+    @seealso
+    mscript_list ().  */
+
+/***ja
+    @brief 3ʸ»ú¸À¸ì¥³¡¼¥É¤ò¥ê¥¹¥È¤¹¤ë.
+
+    ´Ø¿ô mlanguage_list () ¤Ï¡¢À°·Á¼° (well-formed) plist ¤òÊÖ¤¹¡£³Æ¥­¡¼
+    ¤Ï #Msymbol ¤Ç¤¢¤ê¡¢¸Ä¡¹¤ÎÃͤϠISO639-2 ¤ËÄê¤á¤é¤ì¤¿3ʸ»ú¸À¸ì¥³¡¼
+    ¥É¤ò̾Á°¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£
+
+    @return
+    ¤³¤Î´Ø¿ô¤¬ÊÖ¤¹ plist ¤Ï¡¢¸Æ¤Ó½Ð¤·Â¦¤¬ m17n_object_unref () ¤ò»È¤Ã
+    ¤Æ²òÊü¤¹¤ëɬÍפ¬¤¢¤ë¡£
+
+    @seealso
+    mscript_list ().  */
+
+MPlist *
+mlanguage_list (void)
+{
+  MPlist *plist, *pl, *p, *p0;
+
+  if (! language_list
+      && init_language_list () < 0)
+    return NULL;
+  plist = pl = mplist ();
+  MPLIST_DO (p, language_list)
+    {
+      p0 = MPLIST_PLIST (p);
+      pl = mplist_add (pl, Msymbol, MPLIST_VAL (p0));
+    }
+  return plist;
+}
+
+/*=*/
+
+/***en
+    @brief Get a language code.
+
+    The mlanguage_code () function returns a symbol whose name is the
+    ISO639 language code of $LANGUAGE. $LANGUAGE is a symbol whose
+    name is an ISO639-2 3-letter language code, an ISO639-1 2-letter
+    language codes, or an English word.
+
+    $LEN specifies the type of the returned language code.  If it is
+    3, an ISO639-2 3-letter language code is returned.  If it is 2, an
+    ISO639-1 2-letter language code is returned when defined;
+    otherwise #Mnil is returned.  If it is 0, a 2-letter code is
+    returned when defined; otherwise a 3-letter code is returned.
+
+    @return
+    If the information is available, this function returns a non-#Mnil
+    symbol.  Otherwise, it returns #Mnil.
+
+    @seealso
+    mlanguage_name_list (), mlanguage_text ().  */
+
+/***ja
+    @brief ¸À¸ì¥³¡¼¥É¤òÆÀ¤ë.
+
+    ´Ø¿ô mlanguage_code () ¤Ï¡¢$LANGUAGE ¤ËÂбþ¤·¤¿ ISO-639 ¸À¸ì¥³¡¼¥É
+    ¤¬Ì¾Á°¤Ç¤¢¤ë¤è¤¦¤Ê¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£$LANGUAGE ¤Ï¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¤½¤Î
+    Ì¾Á°¤Ï¡¢ISO639-2 3ʸ»ú¸À¸ì¥³¡¼¥É¡¢ISO639-1 2ʸ»ú¸À¸ì¥³¡¼¥É¡¢±Ñ¸ì̾¡¢
+    ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
+
+    $LEN ¤ÏÊÖ¤µ¤ì¤ë¸À¸ì¥³¡¼¥É¤Î¼ïÎà¤ò·èÄꤹ¤ë¡£$LEN ¤¬3¤Î¾ì¹ç¤Ï 
+    ISO639-2 3ʸ»ú¸À¸ì¥³¡¼¥É¤¬ÊÖ¤µ¤ì¤ë¡£2¤Î¾ì¹ç¤Ï¡¢¤â¤·ÄêµÁ¤µ¤ì¤Æ¤¤¤ì
+    ¤Ð ISO639-1 2ʸ»ú¸À¸ì¥³¡¼¥É¤¬¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð #Mnil ¤¬ÊÖ¤µ¤ì¤ë¡£0 
+    ¤Î¾ì¹ç¤Ï¡¢¤â¤·ÄêµÁ¤µ¤ì¤Æ¤¤¤ì¤Ð2ʸ»ú¥³¡¼¥É¤¬¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð3ʸ»ú¥³¡¼
+    ¥É¤¬ÊÖ¤µ¤ì¤ë¡£
+
+    @return
+    ¤â¤·¾ðÊó¤¬ÆÀ¤é¤ì¤ì¤Ð¡¢¤³¤Î´Ø¿ô¤Ï #Mnil °Ê³°¤Î¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£¤½¤¦
+    ¤Ç¤Ê¤±¤ì¤Ð #Mnil ¤òÊÖ¤¹¡£
+
+    @seealso
+    mlanguage_name (), mlanguage_text ().  */
+
+MSymbol
+mlanguage_code (MSymbol language, int len)
 {
 {
+  MPlist *plist = mlanguage__info (language);
+  MSymbol code;
+
+  if (! plist)
+    return Mnil;
+  if (! MPLIST_SYMBOL_P (plist))
+    return Mnil;
+  code = MPLIST_SYMBOL (plist);
+  if (len == 3)
+    return code;
+  plist = MPLIST_NEXT (plist);
+  return ((MPLIST_SYMBOL_P (plist) && MPLIST_SYMBOL (plist) != Mnil)
+         ? MPLIST_SYMBOL (plist)
+         : len == 0 ? code : Mnil);
 }
 
 }
 
+/*=*/
+
+/***en
+    @brief Return the language names written in the specified language.
+
+    The mlanguage_name_list () function returns a plist of LANGUAGE's
+    names written in TARGET language.
+
+    LANGUAGE and TARGET must be a symbol whose name is an ISO639-2
+    3-letter language code or an ISO639-1 2-letter language codes.
+    TARGET may be #Mnil, in which case, the language of the current
+    locale is used.  If locale is not set or is C, English is used.
 
 
-/** Return a plist of languages that use SCRIPT.  If SCRIPT is Mnil,
-    return a plist of all languages.  Each element of the plist has
-    3-letter language code as a key and 2-letter language code as a
-    value.  A caller must unref the returned value when finished.  */
+    @return
+    If the information is available, this function returns a non-empty
+    plist whose keys are #Mtext and values are M-texts of the
+    translated language names.  Otherwise, @c NULL is returned.
+    The returned plist should not be modified nor freed.
+
+    @seealso
+    mlanguage_code (), mlanguage_text ().  */
 
 MPlist *
 
 MPlist *
-mlanguage__list (MSymbol script)
+mlanguage_name_list (MSymbol language, MSymbol target)
 {
 {
-  MDatabase *mdb;
-  MPlist *language_list, *plist, *pl;
+  MPlist *plist;
 
 
-  if (script)
+  plist = mlanguage__info (language);
+  if (! plist)
+    return NULL;
+  language = mplist_value (plist);
+  if (target != Mnil)
     {
     {
-      if ((language_list = msymbol_get (script, M_script_lang_list)))
-       {
-         M17N_OBJECT_REF (language_list);
-         return language_list;
-       }
-      mdb = mdatabase_find (msymbol ("unicode"), Mscript, Mlanguage, Mnil);
-      if (! mdb
-         || ! (plist = mdatabase_load (mdb)))
-       MERROR (MERROR_DB, NULL);
-      MPLIST_DO (pl, plist)
-       {
-         MPlist *p, *lang_list;
-         MSymbol code3, code2;
+      plist = mlanguage__info (target);
+      if (! plist)
+       return NULL;
+      target = mplist_value (plist);
+    }
+  else
+    {
+      MLocale *locale = mlocale_set (LC_MESSAGES, NULL);
 
 
-         if (! MPLIST_PLIST_P (pl))
-           continue;
-         p = MPLIST_PLIST (pl);
-         if (! MPLIST_SYMBOL_P (p))
-           continue;
-         lang_list = mplist ();
-         if (MPLIST_SYMBOL (p) == script)
-           language_list = lang_list;
-         msymbol_put (MPLIST_SYMBOL (p), M_script_lang_list, lang_list);
-         MPLIST_DO (p, MPLIST_NEXT (p))
-           if (MPLIST_SYMBOL_P (p))
-             {
-               code2 = MPLIST_SYMBOL (p);
-               if (MSYMBOL_NAMELEN (code2) == 2)
-                 code3 = msymbol_get (code2, Miso639_2);
-               else
-                 code3 = code2, code2 = Mnil;
-               if (code3 != Mnil)
-                 mplist_push (lang_list, code3, code2);
-             }
-         M17N_OBJECT_UNREF (lang_list);
-       }
-      M17N_OBJECT_UNREF (plist);
-      if (language_list)
-       M17N_OBJECT_REF (language_list);
+      if (! locale)
+       target = msymbol ("eng");
       else
        {
       else
        {
-         language_list = mplist ();
-         msymbol_put (script, M_script_lang_list, language_list);
+         target = mlocale_get_prop (locale, Mlanguage);
+         plist = mlanguage__info (target);
+         if (! plist)
+           return NULL;
+         target = mplist_value (plist);
        }
     }
        }
     }
+  /* Now both LANGUAGE and TARGET are 3-letter codes.  */
+
+  if (langname_list)
+    plist = mplist_get (langname_list, target);
   else
   else
+    langname_list = mplist (), plist = NULL;
+  if (! plist)
     {
     {
-      mdb = mdatabase_find (msymbol ("standard"), Mlanguage,
-                           msymbol ("iso639"), Mnil);
+      MDatabase *mdb = mdatabase_find (Mlanguage, Mname, target, Mnil);
+
       if (! mdb
          || ! (plist = mdatabase_load (mdb)))
       if (! mdb
          || ! (plist = mdatabase_load (mdb)))
-       MERROR (MERROR_DB, NULL);
-      MPLIST_DO (pl, plist)
-       {
-         MPlist *p;
-         MSymbol code3, code2;
+       plist = mplist ();
+      else
+       mplist__pop_unref (plist);
+      langname_list = mplist_push (langname_list, target, plist);
+      MPLIST_SET_NESTED_P (langname_list);
+    }
+  /* PLIST == ((LANGUAGE TRANSLATED) ...) */
+  plist = mplist__assq (plist, language);
+  if (! plist || MPLIST_TAIL_P (plist))
+    return NULL;
+  plist = MPLIST_PLIST (plist);
+  plist = MPLIST_NEXT (plist);
+  return plist;
+}
 
 
-         if (! MPLIST_PLIST_P (pl))
-           continue;
-         p = MPLIST_PLIST (pl);
-         if (! MPLIST_SYMBOL_P (p))
-           continue;
-         code3 = MPLIST_SYMBOL (p);
-         p = MPLIST_NEXT (p);
-         if (! MPLIST_SYMBOL_P (p))
-           continue;
-         code2 = MPLIST_SYMBOL (p);
-         mplist_push (language_list, code3, code2);
-       }
-      M17N_OBJECT_UNREF (plist);
+/*=*/
+
+/***en
+    @brief Return the language name written in that language.
+
+    The mlanguage_text () function returns, in the form of M-text, the
+    language name of $LANGUAGE written in $LANGUAGE.  If the
+    representative characters of the language are known, the
+    characters of the returned M-text has a text property whose key is
+    #Mtext and whose value is an M-text that contains the
+    representative characters.
+
+    @return
+    If the information is available, this function returns an M-text
+    that should not be modified nor freed.  Otherwise, it returns @c
+    NULL.
+
+    @seealso
+    mlanguage_code (), mlanguage_name ().  */
+
+/***ja
+    @brief Í¿¤¨¤é¤ì¤¿¸À¸ì¼«¿È¤Ç½ñ¤«¤ì¤¿¸À¸ì̾¤òÊÖ¤¹.
+
+    ´Ø¿ô mlanguage_text () ¤Ï¡¢¸À¸ì $LANGUAGE ¤Ç½ñ¤«¤ì¤¿ $LANGUAGE ¤Î
+    Ì¾Á°¤ò M-text ¤Î·Á¼°¤ÇÊÖ¤¹¡£¤½¤Î¸À¸ì¤ÎÂåɽŪ¤Êʸ»ú¤¬¤ï¤«¤Ã¤Æ¤¤¤ë¾ì
+    ¹ç¤Ï¡¢ÊÖ¤µ¤ì¤ë M-text ¤Î³Æʸ»ú¤Ë¡¢¥­¡¼¤¬ #Mtext ¤ÇÃͤ¬¤½¤ÎÂåɽŪ¤Ê
+    Ê¸»ú¤ò´Þ¤à M-text ¤Ç¤¢¤ë¤è¤¦¤Ê¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤¬Éղ䵤ì¤ë¡£
+
+    @return
+    µá¤á¤ë¾ðÊó¤¬ÆÀ¤é¤ì¤¿¾ì¹ç¡¢¤³¤Î´Ø¿ô¤¬ÊÖ¤¹ M-text ¤òÊѹ¹¤·¤¿¤ê²òÊü¤·
+    ¤¿¤ê¤·¤Æ¤Ï¤¤¤±¤Ê¤¤¡£¾ðÊó¤¬ÆÀ¤é¤ì¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï @c NULL ¤¬ÊÖ¤µ¤ì¤ë¡£
+
+    @seealso
+    mlanguage_code (), mlanguage_name ().  */
+
+MText *
+mlanguage_text (MSymbol language)
+{
+  MPlist *plist = mlanguage__info (language);
+  MText *mt;
+
+  if (! plist)
+    return NULL;
+  plist = MPLIST_NEXT (plist);
+  if (MPLIST_TAIL_P (plist))
+    return NULL;
+  plist = MPLIST_NEXT (plist);
+  if (MPLIST_TAIL_P (plist))
+    return NULL;
+  plist = MPLIST_NEXT (plist);           
+  if (! MPLIST_MTEXT_P (plist))
+    return NULL;
+  mt = MPLIST_MTEXT (plist);
+  if (mtext_nchars (mt) == 0)
+    return NULL;
+  plist = MPLIST_NEXT (plist);
+  if (MPLIST_MTEXT_P (plist)
+      && ! mtext_get_prop (mt, 0, Mtext))
+    mtext_put_prop (mt, 0, mtext_nchars (mt), Mtext, MPLIST_MTEXT (plist));
+  return mt;
+}
+
+/***en
+    @brief List script names.
+
+    The mscript_list () funciton returns a well-formed plist whose
+    keys are #Msymbol and values are symbols whose names are script
+    names.
+
+    @return
+    This function returns a plist.  The caller should free it by
+    m17n_object_unref ().
+
+    @seealso
+    mscript_language_list (), mlanguage_list ().  */
+
+/***ja
+    @brief ¥¹¥¯¥ê¥×¥È̾¤ò¥ê¥¹¥È¤¹¤ë.
+
+    ´Ø¿ô mscript_list () ¤Ï¡¢À°·Á¼° (well-formed) plist ¤òÊÖ¤¹¡£³Æ¥­¡¼
+    ¤Ï #Msymbol ¤Ç¤¢¤ê¡¢¸Ä¡¹¤ÎÃͤϥ¹¥¯¥ê¥×¥È̾¤ò̾Á°¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢
+    ¤ë¡£
+
+    @return
+    ¤³¤Î´Ø¿ô¤¬ÊÖ¤¹ plist ¤Ï¡¢¸Æ¤Ó½Ð¤·Â¦¤¬ m17n_object_unref () ¤ò»È¤Ã
+    ¤Æ²òÊü¤¹¤ëɬÍפ¬¤¢¤ë¡£
+
+    @seealso
+    mscript_language_list (), mlanguage_list ().  */
+
+MPlist *
+mscript_list (void)
+{
+  MPlist *plist, *pl, *p, *p0;
+
+  if (! script_list
+      && init_script_list () < 0)
+    return NULL;
+  plist = pl = mplist ();
+  MPLIST_DO (p, script_list)
+    {
+      p0 = MPLIST_PLIST (p);
+      pl = mplist_add (pl, Msymbol, MPLIST_VAL (p0));
     }
     }
-  return language_list;
+  return plist;
 }
 
 }
 
-#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
-\f
+/*=*/
 
 
-/* External API */
+/***en
+    @brief List languages that use a specified script.
 
 
-MSymbol Miso639_1, Miso639_2;
+    The mscript_language_list () function lists languages that use
+    $SCRIPT.  $SCRIPT is a symbol whose name is the lower-cased
+    version of a script name that appears in the Unicode Character
+    Database.
+
+    @return
+
+    This function returns a well-formed plist whose keys are #Msymbol
+    and values are symbols whose names are ISO639-1 2-letter codes (or
+    ISO639-2 3-letter codes, if the former is not available).  The
+    caller should not modify nor free it.  If the m17n library does
+    not know about $SCRIPT, it returns @ c NULL.
+
+    @seealso
+    mscript_list (), mlanguage_list ().  */
+
+/***ja
+    @brief Í¿¤¨¤é¤ì¤¿¥¹¥¯¥ê¥×¥È¤òÍѤ¤¤ë¸À¸ì¤ò¥ê¥¹¥È¤¹¤ë.
+
+    ´Ø¿ô mscript_language_list () ¤Ï¡¢$SCRIPT ¤òÍѤ¤¤ë¸À¸ì¤ò¥ê¥¹¥È¤¹¤ë¡£
+    $SCRIPT ¤Ï¥·¥ó¥Ü¥ë¤Ç¡¢¤½¤Î̾Á°¤Ï Unicode Character Database ¤Ë¼¨¤µ
+    ¤ì¤Æ¤¤¤ë¥¹¥¯¥ê¥×¥È̾¤ò¤¹¤Ù¤Æ¾®Ê¸»ú¤Ë¤·¤¿¤â¤Î¤Ç¤¢¤ë¡£
+
+    @return ¤³¤Î´Ø¿ô¤Ï¡¢À°·Á¼° (well-formed) plist ¤òÊÖ¤¹¡£³Æ¥­¡¼¤Ï 
+    #Msymbol ¤Ç¤¢¤ê¡¢¸Ä¡¹¤ÎÃͤϠISO639-1 ¤ËÄê¤á¤é¤ì¤¿2ʸ»ú¸À¸ì¥³¡¼¥É
+    (ÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤Ï ISO639-2 ¤ËÄê¤á¤é¤ì¤¿3ʸ»ú¸À¸ì¥³¡¼¥É) ¤ò̾
+    Á°¤È¤¹¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£ÊÖ¤µ¤ì¤ë plist ¤ÏÊѹ¹¤·¤¿¤ê²òÊü¤·¤¿¤ê¤·¤Æ
+    ¤Ï¤Ê¤é¤Ê¤¤¡£$SCRIPT ¤¬Ì¤ÃΤξì¹ç¤Ï @c NULL ¤¬ÊÖ¤µ¤ì¤ë¡£
+
+    @seealso
+    mscript_list (), mlanguage_list ().  */
+    
+
+MPlist *
+mscript_language_list (MSymbol script)
+{
+  MPlist *plist = mscript__info (script);
+
+  if (plist                    /* script name */
+      && (plist = MPLIST_NEXT (plist)) /* language list */
+      && MPLIST_PLIST_P (plist))
+    return MPLIST_PLIST (plist);
+  return NULL;
+}
+
+/*** @} */
+/*=*/
+/***en
+    @name Obsolete functions
+*/
+/***ja
+    @name Obsolete ¤Ê´Ø¿ô
+*/
+/*** @{ */
+
+/***en
+    @brief Get an English language name.
+
+    This function is obsolete.  Use mlanguage_name_list () instead.
+
+    The mlanguage_name () function returns a symbol whose name is an
+    English name of $LANGUAGE.  $LANGUAGE is a symbol whose name is an
+    ISO639-2 3-letter language code, an ISO639-1 2-letter language
+    codes, or an English word.
+
+    @return
+    If the information is available, this function returns a non-#Mnil
+    symbol.  Otherwise, it returns #Mnil.
+
+    @seealso
+    mlanguage_code (), mlanguage_text ().  */
+
+/***ja
+    @brief ¸À¸ì¤Î±Ñ¸ì̾¤òÆÀ¤ë.
+
+    ´Ø¿ô mlanguage_name () ¤Ï¡¢$LANGUAGE ¤Î±Ñ¸ì̾¤ò̾Á°¤È¤¹¤ë¤è¤¦¤Ê¥·
+    ¥ó¥Ü¥ë¤òÊÖ¤¹¡£$LANGUAGE ¤Ï¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢¤½¤Î̾Á°¤Ï¡¢ISO639-2 3ʸ
+    »ú¸À¸ì¥³¡¼¥É¡¢ISO639-1 2ʸ»ú¸À¸ì¥³¡¼¥É¡¢±Ñ¸ì̾¡¢¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
+
+    @return
+    µá¤á¤Æ¤¤¤ë¾ðÊó¤¬ÆÀ¤é¤ì¤ë¤Ê¤é¡¢¤³¤Î´Ø¿ô¤Ï #Mnil °Ê³°¤Î¥·¥ó¥Ü¥ë¤òÊÖ
+    ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð #Mnil ¤òÊÖ¤¹¡£
+
+    @seealso
+    mlanguage_code (), mlanguage_text ().  */
+
+MSymbol
+mlanguage_name (MSymbol language)
+{
+  MPlist *plist = mlanguage__info (language);
+  MText *mt;
+
+  if (! plist)                 /* 3-letter code */
+    return Mnil;
+  plist = MPLIST_NEXT (plist); /* 2-letter code */
+  if (MPLIST_TAIL_P (plist))
+    return Mnil;
+  plist = MPLIST_NEXT (plist); /* english name */
+  if (MPLIST_MTEXT_P (plist))
+    return Mnil;
+  mt = MPLIST_MTEXT (plist);
+  if (mtext_nbytes (mt) != MSYMBOL_NAMELEN (language)
+      || memcmp (MTEXT_DATA (MPLIST_MTEXT (plist)),
+                MSYMBOL_NAME (language),
+                MSYMBOL_NAMELEN (language)))
+    return Mnil;
+  return language;
+}
+
+/*=*/
+
+/*
+  Local Variables:
+  coding: euc-japan
+  End:
+*/