(MDisplayInfo): New member altgr_mask.
[m17n/m17n-lib.git] / src / m17n-X.c
index fa1b348..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 <X11/StringDefs.h>
 #include <X11/Intrinsic.h>
 
+#ifdef HAVE_XFT2
+#include <X11/Xft/Xft.h>
+#include <fontconfig/fcfreetype.h>
+#endif /* HAVE_XFT2 */
+
 #include "m17n-gui.h"
 #include "m17n-X.h"
 #include "m17n-misc.h"
@@ -61,24 +70,24 @@ typedef struct
      be closed on freeing this structure.  */
   int auto_display;
 
-  /** List of available fonts on the display (except for iso8859-1 and
-      iso10646-1 fonts).  Keys are font registries, values are
-      (MFontList *).  */
-  MPlist *font_registry_list;
-
-  MPlist *iso8859_1_family_list;
+  /** 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 MFont.  */
+  MPlist *font_list;
 
-  MPlist *iso10646_1_family_list;
-
-  /* List of information about each font.  Keys are font registries,
-     values are (MFontInfo *).  */
-  MPlist *realized_font_list;
+  /** Nonzero means that <font_list> already contains all available
+      fonts on the display.  */
+  int all_fonts_scaned;
 
  /** Modifier bit masks of the display.  */
   int meta_mask;
   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.  */
@@ -111,9 +120,12 @@ typedef struct
   /* The first 8 elements are indexed by an intensity for
      anti-aliasing.  The 2nd to 7th are created on demand.  */
   GC gc[GC_MAX];
+#ifdef HAVE_XFT2
+  XftColor xft_color_fore, xft_color_back;
+#endif
 } GCInfo;
 
-struct MWDevice
+typedef struct
 {
   /* Common header for the m17n object.  */
   M17NObject control;
@@ -130,25 +142,38 @@ struct MWDevice
 
   GC scratch_gc;
 
+  int resy;
+
+#ifdef HAVE_XFT2
+  XftDraw *xft_draw;
+#endif
+
   /** List of pointers to realized faces on the frame.  */
   MPlist *realized_face_list;
 
+  /* 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.  */
   MPlist *realized_fontset_list;
 
   /** List of XColors vs GCs on the frame.  */
   MPlist *gc_list;
-};
+} MWDevice;
 
 static MPlist *device_list;
 
 static MSymbol M_iso8859_1, M_iso10646_1;
 
-#define FRAME_DISPLAY(frame) (frame->device->display_info->display)
-#define FRAME_SCREEN(frame) (frame->device->screen_num)
+#define FRAME_DEVICE(frame) ((MWDevice *) (frame)->device)
+#define FRAME_DISPLAY(frame) (FRAME_DEVICE (frame)->display_info->display)
+#define FRAME_SCREEN(frame) (FRAME_DEVICE (frame)->screen_num)
+#define FRAME_CMAP(frame) (FRAME_DEVICE (frame)->cmap)
+#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
 {
@@ -162,45 +187,15 @@ static void
 free_display_info (void *object)
 {
   MDisplayInfo *disp_info = (MDisplayInfo *) object;
-  MPlist *plist;
-
-  for (plist = disp_info->font_registry_list;
-       mplist_key (plist) != Mnil; plist = mplist_next (plist))
-    {
-      MFontList *registry_list = mplist_value (plist);
-
-      if (registry_list->fonts)
-       free (registry_list->fonts);
-      free (registry_list);
-    }
-  M17N_OBJECT_UNREF (disp_info->font_registry_list);
-
-  for (plist = disp_info->iso8859_1_family_list;
-       mplist_key (plist) != Mnil; plist = mplist_next (plist))
-    {
-      MFontList *family_list = mplist_value (plist);
-
-      if (family_list->fonts)
-       free (family_list->fonts);
-      free (family_list);
-    }
-  M17N_OBJECT_UNREF (disp_info->iso8859_1_family_list);
+  MPlist *plist, *pl;
 
-  for (plist = disp_info->iso10646_1_family_list;
-       mplist_key (plist) != Mnil; plist = mplist_next (plist))
+  MPLIST_DO (plist, disp_info->font_list)
     {
-      MFontList *family_list = mplist_value (plist);
-
-      if (family_list->fonts)
-       free (family_list->fonts);
-      free (family_list);
+      MPLIST_DO (pl, MPLIST_VAL (plist))
+       free (MPLIST_VAL (pl));
+      M17N_OBJECT_UNREF (MPLIST_VAL (plist));
     }
-  M17N_OBJECT_UNREF (disp_info->iso10646_1_family_list);
-
-  for (plist = disp_info->realized_font_list;
-       mplist_key (plist) != Mnil; plist = mplist_next (plist))
-    mfont__free_realized ((MRealizedFont *) mplist_value (plist));
-  M17N_OBJECT_UNREF (disp_info->realized_font_list);
+  M17N_OBJECT_UNREF (disp_info->font_list);
 
   if (disp_info->auto_display)
     XCloseDisplay (disp_info->display);
@@ -211,7 +206,7 @@ free_display_info (void *object)
 static void
 free_device (void *object)
 {
-  MWDevice *device = (MWDevice *) object;
+  MWDevice *device = object;
   MPlist *plist;
 
   for (plist = device->realized_fontset_list;
@@ -219,9 +214,17 @@ free_device (void *object)
     mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist));
   M17N_OBJECT_UNREF (device->realized_fontset_list);
 
-  for (plist = device->realized_face_list;
-       mplist_key (plist) != Mnil; plist = mplist_next (plist))
-    mface__free_realized ((MRealizedFace *) mplist_value (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)
+    {
+      MRealizedFace *rface = MPLIST_VAL (plist);
+
+      free (rface->info);
+      mface__free_realized (rface);
+    }
   M17N_OBJECT_UNREF (device->realized_face_list);
 
   MPLIST_DO (plist, device->gc_list)
@@ -233,6 +236,10 @@ free_device (void *object)
   M17N_OBJECT_UNREF (device->gc_list);
   XFreeGC (device->display_info->display, device->scratch_gc);
 
+#ifdef HAVE_XFT2
+  XftDrawDestroy (device->xft_draw);
+#endif
+
   XFreePixmap (device->display_info->display, device->drawable);
   M17N_OBJECT_UNREF (device->display_info);
   free (object);
@@ -252,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);
@@ -272,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
@@ -324,7 +338,7 @@ get_rgb_gc (MWDevice *device, XColor *xcolor)
 static GC
 get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret)
 {
-  MWDevice *device = frame->device;
+  MWDevice *device = FRAME_DEVICE (frame);
   XColor xcolor;
   RGB_GC *rgb_gc;
 
@@ -387,443 +401,424 @@ get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity)
   return (info->gc[intensity] = gc);
 }
 
+static GC
+set_region (MFrame *frame, GC gc, MDrawRegion region)
+{
+  unsigned long valuemask = GCForeground;
+
+  XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
+          FRAME_DEVICE (frame)->scratch_gc);
+  XSetRegion (FRAME_DISPLAY (frame), FRAME_DEVICE (frame)->scratch_gc, region);
+  return FRAME_DEVICE (frame)->scratch_gc;
+}
+
 \f
 /** X font handler */
 
-/** Indices to each field of split font name.  */
-
-enum xlfd_field_idx
-  {
-    XLFD_FOUNDRY,
-    XLFD_FAMILY,
-    XLFD_WEIGHT,
-    XLFD_SLANT,
-    XLFD_SWIDTH,
-    XLFD_ADSTYLE,
-    XLFD_PIXEL,
-    XLFD_POINT,
-    XLFD_RESX,
-    XLFD_RESY,
-    XLFD_SPACING,
-    XLFD_AVGWIDTH,
-    XLFD_REGISTRY,
-    XLFD_ENCODING,
-    /* anchor */
-    XLFD_FIELD_MAX
+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 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 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_has_char, xfont_encode_char,
+    xfont_render, xfont_list, xfont_list_family_names, xfont_check_capability
   };
 
-/** Split the fontname NAME into each XLFD field destructively.  Set
-    each element of the table pointed by PROPERTY_IDX to a pointer to
-    the corresponding font property name.  Store the point size and
-    the resolution-Y of the font to the place pointed by POINT and
-    RESY respectively.
-
-    If NAME does not contain all XLFD fields, the unspecified fields is
-    treated as wild cards.  */
-
 static int
-split_font_name (char *name, char **field,
-                unsigned short *size, unsigned short *resy)
+font_compare (const void *p1, const void *p2)
 {
-  int i;
-  char *p;
+  return strcmp (*(char **) p1, *(char **) p2);
+}
 
-  for (i = 0, p = name; *p; p++)
-    {
-      *p = tolower (*p);
-      if (*p == '-' && i < XLFD_FIELD_MAX)
-       {
-         field[i] = p + 1;
-         if (i != XLFD_ENCODING)
-           *p = '\0';
-         i++;
-       }
-    }
-  if (i < XLFD_REGISTRY)
-    return -1;
-  for (; i < XLFD_FIELD_MAX; i++)
-    field[i] = "*";
+static MPlist *
+xfont_registry_list (MFrame *frame, MSymbol registry)
+{
+  MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
+  MPlist *font_list = disp_info->font_list;
+  MPlist *plist, *p;
+  char pattern[1024];
+  char **font_names, **names;
+  int nfonts;
+  int i, j;
+  MFont font;
+  int for_full_width;
+
+  plist = mplist_get (font_list, registry);
+  if (plist)
+    return plist;
+  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);
 
