-/* 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
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 "internal.h"
#include "language.h"
#include "symbol.h"
+#include "plist.h"
+#include "mtext.h"
#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
+static MPlist *language_list;
+static MPlist *script_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 ...) ...). */
+ MPLIST_DO (pl, plist)
+ {
+ if (! MPLIST_PLIST_P (pl))
+ break;
+ p = MPLIST_PLIST (pl);
+ if (! MPLIST_SYMBOL_P (p))
+ break;
+ }
+ if (! MPLIST_TAIL_P (pl))
+ {
+ M17N_OBJECT_UNREF (plist);
+ return NULL;
+ }
+ 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 */
int
mlang__init ()
{
- /* ISO 639 */
- struct {
- char *name, *fullname;
- } lang_rec[] =
- { {"ab", "Abkhazian"},
- {"aa", "Afar"},
- {"af", "Afrikaans"},
- {"ak", "Akan"},
- {"sq", "Albanian"},
- {"am", "Amharic"},
- {"ar", "Arabic"},
- {"hy", "Armenian"},
- {"as", "Assamese"},
- {"ay", "Aymara"},
- {"az", "Azerbaijani"},
- {"ba", "Bashkir"},
- {"eu", "Basque"},
- {"bn", "Bengali"}, /* Bangla */
- {"dz", "Bhutani"},
- {"bh", "Bihari"},
- {"bi", "Bislama"},
- {"br", "Breton"},
- {"bg", "Bulgarian"},
- {"my", "Burmese"},
- {"be", "Byelorussian"}, /* Belarusian */
- {"km", "Cambodian"}, /* Khmer */
- {"ca", "Catalan"},
-#if 0
- {"??", "Cherokee"},
- {"??", "Chewa"},
-#endif
- {"zh", "Chinese"},
- {"co", "Corsican"},
- {"hr", "Croatian"},
- {"cs", "Czech"},
- {"da", "Danish"},
- {"dv", "Dhivehi"},
- {"nl", "Dutch"},
-#if 0
- {"??", "Edo"},
-#endif
- {"en", "English"},
- {"eo", "Esperanto"},
- {"et", "Estonian"},
- {"fo", "Faeroese"},
- {"fa", "Farsi"},
- {"fj", "Fiji"},
- {"fi", "Finnish"},
-#if 0
- {"??", "Flemish"},
-#endif
- {"fr", "French"},
- {"fy", "Frisian"},
-#if 0
- {"??", "Fulfulde"},
-#endif
- {"gl", "Galician"},
- {"gd", "Gaelic(Scottish)"}, /* Scottish */
- {"gv", "Gaelic(Manx)"}, /* Manx */
- {"ka", "Georgian"},
- {"de", "German"},
- {"el", "Greek"},
- {"kl", "Greenlandic"},
- {"gn", "Guarani"},
- {"gu", "Gujarati"},
- {"ha", "Hausa"},
-#if 0
- {"??", "Hawaiian"},
- {"iw", "Hebrew"},
-#endif
- {"he", "Hebrew"},
- {"hi", "Hindi"},
- {"hu", "Hungarian"},
-#if 0
- {"??", "Ibibio"},
-#endif
- {"is", "Icelandic"},
-#if 0
- {"??", "Igbo"},
- {"in", "Indonesian"},
-#endif
- {"id", "Indonesian"},
-#if 0
- {"ia", "Interlingua"},
- {"ie", "Interlingue"},
-#endif
- {"iu", "Inuktitut"},
- {"ik", "Inupiak"},
- {"ga", "Irish"},
- {"it", "Italian"},
- {"ja", "Japanese"},
- {"jw", "Javanese"},
- {"kn", "Kannada"},
-#if 0
- {"??", "Kanuri"},
-#endif
- {"ks", "Kashmiri"},
- {"kk", "Kazakh"},
- {"rw", "Kinyarwanda"}, /* Ruanda */
- {"ky", "Kirghiz"},
- {"rn", "Kirundi"}, /* Rundi */
- {"ko", "Korean"},
- {"ku", "Kurdish"},
- {"lo", "Laothian"},
- {"la", "Latin"},
- {"lv", "Latvian"}, /* Lettish */
- {"ln", "Lingala"},
- {"lt", "Lithuanian"},
- {"mk", "Macedonian"},
- {"mg", "Malagasy"},
- {"ms", "Malay"},
- {"ml", "Malayalam"},
-#if 0
- {"??", "Manipuri"},
-#endif
- {"mt", "Maltese"},
- {"mi", "Maori"},
- {"mr", "Marathi"},
- {"mo", "Moldavian"},
- {"mn", "Mongolian"},
- {"na", "Nauru"},
- {"ne", "Nepali"},
- {"no", "Norwegian"},
- {"oc", "Occitan"},
- {"or", "Oriya"},
- {"om", "Oromo"}, /* Afan, Galla */
-#if 0
- {"??", "Papiamentu"},
-#endif
- {"ps", "Pashto"}, /* Pushto */
- {"pl", "Polish"},
- {"pt", "Portuguese"},
- {"pa", "Punjabi"},
- {"qu", "Quechua"},
- {"rm", "Rhaeto-Romance"},
- {"ro", "Romanian"},
- {"ru", "Russian"},
-#if 0
- {"??", "Sami"}, /* Lappish */
-#endif
- {"sm", "Samoan"},
- {"sg", "Sangro"},
- {"sa", "Sanskrit"},
- {"sr", "Serbian"},
- {"sh", "Serbo-Croatian"},
- {"st", "Sesotho"},
- {"tn", "Setswana"},
- {"sn", "Shona"},
- {"sd", "Sindhi"},
- {"si", "Sinhalese"},
- {"ss", "Siswati"},
- {"sk", "Slovak"},
- {"sl", "Slovenian"},
- {"so", "Somali"},
- {"es", "Spanish"},
- {"su", "Sundanese"},
- {"sw", "Swahili"}, /* Kiswahili */
- {"sv", "Swedish"},
-#if 0
- {"??", "Syriac"},
-#endif
- {"tl", "Tagalog"},
- {"tg", "Tajik"},
-#if 0
- {"??", "Tamazight"},
-#endif
- {"ta", "Tamil"},
- {"tt", "Tatar"},
- {"te", "Telugu"},
- {"th", "Thai"},
- {"bo", "Tibetan"},
- {"ti", "Tigrinya"},
- {"to", "Tonga"},
- {"ts", "Tsonga"},
- {"tr", "Turkish"},
- {"tk", "Turkmen"},
- {"tw", "Twi"},
- {"ug", "Uighur"},
- {"uk", "Ukrainian"},
- {"ur", "Urdu"},
- {"uz", "Uzbek"},
-#if 0
- {"??", "Venda"},
-#endif
- {"vi", "Vietnamese"},
- {"vo", "Volapuk"},
- {"cy", "Welsh"},
- {"wo", "Wolof"},
- {"xh", "Xhosa"},
-#if 0
- {"??", "Yi"},
- {"ji", "Yiddish"},
-#endif
- {"yi", "Yiddish"},
- {"yo", "Yoruba"},
- {"zu", "Zulu"} };
- int i;
-
- Mlanguage = msymbol ("language");
- msymbol_put (Mlanguage, Mtext_prop_serializer,
- (void *) msymbol__serializer);
- msymbol_put (Mlanguage, Mtext_prop_deserializer,
- (void *) msymbol__deserializer);
- for (i = 0; i < ((sizeof lang_rec) / (sizeof lang_rec[0])); i++)
- msymbol_put (msymbol (lang_rec[i].name), Mlanguage,
- msymbol (lang_rec[i].fullname));
+ 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");
+
+ language_list = script_list = NULL;
return 0;
}
void
mlang__fini (void)
{
+ M17N_OBJECT_UNREF (language_list);
+ language_list = NULL;
+ M17N_OBJECT_UNREF (script_list);
+ script_list = NULL;
+}
+
+/*=*/
+
+/***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.
+
+ 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 *pl = MPLIST_PLIST (plist);
+
+ if (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == language)
+ return MPLIST_PLIST (plist);
+ if (! MPLIST_TAIL_P (pl))
+ {
+ pl = MPLIST_NEXT (pl);
+ if (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == language)
+ return MPLIST_PLIST (plist);
+ if (! MPLIST_TAIL_P (pl))
+ {
+ pl = MPLIST_NEXT (pl);
+ if (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == language)
+ return MPLIST_PLIST (plist);
+ }
+ }
+ }
+ 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))
+ {
+ script = MPLIST_SYMBOL (pl);
+ break;
+ }
+ }
+ return script;
}
#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\e$BJ8;z8@8l%3!<%I$r%j%9%H$9$k\e(B.
+
+ \e$B4X?t\e(B mlanguage_list () \e$B$O!"@07A<0\e(B (well-formed) plist \e$B$rJV$9!#3F%-!<\e(B
+ \e$B$O\e(B #Msymbol \e$B$G$"$j!"8D!9$NCM$O\e(B ISO639-2 \e$B$KDj$a$i$l$?\e(B3\e$BJ8;z8@8l%3!<\e(B
+ \e$B%I$rL>A0$H$9$k%7%s%\%k$G$"$k!#\e(B
+
+ @return
+ \e$B$3$N4X?t$,JV$9\e(B plist \e$B$O!"8F$S=P$7B&$,\e(B m17n_object_unref () \e$B$r;H$C\e(B
+ \e$B$F2rJ|$9$kI,MW$,$"$k!#\e(B
+
+ @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 (), mlanguage_text (). */
+
+/***ja
+ @brief \e$B8@8l%3!<%I$rF@$k\e(B.
+
+ \e$B4X?t\e(B mlanguage_code () \e$B$O!"\e(B$LANGUAGE \e$B$KBP1~$7$?\e(B ISO-639 \e$B8@8l%3!<%I\e(B
+ \e$B$,L>A0$G$"$k$h$&$J%7%s%\%k$rJV$9!#\e(B$LANGUAGE \e$B$O%7%s%\%k$G$"$j!"$=$N\e(B
+ \e$BL>A0$O!"\e(BISO639-2 3\e$BJ8;z8@8l%3!<%I!"\e(BISO639-1 2\e$BJ8;z8@8l%3!<%I!"1Q8lL>!"\e(B
+ \e$B$N$$$:$l$+$G$"$k!#\e(B
+
+ $LEN \e$B$OJV$5$l$k8@8l%3!<%I$N<oN`$r7hDj$9$k!#\e(B$LEN \e$B$,\e(B3\e$B$N>l9g$O\e(B
+ ISO639-2 3\e$BJ8;z8@8l%3!<%I$,JV$5$l$k!#\e(B2\e$B$N>l9g$O!"$b$7Dj5A$5$l$F$$$l\e(B
+ \e$B$P\e(B ISO639-1 2\e$BJ8;z8@8l%3!<%I$,!"$=$&$G$J$1$l$P\e(B #Mnil \e$B$,JV$5$l$k!#\e(B0
+ \e$B$N>l9g$O!"$b$7Dj5A$5$l$F$$$l$P\e(B2\e$BJ8;z%3!<%I$,!"$=$&$G$J$1$l$P\e(B3\e$BJ8;z%3!<\e(B
+ \e$B%I$,JV$5$l$k!#\e(B
+
+ @return
+ \e$B$b$7>pJs$,F@$i$l$l$P!"$3$N4X?t$O\e(B #Mnil \e$B0J30$N%7%s%\%k$rJV$9!#$=$&\e(B
+ \e$B$G$J$1$l$P\e(B #Mnil \e$B$rJV$9!#\e(B
+
+ @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 Get an English language name.
+
+ 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 \e$B8@8l$N1Q8lL>$rF@$k\e(B.
+
+ \e$B4X?t\e(B mlanguage_name () \e$B$O!"\e(B$LANGUAGE \e$B$N1Q8lL>$rL>A0$H$9$k$h$&$J%7\e(B
+ \e$B%s%\%k$rJV$9!#\e(B$LANGUAGE \e$B$O%7%s%\%k$G$"$j!"$=$NL>A0$O!"\e(BISO639-2 3\e$BJ8\e(B
+ \e$B;z8@8l%3!<%I!"\e(BISO639-1 2\e$BJ8;z8@8l%3!<%I!"1Q8lL>!"$N$$$:$l$+$G$"$k!#\e(B
+
+ @return
+ \e$B5a$a$F$$$k>pJs$,F@$i$l$k$J$i!"$3$N4X?t$O\e(B #Mnil \e$B0J30$N%7%s%\%k$rJV\e(B
+ \e$B$9!#$=$&$G$J$1$l$P\e(B #Mnil \e$B$rJV$9!#\e(B
+
+ @seealso
+ mlanguage_code (), mlanguage_text (). */
+
+MSymbol
+mlanguage_name (MSymbol language)
+{
+ MPlist *plist = mlanguage__info (language);
+
+ 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_SYMBOL_P (plist))
+ return Mnil;
+ return MPLIST_SYMBOL (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 \e$BM?$($i$l$?8@8l<+?H$G=q$+$l$?8@8lL>$rJV$9\e(B.
+
+ \e$B4X?t\e(B mlanguage_text () \e$B$O!"8@8l\e(B $LANGUAGE \e$B$G=q$+$l$?\e(B $LANGUAGE \e$B$N\e(B
+ \e$BL>A0$r\e(B M-text \e$B$N7A<0$GJV$9!#$=$N8@8l$NBeI=E*$JJ8;z$,$o$+$C$F$$$k>l\e(B
+ \e$B9g$O!"JV$5$l$k\e(B M-text \e$B$N3FJ8;z$K!"%-!<$,\e(B #Mtext \e$B$GCM$,$=$NBeI=E*$J\e(B
+ \e$BJ8;z$r4^$`\e(B M-text \e$B$G$"$k$h$&$J%F%-%9%H%W%m%Q%F%#$,IU2C$5$l$k!#\e(B
+
+ @return
+ \e$B5a$a$k>pJs$,F@$i$l$?>l9g!"$3$N4X?t$,JV$9\e(B M-text \e$B$rJQ99$7$?$j2rJ|$7\e(B
+ \e$B$?$j$7$F$O$$$1$J$$!#>pJs$,F@$i$l$J$+$C$?>l9g$O\e(B @c NULL \e$B$,JV$5$l$k!#\e(B
+
+ @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 \e$B%9%/%j%W%HL>$r%j%9%H$9$k\e(B.
+
+ \e$B4X?t\e(B mscript_list () \e$B$O!"@07A<0\e(B (well-formed) plist \e$B$rJV$9!#3F%-!<\e(B
+ \e$B$O\e(B #Msymbol \e$B$G$"$j!"8D!9$NCM$O%9%/%j%W%HL>$rL>A0$H$9$k%7%s%\%k$G$"\e(B
+ \e$B$k!#\e(B
+
+ @return
+ \e$B$3$N4X?t$,JV$9\e(B plist \e$B$O!"8F$S=P$7B&$,\e(B m17n_object_unref () \e$B$r;H$C\e(B
+ \e$B$F2rJ|$9$kI,MW$,$"$k!#\e(B
+
+ @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 plist;
+}
+
+/*=*/
+
+/***en
+ @brief List languages that use a specified script.
+
+ 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 \e$BM?$($i$l$?%9%/%j%W%H$rMQ$$$k8@8l$r%j%9%H$9$k\e(B.
+
+ \e$B4X?t\e(B mscript_language_list () \e$B$O!"\e(B$SCRIPT \e$B$rMQ$$$k8@8l$r%j%9%H$9$k!#\e(B
+ $SCRIPT \e$B$O%7%s%\%k$G!"$=$NL>A0$O\e(B Unicode Character Database \e$B$K<($5\e(B
+ \e$B$l$F$$$k%9%/%j%W%HL>$r$9$Y$F>.J8;z$K$7$?$b$N$G$"$k!#\e(B
+
+ @return \e$B$3$N4X?t$O!"@07A<0\e(B (well-formed) plist \e$B$rJV$9!#3F%-!<$O\e(B
+ #Msymbol \e$B$G$"$j!"8D!9$NCM$O\e(B ISO639-1 \e$B$KDj$a$i$l$?\e(B2\e$BJ8;z8@8l%3!<%I\e(B
+ (\e$BDj5A$5$l$F$$$J$$>l9g$O\e(B ISO639-2 \e$B$KDj$a$i$l$?\e(B3\e$BJ8;z8@8l%3!<%I\e(B) \e$B$rL>\e(B
+ \e$BA0$H$9$k%7%s%\%k$G$"$k!#JV$5$l$k\e(B plist \e$B$OJQ99$7$?$j2rJ|$7$?$j$7$F\e(B
+ \e$B$O$J$i$J$$!#\e(B$SCRIPT \e$B$,L$CN$N>l9g$O\e(B @c NULL \e$B$,JV$5$l$k!#\e(B
+
+ @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;
+}