(MDisplayInfo): New member altgr_mask.
[m17n/m17n-lib.git] / src / m17n-X.c
index 072582d..09f57ca 100644 (file)
@@ -1,5 +1,5 @@
 /* m17n-X.c -- implementation of the GUI API on X Windows.
-   Copyright (C) 2003, 2004
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H15PRO112
 
 
    You should have received a copy of the GNU Lesser General Public
    License along with the m17n library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    02111-1307, USA.  */
 
+#include "config.h"
+
+#ifdef HAVE_X11
+
 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
 /*** @addtogroup m17nInternal
      @{ */
 
-#include "config.h"
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
@@ -43,6 +45,7 @@
 
 #ifdef HAVE_XFT2
 #include <X11/Xft/Xft.h>
+#include <fontconfig/fcfreetype.h>
 #endif /* HAVE_XFT2 */
 
 #include "m17n-gui.h"
 #include "fontset.h"
 #include "face.h"
 
-typedef struct {
-  MFont core;
-  unsigned int sizes[2];
-} MXFont;
-
-#define SET_SIZE(xfont, s) ((xfont)->sizes[(s) / 32] |= (1 << ((s) & 0x1F)))
-#define HAVE_SIZE(xfont, s) ((xfont)->sizes[(s) / 32] & (1 << ((s) & 0x1F)))
-
-typedef struct {
-  int size, inc, used;
-  MXFont *fonts;
-} MXFontList;
-
 typedef struct
 {
   /* Common header for the m17n object.  */
@@ -82,14 +72,9 @@ typedef struct
 
   /** List of available X-core fonts on the display.  Keys are
       registries and values are plists whose keys are families and
-      values are pointers to MXFontList.  */
+      values are pointers to MFont.  */
   MPlist *font_list;
 
-  /** List of available X-core fonts on the display.  Keys are
-      families and values are pointers to MFont.  For each MFont, only
-      these properties are important; FOUNDRY, FAMILY, REGISTRY.  */
-  MPlist *base_font_list;
-
   /** Nonzero means that <font_list> already contains all available
       fonts on the display.  */
   int all_fonts_scaned;
@@ -99,6 +84,10 @@ typedef struct
   int alt_mask;
   int super_mask;
   int hyper_mask;
+  int altgr_mask;
+
+  Atom MULE_BASELINE_OFFSET;
+  Atom AVERAGE_WIDTH;
 } MDisplayInfo;
 
 /* Anchor of the chain of MDisplayInfo objects.  */
@@ -153,6 +142,8 @@ typedef struct
 
   GC scratch_gc;
 
+  int resy;
+
 #ifdef HAVE_XFT2
   XftDraw *xft_draw;
 #endif
@@ -160,8 +151,8 @@ typedef struct
   /** List of pointers to realized faces on the frame.  */
   MPlist *realized_face_list;
 
-  /* List of information about each font.  Keys are font registries,
-     values are (MFontInfo *).  */
+  /* List of single element whose value is a root of chain of realized
+     fonts.  */
   MPlist *realized_font_list;
 
   /** List of pointers to realized fontsets on the frame.  */
@@ -182,8 +173,7 @@ static MSymbol M_iso8859_1, M_iso10646_1;
 #define FRAME_VISUAL(frame) DefaultVisual (FRAME_DISPLAY (frame), \
                                           FRAME_SCREEN (frame))
 
-#define DEFAULT_FONT "-misc-fixed-medium-r-normal--*-120-*-*-*-*-iso8859-1"
-#define FALLBACK_FONT "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1"
+#define DEFAULT_FONT "-*-*-medium-r-normal--13-*-*-*-c-*-iso8859-1"
 
 typedef struct
 {
@@ -197,18 +187,15 @@ static void
 free_display_info (void *object)
 {
   MDisplayInfo *disp_info = (MDisplayInfo *) object;
-  MPlist *plist, *p;
+  MPlist *plist, *pl;
 
   MPLIST_DO (plist, disp_info->font_list)
     {
-      MPLIST_DO (p, MPLIST_VAL (plist))
-       free (MPLIST_VAL (p));
+      MPLIST_DO (pl, MPLIST_VAL (plist))
+       free (MPLIST_VAL (pl));
       M17N_OBJECT_UNREF (MPLIST_VAL (plist));
     }
   M17N_OBJECT_UNREF (disp_info->font_list);
-  MPLIST_DO (plist, disp_info->base_font_list)
-    free (MPLIST_VAL (plist));
-  M17N_OBJECT_UNREF (disp_info->base_font_list);
 
   if (disp_info->auto_display)
     XCloseDisplay (disp_info->display);
@@ -227,8 +214,8 @@ free_device (void *object)
     mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist));
   M17N_OBJECT_UNREF (device->realized_fontset_list);
 
-  MPLIST_DO (plist, device->realized_font_list)
-    mfont__free_realized ((MRealizedFont *) MPLIST_VAL (plist));
+  if (MPLIST_VAL (device->realized_font_list))
+    mfont__free_realized (MPLIST_VAL (device->realized_font_list));
   M17N_OBJECT_UNREF (device->realized_font_list);
 
   MPLIST_DO (plist, device->realized_face_list)
@@ -272,6 +259,9 @@ find_modifier_bits (MDisplayInfo *disp_info)
   KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
   KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
   KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
+#ifdef XK_XKB_KEYS
+  KeyCode altgr = XKeysymToKeycode (display, XK_ISO_Level3_Shift);
+#endif
   int i, j;
 
   mods = XGetModifierMapping (display);
@@ -292,6 +282,10 @@ find_modifier_bits (MDisplayInfo *disp_info)
          disp_info->super_mask |= (1 << i);
        else if (code == hyper_l || code == hyper_r)
          disp_info->hyper_mask |= (1 << i);
+#ifdef XK_XKB_KEYS
+       else if (code == altgr)
+         disp_info->altgr_mask |= (1 << i);
+#endif
       }
 
   /* If meta keys are not in any modifier, use alt keys as meta
@@ -421,19 +415,22 @@ set_region (MFrame *frame, GC gc, MDrawRegion region)
 \f
 /** X font handler */
 
-static MRealizedFont *xfont_select (MFrame *, MFont *, MFont *, int);
-static int xfont_open (MRealizedFont *);
+static MFont *xfont_select (MFrame *, MFont *, int);
+static MRealizedFont *xfont_open (MFrame *, MFont *, MFont *, MRealizedFont *);
 static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int);
-static unsigned xfont_encode_char (MRealizedFont *, unsigned);
+static int xfont_has_char (MFrame *, MFont *, MFont *, int, unsigned);
+static unsigned xfont_encode_char (MFrame *, MFont *, MFont *, unsigned);
 static void xfont_render (MDrawWindow, int, int, MGlyphString *,
                          MGlyph *, MGlyph *, int, MDrawRegion);
-static void xfont_list (MFrame *frame, MPlist *plist,
-                       MFont *font, MSymbol language);
-
+static int xfont_list (MFrame *, MPlist *, MFont *, int);
+static void xfont_list_family_names (MFrame *, MPlist *);
+static int xfont_check_capability (MRealizedFont *rfont, MSymbol capability);
 
 static MFontDriver xfont_driver =
   { xfont_select, xfont_open,
-    xfont_find_metric, xfont_encode_char, xfont_render, xfont_list };
+    xfont_find_metric, xfont_has_char, xfont_encode_char,
+    xfont_render, xfont_list, xfont_list_family_names, xfont_check_capability
+  };
 
 static int
 font_compare (const void *p1, const void *p2)
