X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Flanguage.c;h=0104a06bc405ee9c58713c139a19899559f5ba14;hb=699ce2a59e6d5614e57bd85e0f037b16ac95b2c0;hp=359d0bdb815f45b6c4ea39691b6792c8a5530d75;hpb=a61f5390f925972b48807056e4fda29c74f2a4a8;p=m17n%2Fm17n-lib.git diff --git a/src/language.c b/src/language.c index 359d0bd..0104a06 100644 --- a/src/language.c +++ b/src/language.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "m17n.h" #include "m17n-misc.h" @@ -91,6 +92,57 @@ init_script_list (void) return 0; } +static MPlist * +load_lang_name (MSymbol target3, MSymbol target2) +{ + MPlist *plist, *pl, *p; + + plist = mplist (); + mplist_add (plist, Msymbol, target3); + pl = mdatabase_list (Mlanguage, Mname, target3, Mnil); + if (! pl && target2 != Mnil) + pl = mdatabase_list (Mlanguage, Mname, target2, Mnil); + if (pl) + { + MPLIST_DO (p, pl) + { + MDatabase *mdb = MPLIST_VAL (p); + MPlist *p0 = mdatabase_load (mdb), *p1, *territories; + MSymbol script = mdatabase_tag (mdb)[3]; + + if (MPLIST_PLIST_P (p0)) + { + p1 = MPLIST_PLIST (p0); + if (MPLIST_SYMBOL_P (p1) && MPLIST_SYMBOL (p1) == Mlanguage) + { + p1 = MPLIST_NEXT (MPLIST_NEXT (MPLIST_NEXT (MPLIST_NEXT (p1)))); + territories = p1; + while (! MPLIST_TAIL_P (p1)) + { + if (MPLIST_SYMBOL_P (p1)) + p1 = MPLIST_NEXT (p1); + else + mplist__pop_unref (p1); + } + M17N_OBJECT_REF (territories); + mplist__pop_unref (p0); + } + else + territories = mplist (); + mplist_push (p0, Mplist, territories); + M17N_OBJECT_UNREF (territories); + mplist_push (p0, Msymbol, script); + mplist_add (plist, Mplist, p0); + M17N_OBJECT_UNREF (p0); + } + } + M17N_OBJECT_UNREF (pl); + } + mplist_push (langname_list, Mplist, plist); + M17N_OBJECT_UNREF (plist); + return plist; +} + /* Internal API */ @@ -111,13 +163,8 @@ mlang__init () 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); } @@ -185,9 +232,9 @@ mlanguage__info (MSymbol language) 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) + && strncasecmp ((char *) MTEXT_DATA (MPLIST_MTEXT (pl)), + MSYMBOL_NAME (language), + MSYMBOL_NAMELEN (language)) == 0) return MPLIST_PLIST (plist); } } @@ -403,78 +450,153 @@ mlanguage_code (MSymbol language, int len) @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. + names written in TARGET language. SCRIPT and TERRITORY, if not #Mnil, + specifies which script and territory to concern at first. 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. + SCRIPT and TERRITORY must be a symbol whose name is a script and + territory name of a locale (e.g. "TW", "SG") respectively. + @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. + If the translation is available, this function returns a non-empty + plist. The first element has key #MText and the value is an + M-text of a translated language name. If the succeeding elements + also have key #MText, their values are M-texts of alternate + translations. + + If no translation is available, @c NULL is returned. + The returned plist should not be modified nor freed. @seealso mlanguage_code (), mlanguage_text (). */ MPlist * -mlanguage_name_list (MSymbol language, MSymbol target) +mlanguage_name_list (MSymbol language, MSymbol target, + MSymbol script, MSymbol territory) { - MPlist *plist; + MPlist *plist, *pl; + MSymbol language2, target2; plist = mlanguage__info (language); if (! plist) return NULL; - language = mplist_value (plist); + language = MPLIST_SYMBOL (plist); + language2 = MPLIST_SYMBOL (MPLIST_NEXT (plist)); if (target != Mnil) { plist = mlanguage__info (target); if (! plist) return NULL; - target = mplist_value (plist); + target = MPLIST_SYMBOL (plist); + target2 = MPLIST_SYMBOL (MPLIST_NEXT (plist)); } else { MLocale *locale = mlocale_set (LC_MESSAGES, NULL); if (! locale) - target = msymbol ("eng"); + { + target = msymbol ("eng"); + target2 = msymbol ("en"); + script = territory = Mnil; + } else { target = mlocale_get_prop (locale, Mlanguage); plist = mlanguage__info (target); if (! plist) return NULL; - target = mplist_value (plist); + target = MPLIST_SYMBOL (plist); + target2 = MPLIST_SYMBOL (MPLIST_NEXT (plist)); + script = mlocale_get_prop (locale, Mscript); + territory = mlocale_get_prop (locale, Mterritory); } } - /* Now both LANGUAGE and TARGET are 3-letter codes. */ - if (langname_list) - plist = mplist_get (langname_list, target); + /* Now both LANGUAGE and TARGET are 3-letter codes. */ + if (! langname_list) + langname_list = mplist (); + plist = mplist__assq (langname_list, target); + if (plist) + plist = MPLIST_PLIST (plist); else - langname_list = mplist (), plist = NULL; - if (! plist) + plist = load_lang_name (target, target2); + + /* PLIST = (TARGET (SCRIPT (TERRITORY ...) (LANG-CODE NAME ...) ...) ...) */ + plist = MPLIST_NEXT (plist); + if (MPLIST_TAIL_P (plist)) + return NULL; + + MPLIST_DO (pl, plist) + { + MPlist *p = MPLIST_PLIST (pl), *p0; + + if (MPLIST_SYMBOL (p) == script + && (territory == Mnil + || mplist_find_by_value (MPLIST_PLIST (MPLIST_NEXT (p)), + territory)) + && (p = MPLIST_NEXT (MPLIST_NEXT (p))) + && ((p0 = mplist__assq (p, language)) + || (p0 = mplist__assq (p, language2)))) + { + plist = p0; + break; + } + } + if (MPLIST_TAIL_P (pl)) { - MDatabase *mdb = mdatabase_find (Mlanguage, Mname, target, Mnil); + MPLIST_DO (pl, plist) + { + MPlist *p = MPLIST_NEXT (MPLIST_PLIST (pl)), *p0; + + if ((territory == Mnil + || mplist_find_by_value (MPLIST_VAL (p), territory)) + && (p = MPLIST_NEXT (MPLIST_NEXT (p))) + && ((p0 = mplist__assq (p, language)) + || (p0 = mplist__assq (p, language2)))) + { + plist = p0; + break; + } + } + if (MPLIST_TAIL_P (pl)) + { + MPLIST_DO (pl, plist) + { + MPlist *p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (pl))), *p0; + + if ((p0 = mplist__assq (p, language)) + || (p0 = mplist__assq (p, language2))) + { + plist = p0; + break; + } + } + if (MPLIST_TAIL_P (pl)) + return NULL; + } + } - if (! mdb - || ! (plist = mdatabase_load (mdb))) - plist = mplist (); - else - mplist__pop_unref (plist); - langname_list = mplist_push (langname_list, target, plist); - MPLIST_SET_NESTED_P (langname_list); + plist = MPLIST_NEXT (MPLIST_PLIST (plist)); + if (territory != Mnil) + { + MPLIST_DO (pl, MPLIST_NEXT (plist)) + if (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == territory) + break; + if (! MPLIST_TAIL_P (pl) + && (pl = MPLIST_NEXT (pl)) + && MPLIST_MTEXT_P (pl)) + return pl; } - /* 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; + MPLIST_DO (plist, plist) + if (MPLIST_MTEXT_P (plist)) + break; + return (MPLIST_MTEXT_P (plist) ? plist : NULL); } /*=*/ @@ -680,6 +802,7 @@ mlanguage_name (MSymbol language) { MPlist *plist = mlanguage__info (language); MText *mt; + char *str; if (! plist) /* 3-letter code */ return Mnil; @@ -687,15 +810,13 @@ mlanguage_name (MSymbol language) if (MPLIST_TAIL_P (plist)) return Mnil; plist = MPLIST_NEXT (plist); /* english name */ - if (MPLIST_MTEXT_P (plist)) + 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; + str = alloca (mtext_nbytes (mt)); + memcpy (str, MTEXT_DATA (mt), mtext_nbytes (mt)); + str[0] = tolower (str[0]); + return msymbol__with_len (str, mtext_nbytes (mt)); } /*=*/