-  if (*(field[XLFD_RESY]) == '*')
-    *resy = 0;
-  else
-    *resy = atoi (field[XLFD_RESY]);
-  if (*(field[XLFD_PIXEL]) == '*')
-    {
-      if (*(field[XLFD_POINT]) != '*')
-       *size = atoi (field[XLFD_POINT]) * *resy / 72;
-      else
-       *size = 0;
-    }
-  else if (*(field[XLFD_PIXEL]) == '[')
-    {
-      /* The pixel size field specifies a transformation matrix of the
-        form "[A B C D]".  The XLFD spec says that the scalar value N
-        for the pixel size is equivalent to D.  */
-      char *p0 = field[XLFD_PIXEL] + 1, *p1;
-      double d;
-
-      for (i = 0; i < 4; i++, p0 = p1)
-       d = strtod (p0, &p1);
-      *size = d * 10;
-    }
-  else
-    *size = atoi (field[XLFD_PIXEL]) * 10;
-  if (*size == 0 && *(field[XLFD_POINT]) != '*')
-    {
-      *size = atoi (field[XLFD_POINT]);
-      if (*resy)
-       *size = *size * *resy / 72;
-      else
-       *size = *size * 100 / 72;
-    }
+    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);
+  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 (&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;
+       
+       /* 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] + 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, &font) == 0
+             && (font.size > 0 || font.property[MFONT_RESY] == 0))
+           {
+             size = font.size / 10;
+             sizes[nsizes++] = size;
+             normal_size |= (size >= 6 && size <= 29);
+           }
 
-  return 0;
+       font.for_full_width = for_full_width;
+       font.type = MFONT_TYPE_OBJECT;
+       font.source = MFONT_SOURCE_X;
+       if (normal_size)
+         {
+           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;
 }
 
-static int
-build_font_name (MFont *font, char *name, int limit)
-{
-  MSymbol prop[7];
-  char *str[7];
-  int len, i;
-  unsigned short size, resy;
-
-  prop[0] = (MSymbol) mfont_get_prop (font, Mfoundry);
-  prop[1] = (MSymbol) mfont_get_prop (font, Mfamily);
-  prop[2] = (MSymbol) mfont_get_prop (font, Mweight);
-  prop[3] = (MSymbol) mfont_get_prop (font, Mstyle);
-  prop[4] = (MSymbol) mfont_get_prop (font, Mstretch);
-  prop[5] = (MSymbol) mfont_get_prop (font, Madstyle);
-  prop[6] = (MSymbol) mfont_get_prop (font, Mregistry);
-  for (len = 0, i = 0; i < 7; i++)
-    {
-      if (prop[i] != Mnil)
-       {
-         str[i] = msymbol_name (prop[i]);
-         len += strlen (str[i]);
-       }
-      else
-       {
-         str[i] = "*";
-         len++;
-       }
-    }
-  if ((len
-       + 12                    /* 12 dashes */
-       + 3                     /* 3 asterisks */
-       + 30                    /* 3 integers (each 10 digits) */
-       + 1)                    /* '\0' terminal */
-      > limit)
-    return -1;
-
-  size = (int) mfont_get_prop (font, Msize);
-  if ((size % 10) < 5)
-    size /= 10;
-  else
-    size = size / 10 + 1;
-  resy = (int) mfont_get_prop (font, Mresolution);
+static void
+xfont_list_all (MFrame *frame)
+{
+  MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
+  MPlist *font_encoding_list, *p;
 
-  sprintf (name, "-%s-%s-%s-%s-%s-%s-%d-*-%d-%d-*-*-%s",
-          str[0], str[1], str[2], str[3], str[4], str[5],
-          size, resy, resy,  str[6]);
-  return 0;
+  if (disp_info->all_fonts_scaned)
+    return;
+  disp_info->all_fonts_scaned = 1;
+  font_encoding_list = mfont__encoding_list ();
+  if (! font_encoding_list)
+    return;
+  MPLIST_DO (p, font_encoding_list)
+    xfont_registry_list (frame, MPLIST_KEY (p));
 }
 
-static MFontList *
-build_font_list (MFrame *frame, MSymbol family, MSymbol registry,
-                MPlist *plist)
+typedef struct
 {
-  char pattern[1024];
-  MFontList *font_list;
-  char **fontnames;
-  int nfonts;
-  int i, j;
+  M17NObject control;
+  Display *display;
+  XFontStruct *xfont;
+} MRealizedFontX;
 
-  MSTRUCT_CALLOC (font_list, MERROR_WIN);
+/* The X font driver function SELECT.  */
 
-  if (family == Mnil)
-    {
-      sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s",
-              msymbol_name (registry));
-      font_list->tag = registry;
-    }
-  else
-    {
-      sprintf (pattern, "-*-%s-*-*-*-*-*-*-*-*-*-*-%s",
-              msymbol_name (family), msymbol_name (registry));
-      font_list->tag = family;
-    }
+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;
 
-  fontnames = XListFonts (FRAME_DISPLAY (frame), pattern, 0x8000, &nfonts);
-  if (nfonts > 0)
-    {
-      MTABLE_MALLOC (font_list->fonts, nfonts, MERROR_WIN);
-      for (i = j = 0; i < nfonts; i++)
-       if (mwin__parse_font_name (fontnames[i], font_list->fonts + j) >= 0
-           && (font_list->fonts[j].property[MFONT_SIZE] != 0
-               || font_list->fonts[j].property[MFONT_RESY] == 0))
+  if (num > 0)
+    MPLIST_DO (pl, plist)
+      {
+       font = MPLIST_VAL (pl);
+       if (limited_size == 0
+           || font->size == 0
+           || font->size <= limited_size)
          {
-           font_list->fonts[j].property[MFONT_TYPE] = MFONT_TYPE_WIN + 1;
-           j++;
+           found = font;
+           break;
          }
-      XFreeFontNames (fontnames);
-      font_list->nfonts = j;
-    }
-  mplist_add (plist, font_list->tag, font_list);
-  return (nfonts > 0 ? font_list : NULL);
+      }
+  M17N_OBJECT_UNREF (plist);
+  return found;
 }
 
+/* The X font driver function CLOSE.  */
 
-static MRealizedFont *xfont_select (MFrame *, MFont *, MFont *, int);
-static int xfont_open (MRealizedFont *);
-static void xfont_close (MRealizedFont *);
-static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int);
-static unsigned xfont_encode_char (MRealizedFont *, int, unsigned);
-static void xfont_render (MDrawWindow, int, int, MGlyphString *,
-                         MGlyph *, MGlyph *, int, MDrawRegion);
+static void
+close_xfont (void *object)
+{
+  MRealizedFontX *x_rfont = object;
 
-MFontDriver xfont_driver =
-  { xfont_select, xfont_open, xfont_close,
-    xfont_find_metric, xfont_encode_char, xfont_render };
+  XFreeFont (x_rfont->display, x_rfont->xfont);
+  free (x_rfont);
+}
 
-/* The X font driver function SELECT.  */
+/* The X font driver function OPEN.  */
 
 static MRealizedFont *
-xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
+xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
 {
-  MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
-  MRealizedFont *rfont;
-  MFontList *font_list = NULL;
-  int i;
-  MFont *best_font;
-  int best_score, score;
-
-  if (registry == Mnil
-      || ! strchr (MSYMBOL_NAME (registry), '-'))
-    return NULL;
-
-  /* We handles iso8859-1 and iso10646-1 fonts specially because there
-     exists so many such fonts.  */
-  if (registry == M_iso8859_1 || registry == M_iso10646_1)
-    {
-      MPlist *family_list
-       = (registry == M_iso8859_1
-          ? frame->device->display_info->iso8859_1_family_list
-          : frame->device->display_info->iso10646_1_family_list);
-      MSymbol family = FONT_PROPERTY (spec, MFONT_FAMILY);
+  int size;
+  MRealizedFontX *x_rfont;
+  char *name;
+  Display *display = FRAME_DISPLAY (frame);
+  XFontStruct *xfont;
+  int mdebug_flag = MDEBUG_FONT;
+  MFont this;
 
-      if (family != Mnil)
-       {
-         font_list = (MFontList *) mplist_get (family_list, family);
-         if (! font_list)
-           font_list = build_font_list (frame, family, registry, family_list);
-       }
-      if (! font_list)
-       {
-         family = FONT_PROPERTY (request, MFONT_FAMILY);
-         font_list = (MFontList *) mplist_get (family_list, family);
-         if (! font_list)
-           font_list = build_font_list (frame, family, registry, family_list);
-       }
-    }
-  if (! font_list)
+  size = spec->size;
+  if (size)
     {
-      MPlist *registry_list
-       = frame->device->display_info->font_registry_list;
+      int ratio = mfont_resize_ratio (font);
 
-      font_list = (MFontList *) mplist_get (registry_list, registry);
-      if (! font_list)
-       font_list = build_font_list (frame, Mnil, registry, registry_list);
+      if (ratio != 100)
+       size = size * ratio / 100;
     }
-  if (! font_list)
-    return NULL;
+  else
+    size = 120;
 
-  for (i = 0, best_score = -1, best_font = NULL; i < font_list->nfonts; i++)
-    if ((best_score = mfont__score (font_list->fonts + i, spec, request,
-                                   limited_size)) >= 0)
-      break;
-  if (best_score < 0)
-    return NULL;
-  best_font = font_list->fonts + i;
-  for (; best_score > 0 && i < font_list->nfonts ; i++)
+  if (font->size)
     {
-      score = mfont__score (font_list->fonts + i, spec, request,
-                           limited_size);
-      if (score >= 0 && score < best_score)
+      /* non-scalable font */
+      if (font->multiple_sizes)
        {
-         best_font = font_list->fonts + i;
-         best_score = score;
+         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;
     }
 
-  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;
-  rfont->driver = &xfont_driver;
-  return rfont;
-}
-
-typedef struct
-{
-  M17NObject control;
-  MFrame *frame;
-  XFontStruct *f;
-} MXFontInfo;
-
-static void
-close_xfont (void *object)
-{
-  MXFontInfo *xfont = (MXFontInfo *) object;
-
-  if (xfont->f)
-    XFreeFont (FRAME_DISPLAY (xfont->frame), xfont->f);
-  free (object);
-}
-
-
-/* The X font driver function OPEN.  */
+  if (rfont)
+    {
+      for (; rfont; rfont = rfont->next)
+       if (rfont->font == font && rfont->spec.size == size)
+         return rfont;
+    }
 
-static int
-xfont_open (MRealizedFont *rfont)
-{
-  char name[1024];
-  MXFontInfo *xfont;
-  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.  */
-  build_font_name (&rfont->font, name, 1024);
-  M17N_OBJECT (xfont, close_xfont, MERROR_WIN);
-  rfont->info = xfont;
-  xfont->frame = frame;
-  xfont->f = XLoadQueryFont (FRAME_DISPLAY (frame), name);
-  if (! xfont->f)
+  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;
       MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
-      return -1;
+      free (name);
+      font->type = MFONT_TYPE_FAILURE;
+      return NULL;
     }
+  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);
-  rfont->status = 1;
-  rfont->ascent = xfont->f->ascent;
-  rfont->descent = xfont->f->descent;
-  return 0;
+  free (name);
+  return rfont;
 }
 
 
-/* The X font driver function CLOSE.  */
-
-static void
-xfont_close (MRealizedFont *rfont)
-{
-  M17N_OBJECT_UNREF (rfont->info);
-}
-
 /* The X font driver function FIND_METRIC.  */
 
 static void
 xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
                   int from, int to)
 {
-  MXFontInfo *xfont = (MXFontInfo *) rfont->info;
-  XFontStruct *f = xfont->f;
+  XFontStruct *xfont = rfont->fontp;
   MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
 
   for (; g != gend; g++)
-    {
-      if (g->code == MCHAR_INVALID_CODE)
-       {
-         g->lbearing = f->max_bounds.lbearing;
-         g->rbearing = f->max_bounds.rbearing;
-         g->width = f->max_bounds.width;
-         g->ascent = f->ascent;
-         g->descent = f->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 (f->per_char != NULL)
-           {
-             if (f->min_byte1 == 0 && f->max_byte1 == 0)
-               {
-                 if (byte1 == 0
-                     && byte2 >= f->min_char_or_byte2
-                     && byte2 <= f->max_char_or_byte2)
-                   pcm = f->per_char + byte2 - f->min_char_or_byte2;
-               }
-             else
-               {
-                 if (byte1 >= f->min_byte1
-                     && byte1 <= f->max_byte1
-                     && byte2 >= f->min_char_or_byte2
-                     && byte2 <= f->max_char_or_byte2)
-                   {
-                     pcm = (f->per_char
-                            + ((f->max_char_or_byte2-f->min_char_or_byte2 + 1)
-                               * (byte1 - f->min_byte1))
-                            + (byte2 - f->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 = f->max_bounds.width;
-             g->width = f->max_bounds.width;
-             g->ascent = f->ascent;
-             g->descent = f->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;
+      }
 }
 
 
-/* The X font driver function ENCODE_CHAR.  */
+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, int c, unsigned code)
+xfont_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
 {
-  MXFontInfo *xfont;
-  XFontStruct *f;
+  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 = (MXFontInfo *) rfont->info;
-  f = xfont->f;
-  all_chars_exist = (! f->per_char || f->all_chars_exist == True);
-  min_byte1 = f->min_byte1;
-  max_byte1 = f->max_byte1;
-  min_byte2 = f->min_char_or_byte2;
-  max_byte2 = f->max_char_or_byte2;
+  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;
+  min_byte2 = xfont->min_char_or_byte2;
+  max_byte2 = xfont->max_char_or_byte2;
 
   if (min_byte1 == 0 && max_byte1 == 0)
     {
@@ -833,7 +828,7 @@ xfont_encode_char (MRealizedFont *rfont, int c, unsigned code)
        return MCHAR_INVALID_CODE;
       if (all_chars_exist)
        return code;
-      pcm = f->per_char + (code - min_byte2);
+      pcm = xfont->per_char + (code - min_byte2);
       return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
              ? code : MCHAR_INVALID_CODE);
     }
@@ -848,24 +843,13 @@ xfont_encode_char (MRealizedFont *rfont, int c, unsigned code)
 
       if (all_chars_exist)
        return code;
-      pcm = f->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
+      pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
                           + (byte2 - min_byte2));
       return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
              ? code : MCHAR_INVALID_CODE);
     }
 }
 
-static GC
-set_region (MFrame *frame, GC gc, MDrawRegion region)
-{
-  unsigned long valuemask = GCForeground;
-
-  XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
-          frame->device->scratch_gc);
-  XSetRegion (FRAME_DISPLAY (frame), frame->device->scratch_gc, region);
-  return frame->device->scratch_gc;
-}
-
 /* The X font driver function RENDER.  */
 
 static void
@@ -873,61 +857,45 @@ xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
              MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
 {
   MRealizedFace *rface = from->rface;
-  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);
-  if (! rface->rfont || from->code == MCHAR_INVALID_CODE)
-    {
-      int x0 = x;
-
-      for (; from < to; from++)
-       {
-         XDrawRectangle (display, (Window) win, gc,
-                         x0, y - gstring->ascent + 1, from->width - 1,
-                         gstring->ascent + gstring->descent - 2);
-         x0 += from->width;
-       }
-      return;
-    }
-
-  XSetFont (display, gc, ((MXFontInfo *) (rface->rfont->info))->f->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)
@@ -936,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
@@ -952,538 +921,515 @@ 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);
        }
     }
 }
 
-\f
+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;
+  int size = font ? font->size : 0;
+  MPlist *pl, *p;
+  int num = 0;
+  int mdebug_flag = MDEBUG_FONT;
+
+  MDEBUG_PRINT2 (" [X-FONT] listing %s-%s...",
+                family ? msymbol_name (family) : "*",
+                registry ? msymbol_name (registry) : "*");
+
+  if (registry == Mnil)
+    xfont_list_all (frame);
+  else
+    xfont_registry_list (frame, registry);
 
-/* XIM (X Input Method) handler */
+  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))
+           {
+             MFont *fontx = MPLIST_VAL (p);
 
-typedef struct MInputXIMMethodInfo
+             if (! font || (mfont__match_p (fontx, font, MFONT_REGISTRY)))
+               {
+                 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;
+               }
+           }
+      }
+
+ done:
+  MDEBUG_PRINT1 (" %d found\n", num);
+  return num;
+}
+
+static void
+xfont_list_family_names (MFrame *frame, MPlist *plist)
 {
-  Display *display;
-  XIM xim;
-  MSymbol language;
-  MSymbol coding;
-} MInputXIMMethodInfo;
-
-typedef struct MInputXIMContextInfo
-{
-  XIC xic;
-  Window win;
-  MConverter *converter;
-} MInputXIMContextInfo;
-
-static int
-xim_open_im (MInputMethod *im)
-{
-  MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
-  MLocale *saved, *this;
-  char *save_modifier_list;
-  XIM xim;
-  MInputXIMMethodInfo *im_info;
+  MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
+  char **font_names;
+  int i, nfonts;
+  MSymbol last_family = Mnil;
 
-  saved = mlocale_set (LC_CTYPE, NULL);
-  this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
-  if (! this)
-    /* The specified locale is not supported.  */
-    MERROR (MERROR_LOCALE, -1);
-  if (mlocale_get_prop (this, Mcoding) == Mnil)
+  font_names = XListFonts (disp_info->display,
+                          "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", 0x8000, &nfonts);
+  for (i = 0; i < nfonts; i++)
     {
-      /* Unable to decode the output of XIM.  */
-      mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
-      MERROR (MERROR_LOCALE, -1);
-    }
+      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 (arg->modifier_list)
-    save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
-  else
-    save_modifier_list = XSetLocaleModifiers ("");
-  if (! save_modifier_list)
-    {
-      /* The specified locale is not supported by X.  */
-      mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
-      MERROR (MERROR_LOCALE, -1);
+         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);
+}
 
