Update copyright years
[m17n/m17n-lib.git] / src / fontset.c
index ea836af..133d24b 100644 (file)
@@ -1,5 +1,5 @@
 /* fontset.c -- fontset module.
-   Copyright (C) 2003, 2004
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H15PRO112
 
@@ -17,7 +17,7 @@
 
    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.  */
 
 /***en
 #include "font.h"
 #include "fontset.h"
 
+static int mdebug_flag = MDEBUG_FONTSET;
+
+static M17NObjectArray fontset_table;
+
 struct MFontset
 {
   M17NObject control;
@@ -97,9 +101,6 @@ struct MFontset
 
   /* FONT-GROUP */
   MPlist *fallback;
-
-  /* Plist of Mt vs font specs. */
-  MPlist *font_spec_list;
 };
 
 static MFontset *default_fontset;
@@ -114,8 +115,11 @@ struct MRealizedFontset
   /* Initialized to <fontset>->tick.  */
   unsigned tick;
 
-  /* Font spec extracted from a face.  */
-  MFont spec;
+  /* Font spec that must be satisfied, or NULL.  */
+  MFont *spec;
+
+  /* Font spec requested by a face.  */
+  MFont request;
 
   /* The frame on which the realized fontset is realized.  */
   MFrame *frame;
@@ -129,13 +133,13 @@ struct MRealizedFontset
 
 
 static MPlist *