@@ -446,83 +443,96 @@ xfont_registry_list (MFrame *frame, MSymbol registry)
 {
   MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
   MPlist *font_list = disp_info->font_list;
-  MPlist *base_font_list = disp_info->base_font_list;
   MPlist *plist, *p;
   char pattern[1024];
   char **font_names, **names;
   int nfonts;
   int i, j;
-  MXFont font;
-  MXFontList *xfont_table;
-  MFont *bfont = NULL;
+  MFont font;
+  int for_full_width;
 
   plist = mplist_get (font_list, registry);
   if (plist)
     return plist;
-  plist = mplist ();
+  p = plist = mplist ();
   mplist_add (font_list, registry, plist);
   sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", msymbol_name (registry));
   font_names = XListFonts (disp_info->display, pattern, 0x8000, &nfonts);
   if (nfonts == 0)
     return plist;
+  {
+    char *reg_name = msymbol_name (registry);
+
+    for_full_width = (strncmp (reg_name, "jis", 3) == 0
+                     || strncmp (reg_name, "gb", 2) == 0
+                     || strncmp (reg_name, "big5", 4) == 0
+                     || strncmp (reg_name, "ksc", 3) == 0);
+  }
   names = alloca (sizeof (char *) * nfonts);
   memcpy (names, font_names, sizeof (char *) * nfonts);
   qsort (names, nfonts, sizeof (char *), font_compare);
-  for (i = 0, p = NULL; i < nfonts; i++)
-    if (mfont__parse_name_into_font (names[i], Mx, (MFont *) &font) == 0
-       && (font.core.property[MFONT_SIZE] > 0
-           || font.core.property[MFONT_RESY] == 0))
+  MFONT_INIT (&font);
+  for (i = 0; i < nfonts; i++)
+    if (mfont__parse_name_into_font (names[i], Mx, &font) == 0
+       && (font.size > 0 || font.property[MFONT_RESY] == 0))
       {
-       MSymbol family = FONT_PROPERTY ((MFont *) &font, MFONT_FAMILY);
-       int size = font.core.property[MFONT_SIZE] / 10;
+       MSymbol family = FONT_PROPERTY (&font, MFONT_FAMILY);
+       MFont *fontx;
+       unsigned sizes[256];
+       int nsizes = 0;
+       int limit;
+       int size, normal_size;
        char *base_end;
        int base_len;
        int fields;
        
-       font.sizes[0] = font.sizes[1] = 0;
-       SET_SIZE (&font, size);
-           
-       /* Handle fonts of the same base.  */
+       /* Calculate how many bytes to compare to detect fonts of the
+          same base name.  */
        for (base_end = names[i], fields = 0; *base_end; base_end++)
          if (*base_end == '-'
              && ++fields == 7  /* PIXEL_SIZE */)
            break;
-       base_len = base_end - names[i];
-       for (j = i + 1; j < nfonts && ! strncmp (names[i], names[j], base_len);
+       base_len = base_end - names[i] + 1;
+
+       size = font.size / 10;
+       sizes[nsizes++] = size;
+       normal_size = (size >= 6 && size <= 29);
+       limit = (i + 256 < nfonts ? i + 256 : nfonts);
+       for (j = i + 1; j < limit && ! memcmp (names[i], names[j], base_len);
             i = j++)
-         if (mfont__parse_name_into_font (names[j], Mx, (MFont *) &font) == 0
-             && (font.core.property[MFONT_SIZE] > 0
-                 || font.core.property[MFONT_RESY] == 0))
+         if (mfont__parse_name_into_font (names[j], Mx, &font) == 0
+             && (font.size > 0 || font.property[MFONT_RESY] == 0))
            {
-             size = font.core.property[MFONT_SIZE] / 10;
-             SET_SIZE (&font, size);
+             size = font.size / 10;
+             sizes[nsizes++] = size;
+             normal_size |= (size >= 6 && size <= 29);
            }
 
-       if (p && MPLIST_KEY (p) != family)
-         p = mplist_find_by_key (plist, family);
-       if (p)
-         xfont_table = MPLIST_VAL (p);
-       else
-         {
-           p = plist;
-           MSTRUCT_MALLOC (xfont_table, MERROR_WIN);
-           MLIST_INIT1 (xfont_table, fonts, 4);
-           mplist_push (p, family, xfont_table);
-         }
-       MLIST_APPEND1 (xfont_table, fonts, font, MERROR_WIN);
-       if (! bfont
-           || (font.core.property[MFONT_FOUNDRY]
-               != bfont->property[MFONT_FOUNDRY])
-           || (font.core.property[MFONT_FAMILY]
-               != bfont->property[MFONT_FAMILY]))
+       font.for_full_width = for_full_width;
+       font.type = MFONT_TYPE_OBJECT;
+       font.source = MFONT_SOURCE_X;
+       if (normal_size)
          {
-           MSTRUCT_MALLOC (bfont, MERROR_WIN);
-           *bfont = font.core;
-           for (j = MFONT_WEIGHT; j <= MFONT_ADSTYLE; j++)
-             bfont->property[j] = 0;
-           bfont->property[MFONT_SIZE] = bfont->property[MFONT_RESY] = 0;
-           mplist_push (base_font_list, family, bfont);
+           MSTRUCT_CALLOC (fontx, MERROR_WIN);
+           *fontx = font;
+           fontx->multiple_sizes = 1;
+           fontx->size = 0;
+           for (j = 0; j < nsizes; j++)
+             if (sizes[j] >= 6 && sizes[j] <= 29)
+               fontx->size |= 1 << (sizes[j] - 6);
+           p = mplist_add (p, family, fontx);
          }
+       for (j = 0; j < nsizes; j++)
+         if (sizes[j] < 6 || sizes[j] > 29)
+           {
+             MSTRUCT_CALLOC (fontx, MERROR_WIN);
+             *fontx = font;
+             fontx->multiple_sizes = 0;
+             fontx->size = sizes[j] * 10;
+             if (sizes[j] == 0)
+               fontx->property[MFONT_RESY] = 0;
+             p = mplist_add (p, family, fontx);
+           }
       }
   XFreeFontNames (font_names);
   return plist;
@@ -544,149 +554,150 @@ xfont_list_all (MFrame *frame)
     xfont_registry_list (frame, MPLIST_KEY (p));
 }
 
-
 typedef struct
 {
   M17NObject control;
   Display *display;
   XFontStruct *xfont;
-} MXFontInfo;
+} MRealizedFontX;
 
 /* The X font driver function SELECT.  */
 
-static MRealizedFont *
-xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size){
-
-  MSymbol family = FONT_PROPERTY (spec, MFONT_FAMILY);
-  MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
-  int requested_size = request->property[MFONT_SIZE];
-  MRealizedFont *rfont;
-  MPlist *plist;
-  int i;
-  MFont *best_font;
-  int best_score, score;
-
-  if (registry == Mnil
-      || ! strchr (MSYMBOL_NAME (registry), '-'))
-    return NULL;
-
-  plist = xfont_registry_list (frame, registry);
-  if (MPLIST_TAIL_P (plist))
-    return NULL;
-  best_score = -1, best_font = NULL;
-  if (family == Mnil)
-    family = FONT_PROPERTY (request, MFONT_FAMILY);
-  MPLIST_DO (plist, plist)
-    {
-      if (family == Mnil || family == MPLIST_KEY (plist))
-       {
-         MXFontList *xfont_table = MPLIST_VAL (plist);
-
-         for (i = 0; i < xfont_table->used; i++)
-           {
-             MXFont *xfont = xfont_table->fonts + i;
-             MFont *font = (MFont *) xfont;
-             int size = requested_size / 10, s0, s1;
-             
-             for (s0 = size; s0 > 0 && ! HAVE_SIZE (xfont, s0); s0--);
-             if (s0 * 10 == requested_size)
-               /* Exact size match.  */
-               ;
-             else if (xfont->sizes[0] & 1)
-               /* Scalable font.  */
-               size = 0;
-             else if (limited_size)
-               /* We can't use a larger font.  */
-               continue;
-             else if (s0 == 0)
-               {
-                 for (s0 = size + 1; s0 < 64 && ! HAVE_SIZE (xfont, s0); s0++);
-                 if (s0 == 64)
-                   continue;
-                 size = s0;
-               }
-             else
-               {
-                 for (s1 = size + (size - s0) - 1;
-                      s1 > size && HAVE_SIZE (xfont, s1); s1++);
-                 size = (s1 > size ? s1 : s0);
-               }
-             font->property[MFONT_SIZE] = size * 10;
+static MFont *
+xfont_select (MFrame *frame, MFont *font, int limited_size)
+{
+  MPlist *plist = mplist (), *pl;
+  int num = xfont_list (frame, plist, font, 0);
+  MFont *found = NULL;
 
-             if ((score = mfont__score (font, spec, request,
-                                        limited_size)) >= 0
-                 && (best_score < 0 || score < best_score))
-             {
-               best_score = score;
-               best_font = (MFont *) (xfont_table->fonts + i);
-               if (best_score == 0)
-                 break;
-             }
-           }
-         if (best_score == 0)
+  if (num > 0)
+    MPLIST_DO (pl, plist)
+      {
+       font = MPLIST_VAL (pl);
+       if (limited_size == 0
+           || font->size == 0
+           || font->size <= limited_size)
+         {
+           found = font;
            break;
-       }
-    }
-  if (! best_font)
-    return NULL;
-
-  MSTRUCT_CALLOC (rfont, MERROR_WIN);
-  rfont->frame = frame;
-  rfont->spec = *spec;
-  rfont->request = *request;
-  rfont->font = *best_font;
-  if (best_font->property[MFONT_SIZE] == 0)
-    rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE];
-  rfont->score = best_score;
-  return rfont;
+         }
+      }
+  M17N_OBJECT_UNREF (plist);
+  return found;
 }
 