-  xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
-  if (! xim)
-    {
-      /* No input method is available in the current locale.  */
-      XSetLocaleModifiers (save_modifier_list);
-      mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
-      MERROR (MERROR_WIN, -1);
-    }
+static int 
+xfont_check_capability (MRealizedFont *rfont, MSymbol capability)
+{
+  /* Currently X font driver doesn't support any capability.  */
+  return -1;
+}
 
-  MSTRUCT_MALLOC (im_info, MERROR_WIN);
-  im_info->display = arg->display;
-  im_info->xim = xim;
-  im_info->language = mlocale_get_prop (this, Mlanguage);
-  im_info->coding = mlocale_get_prop (this, Mcoding);
-  im->info = im_info;
+\f
+/* Xft Handler */
 
-  XSetLocaleModifiers (save_modifier_list);
-  mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
+#ifdef HAVE_XFT2
 
-  return 0;
-}
+typedef struct
+{
+  M17NObject control;
+  FT_Face ft_face;             /* This must be the 2nd member. */
+  Display *display;
+  XftFont *font_aa;
+  XftFont *font_no_aa;
+  /* 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);
+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
-xim_close_im (MInputMethod *im)
+close_xft (void *object)
 {
-  MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
+  MRealizedFontXft *rfont_xft = object;
 
-  XCloseIM (im_info->xim);
-  free (im_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 int
-xim_create_ic (MInputContext *ic)
+
+static XftFont *
+xft_open_font (Display *display, MSymbol file, double size,
+              FcBool anti_alias)
 {
-  MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
-  MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
-  MInputXIMContextInfo *ic_info;
-  XIC xic;
+  FcPattern *pattern;
+  XftFont *font;
 
-  if (! arg->input_style)
+  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 MRealizedFont *
+xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
+{
+  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 (font->size)
+    /* non-scalable font */
+    size = font->size;
+  else if (spec->size)
     {
-      /* By default, use Root style.  */
-      arg->input_style = XIMPreeditNothing | XIMStatusNothing;
-      arg->preedit_attrs = NULL;
-      arg->status_attrs = NULL;
-    }
+      int ratio = mfont_resize_ratio (font);
 
-  if (! arg->preedit_attrs && ! arg->status_attrs)
-    xic = XCreateIC (im_info->xim,
-                    XNInputStyle, arg->input_style,
-                    XNClientWindow, arg->client_win,
-                    XNFocusWindow, arg->focus_win,
-                    NULL);
-  else if (arg->preedit_attrs && ! arg->status_attrs)
-    xic = XCreateIC (im_info->xim,
-                    XNInputStyle, arg->input_style,
-                    XNClientWindow, arg->client_win,
-                    XNFocusWindow, arg->focus_win,
-                    XNPreeditAttributes, arg->preedit_attrs,
-                    NULL);
-  else if (! arg->preedit_attrs && arg->status_attrs)
-    xic = XCreateIC (im_info->xim,
-                    XNInputStyle, arg->input_style,
-                    XNClientWindow, arg->client_win,
-                    XNFocusWindow, arg->focus_win,
-                    XNStatusAttributes, arg->status_attrs,
-                    NULL);
+      size = ratio == 100 ? spec->size : spec->size * ratio / 100;
+    }
   else
-    xic = XCreateIC (im_info->xim,
-                    XNInputStyle, arg->input_style,
-                    XNClientWindow, arg->client_win,
-                    XNFocusWindow, arg->focus_win,
-                    XNPreeditAttributes, arg->preedit_attrs,
-                    XNStatusAttributes, arg->status_attrs,
-                    NULL);
-  if (! xic)
-    MERROR (MERROR_WIN, -1);
+    size = 120;
 
-  MSTRUCT_MALLOC (ic_info, MERROR_WIN);
-  ic_info->xic = xic;
-  ic_info->win = arg->focus_win;
-  ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
-  ic->info = ic_info;
-  return 0;
+  if (rfont)
+    {
+      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;
+    }
+  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
-xim_destroy_ic (MInputContext *ic)
+xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
+               int from, int to)
 {
-  MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
+  Display *display = FRAME_DISPLAY (rfont->frame);
+  XftFont *xft_font = rfont->fontp;
+  MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
 
-  XDestroyIC (ic_info->xic);
-  mconv_free_converter (ic_info->converter);
-  free (ic_info);
-  ic->info = NULL;
+  for (; g != gend; 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;
+      }
 }
 
 static int
-xim_filter (MInputContext *ic, MSymbol key, void *event)
+xft_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code)
 {
-  MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
+  int result;
 
-  return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
+  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 int
-xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
+static void 
+xft_render (MDrawWindow win, int x, int y,
+           MGlyphString *gstring, MGlyph *from, MGlyph *to,
+           int reverse, MDrawRegion region)
 {
-  MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
-  MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
-  XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
-  KeySym keysym;
-  Status status;
-  char *buf;
-  int len;
+  MRealizedFace *rface = from->rface;
+  MFrame *frame = rface->frame;
+  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);
+  int anti_alias = (gstring->control.anti_alias
+                   && FRAME_DEVICE (frame)->depth > 1);
+  XftFont *xft_font;
+  MGlyph *g;
+  FT_UInt *glyphs;
+  int last_x;
+  int nglyphs;
 
-  buf = (char *) alloca (512);
-  len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
-  if (status == XBufferOverflow)
+  if (from == to)
+    return;
+
+  if (anti_alias)
     {
-      buf = (char *) alloca (len);
-      len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
+      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;
 
-  mtext_reset (ic->produced);
-  if (len == 0)
-    return 1;
+         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;
+       }
+    }
 
-  mconv_reset_converter (ic_info->converter);
-  mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
-  mconv_decode (ic_info->converter, ic->produced);
-  mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
-                 Mlanguage, (void *) im_info->language);
-  mtext_cpy (mt, ic->produced);
-  mtext_reset (ic->produced);  
-  return 0;
+  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++->g.xadv)
+    {
+      if (! g->g.adjusted && !g->left_padding && !g->right_padding)
+       glyphs[nglyphs++] = g->g.code;
+      else
+       {
+         if (nglyphs > 0)
+           XftDrawGlyphs (xft_draw, xft_color, xft_font,
+                          last_x, y, glyphs, nglyphs);
+         nglyphs = 0;
+         XftDrawGlyphs (xft_draw, xft_color, xft_font,
+                        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);
 }
 
-\f
-
-#ifdef X_SET_ERROR_HANDLER
 static int
-x_error_handler (Display *display, XErrorEvent *error)
-{
-  mdebug_hook ();
-  return 0;
+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
-x_io_error_handler (Display *display)
-{
-  mdebug_hook ();
-  return 0;
+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;
 }
-#endif
 
-\f
+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;
+}
 
-int
-mwin__init ()
+static int
+xft_try_otf (MFLTFont *font, MFLTOtfSpec *spec,
+            MFLTGlyphString *in, int from, int to)
 {
-  Mdisplay = msymbol ("display");
-  Mscreen = msymbol ("screen");
-  Mdrawable = msymbol ("drawable");
-  Mdepth = msymbol ("depth");
-  Mwidget = msymbol ("widget");
-  M_iso8859_1 = msymbol ("iso8859-1");
-  M_iso10646_1 = msymbol ("iso10646-1");
+  return xft_drive_otf (font, spec, in, from, to, NULL, NULL);
+}
 
-  display_info_list = mplist ();
-  device_list = mplist ();
+#ifdef HAVE_OTF
 
-  mfont__driver_list[MFONT_TYPE_WIN] = &xfont_driver;
+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 */
 
-  Mxim = msymbol ("xim");
-  msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
+#endif /* HAVE_XFT2 */
 
-  return 0;
-}
+\f
+/* Functions for the device driver.  */
 
-void
-mwin__fini ()
+static void
+mwin__close_device (MFrame *frame)
 {
-  M17N_OBJECT_UNREF (display_info_list);
-  M17N_OBJECT_UNREF (device_list);
+  MWDevice *device = FRAME_DEVICE (frame);
+
+  M17N_OBJECT_UNREF (device);
 }
 
-int
-mwin__parse_font_name (char *name, MFont *font)
+static void *
+mwin__device_get_prop (MFrame *frame, MSymbol key)
 {
-  char *field[XLFD_FIELD_MAX];
-  unsigned short size, resy;
-  MSymbol attrs[MFONT_PROPERTY_MAX];
-  char *copy = (char *) alloca (512);
-  int i, len;
-  char *p, *last = NULL;
-
-  len = strlen (name) + 1;
-  for (i = 0, p = name; *p; p++)
-    {
-      if (*p == '-')
-       i++;
-      else if (p > name && *p == '*' && p[-1] == '-')
-       last = p + 1;
-    }
-  if (i == 14)
-    memcpy (copy, name, len);
-  else if (last)
-    {
-      memcpy (copy, name, last - name);
-      for (; i < 14; i++)
-       strcat (copy, "-*");
-      strcat (copy, last);
-    }
+  MWDevice *device = FRAME_DEVICE (frame);
 
-  if (split_font_name (copy, field, &size, &resy) < 0)
-    return -1;
-  attrs[MFONT_FOUNDRY]
-    = *(field[XLFD_FOUNDRY]) != '*' ? msymbol (field[XLFD_FOUNDRY]) : Mnil;
-  attrs[MFONT_FAMILY]
-    = *(field[XLFD_FAMILY]) != '*' ? msymbol (field[XLFD_FAMILY]) : Mnil;
-  attrs[MFONT_WEIGHT]
-    = *(field[XLFD_WEIGHT]) != '*' ? msymbol (field[XLFD_WEIGHT]) : Mnil;
-  attrs[MFONT_STYLE]
-    = *(field[XLFD_SLANT]) != '*' ? msymbol (field[XLFD_SLANT]) : Mnil;
-  attrs[MFONT_STRETCH]
-    = *(field[XLFD_SWIDTH]) != '*' ? msymbol (field[XLFD_SWIDTH]) : Mnil;
-  attrs[MFONT_ADSTYLE]
-    = *(field[XLFD_ADSTYLE]) != '*' ? msymbol (field[XLFD_ADSTYLE]) : Mnil;
-  attrs[MFONT_REGISTRY]
-    = *(field[XLFD_REGISTRY]) != '*' ? msymbol (field[XLFD_REGISTRY]) : Mnil;
-  mfont__set_spec (font, attrs, size, resy);
-  return 0;
-}
-
-
-char *
-mwin__build_font_name (MFont *font)
-{
-  char name[1024];
-
-  if (build_font_name (font, name, 1024) < 0)
-    return NULL;
-  return strdup (name);
-}
-
-/** Return an MWDevice object corresponding to a display specified in
-    PLIST.
-
-    It searches device_list for a device matching the display.  If
-    found, return the found object.  Otherwise, return a newly created
-    object.  */
-
-MWDevice *
-mwin__open_device (MFrame *frame, MPlist *param)
-{
-  Display *display = NULL;
-  Screen *screen = NULL;
-  int screen_num;
-  Drawable drawable = 0;
-  Widget widget = NULL;
-  Colormap cmap = 0;
-  int auto_display = 0;
-  MDisplayInfo *disp_info = NULL;
-  MWDevice *device = NULL;
-  MSymbol key;
-  XWindowAttributes attr;
-  unsigned depth = 0;
-  MPlist *plist;
-  AppData app_data;
-
-  if (param)
-    for (plist = param; (key = mplist_key (plist)) != Mnil;
-        plist = mplist_next (plist))
-      {
-       if (key == Mdisplay)
-         display = (Display *) mplist_value (plist);
-       else if (key == Mscreen)
-         screen = mplist_value (plist);
-       else if (key == Mdrawable)
-         drawable = (Drawable) mplist_value (plist);
-       else if (key == Mdepth)
-         depth = (unsigned) mplist_value (plist);
-       else if (key == Mwidget)
-         widget = (Widget) mplist_value (plist);
-       else if (key == Mcolormap)
-         cmap = (Colormap) mplist_value (plist);
-      }
-
-  if (widget)
-    {
-      display = XtDisplay (widget);
-      screen_num = XScreenNumberOfScreen (XtScreen (widget));
-      depth = DefaultDepth (display, screen_num);
-    }
-  else if (drawable)
-    {
-      Window root_window;
-      int x, y;
-      unsigned width, height, border_width;
-
-      if (! display)
-       MERROR (MERROR_WIN, NULL);
-      XGetGeometry (display, drawable, &root_window,
-                   &x, &y, &width, &height, &border_width, &depth);
-      XGetWindowAttributes (display, root_window, &attr);
-      screen_num = XScreenNumberOfScreen (attr.screen);
-    }
-  else
-    {
-      if (screen)
-       display = DisplayOfScreen (screen);
-      else
-       {
-         if (! display)
-           {
-             display = XOpenDisplay (NULL);
-             if (! display)
-               MERROR (MERROR_WIN, NULL);
-             auto_display = 1;
-           }
-         screen = DefaultScreenOfDisplay (display);
-       }
-      screen_num = XScreenNumberOfScreen (screen);
-      if (! depth)
-       depth = DefaultDepth (display, screen_num);
-    }
-
-  if (! cmap)
-    cmap = DefaultColormap (display, screen_num);
-
-  for (plist = display_info_list; mplist_key (plist) != Mnil;
-       plist = mplist_next (plist))
-    {
-      disp_info = (MDisplayInfo *) mplist_value (plist);
-      if (disp_info->display == display)
-       break;
-    }
-
-  if (mplist_key (plist) != Mnil)
-    M17N_OBJECT_REF (disp_info);
-  else
-    {
-      M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
-      disp_info->display = display;
-      disp_info->auto_display = auto_display;
-      disp_info->font_registry_list = mplist ();
-      disp_info->iso8859_1_family_list = mplist ();
-      disp_info->iso10646_1_family_list = mplist ();
-      disp_info->realized_font_list = mplist ();
-      find_modifier_bits (disp_info);
-      mplist_add (display_info_list, Mt, disp_info);
-    }  
-
-  for (plist = device_list; mplist_key (plist) != Mnil;
-       plist = mplist_next (plist))
-    {
-      device = (MWDevice *) mplist_value (plist);
-      if (device->display_info == disp_info
-         && device->depth == depth
-         && device->cmap == cmap)
-       break;
-    }
-
-  if (mplist_key (plist) != Mnil)
-    M17N_OBJECT_REF (device);
-  else
-    {
-      unsigned long valuemask = GCForeground;
-      XGCValues values;
-
-      M17N_OBJECT (device, free_device, MERROR_WIN);
-      device->display_info = disp_info;
-      device->screen_num = screen_num;
-      /* A drawable on which to create GCs.  */
-      device->drawable = XCreatePixmap (display,
-                                       RootWindow (display, screen_num),
-                                       1, 1, depth);
-      device->depth = depth;
-      device->cmap = cmap;
-      device->realized_face_list = mplist ();
-      device->realized_fontset_list = mplist ();
-      device->gc_list = mplist ();
-      values.foreground = BlackPixel (display, screen_num);
-      device->scratch_gc = XCreateGC (display, device->drawable,
-                                     valuemask, &values);
-    }
-
-  frame->realized_font_list = disp_info->realized_font_list;
-  frame->realized_face_list = device->realized_face_list;
-  frame->realized_fontset_list = device->realized_fontset_list;
-
-  if (widget)
-    {
-      XtResource resources[] = {
-       { XtNfont, XtCFont, XtRString, sizeof (String),
-         XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
-       { XtNforeground, XtCForeground, XtRString, sizeof (String),
-         XtOffset (AppDataPtr, foreground), XtRString, "black" },
-       { XtNbackground, XtCBackground, XtRString, sizeof (String),
-         XtOffset (AppDataPtr, background), XtRString, "white" },
-       { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
-         XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
-      };
-
-      XtGetApplicationResources (widget, &app_data,
-                                resources, XtNumber (resources), NULL, 0);
-      frame->foreground = msymbol (app_data.foreground);
-      frame->background = msymbol (app_data.background);
-      frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
-    }
-  else
-    {
-      app_data.font = DEFAULT_FONT;
-      frame->foreground = msymbol ("black");
-      frame->background = msymbol ("white");
-      frame->videomode = Mnormal;
-    }
-
-  frame->font = mfont ();
-  {
-    int nfonts;
-    char **names = XListFonts (display, app_data.font, 1, &nfonts);
-
-    if (nfonts > 0)
-      {
-       if (mwin__parse_font_name (names[0], frame->font) < 0)
-         {
-           /* 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 (mwin__parse_font_name (name, frame->font) >= 0)
-                     nfonts = 1;
-                 }
-               XFreeFont (display, xfont);
-             }
-         }
-       XFreeFontNames (names);
-      }
-    if (! nfonts)
-      mwin__parse_font_name (FALLBACK_FONT, frame->font);
-  }
-
-#ifdef X_SET_ERROR_HANDLER
-  XSetErrorHandler (x_error_handler);
-  XSetIOErrorHandler (x_io_error_handler);
-#endif
-
-  return device;
-}
-
-void
-mwin__close_device (MFrame *frame)
-{
-  M17N_OBJECT_UNREF (frame->device);
-}
-
-void *
-mwin__device_get_prop (MWDevice *device, MSymbol key)
-{
   if (key == Mdisplay)
     return (void *) device->display_info->display;
   if (key == Mscreen)
@@ -1496,14 +1442,13 @@ mwin__device_get_prop (MWDevice *device, MSymbol key)
   return NULL;
 }
 
-void
+static void
 mwin__realize_face (MRealizedFace *rface)
 {
   MFrame *frame;
   MSymbol foreground, background, videomode;
   MFaceHLineProp *hline;
   MFaceBoxProp *box;
-  MFaceHookFunc func;
   GCInfo *info;
 
   if (rface != rface->ascii_rface)
@@ -1530,6 +1475,30 @@ mwin__realize_face (MRealizedFace *rface)
       info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
       info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
     }
+#ifdef HAVE_XFT2
+  if (foreground == Mnil)
+    foreground = frame->foreground;
+  if (background == Mnil)
+    background = frame->background;
+  if (videomode == Mreverse)
+    {
+      MSymbol temp = foreground;
+      foreground = background;
+      background = temp;
+    }
+  if (! XftColorAllocName (FRAME_DISPLAY (frame),
+                          FRAME_VISUAL (frame),
+                          FRAME_CMAP (frame),
+                          MSYMBOL_NAME (foreground),
+                          &info->xft_color_fore))
+    mdebug_hook ();
+  if (! XftColorAllocName (FRAME_DISPLAY (frame),
+                          FRAME_VISUAL (frame),
+                          FRAME_CMAP (frame),
+                          MSYMBOL_NAME (background),
+                          &info->xft_color_back))
+    mdebug_hook ();
+#endif /* HAVE_XFT2 */
 
   hline = rface->hline;
   if (hline)
@@ -1551,28 +1520,24 @@ mwin__realize_face (MRealizedFace *rface)
       if (box->color_left && box->color_left != box->color_top)
        info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
       else
-       info->gc[GC_BOX_LEFT] = info->gc[GC_NORMAL];
+       info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP];
 
       if (box->color_bottom && box->color_bottom != box->color_top)
        info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
       else
-       info->gc[GC_BOX_BOTTOM] = info->gc[GC_NORMAL];
+       info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP];
 
-      if (box->color_right && box->color_right != box->color_top)
+      if (box->color_right && box->color_right != box->color_bottom)
        info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
       else
-       info->gc[GC_BOX_RIGHT] = info->gc[GC_NORMAL];
+       info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM];
     }
 
   rface->info = info;
-
-  func = (MFaceHookFunc) rface->face.property[MFACE_HOOK_FUNC];
-  if (func)
-    (func) (&(rface->face), rface->info, rface->face.property[MFACE_HOOK_ARG]);
 }
 
 
-void
+static void
 mwin__free_realized_face (MRealizedFace *rface)
 {
   if (rface == rface->ascii_rface)
@@ -1580,7 +1545,7 @@ mwin__free_realized_face (MRealizedFace *rface)
 }
 
 
-void
+static void
 mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
                  int reverse,
                  int x, int y, int width, int height, MDrawRegion region)
@@ -1595,7 +1560,31 @@ mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
 }
 
 
-void
+static void
+mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
+                       MGlyphString *gstring, MGlyph *from, MGlyph *to,
+                       int reverse, MDrawRegion region)
+{
+  MRealizedFace *rface = from->rface;
+  Display *display = FRAME_DISPLAY (rface->frame);
+  GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
+
+  if (from == to)
+    return;
+
+  if (region)
+    gc = set_region (rface->frame, gc, region);
+  for (; from < to; from++)
+    {
+      XDrawRectangle (display, (Window) win, gc,
+                     x, y - gstring->ascent + 1, from->g.xadv - 1,
+                     gstring->ascent + gstring->descent - 2);
+      x += from->g.xadv;
+    }
+}
+
+
+static void
 mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
                 MRealizedFace *rface, int reverse,
                 int x, int y, int width, MDrawRegion region)
@@ -1621,7 +1610,7 @@ mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
 }
 
 
-void
+static void
 mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
                MGlyph *g, int x, int y, int width, MDrawRegion region)
 {
@@ -1651,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++)
@@ -1714,7 +1703,7 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
 
 
 #if 0
-void
+static void
 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
                   int reverse, int x, int y,
                   int width, int height, int row_bytes, unsigned char *bmp,
@@ -1734,7 +1723,7 @@ mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
 }
 #endif
 
-void
+static void
 mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
                   int intensity, MDrawPoint *points, int num,
                   MDrawRegion region)
@@ -1743,8 +1732,8 @@ mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
   GC gc;
 
   if (! (gc = info->gc[intensity]))
-    gc = info->gc[intensity] = get_gc_for_anti_alias (frame->device, info,
-                                                     intensity);
+    gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
+                                                     info, intensity);
   if (region)
     gc = set_region (frame, gc, region);
 
@@ -1753,7 +1742,7 @@ mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
 }
 
 
-MDrawRegion
+static MDrawRegion
 mwin__region_from_rect (MDrawMetric *rect)
 {
   MDrawRegion region1 = XCreateRegion ();
@@ -1769,7 +1758,7 @@ mwin__region_from_rect (MDrawMetric *rect)
   return region2;
 }
 
-void
+static void
 mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
 {
   MDrawRegion region1 = XCreateRegion ();
@@ -1785,7 +1774,7 @@ mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
   XDestroyRegion (region1);
 }
 
-void
+static void
 mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
 {
   MDrawRegion region = XCreateRegion ();
@@ -1795,7 +1784,7 @@ mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
   XDestroyRegion (region);
 }
 
-void
+static void
 mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
 {
   MDrawRegion region1 = XCreateRegion ();
@@ -1809,7 +1798,7 @@ mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
   XDestroyRegion (region1);
 }
 
-void
+static void
 mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
 {
   XRectangle xrect;
@@ -1821,13 +1810,13 @@ mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
   rect->height = xrect.height;
 }
 
-void
+static void
 mwin__free_region (MDrawRegion region)
 {
   XDestroyRegion (region);
 }
 
-void
+static void
 mwin__dump_region (MDrawRegion region)
 {
   XRectangle rect;
@@ -1835,13 +1824,8 @@ mwin__dump_region (MDrawRegion region)
   fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
 }
 
-void
-mwin__verify_region (MFrame *frame, MDrawRegion region)
-{
-  set_region (frame, ((GCInfo *) frame->rface->info)->gc[GC_NORMAL], region);
-}
 
-MDrawWindow
+static MDrawWindow
 mwin__create_window (MFrame *frame, MDrawWindow parent)
 {
   Display *display = FRAME_DISPLAY (frame);
@@ -1871,20 +1855,26 @@ mwin__create_window (MFrame *frame, MDrawWindow parent)
   return (MDrawWindow) win;
 }
 
-void
+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);
 }
 
 #if 0
-MDrawWindow
+static MDrawWindow
 mwin__event_window (void *event)
 {
   return ((MDrawWindow) ((XEvent *) event)->xany.window);
 }
 
-void
+static void
 mwin__print_event (void *arg, char *win_name)
 {
   char *event_name;
@@ -1932,19 +1922,19 @@ mwin__print_event (void *arg, char *win_name)
 }
 #endif
 
-void
+static void
 mwin__map_window (MFrame *frame, MDrawWindow win)
 {
   XMapRaised (FRAME_DISPLAY (frame), (Window) win);
 }
 
-void
+static void
 mwin__unmap_window (MFrame *frame, MDrawWindow win)
 {
   XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
 }
 
-void
+static void
 mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
                       MDrawMetric *geometry)
 {
@@ -1977,168 +1967,666 @@ mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
     }
 }
 
-void
-mwin__adjust_window (MFrame *frame, MDrawWindow win,
-                    MDrawMetric *current, MDrawMetric *new)
+static void
+mwin__adjust_window (MFrame *frame, MDrawWindow win,
+                    MDrawMetric *current, MDrawMetric *new)
+{
+  Display *display = FRAME_DISPLAY (frame);
+  unsigned int mask = 0;
+  XWindowChanges values;
+
+  if (current->width != new->width)
+    {
+      mask |= CWWidth;
+      if (new->width <= 0)
+       new->width = 1;
+      values.width = current->width = new->width;
+    }
+  if (current->height != new->height)
+    {
+      mask |= CWHeight;
+      if (new->height <= 0)
+       new->height = 1;
+      values.height = current->height = new->height;
+    }
+  if (current->x != new->x)
+    {
+      mask |= CWX;
+      values.x = current->x = new->x;
+    }
+  if (current->y != new->y)
+    {
+      mask |= CWY;
+      current->y = new->y;
+      values.y = current->y = new->y;
+    }
+  if (mask)
+    XConfigureWindow (display, (Window) win, mask, &values);
+  XClearWindow (display, (Window) win);
+}
+
+static MSymbol
+mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
+{
+  XEvent *event = (XEvent *) arg;
+  MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
+  int len;
+  char buf[512];
+  KeySym keysym;
+  MSymbol key;
+
+  *modifiers = 0;
+  if (event->xany.type != KeyPress
+      /* && event->xany.type != KeyRelease */
+      )
+    return Mnil;
+  len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
+  if (len > 1)
+    return Mnil;
+  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;
+
+      key = minput__char_to_key (c);
+      if (c == ' ' && ((XKeyEvent *) event)->state & ShiftMask)
+       *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
+    }
+  else
+    {
+      char *str = XKeysymToString (keysym);
+
+      if (! str)
+       return Mnil;
+      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 & disp_info->meta_mask)
+    *modifiers |= MINPUT_KEY_META_MODIFIER;
+  if (((XKeyEvent *) event)->state & disp_info->alt_mask)
+    *modifiers |= MINPUT_KEY_ALT_MODIFIER;
+  if (((XKeyEvent *) event)->state & disp_info->super_mask)
+    *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;
+}
+
+
+void
+mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
+{
+  unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
+  XGCValues values;
+  Display *display = FRAME_DISPLAY (frame);
+  GCInfo *info = rface->info;
+  int i;
+
+  for (i = 0; i <= GC_INVERSE; i++)
+    {
+      XGetGCValues (display, info->gc[i], valuemask, &values);
+      fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
+              values.foreground, values.background);
+      fprintf (stderr, "\n");
+    }
+}
+
+static MDeviceDriver x_driver =
+  {
+    mwin__close_device,
+    mwin__device_get_prop,
+    mwin__realize_face,
+    mwin__free_realized_face,
+    mwin__fill_space,
+    mwin__draw_empty_boxes,
+    mwin__draw_hline,
+    mwin__draw_box,
+    mwin__draw_points,
+    mwin__region_from_rect,
+    mwin__union_rect_with_region,
+    mwin__intersect_region,
+    mwin__region_add_rect,
+    mwin__region_to_rect,
+    mwin__free_region,
+    mwin__dump_region,
+    mwin__create_window,
+    mwin__destroy_window,
+    mwin__map_window,
+    mwin__unmap_window,
+    mwin__window_geometry,
+    mwin__adjust_window,
+    mwin__parse_event
+  };
+
+/* Functions to be stored in MDeviceLibraryInterface by dlsym ().  */
+
+int
+device_init ()
+{
+  M_iso8859_1 = msymbol ("iso8859-1");
+  M_iso10646_1 = msymbol ("iso10646-1");
+
+  display_info_list = mplist ();
+  device_list = mplist ();
+
+#ifdef HAVE_XFT2
+  xft_driver.select = mfont__ft_driver.select;
+  xft_driver.list = mfont__ft_driver.list;
+  xft_driver.list_family_names = mfont__ft_driver.list_family_names;
+#endif
+
+  Mxim = msymbol ("xim");
+  msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
+
+  return 0;
+}
+
+int
+device_fini ()
+{
+  M17N_OBJECT_UNREF (display_info_list);
+  M17N_OBJECT_UNREF (device_list);
+  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.
+
+    It searches device_list for a device matching the display.  If
+    found, return the found object.  Otherwise, return a newly created
+    object.  */
+
+int
+device_open (MFrame *frame, MPlist *param)
+{
+  Display *display = NULL;
+  Screen *screen = NULL;
+  int screen_num;
+  Drawable drawable = 0;
+  Widget widget = NULL;
+  Colormap cmap = 0;
+  int auto_display = 0;
+  MDisplayInfo *disp_info = NULL;
+  MWDevice *device = NULL;
+  MSymbol key;
+  XWindowAttributes attr;
+  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))
+    {
+      if (key == Mdisplay)
+       display = (Display *) mplist_value (plist);
+      else if (key == Mscreen)
+       screen = mplist_value (plist);
+      else if (key == Mdrawable)
+       drawable = (Drawable) mplist_value (plist);
+      else if (key == Mdepth)
+       depth = (unsigned) mplist_value (plist);
+      else if (key == Mwidget)
+       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);
+      screen_num = XScreenNumberOfScreen (XtScreen (widget));
+      depth = DefaultDepth (display, screen_num);
+    }
+  else if (drawable)
+    {
+      Window root_window;
+      int x, y;
+      unsigned width, height, border_width;
+
+      if (! display)
+       MERROR (MERROR_WIN, -1);
+      XGetGeometry (display, drawable, &root_window,
+                   &x, &y, &width, &height, &border_width, &depth);
+      XGetWindowAttributes (display, root_window, &attr);
+      screen_num = XScreenNumberOfScreen (attr.screen);
+    }
+  else
+    {
+      if (screen)
+       display = DisplayOfScreen (screen);
+      else
+       {
+         if (! display)
+           {
+             display = XOpenDisplay (NULL);
+             if (! display)
+               MERROR (MERROR_WIN, -1);
+             auto_display = 1;
+           }
+         screen = DefaultScreenOfDisplay (display);
+       }
+      screen_num = XScreenNumberOfScreen (screen);
+      if (! depth)
+       depth = DefaultDepth (display, screen_num);
+    }
+
+  if (! cmap)
+    cmap = DefaultColormap (display, screen_num);
+
+  for (plist = display_info_list; mplist_key (plist) != Mnil;
+       plist = mplist_next (plist))
+    {
+      disp_info = (MDisplayInfo *) mplist_value (plist);
+      if (disp_info->display == display)
+       break;
+    }
+
+  if (mplist_key (plist) != Mnil)
+    M17N_OBJECT_REF (disp_info);
+  else
+    {
+      M17N_OBJECT (disp_info, free_display_info, MERROR_WIN);
+      disp_info->display = display;
+      disp_info->auto_display = auto_display;
+      disp_info->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);
+    }  
+
+  for (plist = device_list; mplist_key (plist) != Mnil;
+       plist = mplist_next (plist))
+    {
+      device = (MWDevice *) mplist_value (plist);
+      if (device->display_info == disp_info
+         && device->depth == depth
+         && device->cmap == cmap
+         && device->screen_num == screen_num)
+       break;
+    }
+
+  if (mplist_key (plist) != Mnil)
+    M17N_OBJECT_REF (device);
+  else
+    {
+      unsigned long valuemask = GCForeground;
+      XGCValues values;
+      double pixels, mm;
+
+      M17N_OBJECT (device, free_device, MERROR_WIN);
+      device->display_info = disp_info;
+      device->screen_num = screen_num;
+      /* A drawable on which to create GCs.  */
+      device->drawable = XCreatePixmap (display,
+                                       RootWindow (display, screen_num),
+                                       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);
+      device->scratch_gc = XCreateGC (display, device->drawable,
+                                     valuemask, &values);
+#ifdef HAVE_XFT2
+      device->xft_draw = XftDrawCreate (display, device->drawable,
+                                       DefaultVisual (display, screen_num),
+                                       cmap);
+#endif
+    }
+
+  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 ();
+#ifdef HAVE_XFT2
+  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;
+
+  if (widget)
+    {
+      XtResource resources[] = {
+       { XtNfont, XtCFont, XtRString, sizeof (String),
+         XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
+       { XtNforeground, XtCForeground, XtRString, sizeof (String),
+         XtOffset (AppDataPtr, foreground), XtRString, "black" },
+       { XtNbackground, XtCBackground, XtRString, sizeof (String),
+         XtOffset (AppDataPtr, background), XtRString, "white" },
+       { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
+         XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
+      };
+
+      XtGetApplicationResources (widget, &app_data,
+                                resources, XtNumber (resources), NULL, 0);
+      frame->foreground = msymbol (app_data.foreground);
+      frame->background = msymbol (app_data.background);
+      frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
+    }
+  else
+    {
+      app_data.font = DEFAULT_FONT;
+      frame->foreground = msymbol ("black");
+      frame->background = msymbol ("white");
+      frame->videomode = Mnormal;
+    }
+
+  if (strcmp (app_data.font, DEFAULT_FONT) != 0)
+    {
+      XFontStruct *xfont = XLoadQueryFont (display, app_data.font);
+      unsigned long value;
+      char *name;
+
+      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;
+  mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline));
+  mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox));
+  face->property[MFACE_VIDEOMODE] = frame->videomode;
+  mface_put_prop (face, Mhook_func, 
+                 mface_get_prop (mface__default, Mhook_func));
+  face->property[MFACE_RATIO] = (void *) 100;
+  mplist_push (param, Mface, face);
+  M17N_OBJECT_UNREF (face);
+
+#ifdef X_SET_ERROR_HANDLER
+  XSetErrorHandler (x_error_handler);
+  XSetIOErrorHandler (x_io_error_handler);
+#endif
+  return 0;
+}
+
+\f
+
+/* XIM (X Input Method) handler */
+
+typedef struct MInputXIMMethodInfo
+{
+  Display *display;
+  XIM xim;
+  MSymbol language;
+  MSymbol coding;
+} MInputXIMMethodInfo;
+
+typedef struct MInputXIMContextInfo
+{
+  XIC xic;
+  Window win;
+  MConverter *converter;
+} MInputXIMContextInfo;
+
+static int
+xim_open_im (MInputMethod *im)
 {
-  Display *display = FRAME_DISPLAY (frame);
-  unsigned int mask = 0;
-  XWindowChanges values;
+  MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
+  MLocale *saved, *this;
+  char *save_modifier_list;
+  XIM xim;
+  MInputXIMMethodInfo *im_info;
 
-  if (current->width != new->width)
-    {
-      mask |= CWWidth;
-      if (new->width <= 0)
-       new->width = 1;
-      values.width = current->width = new->width;
-    }
-  if (current->height != new->height)
+  saved = mlocale_set (LC_CTYPE, NULL);
+  this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : "");
+  if (! this)
+    /* The specified locale is not supported.  */
+    MERROR (MERROR_LOCALE, -1);
+  if (mlocale_get_prop (this, Mcoding) == Mnil)
     {
-      mask |= CWHeight;
-      if (new->height <= 0)
-       new->height = 1;
-      values.height = current->height = new->height;
+      /* Unable to decode the output of XIM.  */
+      mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
+      MERROR (MERROR_LOCALE, -1);
     }
-  if (current->x != new->x)
+
+  if (arg->modifier_list)
+    save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
+  else
+    save_modifier_list = XSetLocaleModifiers ("");
+  if (! save_modifier_list)
     {
-      mask |= CWX;
-      values.x = current->x = new->x;
+      /* The specified locale is not supported by X.  */
+      mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
+      MERROR (MERROR_LOCALE, -1);
     }
-  if (current->y != new->y)
+
+  xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
+  if (! xim)
     {
-      mask |= CWY;
-      current->y = new->y;
-      values.y = current->y = new->y;
+      /* No input method is available in the current locale.  */
+      XSetLocaleModifiers (save_modifier_list);
+      mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
+      MERROR (MERROR_WIN, -1);
     }
