(describe-property-list): Sync to HEAD.
[bpt/emacs.git] / src / fontset.c
dissimilarity index 78%
index d1819cc..e6dcc08 100644 (file)
-/* Fontset handler.
-   Copyright (C) 1995, 1997 Electrotechnical Laboratory, JAPAN.
-   Licensed to the Free Software Foundation.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-#include <config.h>
-#if HAVE_ALLOCA_H
-#include <alloca.h>
-#endif /* HAVE_ALLOCA_H */ 
-#include "lisp.h"
-#include "charset.h"
-#include "ccl.h"
-#include "fontset.h"
-#include "frame.h"
-
-Lisp_Object Vglobal_fontset_alist;
-Lisp_Object Vfont_encoding_alist;
-Lisp_Object Vuse_default_ascent;
-Lisp_Object Valternative_fontname_alist;
-Lisp_Object Vfontset_alias_alist;
-Lisp_Object Vhighlight_wrong_size_font;
-Lisp_Object Vclip_large_size_font;
-
-/* Used as a temporary in macro FS_LOAD_FONT.  */
-int font_idx_temp;
-
-/* We had better have our own strcasecmp function because some system
-   doesn't have it.  */
-static char my_strcasetbl[256];
-
-/* Compare two strings S0 and S1 while ignoring differences in case.
-   Return 1 if they differ, else return 0.  */
-static int
-my_strcasecmp (s0, s1)
-     unsigned char *s0, *s1;
-{
-  while (*s0)
-    if (my_strcasetbl[*s0++] != my_strcasetbl[*s1++]) return 1;
-  return (int) *s1;
-}
-
-/* The following six are window system dependent functions.  See
-   the comments in src/fontset.h for more detail.  */
-
-/* Return a pointer to struct font_info of font FONT_IDX of frame F.  */
-struct font_info *(*get_font_info_func) (/* FRAME_PTR f; int font_idx */);
-
-/* Return a list of font names which matches PATTERN.  See the document of
-   `x-list-fonts' for more detail.  */
-Lisp_Object (*list_fonts_func) (/* Lisp_Object pattern, face, frame, width */);
-
-/* Load a font named NAME for frame F and return a pointer to the
-   information of the loaded font.  If loading is failed, return 0.  */
-struct font_info *(*load_font_func) (/* FRAME_PTR f; char *name */);
-
-/* Return a pointer to struct font_info of a font named NAME for frame F.  */
-struct font_info *(*query_font_func) (/* FRAME_PTR f; char *name */);
-
-/* Additional function for setting fontset or changing fontset
-   contents of frame F.  */
-void (*set_frame_fontset_func) (/* FRAME_PTR f; Lisp_Object arg, oldval */);
-
-/* Check if any window system is used now.  */
-void (*check_window_system_func) ();
-
-struct fontset_data *
-alloc_fontset_data ()
-{
-  struct fontset_data *fontset_data
-    = (struct fontset_data *) xmalloc (sizeof (struct fontset_data));
-
-  bzero (fontset_data, sizeof (struct fontset_data));
-
-  return fontset_data;
-}
-
-void
-free_fontset_data (fontset_data)
-     struct fontset_data *fontset_data;
-{
-  int i;
-
-  for (i = 0; i < fontset_data->n_fontsets; i++)
-    {
-      int j;
-
-      xfree (fontset_data->fontset_table[i]->name);
-      for (j = 0; j <= MAX_CHARSET; j++)
-       if (fontset_data->fontset_table[i]->fontname[j])
-         xfree (fontset_data->fontset_table[i]->fontname[j]);
-      xfree (fontset_data->fontset_table[i]);
-    }
-  xfree (fontset_data->fontset_table);
-
-  xfree (fontset_data);
-}
-
-/* Load a font named FONTNAME for displaying CHARSET on frame F.
-   All fonts for frame F is stored in a table pointed by FONT_TABLE.
-   Return a pointer to the struct font_info of the loaded font.
-   If loading fails, return 0;
-   If FONTNAME is NULL, the name is taken from the information of FONTSET.
-   If FONTSET is given, try to load a font whose size matches that of
-   FONTSET, and, the font index is stored in the table for FONTSET.
-
-   If you give FONTSET argument, don't call this function directry,
-   instead call macro FS_LOAD_FONT with the same argument.  */
-
-struct font_info *
-fs_load_font (f, font_table, charset, fontname, fontset)
-     FRAME_PTR f;
-     struct font_info *font_table;
-     int charset, fontset;
-     char *fontname;
-{
-  Lisp_Object font_list;
-  Lisp_Object list, elt;
-  int font_idx;
-  int size = 0;
-  struct fontset_info *fontsetp = 0;
-  struct font_info *fontp;
-
-  if (fontset >= 0 && fontset < FRAME_FONTSET_DATA (f)->n_fontsets)
-    {
-      fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
-      font_idx = fontsetp->font_indexes[charset];
-      if (font_idx >= 0)
-       /* We have already loaded a font.  */
-       return font_table + font_idx;
-      else if (font_idx == FONT_NOT_FOUND)
-       /* We have already tried loading a font and failed.  */
-       return 0;
-      if (!fontname)
-       fontname = fontsetp->fontname[charset];
-    }
-
-  if (!fontname)
-    /* No way to get fontname.  */
-    return 0;
-
-  /* If CHARSET is not ASCII and FONTSET is specified, we must load a
-     font of appropriate size to be used with other fonts in this
-     fontset.  */
-  if (charset != CHARSET_ASCII && fontsetp)
-    {
-      /* If we have not yet loaded ASCII font of FONTSET, we must load
-        it now to decided the size and height of this fontset.  */
-      if (fontsetp->size == 0)
-       {
-         fontp = fs_load_font (f, font_table, CHARSET_ASCII, 0, fontset);
-         if (!fontp)
-           /* Any fontset should contain avairable ASCII.  */
-           return 0;
-       }
-      /* Now we have surely decided the size of this fontset.  */
-      size = fontsetp->size * CHARSET_WIDTH (charset);
-    }
-
-  fontp = (*load_font_func) (f, fontname, size);
-
-  if (!fontp)
-    {
-      if (fontsetp)
-       fontsetp->font_indexes[charset] = FONT_NOT_FOUND;
-      return 0;
-    }
-
-  /* Fill in fields (CHARSET, ENCODING, and FONT_ENCODER) which are
-     not set by (*load_font_func).  */
-  fontp->charset = charset;
-
-  if (fontp->encoding[1] != FONT_ENCODING_NOT_DECIDED)
-    {
-      /* The font itself tells which code points to be used.  Use this
-        encoding for all other charsets.  */
-      int i;
-
-      fontp->encoding[0] = fontp->encoding[1];
-      for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i <= MAX_CHARSET; i++)
-       fontp->encoding[i] = fontp->encoding[1];
-    }
-  else
-    {
-      /* The font itself doesn't tell which code points to be used.  */
-      int i;
-
-      /* At first, set 1 (means 0xA0..0xFF) as the default.  */
-      fontp->encoding[0] = 1;
-      for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i <= MAX_CHARSET; i++)
-       fontp->encoding[i] = 1;
-      /* Then override them by a specification in Vfont_encoding_alist.  */
-      for (list = Vfont_encoding_alist; CONSP (list); list = XCONS (list)->cdr)
-       {
-         elt = XCONS (list)->car;
-         if (CONSP (elt)
-             && STRINGP (XCONS (elt)->car) && CONSP (XCONS (elt)->cdr)
-             && (fast_c_string_match_ignore_case (XCONS (elt)->car, fontname)
-                 >= 0))
-           {
-             Lisp_Object tmp;
-
-             for (tmp = XCONS (elt)->cdr; CONSP (tmp); tmp = XCONS (tmp)->cdr)
-               if (CONSP (XCONS (tmp)->car)
-                   && ((i = get_charset_id (XCONS (XCONS (tmp)->car)->car))
-                       >= 0)
-                   && INTEGERP (XCONS (XCONS (tmp)->car)->cdr)
-                   && XFASTINT (XCONS (XCONS (tmp)->car)->cdr) < 4)
-                 fontp->encoding[i]
-                   = XFASTINT (XCONS (XCONS (tmp)->car)->cdr);
-           }
-       }
-    }
-
-  fontp->font_encoder = (struct ccl_program *) 0;
-  for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCONS (list)->cdr)
-    {
-      elt = XCONS (list)->car;
-      if (CONSP (elt)
-         && STRINGP (XCONS (elt)->car) && VECTORP (XCONS (elt)->cdr)
-         && fast_c_string_match_ignore_case (XCONS (elt)->car, fontname) >= 0)
-       {
-         fontp->font_encoder
-           = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
-         setup_ccl_program (fontp->font_encoder, XCONS (elt)->cdr);
-         break;
-       }
-    }
-
-  /* If FONTSET is specified, setup various fields of it.  */
-  if (fontsetp)
-    {
-      fontsetp->font_indexes[charset] = fontp->font_idx;
-      if (charset == CHARSET_ASCII)
-       {
-         /* Decide or change the size and height of this fontset.  */
-         if (fontsetp->size == 0)
-           {
-             fontsetp->size = fontp->size;
-             fontsetp->height = fontp->height;
-           }
-         else if (fontsetp->size != fontp->size
-                  || fontsetp->height != fontp->height)
-           {
-             /* When loading ASCII font of the different size from
-                the size of FONTSET, we have to update the size of
-                FONTSET.  Since changing the size of FONTSET may make
-                some fonts already loaded inappropriate to be used in
-                FONTSET, we must delete the record of such fonts.  In
-                that case, we also have to calculate the height of
-                FONTSET from the remaining fonts.  */
-             int i;
-
-             fontsetp->size = fontp->size;
-             fontsetp->height = fontp->height;
-             for (i = CHARSET_ASCII + 1; i <= MAX_CHARSET; i++)
-               {
-                 font_idx = fontsetp->font_indexes[i];
-                 if (font_idx >= 0)
-                   {
-                     struct font_info *fontp2 = font_table + font_idx;
-
-                     if (fontp2->size != fontp->size * CHARSET_WIDTH (i))
-                       fontsetp->font_indexes[i] = FONT_NOT_OPENED;
-                     /* The following code should be disabled until
-                        Emacs supports variable height lines.  */
-#if 0
-                     else if (fontsetp->height < fontp->height)
-                       fontsetp->height = fontp->height;
-#endif
-                   }
-               }
-           }
-       }
-    }
-
-  return fontp;
-}
-
-/* Return ID of the fontset named NAME on frame F.  */
-
-int
-fs_query_fontset (f, name)
-     FRAME_PTR f;
-     char *name;
-{
-  struct fontset_data *fontset_data = FRAME_FONTSET_DATA (f);
-  int i;
-
-  for (i = 0; i < fontset_data->n_fontsets; i++)
-    if (!my_strcasecmp(name, fontset_data->fontset_table[i]->name))
-      return i;
-  return -1;
-}
-
-/* Register a fontset specified by FONTSET_INFO for frame FRAME.
-   Return the fontset ID if successfully registered, else return -1.
-   FONTSET_INFO is a cons of name of the fontset and FONTLIST, where
-   FONTLIST is an alist of charsets vs fontnames.  */
-
-int
-fs_register_fontset (f, fontset_info)
-     FRAME_PTR f;
-     Lisp_Object fontset_info;
-{
-  struct fontset_data *fontset_data = FRAME_FONTSET_DATA (f);
-  Lisp_Object name, fontlist;
-  int fontset;
-  struct fontset_info *fontsetp;
-  int i;
-
-  if (!CONSP (fontset_info)
-      || !STRINGP (XCONS (fontset_info)->car)
-      || !CONSP (XCONS (fontset_info)->cdr))
-    /* Invalid data in FONTSET_INFO.  */
-    return -1;
-
-  name = XCONS (fontset_info)->car;
-  if ((fontset = fs_query_fontset (f, XSTRING (name)->data)) >= 0)
-    /* This fontset already exists on frame F.  */
-    return fontset;
-
-  fontsetp = (struct fontset_info *) xmalloc (sizeof (struct fontset_info));
-
-  fontsetp->name = (char *) xmalloc (XSTRING (name)->size + 1);
-  bcopy(XSTRING (name)->data, fontsetp->name, XSTRING (name)->size + 1);
-
-  fontsetp->size = fontsetp->height = 0;
-
-  for (i = 0; i <= MAX_CHARSET; i++)
-    {
-      fontsetp->fontname[i] = (char *) 0;
-      fontsetp->font_indexes[i] = FONT_NOT_OPENED;
-    }
-
-  for (fontlist = XCONS (fontset_info)->cdr; CONSP (fontlist);
-       fontlist = XCONS (fontlist)->cdr)
-    {
-      Lisp_Object tem = Fcar (fontlist);
-      int charset;
-
-      if (CONSP (tem)
-         && (charset = get_charset_id (XCONS (tem)->car)) >= 0
-         && STRINGP (XCONS (tem)->cdr))
-       {
-         fontsetp->fontname[charset]
-            = (char *) xmalloc (XSTRING (XCONS (tem)->cdr)->size + 1);
-         bcopy (XSTRING (XCONS (tem)->cdr)->data,
-                fontsetp->fontname[charset],
-                XSTRING (XCONS (tem)->cdr)->size + 1);
-       }
-      else
-       /* Broken or invalid data structure.  */
-       return -1;
-    }
-
-  /* Do we need to create the table?  */
-  if (fontset_data->fontset_table_size == 0)
-    {
-      fontset_data->fontset_table_size = 8;
-      fontset_data->fontset_table
-       = (struct fontset_info **) xmalloc (fontset_data->fontset_table_size
-                                           * sizeof (struct fontset_info *));
-    }
-  /* Do we need to grow the table?  */
-  else if (fontset_data->n_fontsets >= fontset_data->fontset_table_size)
-    {
-      fontset_data->fontset_table_size += 8;
-      fontset_data->fontset_table
-       = (struct fontset_info **) xrealloc (fontset_data->fontset_table,
-                                            fontset_data->fontset_table_size
-                                            * sizeof (struct fontset_info *));
-    }
-  fontset = fontset_data->n_fontsets++;
-  fontset_data->fontset_table[fontset] = fontsetp;
-
-  return fontset;
-}
-
-/* Cache data used by fontset_pattern_regexp.  The car part is a
-   pattern string containing at least one wild card, the cdr part is
-   the corresponding regular expression.  */
-static Lisp_Object Vcached_fontset_data;
-
-#define CACHED_FONTSET_NAME (XSTRING (XCONS (Vcached_fontset_data)->car)->data)
-#define CACHED_FONTSET_REGEX (XCONS (Vcached_fontset_data)->cdr)
-
-/* If fontset name PATTERN contains any wild card, return regular
-   expression corresponding to PATTERN.  */
-
-Lisp_Object
-fontset_pattern_regexp (pattern)
-     Lisp_Object pattern;
-{
-  if (!index (XSTRING (pattern)->data, '*')
-      && !index (XSTRING (pattern)->data, '?'))
-    /* PATTERN does not contain any wild cards.  */
-    return Qnil;
-
-  if (!CONSP (Vcached_fontset_data)
-      || strcmp (XSTRING (pattern)->data, CACHED_FONTSET_NAME))
-    {
-      /* We must at first update the cached data.  */
-      char *regex = (char *) alloca (XSTRING (pattern)->size * 2);
-      char *p0, *p1 = regex;
-
-      /* Convert "*" to ".*", "?" to ".".  */
-      *p1++ = '^';
-      for (p0 = (char *) XSTRING (pattern)->data; *p0; p0++)
-       {
-         if (*p0 == '*')
-           {
-             *p1++ = '.';
-             *p1++ = '*';
-           }
-         else if (*p0 == '?')
-           *p1++ == '.';
-         else
-           *p1++ = *p0;
-       }
-      *p1++ = '$';
-      *p1++ = 0;
-
-      Vcached_fontset_data = Fcons (build_string (XSTRING (pattern)->data),
-                                   build_string (regex));
-    }
-
-  return CACHED_FONTSET_REGEX;
-}
-
-DEFUN ("query-fontset", Fquery_fontset, Squery_fontset, 1, 1, 0,
-  "Return a fontset name which matches PATTERN, nil if no matching fontset.\n\
-PATTERN can contain `*' or `?' as a wild card\n\
-just like X's font name matching algorithm allows.")
-  (pattern)
-     Lisp_Object pattern;
-{
-  Lisp_Object regexp, tem;
-
-  (*check_window_system_func) ();
-
-  CHECK_STRING (pattern, 0);
-
-  if (XSTRING (pattern)->size == 0)
-    return Qnil;
-
-  tem = Frassoc (pattern, Vfontset_alias_alist);
-  if (!NILP (tem))
-    return Fcar (tem);
-
-  regexp = fontset_pattern_regexp (pattern);
-
-  for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCONS (tem)->cdr)
-    {
-      Lisp_Object fontset_name = XCONS (XCONS (tem)->car)->car;
-      if (!NILP (regexp))
-       {
-         if (fast_c_string_match_ignore_case (regexp,
-                                              XSTRING (fontset_name)->data)
-             >= 0)
-           return fontset_name;
-       }
-      else
-       {
-         if (!my_strcasecmp (XSTRING (pattern)->data,
-                             XSTRING (fontset_name)->data))
-           return fontset_name;
-       }
-    }
-
-  return Qnil;
-}
-
-Lisp_Object Fframe_char_width ();
-
-/* Return a list of names of available fontsets matching PATTERN on
-   frame F.  If SIZE is not 0, it is the size (maximum bound width) of
-   fontsets to be listed. */
-
-Lisp_Object
-list_fontsets (f, pattern, size)
-     FRAME_PTR f;
-     Lisp_Object pattern;
-     int size;
-{
-  int i;
-  Lisp_Object regexp, val;
-
-  regexp = fontset_pattern_regexp (pattern);
-
-  val = Qnil;
-  for (i = 0; i < FRAME_FONTSET_DATA (f)->n_fontsets; i++)
-    {
-      struct fontset_info *fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[i];
-      int name_matched = 0;
-      int size_matched = 0;
-
-      if (!NILP (regexp))
-       {
-         if (fast_c_string_match_ignore_case (regexp, fontsetp->name) >= 0)
-           name_matched = 1;
-       }
-      else
-       {
-         if (!my_strcasecmp (XSTRING (pattern)->data, fontsetp->name))
-           name_matched = 1;     
-       }
-
-      if (name_matched)
-       {
-         if (!size || fontsetp->size == size)
-           size_matched = 1;
-         else if (fontsetp->size == 0)
-           {
-             /* No font of this fontset has loaded yet.  Try loading
-                one with SIZE.  */
-             int j;
-
-             for (j = 0; j <= MAX_CHARSET; j++)
-               if (fontsetp->fontname[j])
-                 {
-                   if ((*load_font_func) (f, fontsetp->fontname[j], size))
-                     size_matched = 1;
-                   break;
-                 }
-           }
-
-         if (size_matched)
-           val = Fcons (build_string (fontsetp->name), val);
-       }
-    }
-
-  return val;
-}
-
-DEFUN ("new-fontset", Fnew_fontset, Snew_fontset, 2, 2, 0,
-  "Create a new fontset NAME which contains fonts in FONTLIST.\n\
-FONTLIST is an alist of charsets vs corresponding font names.")
-  (name, fontlist)
-     Lisp_Object name, fontlist;
-{
-  Lisp_Object fullname, fontset_info;
-  Lisp_Object tail;
-
-  (*check_window_system_func) ();
-
-  CHECK_STRING (name, 0);
-  CHECK_LIST (fontlist, 1);
-
-  fullname = Fquery_fontset (name);
-  if (!NILP (fullname))
-    error ("Fontset \"%s\" matches the existing fontset \"%s\"",
-          XSTRING (name)->data, XSTRING (fullname)->data);
-
-  /* Check the validity of FONTLIST.  */
-  for (tail = fontlist; CONSP (tail); tail = XCONS (tail)->cdr)
-    {
-      Lisp_Object tem = XCONS (tail)->car;
-      int charset;
-
-      if (!CONSP (tem)
-         || (charset = get_charset_id (XCONS (tem)->car)) < 0
-         || !STRINGP (XCONS (tem)->cdr))
-       error ("Elements of fontlist must be a cons of charset and font name");
-    }
-
-  fontset_info = Fcons (name, fontlist);
-  Vglobal_fontset_alist  = Fcons (fontset_info, Vglobal_fontset_alist);
-
-  /* Register this fontset for all existing frames.  */
-  {
-    Lisp_Object framelist, frame;
-    
-    FOR_EACH_FRAME (framelist, frame)
-      if (!FRAME_TERMCAP_P (XFRAME (frame)))
-       fs_register_fontset (XFRAME (frame), fontset_info);
-  }
-
-  return Qnil;
-}
-
-extern Lisp_Object Fframe_parameters ();
-extern Lisp_Object Qfont;
-Lisp_Object Qfontset;
-
-DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 4, 0,
-  "Set FONTNAME for a font of CHARSET in fontset NAME on frame FRAME.\n\
-If FRAME is omitted or nil, all frames are affected.")
-  (name, charset_symbol, fontname, frame)
-     Lisp_Object name, charset_symbol, fontname, frame;
-{
-  int charset;
-  Lisp_Object fullname, fontlist;
-
-  (*check_window_system_func) ();
-
-  CHECK_STRING (name, 0);
-  CHECK_SYMBOL (charset_symbol, 1);
-  CHECK_STRING (fontname, 2);
-  if (!NILP (frame))
-    CHECK_LIVE_FRAME (frame, 3);
-
-  if ((charset = get_charset_id (charset_symbol)) < 0)
-    error ("Invalid charset: %s", XSYMBOL (charset_symbol)->name->data);
-
-  fullname = Fquery_fontset (name);
-  if (NILP (fullname))
-    error ("Fontset \"%s\" does not exist", XSTRING (name)->data);
-
-  /* If FRAME is not specified, we must, at first, update contents of
-     `global-fontset-alist' for a frame created in the future.  */
-  if (NILP (frame))
-    {
-      Lisp_Object fontset_info = Fassoc (fullname, Vglobal_fontset_alist);
-      Lisp_Object tem = Fassq (charset_symbol, XCONS (fontset_info)->cdr);
-
-      if (NILP (tem))
-       XCONS (fontset_info)->cdr
-         = Fcons (Fcons (charset_symbol, fontname),
-                  XCONS (fontset_info)->cdr);
-      else
-       XCONS (tem)->cdr = fontname;
-    }
-
-  /* Then, update information in the specified frame or all existing
-     frames.  */
-  {
-    Lisp_Object framelist, tem;
-
-    FOR_EACH_FRAME (framelist, tem)
-      if (!FRAME_TERMCAP_P (XFRAME (tem))
-         && (NILP (frame) || EQ (frame, tem)))
-       {
-         FRAME_PTR f = XFRAME (tem);
-         int fontset = fs_query_fontset (f, XSTRING (fullname)->data);
-         struct fontset_info *fontsetp
-           = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
-
-         if (fontsetp->fontname[charset])
-           xfree (fontsetp->fontname[charset]);
-         fontsetp->fontname[charset]
-           = (char *) xmalloc (XSTRING (fontname)->size + 1);
-         bcopy (XSTRING (fontname)->data, fontsetp->fontname[charset],
-                XSTRING (fontname)->size + 1);
-         fontsetp->font_indexes[charset] = FONT_NOT_OPENED;
-
-         if (charset == CHARSET_ASCII)
-           {
-             Lisp_Object font_param = Fassq (Qfont, Fframe_parameters (tem));
-
-             if (set_frame_fontset_func
-                 && !NILP (font_param)
-                 && !strcmp (XSTRING (fullname)->data,
-                             XSTRING (XCONS (font_param)->cdr)->data))
-               /* This fontset is the default fontset on frame TEM.
-                  We may have to resize this frame because of new
-                  ASCII font.  */
-               (*set_frame_fontset_func) (f, fullname, Qnil);
-           }
-       }
-  }
-
-  return Qnil;
-}
-
-DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
-  "Return information about a font named NAME on frame FRAME.\n\
-If FRAME is omitted or nil, use the selected frame.\n\
-The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,\n\
-  HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,\n\
-where\n\
-  OPENED-NAME is the name used for opening the font,\n\
-  FULL-NAME is the full name of the font,\n\
-  CHARSET is the charset displayed by the font,\n\
-  SIZE is the minimum bound width of the font,\n\
-  HEIGHT is the height of the font,\n\
-  BASELINE-OFFSET is the upward offset pixels from ASCII baseline,\n\
-  RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling\n\
-    how to compose characters.\n\
-If the named font is not yet loaded, return nil.")
-  (name, frame)
-     Lisp_Object name, frame;
-{
-  FRAME_PTR f;
-  struct font_info *fontp;
-  Lisp_Object info;
-
-  (*check_window_system_func) ();
-
-  CHECK_STRING (name, 0);
-  if (NILP (frame))
-    f = selected_frame;
-  else
-    {
-      CHECK_LIVE_FRAME (frame, 1);
-      f = XFRAME (frame);
-    }
-
-  if (!query_font_func)
-    error ("Font query function is not supported");
-
-  fontp = (*query_font_func) (f, XSTRING (name)->data);
-  if (!fontp)
-    return Qnil;
-
-  info = Fmake_vector (make_number (7), Qnil);
-
-  XVECTOR (info)->contents[0] = build_string (fontp->name);
-  XVECTOR (info)->contents[1] = build_string (fontp->full_name);
-  XVECTOR (info)->contents[2] = CHARSET_SYMBOL (fontp->charset);
-  XVECTOR (info)->contents[3] = make_number (fontp->size);
-  XVECTOR (info)->contents[4] = make_number (fontp->height);
-  XVECTOR (info)->contents[5] = make_number (fontp->baseline_offset);
-  XVECTOR (info)->contents[6] = make_number (fontp->relative_compose);
-  XVECTOR (info)->contents[7] = make_number (fontp->default_ascent);
-
-  return info;
-}
-
-DEFUN ("fontset-info", Ffontset_info, Sfontset_info, 1, 2, 0,
-  "Return information about a fontset named NAME on frame FRAME.\n\
-If FRAME is omitted or nil, use the selected frame.\n\
-The returned value is a vector of SIZE, HEIGHT, and FONT-LIST,\n\
-where\n\
-  SIZE is the minimum bound width of ASCII font of the fontset,\n\
-  HEIGHT is the height of the tallest font in the fontset, and\n\
-  FONT-LIST is an alist of the format:\n\
-    (CHARSET REQUESTED-FONT-NAME LOADED-FONT-NAME).\n\
-LOADED-FONT-NAME t means the font is not yet loaded, nil means the\n\
-loading failed.")
-  (name, frame)
-     Lisp_Object name, frame;
-{
-  FRAME_PTR f;
-  int fontset;
-  struct fontset_info *fontsetp;
-  Lisp_Object info, val;
-  int i;
-  
-  (*check_window_system_func) ();
-
-  CHECK_STRING(name, 0);
-  if (NILP (frame))
-    f = selected_frame;
-  else
-    {
-      CHECK_LIVE_FRAME (frame, 1);
-      f = XFRAME (frame);
-    }
-
-  fontset = fs_query_fontset (f, XSTRING (name)->data);
-  if (fontset < 0)
-    error ("Fontset \"%s\" does not exist", XSTRING (name)->data);
-
-  info = Fmake_vector (make_number (3), Qnil);
-
-  fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
-
-  XVECTOR (info)->contents[0] = make_number (fontsetp->size);
-  XVECTOR (info)->contents[1] = make_number (fontsetp->height);
-  val = Qnil;
-  for (i = 0; i <= MAX_CHARSET; i++)
-    if (fontsetp->fontname[i])
-      {
-       int font_idx = fontsetp->font_indexes[i];
-       Lisp_Object loaded;
-
-       if (font_idx == FONT_NOT_OPENED)
-         loaded = Qt;
-       else if (font_idx == FONT_NOT_FOUND)
-         loaded = Qnil;
-       else
-         loaded
-           = build_string ((*get_font_info_func) (f, font_idx)->full_name);
-       val = Fcons (Fcons (CHARSET_SYMBOL (i),
-                           Fcons (build_string (fontsetp->fontname[i]),
-                                  Fcons (loaded, Qnil))),
-                    val);
-      }
-  XVECTOR (info)->contents[2] = val;
-  return info;
-}
-
-syms_of_fontset ()
-{
-  int i;
-
-  for (i = 0; i < 256; i++)
-    my_strcasetbl[i] = (i >= 'A' && i <= 'Z') ? i + 'a' - 'A' : i;
-
-  if (!load_font_func)
-    /* Window system initializer should have set proper functions.  */
-    abort ();
-
-  Qfontset = intern ("fontset");
-  staticpro (&Qfontset);
-
-  Vcached_fontset_data = Qnil;
-  staticpro (&Vcached_fontset_data);
-
-  DEFVAR_LISP ("global-fontset-alist", &Vglobal_fontset_alist,
-    "Internal data for fontset.  Not for external use.\n\
-This is an alist associating fontset names with the lists of fonts\n\
- contained in them.\n\
-Newly created frames make their own fontset database from here.");
-  Vglobal_fontset_alist = Qnil;
-
-  DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist,
-    "Alist of fontname patterns vs corresponding encoding info.\n\
-Each element looks like (REGEXP . ENCODING-INFO),\n\
- where ENCODING-INFO is an alist of CHARSET vs ENCODING.\n\
-ENCODING is one of the following integer values:\n\
-       0: code points 0x20..0x7F or 0x2020..0x7F7F are used,\n\
-       1: code points 0xA0..0xFF or 0xA0A0..0xFFFF are used,\n\
-       2: code points 0x20A0..0x7FFF are used,\n\
-       3: code points 0xA020..0xFF7F are used.");
-  Vfont_encoding_alist = Qnil;
-
-  DEFVAR_LISP ("use-default-ascent", &Vuse_default_ascent,
-     "Char table of characters of which ascent values should be ignored.\n\
-If an entry for a character is non-nil, the ascent value of the glyph\n\
-is assumed to be what specified by _MULE_DEFAULT_ASCENT property of a font.");
-  Vuse_default_ascent = Qnil;
-
-  DEFVAR_LISP ("alternative-fontname-alist", &Valternative_fontname_alist,
-     "Alist of fontname vs list of the alternative fontnames.\n\
-When no font can be opened by a fontname, the corresponding\n\
-alternative fontnames are tried.");
-  Valternative_fontname_alist = Qnil;
-
-  DEFVAR_LISP ("fontset-alias-alist", &Vfontset_alias_alist,
-     "Alist of fontset names vs the aliases.");
-  Vfontset_alias_alist = Qnil;
-
-  DEFVAR_LISP ("highlight-wrong-size-font", &Vhighlight_wrong_size_font,
-     "*Non-nil means highlight characters shown in wrong size fonts somehow.\n\
-The way to highlight them depends on window system on which Emacs runs.\n\
-On X window, a rectangle is shown around each such character.");
-  Vhighlight_wrong_size_font = Qt;
-
-  DEFVAR_LISP ("clip-large-size-font", &Vclip_large_size_font,
-     "*Non-nil means characters shown in large size fonts are clipped.\n\
-The height of clipping area is the same as that of an ASCII character.\n\
-The width of the area is the same as that of an ASCII character or\n\
-twice wider than that of an ASCII character depending on\n\
-the width (i.e. column numbers occupied on screen) of the character set\n\
-of the character.\n\
-\n\
-In the case that you only have too large size font for a specific\n\
-charscter set, and clipping characters of the character set makes them\n\
-almost unreadable, you can set this variable to t to see the\n\
-characters in exchage for garbage dots left on your screen.");
-  Vclip_large_size_font = Qt;
-
-  defsubr (&Squery_fontset);
-  defsubr (&Snew_fontset);
-  defsubr (&Sset_fontset_font);
-  defsubr (&Sfont_info);
-  defsubr (&Sfontset_info);
-}
+/* Fontset handler.
+   Copyright (C) 1995, 1997, 2000 Electrotechnical Laboratory, JAPAN.
+     Licensed to the Free Software Foundation.
+   Copyright (C) 2003
+     National Institute of Advanced Industrial Science and Technology (AIST)
+     Registration Number H13PRO009
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* #define FONTSET_DEBUG */
+
+#include <config.h>
+
+#ifdef FONTSET_DEBUG
+#include <stdio.h>
+#endif
+
+#include "lisp.h"
+#include "blockinput.h"
+#include "buffer.h"
+#include "character.h"
+#include "charset.h"
+#include "ccl.h"
+#include "keyboard.h"
+#include "frame.h"
+#include "dispextern.h"
+#include "intervals.h"
+#include "fontset.h"
+#include "window.h"
+
+#undef xassert
+#ifdef FONTSET_DEBUG
+#define xassert(X)     do {if (!(X)) abort ();} while (0)
+#undef INLINE
+#define INLINE
+#else   /* not FONTSET_DEBUG */
+#define xassert(X)     (void) 0
+#endif /* not FONTSET_DEBUG */
+
+EXFUN (Fclear_face_cache, 1);
+
+/* FONTSET
+
+   A fontset is a collection of font related information to give
+   similar appearance (style, etc) of characters.  A fontset has two
+   roles.  One is to use for the frame parameter `font' as if it is an
+   ASCII font.  In that case, Emacs uses the font specified for
+   `ascii' script for the frame's default font.
+
+   Another role, the more important one, is to provide information
+   about which font to use for each non-ASCII character.
+
+   There are two kinds of fontsets; base and realized.  A base fontset
+   is created by `new-fontset' from Emacs Lisp explicitly.  A realized
+   fontset is created implicitly when a face is realized for ASCII
+   characters.  A face is also realized for non-ASCII characters based
+   on an ASCII face.  All of non-ASCII faces based on the same ASCII
+   face share the same realized fontset.
+
+   A fontset object is implemented by a char-table whose default value
+   and parent are always nil.
+
+   An element of a base fontset is a vector of FONT-DEFs which itself
+   is a vector [ FONT-SPEC ENCODING REPERTORY ].
+
+   FONT-SPEC is:
+       [ FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY ]
+   or
+       FONT-NAME
+   where FAMILY, WEIGHT, SLANT, SWIDTH, ADSTYLE, REGISTRY, and
+   FONT-NAME are strings.
+
+   Note: Currently WEIGHT through ADSTYLE are ignored.
+
+   ENCODING is a charset ID that can convert characters to glyph codes
+   of the corresponding font.
+
+   REPERTORY is a charset ID, a char-table, or nil.  If REPERTORY is a
+   charset ID, the repertory of the charset exactly matches with that
+   of the font.  If REPERTORY is a char-table, all characters who have
+   a non-nil value in the table are supported.  If REPERTORY is nil,
+   we consult with the font itself to get the repertory.
+
+   ENCODING and REPERTORY are extracted from the variable
+   Vfont_encoding_alist by using a font name generated from FONT-SPEC
+   (if it is a vector) or FONT-NAME as a matching target.
+
+
+   An element of a realized fontset is nil or t, or has this form:
+
+       [CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID
+        PREFERRED-RFONT-DEF RFONT-DEF0 RFONT-DEF1 ...].
+
+   RFONT-DEFn (i.e. Realized FONT-DEF) has this form:
+
+       [ FACE-ID FONT-INDEX FONT-DEF OPENED-FONT-NAME ]
+
+   RFONT-DEFn is automatically reordered by the current charset
+   priority list.
+
+   The value nil means that we have not yet generated the above vector
+   from the base of the fontset.
+
+   The value t means that no font is available for the corresponding
+   range of characters.
+
+
+   A fontset has 9 extra slots.
+
+   The 1st slot: the ID number of the fontset
+
+   The 2nd slot:
+       base: the name of the fontset
+       realized: nil
+
+   The 3rd slot:
+       base: nil
+       realized: the base fontset
+
+   The 4th slot:
+       base: nil
+       realized: the frame that the fontset belongs to
+
+   The 5th slot:
+       base: the font name for ASCII characters
+       realized: nil
+
+   The 6th slot:
+       base: nil
+       realized: the ID number of a face to use for characters that
+                 has no font in a realized fontset.
+
+   The 7th slot:
+       base: nil
+       realized: Alist of font index vs the corresponding repertory
+       char-table.
+       
+   The 8th slot:
+       base: nil
+       realized: If the base is not the default fontset, a fontset
+       realized from the default fontset, else nil.
+
+   The 9th slot:
+       base: Same as element value (but for fallback fonts).
+       realized: Likewise.
+
+   All fontsets are recorded in the vector Vfontset_table.
+
+
+   DEFAULT FONTSET
+
+   There's a special base fontset named `default fontset' which
+   defines the default font specifications.  When a base fontset
+   doesn't specify a font for a specific character, the corresponding
+   value in the default fontset is used.
+
+   The parent of a realized fontset created for such a face that has
+   no fontset is the default fontset.
+
+
+   These structures are hidden from the other codes than this file.
+   The other codes handle fontsets only by their ID numbers.  They
+   usually use the variable name `fontset' for IDs.  But, in this
+   file, we always use varialbe name `id' for IDs, and name `fontset'
+   for an actual fontset object, i.e., char-table.
+
+*/
+
+/********** VARIABLES and FUNCTION PROTOTYPES **********/
+
+extern Lisp_Object Qfont;
+static Lisp_Object Qfontset;
+static Lisp_Object Qfontset_info;
+static Lisp_Object Qprepend, Qappend;
+
+/* Vector containing all fontsets.  */
+static Lisp_Object Vfontset_table;
+
+/* Next possibly free fontset ID.  Usually this keeps the minimum
+   fontset ID not yet used.  */
+static int next_fontset_id;
+
+/* The default fontset.  This gives default FAMILY and REGISTRY of
+   font for each character.  */
+static Lisp_Object Vdefault_fontset;
+
+Lisp_Object Vfont_encoding_alist;
+Lisp_Object Vuse_default_ascent;
+Lisp_Object Vignore_relative_composition;
+Lisp_Object Valternate_fontname_alist;
+Lisp_Object Vfontset_alias_alist;
+Lisp_Object Vvertical_centering_font_regexp;
+
+/* The following six are declarations of callback functions depending
+   on window system.  See the comments in src/fontset.h for more
+   detail.  */
+
+/* Return a pointer to struct font_info of font FONT_IDX of frame F.  */
+struct font_info *(*get_font_info_func) P_ ((FRAME_PTR f, int font_idx));
+
+/* Return a list of font names which matches PATTERN.  See the documentation
+   of `x-list-fonts' for more details.  */
+Lisp_Object (*list_fonts_func) P_ ((struct frame *f,
+                                   Lisp_Object pattern,
+                                   int size,
+                                   int maxnames));
+
+/* Load a font named NAME for frame F and return a pointer to the
+   information of the loaded font.  If loading is failed, return 0.  */
+struct font_info *(*load_font_func) P_ ((FRAME_PTR f, char *name, int));
+
+/* Return a pointer to struct font_info of a font named NAME for frame F.  */
+struct font_info *(*query_font_func) P_ ((FRAME_PTR f, char *name));
+
+/* Additional function for setting fontset or changing fontset
+   contents of frame F.  */
+void (*set_frame_fontset_func) P_ ((FRAME_PTR f, Lisp_Object arg,
+                                   Lisp_Object oldval));
+
+/* To find a CCL program, fs_load_font calls this function.
+   The argument is a pointer to the struct font_info.
+   This function set the member `encoder' of the structure.  */
+void (*find_ccl_program_func) P_ ((struct font_info *));
+
+Lisp_Object (*get_font_repertory_func) P_ ((struct frame *,
+                                           struct font_info *));
+
+/* Check if any window system is used now.  */
+void (*check_window_system_func) P_ ((void));
+
+
+/* Prototype declarations for static functions.  */
+static Lisp_Object fontset_add P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
+                                   Lisp_Object));
+static Lisp_Object fontset_font P_ ((Lisp_Object, int, struct face *, int));
+static Lisp_Object make_fontset P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
+static Lisp_Object fontset_pattern_regexp P_ ((Lisp_Object));
+static void accumulate_script_ranges P_ ((Lisp_Object, Lisp_Object,
+                                         Lisp_Object));
+static Lisp_Object find_font_encoding P_ ((char *));
+
+static void set_fontset_font P_ ((Lisp_Object, Lisp_Object));
+
+#ifdef FONTSET_DEBUG
+
+/* Return 1 if ID is a valid fontset id, else return 0.  */
+
+static int
+fontset_id_valid_p (id)
+     int id;
+{
+  return (id >= 0 && id < ASIZE (Vfontset_table) - 1);
+}
+
+#endif
+
+
+\f
+/********** MACROS AND FUNCTIONS TO HANDLE FONTSET **********/
+
+/* Return the fontset with ID.  No check of ID's validness.  */
+#define FONTSET_FROM_ID(id) AREF (Vfontset_table, id)
+
+/* Macros to access special values of FONTSET.  */
+#define FONTSET_ID(fontset)            XCHAR_TABLE (fontset)->extras[0]
+
+/* Macros to access special values of (base) FONTSET.  */
+#define FONTSET_NAME(fontset)          XCHAR_TABLE (fontset)->extras[1]
+#define FONTSET_ASCII(fontset)         XCHAR_TABLE (fontset)->extras[4]
+
+/* Macros to access special values of (realized) FONTSET.  */
+#define FONTSET_BASE(fontset)          XCHAR_TABLE (fontset)->extras[2]
+#define FONTSET_FRAME(fontset)         XCHAR_TABLE (fontset)->extras[3]
+#define FONTSET_NOFONT_FACE(fontset)   XCHAR_TABLE (fontset)->extras[5]
+#define FONTSET_REPERTORY(fontset)     XCHAR_TABLE (fontset)->extras[6]
+#define FONTSET_DEFAULT(fontset)       XCHAR_TABLE (fontset)->extras[7]
+
+/* For both base and realized fontset.  */
+#define FONTSET_FALLBACK(fontset)      XCHAR_TABLE (fontset)->extras[8]
+
+#define BASE_FONTSET_P(fontset)                (NILP (FONTSET_BASE (fontset)))
+
+
+/* Return the element of FONTSET for the character C.  If FONTSET is a
+   base fontset other then the default fontset and FONTSET doesn't
+   contain information for C, return the information in the default
+   fontset.  */
+
+#define FONTSET_REF(fontset, c)                \
+  (EQ (fontset, Vdefault_fontset)      \
+   ? CHAR_TABLE_REF (fontset, c)       \
+   : fontset_ref ((fontset), (c)))
+
+static Lisp_Object
+fontset_ref (fontset, c)
+     Lisp_Object fontset;
+     int c;
+{
+  Lisp_Object elt;
+
+  elt = CHAR_TABLE_REF (fontset, c);
+  if (NILP (elt) && ! EQ (fontset, Vdefault_fontset)
+      /* Don't check Vdefault_fontset for a realized fontset.  */
+      && NILP (FONTSET_BASE (fontset)))
+    elt = CHAR_TABLE_REF (Vdefault_fontset, c);
+  return elt;
+}
+
+
+/* Return the element of FONTSET for the character C, set FROM and TO
+   to the range of characters around C that have the same value as C.
+   If FONTSET is a base fontset other then the default fontset and
+   FONTSET doesn't contain information for C, return the information
+   in the default fontset.  */
+
+#define FONTSET_REF_AND_RANGE(fontset, c, form, to)    \
+  (EQ (fontset, Vdefault_fontset)                      \
+   ? char_table_ref_and_range (fontset, c, &from, &to) \
+   : fontset_ref_and_range (fontset, c, &from, &to))
+
+static Lisp_Object
+fontset_ref_and_range (fontset, c, from, to)
+     Lisp_Object fontset;
+     int c;
+     int *from, *to;
+{
+  Lisp_Object elt;
+
+  elt = char_table_ref_and_range (fontset, c, from, to);
+  if (NILP (elt) && ! EQ (fontset, Vdefault_fontset)
+      /* Don't check Vdefault_fontset for a realized fontset.  */
+      && NILP (FONTSET_BASE (fontset)))
+    {
+      int from1, to1;
+
+      elt = char_table_ref_and_range (Vdefault_fontset, c, &from1, &to1);
+      if (*from < from1)
+       *from = from1;
+      if (*to > to1)
+       *to = to1;
+    }
+  return elt;
+}
+
+
+/* Set elements of FONTSET for characters in RANGE to the value ELT.
+   RANGE is a cons (FROM . TO), where FROM and TO are character codes
+   specifying a range.  */
+
+#define FONTSET_SET(fontset, range, elt)       \
+  Fset_char_table_range ((fontset), (range), (elt))
+
+
+/* Modify the elements of FONTSET for characters in RANGE by replacing
+   with ELT or adding ELT.  RANGE is a cons (FROM . TO), where FROM
+   and TO are character codes specifying a range.  If ADD is nil,
+   replace with ELT, if ADD is `prepend', prepend ELT, otherwise,
+   append ELT.  */
+
+#define FONTSET_ADD(fontset, range, elt, add)                               \
+  (NILP (add)                                                               \
+   ? (NILP (range)                                                          \
+      ? (FONTSET_FALLBACK (fontset) = Fmake_vector (make_number (1), (elt))) \
+      : Fset_char_table_range ((fontset), (range),                          \
+                              Fmake_vector (make_number (1), (elt))))       \
+   : fontset_add ((fontset), (range), (elt), (add)))
+
+static Lisp_Object
+fontset_add (fontset, range, elt, add)
+     Lisp_Object fontset, range, elt, add;
+{
+  Lisp_Object args[2];
+  int idx = (EQ (add, Qappend) ? 0 : 1);
+
+  args[1 - idx] = Fmake_vector (make_number (1), elt);
+
+  if (CONSP (range))
+    {
+      int from = XINT (XCAR (range));
+      int to = XINT (XCDR (range));
+      int from1, to1;
+
+      do {
+       args[idx] = char_table_ref_and_range (fontset, from, &from1, &to1);
+       if (to < to1)
+         to1 = to;
+       char_table_set_range (fontset, from, to1,
+                             NILP (args[idx]) ? args[1 - idx]
+                             : Fvconcat (2, args));
+       from = to1 + 1;
+      } while (from < to);
+    }
+  else
+    {
+      args[idx] = FONTSET_FALLBACK (fontset);
+      FONTSET_FALLBACK (fontset)
+       = NILP (args[idx]) ? args[1 - idx] : Fvconcat (2, args);
+    }
+  return Qnil;
+}
+
+
+/* Update FONTSET_ELEMENT which has this form:
+       [CHARSET-ORDERED-LIST-TICK PREFERRED-CHARSET-ID PREFERRED-RFONT-DEF
+        RFONT-DEF0 RFONT-DEF1 ...].
+   Reorder RFONT-DEFs according to the current order of charset
+   (Vcharset_ordered_list), and update CHARSET-ORDERED-LIST-TICK to
+   the latest value.  */
+
+static void
+reorder_font_vector (fontset_element)
+     Lisp_Object fontset_element;
+{
+  Lisp_Object vec, list, *new_vec;
+  Lisp_Object font_def;
+  int size;
+  int *charset_id_table;
+  int i, idx;
+
+  ASET (fontset_element, 0, make_number (charset_ordered_list_tick));
+  size = ASIZE (fontset_element) - 3;
+  if (size <= 1)
+    /* No need to reorder VEC.  */
+    return;
+  charset_id_table = (int *) alloca (sizeof (int) * size);
+  new_vec = (Lisp_Object *) alloca (sizeof (Lisp_Object) * size);
+
+  /* At first, extract ENCODING (a chaset ID) from each FONT-DEF.
+     FONT-DEF has this form:
+       [FACE-ID FONT-INDEX [ FONT-SPEC ENCODING REPERTORY ]] */
+  for (i = 0; i < size; i++)
+    {
+      font_def = AREF (fontset_element, i + 3);
+      charset_id_table[i] = XINT (AREF (AREF (font_def, 2), 1));
+    }
+
+  /* Then, store FONT-DEFs in NEW_VEC in the correct order.  */
+  for (idx = 0, list = Vcharset_ordered_list;
+       idx < size && CONSP (list); list = XCDR (list))
+    {
+      for (i = 0; i < size; i++)
+       if (charset_id_table[i] == XINT (XCAR (list)))
+         new_vec[idx++] = AREF (fontset_element, i + 3);
+    }
+
+  /* At last, update FONT-DEFs.  */
+  for (i = 0; i < size; i++)
+    ASET (fontset_element, i + 3, new_vec[i]);
+}
+
+
+/* Load a font matching the font related attributes in FACE->lface and
+   font pattern in FONT_DEF of FONTSET, and return an index of the
+   font.  FONT_DEF has this form:
+       [ FONT-SPEC ENCODING REPERTORY ]
+   If REPERTORY is nil, generate a char-table representing the font
+   repertory by looking into the font itself.  */
+
+static int
+load_font_get_repertory (f, face, font_def, fontset)
+     FRAME_PTR f;
+     struct face *face;
+     Lisp_Object font_def;
+     Lisp_Object fontset;
+{
+  char *font_name;
+  struct font_info *font_info;
+  int charset;
+
+  font_name = choose_face_font (f, face->lface, AREF (font_def, 0), NULL);
+  charset = XINT (AREF (font_def, 1));
+  if (! (font_info = fs_load_font (f, font_name, charset)))
+    return -1;
+
+  if (NILP (AREF (font_def, 2))
+      && NILP (Fassq (make_number (font_info->font_idx),
+                     FONTSET_REPERTORY (fontset))))
+    {
+      /* We must look into the font to get the correct repertory as a
+        char-table.  */
+      Lisp_Object repertory;
+
+      repertory = (*get_font_repertory_func) (f, font_info);
+      FONTSET_REPERTORY (fontset)
+       = Fcons (Fcons (make_number (font_info->font_idx), repertory),
+                FONTSET_REPERTORY (fontset));
+    }
+       
+  return font_info->font_idx;
+}
+
+
+/* Return RFONT-DEF (vector) in the realized fontset FONTSET for the
+   character C.  If the corresponding font is not yet opened, open it
+   (if FACE is not NULL) or return Qnil (if FACE is NULL).
+   If no proper font is found for C, return Qnil.  */
+
+static Lisp_Object
+fontset_font (fontset, c, face, id)
+     Lisp_Object fontset;
+     int c;
+     struct face *face;
+     int id;
+{
+  Lisp_Object base_fontset, elt, vec;
+  int i, from, to;
+  int font_idx;
+  FRAME_PTR f = XFRAME (FONTSET_FRAME (fontset));
+
+  base_fontset = FONTSET_BASE (fontset);
+  vec = CHAR_TABLE_REF (fontset, c);
+  if (EQ (vec, Qt))
+    goto try_fallback;
+
+  if (NILP (vec))
+    {
+      /* We have not yet decided a face for C.  */
+      Lisp_Object range;
+
+      if (! face)
+       return Qnil;
+      elt = FONTSET_REF_AND_RANGE (base_fontset, c, from, to);
+      range = Fcons (make_number (from), make_number (to));
+      if (NILP (elt))
+       {
+         /* Record that we have no font for characters of this
+            range.  */
+         vec = Qt;
+         FONTSET_SET (fontset, range, vec);
+         goto try_fallback;
+       }
+      /* Build a vector [ -1 -1 nil NEW-ELT0 NEW-ELT1 NEW-ELT2 ... ],
+        where the first -1 is to force reordering of NEW-ELTn,
+        NEW-ETLn is [nil nil AREF (elt, n) nil].  */
+      vec = Fmake_vector (make_number (ASIZE (elt) + 3), make_number (-1));
+      ASET (vec, 2, Qnil);
+      for (i = 0; i < ASIZE (elt); i++)
+       {
+         Lisp_Object tmp;
+
+         tmp = Fmake_vector (make_number (4), Qnil);
+         ASET (tmp, 2, AREF (elt, i));
+         ASET (vec, 3 + i, tmp);
+       }
+      /* Then store it in the fontset.  */
+      FONTSET_SET (fontset, range, vec);
+    }
+
+ retry:
+  if (XINT (AREF (vec, 0)) != charset_ordered_list_tick)
+    /* The priority of charsets is changed after we selected a face
+       for C last time.  */
+    reorder_font_vector (vec);
+
+  if (id < 0)
+    i = 3;
+  else if (id == XFASTINT (AREF (vec, 1)))
+    i = 2;
+  else
+    {
+      ASET (vec, 1, make_number (id));
+      for (i = 3; i < ASIZE (vec); i++)
+       if (id == XFASTINT (AREF (AREF (AREF (vec, i), 2), 1)))
+         break;
+      if (i < ASIZE (vec))
+       {
+         ASET (vec, 2, AREF (vec, i));
+         i = 2;
+       }
+      else
+       {
+         ASET (vec, 2, Qnil);
+         i = 3;
+       }
+    }
+
+  /* Find the first available font in the vector of RFONT-DEF.  */
+  for (; i < ASIZE (vec); i++)
+    {
+      Lisp_Object font_def;
+
+      elt = AREF (vec, i);
+      if (NILP (elt))
+       continue;
+      /* ELT == [ FACE-ID FONT-INDEX FONT-DEF OPENED-FONT-NAME ] */
+      if (INTEGERP (AREF (elt, 1)) && XINT (AREF (elt, 1)) < 0)
+       /* We couldn't open this font last time.  */
+       continue;
+
+      if (!face && NILP (AREF (elt, 1)))
+       /* We have not yet opened the font.  */
+       return Qnil;
+
+      font_def = AREF (elt, 2);
+      /* FONT_DEF == [ FONT-SPEC ENCODING REPERTORY ] */
+      if (INTEGERP (AREF (font_def, 2)))
+       {
+         /* The repertory is specified by charset ID.  */
+         struct charset *charset
+           = CHARSET_FROM_ID (XINT (AREF (font_def, 2)));
+
+         if (! CHAR_CHARSET_P (c, charset))
+           /* This font can't display C.  */
+           continue;
+       }
+      else if (CHAR_TABLE_P (AREF (font_def, 2)))
+       {
+         /* The repertory is specified by a char table.  */
+         if (NILP (CHAR_TABLE_REF (AREF (font_def, 2), c)))
+           /* This font can't display C.  */
+           continue;
+       }
+      else
+       {
+         Lisp_Object slot;
+
+         if (! INTEGERP (AREF (elt, 1)))
+           {
+             /* We have not yet opened a font matching this spec.
+                Open the best matching font now and register the
+                repertory.  */
+             struct font_info *font_info;
+
+             font_idx = load_font_get_repertory (f, face, font_def, fontset);
+             ASET (elt, 1, make_number (font_idx));
+             if (font_idx < 0)
+               /* This means that we couldn't find a font matching
+                  FONT_DEF.  */
+               continue;
+             font_info = (*get_font_info_func) (f, font_idx);
+             ASET (elt, 3, build_string (font_info->full_name));
+           }
+
+         slot = Fassq (AREF (elt, 1), FONTSET_REPERTORY (fontset));
+         xassert (CONSP (slot));
+         if (NILP (CHAR_TABLE_REF (XCDR (slot), c)))
+           /* This font can't display C.  */
+           continue;
+       }
+
+      /* Now we have decided to use this font spec to display C.  */
+      if (! INTEGERP (AREF (elt, 1)))
+       {
+         /* But not yet opened the best matching font.  */
+         struct font_info *font_info;
+
+         font_idx = load_font_get_repertory (f, face, font_def, fontset);
+         ASET (elt, 1, make_number (font_idx));
+         if (font_idx < 0)
+           /* Can't open it.  Try the other one.  */
+           continue;
+         font_info = (*get_font_info_func) (f, font_idx);
+         ASET (elt, 3, build_string (font_info->full_name));
+       }
+
+      /* Now we have the opened font.  */
+      return elt;
+    }
+
+ try_fallback:
+  if (! EQ (vec, FONTSET_FALLBACK (fontset)))
+    {
+      vec = FONTSET_FALLBACK (fontset);
+      if (VECTORP (vec))
+       goto retry;
+      if (EQ (vec, Qt))
+       goto try_default;
+      elt = FONTSET_FALLBACK (base_fontset);
+      if (! NILP (elt))
+       {
+         vec = Fmake_vector (make_number (ASIZE (elt) + 3), make_number (-1));
+         ASET (vec, 2, Qnil);
+         for (i = 0; i < ASIZE (elt); i++)
+           {
+             Lisp_Object tmp;
+
+             tmp = Fmake_vector (make_number (4), Qnil);
+             ASET (tmp, 2, AREF (elt, i));
+             ASET (vec, 3 + i, tmp);
+           }
+         FONTSET_FALLBACK (fontset) = vec;       
+         goto retry;
+       }
+      /* Record that this fontset has no fallback fonts.  */
+      FONTSET_FALLBACK (fontset) = Qt;
+    }
+
+  /* Try the default fontset.  */
+ try_default:
+  if (! EQ (base_fontset, Vdefault_fontset))
+    {
+      if (NILP (FONTSET_DEFAULT (fontset)))
+       FONTSET_DEFAULT (fontset)
+         = make_fontset (FONTSET_FRAME (fontset), Qnil, Vdefault_fontset);
+      return fontset_font (FONTSET_DEFAULT (fontset), c, face, id);
+    }
+  return Qnil;
+}
+
+
+/* Return a newly created fontset with NAME.  If BASE is nil, make a
+   base fontset.  Otherwise make a realized fontset whose base is
+   BASE.  */
+
+static Lisp_Object
+make_fontset (frame, name, base)
+     Lisp_Object frame, name, base;
+{
+  Lisp_Object fontset;
+  int size = ASIZE (Vfontset_table);
+  int id = next_fontset_id;
+
+  /* Find a free slot in Vfontset_table.  Usually, next_fontset_id is
+     the next available fontset ID.  So it is expected that this loop
+     terminates quickly.  In addition, as the last element of
+     Vfontset_table is always nil, we don't have to check the range of
+     id.  */
+  while (!NILP (AREF (Vfontset_table, id))) id++;
+
+  if (id + 1 == size)
+    {
+      /* We must grow Vfontset_table.  */
+      Lisp_Object tem;
+      int i;
+
+      tem = Fmake_vector (make_number (size + 32), Qnil);
+      for (i = 0; i < size; i++)
+       AREF (tem, i) = AREF (Vfontset_table, i);
+      Vfontset_table = tem;
+    }
+
+  fontset = Fmake_char_table (Qfontset, Qnil);
+
+  FONTSET_ID (fontset) = make_number (id);
+  if (NILP (base))
+    {
+      FONTSET_NAME (fontset) = name;
+    }
+  else
+    {
+      FONTSET_NAME (fontset) = Qnil;
+      FONTSET_FRAME (fontset) = frame;
+      FONTSET_BASE (fontset) = base;
+    }
+
+  ASET (Vfontset_table, id, fontset);
+  next_fontset_id = id + 1;
+  return fontset;
+}
+
+
+\f
+/********** INTERFACES TO xfaces.c, xfns.c, and dispextern.h **********/
+
+/* Return the name of the fontset who has ID.  */
+
+Lisp_Object
+fontset_name (id)
+     int id;
+{
+  Lisp_Object fontset;
+
+  fontset = FONTSET_FROM_ID (id);
+  return FONTSET_NAME (fontset);
+}
+
+
+/* Return the ASCII font name of the fontset who has ID.  */
+
+Lisp_Object
+fontset_ascii (id)
+     int id;
+{
+  Lisp_Object fontset, elt;
+
+  fontset= FONTSET_FROM_ID (id);
+  elt = FONTSET_ASCII (fontset);
+  /* It is assured that ELT is always a string (i.e. fontname
+     pattern).  */
+  return elt;
+}
+
+
+/* Free fontset of FACE defined on frame F.  Called from
+   free_realized_face.  */
+
+void
+free_face_fontset (f, face)
+     FRAME_PTR f;
+     struct face *face;
+{
+  Lisp_Object fontset;
+
+  fontset = AREF (Vfontset_table, face->fontset);
+  xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
+  xassert (f == XFRAME (FONTSET_FRAME (fontset)));
+  ASET (Vfontset_table, face->fontset, Qnil);
+  if (face->fontset < next_fontset_id)
+    next_fontset_id = face->fontset;
+  if (! NILP (FONTSET_DEFAULT (fontset)))
+    {
+      int id = XINT (FONTSET_ID (FONTSET_DEFAULT (fontset)));
+      
+      fontset = AREF (Vfontset_table, id);
+      xassert (!NILP (fontset) && ! BASE_FONTSET_P (fontset));
+      xassert (f == XFRAME (FONTSET_FRAME (fontset)));
+      ASET (Vfontset_table, id, Qnil);
+      if (id < next_fontset_id)
+       next_fontset_id = face->fontset;
+    }
+}
+
+
+/* Return 1 iff FACE is suitable for displaying character C.
+   Otherwise return 0.  Called from the macro FACE_SUITABLE_FOR_CHAR_P
+   when C is not an ASCII character.  */
+
+int
+face_suitable_for_char_p (face, c)
+     struct face *face;
+     int c;
+{
+  Lisp_Object fontset, rfont_def;
+
+  fontset = FONTSET_FROM_ID (face->fontset);
+  rfont_def = fontset_font (fontset, c, NULL, -1);
+  return (VECTORP (rfont_def)
+         && INTEGERP (AREF (rfont_def, 0))
+         && face->id == XINT (AREF (rfont_def, 0)));
+}
+
+
+/* Return ID of face suitable for displaying character C on frame F.
+   FACE must be reazlied for ASCII characters in advance.  Called from
+   the macro FACE_FOR_CHAR.  */
+
+int
+face_for_char (f, face, c, pos, object)
+     FRAME_PTR f;
+     struct face *face;
+     int c, pos;
+     Lisp_Object object;
+{
+  Lisp_Object fontset, charset, rfont_def;
+  int face_id;
+  int id;
+
+  if (ASCII_CHAR_P (c))
+    return face->ascii_face->id;
+
+  xassert (fontset_id_valid_p (face->fontset));
+  fontset = FONTSET_FROM_ID (face->fontset);
+  xassert (!BASE_FONTSET_P (fontset));
+  if (pos < 0)
+    id = -1;
+  else
+    {
+      charset = Fget_char_property (make_number (pos), Qcharset, object);
+      if (NILP (charset))
+       id = -1;
+      else if (CHARSETP (charset))
+       id = XINT (CHARSET_SYMBOL_ID (charset));
+    }
+  rfont_def = fontset_font (fontset, c, face, id);
+  if (VECTORP (rfont_def))
+    {
+      if (NILP (AREF (rfont_def, 0)))
+       {
+         /* We have not yet made a realized face that uses this font.  */
+         int font_idx = XINT (AREF (rfont_def, 1));
+
+         face_id = lookup_non_ascii_face (f, font_idx, face);
+         ASET (rfont_def, 0, make_number (face_id));
+       }
+      return XINT (AREF (rfont_def, 0));
+    }
+
+  if (NILP (FONTSET_NOFONT_FACE (fontset)))
+    {
+      face_id = lookup_non_ascii_face (f, -1, face);
+      FONTSET_NOFONT_FACE (fontset) = make_number (face_id);
+    }
+  return XINT (FONTSET_NOFONT_FACE (fontset));
+}
+
+
+/* Make a realized fontset for ASCII face FACE on frame F from the
+   base fontset BASE_FONTSET_ID.  If BASE_FONTSET_ID is -1, use the
+   default fontset as the base.  Value is the id of the new fontset.
+   Called from realize_x_face.  */
+
+int
+make_fontset_for_ascii_face (f, base_fontset_id, face)
+     FRAME_PTR f;
+     int base_fontset_id;
+     struct face *face;
+{
+  Lisp_Object base_fontset, fontset, frame;
+
+  XSETFRAME (frame, f);
+  if (base_fontset_id >= 0)
+    {
+      base_fontset = FONTSET_FROM_ID (base_fontset_id);
+      if (!BASE_FONTSET_P (base_fontset))
+       base_fontset = FONTSET_BASE (base_fontset);
+      xassert (BASE_FONTSET_P (base_fontset));
+      if (! BASE_FONTSET_P (base_fontset))
+       abort ();
+    }
+  else
+    base_fontset = Vdefault_fontset;
+
+  fontset = make_fontset (frame, Qnil, base_fontset);
+  {
+    Lisp_Object elt, rfont_def;
+
+    elt = FONTSET_REF (base_fontset, 0);
+    xassert (VECTORP (elt) && ASIZE (elt) > 0);
+    rfont_def = Fmake_vector (make_number (4), Qnil);
+    ASET (rfont_def, 0, make_number (face->id));
+    ASET (rfont_def, 1, make_number (face->font_info_id));
+    ASET (rfont_def, 2, AREF (elt, 0));
+    ASET (rfont_def, 3, build_string (face->font_name));
+    elt = Fmake_vector (make_number (4), Qnil);
+    ASET (elt, 0, make_number (charset_ordered_list_tick));
+    ASET (elt, 1, make_number (charset_ascii));
+    ASET (elt, 2, rfont_def);
+    ASET (elt, 3, rfont_def);
+    char_table_set_range (fontset, 0, 127, elt);
+  }
+  return XINT (FONTSET_ID (fontset));
+}
+
+
+#if defined(WINDOWSNT) && defined (_MSC_VER)
+#pragma optimize("", off)
+#endif
+
+/* Load a font named FONTNAME on frame F.  Return a pointer to the
+   struct font_info of the loaded font.  If loading fails, return
+   NULL.  CHARSET is an ID of charset to encode characters for this
+   font.  If it is -1, find one from Vfont_encoding_alist.  */
+
+struct font_info *
+fs_load_font (f, fontname, charset)
+     FRAME_PTR f;
+     char *fontname;
+     int charset;
+{
+  struct font_info *fontp;
+
+  if (!fontname)
+    /* No way to get fontname.  */
+    return NULL;
+
+  fontp = (*load_font_func) (f, fontname, 0);
+  if (! fontp || fontp->charset >= 0)
+    return fontp;
+
+  fontname = fontp->full_name;
+
+  if (charset < 0)
+    {
+      Lisp_Object charset_symbol;
+
+      charset_symbol = find_font_encoding (fontname);
+      if (CONSP (charset_symbol))
+       charset_symbol = XCAR (charset_symbol);
+      charset = XINT (CHARSET_SYMBOL_ID (charset_symbol));
+    }
+  fontp->charset = charset;
+  fontp->vertical_centering = 0;
+  fontp->font_encoder = NULL;
+
+  if (charset != charset_ascii)
+    {
+      fontp->vertical_centering
+       = (STRINGP (Vvertical_centering_font_regexp)
+          && (fast_c_string_match_ignore_case
+              (Vvertical_centering_font_regexp, fontname) >= 0));
+
+      if (find_ccl_program_func)
+       (*find_ccl_program_func) (fontp);
+    }
+
+  return fontp;
+}
+
+#if defined(WINDOWSNT) && defined (_MSC_VER)
+#pragma optimize("", on)
+#endif
+
+\f
+/* Return ENCODING or a cons of ENCODING and REPERTORY of the font
+   FONTNAME.  ENCODING is a charset symbol that specifies the encoding
+   of the font.  REPERTORY is a charset symbol or nil.  */
+
+
+static Lisp_Object
+find_font_encoding (fontname)
+     char *fontname;
+{
+  Lisp_Object tail, elt;
+
+  for (tail = Vfont_encoding_alist; CONSP (tail); tail = XCDR (tail))
+    {
+      elt = XCAR (tail);
+      if (CONSP (elt)
+         && STRINGP (XCAR (elt))
+         && fast_c_string_match_ignore_case (XCAR (elt), fontname) >= 0
+         && (SYMBOLP (XCDR (elt))
+             ? CHARSETP (XCDR (elt))
+             : CONSP (XCDR (elt)) && CHARSETP (XCAR (XCDR (elt)))))
+       return (XCDR (elt));
+    }
+  /* We don't know the encoding of this font.  Let's assume `ascii'.  */
+  return Qascii;
+}
+
+
+/* Cache data used by fontset_pattern_regexp.  The car part is a
+   pattern string containing at least one wild card, the cdr part is
+   the corresponding regular expression.  */
+static Lisp_Object Vcached_fontset_data;
+
+#define CACHED_FONTSET_NAME (SDATA (XCAR (Vcached_fontset_data)))
+#define CACHED_FONTSET_REGEX (XCDR (Vcached_fontset_data))
+
+/* If fontset name PATTERN contains any wild card, return regular
+   expression corresponding to PATTERN.  */
+
+static Lisp_Object
+fontset_pattern_regexp (pattern)
+     Lisp_Object pattern;
+{
+  if (!index (SDATA (pattern), '*')
+      && !index (SDATA (pattern), '?'))
+    /* PATTERN does not contain any wild cards.  */
+    return Qnil;
+
+  if (!CONSP (Vcached_fontset_data)
+      || strcmp (SDATA (pattern), CACHED_FONTSET_NAME))
+    {
+      /* We must at first update the cached data.  */
+      char *regex = (char *) alloca (SCHARS (pattern) * 2 + 3);
+      char *p0, *p1 = regex;
+
+      /* Convert "*" to ".*", "?" to ".".  */
+      *p1++ = '^';
+      for (p0 = (char *) SDATA (pattern); *p0; p0++)
+       {
+         if (*p0 == '*')
+           {
+             *p1++ = '.';
+             *p1++ = '*';
+           }
+         else if (*p0 == '?')
+           *p1++ = '.';
+         else
+           *p1++ = *p0;
+       }
+      *p1++ = '$';
+      *p1++ = 0;
+
+      Vcached_fontset_data = Fcons (build_string (SDATA (pattern)),
+                                   build_string (regex));
+    }
+
+  return CACHED_FONTSET_REGEX;
+}
+
+/* Return ID of the base fontset named NAME.  If there's no such
+   fontset, return -1.  */
+
+int
+fs_query_fontset (name, regexpp)
+     Lisp_Object name;
+     int regexpp;
+{
+  Lisp_Object tem;
+  int i;
+
+  name = Fdowncase (name);
+  if (!regexpp)
+    {
+      tem = Frassoc (name, Vfontset_alias_alist);
+      if (NILP (tem))
+       tem = Fassoc (name, Vfontset_alias_alist);
+      if (CONSP (tem) && STRINGP (XCAR (tem)))
+       name = XCAR (tem);
+      else
+       {
+         tem = fontset_pattern_regexp (name);
+         if (STRINGP (tem))
+           {
+             name = tem;
+             regexpp = 1;
+           }
+       }
+    }
+
+  for (i = 0; i < ASIZE (Vfontset_table); i++)
+    {
+      Lisp_Object fontset;
+      unsigned char *this_name;
+
+      fontset = FONTSET_FROM_ID (i);
+      if (NILP (fontset)
+         || !BASE_FONTSET_P (fontset))
+       continue;
+
+      this_name = SDATA (FONTSET_NAME (fontset));
+      if (regexpp
+         ? fast_c_string_match_ignore_case (name, this_name) >= 0
+         : !strcmp (SDATA (name), this_name))
+       return i;
+    }
+  return -1;
+}
+
+
+DEFUN ("query-fontset", Fquery_fontset, Squery_fontset, 1, 2, 0,
+       doc: /* Return the name of a fontset that matches PATTERN.
+The value is nil if there is no matching fontset.
+PATTERN can contain `*' or `?' as a wildcard
+just as X font name matching algorithm allows.
+If REGEXPP is non-nil, PATTERN is a regular expression.  */)
+     (pattern, regexpp)
+     Lisp_Object pattern, regexpp;
+{
+  Lisp_Object fontset;
+  int id;
+
+  (*check_window_system_func) ();
+
+  CHECK_STRING (pattern);
+
+  if (SCHARS (pattern) == 0)
+    return Qnil;
+
+  id = fs_query_fontset (pattern, !NILP (regexpp));
+  if (id < 0)
+    return Qnil;
+
+  fontset = FONTSET_FROM_ID (id);
+  return FONTSET_NAME (fontset);
+}
+
+/* Return a list of base fontset names matching PATTERN on frame F.  */
+
+Lisp_Object
+list_fontsets (f, pattern, size)
+     FRAME_PTR f;
+     Lisp_Object pattern;
+     int size;
+{
+  Lisp_Object frame, regexp, val;
+  int id;
+
+  XSETFRAME (frame, f);
+
+  regexp = fontset_pattern_regexp (pattern);
+  val = Qnil;
+
+  for (id = 0; id < ASIZE (Vfontset_table); id++)
+    {
+      Lisp_Object fontset;
+      unsigned char *name;
+
+      fontset = FONTSET_FROM_ID (id);
+      if (NILP (fontset)
+         || !BASE_FONTSET_P (fontset)
+         || !EQ (frame, FONTSET_FRAME (fontset)))
+       continue;
+      name = SDATA (FONTSET_NAME (fontset));
+
+      if (STRINGP (regexp)
+         ? (fast_c_string_match_ignore_case (regexp, name) < 0)
+         : strcmp (SDATA (pattern), name))
+       continue;
+
+      val = Fcons (Fcopy_sequence (FONTSET_NAME (fontset)), val);
+    }
+
+  return val;
+}
+
+
+/* Free all realized fontsets whose base fontset is BASE.  */
+
+static void
+free_realized_fontsets (base)
+     Lisp_Object base;
+{
+#if 0
+  int id;
+
+  /* For the moment, this doesn't work because free_realized_face
+     doesn't remove FACE from a cache.  Until we find a solution, we
+     suppress this code, and simply use Fclear_face_cache even though
+     that is not efficient.  */
+  BLOCK_INPUT;
+  for (id = 0; id < ASIZE (Vfontset_table); id++)
+    {
+      Lisp_Object this = AREF (Vfontset_table, id);
+
+      if (EQ (FONTSET_BASE (this), base))
+       {
+         Lisp_Object tail;
+
+         for (tail = FONTSET_FACE_ALIST (this); CONSP (tail);
+              tail = XCDR (tail))
+           {
+             FRAME_PTR f = XFRAME (FONTSET_FRAME (this));
+             int face_id = XINT (XCDR (XCAR (tail)));
+             struct face *face = FACE_FROM_ID (f, face_id);
+
+             /* Face THIS itself is also freed by the following call.  */
+             free_realized_face (f, face);
+           }
+       }
+    }
+  UNBLOCK_INPUT;
+#else  /* not 0 */
+  Fclear_face_cache (Qt);
+#endif /* not 0 */
+}
+
+
+/* Check validity of NAME as a fontset name and return the
+   corresponding fontset.  If not valid, signal an error.
+   If NAME is t, return Vdefault_fontset.  */
+
+static Lisp_Object
+check_fontset_name (name)
+     Lisp_Object name;
+{
+  int id;
+
+  if (EQ (name, Qt))
+    return Vdefault_fontset;
+
+  CHECK_STRING (name);
+  id = fs_query_fontset (name, 0);
+  if (id < 0)
+    error ("Fontset `%s' does not exist", SDATA (name));
+  return FONTSET_FROM_ID (id);
+}
+
+static void
+accumulate_script_ranges (arg, range, val)
+     Lisp_Object arg, range, val;
+{
+  if (EQ (XCAR (arg), val))
+    {
+      if (CONSP (range))
+       XSETCDR (arg, Fcons (Fcons (XCAR (range), XCDR (range)), XCDR (arg)));
+      else
+       XSETCDR (arg, Fcons (Fcons (range, range), XCDR (arg)));
+    }
+}
+
+
+/* Return an ASCII font name generated from fontset name NAME and
+   ASCII font specification ASCII_SPEC.  NAME is a string conforming
+   to XLFD.  ASCII_SPEC is a vector:
+       [FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY].  */
+
+static INLINE Lisp_Object
+generate_ascii_font_name (name, ascii_spec)
+     Lisp_Object name, ascii_spec;
+{
+  Lisp_Object vec;
+  int i;
+
+  vec = split_font_name_into_vector (name);
+  for (i = FONT_SPEC_FAMILY_INDEX; i <= FONT_SPEC_ADSTYLE_INDEX; i++)
+    if (! NILP (AREF (ascii_spec, i)))
+      ASET (vec, 1 + i, AREF (ascii_spec, i));
+  if (! NILP (AREF (ascii_spec, FONT_SPEC_REGISTRY_INDEX)))
+    ASET (vec, 12, AREF (ascii_spec, FONT_SPEC_REGISTRY_INDEX));
+  return build_font_name_from_vector (vec);
+}
+
+/* Variables referred in set_fontset_font.  They are set before
+   map_charset_chars is called in Fset_fontset_font.  */
+static Lisp_Object font_def_arg, add_arg;
+static int from_arg, to_arg;
+
+/* Callback function for map_charset_chars in Fset_fontset_font.  In
+   FONTSET, set font_def_arg in a fashion specified by add_arg for
+   characters in RANGE while ignoring the range between from_arg and
+   to_arg.  */
+
+static void
+set_fontset_font (fontset, range)
+     Lisp_Object fontset, range;
+{
+  if (from_arg < to_arg)
+    {
+      int from = XINT (XCAR (range)), to = XINT (XCDR (range));
+
+      if (from < from_arg)
+       {
+         if (to > to_arg)
+           {
+             Lisp_Object range2;
+
+             range2 = Fcons (make_number (to_arg), XCDR (range));
+             FONTSET_ADD (fontset, range, font_def_arg, add_arg);
+             to = to_arg;
+           }
+         if (to > from_arg)
+           range = Fcons (XCAR (range), make_number (from_arg));
+       }
+      else if (to <= to_arg)
+       return;
+      else
+       {
+         if (from < to_arg)
+           range = Fcons (make_number (to_arg), XCDR (range));
+       }
+    }
+  FONTSET_ADD (fontset, range, font_def_arg, add_arg);
+}
+
+
+DEFUN ("set-fontset-font", Fset_fontset_font, Sset_fontset_font, 3, 5, 0,
+       doc: /*
+Modify fontset NAME to use FONT-SPEC for TARGET characters.
+
+TARGET may be a cons; (FROM . TO), where FROM and TO are characters.
+In that case, use FONT-SPEC for all characters in the range FROM and
+TO (inclusive).
+
+TARGET may be a script name symbol.  In that case, use FONT-SPEC for
+all characters that belong to the script.
+
+TARGET may be a charset.  In that case, use FONT-SPEC for all
+characters in the charset.
+
+TARGET may be nil.  In that case, use FONT-SPEC for any characters for
+that no FONT-SPEC is specified.
+
+FONT-SPEC may be:
+ * A vector [ FAMILY WEIGHT SLANT WIDTH ADSTYLE REGISTRY ].
+   See the documentation of `set-face-attribute' for the detail of
+   these vector elements;
+ * A cons (FAMILY . REGISTRY), where FAMILY is a font family name and
+   REGISTRY is a font registry name;
+ * A font name string.
+
+Optional 4th argument FRAME, if non-nil, is a frame.  This argument is
+kept for backward compatibility and has no meaning.
+
+Optional 5th argument ADD, if non-nil, specifies how to add FONT-SPEC
+to the font specifications for TARGET previously set.  If it is
+`prepend', FONT-SPEC is prepended.  If it is `append', FONT-SPEC is
+appended.  By default, FONT-SPEC overrides the previous settings.  */)
+     (name, target, font_spec, frame, add)
+     Lisp_Object name, target, font_spec, frame, add;
+{
+  Lisp_Object fontset;
+  Lisp_Object font_def, registry;
+  Lisp_Object encoding, repertory;
+  Lisp_Object range_list;
+  struct charset *charset = NULL;
+
+  fontset = check_fontset_name (name);
+
+  /* The arg FRAME is kept for backward compatibility.  We only check
+     the validity.  */
+  if (!NILP (frame))
+    CHECK_LIVE_FRAME (frame);
+
+  if (VECTORP (font_spec))
+    {
+      int j;
+
+      if (ASIZE (font_spec) != FONT_SPEC_MAX_INDEX)
+       args_out_of_range (make_number (FONT_SPEC_MAX_INDEX),
+                          make_number (ASIZE (font_spec)));
+
+      font_spec = Fcopy_sequence (font_spec);
+      for (j = 0; j < FONT_SPEC_MAX_INDEX - 1; j++)
+       if (! NILP (AREF (font_spec, j)))
+         {
+           CHECK_STRING (AREF (font_spec, j));
+           ASET (font_spec, j, Fdowncase (AREF (font_spec, j)));
+         }
+      /* REGISTRY should not be omitted.  */
+      CHECK_STRING (AREF (font_spec, FONT_SPEC_REGISTRY_INDEX));
+      registry = Fdowncase (AREF (font_spec, FONT_SPEC_REGISTRY_INDEX));
+      ASET (font_spec, FONT_SPEC_REGISTRY_INDEX, registry);
+
+    }
+  else if (CONSP (font_spec))
+    {
+      Lisp_Object family;
+
+      family = XCAR (font_spec);
+      registry = XCDR (font_spec);
+
+      if (! NILP (family))
+       {
+         CHECK_STRING (family);
+         family = Fdowncase (family);
+       }
+      CHECK_STRING (registry);
+      registry = Fdowncase (registry);
+      font_spec = Fmake_vector (make_number (FONT_SPEC_MAX_INDEX), Qnil);
+      ASET (font_spec, FONT_SPEC_FAMILY_INDEX, family);
+      ASET (font_spec, FONT_SPEC_REGISTRY_INDEX, registry);
+    }
+  else
+    {
+      CHECK_STRING (font_spec);
+      font_spec = Fdowncase (font_spec);
+    }
+
+  if (STRINGP (font_spec))
+    encoding = find_font_encoding ((char *) SDATA (font_spec));
+  else
+    encoding = find_font_encoding ((char *) SDATA (registry));
+  if (SYMBOLP (encoding))
+    {
+      CHECK_CHARSET (encoding);
+      encoding = repertory = CHARSET_SYMBOL_ID (encoding);
+    }
+  else
+    {
+      repertory = XCDR (encoding);
+      encoding = XCAR (encoding);
+      CHECK_CHARSET (encoding);
+      encoding = CHARSET_SYMBOL_ID (encoding);
+      if (! NILP (repertory) && SYMBOLP (repertory))
+       {
+         CHECK_CHARSET (repertory);
+         repertory = CHARSET_SYMBOL_ID (repertory);
+       }
+    }
+  font_def = Fmake_vector (make_number (3), font_spec);
+  ASET (font_def, 1, encoding);
+  ASET (font_def, 2, repertory);
+
+  if (CHARACTERP (target))
+    range_list = Fcons (Fcons (target, target), Qnil);
+  else if (CONSP (target))
+    {
+      Lisp_Object from, to;
+
+      from = Fcar (target);
+      to = Fcdr (target);
+      CHECK_CHARACTER (from);
+      CHECK_CHARACTER (to);
+      range_list = Fcons (target, Qnil);
+    }
+  else if (SYMBOLP (target) && !NILP (target))
+    {
+      Lisp_Object script_list;
+      Lisp_Object val;
+
+      range_list = Qnil;
+      script_list = XCHAR_TABLE (Vchar_script_table)->extras[0];
+      if (! NILP (Fmemq (target, script_list)))
+       {
+         val = Fcons (target, Qnil);
+         map_char_table (accumulate_script_ranges, Qnil, Vchar_script_table,
+                         val);
+         range_list = XCDR (val);
+       }
+      if (CHARSETP (target))
+       {
+         if (EQ (target, Qascii))
+           {
+             if (VECTORP (font_spec))
+               font_spec = generate_ascii_font_name (FONTSET_NAME (fontset),
+                                                     font_spec);
+             FONTSET_ASCII (fontset) = font_spec;
+             range_list = Fcons (Fcons (make_number (0), make_number (127)),
+                                 Qnil);
+           }
+         else
+           {
+             CHECK_CHARSET_GET_CHARSET (target, charset);
+           }
+       }
+      else if (NILP (range_list))
+       error ("Invalid script or charset name: %s",
+              SDATA (SYMBOL_NAME (target)));
+    }
+  else if (NILP (target))
+    range_list = Fcons (Qnil, Qnil);
+  else
+    error ("Invalid target for setting a font");
+
+
+  if (charset)
+    {
+      font_def_arg = font_def;
+      add_arg = add;
+      if (NILP (range_list))
+       from_arg = to_arg = 0;
+      else
+       from_arg = XINT (XCAR (XCAR (range_list))),
+         to_arg = XINT (XCDR (XCAR (range_list)));
+
+      map_charset_chars (set_fontset_font, Qnil, fontset, charset,
+                        CHARSET_MIN_CODE (charset),
+                        CHARSET_MAX_CODE (charset));
+    }
+  for (; CONSP (range_list); range_list = XCDR (range_list))
+    FONTSET_ADD (fontset, XCAR (range_list), font_def, add);
+
+  /* Free all realized fontsets whose base is FONTSET.  This way, the
+     specified character(s) are surely redisplayed by a correct
+     font.  */
+  free_realized_fontsets (fontset);
+
+  return Qnil;
+}
+
+
+DEFUN ("new-fontset", Fnew_fontset, Snew_fontset, 2, 2, 0,
+       doc: /* Create a new fontset NAME from font information in FONTLIST.
+
+FONTLIST is an alist of scripts vs the corresponding font specification list.
+Each element of FONTLIST has the form (SCRIPT FONT-SPEC ...), where a
+character of SCRIPT is displayed by a font that matches one of
+FONT-SPEC.
+
+SCRIPT is a symbol that appears in the first extra slot of the
+char-table `char-script-table'.
+
+FONT-SPEC is a vector, a cons, or a string.  See the documentation of
+`set-fontset-font' for the meaning.  */)
+  (name, fontlist)
+     Lisp_Object name, fontlist;
+{
+  Lisp_Object fontset;
+  Lisp_Object val;
+  int id;
+
+  CHECK_STRING (name);
+  CHECK_LIST (fontlist);
+
+  id = fs_query_fontset (name, 0);
+  if (id < 0)
+    {
+      name = Fdowncase (name);
+      val = split_font_name_into_vector (name);
+      if (NILP (val) || NILP (AREF (val, 12)) || NILP (AREF (val, 13)))
+       error ("Fontset name must be in XLFD format");
+      if (strcmp (SDATA (AREF (val, 12)), "fontset"))
+       error ("Registry field of fontset name must be \"fontset\"");
+      Vfontset_alias_alist
+       = Fcons (Fcons (name,
+                       concat2 (concat2 (AREF (val, 12), build_string ("-")),
+                                AREF (val, 13))),
+                Vfontset_alias_alist);
+      ASET (val, 12, build_string ("iso8859-1"));
+      fontset = make_fontset (Qnil, name, Qnil);
+      FONTSET_ASCII (fontset) = build_font_name_from_vector (val);
+    }
+  else
+    {
+      fontset = FONTSET_FROM_ID (id);;
+      free_realized_fontsets (fontset);
+      Fset_char_table_range (fontset, Qt, Qnil);
+    }
+
+  for (; ! NILP (fontlist); fontlist = Fcdr (fontlist))
+    {
+      Lisp_Object elt, script;
+
+      elt = Fcar (fontlist);
+      script = Fcar (elt);
+      elt = Fcdr (elt);
+      if (CONSP (elt) && (NILP (XCDR (elt)) || CONSP (XCDR (elt))))
+       for (; CONSP (elt); elt = XCDR (elt))
+         Fset_fontset_font (name, script, XCAR (elt), Qnil, Qappend);
+      else
+       Fset_fontset_font (name, script, elt, Qnil, Qappend);
+    }
+  return name;
+}
+
+
+/* Alist of automatically created fontsets.  Each element is a cons
+   (FONTNAME . FONTSET-ID).  */
+static Lisp_Object auto_fontset_alist;
+
+int
+new_fontset_from_font_name (Lisp_Object fontname)
+{
+  Lisp_Object val;
+  Lisp_Object name;
+  Lisp_Object vec;
+  int id;
+
+  fontname = Fdowncase (fontname);
+  val = Fassoc (fontname, auto_fontset_alist);
+  if (CONSP (val))
+    return XINT (XCDR (val));
+
+  vec = split_font_name_into_vector (fontname);
+  if ( NILP (vec))
+    vec = Fmake_vector (make_number (14), build_string (""));
+  ASET (vec, 12, build_string ("fontset"));
+  if (NILP (auto_fontset_alist))
+    {
+      ASET (vec, 13, build_string ("startup"));
+      name = build_font_name_from_vector (vec);
+    }
+  else
+    {
+      char temp[20];
+      int len = XINT (Flength (auto_fontset_alist));
+
+      sprintf (temp, "auto%d", len);
+      ASET (vec, 13, build_string (temp));
+      name = build_font_name_from_vector (vec);
+    }
+  name = Fnew_fontset (name, list2 (list2 (Qascii, fontname),
+                                   list2 (Fcons (make_number (0),
+                                                 make_number (MAX_CHAR)),
+                                          fontname)));
+  id = fs_query_fontset (name, 0);
+  auto_fontset_alist
+    = Fcons (Fcons (fontname, make_number (id)), auto_fontset_alist);
+  return id;
+}
+
+
+DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
+       doc: /* Return information about a font named NAME on frame FRAME.
+If FRAME is omitted or nil, use the selected frame.
+The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,
+  HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,
+where
+  OPENED-NAME is the name used for opening the font,
+  FULL-NAME is the full name of the font,
+  SIZE is the maximum bound width of the font,
+  HEIGHT is the height of the font,
+  BASELINE-OFFSET is the upward offset pixels from ASCII baseline,
+  RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling
+    how to compose characters.
+If the named font is not yet loaded, return nil.  */)
+     (name, frame)
+     Lisp_Object name, frame;
+{
+  FRAME_PTR f;
+  struct font_info *fontp;
+  Lisp_Object info;
+
+  (*check_window_system_func) ();
+
+  CHECK_STRING (name);
+  name = Fdowncase (name);
+  if (NILP (frame))
+    frame = selected_frame;
+  CHECK_LIVE_FRAME (frame);
+  f = XFRAME (frame);
+
+  if (!query_font_func)
+    error ("Font query function is not supported");
+
+  fontp = (*query_font_func) (f, SDATA (name));
+  if (!fontp)
+    return Qnil;
+
+  info = Fmake_vector (make_number (7), Qnil);
+
+  XVECTOR (info)->contents[0] = build_string (fontp->name);
+  XVECTOR (info)->contents[1] = build_string (fontp->full_name);
+  XVECTOR (info)->contents[2] = make_number (fontp->size);
+  XVECTOR (info)->contents[3] = make_number (fontp->height);
+  XVECTOR (info)->contents[4] = make_number (fontp->baseline_offset);
+  XVECTOR (info)->contents[5] = make_number (fontp->relative_compose);
+  XVECTOR (info)->contents[6] = make_number (fontp->default_ascent);
+
+  return info;
+}
+
+
+/* Return the font name for the character at POSITION in the current
+   buffer.  This is computed from all the text properties and overlays
+   that apply to POSITION.  It returns nil in the following cases:
+
+   (1) The window system doesn't have a font for the character (thus
+   it is displayed by an empty box).
+
+   (2) The character code is invalid.
+
+   (3) The current buffer is not displayed in any window.
+
+   In addition, the returned font name may not take into account of
+   such redisplay engine hooks as what used in jit-lock-mode if
+   POSITION is currently not visible.  */
+
+
+DEFUN ("internal-char-font", Finternal_char_font, Sinternal_char_font, 1, 1, 0,
+       doc: /* For internal use only.  */)
+     (position)
+     Lisp_Object position;
+{
+  int pos, pos_byte, dummy;
+  int face_id;
+  int c;
+  Lisp_Object window;
+  struct window *w;
+  struct frame *f;
+  struct face *face;
+  Lisp_Object charset, rfont_def;
+  int charset_id;
+
+  CHECK_NUMBER_COERCE_MARKER (position);
+  pos = XINT (position);
+  if (pos < BEGV || pos >= ZV)
+    args_out_of_range_3 (position, make_number (BEGV), make_number (ZV));
+  pos_byte = CHAR_TO_BYTE (pos);
+  c = FETCH_CHAR (pos_byte);
+  window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
+  if (NILP (window))
+    return Qnil;
+  w = XWINDOW (window);
+  f = XFRAME (w->frame);
+  face_id = face_at_buffer_position (w, pos, -1, -1, &dummy, pos + 100, 0);
+  face = FACE_FROM_ID (f, face_id);
+  charset = Fget_char_property (position, Qcharset, Qnil);
+  if (CHARSETP (charset))
+    charset_id = XINT (CHARSET_SYMBOL_ID (charset));
+  else
+    charset_id = -1;
+  rfont_def = fontset_font (FONTSET_FROM_ID (face->fontset),
+                           c, face, charset_id);
+  return (VECTORP (rfont_def) && STRINGP (AREF (rfont_def, 3))
+         ? AREF (rfont_def, 3)
+         : Qnil);
+}
+
+
+DEFUN ("fontset-info", Ffontset_info, Sfontset_info, 1, 2, 0,
+       doc: /* Return information about a fontset FONTSET on frame FRAME.
+The value is a char-table of which elements has this form.
+
+    ((FONT-PATTERN OPENED-FONT ...) ...)
+
+FONT-PATTERN is a vector:
+
+       [ FAMILY WEIGHT SLANT SWIDTH ADSTYLE REGISTRY ]
+
+or a string of font name pattern.
+
+OPENED-FONT is a name of a font actually opened.
+
+The char-table has one extra slot.  The value is a char-table
+containing the information about the derived fonts from the default
+fontset.  The format is the same as abobe.  */)
+     (fontset, frame)
+     Lisp_Object fontset, frame;
+{
+  FRAME_PTR f;
+  Lisp_Object *realized[2], fontsets[2], tables[2];
+  Lisp_Object val, elt;
+  int c, i, j, k;
+
+  (*check_window_system_func) ();
+
+  fontset = check_fontset_name (fontset);
+
+  if (NILP (frame))
+    frame = selected_frame;
+  CHECK_LIVE_FRAME (frame);
+  f = XFRAME (frame);
+
+  /* Recode fontsets realized on FRAME from the base fontset FONTSET
+     in the table `realized'.  */
+  realized[0] = (Lisp_Object *) alloca (sizeof (Lisp_Object)
+                                       * ASIZE (Vfontset_table));
+  for (i = j = 0; i < ASIZE (Vfontset_table); i++)
+    {
+      elt = FONTSET_FROM_ID (i);
+      if (!NILP (elt)
+         && EQ (FONTSET_BASE (elt), fontset)
+         && EQ (FONTSET_FRAME (elt), frame))
+       realized[0][j++] = elt;
+    }
+  realized[0][j] = Qnil;
+
+  realized[1] = (Lisp_Object *) alloca (sizeof (Lisp_Object)
+                                       * ASIZE (Vfontset_table));
+  for (i = j = 0; ! NILP (realized[0][i]); i++)
+    {
+      elt = FONTSET_DEFAULT (realized[0][i]);
+      if (! NILP (elt))
+       realized[1][j++] = elt;
+    }
+  realized[1][j] = Qnil;
+
+  tables[0] = Fmake_char_table (Qfontset_info, Qnil);
+  tables[1] = Fmake_char_table (Qnil, Qnil);
+  XCHAR_TABLE (tables[0])->extras[0] = tables[1];
+  fontsets[0] = fontset;
+  fontsets[1] = Vdefault_fontset;
+
+  /* Accumulate information of the fontset in TABLE.  The format of
+     each element is ((FONT-SPEC OPENED-FONT ...) ...).  */
+  for (k = 0; k <= 1; k++)
+    {
+      for (c = 0; c <= MAX_CHAR; )
+       {
+         int from, to;
+
+         if (c <= MAX_5_BYTE_CHAR)
+           {
+             val = char_table_ref_and_range (fontsets[k], c, &from, &to);
+             if (to > MAX_5_BYTE_CHAR)
+               to = MAX_5_BYTE_CHAR;
+           }
+         else
+           {
+             val = FONTSET_FALLBACK (fontsets[k]);
+             to = MAX_CHAR;
+           }
+         if (VECTORP (val))
+           {
+             Lisp_Object alist;
+
+             /* At first, set ALIST to ((FONT-SPEC) ...).  */
+             for (alist = Qnil, i = 0; i < ASIZE (val); i++)
+               alist = Fcons (Fcons (AREF (AREF (val, i), 0), Qnil), alist);
+             alist = Fnreverse (alist);
+
+             /* Then store opend font names to cdr of each elements.  */
+             for (i = 0; ! NILP (realized[k][i]); i++)
+               {
+                 if (c <= MAX_5_BYTE_CHAR)
+                   val = FONTSET_REF (realized[k][i], c);
+                 else
+                   val = FONTSET_FALLBACK (realized[k][i]);
+                 if (! VECTORP (val))
+                   continue;
+                 /* VAL is [int int ?
+                            [FACE-ID FONT-INDEX FONT-DEF FONT-NAME] ...].
+                    If a font of an element is already opened,
+                    FONT-NAME is the name of a opened font.  */
+                 for (j = 3; j < ASIZE (val); j++)
+                   if (STRINGP (AREF (AREF (val, j), 3)))
+                     {
+                       Lisp_Object font_idx;
+
+                       font_idx = AREF (AREF (val, j), 1);
+                       elt = Fassq (AREF (AREF (AREF (val, j), 2), 0), alist);
+                       if (CONSP (elt)
+                           && NILP (Fmemq (font_idx, XCDR(elt))))
+                         nconc2 (elt, Fcons (font_idx, Qnil));
+                     }
+               }
+             for (val = alist; CONSP (val); val = XCDR (val))
+               for (elt = XCDR (XCAR (val)); CONSP (elt); elt = XCDR (elt))
+                 {
+                   struct font_info *font_info
+                     = (*get_font_info_func) (f, XINT (XCAR (elt)));
+                   XSETCAR (elt, build_string (font_info->full_name));
+                 }
+
+             /* Store ALIST in TBL for characters C..TO.  */
+             if (c <= MAX_5_BYTE_CHAR)
+               char_table_set_range (tables[k], c, to, alist);
+             else
+               XCHAR_TABLE (tables[k])->defalt = alist;
+           }
+         c = to + 1;
+       }
+    }
+
+  return tables[0];
+}
+
+
+DEFUN ("fontset-font", Ffontset_font, Sfontset_font, 2, 2, 0,
+       doc: /* Return a font name pattern for character CH in fontset NAME.
+If NAME is t, find a font name pattern in the default fontset.  */)
+     (name, ch)
+     Lisp_Object name, ch;
+{
+  int c;
+  Lisp_Object fontset, elt;
+
+  fontset = check_fontset_name (name);
+
+  CHECK_CHARACTER (ch);
+  c = XINT (ch);
+  elt = FONTSET_REF (fontset, c);
+  return Fcopy_sequence (elt);
+}
+
+DEFUN ("fontset-list", Ffontset_list, Sfontset_list, 0, 0, 0,
+       doc: /* Return a list of all defined fontset names.  */)
+     ()
+{
+  Lisp_Object fontset, list;
+  int i;
+
+  list = Qnil;
+  for (i = 0; i < ASIZE (Vfontset_table); i++)
+    {
+      fontset = FONTSET_FROM_ID (i);
+      if (!NILP (fontset)
+         && BASE_FONTSET_P (fontset))
+       list = Fcons (FONTSET_NAME (fontset), list);
+    }
+
+  return list;
+}
+
+
+#ifdef FONTSET_DEBUG
+
+Lisp_Object
+dump_fontset (fontset)
+     Lisp_Object fontset;
+{
+  Lisp_Object vec;
+
+  vec = Fmake_vector (make_number (3), Qnil);
+  ASET (vec, 0, FONTSET_ID (fontset));
+
+  if (BASE_FONTSET_P (fontset))
+    {
+      ASET (vec, 1, FONTSET_NAME (fontset));
+    }
+  else
+    {
+      Lisp_Object frame;
+
+      frame = FONTSET_FRAME (fontset);
+      if (FRAMEP (frame))
+       {
+         FRAME_PTR f = XFRAME (frame);
+
+         if (FRAME_LIVE_P (f))
+           ASET (vec, 1, f->name);
+         else
+           ASET (vec, 1, Qt);
+       }
+      if (!NILP (FONTSET_DEFAULT (fontset)))
+       ASET (vec, 2, FONTSET_ID (FONTSET_DEFAULT (fontset)));
+    }
+  return vec;
+}
+
+DEFUN ("fontset-list-all", Ffontset_list_all, Sfontset_list_all, 0, 0, 0,
+       doc: /* Return a brief summary of all fontsets for debug use.  */)
+     ()
+{
+  Lisp_Object val;
+  int i;
+
+  for (i = 0, val = Qnil; i < ASIZE (Vfontset_table); i++)
+    if (! NILP (AREF (Vfontset_table, i)))
+      val = Fcons (dump_fontset (AREF (Vfontset_table, i)), val);
+  return (Fnreverse (val));
+}
+#endif /* FONTSET_DEBUG */
+
+void
+syms_of_fontset ()
+{
+  if (!load_font_func)
+    /* Window system initializer should have set proper functions.  */
+    abort ();
+
+  DEFSYM (Qfontset, "fontset");
+  Fput (Qfontset, Qchar_table_extra_slots, make_number (9));
+  DEFSYM (Qfontset_info, "fontset-info");
+  Fput (Qfontset_info, Qchar_table_extra_slots, make_number (1));
+
+  DEFSYM (Qprepend, "prepend");
+  DEFSYM (Qappend, "append");
+
+  Vcached_fontset_data = Qnil;
+  staticpro (&Vcached_fontset_data);
+
+  Vfontset_table = Fmake_vector (make_number (32), Qnil);
+  staticpro (&Vfontset_table);
+
+  Vdefault_fontset = Fmake_char_table (Qfontset, Qnil);
+  staticpro (&Vdefault_fontset);
+  FONTSET_ID (Vdefault_fontset) = make_number (0);
+  FONTSET_NAME (Vdefault_fontset)
+    = build_string ("-*-*-*-*-*-*-*-*-*-*-*-*-fontset-default");
+  {
+    Lisp_Object default_ascii_font;
+
+#if defined (macintosh)
+    default_ascii_font
+      = build_string ("-apple-monaco-medium-r-*--*-120-*-*-*-*-mac-roman");
+#elif defined (WINDOWSNT)
+    default_ascii_font
+      = build_string ("-*-courier new-normal-r-*-*-*-100-*-*-*-*-iso8859-1");
+#else
+    default_ascii_font
+      = build_string ("-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
+#endif
+    FONTSET_ASCII (Vdefault_fontset) = default_ascii_font;
+  }
+  AREF (Vfontset_table, 0) = Vdefault_fontset;
+  next_fontset_id = 1;
+
+  auto_fontset_alist = Qnil;
+  staticpro (&auto_fontset_alist);
+
+  DEFVAR_LISP ("font-encoding-alist", &Vfont_encoding_alist,
+              doc: /*
+Alist of fontname patterns vs the corresponding encoding and repertory info.
+Each element looks like (REGEXP . (ENCODING . REPERTORY)),
+where ENCODING is a charset or a char-table,
+and REPERTORY is a charset, a char-table, or nil.
+
+ENCODING is for converting a character to a glyph code of the font.
+If ENCODING is a charset, encoding a character by the charset gives
+the corresponding glyph code.  If ENCODING is a char-table, looking up
+the table by a character gives the corresponding glyph code.
+
+REPERTORY specifies a repertory of characters supported by the font.
+If REPERTORY is a charset, all characters beloging to the charset are
+supported.  If REPERTORY is a char-table, all characters who have a
+non-nil value in the table are supported.  It REPERTORY is nil, Emacs
+gets the repertory information by an opened font and ENCODING.  */);
+  Vfont_encoding_alist = Qnil;
+
+  DEFVAR_LISP ("use-default-ascent", &Vuse_default_ascent,
+              doc: /*
+Char table of characters whose ascent values should be ignored.
+If an entry for a character is non-nil, the ascent value of the glyph
+is assumed to be what specified by _MULE_DEFAULT_ASCENT property of a font.
+
+This affects how a composite character which contains
+such a character is displayed on screen.  */);
+  Vuse_default_ascent = Qnil;
+
+  DEFVAR_LISP ("ignore-relative-composition", &Vignore_relative_composition,
+              doc: /*
+Char table of characters which is not composed relatively.
+If an entry for a character is non-nil, a composition sequence
+which contains that character is displayed so that
+the glyph of that character is put without considering
+an ascent and descent value of a previous character.  */);
+  Vignore_relative_composition = Qnil;
+
+  DEFVAR_LISP ("alternate-fontname-alist", &Valternate_fontname_alist,
+              doc: /* Alist of fontname vs list of the alternate fontnames.
+When a specified font name is not found, the corresponding
+alternate fontnames (if any) are tried instead.  */);
+  Valternate_fontname_alist = Qnil;
+
+  DEFVAR_LISP ("fontset-alias-alist", &Vfontset_alias_alist,
+              doc: /* Alist of fontset names vs the aliases.  */);
+  Vfontset_alias_alist = Fcons (Fcons (FONTSET_NAME (Vdefault_fontset),
+                                      build_string ("fontset-default")),
+                               Qnil);
+
+  DEFVAR_LISP ("vertical-centering-font-regexp",
+              &Vvertical_centering_font_regexp,
+              doc: /* *Regexp matching font names that require vertical centering on display.
+When a character is displayed with such fonts, the character is displayed
+at the vertical center of lines.  */);
+  Vvertical_centering_font_regexp = Qnil;
+
+  defsubr (&Squery_fontset);
+  defsubr (&Snew_fontset);
+  defsubr (&Sset_fontset_font);
+  defsubr (&Sfont_info);
+  defsubr (&Sinternal_char_font);
+  defsubr (&Sfontset_info);
+  defsubr (&Sfontset_font);
+  defsubr (&Sfontset_list);
+#ifdef FONTSET_DEBUG
+  defsubr (&Sfontset_list_all);
+#endif
+}