-
 /* The X font driver function CLOSE.  */
 
 static void
 close_xfont (void *object)
 {
-  MXFontInfo *xfont_info = object;
+  MRealizedFontX *x_rfont = object;
 
-  XFreeFont (xfont_info->display, xfont_info->xfont);
-  free (object);
+  XFreeFont (x_rfont->display, x_rfont->xfont);
+  free (x_rfont);
 }
 
-
 /* The X font driver function OPEN.  */
 
-static int
-xfont_open (MRealizedFont *rfont)
+static MRealizedFont *
+xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
 {
+  int size;
+  MRealizedFontX *x_rfont;
   char *name;
-  MXFontInfo *xfont_info;
-  MFrame *frame = rfont->frame;
-  int mdebug_mask = MDEBUG_FONT;
-
-  /* This never fail to generate a valid fontname because open_spec
-     should correspond to a font available on the system.  */
-  name = mfont_unparse_name (&rfont->font, Mx);
-  M17N_OBJECT (xfont_info, close_xfont, MERROR_WIN);
-  xfont_info->display = FRAME_DISPLAY (frame);
-  xfont_info->xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
-  if (! xfont_info->xfont)
+  Display *display = FRAME_DISPLAY (frame);
+  XFontStruct *xfont;
+  int mdebug_flag = MDEBUG_FONT;
+  MFont this;
+
+  size = spec->size;
+  if (size)
+    {
+      int ratio = mfont_resize_ratio (font);
+
+      if (ratio != 100)
+       size = size * ratio / 100;
+    }
+  else
+    size = 120;
+
+  if (font->size)
+    {
+      /* non-scalable font */
+      if (font->multiple_sizes)
+       {
+         int i;
+
+         if (size < 60)
+           size = 60;
+         else if (size > 290)
+           size = 290;
+         for (i = size / 10 - 6; i >= 0; i--)
+           if (font->size & (1 << i))
+             break;
+         if (i == 0)
+           for (i = size / 10 - 5; i < 24; i++)
+             if (font->size & (1 << i))
+               break;
+         size = (i + 6) * 10;
+       }
+      else
+       size = font->size;
+    }
+
+  if (rfont)
+    {
+      for (; rfont; rfont = rfont->next)
+       if (rfont->font == font && rfont->spec.size == size)
+         return rfont;
+    }
+
+  this = *font;
+  this.multiple_sizes = 0;
+  this.size = size;
+  /* This never fail to generate a valid fontname.  */
+  name = mfont_unparse_name (&this, Mx);
+  xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
+  if (! xfont)
     {
-      rfont->status = -1;
-      free (xfont_info);
       MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
       free (name);
-      return -1;
+      font->type = MFONT_TYPE_FAILURE;
+      return NULL;
     }
-  rfont->info = xfont_info;
+  M17N_OBJECT (x_rfont, close_xfont, MERROR_FONT_X);
+  x_rfont->display = display;
+  x_rfont->xfont = xfont;
+  MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
+  rfont->id = msymbol (name);
+  rfont->spec = this;
+  rfont->spec.type = MFONT_TYPE_REALIZED;
+  rfont->spec.source = MFONT_SOURCE_X;
+  rfont->frame = frame;
+  rfont->font = font;
+  rfont->driver = &xfont_driver;
+  rfont->info = x_rfont;
+  {
+    MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
+    unsigned long value;
+
+    rfont->baseline_offset
+      = (XGetFontProperty (xfont, disp_info->MULE_BASELINE_OFFSET, &value)
+        ? (int) (value << 6) : 0);
+    rfont->average_width
+      = (XGetFontProperty (xfont, disp_info->AVERAGE_WIDTH, &value)
+        ? (int) (value << 6) / 10 : 0);
+  }
+  rfont->ascent = (xfont->ascent << 6) + rfont->baseline_offset;
+  rfont->descent = (xfont->descent << 6) - rfont->baseline_offset;
+  rfont->max_advance = xfont->max_bounds.width << 6;
+  rfont->x_ppem = rfont->y_ppem = size / 10;
+  rfont->fontp = xfont;
+  rfont->next = MPLIST_VAL (frame->realized_font_list);
+  MPLIST_VAL (frame->realized_font_list) = rfont;
   MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
   free (name);
-  rfont->status = 1;
-  rfont->ascent = xfont_info->xfont->ascent;
-  rfont->descent = xfont_info->xfont->descent;
-  rfont->type = Mx;
-  rfont->fontp = xfont_info->xfont;
-  return 0;
+  return rfont;
 }
 
 
@@ -696,94 +707,113 @@ static void
 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
                   int from, int to)
 {
-  MXFontInfo *xfont_info = rfont->info;
-  XFontStruct *xfont = xfont_info->xfont;
+  XFontStruct *xfont = rfont->fontp;
   MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
 
   for (; g != gend; g++)
-    {
-      if (g->code == MCHAR_INVALID_CODE)
-       {
-         g->lbearing = xfont->max_bounds.lbearing;
-         g->rbearing = xfont->max_bounds.rbearing;
-         g->width = xfont->max_bounds.width;
-         g->ascent = xfont->ascent;
-         g->descent = xfont->descent;
-       }
-      else
-       {
-         int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
-         XCharStruct *pcm = NULL;
+    if (! g->g.measured)
+      {
+       if (g->g.code == MCHAR_INVALID_CODE)
+         {
+           g->g.lbearing = xfont->max_bounds.lbearing << 6;
+           g->g.rbearing = xfont->max_bounds.rbearing << 6;
+           g->g.xadv = xfont->max_bounds.width << 6;
+           g->g.ascent = xfont->ascent << 6;
+           g->g.descent = xfont->descent << 6;
+         }
+       else
+         {
+           int byte1 = g->g.code >> 8, byte2 = g->g.code & 0xFF;
+           XCharStruct *pcm = NULL;
 
-         if (xfont->per_char != NULL)
-           {
-             if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
-               {
-                 if (byte1 == 0
-                     && byte2 >= xfont->min_char_or_byte2
-                     && byte2 <= xfont->max_char_or_byte2)
-                   pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
-               }
-             else
-               {
-                 if (byte1 >= xfont->min_byte1
-                     && byte1 <= xfont->max_byte1
-                     && byte2 >= xfont->min_char_or_byte2
-                     && byte2 <= xfont->max_char_or_byte2)
-                   {
-                     pcm = (xfont->per_char
-                            + ((xfont->max_char_or_byte2
-                                - xfont->min_char_or_byte2 + 1)
-                               * (byte1 - xfont->min_byte1))
-                            + (byte2 - xfont->min_char_or_byte2));
-                   }
-               }
-           }
+           if (xfont->per_char != NULL)
+             {
+               if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
+                 {
+                   if (byte1 == 0
+                       && byte2 >= xfont->min_char_or_byte2
+                       && byte2 <= xfont->max_char_or_byte2)
+                     pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
+                 }
+               else
+                 {
+                   if (byte1 >= xfont->min_byte1
+                       && byte1 <= xfont->max_byte1
+                       && byte2 >= xfont->min_char_or_byte2
+                       && byte2 <= xfont->max_char_or_byte2)
+                     {
+                       pcm = (xfont->per_char
+                              + ((xfont->max_char_or_byte2
+                                  - xfont->min_char_or_byte2 + 1)
+                                 * (byte1 - xfont->min_byte1))
+                              + (byte2 - xfont->min_char_or_byte2));
+                     }
+                 }
+             }
 
-         if (pcm)
-           {
-             g->lbearing = pcm->lbearing;
-             g->rbearing = pcm->rbearing;
-             g->width = pcm->width;
-             g->ascent = pcm->ascent;
-             g->descent = pcm->descent;
-           }
-         else
-           {
-             /* If the per_char pointer is null, all glyphs between
-                the first and last character indexes inclusive have
-                the same information, as given by both min_bounds and
-                max_bounds.  */
-             g->lbearing = 0;
-             g->rbearing = xfont->max_bounds.width;
-             g->width = xfont->max_bounds.width;
-             g->ascent = xfont->ascent;
-             g->descent = xfont->descent;
-           }
-       }
-    }
+           if (pcm)
+             {
+               g->g.lbearing = pcm->lbearing << 6;
+               g->g.rbearing = pcm->rbearing << 6;
+               g->g.xadv = pcm->width << 6;
+               g->g.ascent = pcm->ascent << 6;
+               g->g.descent = pcm->descent << 6;
+             }
+           else
+             {
+               /* If the per_char pointer is null, all glyphs between
+                  the first and last character indexes inclusive have
+                  the same information, as given by both min_bounds and
+                  max_bounds.  */
+               g->g.lbearing = 0;
+               g->g.rbearing = xfont->max_bounds.width << 6;
+               g->g.xadv = xfont->max_bounds.width << 6;
+               g->g.ascent = xfont->ascent << 6;
+               g->g.descent = xfont->descent << 6;
+             }
+         }
+       g->g.yadv = 0;
+       g->g.ascent += rfont->baseline_offset;
+       g->g.descent -= rfont->baseline_offset;
+       g->g.measured = 1;
+      }
 }
 
 
+static int
+xfont_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
+{
+  return (xfont_encode_char (frame, font, spec, code) != MCHAR_INVALID_CODE);
+}
+
 /* The X font driver function GET_GLYPH_ID.  */
 
 static unsigned
-xfont_encode_char (MRealizedFont *rfont, unsigned code)
+xfont_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
 {
-  MXFontInfo *xfont_info;
+  MRealizedFont *rfont;
   XFontStruct *xfont;
   unsigned min_byte1, max_byte1, min_byte2, max_byte2;
   int all_chars_exist;
 
-  if (rfont->status < 0 || code >= 0x10000)
-    return MCHAR_INVALID_CODE;
-  if (rfont->status == 0)
+  if (font->type == MFONT_TYPE_REALIZED)
+    rfont = (MRealizedFont *) font;
+  else if (font->type == MFONT_TYPE_OBJECT)
     {
-      if (xfont_open (rfont) < 0)
-       return MCHAR_INVALID_CODE;
+      for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
+          rfont = rfont->next)
+       if (rfont->font == font)
+         break;
+      if (! rfont)
+       {
+         rfont = xfont_open (frame, font, spec, NULL);
+         if (! rfont)
+           return MCHAR_INVALID_CODE;
+       }
     }
-  xfont_info = rfont->info;
-  xfont = xfont_info->xfont;
+  else
+    MFATAL (MERROR_FONT_X);
+  xfont = rfont->fontp;
   all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True);
   min_byte1 = xfont->min_byte1;
   max_byte1 = xfont->max_byte1;
@@ -827,48 +857,45 @@ xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
              MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
 {
   MRealizedFace *rface = from->rface;
-  MXFontInfo *xfont_info = rface->rfont->info;
-  Display *display;
+  Display *display = FRAME_DISPLAY (rface->frame);
   XChar2b *code;
   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
   MGlyph *g;
   int i;
+  int baseline_offset;
 
   if (from == to)
     return;
 
-  /* It is assured that the all glyphs in the current range use the
-     same realized face.  */
-  display = FRAME_DISPLAY (rface->frame);
-
+  baseline_offset = rface->rfont->baseline_offset >> 6;
   if (region)
     gc = set_region (rface->frame, gc, region);
-  XSetFont (display, gc, xfont_info->xfont->fid);
+  XSetFont (display, gc, ((XFontStruct *) rface->rfont->fontp)->fid);
   code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
   for (i = 0, g = from; g < to; i++, g++)
     {
-      code[i].byte1 = g->code >> 8;
-      code[i].byte2 = g->code & 0xFF;
+      code[i].byte1 = g->g.code >> 8;
+      code[i].byte2 = g->g.code & 0xFF;
     }
 
   g = from;
   while (g < to)
     {
       if (g->type == GLYPH_PAD)
-       x += g++->width;
+       x += g++->g.xadv;
       else if (g->type == GLYPH_SPACE)
        for (; g < to && g->type == GLYPH_SPACE; g++)
-         x += g->width;
+         x += g->g.xadv;
       else if (! g->rface->rfont)
        {
-         if ((g->c >= 0x200B && g->c <= 0x200F)
-             || (g->c >= 0x202A && g->c <= 0x202E))
-           x += g++->width;
+         if ((g->g.c >= 0x200B && g->g.c <= 0x200F)
+             || (g->g.c >= 0x202A && g->g.c <= 0x202E))
+           x += g++->g.xadv;
          else
            {
              /* As a font is not found for this character, draw an
                 empty box.  */
-             int box_width = g->width;
+             int box_width = g->g.xadv;
              int box_height = gstring->ascent + gstring->descent;
 
              if (box_width > 4)
@@ -877,14 +904,15 @@ xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
                box_height -= 2;
              XDrawRectangle (display, (Window) win, gc,
                              x, y - gstring->ascent, box_width, box_height);
-             x += g++->width;
+             x += g++->g.xadv;
            }
        }
-      else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
+      else if (g->g.xoff != 0 || g->g.yoff != 0 || g->right_padding)
        {
          XDrawString16 (display, (Window) win, gc,
-                        x + g->xoff, y + g->yoff, code + (g - from), 1);
-         x += g->width;
+                        x + g->g.xoff, y + g->g.yoff - baseline_offset,
+                        code + (g - from), 1);
+         x += g->g.xadv;
          g++;
        }
       else
@@ -893,72 +921,116 @@ xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
          int code_idx = g - from;
 
          for (i = 0;
-              g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
+              g < to && g->type == GLYPH_CHAR && g->g.xoff == 0 && g->g.yoff == 0;
               i++, g++)
-             x += g->width;
-         XDrawString16 (display, (Window) win, gc, orig_x, y,
-                        code + code_idx, i);
+             x += g->g.xadv;
+         XDrawString16 (display, (Window) win, gc,
+                        orig_x, y - baseline_offset, code + code_idx, i);
        }
     }
 }
 
-static void
-xfont_list (MFrame *frame, MPlist *plist, MFont *font, MSymbol language)
+static int
+xfont_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum)
 {
   MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
   MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil;
   MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil;
-  MPlist *p, *pl;
+  int size = font ? font->size : 0;
+  MPlist *pl, *p;
+  int num = 0;
+  int mdebug_flag = MDEBUG_FONT;
 
-  if (registry != Mnil)
-    xfont_registry_list (frame, registry);
-  else
-    xfont_list_all (frame);
+  MDEBUG_PRINT2 (" [X-FONT] listing %s-%s...",
+                family ? msymbol_name (family) : "*",
+                registry ? msymbol_name (registry) : "*");
 
-  /* As we have not yet implemented the language check, return all
-     base fonts.  */
-  if (! font)
-    MPLIST_DO (p, disp_info->base_font_list)
-      mplist_push (plist, MPLIST_KEY (p), MPLIST_VAL (p));
+  if (registry == Mnil)
+    xfont_list_all (frame);
   else
-    {
-      MXFontList *xfontlist;
-      MXFont *xfont;
-      int i;
-
-      pl = disp_info->font_list;
-      if (registry != Mnil)
-       {
-         pl = mplist_find_by_key (pl, registry);
-         if (! pl)
-           return;
-       }
+    xfont_registry_list (frame, registry);
 
-      MPLIST_DO (pl, pl)
-       {
-         p = MPLIST_VAL (pl);
-         if (family != Mnil)
-           {
-             p = mplist_find_by_key (p, family);
-             if (! p)
-               return;
-           }
-         MPLIST_DO (p, p)
+  MPLIST_DO (pl, disp_info->font_list)
+    if (registry == Mnil || registry == MPLIST_KEY (pl))
+      {
+       MPLIST_DO (p, MPLIST_VAL (pl))
+         if (family == Mnil || family == MPLIST_KEY (p))
            {
-             xfontlist = MPLIST_VAL (p);
-             for (i = 0; i < xfontlist->used; i++)
+             MFont *fontx = MPLIST_VAL (p);
+
+             if (! font || (mfont__match_p (fontx, font, MFONT_REGISTRY)))
                {
-                 xfont = xfontlist->fonts + i;
-                 if (mfont__match_p (&xfont->core, font, MFONT_REGISTRY))
-                   mplist_push (plist, MPLIST_KEY (p), &xfont->core);
+                 if (fontx->size != 0 && size)
+                   {
+                     if (fontx->multiple_sizes)
+                       {
+                         if (size < 60 || size > 290
+                             || ! (fontx->size & (1 << (size / 10 - 6))))
+                           continue;
+                       }
+                     else if (fontx->size != size)
+                       continue;
+                   }
+                 mplist_push (plist, MPLIST_KEY (p), fontx);
+                 num++;
+                 if (maxnum > 0 && maxnum == num)
+                   goto done;
                }
-             if (family != Mnil)
-               break;
            }
-         if (registry != Mnil)
+      }
+
+ done:
+  MDEBUG_PRINT1 (" %d found\n", num);
+  return num;
+}
+
+static void
+xfont_list_family_names (MFrame *frame, MPlist *plist)
+{
+  MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
+  char **font_names;
+  int i, nfonts;
+  MSymbol last_family = Mnil;
+
+  font_names = XListFonts (disp_info->display,
+                          "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", 0x8000, &nfonts);
+  for (i = 0; i < nfonts; i++)
+    {
+      MSymbol family;
+      char foundry[256], fam[256];
+      MPlist *p;
+      
+      if (sscanf (font_names[i], "-%s-%s-", foundry, fam) < 2)
+       continue;
+      family = msymbol (fam);
+      if (family == last_family)
+       continue;
+      last_family = family;
+
+      MPLIST_DO (p, plist)
+       {
+         MSymbol sym = MPLIST_SYMBOL (p);
+
+         if (sym == family)
            break;
+         if (strcmp (MSYMBOL_NAME (sym), fam) > 0)
+           {
+             mplist_push (p, Msymbol, family);
+             break;
+           }
        }
+      if (MPLIST_TAIL_P (p))
+       mplist_push (p, Msymbol, family);
     }
+  if (font_names)
+    XFreeFontNames (font_names);
+}
+
+static int 
+xfont_check_capability (MRealizedFont *rfont, MSymbol capability)
+{
+  /* Currently X font driver doesn't support any capability.  */
+  return -1;
 }
 
 \f
@@ -969,127 +1041,228 @@ xfont_list (MFrame *frame, MPlist *plist, MFont *font, MSymbol language)
 typedef struct
 {
   M17NObject control;
+  FT_Face ft_face;             /* This must be the 2nd member. */
   Display *display;
   XftFont *font_aa;
   XftFont *font_no_aa;
-} MXftFontInfo;
-
-static int xft_open (MRealizedFont *);
+  /* Pointer to MRealizedFontFT */
+  void *info;
+} MRealizedFontXft;
+
+static MRealizedFont *xft_open (MFrame *frame, MFont *font, MFont *spec,
+                               MRealizedFont *);
+static int xft_has_char (MFrame *frame, MFont *font, MFont *spec,
+                        int c, unsigned code);
+static unsigned xft_encode_char (MFrame *frame, MFont *font, MFont *spec,
+                                unsigned code);
 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
 static void xft_render (MDrawWindow, int, int, MGlyphString *,
                        MGlyph *, MGlyph *, int, MDrawRegion);
-
-MFontDriver xft_driver =
-  { NULL,                      /* Set to ft_select in device_init (). */
-    xft_open, xft_find_metric,
-    NULL,                      /* Set to ft_encode_char in device_init (). */
-    xft_render,
-    NULL                       /* Set to ft_list in device_init (). */
+static int xft_check_capability (MRealizedFont *rfont, MSymbol capability);
+static int xft_check_otf (MFLTFont *font, MFLTOtfSpec *spec);
+static int xft_drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
+                         MFLTGlyphString *in, int from, int to,
+                         MFLTGlyphString *out,
+                         MFLTGlyphAdjustment *adjustment);
+static int xft_try_otf (MFLTFont *font, MFLTOtfSpec *spec,
+                       MFLTGlyphString *in, int from, int to);
+static int xft_iterate_otf_feature (struct _MFLTFont *font, MFLTOtfSpec *spec,
+                                   int from, int to, unsigned char *table);
+
+
+static MFontDriver xft_driver =
+  { NULL, xft_open,
+    xft_find_metric, xft_has_char, xft_encode_char, xft_render, NULL, NULL,
+    xft_check_capability, NULL, NULL, xft_check_otf, xft_drive_otf, xft_try_otf,
+#ifdef HAVE_OTF
+    xft_iterate_otf_feature
+#endif /* HAVE_OTF */
   };
 
-
 static void
 close_xft (void *object)
 {
-  MXftFontInfo *font_info = object;
+  MRealizedFontXft *rfont_xft = object;
 
-  XftFontClose (font_info->display, font_info->font_aa);
-  XftFontClose (font_info->display, font_info->font_no_aa);
-  free (font_info);
+  if (rfont_xft->font_aa)
+    XftFontClose (rfont_xft->display, rfont_xft->font_aa);
+  if (rfont_xft->font_no_aa)
+    XftFontClose (rfont_xft->display, rfont_xft->font_no_aa);
+  M17N_OBJECT_UNREF (rfont_xft->info);
+  free (rfont_xft);
 }
 
 
 static XftFont *
-xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
+xft_open_font (Display *display, MSymbol file, double size,
+              FcBool anti_alias)
 {
-  XftPattern *pattern;
-  XftFontInfo *xft_font_info;
+  FcPattern *pattern;
   XftFont *font;
 
-  pattern = XftPatternCreate ();
-  XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
-  XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
-  XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
-  xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
-  if (! xft_font_info)
-    return NULL;
-  font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
-  XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
+  pattern = FcPatternCreate ();
+  FcPatternAddString (pattern, FC_FILE, (FcChar8 *) msymbol_name (file));
+  FcPatternAddDouble (pattern, FC_PIXEL_SIZE, size);
+  FcPatternAddBool (pattern, FC_ANTIALIAS, anti_alias);
+  font = XftFontOpenPattern (display, pattern);
   return font;
 }
 
 
-static int
-xft_open (MRealizedFont *rfont)
+static MRealizedFont *
+xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
 {
-  MFrame *frame;
-  MFTInfo *ft_info;
-  MXftFontInfo *font_info;
+  Display *display = FRAME_DISPLAY (frame);
+  int reg = spec->property[MFONT_REGISTRY];
+  FT_Face ft_face;
+  MRealizedFontXft *rfont_xft;
+  FcBool anti_alias = FRAME_DEVICE (frame)->depth > 1 ? FcTrue : FcFalse;
   int size;
+  XftFont *xft_font;
+  int ascent, descent, max_advance, average_width, baseline_offset;
 
-  if ((mfont__ft_driver.open) (rfont) < 0)
-    return -1;
+  if (font->size)
+    /* non-scalable font */
+    size = font->size;
+  else if (spec->size)
+    {
+      int ratio = mfont_resize_ratio (font);
 
-  size = rfont->font.property[MFONT_SIZE] / 10;
-  frame = rfont->frame;
+      size = ratio == 100 ? spec->size : spec->size * ratio / 100;
+    }
+  else
+    size = 120;
 
-  ft_info = rfont->info;
-  M17N_OBJECT (font_info, close_xft, MERROR_WIN);
-  ft_info->extra_info = font_info;
-  font_info->display = FRAME_DISPLAY (frame);
-  font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
-  if (font_info->font_aa)
+  if (rfont)
     {
-      font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
-      if (font_info->font_no_aa)
-       {
-         rfont->type = Mxft;
-         rfont->fontp = font_info->font_no_aa;
-         return 0;
-       }
-      XftFontClose (FRAME_DISPLAY (rfont->frame), font_info->font_aa);
+      MRealizedFont *save = NULL;
+
+      for (; rfont; rfont = rfont->next)
+       if (rfont->font == font
+           && (rfont->font->size ? rfont->font->size == size
+               : rfont->spec.size == size)
+           && rfont->spec.property[MFONT_REGISTRY] == reg)
+         {
+           if (! save)
+             save = rfont;
+           if (rfont->driver == &xft_driver)
+             return rfont;
+         }
+      rfont = save;
     }
-  free (font_info);  
-  ft_info->extra_info = NULL;
-  rfont->status = -1;
-  return -1;
+  rfont = (mfont__ft_driver.open) (frame, font, spec, rfont);
+  if (! rfont)
+    return NULL;
+  ascent = rfont->ascent;
+  descent = rfont->descent;
+  max_advance = rfont->max_advance;
+  average_width = rfont->average_width;
+  baseline_offset = rfont->baseline_offset;
+  spec = &rfont->spec;
+  ft_face = rfont->fontp;
+  xft_font = xft_open_font (display, font->file, size / 10, anti_alias);
+  if (! xft_font)
+    return NULL;
+  M17N_OBJECT (rfont_xft, close_xft, MERROR_WIN);
+  rfont_xft->display = display;
+  if (anti_alias == FcTrue)
+    rfont_xft->font_aa = xft_font;
+  else
+    rfont_xft->font_no_aa = xft_font;
+  rfont_xft->ft_face = ft_face;
+  rfont_xft->info = rfont->info;
+  M17N_OBJECT_REF (rfont->info);
+  MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
+  rfont->id = font->file;
+  rfont->spec = *spec;
+  rfont->spec.size = size;
+  rfont->frame = frame;
+  rfont->font = font;
+  rfont->driver = &xft_driver;
+  rfont->info = rfont_xft;
+  rfont->ascent = ascent;
+  rfont->descent = descent;
+  rfont->max_advance = max_advance;
+  rfont->average_width = average_width;
+  rfont->baseline_offset = baseline_offset;
+  rfont->x_ppem = ft_face->size->metrics.x_ppem;
+  rfont->y_ppem = ft_face->size->metrics.y_ppem;
+  rfont->fontp = xft_font;
+  rfont->next = MPLIST_VAL (frame->realized_font_list);
+  MPLIST_VAL (frame->realized_font_list) = rfont;
+  return rfont;
 }
 
-
 static void
 xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
                int from, int to)
 {
-  MFTInfo *ft_info = rfont->info;
-  MXftFontInfo *font_info = ft_info->extra_info;
+  Display *display = FRAME_DISPLAY (rfont->frame);
+  XftFont *xft_font = rfont->fontp;
   MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
 
   for (; g != gend; g++)
-    {
-      if (g->code == MCHAR_INVALID_CODE)
-       {
-         MGlyph *start = g++;
+    if (! g->g.measured)
+      {
+       if (g->g.code == MCHAR_INVALID_CODE)
+         {
+           g->g.lbearing = 0;
+           g->g.rbearing = xft_font->max_advance_width << 6;
+           g->g.xadv = g->g.rbearing << 6;
+           g->g.ascent = xft_font->ascent << 6;
+           g->g.descent = xft_font->descent << 6;
+         }
+       else
+         {
+           XGlyphInfo extents;
+
+           XftGlyphExtents (display, xft_font, &g->g.code, 1, &extents);
+           g->g.lbearing = (- extents.x) << 6;
+           g->g.rbearing = (extents.width - extents.x) << 6;
+           g->g.xadv = extents.xOff << 6;
+           g->g.ascent = extents.y << 6;
+           g->g.descent = (extents.height - extents.y) << 6;
+         }
+       g->g.yadv = 0;
+       g->g.measured = 1;
+      }
+}
 
-         while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
-         (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
-                                         GLYPH_INDEX (g));
-         g--;
-       }
-      else
-       {
-         XGlyphInfo extents;
-
-         XftGlyphExtents (FRAME_DISPLAY (gstring->frame),
-                          font_info->font_aa, &g->code, 1, &extents);
-         g->lbearing = - extents.x;
-         g->rbearing = extents.width - extents.x;
-         g->width = extents.xOff;
-         g->ascent = extents.y;
-         g->descent = extents.height - extents.y;
-       }
+static int
+xft_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
+{
+  int result;
+
+  if (font->type == MFONT_TYPE_REALIZED)
+    {
+      MRealizedFont *rfont = (MRealizedFont *) font;
+      MRealizedFontXft *rfont_xft = rfont->info;
+      
+      rfont->info = rfont_xft->info;
+      result = mfont__ft_driver.has_char (frame, font, spec, c, code);
+      rfont->info = rfont_xft;
     }
+  else
+    result = mfont__ft_driver.has_char (frame, font, spec, c, code);
+  return result;
 }
 
+static unsigned
+xft_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
+{
+  if (font->type == MFONT_TYPE_REALIZED)
+    {
+      MRealizedFont *rfont = (MRealizedFont *) font;
+      MRealizedFontXft *rfont_xft = rfont->info;
+      
+      rfont->info = rfont_xft->info;
+      code = mfont__ft_driver.encode_char (frame, font, spec, code);
+      rfont->info = rfont_xft;
+    }
+  else
+    code = mfont__ft_driver.encode_char (frame, font, spec, code);
+  return code;
+}
 
 static void 
 xft_render (MDrawWindow win, int x, int y,
@@ -1098,15 +1271,16 @@ xft_render (MDrawWindow win, int x, int y,
 {
   MRealizedFace *rface = from->rface;
   MFrame *frame = rface->frame;
-  MFTInfo *ft_info = rface->rfont->info;
-  MXftFontInfo *font_info = ft_info->extra_info;
+  Display *display = FRAME_DISPLAY (frame);
+  MRealizedFont *rfont = rface->rfont;
+  MRealizedFontXft *rfont_xft = rfont->info;
   XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
   XftColor *xft_color = (! reverse
                         ? &((GCInfo *) rface->info)->xft_color_fore
                         : &((GCInfo *) rface->info)->xft_color_back);
-  XftFont *xft_font = (gstring->control.anti_alias
-                      && FRAME_DEVICE (frame)->depth > 1
-                      ? font_info->font_aa : font_info->font_no_aa);
+  int anti_alias = (gstring->control.anti_alias
+                   && FRAME_DEVICE (frame)->depth > 1);
+  XftFont *xft_font;
   MGlyph *g;
   FT_UInt *glyphs;
   int last_x;
@@ -1115,14 +1289,48 @@ xft_render (MDrawWindow win, int x, int y,
   if (from == to)
     return;
 
+  if (anti_alias)
+    {
+      if (rfont_xft->font_aa)
+       xft_font = rfont_xft->font_aa;
+      else
+       {
+         double size = rfont->spec.size;
+
+         xft_font = xft_open_font (display, rfont->spec.file, size / 10,
+                                   FcTrue);
+         if (xft_font)
+           rfont_xft->font_aa = xft_font;
+         else
+           xft_font = rfont->fontp;
+       }
+    }
+  else
+    {
+      if (rfont_xft->font_no_aa)
+       xft_font = rfont_xft->font_no_aa;
+      else
+       {
+         double size = rfont->spec.size;
+
+         xft_font = xft_open_font (display, rfont->spec.file, size / 10,
+                                   FcTrue);
+         if (xft_font)
+           rfont_xft->font_no_aa = xft_font;
+         else
+           xft_font = rfont->fontp;
+       }
+    }
+
   XftDrawChange (xft_draw, (Drawable) win);
   XftDrawSetClip (xft_draw, (Region) region);
       
+  y -= rfont->baseline_offset >> 6;
   glyphs = alloca (sizeof (FT_UInt) * (to - from));
-  for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
+  for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->g.xadv)
     {
-      if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
-       glyphs[nglyphs++] = g->code;
+      if (! g->g.adjusted && !g->left_padding && !g->right_padding)
+       glyphs[nglyphs++] = g->g.code;
       else
        {
          if (nglyphs > 0)
@@ -1130,15 +1338,81 @@ xft_render (MDrawWindow win, int x, int y,
                           last_x, y, glyphs, nglyphs);
          nglyphs = 0;
          XftDrawGlyphs (xft_draw, xft_color, xft_font,
-                        x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
-         last_x = x + g->width;
+                        x + g->g.xoff, y + g->g.yoff, (FT_UInt *) &g->g.code, 1);
+         last_x = x + g->g.xadv;
        }
     }
   if (nglyphs > 0)
     XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
 }
 
-#endif
+static int
+xft_check_capability (MRealizedFont *rfont, MSymbol capability)
+{
+  MRealizedFontXft *rfont_xft = rfont->info;
+  int result;
+      
+  rfont->info = rfont_xft->info;
+  result = mfont__ft_driver.check_capability (rfont, capability);
+  rfont->info = rfont_xft;
+  return result;
+}
+
+static int
+xft_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
+{
+  MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
+  MRealizedFontXft *rfont_xft = rfont->info;
+  int result;
+      
+  rfont->info = rfont_xft->info;
+  result = mfont__ft_driver.check_otf (font, spec);
+  rfont->info = rfont_xft;
+  return result;
+}
+
+static int
+xft_drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
+              MFLTGlyphString *in, int from, int to,
+              MFLTGlyphString *out,
+              MFLTGlyphAdjustment *adjustment)
+{
+  MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
+  MRealizedFontXft *rfont_xft = rfont->info;
+  int result;
+      
+  rfont->info = rfont_xft->info;
+  result = mfont__ft_driver.drive_otf (font, spec, in, from, to, out,
+                                      adjustment);
+  rfont->info = rfont_xft;
+  return result;
+}
+
+static int
+xft_try_otf (MFLTFont *font, MFLTOtfSpec *spec,
+            MFLTGlyphString *in, int from, int to)
+{
+  return xft_drive_otf (font, spec, in, from, to, NULL, NULL);
+}
+
+#ifdef HAVE_OTF
+
+static int
+xft_iterate_otf_feature (struct _MFLTFont *font, MFLTOtfSpec *spec,
+                        int from, int to, unsigned char *table)
+{
+  MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
+  MRealizedFontXft *rfont_xft = rfont->info;
+  int result;
+      
+  rfont->info = rfont_xft->info;
+  result = mfont__ft_driver.iterate_otf_feature (font, spec, from, to, table);
+  rfont->info = rfont_xft;
+  return result;
+}
+#endif /* HAVE_OTF */
+
+#endif /* HAVE_XFT2 */
 
 \f
 /* Functions for the device driver.  */
@@ -1146,7 +1420,9 @@ xft_render (MDrawWindow win, int x, int y,
 static void
 mwin__close_device (MFrame *frame)
 {
-  M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
+  MWDevice *device = FRAME_DEVICE (frame);
+
+  M17N_OBJECT_UNREF (device);
 }
 
 static void *
@@ -1222,7 +1498,7 @@ mwin__realize_face (MRealizedFace *rface)
                           MSYMBOL_NAME (background),
                           &info->xft_color_back))
     mdebug_hook ();
-#endif
+#endif /* HAVE_XFT2 */
 
   hline = rface->hline;
   if (hline)
@@ -1301,9 +1577,9 @@ mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
   for (; from < to; from++)
     {
       XDrawRectangle (display, (Window) win, gc,
-                     x, y - gstring->ascent + 1, from->width - 1,
+                     x, y - gstring->ascent + 1, from->g.xadv - 1,
                      gstring->ascent + gstring->descent - 2);
-      x += from->width;
+      x += from->g.xadv;
     }
 }
 
@@ -1364,9 +1640,9 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
       int x0, x1;
 
       if (g->left_padding)
-       x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
+       x0 = x + box->outer_hmargin, x1 = x + g->g.xadv - 1;
       else
-       x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
+       x0 = x, x1 = x + g->g.xadv - box->outer_hmargin - 1;
 
       /* Draw the top side.  */
       for (i = 0; i < box->width; i++)
@@ -1582,6 +1858,12 @@ mwin__create_window (MFrame *frame, MDrawWindow parent)
 static void
 mwin__destroy_window (MFrame *frame, MDrawWindow win)
 {
+#ifdef HAVE_XFT2
+  XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
+
+  if (XftDrawDrawable (xft_draw) == (Drawable) win)
+    XftDrawChange (xft_draw, FRAME_DEVICE (frame)->drawable);
+#endif /* HAVE_XFT2 */
   XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
 }
 
@@ -1741,25 +2023,20 @@ mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
   len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
   if (len > 1)
     return Mnil;
-  if (len == 1)
+  if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
+    return Mnil;
+#ifdef XK_XKB_KEYS
+  if ((keysym & 0xff00) == 0xfe00)
+    return Mnil;
+#endif
+  if (len == 1 && keysym >= XK_space && keysym <= XK_asciitilde)
     {
       int c = keysym;
 
-      if (c < XK_space || c > XK_asciitilde)
-       c = buf[0];
-      if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
-       *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
-      if (((XKeyEvent *) event)->state & ControlMask)
-       {
-         if (c >= 'a' && c <= 'z')
-           c += 'A' - 'a';
-         if (c >= ' ' && c < 127)
-           *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
-       }
       key = minput__char_to_key (c);
+      if (c == ' ' && ((XKeyEvent *) event)->state & ShiftMask)
+       *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
     }
-  else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
-    return Mnil;
   else
     {
       char *str = XKeysymToString (keysym);
@@ -1769,9 +2046,9 @@ mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
       key = msymbol (str);
       if (((XKeyEvent *) event)->state & ShiftMask)
        *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
-      if (((XKeyEvent *) event)->state & ControlMask)
-       *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
     }
+  if (((XKeyEvent *) event)->state & ControlMask)
+    *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
   if (((XKeyEvent *) event)->state & disp_info->meta_mask)
     *modifiers |= MINPUT_KEY_META_MODIFIER;
   if (((XKeyEvent *) event)->state & disp_info->alt_mask)
@@ -1780,7 +2057,10 @@ mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
     *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
   if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
     *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
-
+#ifdef XK_XKB_KEYS
+  if (((XKeyEvent *) event)->state & disp_info->altgr_mask)
+    *modifiers |= MINPUT_KEY_ALTGR_MODIFIER;
+#endif
   return key;
 }
 
@@ -1843,8 +2123,8 @@ device_init ()
 
 #ifdef HAVE_XFT2
   xft_driver.select = mfont__ft_driver.select;
-  xft_driver.encode_char = mfont__ft_driver.encode_char;
   xft_driver.list = mfont__ft_driver.list;
+  xft_driver.list_family_names = mfont__ft_driver.list_family_names;
 #endif
 
   Mxim = msymbol ("xim");
@@ -1861,6 +2141,23 @@ device_fini ()
   return 0;
 }
 
+
+#ifdef X_SET_ERROR_HANDLER
+static int
+x_error_handler (Display *display, XErrorEvent *error)
+{
+  mdebug_hook ();
+  return 0;
+}
+
+static int
+x_io_error_handler (Display *display)
+{
+  mdebug_hook ();
+  return 0;
+}
+#endif
+
 /** Return an MWDevice object corresponding to a display specified in
     PLIST.
 
@@ -1885,7 +2182,9 @@ device_open (MFrame *frame, MPlist *param)
   unsigned depth = 0;
   MPlist *plist;
   AppData app_data;
+  MFont *font = NULL;
   MFace *face;
+  int use_xfont = 0, use_freetype = 0, use_xft = 0;
 
   for (plist = param; (key = mplist_key (plist)) != Mnil;
        plist = mplist_next (plist))
@@ -1902,8 +2201,27 @@ device_open (MFrame *frame, MPlist *param)
        widget = (Widget) mplist_value (plist);
       else if (key == Mcolormap)
        cmap = (Colormap) mplist_value (plist);
+      else if (key == Mfont)
+       {
+         MSymbol val = MPLIST_SYMBOL (plist);
+
+         if (val == Mx)
+           use_xfont = 1;
+#ifdef HAVE_FREETYPE
+         else if (val == Mfreetype)
+           use_freetype = 1;
+#ifdef HAVE_XFT2
+         else if (val == Mxft)
+           use_xft = 1;
+#endif
+#endif
+       }
     }
 
+  /* If none of them is specified, use all of them.  */
+  if (! use_xfont && ! use_freetype && ! use_xft)
+    use_xfont = use_freetype = use_xft = 1;
+
   if (widget)
     {
       display = XtDisplay (widget);
@@ -1962,8 +2280,11 @@ device_open (MFrame *frame, MPlist *param)
       disp_info->display = display;
       disp_info->auto_display = auto_display;
       disp_info->font_list = mplist ();
-      disp_info->base_font_list = mplist ();
       find_modifier_bits (disp_info);
+      disp_info->MULE_BASELINE_OFFSET
+       = XInternAtom (display, "_MULE_BASELINE_OFFSET", False);
+      disp_info->AVERAGE_WIDTH
+       = XInternAtom (display, "AVERAGE_WIDTH", False);
       mplist_add (display_info_list, Mt, disp_info);
     }  
 
@@ -1973,7 +2294,8 @@ device_open (MFrame *frame, MPlist *param)
       device = (MWDevice *) mplist_value (plist);
       if (device->display_info == disp_info
          && device->depth == depth
-         && device->cmap == cmap)
+         && device->cmap == cmap
+         && device->screen_num == screen_num)
        break;
     }
 
@@ -1983,6 +2305,7 @@ device_open (MFrame *frame, MPlist *param)
     {
       unsigned long valuemask = GCForeground;
       XGCValues values;
+      double pixels, mm;
 
       M17N_OBJECT (device, free_device, MERROR_WIN);
       device->display_info = disp_info;
@@ -1993,8 +2316,12 @@ device_open (MFrame *frame, MPlist *param)
                                        1, 1, depth);
       device->depth = depth;
       device->cmap = cmap;
+      pixels = DisplayHeight (display, screen_num);
+      mm = DisplayHeightMM (display, screen_num);
+      device->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
       device->realized_face_list = mplist ();
       device->realized_font_list = mplist ();
+      mplist_add (device->realized_font_list, Mt, NULL);
       device->realized_fontset_list = mplist ();
       device->gc_list = mplist ();
       values.foreground = BlackPixel (display, screen_num);
@@ -2009,14 +2336,23 @@ device_open (MFrame *frame, MPlist *param)
 
   frame->device = device;
   frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
+  frame->dpi = device->resy;
   frame->driver = &x_driver;
   frame->font_driver_list = mplist ();
-  mplist_add (frame->font_driver_list, Mx, &xfont_driver);
 #ifdef HAVE_XFT2
-  mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
-#elif HAVE_FREETYPE
-  mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
-#endif
+  if (use_xft)
+    {
+      mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
+      use_freetype = 0;
+    }
+#endif /* HAVE_XFT2 */
+#ifdef HAVE_FREETYPE
+  if (use_freetype)
+    mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
+#endif /* HAVE_FREETYPE */
+  if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list))
+    mplist_add (frame->font_driver_list, Mx, &xfont_driver);
+
   frame->realized_font_list = device->realized_font_list;
   frame->realized_face_list = device->realized_face_list;
   frame->realized_fontset_list = device->realized_fontset_list;
@@ -2048,41 +2384,28 @@ device_open (MFrame *frame, MPlist *param)
       frame->videomode = Mnormal;
     }
 
-  {
-    int nfonts;
-    char **names = XListFonts (display, app_data.font, 1, &nfonts);
-
-    if (nfonts > 0)
-      {
-       if (! (frame->font = mfont_parse_name (names[0], Mx)))
-         {
-           /* The font name does not conform to XLFD.  Try to open the
-              font and get XA_FONT property.  */
-           XFontStruct *xfont = XLoadQueryFont (display, names[0]);
-
-           nfonts = 0;
-           if (xfont)
-             {
-               unsigned long value;
-               char *name;
-
-               if (XGetFontProperty (xfont, XA_FONT, &value)
-                   && (name = ((char *)
-                               XGetAtomName (display, (Atom) value))))
-                 {
-                   if ((frame->font = mfont_parse_name (name, Mx)))
-                     nfonts = 1;
-                 }
-               XFreeFont (display, xfont);
-             }
-         }
-       XFreeFontNames (names);
-      }
-    if (! nfonts)
-      frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
-  }
+  if (strcmp (app_data.font, DEFAULT_FONT) != 0)
+    {
+      XFontStruct *xfont = XLoadQueryFont (display, app_data.font);
+      unsigned long value;
+      char *name;
 
-  face = mface_from_font (frame->font);
+      if (xfont)
+       {
+         font = mfont_parse_name (app_data.font, Mx);
+         if (! font
+             && XGetFontProperty (xfont, XA_FONT, &value)
+             && (name = ((char *) XGetAtomName (display, (Atom) value))))
+           font = mfont_parse_name (name, Mx);
+         XFreeFont (display, xfont);
+       }
+    }
+  if (! font)
+      font = mfont_parse_name (DEFAULT_FONT, Mx);
+  else if (! font->size)
+    font->size = 130;
+  face = mface_from_font (font);
+  free (font);
   face->property[MFACE_FONTSET] = mfontset (NULL);
   face->property[MFACE_FOREGROUND] = frame->foreground;
   face->property[MFACE_BACKGROUND] = frame->background;
@@ -2099,7 +2422,6 @@ device_open (MFrame *frame, MPlist *param)
   XSetErrorHandler (x_error_handler);
   XSetIOErrorHandler (x_io_error_handler);
 #endif
-
   return 0;
 }
 
@@ -2294,23 +2616,6 @@ xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
 }
 
 \f
-
-#ifdef X_SET_ERROR_HANDLER
-static int
-x_error_handler (Display *display, XErrorEvent *error)
-{
-  mdebug_hook ();
-  return 0;
-}
-
-static int
-x_io_error_handler (Display *display)
-{
-  mdebug_hook ();
-  return 0;
-}
-#endif
-
 /*=*/
 
 /*** @} */
@@ -2319,9 +2624,9 @@ x_io_error_handler (Display *display)
 /* External API */
 
 /*** @addtogroup m17nInputMethodWin */
-/*=*/
-/*** @{ */
 
+/*** @{ */
+/*=*/
 /***en
     @brief Input method driver for XIM.
 
@@ -2354,37 +2659,39 @@ x_io_error_handler (Display *display)
 /***ja
     @brief XIMÍÑÆþÎϥɥ饤¥Ð.
 
-    ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
-    ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
-    ¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
+    ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ê¡¢
+    XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
 
     ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
-    #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
-    ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
+    #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim 
+    ¤Ç¤¢¤ëÆþÎϥ᥽¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
 
-    ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
-    ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
+    ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ 
+    ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
 
-    ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIM ¤Ø¤Î¥Ý
-    ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
-    »²¾È¡£
+    ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIM 
+    ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò»²¾È¡£
 
-    ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIC ¤Ø¤Î
-    ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
-    ¤ò»²¾È¡£
+    ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIC 
+    ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ¤ò»²¾È¡£
 
-    ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ@c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
-    ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
+    ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ@c XEvent 
+    ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
 
     ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter () 
-    ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì
-    ¤ë¡£  */
+    ¤Î°ú¿ô $ARG ¤ÈƱ¤¸¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£ °ú¿ô $KEY ¤Ï¡¢Ìµ»ë¤µ¤ì¤ë¡£  */
 
 MInputDriver minput_xim_driver =
   { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
     xim_filter, xim_lookup, NULL };
-
+/*=*/
 /*** @} */ 
+/*=*/
+#else  /* not HAVE_X11 */
+
+int device_open () { return -1; }
+
+#endif /* not HAVE_X11 */
 
 /*
   Local Variables: