+static int
+ft_check_lang (MFontFT *ft_info, MFontCapability *cap)
+{
+#ifdef HAVE_FONTCONFIG
+ MPlist *plist;
+ MText *mt;
+ int i, j;
+
+ for (i = 0; cap->lang[i] != Mnil; i++)
+ {
+ if (ft_info->lang
+ && (plist = mplist_find_by_key (ft_info->lang, cap->lang[i])))
+ {
+ if (MPLIST_VAL (plist))
+ return 0;
+ continue;
+ }
+
+ if (! ft_info->langset)
+ {
+ FcPattern *pat = FcPatternBuild (NULL, FC_FILE, FcTypeString,
+ MSYMBOL_NAME (ft_info->font.file),
+ NULL);
+ FcObjectSet *os = FcObjectSetBuild (FC_LANG, FC_CHARSET, NULL);
+ FcFontSet *fs = FcFontList (fc_config, pat, os);
+
+ if (fs->nfont == 0)
+ return -1;
+ if (FcPatternGetLangSet (fs->fonts[0], FC_LANG, 0, &ft_info->langset)
+ == FcResultMatch)
+ ft_info->langset = FcLangSetCopy (ft_info->langset);
+ else
+ ft_info->langset = FcLangSetCreate ();
+ FcPatternGetCharSet (fs->fonts[0], FC_CHARSET, 0, &ft_info->charset);
+ FcFontSetDestroy (fs);
+ FcObjectSetDestroy (os);
+ FcPatternDestroy (pat);
+ }
+ if (! ft_info->lang)
+ ft_info->lang = mplist ();
+ if (FcLangSetHasLang (ft_info->langset,
+ (FcChar8 *) MSYMBOL_NAME (cap->lang[i]))
+ == FcLangEqual)
+ {
+ mplist_push (ft_info->lang, cap->lang[i], Mt);
+ return 0;
+ }
+
+ mt = msymbol_get (cap->lang[i], Mtext);
+ if (! mt)
+ {
+ mplist_push (ft_info->lang, cap->lang[i], Mnil);
+ continue;
+ }
+
+ for (j = mtext_nchars (mt) - 1; j >= 0; j--)
+ if (! FcCharSetAddChar (ft_info->charset,
+ (FcChar32) mtext_ref_char (mt, j)))
+ break;
+ mplist_push (ft_info->lang, cap->lang[i], (j < 0 ? Mt : Mnil));
+ if (j < 0)
+ return 0;
+ }
+#endif /* HAVE_FONTCONFIG */
+ return -1;
+}
+
+static MPlist *ft_capability_list;
+
+static MPlist *
+ft_list_capability (MSymbol sym)
+{
+ MPlist *plist, *pl, *p;
+ MFontCapability *cap = mfont__get_capability (sym);
+
+ if (! cap)
+ return NULL;
+ if (ft_capability_list)
+ {
+ plist = mplist_find_by_key (ft_capability_list, sym);
+ if (plist)
+ return (MPLIST_VAL (plist) ? MPLIST_VAL (plist) : NULL);
+ }
+ else
+ {
+ plist = NULL;
+ ft_capability_list = mplist ();
+ }
+
+ if (cap->script != Mnil)
+ {
+ pl = ft_list_script (cap->script);
+ if (pl)
+ MPLIST_DO (pl, pl)
+ {
+ if (cap->script_tag && ft_check_otf (MPLIST_VAL (pl), cap) < 0)
+ continue;
+ if (cap->lang && ft_check_lang (MPLIST_VAL (pl), cap) < 0)
+ continue;
+ if (! plist)
+ plist = mplist ();
+ mplist_add (plist, MPLIST_KEY (pl), MPLIST_VAL (pl));
+ }
+ mplist_push (ft_capability_list, sym, plist);
+ return plist;
+ }
+
+ if (cap->lang)
+ {
+ int i;
+
+ for (i = 0; cap->lang[i] != Mnil; i++)
+ {
+ p = ft_list_language (cap->lang[i]);
+ if (p)
+ {
+ if (! plist)
+ plist = mplist ();
+ MPLIST_DO (p, p)
+ mplist_add (plist, MPLIST_KEY (p), MPLIST_VAL (p));
+ }
+ }
+ }
+ mplist_push (ft_capability_list, sym, plist);
+ return plist;
+}
+
+
+static MPlist *
+ft_list_file (MSymbol filename)
+{
+ MPlist *plist = NULL;
+
+ if (! ft_file_list)
+ ft_file_list = mplist ();
+ else if ((plist = mplist_find_by_key (ft_file_list, filename)))
+ return (MPLIST_VAL (plist) ? MPLIST_PLIST (plist) : NULL);
+
+#ifdef HAVE_FONTCONFIG
+ {
+ FcPattern *pattern = FcPatternCreate ();
+ FcObjectSet *os;
+ FcFontSet *fs;
+
+ FcPatternAddString (pattern, FC_FILE, (FcChar8 *) MSYMBOL_NAME (filename));
+ os = FcObjectSetBuild (FC_FAMILY, NULL);
+ fs = FcFontList (fc_config, pattern, os);
+ if (fs->nfont > 0)