-load_font_group (MPlist *plist, MPlist *elt, MPlist *spec_list)
+load_font_group (MPlist *plist, MPlist *elt)
 {
   MPLIST_DO (elt, elt)
     {
-      /* ELT ::= ( FONT-SPEC-LIST [ LAYOUTER ] ) ...  */
-      MPlist *elt2, *p;
-      MFont font, *spec = NULL;
+      /* ELT ::= ( FONT-SPEC [ LAYOUTER ] ) ...  */
+      MPlist *elt2;
+      MFont *font;
       MSymbol layouter_name;
 
       if (! MPLIST_PLIST_P (elt))
@@ -143,28 +147,15 @@ load_font_group (MPlist *plist, MPlist *elt, MPlist *spec_list)
       elt2 = MPLIST_PLIST (elt);
       if (! MPLIST_PLIST_P (elt2))
        MWARNING (MERROR_FONTSET);
-      mfont__set_spec_from_plist (&font, MPLIST_PLIST (elt2));
-      MPLIST_DO (p, spec_list)
-        {
-         if (! memcmp (MPLIST_VAL (p), &font, sizeof (MFont)))
-           {
-             spec = MPLIST_VAL (p);
-             break;
-           }
-        }
-      if (! spec)
-       {
-         MSTRUCT_MALLOC (spec, MERROR_FONTSET);
-         *spec = font;
-         mplist_add (spec_list, Mt, spec);
-       }
+      MSTRUCT_CALLOC (font, MERROR_FONTSET);
+      mfont__set_spec_from_plist (font, MPLIST_PLIST (elt2));
       elt2 = MPLIST_NEXT (elt2);
       layouter_name = Mt;
       if (MPLIST_SYMBOL_P (elt2))
        layouter_name = MPLIST_SYMBOL (elt2);
       if (layouter_name == Mnil)
        layouter_name = Mt;
-      plist = mplist_add (plist, layouter_name, spec);
+      plist = mplist_add (plist, layouter_name, font);
       continue;
     warning:
       /* ANSI-C requires some statement after a label.  */
@@ -178,59 +169,53 @@ load_font_group (MPlist *plist, MPlist *elt, MPlist *spec_list)
 static void
 load_fontset_contents (MFontset *fontset)
 {
-  MPlist *per_script, *per_charset, *fallback, *spec_list, *font_group;
-  MSymbol script, lang;
+  MPlist *per_script, *per_charset, *font_group;
   MPlist *fontset_def, *plist;
 
   fontset->per_script = per_script = mplist ();
   fontset->per_charset = per_charset = mplist ();
-  fontset->fallback = fallback = mplist ();
-  fontset->font_spec_list = spec_list = mplist ();
+  fontset->fallback = mplist ();
   if (! (fontset_def = (MPlist *) mdatabase_load (fontset->mdb)))
     return;
 
   MPLIST_DO (plist, fontset_def)
     {
-      /* PLIST ::= ( SCRIPT ( LANGUAGE FONT-SPEC-ELT ... ) ... )
-                  | (CHARSET FONT-SPEC-ELT ...)
-                  | FONT-SPEC-ELT  */
+      /* PLIST ::=   ( SCRIPT ( LANGUAGE ( FONT-SPEC [LAYOUTER]) ... ) ... )
+                  | ( CHARSET ( FONT-SPEC [LAYOUTER] ) ...)
+                  | ( nil ( FONT-SPEC [LAYOUTER] ) ...)
+        FONT-SPEC :: = ( ... ) */
       MPlist *elt;
+      MSymbol sym;
 
       if (! MPLIST_PLIST_P (plist))
        MWARNING (MERROR_FONTSET);
       elt = MPLIST_PLIST (plist);
       if (! MPLIST_SYMBOL_P (elt))
        MWARNING (MERROR_FONTSET);
-      script = MPLIST_SYMBOL (elt);
+      sym = MPLIST_SYMBOL (elt);
       elt = MPLIST_NEXT (elt);
       if (! MPLIST_PLIST_P (elt))
        MWARNING (MERROR_FONTSET);
-      if (script == Mnil)
-       fallback = load_font_group (fallback, elt, spec_list);
+      if (sym == Mnil)
+       load_font_group (fontset->fallback, elt);
       else if (MPLIST_PLIST_P (MPLIST_PLIST (elt)))
        {
-         font_group = mplist_find_by_key (fontset->per_charset, script);
-         if (! font_group)
-           {
-             font_group = mplist ();
-             per_charset = mplist_add (per_charset, script, font_group);
-           }
-         load_font_group (font_group, elt, spec_list);
+         /* SYM is a charset.  */
+         font_group = mplist ();
+         per_charset = mplist_add (per_charset, sym, font_group);
+         load_font_group (font_group, elt);
        }
       else
        {
-         MPlist *per_lang = mplist_find_by_key (fontset->per_script, script);
-
-         if (! per_lang)
-           {
-             per_lang = mplist ();
-             per_script = mplist_add (per_script, script, per_lang);
-           }
+         /* SYM is a script */
+         MPlist *per_lang = mplist ();
 
+         per_script = mplist_add (per_script, sym, per_lang);
          MPLIST_DO (elt, elt)
            {
              /* ELT ::= ( LANGUAGE FONT-DEF ...) ... */
              MPlist *elt2;
+             MSymbol lang;
 
              if (! MPLIST_PLIST_P (elt))
                MWARNING (MERROR_FONTSET);
@@ -240,14 +225,10 @@ load_fontset_contents (MFontset *fontset)
              lang = MPLIST_SYMBOL (elt2);
              if (lang == Mnil)
                lang = Mt;
-             font_group = mplist_find_by_key (per_lang, lang);
-             if (! font_group)
-               {
-                 font_group = mplist ();
-                 mplist_add (per_lang, lang, font_group);
-               }
+             font_group = mplist ();
+             mplist_add (per_lang, lang, font_group);
              elt2 = MPLIST_NEXT (elt2);
-             load_font_group (font_group, elt2, spec_list);
+             load_font_group (font_group, elt2);
            }
        }
       continue;
@@ -273,6 +254,8 @@ free_fontset (void *object)
        {
          MPLIST_DO (pl, MPLIST_PLIST (plist))
            {
+             MPLIST_DO (p, MPLIST_PLIST (pl))
+               free (MPLIST_VAL (p));
              p = MPLIST_PLIST (pl);
              M17N_OBJECT_UNREF (p);
            }
@@ -283,98 +266,129 @@ free_fontset (void *object)
     }
   if (fontset->per_charset)
     {
-      MPLIST_DO (plist, fontset->per_charset)
+      MPLIST_DO (pl, fontset->per_charset)
        {
-         pl = MPLIST_PLIST (plist);
-         M17N_OBJECT_UNREF (pl);
+         MPLIST_DO (p, MPLIST_PLIST (pl))
+           free (MPLIST_VAL (p));
+         p = MPLIST_PLIST (p);
+         M17N_OBJECT_UNREF (p);
        }
       M17N_OBJECT_UNREF (fontset->per_charset);
     }
   if (fontset->fallback)
-    M17N_OBJECT_UNREF (fontset->fallback);
+    {
+      MPLIST_DO (p, fontset->fallback)
+       free (MPLIST_VAL (p));
+      M17N_OBJECT_UNREF (fontset->fallback);
+    }
+
   plist = mplist_find_by_key (fontset_list, fontset->name);
   if (! plist)
     mdebug_hook ();
   mplist_pop (plist);
-  if (fontset->font_spec_list)
+  if (MPLIST_TAIL_P (fontset_list))
     {
-      if (((M17NObject *) (fontset->font_spec_list))->ref_count == 1)
-       MPLIST_DO (plist, fontset->font_spec_list)
-         free (MPLIST_VAL (plist));
-      M17N_OBJECT_UNREF (fontset->font_spec_list);
+      M17N_OBJECT_UNREF (fontset_list);
+      fontset_list = NULL;
     }
+  M17N_OBJECT_UNREGISTER (fontset_table, fontset);
   free (object);
 }
 
 static void
-realize_font_group (MFrame *frame, MFont *request, MPlist *font_group,
-                   int size)
-{
-  MPlist *plist = MPLIST_VAL (font_group), *pl, *p;
-
-  mplist_set (font_group, Mnil, NULL);
-  MPLIST_DO (pl, plist)
-    {
-      MSymbol layouter = MPLIST_KEY (pl);
-      MFont this_request = *request;
-      MRealizedFont *rfont;
-
-      mfont__resize (MPLIST_VAL (pl), &this_request);
-      rfont = mfont__select (frame, MPLIST_VAL (pl), &this_request,
-                            size, layouter == Mt ? Mnil : layouter);
-
-      if (rfont)
-       {
-         MPLIST_DO (p, font_group)
-           if (((MRealizedFont *) (MPLIST_VAL (p)))->score > rfont->score)
-             break;
-         mplist_push (p, Mt, rfont);
-       }
-    }
-}
-
-static void
-realize_fontset_elements (MFrame *frame, MRealizedFontset *realized,
-                         MFontset *fontset, MFont *request)
+realize_fontset_elements (MFrame *frame, MRealizedFontset *realized)
 {
-  MPlist *per_script, *per_lang, *per_charset, *font_group;
-  MPlist *plist, *pl;
+  MFontset *fontset = realized->fontset;
+  MPlist *per_script, *per_charset, *font_group;
+  MPlist *plist, *p;
 
-  realized->fontset = fontset;
-  realized->tick = fontset->tick;
-  realized->spec = *request;
-  realized->frame = frame;
   realized->per_script = per_script = mplist ();
+  /* The actual elements of per_script are realized on demand.  */
+#if 0
   MPLIST_DO (plist, fontset->per_script)
     {
+      MPlist *pl;
+
       per_lang = mplist ();
       per_script = mplist_add (per_script, MPLIST_KEY (plist), per_lang);
       MPLIST_DO (pl, MPLIST_PLIST (plist))
        {
          font_group = mplist ();
-         mplist_add (font_group, Mplist, MPLIST_VAL (pl));
          per_lang = mplist_add (per_lang, MPLIST_KEY (pl), font_group);
+         MPLIST_DO (p, MPLIST_PLIST (pl))
+           font_group = mplist_add (font_group,
+                                    MPLIST_KEY (p), MPLIST_VAL (p));
        }
     }
+#endif
 
   realized->per_charset = per_charset = mplist ();
   MPLIST_DO (plist, fontset->per_charset)
     {
       font_group = mplist ();
-      mplist_add (font_group, Mplist, MPLIST_VAL (plist));
       per_charset = mplist_add (per_charset, MPLIST_KEY (plist), font_group);
+      MPLIST_DO (p, MPLIST_PLIST (plist))
+       font_group = mplist_add (font_group, MPLIST_KEY (p), MPLIST_VAL (p));
     }
+  realized->fallback = font_group = mplist ();
+  MPLIST_DO (p, fontset->fallback)
+    font_group = mplist_add (font_group, MPLIST_KEY (p), MPLIST_VAL (p));
+}
 
-  realized->fallback = mplist ();
-  mplist_add (realized->fallback, Mplist, fontset->fallback);
 
+/* Return a plist of fonts for SCRIPT in FONTSET.  The returned list
+   is acutally a plist of languages vs font groups (which is a plist).
+   If SCRIPT is nil, return a plist of fallback fonts.  If FONTSET
+   doesn't record any fonts for SCRIPT, generate a proper font spec
+   lists for X backend and FreeType backend.  */
+
+MPlist *
+get_per_script (MFontset *fontset, MSymbol script)
+{
+  MPlist *plist;
+
+  if (script == Mnil)
+    return fontset->fallback;
+  plist = mplist_get (fontset->per_script, script);
+  if (! plist)
+    {
+      int len = MSYMBOL_NAMELEN (script);
+      char *cap = alloca (8 + len + 1);
+      MSymbol capability;
+      MFont *font;
+      MPlist *pl, *p;
+
+      sprintf (cap, ":script=%s", MSYMBOL_NAME (script));
+      capability = msymbol (cap);
+
+      pl = mplist ();
+      MPLIST_DO (p, fontset->fallback)
+       {
+         font = mfont_copy (MPLIST_VAL (p));
+         mfont_put_prop (font, Mregistry, Municode_bmp);
+         font->source = MFONT_SOURCE_FT;
+         font->capability = capability;
+         mplist_add (pl, Mt, font);
+
+         font = mfont_copy (MPLIST_VAL (p));
+         mfont_put_prop (font, Mregistry, Miso10646_1);
+         font->source = MFONT_SOURCE_X;
+         font->capability = capability;
+         mplist_add (pl, Mt, font);
+       }
+      plist = mplist ();
+      mplist_add (plist, Mt, pl);
+      mplist_add (fontset->per_script, script, plist);
+    }
+  return plist;
 }
 
 static void
 free_realized_fontset_elements (MRealizedFontset *realized)
 {
   MPlist *plist, *pl, *p;
-  MRealizedFont *rfont;
+  MFont *font;
+  MFontList *font_list;
 
   if (realized->per_script)
     {
@@ -383,8 +397,18 @@ free_realized_fontset_elements (MRealizedFontset *realized)
          MPLIST_DO (pl, MPLIST_PLIST (plist))
            {
              MPLIST_DO (p, MPLIST_PLIST (pl))
-               if ((rfont = MPLIST_VAL (p)) && ! rfont->frame)
-                 free (rfont);
+               {
+                 font = MPLIST_VAL (p);
+                 if (font->type == MFONT_TYPE_OBJECT)
+                   {
+                     font_list = (MFontList *) font;
+                     free (font_list->fonts);
+                     free (font_list);
+                   }
+                 /* This is to avoid freeing rfont again by the later
+                    M17N_OBJECT_UNREF (p) */
+                 MPLIST_KEY (p) = Mt;
+               }
              p = MPLIST_PLIST (pl);
              M17N_OBJECT_UNREF (p);
            }
@@ -398,8 +422,16 @@ free_realized_fontset_elements (MRealizedFontset *realized)
       MPLIST_DO (plist, realized->per_charset)
        {
          MPLIST_DO (pl, MPLIST_PLIST (plist))
-           if ((rfont = MPLIST_VAL (pl)) && ! rfont->frame)
-             free (rfont);
+           {
+             font = MPLIST_VAL (pl);
+             if (font->type == MFONT_TYPE_OBJECT)
+               {
+                 font_list = (MFontList *) font;
+                 free (font_list->fonts);
+                 free (font_list);
+               }
+             MPLIST_KEY (pl) = Mt;
+           }
          pl = MPLIST_PLIST (plist);
          M17N_OBJECT_UNREF (pl);
        }
@@ -408,8 +440,16 @@ free_realized_fontset_elements (MRealizedFontset *realized)
   if (realized->fallback)
     {
       MPLIST_DO (plist, realized->fallback)
-       if ((rfont = MPLIST_VAL (plist)) && ! rfont->frame)
-         free (rfont);
+       {
+         font = MPLIST_VAL (plist);
+         if (font->type == MFONT_TYPE_OBJECT)
+           {
+             font_list = (MFontList *) font;
+             free (font_list->fonts);
+             free (font_list);
+           }
+         MPLIST_KEY (plist) = Mt;
+       }
       M17N_OBJECT_UNREF (realized->fallback);
     }
 }
@@ -418,8 +458,7 @@ static void
 update_fontset_elements (MRealizedFontset *realized)
 {
   free_realized_fontset_elements (realized);
-  realize_fontset_elements (realized->frame, realized, realized->fontset,
-                           &realized->spec);
+  realize_fontset_elements (realized->frame, realized);
 }
 
 
@@ -430,6 +469,8 @@ update_fontset_elements (MRealizedFontset *realized)
 int
 mfont__fontset_init ()
 {
+  M17N_OBJECT_ADD_ARRAY (fontset_table, "Fontset");
+
   Mfontset = msymbol ("fontset");
   Mfontset->managing_key = 1;
   fontset_list = mplist ();
@@ -453,15 +494,14 @@ mfont__fontset_init ()
 void
 mfont__fontset_fini ()
 {
-  while (! MPLIST_TAIL_P (fontset_list))
-    free_fontset ((MFontset *) MPLIST_VAL (fontset_list));
-  M17N_OBJECT_UNREF (fontset_list);
-  fontset_list = NULL;
+  M17N_OBJECT_UNREF (default_fontset);
+  default_fontset = NULL;
 }
 
 
 MRealizedFontset *
-mfont__realize_fontset (MFrame *frame, MFontset *fontset, MFace *face)
+mfont__realize_fontset (MFrame *frame, MFontset *fontset,
+                       MFace *face, MFont *spec)
 {
   MRealizedFontset *realized;
   MFont request;
@@ -470,22 +510,36 @@ mfont__realize_fontset (MFrame *frame, MFontset *fontset, MFace *face)
   if (fontset->mdb)
     load_fontset_contents (fontset);
 
+  MFONT_INIT (&request);
   mfont__set_spec_from_face (&request, face);
-  if (request.property[MFONT_SIZE] <= 0)
+  if (request.size <= 0)
     {
       mdebug_hook ();
-      request.property[MFONT_SIZE] = 120;
+      request.size = 120;
     }
   MPLIST_DO (plist, frame->realized_fontset_list)
     {
       realized = (MRealizedFontset *) MPLIST_VAL (plist);
       if (fontset->name == MPLIST_KEY (plist)
-         && ! memcmp (&request, &realized->spec, sizeof (request)))
+         && ! memcmp (&request, &realized->request, sizeof (MFont))
+         && (realized->spec
+             ? (spec && ! memcmp (spec, &realized->spec, sizeof (MFont)))
+             : ! spec))
        return realized;
     }
 
-  MSTRUCT_MALLOC (realized, MERROR_FONTSET);
-  realize_fontset_elements (frame, realized, fontset, &request);
+  MSTRUCT_CALLOC (realized, MERROR_FONTSET);
+  realized->fontset = fontset;
+  M17N_OBJECT_REF (fontset);
+  realized->tick = fontset->tick;
+  if (spec)
+    {
+      MSTRUCT_CALLOC (realized->spec, MERROR_FONTSET);
+      *realized->spec = *spec;
+    }
+  realized->request = request;
+  realized->frame = frame;
+  realize_fontset_elements (frame, realized);
   mplist_add (frame->realized_fontset_list, fontset->name, realized);
   return realized;
 }
@@ -495,75 +549,196 @@ void
 mfont__free_realized_fontset (MRealizedFontset *realized)
 {
   free_realized_fontset_elements (realized);
+  M17N_OBJECT_UNREF (realized->fontset);
+  if (realized->spec)
+    free (realized->spec);
   free (realized);
 }
 
 
 static MRealizedFont *
-try_font_group (MRealizedFontset *realized,
-               MPlist *font_group, MGlyph *g, int *num, int size)
+try_font_list (MFrame *frame, MFontList *font_list, MFont *request,
+              MSymbol layouter, MGlyph *g, int *num, int all, int exact)
 {
-  MFrame *frame = realized->frame;
+  int i, j;
+  MFont *font;
   MRealizedFont *rfont;
-  MPlist *plist;
-  int i;
 
-  if (MPLIST_PLIST_P (font_group))
-    realize_font_group (frame, &realized->spec, font_group, size);
-
-  MPLIST_DO (plist, font_group)
+  for (i = 0; i < font_list->nfonts; i++)
     {
-      rfont = (MRealizedFont *) MPLIST_VAL (plist);
-      if (rfont->status < 0)
+      if (font_list->fonts[i].font->type == MFONT_TYPE_SPEC)
+       MFATAL (MERROR_FONT);
+      if (exact)
+       {
+         if (font_list->fonts[i].score > 0)
+           break;
+       }
+      else
+       {
+         if (font_list->fonts[i].score == 0)
+           continue;
+       }
+      font = font_list->fonts[i].font;
+      if (font->type == MFONT_TYPE_FAILURE)
        continue;
       /* Check if this font can display all glyphs.  */
-      for (i = 0; i < *num; i++)
+      for (j = 0; j < *num; j++)
        {
-         g[i].code = mfont__encode_char (rfont,
-                                         g[i].type == GLYPH_CHAR ? g[i].c
-                                         : ' ');
-         if (g[i].code == MCHAR_INVALID_CODE)
+         int c = g[j].type == GLYPH_CHAR ? g[j].g.c : ' ';
+         MFLT *flt;
+         MCharTable *coverage;
+
+         if (layouter != Mt
+             ? ((flt = mflt_get (layouter))
+                ? (coverage = mflt_coverage (flt),
+                   ! mchartable_lookup (coverage, c))
+                : 0)
+             : ! mfont__has_char (frame, font, &font_list->object, c))
            break;
        }
-      if (i == *num)
+      if (j == 0 && *num > 0)
+       continue;
+      if (j == *num || !all)
        {
-         if (rfont->status > 0
-             || mfont__open (rfont) == 0)
-           /* We found a font that can display all glyphs.  */
-           return rfont;
+         MCharTable *coverage = NULL;
+
+         /* We found a font that can display the requested range of
+            glyphs.  */
+         if (font->type == MFONT_TYPE_REALIZED)
+           rfont = (MRealizedFont *) font;
+         else
+           {
+             rfont = mfont__open (frame, font, &font_list->object);
+             if (! rfont)
+               continue;
+             font_list->fonts[i].font = (MFont *) rfont;
+           }
+         rfont->layouter = layouter == Mt ? Mnil : layouter;
+         if (rfont->layouter)
+           {
+             MFLT *flt = mflt_get (rfont->layouter);
+
+             if (flt)
+               coverage = mflt_coverage (flt);
+           }
+         *num = j;
+         for (j = 0; j < *num; j++)
+           {
+             int c = g[j].type == GLYPH_CHAR ? g[j].g.c : ' ';
+
+             g[j].g.code = (coverage
+                            ? (unsigned ) mchartable_lookup (coverage, c)
+                            : mfont__encode_char (frame, (MFont *) rfont,
+                                                  &font_list->object, c));
+           }
+         return rfont;
        }
     }
+  return NULL;
+}
 
-  /* We couldn't find a font that can display all glyphs.  Find one
-     that can display at least the first glyph.  */
-  MPLIST_DO (plist, font_group)
+
+static MRealizedFont *
+try_font_group (MRealizedFontset *realized, MFont *request,
+               MPlist *font_group, MGlyph *g, int *num, int size)
+{
+  MFrame *frame = realized->frame;
+  MFont *font;
+  MFontList *font_list;
+  MRealizedFont *rfont;
+  MPlist *plist;
+  MSymbol layouter;
+  int best_score = -1, worst_score;
+
+  for (plist = font_group; ! MPLIST_TAIL_P (plist); )
     {
-      rfont = (MRealizedFont *) MPLIST_VAL (plist);
-      if (rfont->status < 0)
-       continue;
-      g->code = mfont__encode_char (rfont,
-                                   g->type == GLYPH_CHAR ? g->c : ' ');
-      if (g->code != MCHAR_INVALID_CODE)
+      int this_score;
+
+      layouter = MPLIST_KEY (plist);
+      font = MPLIST_VAL (plist);
+      if (font->type == MFONT_TYPE_SPEC)
        {
-         if (rfont->status > 0
-             || mfont__open (rfont) == 0)
+         /* We have not yet made this entry a MFontList.  */
+         if (realized->spec)
            {
-             /* Ok, let's use this font.  Check how many more
-                characters it supports.  */
-             int i;
-
-             for (i = 1; i < *num; i++)
+             MFont this = *font;
+             
+             if (mfont__merge (&this, realized->spec, 1) < 0)
                {
-                 g[i].code = mfont__encode_char (rfont,
-                                                 g[i].type == GLYPH_CHAR
-                                                 ? g[i].c : ' ');
-                 if (g[i].code == MCHAR_INVALID_CODE)
-                   break;
+                 mplist_pop (plist);
+                 continue;
                }
-             *num = i;
-             return rfont;
+             font_list = mfont__list (frame, &this, &this, size);
            }
+         else
+           font_list = mfont__list (frame, font, request, size);
+         if (! font_list)
+           {
+             /* As there's no font matching this spec, remove this
+                element from the font group.  */
+             mplist_pop (plist);
+             continue;
+           }
+         MPLIST_VAL (plist) = font_list;
+       }
+      else
+       font_list = (MFontList *) font;
+
+      this_score = font_list->fonts[0].score;
+      if ((this_score == 0)
+         && (rfont = try_font_list (frame, font_list, request,
+                                    layouter, g, num, 1, 1)))
+       return rfont;
+      if (best_score < 0)
+       {
+         best_score = worst_score = this_score;
+         plist = MPLIST_NEXT (plist);
        }
+      else if (this_score >= worst_score)
+       {
+         worst_score = this_score;
+         plist = MPLIST_NEXT (plist);
+       }
+      else
+       {
+         MPlist *pl;
+
+         MPLIST_DO (pl, font_group)
+           if (this_score < ((MFontList *) MPLIST_VAL (pl))->fonts[0].score)
+             break;
+         mplist_pop (plist);
+         mplist_push (pl, layouter, font_list);
+       }
+    }
+
+  /* We couldn't find an exact matching font that can display all
+     glyphs.  Find one that can at least display all glyphs.  */
+  MPLIST_DO (plist, font_group)
+    {
+      rfont = try_font_list (frame, MPLIST_VAL (plist), request,
+                            MPLIST_KEY (plist), g, num, 1, 0);
+      if (rfont)
+       return rfont;
+    }
+
+  /* We couldn't find a font that can display all glyphs.  Find an
+     exact matching font that can at least display the first
+     glyph.  */
+  MPLIST_DO (plist, font_group)
+    {
+      rfont = try_font_list (frame, MPLIST_VAL (plist), request,
+                            MPLIST_KEY (plist), g, num, 0, 1);
+      if (rfont)
+       return rfont;
+    }
+
+  /* Find any font that can at least display the first glyph.  */
+  MPLIST_DO (plist, font_group)
+    {
+      rfont = try_font_list (frame, MPLIST_VAL (plist), request,
+                            MPLIST_KEY (plist), g, num, 0, 0);
+      if (rfont)
+       return rfont;
     }
 
   return NULL;
@@ -572,24 +747,51 @@ try_font_group (MRealizedFontset *realized,
 MRealizedFont *
 mfont__lookup_fontset (MRealizedFontset *realized, MGlyph *g, int *num,
                       MSymbol script, MSymbol language, MSymbol charset,
-                      int size)
+                      int size, int ignore_fallback)
 {
   MCharset *preferred_charset = (charset == Mnil ? NULL : MCHARSET (charset));
   MPlist *per_charset, *per_script, *per_lang;
   MPlist *plist;
   MRealizedFont *rfont = NULL;
 
+  if (MDEBUG_FLAG ())
+    {
+      int i;
+
+      MDEBUG_PRINT1 (" [FONTSET] fontset looking up for %s:",
+                    script ? script->name : "none");
+      for (i = 0; i < *num; i++)
+       MDEBUG_PRINT1 (" U+%04X", g[i].g.c);
+      MDEBUG_PRINT ("\n");
+    }
+
   if (realized->tick != realized->fontset->tick)
     update_fontset_elements (realized);
 
   if (preferred_charset
       && (per_charset = mplist_get (realized->per_charset, charset)) != NULL
-      && (rfont = try_font_group (realized, per_charset, g, num, size)))
-    return rfont;
+      && (rfont = try_font_group (realized, &realized->request, per_charset,
+                                 g, num, size)))
+    goto done;
 
-  if (script != Mnil
-      && (per_script = mplist_get (realized->per_script, script)))
+  if (script != Mnil)
     {
+      MFont request = realized->request;
+
+      if (script != Mlatin)
+       /* This is not appropriate for non-Latin scripts.  */
+       request.property[MFONT_REGISTRY] = 0;
+
+      per_script = mplist_get (realized->per_script, script);
+      if (! per_script)
+       {
+         per_script = mplist_copy (get_per_script (realized->fontset, script));
+         /* PER_SCRIPT ::= (LANGUAGE:(LAYOUTER:FONT-SPEC ...) ...) */
+         MPLIST_DO (plist, per_script)
+           MPLIST_VAL (plist) = mplist_copy (MPLIST_VAL (plist));
+         mplist_add (realized->per_script, script, per_script);
+       }
+
       /* We prefer font groups in this order:
          (1) group matching with LANGUAGE if LANGUAGE is not Mnil
          (2) group for generic language
@@ -597,62 +799,179 @@ mfont__lookup_fontset (MRealizedFontset *realized, MGlyph *g, int *num,
       if (language == Mnil)
        language = Mt;
       if ((per_lang = mplist_get (per_script, language))
-         && (rfont = try_font_group (realized, per_lang, g, num, size)))
-       return rfont;
+         && (rfont = try_font_group (realized, &request, per_lang,
+                                     g, num, size)))
+       goto done;
 
+      if (per_lang && *num > 1)
+       *num = 1;
       if (language == Mt)
        {
          /* Try the above (3) */
          MPLIST_DO (plist, per_script)
            if (MPLIST_KEY (plist) != language
-               && (rfont = try_font_group (realized, MPLIST_PLIST (plist),
+               && (rfont = try_font_group (realized, &request,
+                                           MPLIST_PLIST (plist),
                                            g, num, size)))
-             return rfont;
+             goto done;
        }
       else
        {
          /* At first try the above (2) */
          if ((per_lang = mplist_get (per_script, Mt))
-             && (rfont = try_font_group (realized, per_lang, g, num, size)))
-           return rfont;
+             && (rfont = try_font_group (realized, &request, per_lang,
+                                         g, num, size)))
+           goto done;
 
+         if (per_lang && *num > 1)
+           *num = 1;
          /* Then try the above (3) */
          MPLIST_DO (plist, per_script)
            if (MPLIST_KEY (plist) != language
                && MPLIST_KEY (plist) != Mt
-               && (rfont = try_font_group (realized, MPLIST_PLIST (plist),
+               && (rfont = try_font_group (realized, &request,
+                                           MPLIST_PLIST (plist),
                                            g, num, size)))
-             return rfont;
+             goto done;
        }
+      if (ignore_fallback)
+       goto done;
     }
 
   if (language != Mnil)
     /* Find a font group for this language from all scripts.  */
     MPLIST_DO (plist, realized->per_script)
-      if ((per_lang = mplist_get (MPLIST_PLIST (plist), language))
-         && (rfont = try_font_group (realized, per_lang, g, num, size)))
-       return rfont;
+      {
+       MFont request = realized->request;
+
+       if (MPLIST_KEY (plist) != Mlatin)
+         request.property[MFONT_FOUNDRY]
+           = request.property[MFONT_FAMILY]
+           = request.property[MFONT_FAMILY] = 0;
+       if ((per_lang = mplist_get (MPLIST_PLIST (plist), language))
+           && (rfont = try_font_group (realized, &request, per_lang,
+                                       g, num, size)))
+         goto done;
+      }
 
   /* Try fallback fonts.  */
-  if ((rfont = try_font_group (realized, realized->fallback, g, num, size)))
-    return rfont;
+  rfont = try_font_group (realized, &realized->request,
+                         realized->fallback, g, num, size);
+ done:
+  if (MDEBUG_FLAG ())
+    {
+      if (rfont)
+       {
+         MSymbol family = mfont_get_prop (rfont->font, Mfamily);
+         MDEBUG_PRINT1 (" [FONTSET] found %s\n", family->name);
+       }
+      else
+       MDEBUG_PRINT (" [FONTSET] not found\n");
+    }
+
+  return rfont;
+}
+
+MRealizedFont *
+get_font_from_group (MFrame *frame, MPlist *plist, MFont *font)
+{
+  MRealizedFont *rfont;
+
+  MPLIST_DO (plist, plist)
+    {
+      MFont spec = *(MFont *) MPLIST_VAL (plist);
+      if (mfont__merge (&spec, font, 1) < 0)
+       continue;
+      if (font->type == MFONT_TYPE_SPEC)
+       rfont = (MRealizedFont *) mfont_find (frame, &spec, NULL, 0);
+      else if (font->type == MFONT_TYPE_OBJECT)
+       rfont = mfont__open (frame, font, &spec);
+      else
+       rfont = (MRealizedFont *) font;
+      if (rfont
+         && (spec.capability == Mnil
+             || mfont__check_capability (rfont, spec.capability) == 0))
+       {
+         rfont->layouter
+           = MPLIST_KEY (plist) == Mt ? Mnil : MPLIST_KEY (plist);
+         return rfont;
+       }
+    }
+  return NULL;
+}
+
+MRealizedFont *
+mfontset__get_font (MFrame *frame, MFontset *fontset,
+                   MSymbol script, MSymbol language, MFont *font,
+                   int *best)
+{
+  MPlist *per_script, *per_lang;
+  MRealizedFont *rfont;
+
+  if (best)
+    *best = 0;
 
-  /* At last try all fonts.  */
-  MPLIST_DO (per_script, realized->per_script)
+  if (language == Mnil)
+    language = Mt;
+
+  if (script != Mnil)
     {
-      MPLIST_DO (per_lang, MPLIST_PLIST (per_script))
-       if ((rfont = try_font_group (realized, MPLIST_PLIST (per_lang),
-                                    g, num, size)))
+      per_script = get_per_script (fontset, script);
+      if ((per_lang = mplist_get (per_script, language))
+         && (rfont = get_font_from_group (frame, per_lang, font)))
+       {
+         if (best)
+           *best = 1;
          return rfont;
+       }
+      if (best)
+       *best = per_lang ? 0 : 1;
+      if (language == Mt)
+       {
+         MPLIST_DO (per_script, per_script)
+           if (MPLIST_KEY (per_script) != language
+               && (rfont = get_font_from_group (frame,
+                                                MPLIST_PLIST (per_script),
+                                                font)))
+             return rfont;
+       }
+      else
+       {
+         if ((per_lang = mplist_get (per_script, Mt))
+             && (rfont = get_font_from_group (frame, per_lang, font)))
+           return rfont;
+         if (best)
+           *best = 0;
+         MPLIST_DO (per_script, per_script)
+           if (MPLIST_KEY (per_script) != language
+               && MPLIST_KEY (per_script) != Mt
+               && (rfont = get_font_from_group (frame,
+                                                MPLIST_PLIST (per_script),
+                                                font)))
+             return rfont;
+       }
     }
-  MPLIST_DO (per_charset, realized->per_charset)
-    if ((rfont = try_font_group (realized, MPLIST_PLIST (per_charset),
-                                g, num, size)))
-      return rfont;
 
+  if (language != Mt)
+    MPLIST_DO (per_script, fontset->per_script)
+      {
+       if ((per_lang = mplist_get (MPLIST_PLIST (per_script), language))
+           && (rfont = get_font_from_group (frame, per_lang, font)))
+         {
+           if (best)
+             *best = 1;
+           return rfont;
+         }
+      }
+
+  if (best)
+    *best = 0;
+  if ((rfont = get_font_from_group (frame, fontset->fallback, font)))
+    return rfont;
   return NULL;
 }
 
+
 /*** @} */
 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
 
@@ -708,14 +1027,20 @@ mfontset (char *name)
   MFontset *fontset;
 
   if (! name)
-    fontset = default_fontset;
+    {
+      fontset = default_fontset;
+      M17N_OBJECT_REF (fontset);
+    }
   else
     {
       sym = msymbol (name);
       fontset = mplist_get (fontset_list, sym);
-      if (! fontset)
+      if (fontset)
+       M17N_OBJECT_REF (fontset);
+      else
        {
          M17N_OBJECT (fontset, free_fontset, MERROR_FONTSET);
+         M17N_OBJECT_REGISTER (fontset_table, fontset);
          fontset->name = sym;
          fontset->mdb = mdatabase_find (Mfontset, sym, Mnil, Mnil);
          if (! fontset->mdb)
@@ -723,12 +1048,10 @@ mfontset (char *name)
              fontset->per_script = mplist ();
              fontset->per_charset = mplist ();
              fontset->fallback = mplist ();
-             fontset->font_spec_list = mplist ();
            }
          mplist_put (fontset_list, sym, fontset);
        }
     }
-  M17N_OBJECT_REF (fontset);
   return fontset;
 }
 
@@ -770,11 +1093,12 @@ mfontset_copy (MFontset *fontset, char *name)
 {
   MSymbol sym = msymbol (name);
   MFontset *copy = mplist_get (fontset_list, sym);
-  MPlist *plist, *pl;
+  MPlist *plist, *pl, *p;
 
   if (copy)
     return NULL;
   M17N_OBJECT (copy, free_fontset, MERROR_FONTSET);
+  M17N_OBJECT_REGISTER (fontset_table, copy);
   copy->name = sym;
 
   if (fontset->mdb)
@@ -785,28 +1109,46 @@ mfontset_copy (MFontset *fontset, char *name)
       copy->per_script = mplist ();
       MPLIST_DO (plist, fontset->per_script)
         {
-         MPlist *new = mplist ();
+         MPlist *per_lang = mplist ();
 
+         mplist_add (copy->per_script, MPLIST_KEY (plist), per_lang);
          MPLIST_DO (pl, MPLIST_PLIST (plist))
-           mplist_add (new, MPLIST_KEY (pl), mplist_copy (MPLIST_PLIST (pl)));
-         mplist_add (copy->per_script, MPLIST_KEY (plist), new);
+           {
+             MPlist *font_group = mplist ();
+
+             per_lang = mplist_add (per_lang, MPLIST_KEY (pl), font_group);
+             MPLIST_DO (p, MPLIST_PLIST (pl))
+               font_group = mplist_add (font_group, MPLIST_KEY (p),
+                                        mfont_copy (MPLIST_VAL (p)));
+           }
        }
     }
   if (fontset->per_charset)
     {
-      copy->per_charset = mplist ();
-      MPLIST_DO (plist, fontset->per_charset)
-       mplist_add (copy->per_charset, MPLIST_KEY (plist),
-                   mplist_copy (MPLIST_PLIST (plist)));
+      MPlist *per_charset = mplist ();
+
+      copy->per_charset = per_charset;
+      MPLIST_DO (pl, fontset->per_charset)
+       {
+         MPlist *font_group = mplist ();
+
+         per_charset = mplist_add (per_charset, MPLIST_KEY (pl), font_group);
+         MPLIST_DO (p, MPLIST_PLIST (pl))
+           font_group = mplist_add (font_group, MPLIST_KEY (p),
+                                    mfont_copy (MPLIST_VAL (p)));
+       }
     }
   if (fontset->fallback)
-    copy->fallback = mplist_copy (fontset->fallback);
+    {
+      MPlist *font_group = mplist ();
 
-  copy->font_spec_list = fontset->font_spec_list;
-  M17N_OBJECT_REF (copy->font_spec_list);
+      copy->fallback = font_group;
+      MPLIST_DO (p, fontset->fallback)
+       font_group = mplist_add (font_group, MPLIST_KEY (p),
+                                mfont_copy (MPLIST_VAL (p)));
+    }                           
 
   mplist_put (fontset_list, sym, copy);
-  M17N_OBJECT_REF (copy);
   return copy;
 }
 
@@ -848,7 +1190,7 @@ mfontset_copy (MFontset *fontset, char *name)
     are removed from the group.
 
     If $LAYOUTER_NAME is not @c Mnil, it must be a symbol representing
-    a @ref flt (font layout table).  In that case, if $FONT is
+    a @ref mdbFLT (font layout table).  In that case, if $FONT is
     selected for drawing an M-text, that font layout table is used to
     generate a glyph code sequence from a character sequence.
 
@@ -885,7 +1227,7 @@ mfontset_copy (MFontset *fontset, char *name)
     ¤¬Éé¤Ê¤é¤Ð¡¢ºÇÄã¤ÎÍ¥ÀèÅÙ¤ò»ý¤Ä¡£$HOW ¤¬ 0 ¤Ê¤é¤Ð¡¢$FONT 
     ¤Ï´ØÏ¢ÉÕ¤±¤é¤ì¤¿¤â¤Î¤ËÂФ¹¤ëÍ£°ì¤ÎÍøÍѲÄǽ¤Ê¥Õ¥©¥ó¥È¤È¤Ê¤ê¡¢Â¾¤Î¥Õ¥©¥ó¥È¤Ï¥°¥ë¡¼¥×¤«¤é¼è¤ê½ü¤«¤ì¤ë¡£
 
-    $LAYOUTER_NAME ¤Ï @c Mnil ¤Ç¤¢¤ë¤«¡¢@ref flt 
+    $LAYOUTER_NAME ¤Ï @c Mnil ¤Ç¤¢¤ë¤«¡¢@ref mdbFLT 
     ¡Ê¥Õ¥©¥ó¥È¥ì¥¤¥¢¥¦¥È¥Æ¡¼¥Ö¥ë¡Ë¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£¥·¥ó¥Ü¥ë¤Ç¤¢¤ì¤Ð¡¢$FONT ¤òÍѤ¤¤Æ
     M-text ¤òɽ¼¨¤¹¤ëºÝ¤Ë¤Ï¡¢¤½¤Î¥Õ¥©¥ó¥È¥ì¥¤¥¢¥¦¥È¥Æ¡¼¥Ö¥ë¤ò»È¤Ã¤Æʸ»úÎ󤫤饰¥ê¥Õ¥³¡¼¥ÉÎó¤òÀ¸À®¤¹¤ë¡£
 
@@ -903,31 +1245,13 @@ mfontset_modify_entry (MFontset *fontset,
                       MFont *spec, MSymbol layouter_name,
                       int how)
 {
-  MPlist *per_lang, *plist[3], *pl;
+  MPlist *per_lang, *plist[3];
   MFont *font = NULL;
   int i;
 
   if (fontset->mdb)
     load_fontset_contents (fontset);
 
-  if (! fontset->font_spec_list)
-    fontset->font_spec_list = mplist ();
-  else
-    MPLIST_DO (pl, fontset->font_spec_list)
-      {
-       if (! memcmp (MPLIST_VAL (pl), spec, sizeof (MFont)))
-         {
-           font = MPLIST_VAL (pl);
-           break;
-         }
-      }
-  if (! font)
-    {
-      font = mfont ();
-      *font = *spec;
-      mplist_add (fontset->font_spec_list, Mt, font);
-    }
-
   i = 0;
   if (script != Mnil)
     {
@@ -957,12 +1281,18 @@ mfontset_modify_entry (MFontset *fontset,
     layouter_name = Mt;
   for (i--; i >= 0; i--)
     {
+      font = mfont_copy (spec);
+      font->type = MFONT_TYPE_SPEC;
       if (how == 1)
        mplist_push (plist[i], layouter_name, font);
       else if (how == -1)
        mplist_add (plist[i], layouter_name, font);
       else
        {
+         MPlist *pl;
+
+         MPLIST_DO (pl, plist[i])
+           free (MPLIST_VAL (pl));
          mplist_set (plist[i], Mnil, NULL);
          mplist_add (plist[i], layouter_name, font);
        }
@@ -1076,10 +1406,8 @@ mfontset_lookup (MFontset *fontset,
     }
   if (script != Mnil)
     {
-      if (! fontset->per_script)
-       return plist;
-      pl = mplist_get (fontset->per_script, script);
-      if (! pl)
+      pl = get_per_script (fontset, script);
+      if (MPLIST_TAIL_P (pl))
        return plist;
       if (language == Mt)
        {
@@ -1122,17 +1450,19 @@ mfontset_lookup (MFontset *fontset,
 /***en
     @brief Dump a fontset.
 
-    The mdebug_dump_fontset () function prints fontset $FONTSET in a human readable
-    way to the stderr.  $INDENT specifies how many columns to indent
-    the lines but the first one.
+    The mdebug_dump_fontset () function prints fontset $FONTSET in a
+    human readable way to the stderr or to what specified by the
+    environment variable MDEBUG_OUTPUT_FILE.  $INDENT specifies how
+    many columns to indent the lines but the first one.
 
     @return
     This function returns $FONTSET.  */
 /***ja
     @brief ¥Õ¥©¥ó¥È¥»¥Ã¥È¤ò¥À¥ó¥×¤¹¤ë.
 
-    ´Ø¿ô mdebug_dump_face () ¤Ï¥Õ¥©¥ó¥È¥»¥Ã¥È $FONTSET ¤ò stderr 
-    ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£ $INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
+    ´Ø¿ô mdebug_dump_face () ¤Ï¥Õ¥©¥ó¥È¥»¥Ã¥È $FONTSET ¤òɸ½à¥¨¥é¡¼½ÐÎÏ
+    ¤â¤·¤¯¤Ï´Ä¶­ÊÑ¿ô MDEBUG_DUMP_FONT ¤Ç»ØÄꤵ¤ì¤¿¥Õ¥¡¥¤¥ë¤Ë¿Í´Ö¤Ë²ÄÆÉ
+    ¤Ê·Á¤Ç½ÐÎϤ¹¤ë¡£ $INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
 
     @return
     ¤³¤Î´Ø¿ô¤Ï $FONTSET ¤òÊÖ¤¹¡£  */
@@ -1146,47 +1476,50 @@ mdebug_dump_fontset (MFontset *fontset, int indent)
   memset (prefix, 32, indent);
   prefix[indent] = 0;
 
-  fprintf (stderr, "(fontset %s", fontset->name->name);
+  fprintf (mdebug__output, "(fontset %s", fontset->name->name);
   if (fontset->per_script)
     MPLIST_DO (plist, fontset->per_script)
       {
-       fprintf (stderr, "\n  %s(%s", prefix, MPLIST_KEY (plist)->name);
+       fprintf (mdebug__output, "\n  %s(%s", prefix, MPLIST_KEY (plist)->name);
        MPLIST_DO (pl, MPLIST_PLIST (plist))
          {
-           fprintf (stderr, "\n    %s(%s", prefix, MPLIST_KEY (pl)->name);
+           fprintf (mdebug__output, "\n    %s(%s", prefix,
+                    MPLIST_KEY (pl)->name);
            MPLIST_DO (p, MPLIST_PLIST (pl))
              {
-               fprintf (stderr, "\n      %s(%s ", prefix,
+               fprintf (mdebug__output, "\n      %s(0x%X %s ", prefix,
+                        (unsigned) MPLIST_VAL (p),
                         MPLIST_KEY (p)->name);
                mdebug_dump_font (MPLIST_VAL (p));
-               fprintf (stderr, ")");
+               fprintf (mdebug__output, ")");
              }
-           fprintf (stderr, ")");
+           fprintf (mdebug__output, ")");
          }
-       fprintf (stderr, ")");
+       fprintf (mdebug__output, ")");
       }
   if (fontset->per_charset)
     MPLIST_DO (pl, fontset->per_charset)
       {
-       fprintf (stderr, "\n  %s(%s", prefix, MPLIST_KEY (pl)->name);
+       fprintf (mdebug__output, "\n  %s(%s", prefix, MPLIST_KEY (pl)->name);
        MPLIST_DO (p, MPLIST_PLIST (pl))
          {
-           fprintf (stderr, "\n    %s(%s ", prefix, MPLIST_KEY (p)->name);
+           fprintf (mdebug__output, "\n    %s(%s ", prefix,
+                    MPLIST_KEY (p)->name);
            mdebug_dump_font (MPLIST_VAL (p));
-           fprintf (stderr, ")");
+           fprintf (mdebug__output, ")");
          }
-       fprintf (stderr, ")");
+       fprintf (mdebug__output, ")");
       }
 
   if (fontset->fallback)
     MPLIST_DO (p, fontset->fallback)
       {
-       fprintf (stderr, "\n  %s(%s ", prefix, MPLIST_KEY (p)->name);
+       fprintf (mdebug__output, "\n  %s(%s ", prefix, MPLIST_KEY (p)->name);
        mdebug_dump_font (MPLIST_VAL (p));
-       fprintf (stderr, ")");
+       fprintf (mdebug__output, ")");
       }
 
-  fprintf (stderr, ")");
+  fprintf (mdebug__output, ")");
   return fontset;
 }