-  if (mask)
-    XConfigureWindow (display, (Window) win, mask, &values);
-  XClearWindow (display, (Window) win);
+
+  MSTRUCT_MALLOC (im_info, MERROR_WIN);
+  im_info->display = arg->display;
+  im_info->xim = xim;
+  im_info->language = mlocale_get_prop (this, Mlanguage);
+  im_info->coding = mlocale_get_prop (this, Mcoding);
+  im->info = im_info;
+
+  XSetLocaleModifiers (save_modifier_list);
+  mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
+
+  return 0;
 }
 
-MSymbol
-mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
+static void
+xim_close_im (MInputMethod *im)
 {
-  XEvent *event = (XEvent *) arg;
-  MDisplayInfo *disp_info = frame->device->display_info;
-  int len;
-  char buf[512];
-  KeySym keysym;
-  MSymbol key;
+  MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
 
-  *modifiers = 0;
-  if (event->xany.type != KeyPress
-      /* && event->xany.type != KeyRelease */
-      )
-    return Mnil;
-  len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
-  if (len > 1)
-    return Mnil;
-  if (len == 1)
-    {
-      int c = keysym;
+  XCloseIM (im_info->xim);
+  free (im_info);
+}
 
-      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);
-    }
-  else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
-    return Mnil;
-  else
-    {
-      char *str = XKeysymToString (keysym);
+static int
+xim_create_ic (MInputContext *ic)
+{
+  MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
+  MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
+  MInputXIMContextInfo *ic_info;
+  XIC xic;
 
-      if (! str)
-       return Mnil;
-      key = msymbol (str);
-      if (((XKeyEvent *) event)->state & ShiftMask)
-       *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
-      if (((XKeyEvent *) event)->state & ControlMask)
-       *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
+  if (! arg->input_style)
+    {
+      /* By default, use Root style.  */
+      arg->input_style = XIMPreeditNothing | XIMStatusNothing;
+      arg->preedit_attrs = NULL;
+      arg->status_attrs = NULL;
     }
-  if (((XKeyEvent *) event)->state & disp_info->meta_mask)
-    *modifiers |= MINPUT_KEY_META_MODIFIER;
-  if (((XKeyEvent *) event)->state & disp_info->alt_mask)
-    *modifiers |= MINPUT_KEY_ALT_MODIFIER;
-  if (((XKeyEvent *) event)->state & disp_info->super_mask)
-    *modifiers |= MINPUT_KEY_SUPER_MODIFIER;
-  if (((XKeyEvent *) event)->state & disp_info->hyper_mask)
-    *modifiers |= MINPUT_KEY_HYPER_MODIFIER;
 
-  return key;
-}
+  if (! arg->preedit_attrs && ! arg->status_attrs)
+    xic = XCreateIC (im_info->xim,
+                    XNInputStyle, arg->input_style,
+                    XNClientWindow, arg->client_win,
+                    XNFocusWindow, arg->focus_win,
+                    NULL);
+  else if (arg->preedit_attrs && ! arg->status_attrs)
+    xic = XCreateIC (im_info->xim,
+                    XNInputStyle, arg->input_style,
+                    XNClientWindow, arg->client_win,
+                    XNFocusWindow, arg->focus_win,
+                    XNPreeditAttributes, arg->preedit_attrs,
+                    NULL);
+  else if (! arg->preedit_attrs && arg->status_attrs)
+    xic = XCreateIC (im_info->xim,
+                    XNInputStyle, arg->input_style,
+                    XNClientWindow, arg->client_win,
+                    XNFocusWindow, arg->focus_win,
+                    XNStatusAttributes, arg->status_attrs,
+                    NULL);
+  else
+    xic = XCreateIC (im_info->xim,
+                    XNInputStyle, arg->input_style,
+                    XNClientWindow, arg->client_win,
+                    XNFocusWindow, arg->focus_win,
+                    XNPreeditAttributes, arg->preedit_attrs,
+                    XNStatusAttributes, arg->status_attrs,
+                    NULL);
+  if (! xic)
+    MERROR (MERROR_WIN, -1);
 
+  MSTRUCT_MALLOC (ic_info, MERROR_WIN);
+  ic_info->xic = xic;
+  ic_info->win = arg->focus_win;
+  ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
+  ic->info = ic_info;
+  return 0;
+}
 
-MText *
-mwin__get_selection_text (MFrame *frame)
+static void
+xim_destroy_ic (MInputContext *ic)
 {
-  return NULL;
-}
+  MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
 
+  XDestroyIC (ic_info->xic);
+  mconv_free_converter (ic_info->converter);
+  free (ic_info);
+  ic->info = NULL;
+}
 
-void
-mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
+static int
+xim_filter (MInputContext *ic, MSymbol key, void *event)
 {
-  unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
-  XGCValues values;
-  Display *display = FRAME_DISPLAY (frame);
-  GCInfo *info = rface->info;
-  int i;
+  MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
 
-  for (i = 0; i <= GC_INVERSE; i++)
-    {
-      XGetGCValues (display, info->gc[i], valuemask, &values);
-      fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
-              values.foreground, values.background);
-      fprintf (stderr, "\n");
-    }
+  return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
 }
 
-/*** @} */
-#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
-\f
-/* External API */
 
-/*=*/
-/*** @addtogroup m17nFrame */
-/*** @{ */
-/*=*/
+static int
+xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
+{
+  MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
+  MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
+  XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
+  KeySym keysym;
+  Status status;
+  char *buf;
+  int len;
 
-/***en
-    @name Variables: Keys of frame parameter (X specific).
+  buf = (char *) alloca (512);
+  len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
+  if (status == XBufferOverflow)
+    {
+      buf = (char *) alloca (len);
+      len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
+    }
 
-    These are the symbols to use as parameter keys for the function
-    mframe () (which see).  They are also keys of a frame property
-    except for #Mwidget.  */
-/***ja
-    @name ÊÑ¿ô¡§ ¥Õ¥ì¡¼¥à¥Ñ¥é¥á¡¼¥¿ÍÑ¥­¡¼ (X ¸ÇÍ­).
+  mtext_reset (ic->produced);
+  if (len == 0)
+    return 1;
 
-    ´Ø¿ô mframe () ¤Î¥Ñ¥é¥á¡¼¥¿¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¥·¥ó¥Ü¥ë¡£( mframe
-    () ¤ÎÀâÌÀ»²¾È¡£) #Mwidget ¤ò½ü¤¤¤Æ¤Ï¥Õ¥ì¡¼¥à¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤Ç¤â¤¢
-    ¤ë¡£
-    */
+  mconv_reset_converter (ic_info->converter);
+  mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len);
+  mconv_decode (ic_info->converter, ic->produced);
+  mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced),
+                 Mlanguage, (void *) im_info->language);
+  mtext_cpy (mt, ic->produced);
+  mtext_reset (ic->produced);  
+  return 0;
+}
 
+\f
 /*=*/
-/*** @{ */ 
-/* Keywords for mwin__open_device ().  */
-MSymbol Mdisplay, Mscreen, Mdrawable, Mdepth, Mwidget, Mcolormap;
 
 /*** @} */
-/*** @} */
+#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
+\f
+/* External API */
 
-/*=*/
 /*** @addtogroup m17nInputMethodWin */
-/*=*/
-/*** @{ */
 
+/*** @{ */
+/*=*/
 /***en
     @brief Input method driver for XIM.
 
@@ -2155,11 +2643,11 @@ MSymbol Mdisplay, Mscreen, Mdrawable, Mdepth, Mwidget, Mcolormap;
 
     The argument $ARG of the function minput_open_im () must be a
     pointer to the structure #MInputXIMArgIM.  See the documentation
-    of #MInputXIMArgIM for more detail.
+    of #MInputXIMArgIM for more details.
 
     The argument $ARG of the function minput_create_ic () must be a
     pointer to the structure #MInputXIMArgIC. See the documentation
-    of #MInputXIMArgIC for more detail.
+    of #MInputXIMArgIC for more details.
 
     The argument $ARG of the function minput_filter () must be a
     pointer to the structure @c XEvent.  The argument $KEY is ignored.
@@ -2169,54 +2657,41 @@ MSymbol Mdisplay, Mscreen, Mdrawable, Mdepth, Mwidget, Mcolormap;
     $KEY is ignored.  */
 
 /***ja
-    @brief XIMÍÑÆþÎϥɥ饤¥Ð
+    @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 */
 
-/***en
-    @brief Symbol of the name "xim".
-
-    The variable Mxim is a symbol of name "xim".  It is a name of the
-    input method driver #minput_xim_driver.  */ 
-/***ja
-    @brief "xim"¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë .
-
-    ÊÑ¿ô Mxim ¤Ï"xim"¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£"xim" ¤ÏÆþÎϥ᥽¥Ã
-    ¥É¥É¥é¥¤¥Ð #minput_xim_driver ¤Î̾Á°¤Ç¤¢¤ë¡£  */ 
-
-MSymbol Mxim;
+int device_open () { return -1; }
 
-/*** @} */ 
+#endif /* not HAVE_X11 */
 
 /*
   Local Variables: