(FRAME_DEVICE): New macro.
authorhanda <handa>
Thu, 27 May 2004 09:06:17 +0000 (09:06 +0000)
committerhanda <handa>
Thu, 27 May 2004 09:06:17 +0000 (09:06 +0000)
(FRAME_DISPLAY, FRAME_SCREEN, FRAME_CMAP): Use FRAME_DEVICE.
(free_display_info): Use MPLIST_DO.
(free_device): Free rface->info.
(xft_close): Delete it.
(device_init): Renamed from mwin__init.
(device_fini): Renamed from mwin__fini.
(device_open): Renamed from mwin__open_device.
(x_driver): New variable.
(MXFontInfo): Delete member frame, add member display.
(Mdisplay, Mscreen, Mdrawable, Mdepth, Mwidget, Mcolormap, Mxim):
Don't declare them here.

src/m17n-X.c

index 7d28516..ddffeea 100644 (file)
@@ -122,7 +122,7 @@ typedef struct
 #endif
 } GCInfo;
 
-struct MWDevice
+typedef struct
 {
   /* Common header for the m17n object.  */
   M17NObject control;
@@ -151,15 +151,16 @@ struct MWDevice
 
   /** 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_CMAP(frame) ((frame)->device->cmap)
+#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))
 
@@ -180,10 +181,9 @@ 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))
+  MPLIST_DO (plist, disp_info->font_registry_list)
     {
-      MFontList *registry_list = mplist_value (plist);
+      MFontList *registry_list = MPLIST_VAL (plist);
 
       if (registry_list->fonts)
        free (registry_list->fonts);
@@ -191,10 +191,9 @@ free_display_info (void *object)
     }
   M17N_OBJECT_UNREF (disp_info->font_registry_list);
 
-  for (plist = disp_info->iso8859_1_family_list;
-       mplist_key (plist) != Mnil; plist = mplist_next (plist))
+  MPLIST_DO (plist, disp_info->iso8859_1_family_list)
     {
-      MFontList *family_list = mplist_value (plist);
+      MFontList *family_list = MPLIST_VAL (plist);
 
       if (family_list->fonts)
        free (family_list->fonts);
@@ -202,10 +201,9 @@ free_display_info (void *object)
     }
   M17N_OBJECT_UNREF (disp_info->iso8859_1_family_list);
 
-  for (plist = disp_info->iso10646_1_family_list;
-       mplist_key (plist) != Mnil; plist = mplist_next (plist))
+  MPLIST_DO (plist, disp_info->iso10646_1_family_list)
     {
-      MFontList *family_list = mplist_value (plist);
+      MFontList *family_list = MPLIST_VAL (plist);
 
       if (family_list->fonts)
        free (family_list->fonts);
@@ -213,9 +211,8 @@ free_display_info (void *object)
     }
   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));
+  MPLIST_DO (plist, disp_info->realized_font_list)
+    mfont__free_realized ((MRealizedFont *) MPLIST_VAL (plist));
   M17N_OBJECT_UNREF (disp_info->realized_font_list);
 
   if (disp_info->auto_display)
@@ -227,7 +224,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;
@@ -235,9 +232,13 @@ 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));
+  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)
@@ -344,7 +345,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;
 
@@ -407,1986 +408,1983 @@ get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity)
   return (info->gc[intensity] = gc);
 }
 
-\f
-/** X font handler */
+static GC
+set_region (MFrame *frame, GC gc, MDrawRegion region)
+{
+  unsigned long valuemask = GCForeground;
 
-/** Indices to each field of split font name.  */
+  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;
+}
 
-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
-  };
+\f
+/* Functions for the device driver.  */
 
-/** 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.
+void
+mwin__close_device (MFrame *frame)
+{
+  M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
+}
 
-    If NAME does not contain all XLFD fields, the unspecified fields is
-    treated as wild cards.  */
+void *
+mwin__device_get_prop (MFrame *frame, MSymbol key)
+{
+  MWDevice *device = FRAME_DEVICE (frame);
 
-static int
-split_font_name (char *name, char **field,
-                unsigned short *size, unsigned short *resy)
+  if (key == Mdisplay)
+    return (void *) device->display_info->display;
+  if (key == Mscreen)
+    return (void *) ScreenOfDisplay(device->display_info->display,
+                                   device->screen_num);
+  if (key == Mcolormap)
+    return (void *) device->cmap;
+  if (key == Mdepth)
+    return (void *) device->depth;
+  return NULL;
+}
+
+void
+mwin__realize_face (MRealizedFace *rface)
 {
-  int i;
-  char *p;
+  MFrame *frame;
+  MSymbol foreground, background, videomode;
+  MFaceHLineProp *hline;
+  MFaceBoxProp *box;
+  GCInfo *info;
 
-  for (i = 0, p = name; *p; p++)
+  if (rface != rface->ascii_rface)
     {
-      *p = tolower (*p);
-      if (*p == '-' && i < XLFD_FIELD_MAX)
-       {
-         field[i] = p + 1;
-         if (i != XLFD_ENCODING)
-           *p = '\0';
-         i++;
-       }
+      rface->info = rface->ascii_rface->info;
+      return;
     }
-  if (i < XLFD_REGISTRY)
-    return -1;
-  for (; i < XLFD_FIELD_MAX; i++)
-    field[i] = "*";
 
-  if (*(field[XLFD_RESY]) == '*')
-    *resy = 0;
+  frame = rface->frame;
+  MSTRUCT_CALLOC (info, MERROR_WIN);
+
+  foreground = rface->face.property[MFACE_FOREGROUND];
+  background = rface->face.property[MFACE_BACKGROUND];
+  videomode = rface->face.property[MFACE_VIDEOMODE];
+  if (! videomode)
+    videomode = frame->videomode;
+  if (videomode != Mreverse)
+    {
+      info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
+      info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
+    }
   else
-    *resy = atoi (field[XLFD_RESY]);
-  if (*(field[XLFD_PIXEL]) == '*')
     {
-      if (*(field[XLFD_POINT]) != '*')
-       *size = atoi (field[XLFD_POINT]) * *resy / 72;
-      else
-       *size = 0;
+      info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore);
+      info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back);
     }
-  else if (*(field[XLFD_PIXEL]) == '[')
+#ifdef HAVE_XFT2
+  if (foreground == Mnil)
+    foreground = frame->foreground;
+  if (background == Mnil)
+    background = frame->background;
+  if (videomode == Mreverse)
     {
-      /* 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;
+      MSymbol temp = foreground;
+      foreground = background;
+      background = temp;
     }
-  else
-    *size = atoi (field[XLFD_PIXEL]) * 10;
-  if (*size == 0 && *(field[XLFD_POINT]) != '*')
+  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
+
+  hline = rface->hline;
+  if (hline)
     {
-      *size = atoi (field[XLFD_POINT]);
-      if (*resy)
-       *size = *size * *resy / 72;
+      if (hline->color)
+       info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
       else
-       *size = *size * 100 / 72;
+       info->gc[GC_HLINE] = info->gc[GC_NORMAL];
     }
 
-  return 0;
-}
+  box = rface->box;
+  if (box)
+    {
+      if (box->color_top)
+       info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
+      else
+       info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
 
-static int
-build_font_name (MFont *font, char *name, int limit)
-{
-  MSymbol prop[7];
-  char *str[7];
-  int len, i;
-  unsigned short size, resy;
+      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_BOX_TOP];
 
-  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]);
-       }
+      if (box->color_bottom && box->color_bottom != box->color_top)
+       info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
       else
-       {
-         str[i] = "*";
-         len++;
-       }
+       info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_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_BOX_BOTTOM];
     }
-  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);
+  rface->info = info;
+}
 
-  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;
+
+void
+mwin__free_realized_face (MRealizedFace *rface)
+{
+  if (rface == rface->ascii_rface)
+    free (rface->info);
 }
 
-static MFontList *
-build_font_list (MFrame *frame, MSymbol family, MSymbol registry,
-                MPlist *plist)
+
+void
+mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
+                 int reverse,
+                 int x, int y, int width, int height, MDrawRegion region)
 {
-  char pattern[1024];
-  MFontList *font_list;
-  char **fontnames;
-  int nfonts;
-  int i, j;
+  GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
 
-  MSTRUCT_CALLOC (font_list, MERROR_WIN);
+  if (region)
+    gc = set_region (frame, gc, region);
 
-  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;
-    }
+  XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
+                 x, y, width, height);
+}
 
-  fontnames = XListFonts (FRAME_DISPLAY (frame), pattern, 0x8000, &nfonts);
-  if (nfonts > 0)
+
+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++)
     {
-      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))
-         j++;
-      XFreeFontNames (fontnames);
-      font_list->nfonts = j;
+      XDrawRectangle (display, (Window) win, gc,
+                     x, y - gstring->ascent + 1, from->width - 1,
+                     gstring->ascent + gstring->descent - 2);
+      x += from->width;
     }
-  mplist_add (plist, font_list->tag, font_list);
-  return (nfonts > 0 ? font_list : NULL);
 }
 
 
-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);
+void
+mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
+                MRealizedFace *rface, int reverse,
+                int x, int y, int width, MDrawRegion region)
+{
+  enum MFaceHLineType type = rface->hline->type;
+  GCInfo *info = rface->info;
+  GC gc = gc = info->gc[GC_HLINE];
+  int i;
 
-static MFontDriver xfont_driver =
-  { xfont_select, xfont_open, xfont_close,
-    xfont_find_metric, xfont_encode_char, xfont_render };
+  y = (type == MFACE_HLINE_BOTTOM
+       ? y + gstring->text_descent - rface->hline->width
+       : type == MFACE_HLINE_UNDER
+       ? y + 1
+       : type == MFACE_HLINE_STRIKE_THROUGH
+       ? y - ((gstring->ascent + gstring->descent) / 2)
+       : y - gstring->text_ascent);
+  if (region)
+    gc = set_region (frame, gc, region);
 
-/* The X font driver function SELECT.  */
+  for (i = 0; i < rface->hline->width; i++)
+    XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
+              x, y + i, x + width - 1, y + i);
+}
 
-static MRealizedFont *
-xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
+
+void
+mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
+               MGlyph *g, int x, int y, int width, MDrawRegion region)
 {
-  MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
-  MRealizedFont *rfont;
-  MFontList *font_list = NULL;
+  Display *display = FRAME_DISPLAY (frame);
+  MRealizedFace *rface = g->rface;
+  MFaceBoxProp *box = rface->box;
+  GCInfo *info = rface->info;
+  GC gc_top, gc_left, gc_right, gc_btm;
+  int y0, y1;
   int i;
-  MFont *best_font;
-  int best_score, score;
 
-  if (registry == Mnil
-      || ! strchr (MSYMBOL_NAME (registry), '-'))
-    return NULL;
+  y0 = y - (gstring->text_ascent
+           + rface->box->inner_vmargin + rface->box->width);
+  y1 = y + (gstring->text_descent
+           + rface->box->inner_vmargin + rface->box->width - 1);
 
-  /* 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)
+  gc_top = info->gc[GC_BOX_TOP];
+  if (region)
+    gc_top = set_region (frame, gc_top, region);
+  if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
+    gc_btm = gc_top;
+  else
+    gc_btm = info->gc[GC_BOX_BOTTOM];
+
+  if (g->type == GLYPH_BOX)
     {
-      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 x0, x1;
 
-      if (family != Mnil)
+      if (g->left_padding)
+       x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
+      else
+       x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
+
+      /* Draw the top side.  */
+      for (i = 0; i < box->width; i++)
+       XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
+
+      /* Draw the bottom side.  */
+      if (region && gc_btm != gc_top)
+       gc_btm = set_region (frame, gc_btm, region);
+      for (i = 0; i < box->width; i++)
+       XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
+
+      if (g->left_padding > 0)
        {
-         font_list = (MFontList *) mplist_get (family_list, family);
-         if (! font_list)
-           font_list = build_font_list (frame, family, registry, family_list);
+         /* Draw the left side.  */
+         if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
+           gc_left = gc_top;
+         else
+           {
+             gc_left = info->gc[GC_BOX_LEFT];
+             if (region)
+               gc_left = set_region (frame, gc_left, region);
+           }
+         for (i = 0; i < rface->box->width; i++)
+           XDrawLine (display, (Window) win, gc_left,
+                      x0 + i, y0 + i, x0 + i, y1 - i);
        }
-      if (! font_list)
+      else
        {
-         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);
+         /* Draw the right side.  */
+         if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
+           gc_right = gc_top;
+         else
+           {
+             gc_right = info->gc[GC_BOX_RIGHT];
+             if (region)
+               gc_right = set_region (frame, gc_right, region);
+           }
+         for (i = 0; i < rface->box->width; i++)
+           XDrawLine (display, (Window) win, gc_right,
+                      x1 - i, y0 + i, x1 - i, y1 - i);
        }
     }
-  if (! font_list)
+  else
     {
-      MPlist *registry_list
-       = frame->device->display_info->font_registry_list;
+      /* Draw the top side.  */
+      for (i = 0; i < box->width; i++)
+       XDrawLine (display, (Window) win, gc_top,
+                  x, y0 + i, x + width - 1, y0 + i);
 
-      font_list = (MFontList *) mplist_get (registry_list, registry);
-      if (! font_list)
-       font_list = build_font_list (frame, Mnil, registry, registry_list);
+      /* Draw the bottom side.  */
+      if (region && gc_btm != gc_top)
+       gc_btm = set_region (frame, gc_btm, region);
+      for (i = 0; i < box->width; i++)
+       XDrawLine (display, (Window) win, gc_btm,
+                  x, y1 - i, x + width - 1, y1 - i);
     }
-  if (! font_list)
-    return NULL;
+}
 
-  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++)
-    {
-      score = mfont__score (font_list->fonts + i, spec, request,
-                           limited_size);
-      if (score >= 0 && score < best_score)
-       {
-         best_font = font_list->fonts + i;
-         best_score = score;
-       }
-    }
 
-  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;
+#if 0
+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,
+                  MDrawRegion region)
+{
+  Display *display = FRAME_DISPLAY (frame);
+  int i, j;
+  GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
+
+  if (region)
+    gc = set_region (frame, gc, region);
+
+  for (i = 0; i < height; i++, bmp += row_bytes)
+    for (j = 0; j < width; j++)
+      if (bmp[j / 8] & (1 << (7 - (j % 8))))
+       XDrawPoint (display, (Window) win, gc, x + j, y + i);
 }
+#endif
 
-typedef struct
+void
+mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
+                  int intensity, MDrawPoint *points, int num,
+                  MDrawRegion region)
 {
-  M17NObject control;
-  MFrame *frame;
-  XFontStruct *f;
-} MXFontInfo;
+  GCInfo *info = rface->info;
+  GC gc;
 
-static void
-close_xfont (void *object)
-{
-  MXFontInfo *xfont = (MXFontInfo *) object;
+  if (! (gc = info->gc[intensity]))
+    gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame),
+                                                     info, intensity);
+  if (region)
+    gc = set_region (frame, gc, region);
 
-  if (xfont->f)
-    XFreeFont (FRAME_DISPLAY (xfont->frame), xfont->f);
-  free (object);
+  XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
+              (XPoint *) points, num, CoordModeOrigin);
 }
 
 
-/* The X font driver function OPEN.  */
-
-static int
-xfont_open (MRealizedFont *rfont)
+MDrawRegion
+mwin__region_from_rect (MDrawMetric *rect)
 {
-  char name[1024];
-  MXFontInfo *xfont;
-  MFrame *frame = rfont->frame;
-  int mdebug_mask = MDEBUG_FONT;
+  MDrawRegion region1 = XCreateRegion ();
+  MDrawRegion region2 = XCreateRegion ();
+  XRectangle xrect;
 
-  /* 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)
-    {
-      rfont->status = -1;
-      MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
-      return -1;
-    }
-  MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
-  rfont->status = 1;
-  rfont->ascent = xfont->f->ascent;
-  rfont->descent = xfont->f->descent;
-  return 0;
+  xrect.x = rect->x;
+  xrect.y = rect->y;
+  xrect.width = rect->width;
+  xrect.height = rect->height;
+  XUnionRectWithRegion (&xrect, region1, region2);
+  XDestroyRegion (region1);
+  return region2;
 }
 
+void
+mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
+{
+  MDrawRegion region1 = XCreateRegion ();
+  XRectangle xrect;
 
-/* The X font driver function CLOSE.  */
+  xrect.x = rect->x;
+  xrect.y = rect->y;
+  xrect.width = rect->width;
+  xrect.height = rect->height;
 
-static void
-xfont_close (MRealizedFont *rfont)
-{
-  M17N_OBJECT_UNREF (rfont->info);
+  XUnionRegion (region, region, region1);
+  XUnionRectWithRegion (&xrect, region1, region);
+  XDestroyRegion (region1);
 }
 
-/* The X font driver function FIND_METRIC.  */
-
-static void
-xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
-                  int from, int to)
+void
+mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
 {
-  MXFontInfo *xfont = (MXFontInfo *) rfont->info;
-  XFontStruct *f = xfont->f;
-  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 (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));
-                   }
-               }
-           }
+  MDrawRegion region = XCreateRegion ();
 
-         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;
-           }
-       }
-    }
+  XUnionRegion (region1, region1, region);
+  XIntersectRegion (region, region2, region1);
+  XDestroyRegion (region);
 }
 
-
-/* The X font driver function ENCODE_CHAR.  */
-
-static unsigned
-xfont_encode_char (MRealizedFont *rfont, int c, unsigned code)
+void
+mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
 {
-  MXFontInfo *xfont;
-  XFontStruct *f;
-  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 (xfont_open (rfont) < 0)
-       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;
-
-  if (min_byte1 == 0 && max_byte1 == 0)
-    {
-      XCharStruct *pcm;
+  MDrawRegion region1 = XCreateRegion ();
+  XRectangle xrect;
 
-      if (code < min_byte2 || code > max_byte2)
-       return MCHAR_INVALID_CODE;
-      if (all_chars_exist)
-       return code;
-      pcm = f->per_char + (code - min_byte2);
-      return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
-             ? code : MCHAR_INVALID_CODE);
-    }
-  else
-    {
-      unsigned byte1 = code >> 8, byte2 = code & 0xFF;
-      XCharStruct *pcm;
+  xrect.x = rect->x;
+  xrect.y = rect->y;
+  xrect.width = rect->width;
+  xrect.height = rect->height;
+  XUnionRectWithRegion (&xrect, region1, region);
+  XDestroyRegion (region1);
+}
 
-      if (byte1 < min_byte1 || byte1 > max_byte1
-         || byte2 < min_byte2 || byte2 > max_byte2)
-       return MCHAR_INVALID_CODE;
+void
+mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
+{
+  XRectangle xrect;
 
-      if (all_chars_exist)
-       return code;
-      pcm = f->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);
-    }
+  XClipBox (region, &xrect);
+  rect->x = xrect.x;
+  rect->y = xrect.y;
+  rect->width = xrect.width;
+  rect->height = xrect.height;
 }
 
-static GC
-set_region (MFrame *frame, GC gc, MDrawRegion region)
+void
+mwin__free_region (MDrawRegion region)
 {
-  unsigned long valuemask = GCForeground;
+  XDestroyRegion (region);
+}
 
-  XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
-          frame->device->scratch_gc);
-  XSetRegion (FRAME_DISPLAY (frame), frame->device->scratch_gc, region);
-  return frame->device->scratch_gc;
+void
+mwin__dump_region (MDrawRegion region)
+{
+  XRectangle rect;
+  XClipBox (region, &rect);
+  fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
 }
 
-/* The X font driver function RENDER.  */
 
-static void
-xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
-             MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
+MDrawWindow
+mwin__create_window (MFrame *frame, MDrawWindow parent)
 {
-  MRealizedFace *rface = from->rface;
-  Display *display;
-  XChar2b *code;
-  GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
-  MGlyph *g;
-  int i;
+  Display *display = FRAME_DISPLAY (frame);
+  Window win;
+  XWMHints wm_hints = { InputHint, False };
+  XClassHint class_hints = { "M17N-IM", "m17n-im" };
+  XSetWindowAttributes set_attrs;
+  unsigned long mask;
+  XGCValues values;
+  GCInfo *info = frame->rface->info;
 
-  if (from == to)
-    return;
+  if (! parent)
+    parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
+  mask = GCForeground;
+  XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
+  set_attrs.background_pixel = values.foreground;
+  set_attrs.backing_store = Always;
+  set_attrs.override_redirect = True;
+  set_attrs.save_under = True;
+  mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
+  win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
+                      CopyFromParent, InputOutput, CopyFromParent,
+                      mask, &set_attrs);
+  XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
+                   NULL, &wm_hints, &class_hints);
+  XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
+  return (MDrawWindow) win;
+}
 
-  /* It is assured that the all glyphs in the current range use the
-     same realized face.  */
-  display = FRAME_DISPLAY (rface->frame);
+void
+mwin__destroy_window (MFrame *frame, MDrawWindow win)
+{
+  XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
+}
 
-  if (region)
-    gc = set_region (rface->frame, gc, region);
-  if (! rface->rfont || from->code == MCHAR_INVALID_CODE)
-    {
-      int x0 = x;
+#if 0
+MDrawWindow
+mwin__event_window (void *event)
+{
+  return ((MDrawWindow) ((XEvent *) event)->xany.window);
+}
 
-      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;
-    }
+void
+mwin__print_event (void *arg, char *win_name)
+{
+  char *event_name;
+  XEvent *event = (XEvent *) arg;
 
-  XSetFont (display, gc, ((MXFontInfo *) (rface->rfont->info))->f->fid);
-  code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
-  for (i = 0, g = from; g < to; i++, g++)
+  switch (event->xany.type)
     {
-      code[i].byte1 = g->code >> 8;
-      code[i].byte2 = g->code & 0xFF;
+    case 2: event_name = "KeyPress"; break;
+    case 3: event_name = "KeyRelease"; break;
+    case 4: event_name = "ButtonPress"; break;
+    case 5: event_name = "ButtonRelease"; break;
+    case 6: event_name = "MotionNotify"; break;
+    case 7: event_name = "EnterNotify"; break;
+    case 8: event_name = "LeaveNotify"; break;
+    case 9: event_name = "FocusIn"; break;
+    case 10: event_name = "FocusOut"; break;
+    case 11: event_name = "KeymapNotify"; break;
+    case 12: event_name = "Expose"; break;
+    case 13: event_name = "GraphicsExpose"; break;
+    case 14: event_name = "NoExpose"; break;
+    case 15: event_name = "VisibilityNotify"; break;
+    case 16: event_name = "CreateNotify"; break;
+    case 17: event_name = "DestroyNotify"; break;
+    case 18: event_name = "UnmapNotify"; break;
+    case 19: event_name = "MapNotify"; break;
+    case 20: event_name = "MapRequest"; break;
+    case 21: event_name = "ReparentNotify"; break;
+    case 22: event_name = "ConfigureNotify"; break;
+    case 23: event_name = "ConfigureRequest"; break;
+    case 24: event_name = "GravityNotify"; break;
+    case 25: event_name = "ResizeRequest"; break;
+    case 26: event_name = "CirculateNotify"; break;
+    case 27: event_name = "CirculateRequest"; break;
+    case 28: event_name = "PropertyNotify"; break;
+    case 29: event_name = "SelectionClear"; break;
+    case 30: event_name = "SelectionRequest"; break;
+    case 31: event_name = "SelectionNotify"; break;
+    case 32: event_name = "ColormapNotify"; break;
+    case 33: event_name = "ClientMessage"; break;
+    case 34: event_name = "MappingNotify"; break;
+    default: event_name = "unknown";
     }
 
-  g = from;
-  while (g < to)
-    {
-      if (g->type == GLYPH_PAD)
-       x += g++->width;
-      else if (g->type == GLYPH_SPACE)
-       for (; g < to && g->type == GLYPH_SPACE; g++)
-         x += g->width;
-      else if (! g->rface->rfont)
-       {
-         if ((g->c >= 0x200B && g->c <= 0x200F)
-             || (g->c >= 0x202A && g->c <= 0x202E))
-           x += g++->width;
-         else
-           {
-             /* As a font is not found for this character, draw an
-                empty box.  */
-             int box_width = g->width;
-             int box_height = gstring->ascent + gstring->descent;
-
-             if (box_width > 4)
-               box_width -= 2;
-             if (box_height > 4)
-               box_height -= 2;
-             XDrawRectangle (display, (Window) win, gc,
-                             x, y - gstring->ascent, box_width, box_height);
-             x += g++->width;
-           }
-       }
-      else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
-       {
-         XDrawString16 (display, (Window) win, gc,
-                        x + g->xoff, y + g->yoff, code + (g - from), 1);
-         x += g->width;
-         g++;
-       }
-      else
-       {
-         int orig_x = x;
-         int code_idx = g - from;
+  fprintf (stderr, "%s: %s\n", win_name, event_name);
+}
+#endif
 
-         for (i = 0;
-              g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
-              i++, g++)
-             x += g->width;
-         XDrawString16 (display, (Window) win, gc, orig_x, y,
-                        code + code_idx, i);
-       }
-    }
+void
+mwin__map_window (MFrame *frame, MDrawWindow win)
+{
+  XMapRaised (FRAME_DISPLAY (frame), (Window) win);
 }
 
-\f
-/* Xft Handler */
+void
+mwin__unmap_window (MFrame *frame, MDrawWindow win)
+{
+  XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
+}
 
-#ifdef HAVE_XFT2
+void
+mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
+                      MDrawMetric *geometry)
+{
+  Display *display = FRAME_DISPLAY (frame);
+  XWindowAttributes attr;
+  Window parent = (Window) parent_win, root;
 
-typedef struct {
-  M17NObject control;
-  MFrame *frame;
-  XftFont *font_aa;
-  XftFont *font_no_aa;
-} MXftFontInfo;
+  XGetWindowAttributes (display, (Window) win, &attr);
+  geometry->x = attr.x + attr.border_width;
+  geometry->y = attr.y + attr.border_width;
+  geometry->width = attr.width;
+  geometry->height = attr.height; 
 
-static MRealizedFont *xft_select (MFrame *, MFont *, MFont *, int);
-static int xft_open (MRealizedFont *);
-static void xft_close (MRealizedFont *);
-static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
-static void xft_render (MDrawWindow, int, int, MGlyphString *,
-                       MGlyph *, MGlyph *, int, MDrawRegion);
+  if (! parent)
+    parent = RootWindow (display, FRAME_SCREEN (frame));
+  while (1)
+    {
+      Window this_parent, *children;
+      unsigned n;
 
-MFontDriver xft_driver =
-  { xft_select, xft_open, xft_close,
-    xft_find_metric,
-    NULL,                      /* Set to ft_encode_char in mwin__init (). */
-    xft_render };
+      XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
+      if (children)
+       XFree (children);
+      if (this_parent == parent || this_parent == root)
+       break;
+      win = (MDrawWindow) this_parent;
+      XGetWindowAttributes (display, (Window) win, &attr);
+      geometry->x += attr.x + attr.border_width;
+      geometry->y += attr.y + attr.border_width;
+    }
+}
 
-static MRealizedFont *
-xft_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
+void
+mwin__adjust_window (MFrame *frame, MDrawWindow win,
+                    MDrawMetric *current, MDrawMetric *new)
 {
-  MRealizedFont *rfont;
+  Display *display = FRAME_DISPLAY (frame);
+  unsigned int mask = 0;
+  XWindowChanges values;
 
-  rfont = (mfont__ft_driver.select) (frame, spec, request, limited_size);
-  if (rfont)
-    rfont->driver = &xft_driver;
-  return rfont;
+  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 void
-close_xft (void *object)
+MSymbol
+mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
 {
-  MXftFontInfo *font_info = object;
+  XEvent *event = (XEvent *) arg;
+  MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
+  int len;
+  char buf[512];
+  KeySym keysym;
+  MSymbol key;
 
-  if (font_info->font_aa)
-    XftFontClose (FRAME_DISPLAY (font_info->frame), font_info->font_aa);
-  if (font_info->font_no_aa)
-    XftFontClose (FRAME_DISPLAY (font_info->frame), font_info->font_no_aa);
-  free (object);
-}
+  *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;
 
+      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 XftFont *
-xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
-{
-  XftPattern *pattern;
-  XftFontInfo *xft_font_info;
-  XftFont *font;
+      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;
 
-  pattern = XftPatternCreate ();
-  XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
-  XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
-  XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
-  xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
-  if (! xft_font_info)
-    return NULL;
-  font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
-  XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
-  return font;
+  return key;
 }
 
 
-static int
-xft_open (MRealizedFont *rfont)
+MText *
+mwin__get_selection_text (MFrame *frame)
 {
-  MFrame *frame;
-  MFTInfo *ft_info;
-  MXftFontInfo *font_info;
-  int size;
+  return NULL;
+}
 
-  if ((mfont__ft_driver.open) (rfont) < 0)
-    return -1;
 
-  size = rfont->font.property[MFONT_SIZE] / 10;
-  frame = rfont->frame;
+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;
 
-  ft_info = rfont->info;
-  M17N_OBJECT (font_info, close_xft, MERROR_WIN);
-  ft_info->extra_info = font_info;
-  font_info->frame = frame;
-  font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
-  if (font_info->font_aa)
+  for (i = 0; i <= GC_INVERSE; i++)
     {
-      font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
-      if (font_info->font_no_aa)
-       return 0;
+      XGetGCValues (display, info->gc[i], valuemask, &values);
+      fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
+              values.foreground, values.background);
+      fprintf (stderr, "\n");
     }
-  M17N_OBJECT_UNREF (font_info);  
-  ft_info->extra_info = NULL;
-  rfont->status = -1;
-  return -1;
 }
 
+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
+  };
 
-static void
-xft_close (MRealizedFont *rfont)
-{
-  M17N_OBJECT_UNREF (rfont->info);
-}
-
-
-static void
-xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
-               int from, int to)
-{
-  MFTInfo *ft_info = rfont->info;
-  MXftFontInfo *font_info = ft_info->extra_info;
-  FT_Face ft_face = ft_info->ft_face;
-  MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
-
-  for (; g != gend; g++)
-    {
-      if (g->code == MCHAR_INVALID_CODE)
-       {
-         MGlyph *start = g++;
-
-         while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
-         (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
-                                         GLYPH_INDEX (g));
-         g--;
-       }
-      else
-       {
-         XGlyphInfo extents;
-         unsigned code;
-
-         if (g->otf_encoded)
-           code = g->code;
-         else
-           code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
+\f
+/** X font handler */
 
-         XftGlyphExtents (FRAME_DISPLAY (font_info->frame),
-                          font_info->font_aa, &code, 1, &extents);
-         g->lbearing = extents.x;
-         g->rbearing = extents.width - extents.x;
-         g->width = extents.xOff;
-         g->ascent = extents.y;
-         g->descent = extents.height - extents.y;
-       }
-    }
-}
+static MRealizedFont *xfont_select (MFrame *, MFont *, MFont *, int);
+static int xfont_open (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 MFont *xfont_parse_name (char *name, MFont *font);
+static char *xfont_build_name (MFont *font);
 
+static MFontDriver xfont_driver =
+  { xfont_select, xfont_open,
+    xfont_find_metric, xfont_encode_char, xfont_render,
+    xfont_parse_name, xfont_build_name };
 
-void 
-xft_render (MDrawWindow win, int x, int y,
-           MGlyphString *gstring, MGlyph *from, MGlyph *to,
-           int reverse, MDrawRegion region)
+typedef struct
 {
-  MRealizedFace *rface = from->rface;
-  MFrame *frame = rface->frame;
-  MFTInfo *ft_info = rface->rfont->info;
-  MXftFontInfo *font_info = ft_info->extra_info;
-  FT_Face ft_face = ft_info->ft_face;
-  XftDraw *xft_draw = frame->device->xft_draw;
-  XftColor *xft_color = (! reverse
-                        ? &((GCInfo *) rface->info)->xft_color_fore
-                        : &((GCInfo *) rface->info)->xft_color_back);
-  XftFont *xft_font = (gstring->control.anti_alias && frame->device->depth > 1
-                      ? font_info->font_aa : font_info->font_no_aa);
-  MGlyph *g;
-  FT_UInt *glyphs;
-  int last_x;
-  int nglyphs;
-
-  if (from == to)
-    return;
-
-  XftDrawChange (xft_draw, (Drawable) win);
-  XftDrawSetClip (xft_draw, (Region) region);
-      
-  glyphs = alloca (sizeof (FT_UInt) * (to - from));
-  for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
-    {
-      unsigned code;
-
-      if (g->otf_encoded)
-       code = g->code;
-      else
-       code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
-      if (g->xoff == 0 && g->yoff == 0)
-       glyphs[nglyphs++] = 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->xoff, y + g->yoff, (FT_UInt *) &code, 1);
-         last_x = x + g->width;
-       }
-    }
-  if (nglyphs > 0)
-    XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
-}
-
-#endif
+  M17NObject control;
+  Display *display;
+  XFontStruct *xfont;
+} MXFontInfo;
 
-\f
+/** Indices to each field of split font name.  */
 
-/* XIM (X Input Method) handler */
+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
+  };
 
-typedef struct MInputXIMMethodInfo
-{
-  Display *display;
-  XIM xim;
-  MSymbol language;
-  MSymbol coding;
-} MInputXIMMethodInfo;
+/** 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.
 
-typedef struct MInputXIMContextInfo
-{
-  XIC xic;
-  Window win;
-  MConverter *converter;
-} MInputXIMContextInfo;
+    If NAME does not contain all XLFD fields, the unspecified fields is
+    treated as wild cards.  */
 
 static int
-xim_open_im (MInputMethod *im)
+split_font_name (char *name, char **field,
+                unsigned short *size, unsigned short *resy)
 {
-  MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
-  MLocale *saved, *this;
-  char *save_modifier_list;
-  XIM xim;
-  MInputXIMMethodInfo *im_info;
+  int i;
+  char *p;
 
-  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)
+  for (i = 0, p = name; *p; p++)
     {
-      /* Unable to decode the output of XIM.  */
-      mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
-      MERROR (MERROR_LOCALE, -1);
+      *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] = "*";
 
-  if (arg->modifier_list)
-    save_modifier_list = XSetLocaleModifiers (arg->modifier_list);
+  if (*(field[XLFD_RESY]) == '*')
+    *resy = 0;
   else
-    save_modifier_list = XSetLocaleModifiers ("");
-  if (! save_modifier_list)
+    *resy = atoi (field[XLFD_RESY]);
+  if (*(field[XLFD_PIXEL]) == '*')
     {
-      /* The specified locale is not supported by X.  */
-      mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
-      MERROR (MERROR_LOCALE, -1);
+      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;
 
-  xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class);
-  if (! xim)
+      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]) != '*')
     {
-      /* 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);
+      *size = atoi (field[XLFD_POINT]);
+      if (*resy)
+       *size = *size * *resy / 72;
+      else
+       *size = *size * 100 / 72;
     }
 
-  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;
 }
 
-static void
-xim_close_im (MInputMethod *im)
-{
-  MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
-
-  XCloseIM (im_info->xim);
-  free (im_info);
-}
-
-static int
-xim_create_ic (MInputContext *ic)
+char *
+build_font_name (MFont *font, char *name, int limit)
 {
-  MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
-  MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
-  MInputXIMContextInfo *ic_info;
-  XIC xic;
+  MSymbol prop[7];
+  char *str[7];
+  int len, i;
+  unsigned short size, resy;
 
-  if (! arg->input_style)
-    {
-      /* By default, use Root style.  */
-      arg->input_style = XIMPreeditNothing | XIMStatusNothing;
-      arg->preedit_attrs = NULL;
-      arg->status_attrs = NULL;
+  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 NULL;
 
-  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 = (int) mfont_get_prop (font, Msize);
+  if ((size % 10) < 5)
+    size /= 10;
   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 = size / 10 + 1;
+  resy = (int) mfont_get_prop (font, Mresolution);
 
-  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;
+  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 name;
 }
 
-static void
-xim_destroy_ic (MInputContext *ic)
+static MFontList *
+build_font_list (MFrame *frame, MSymbol family, MSymbol registry,
+                MPlist *plist)
 {
-  MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
+  char pattern[1024];
+  MFontList *font_list;
+  char **fontnames;
+  int nfonts;
+  int i, j;
 
-  XDestroyIC (ic_info->xic);
-  mconv_free_converter (ic_info->converter);
-  free (ic_info);
-  ic->info = NULL;
-}
+  MSTRUCT_CALLOC (font_list, MERROR_WIN);
 
-static int
-xim_filter (MInputContext *ic, MSymbol key, void *event)
-{
-  MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
+  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;
+    }
 
-  return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
+  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 (xfont_parse_name (fontnames[i], font_list->fonts + j)
+           && (font_list->fonts[j].property[MFONT_SIZE] != 0
+               || font_list->fonts[j].property[MFONT_RESY] == 0))
+         j++;
+      XFreeFontNames (fontnames);
+      font_list->nfonts = j;
+    }
+  mplist_add (plist, font_list->tag, font_list);
+  return (nfonts > 0 ? font_list : NULL);
 }
 
+/* The X font driver function SELECT.  */
 
-static int
-xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
+static MRealizedFont *
+xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
 {
-  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;
+  MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
+  MRealizedFont *rfont;
+  MFontList *font_list = NULL;
+  int i;
+  MFont *best_font;
+  int best_score, score;
 
-  buf = (char *) alloca (512);
-  len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status);
-  if (status == XBufferOverflow)
+  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)
     {
-      buf = (char *) alloca (len);
-      len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status);
+      MPlist *family_list
+       = (registry == M_iso8859_1
+          ? FRAME_DEVICE (frame)->display_info->iso8859_1_family_list
+          : FRAME_DEVICE (frame)->display_info->iso10646_1_family_list);
+      MSymbol family = FONT_PROPERTY (spec, MFONT_FAMILY);
+
+      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)
+    {
+      MPlist *registry_list
+       = FRAME_DEVICE (frame)->display_info->font_registry_list;
 
-  mtext_reset (ic->produced);
-  if (len == 0)
-    return 1;
+      font_list = (MFontList *) mplist_get (registry_list, registry);
+      if (! font_list)
+       font_list = build_font_list (frame, Mnil, registry, registry_list);
+    }
+  if (! font_list)
+    return NULL;
 
-  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;
+  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++)
+    {
+      score = mfont__score (font_list->fonts + i, spec, request,
+                           limited_size);
+      if (score >= 0 && score < best_score)
+       {
+         best_font = font_list->fonts + i;
+         best_score = score;
+       }
+    }
+
+  MSTRUCT_CALLOC (rfont, MERROR_WIN);
+  rfont->frame = frame;
+  rfont->spec = *spec;
+  rfont->request = *request;
+  rfont->font = *best_font;
+  if (best_font->property[MFONT_SIZE] == 0)
+    rfont->font.property[MFONT_SIZE] = request->property[MFONT_SIZE];
+  rfont->score = best_score;
+  return rfont;
 }
 
-\f
 
-#ifdef X_SET_ERROR_HANDLER
-static int
-x_error_handler (Display *display, XErrorEvent *error)
+/* The X font driver function CLOSE.  */
+
+static void
+close_xfont (void *object)
 {
-  mdebug_hook ();
-  return 0;
+  MXFontInfo *xfont_info = object;
+
+  XFreeFont (xfont_info->display, xfont_info->xfont);
+  free (object);
 }
 
+
+/* The X font driver function OPEN.  */
+
 static int
-x_io_error_handler (Display *display)
+xfont_open (MRealizedFont *rfont)
 {
-  mdebug_hook ();
+  char name[1024];
+  MXFontInfo *xfont_info;
+  MFrame *frame = rfont->frame;
+  int mdebug_mask = MDEBUG_FONT;
+
+  /* This never fail to generate a valid fontname because open_spec
+     should correspond to a font available on the system.  */
+  build_font_name (&rfont->font, name, 1024);
+  M17N_OBJECT (xfont_info, close_xfont, MERROR_WIN);
+  xfont_info->display = FRAME_DISPLAY (frame);
+  xfont_info->xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
+  if (! xfont_info->xfont)
+    {
+      rfont->status = -1;
+      free (xfont_info);
+      MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
+      return -1;
+    }
+  rfont->info = xfont_info;
+  MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
+  rfont->status = 1;
+  rfont->ascent = xfont_info->xfont->ascent;
+  rfont->descent = xfont_info->xfont->descent;
   return 0;
 }
-#endif
-
-\f
 
-int
-mwin__init ()
-{
-  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");
 
-  display_info_list = mplist ();
-  device_list = mplist ();
+/* The X font driver function FIND_METRIC.  */
 
-  mplist_add (mfont__driver_list, msymbol ("x"), &xfont_driver);
-#ifdef HAVE_XFT2
-  xft_driver.encode_char = mfont__ft_driver.encode_char;
-  mplist_put (mfont__driver_list, msymbol ("freetype"), &xft_driver);
-#endif
-
-  Mxim = msymbol ("xim");
-  msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
-
-  return 0;
-}
-
-void
-mwin__fini ()
-{
-  M17N_OBJECT_UNREF (display_info_list);
-  M17N_OBJECT_UNREF (device_list);
-}
-
-int
-mwin__parse_font_name (char *name, MFont *font)
+static void
+xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
+                  int from, int to)
 {
-  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;
+  MXFontInfo *xfont_info = rfont->info;
+  XFontStruct *xfont = xfont_info->xfont;
+  MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
 
-  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)
+  for (; g != gend; g++)
     {
-      memcpy (copy, name, last - name);
-      for (; i < 14; i++)
-       strcat (copy, "-*");
-      strcat (copy, last);
-    }
-
-  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;
-}
-
+      if (g->code == MCHAR_INVALID_CODE)
+       {
+         g->lbearing = xfont->max_bounds.lbearing;
+         g->rbearing = xfont->max_bounds.rbearing;
+         g->width = xfont->max_bounds.width;
+         g->ascent = xfont->ascent;
+         g->descent = xfont->descent;
+       }
+      else
+       {
+         int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
+         XCharStruct *pcm = NULL;
 
-char *
-mwin__build_font_name (MFont *font)
-{
-  char name[1024];
+         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 (build_font_name (font, name, 1024) < 0)
-    return NULL;
-  return strdup (name);
+         if (pcm)
+           {
+             g->lbearing = pcm->lbearing;
+             g->rbearing = pcm->rbearing;
+             g->width = pcm->width;
+             g->ascent = pcm->ascent;
+             g->descent = pcm->descent;
+           }
+         else
+           {
+             /* If the per_char pointer is null, all glyphs between
+                the first and last character indexes inclusive have
+                the same information, as given by both min_bounds and
+                max_bounds.  */
+             g->lbearing = 0;
+             g->rbearing = xfont->max_bounds.width;
+             g->width = xfont->max_bounds.width;
+             g->ascent = xfont->ascent;
+             g->descent = xfont->descent;
+           }
+       }
+    }
 }
 
-/** 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.  */
+/* The X font driver function ENCODE_CHAR.  */
 
-MWDevice *
-mwin__open_device (MFrame *frame, MPlist *param)
+static unsigned
+xfont_encode_char (MRealizedFont *rfont, int c, unsigned code)
 {
-  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;
-  MFace *face;
+  MXFontInfo *xfont_info;
+  XFontStruct *xfont;
+  unsigned min_byte1, max_byte1, min_byte2, max_byte2;
+  int all_chars_exist;
 
-  for (plist = param; (key = mplist_key (plist)) != Mnil;
-       plist = mplist_next (plist))
+  if (rfont->status < 0 || code >= 0x10000)
+    return MCHAR_INVALID_CODE;
+  if (rfont->status == 0)
     {
-      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 (xfont_open (rfont) < 0)
+       return MCHAR_INVALID_CODE;
     }
+  xfont_info = rfont->info;
+  xfont = xfont_info->xfont;
+  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 (widget)
-    {
-      display = XtDisplay (widget);
-      screen_num = XScreenNumberOfScreen (XtScreen (widget));
-      depth = DefaultDepth (display, screen_num);
-    }
-  else if (drawable)
+  if (min_byte1 == 0 && max_byte1 == 0)
     {
-      Window root_window;
-      int x, y;
-      unsigned width, height, border_width;
+      XCharStruct *pcm;
 
-      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);
+      if (code < min_byte2 || code > max_byte2)
+       return MCHAR_INVALID_CODE;
+      if (all_chars_exist)
+       return code;
+      pcm = xfont->per_char + (code - min_byte2);
+      return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
+             ? code : MCHAR_INVALID_CODE);
     }
   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;
-    }
+      unsigned byte1 = code >> 8, byte2 = code & 0xFF;
+      XCharStruct *pcm;
 
-  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);
-    }  
+      if (byte1 < min_byte1 || byte1 > max_byte1
+         || byte2 < min_byte2 || byte2 > max_byte2)
+       return MCHAR_INVALID_CODE;
 
-  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 (all_chars_exist)
+       return code;
+      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);
     }
+}
 
-  if (mplist_key (plist) != Mnil)
-    M17N_OBJECT_REF (device);
-  else
-    {
-      unsigned long valuemask = GCForeground;
-      XGCValues values;
+/* The X font driver function RENDER.  */
 
-      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);
-#ifdef HAVE_XFT2
-      device->xft_draw = XftDrawCreate (display, device->drawable,
-                                       DefaultVisual (display, screen_num),
-                                       cmap);
-#endif
-    }
+static void
+xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
+             MGlyph *from, MGlyph *to, int reverse, MDrawRegion region)
+{
+  MRealizedFace *rface = from->rface;
+  MXFontInfo *xfont_info = rface->rfont->info;
+  Display *display;
+  XChar2b *code;
+  GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
+  MGlyph *g;
+  int i;
 
-  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 (from == to)
+    return;
 
-  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 }
-      };
+  /* It is assured that the all glyphs in the current range use the
+     same realized face.  */
+  display = FRAME_DISPLAY (rface->frame);
 
-      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
+  if (region)
+    gc = set_region (rface->frame, gc, region);
+  XSetFont (display, gc, xfont_info->xfont->fid);
+  code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
+  for (i = 0, g = from; g < to; i++, g++)
     {
-      app_data.font = DEFAULT_FONT;
-      frame->foreground = msymbol ("black");
-      frame->background = msymbol ("white");
-      frame->videomode = Mnormal;
+      code[i].byte1 = g->code >> 8;
+      code[i].byte2 = g->code & 0xFF;
     }
 
-  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);
-  }
-
-  face = mface_from_font (frame->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 device;
-}
+  g = from;
+  while (g < to)
+    {
+      if (g->type == GLYPH_PAD)
+       x += g++->width;
+      else if (g->type == GLYPH_SPACE)
+       for (; g < to && g->type == GLYPH_SPACE; g++)
+         x += g->width;
+      else if (! g->rface->rfont)
+       {
+         if ((g->c >= 0x200B && g->c <= 0x200F)
+             || (g->c >= 0x202A && g->c <= 0x202E))
+           x += g++->width;
+         else
+           {
+             /* As a font is not found for this character, draw an
+                empty box.  */
+             int box_width = g->width;
+             int box_height = gstring->ascent + gstring->descent;
 
-void
-mwin__close_device (MFrame *frame)
-{
-  M17N_OBJECT_UNREF (frame->device);
-}
+             if (box_width > 4)
+               box_width -= 2;
+             if (box_height > 4)
+               box_height -= 2;
+             XDrawRectangle (display, (Window) win, gc,
+                             x, y - gstring->ascent, box_width, box_height);
+             x += g++->width;
+           }
+       }
+      else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
+       {
+         XDrawString16 (display, (Window) win, gc,
+                        x + g->xoff, y + g->yoff, code + (g - from), 1);
+         x += g->width;
+         g++;
+       }
+      else
+       {
+         int orig_x = x;
+         int code_idx = g - from;
 
-void *
-mwin__device_get_prop (MWDevice *device, MSymbol key)
-{
-  if (key == Mdisplay)
-    return (void *) device->display_info->display;
-  if (key == Mscreen)
-    return (void *) ScreenOfDisplay(device->display_info->display,
-                                   device->screen_num);
-  if (key == Mcolormap)
-    return (void *) device->cmap;
-  if (key == Mdepth)
-    return (void *) device->depth;
-  return NULL;
+         for (i = 0;
+              g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
+              i++, g++)
+             x += g->width;
+         XDrawString16 (display, (Window) win, gc, orig_x, y,
+                        code + code_idx, i);
+       }
+    }
 }
 
-void
-mwin__realize_face (MRealizedFace *rface)
+static MFont *
+xfont_parse_name (char *name, MFont *font)
 {
-  MFrame *frame;
-  MSymbol foreground, background, videomode;
-  MFaceHLineProp *hline;
-  MFaceBoxProp *box;
-  GCInfo *info;
-
-  if (rface != rface->ascii_rface)
-    {
-      rface->info = rface->ascii_rface->info;
-      return;
-    }
-
-  frame = rface->frame;
-  MSTRUCT_CALLOC (info, MERROR_WIN);
-
-  foreground = rface->face.property[MFACE_FOREGROUND];
-  background = rface->face.property[MFACE_BACKGROUND];
-  videomode = rface->face.property[MFACE_VIDEOMODE];
-  if (! videomode)
-    videomode = frame->videomode;
-  if (videomode != Mreverse)
-    {
-      info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
-      info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
-    }
-  else
-    {
-      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
+  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;
 
-  hline = rface->hline;
-  if (hline)
+  len = strlen (name) + 1;
+  for (i = 0, p = name; *p; p++)
     {
-      if (hline->color)
-       info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
-      else
-       info->gc[GC_HLINE] = info->gc[GC_NORMAL];
+      if (*p == '-')
+       i++;
+      else if (p > name && *p == '*' && p[-1] == '-')
+       last = p + 1;
     }
-
-  box = rface->box;
-  if (box)
+  if (i == 14)
+    memcpy (copy, name, len);
+  else if (last)
     {
-      if (box->color_top)
-       info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL);
-      else
-       info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL];
-
-      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_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_BOX_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_BOX_BOTTOM];
+      memcpy (copy, name, last - name);
+      for (; i < 14; i++)
+       strcat (copy, "-*");
+      strcat (copy, last);
     }
 
-  rface->info = info;
+  if (split_font_name (copy, field, &size, &resy) < 0)
+    return NULL;
+  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 font;
 }
 
-
-void
-mwin__free_realized_face (MRealizedFace *rface)
+static char *
+xfont_build_name (MFont *font)
 {
-  if (rface == rface->ascii_rface)
-    free (rface->info);
+  char name[1024];
+
+  if (! build_font_name (font, name, 1024))
+    return NULL;
+  return strdup (name);
 }
 
+\f
+/* Xft Handler */
 
-void
-mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
-                 int reverse,
-                 int x, int y, int width, int height, MDrawRegion region)
+#ifdef HAVE_XFT2
+
+typedef struct
 {
-  GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
+  M17NObject control;
+  Display *display;
+  XftFont *font_aa;
+  XftFont *font_no_aa;
+} MXftFontInfo;
 
-  if (region)
-    gc = set_region (frame, gc, region);
+static MRealizedFont *xft_select (MFrame *, MFont *, MFont *, int);
+static int xft_open (MRealizedFont *);
+static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
+static void xft_render (MDrawWindow, int, int, MGlyphString *,
+                       MGlyph *, MGlyph *, int, MDrawRegion);
 
-  XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
-                 x, y, width, height);
-}
+MFontDriver xft_driver =
+  { NULL,                      /* Set to ft_select in mwin__init (). */
+    xft_open, xft_find_metric,
+    NULL,                      /* Set to ft_encode_char in mwin__init (). */
+    xft_render };
 
 
-void mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
-                            MGlyphString *gstring, MGlyph *from, MGlyph *to,
-                            int reverse, MDrawRegion region)
+static void
+close_xft (void *object)
 {
-  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;
+  MXftFontInfo *font_info = object;
 
-  if (region)
-    gc = set_region (rface->frame, gc, region);
-  for (; from < to; from++)
-    {
-      XDrawRectangle (display, (Window) win, gc,
-                     x, y - gstring->ascent + 1, from->width - 1,
-                     gstring->ascent + gstring->descent - 2);
-      x += from->width;
-    }
+  XftFontClose (font_info->display, font_info->font_aa);
+  XftFontClose (font_info->display, font_info->font_no_aa);
+  free (font_info);
 }
 
 
-void
-mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
-                MRealizedFace *rface, int reverse,
-                int x, int y, int width, MDrawRegion region)
+static XftFont *
+xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
 {
-  enum MFaceHLineType type = rface->hline->type;
-  GCInfo *info = rface->info;
-  GC gc = gc = info->gc[GC_HLINE];
-  int i;
-
-  y = (type == MFACE_HLINE_BOTTOM
-       ? y + gstring->text_descent - rface->hline->width
-       : type == MFACE_HLINE_UNDER
-       ? y + 1
-       : type == MFACE_HLINE_STRIKE_THROUGH
-       ? y - ((gstring->ascent + gstring->descent) / 2)
-       : y - gstring->text_ascent);
-  if (region)
-    gc = set_region (frame, gc, region);
+  XftPattern *pattern;
+  XftFontInfo *xft_font_info;
+  XftFont *font;
 
-  for (i = 0; i < rface->hline->width; i++)
-    XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
-              x, y + i, x + width - 1, y + i);
+  pattern = XftPatternCreate ();
+  XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
+  XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
+  XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
+  xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
+  if (! xft_font_info)
+    return NULL;
+  font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
+  XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
+  return font;
 }
 
 
-void
-mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
-               MGlyph *g, int x, int y, int width, MDrawRegion region)
+static int
+xft_open (MRealizedFont *rfont)
 {
-  Display *display = FRAME_DISPLAY (frame);
-  MRealizedFace *rface = g->rface;
-  MFaceBoxProp *box = rface->box;
-  GCInfo *info = rface->info;
-  GC gc_top, gc_left, gc_right, gc_btm;
-  int y0, y1;
-  int i;
+  MFrame *frame;
+  MFTInfo *ft_info;
+  MXftFontInfo *font_info;
+  int size;
 
-  y0 = y - (gstring->text_ascent
-           + rface->box->inner_vmargin + rface->box->width);
-  y1 = y + (gstring->text_descent
-           + rface->box->inner_vmargin + rface->box->width - 1);
+  if ((mfont__ft_driver.open) (rfont) < 0)
+    return -1;
 
-  gc_top = info->gc[GC_BOX_TOP];
-  if (region)
-    gc_top = set_region (frame, gc_top, region);
-  if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM])
-    gc_btm = gc_top;
-  else
-    gc_btm = info->gc[GC_BOX_BOTTOM];
+  size = rfont->font.property[MFONT_SIZE] / 10;
+  frame = rfont->frame;
 
-  if (g->type == GLYPH_BOX)
+  ft_info = rfont->info;
+  M17N_OBJECT (font_info, close_xft, MERROR_WIN);
+  ft_info->extra_info = font_info;
+  font_info->display = FRAME_DISPLAY (frame);
+  font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
+  if (font_info->font_aa)
     {
-      int x0, x1;
-
-      if (g->left_padding)
-       x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
-      else
-       x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
+      font_info->font_no_aa = xft_open_font (frame, ft_info, size, 0);
+      if (font_info->font_no_aa)
+       return 0;
+      XftFontClose (FRAME_DISPLAY (rfont->frame), font_info->font_aa);
+    }
+  free (font_info);  
+  ft_info->extra_info = NULL;
+  rfont->status = -1;
+  return -1;
+}
 
-      /* Draw the top side.  */
-      for (i = 0; i < box->width; i++)
-       XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
 
-      /* Draw the bottom side.  */
-      if (region && gc_btm != gc_top)
-       gc_btm = set_region (frame, gc_btm, region);
-      for (i = 0; i < box->width; i++)
-       XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
+static void
+xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
+               int from, int to)
+{
+  MFTInfo *ft_info = rfont->info;
+  MXftFontInfo *font_info = ft_info->extra_info;
+  FT_Face ft_face = ft_info->ft_face;
+  MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
 
-      if (g->left_padding > 0)
+  for (; g != gend; g++)
+    {
+      if (g->code == MCHAR_INVALID_CODE)
        {
-         /* Draw the left side.  */
-         if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
-           gc_left = gc_top;
-         else
-           {
-             gc_left = info->gc[GC_BOX_LEFT];
-             if (region)
-               gc_left = set_region (frame, gc_left, region);
-           }
-         for (i = 0; i < rface->box->width; i++)
-           XDrawLine (display, (Window) win, gc_left,
-                      x0 + i, y0 + i, x0 + i, y1 - i);
+         MGlyph *start = g++;
+
+         while (g != gend && g->code == MCHAR_INVALID_CODE) g++;
+         (mfont__ft_driver.find_metric) (rfont, gstring, GLYPH_INDEX (start),
+                                         GLYPH_INDEX (g));
+         g--;
        }
       else
        {
-         /* Draw the right side.  */
-         if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
-           gc_right = gc_top;
+         XGlyphInfo extents;
+         unsigned code;
+
+         if (g->otf_encoded)
+           code = g->code;
          else
-           {
-             gc_right = info->gc[GC_BOX_RIGHT];
-             if (region)
-               gc_right = set_region (frame, gc_right, region);
-           }
-         for (i = 0; i < rface->box->width; i++)
-           XDrawLine (display, (Window) win, gc_right,
-                      x1 - i, y0 + i, x1 - i, y1 - i);
-       }
-    }
-  else
-    {
-      /* Draw the top side.  */
-      for (i = 0; i < box->width; i++)
-       XDrawLine (display, (Window) win, gc_top,
-                  x, y0 + i, x + width - 1, y0 + i);
+           code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
 
-      /* Draw the bottom side.  */
-      if (region && gc_btm != gc_top)
-       gc_btm = set_region (frame, gc_btm, region);
-      for (i = 0; i < box->width; i++)
-       XDrawLine (display, (Window) win, gc_btm,
-                  x, y1 - i, x + width - 1, y1 - i);
+         XftGlyphExtents (FRAME_DISPLAY (rfont->frame),
+                          font_info->font_aa, &code, 1, &extents);
+         g->lbearing = extents.x;
+         g->rbearing = extents.width - extents.x;
+         g->width = extents.xOff;
+         g->ascent = extents.y;
+         g->descent = extents.height - extents.y;
+       }
     }
 }
 
 
-#if 0
-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,
-                  MDrawRegion region)
+void 
+xft_render (MDrawWindow win, int x, int y,
+           MGlyphString *gstring, MGlyph *from, MGlyph *to,
+           int reverse, MDrawRegion region)
 {
-  Display *display = FRAME_DISPLAY (frame);
-  int i, j;
-  GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
+  MRealizedFace *rface = from->rface;
+  MFrame *frame = rface->frame;
+  MFTInfo *ft_info = rface->rfont->info;
+  MXftFontInfo *font_info = ft_info->extra_info;
+  FT_Face ft_face = ft_info->ft_face;
+  XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
+  XftColor *xft_color = (! reverse
+                        ? &((GCInfo *) rface->info)->xft_color_fore
+                        : &((GCInfo *) rface->info)->xft_color_back);
+  XftFont *xft_font = (gstring->control.anti_alias
+                      && FRAME_DEVICE (frame)->depth > 1
+                      ? font_info->font_aa : font_info->font_no_aa);
+  MGlyph *g;
+  FT_UInt *glyphs;
+  int last_x;
+  int nglyphs;
 
-  if (region)
-    gc = set_region (frame, gc, region);
+  if (from == to)
+    return;
 
-  for (i = 0; i < height; i++, bmp += row_bytes)
-    for (j = 0; j < width; j++)
-      if (bmp[j / 8] & (1 << (7 - (j % 8))))
-       XDrawPoint (display, (Window) win, gc, x + j, y + i);
+  XftDrawChange (xft_draw, (Drawable) win);
+  XftDrawSetClip (xft_draw, (Region) region);
+      
+  glyphs = alloca (sizeof (FT_UInt) * (to - from));
+  for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
+    {
+      unsigned code;
+
+      if (g->otf_encoded)
+       code = g->code;
+      else
+       code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
+      if (g->xoff == 0 && g->yoff == 0)
+       glyphs[nglyphs++] = 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->xoff, y + g->yoff, (FT_UInt *) &code, 1);
+         last_x = x + g->width;
+       }
+    }
+  if (nglyphs > 0)
+    XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
 }
+
 #endif
 
-void
-mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
-                  int intensity, MDrawPoint *points, int num,
-                  MDrawRegion region)
-{
-  GCInfo *info = rface->info;
-  GC gc;
+\f
 
-  if (! (gc = info->gc[intensity]))
-    gc = info->gc[intensity] = get_gc_for_anti_alias (frame->device, info,
-                                                     intensity);
-  if (region)
-    gc = set_region (frame, gc, region);
+/* XIM (X Input Method) handler */
 
-  XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
-              (XPoint *) points, num, CoordModeOrigin);
-}
+typedef struct MInputXIMMethodInfo
+{
+  Display *display;
+  XIM xim;
+  MSymbol language;
+  MSymbol coding;
+} MInputXIMMethodInfo;
 
+typedef struct MInputXIMContextInfo
+{
+  XIC xic;
+  Window win;
+  MConverter *converter;
+} MInputXIMContextInfo;
 
-MDrawRegion
-mwin__region_from_rect (MDrawMetric *rect)
+static int
+xim_open_im (MInputMethod *im)
 {
-  MDrawRegion region1 = XCreateRegion ();
-  MDrawRegion region2 = XCreateRegion ();
-  XRectangle xrect;
+  MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg;
+  MLocale *saved, *this;
+  char *save_modifier_list;
+  XIM xim;
+  MInputXIMMethodInfo *im_info;
 
-  xrect.x = rect->x;
-  xrect.y = rect->y;
-  xrect.width = rect->width;
-  xrect.height = rect->height;
-  XUnionRectWithRegion (&xrect, region1, region2);
-  XDestroyRegion (region1);
-  return region2;
-}
+  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)
+    {
+      /* Unable to decode the output of XIM.  */
+      mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
+      MERROR (MERROR_LOCALE, -1);
+    }
 
-void
-mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
-{
-  MDrawRegion region1 = XCreateRegion ();
-  XRectangle xrect;
+  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);
+    }
 
-  xrect.x = rect->x;
-  xrect.y = rect->y;
-  xrect.width = rect->width;
-  xrect.height = rect->height;
+  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);
+    }
 
-  XUnionRegion (region, region, region1);
-  XUnionRectWithRegion (&xrect, region1, region);
-  XDestroyRegion (region1);
-}
+  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;
 
-void
-mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
-{
-  MDrawRegion region = XCreateRegion ();
+  XSetLocaleModifiers (save_modifier_list);
+  mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname)));
 
-  XUnionRegion (region1, region1, region);
-  XIntersectRegion (region, region2, region1);
-  XDestroyRegion (region);
+  return 0;
 }
 
-void
-mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
+static void
+xim_close_im (MInputMethod *im)
 {
-  MDrawRegion region1 = XCreateRegion ();
-  XRectangle xrect;
+  MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info;
 
-  xrect.x = rect->x;
-  xrect.y = rect->y;
-  xrect.width = rect->width;
-  xrect.height = rect->height;
-  XUnionRectWithRegion (&xrect, region1, region);
-  XDestroyRegion (region1);
+  XCloseIM (im_info->xim);
+  free (im_info);
 }
 
-void
-mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
+static int
+xim_create_ic (MInputContext *ic)
 {
-  XRectangle xrect;
+  MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
+  MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
+  MInputXIMContextInfo *ic_info;
+  XIC xic;
 
-  XClipBox (region, &xrect);
-  rect->x = xrect.x;
-  rect->y = xrect.y;
-  rect->width = xrect.width;
-  rect->height = xrect.height;
-}
+  if (! arg->input_style)
+    {
+      /* By default, use Root style.  */
+      arg->input_style = XIMPreeditNothing | XIMStatusNothing;
+      arg->preedit_attrs = NULL;
+      arg->status_attrs = NULL;
+    }
 
-void
-mwin__free_region (MDrawRegion region)
-{
-  XDestroyRegion (region);
+  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;
 }
 
-void
-mwin__dump_region (MDrawRegion region)
+static void
+xim_destroy_ic (MInputContext *ic)
 {
-  XRectangle rect;
-  XClipBox (region, &rect);
-  fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
+  MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
+
+  XDestroyIC (ic_info->xic);
+  mconv_free_converter (ic_info->converter);
+  free (ic_info);
+  ic->info = NULL;
 }
 
-void
-mwin__verify_region (MFrame *frame, MDrawRegion region)
+static int
+xim_filter (MInputContext *ic, MSymbol key, void *event)
 {
-  set_region (frame, ((GCInfo *) frame->rface->info)->gc[GC_NORMAL], region);
+  MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
+
+  return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
 }
 
-MDrawWindow
-mwin__create_window (MFrame *frame, MDrawWindow parent)
+
+static int
+xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
 {
-  Display *display = FRAME_DISPLAY (frame);
-  Window win;
-  XWMHints wm_hints = { InputHint, False };
-  XClassHint class_hints = { "M17N-IM", "m17n-im" };
-  XSetWindowAttributes set_attrs;
-  unsigned long mask;
-  XGCValues values;
-  GCInfo *info = frame->rface->info;
+  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;
 
-  if (! parent)
-    parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame));
-  mask = GCForeground;
-  XGetGCValues (display, info->gc[GC_INVERSE], mask, &values);
-  set_attrs.background_pixel = values.foreground;
-  set_attrs.backing_store = Always;
-  set_attrs.override_redirect = True;
-  set_attrs.save_under = True;
-  mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
-  win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0,
-                      CopyFromParent, InputOutput, CopyFromParent,
-                      mask, &set_attrs);
-  XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
-                   NULL, &wm_hints, &class_hints);
-  XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
-  return (MDrawWindow) win;
+  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);
+    }
+
+  mtext_reset (ic->produced);
+  if (len == 0)
+    return 1;
+
+  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;
 }
 
-void
-mwin__destroy_window (MFrame *frame, MDrawWindow win)
+\f
+
+#ifdef X_SET_ERROR_HANDLER
+static int
+x_error_handler (Display *display, XErrorEvent *error)
 {
-  XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
+  mdebug_hook ();
+  return 0;
 }
 
-#if 0
-MDrawWindow
-mwin__event_window (void *event)
+static int
+x_io_error_handler (Display *display)
 {
-  return ((MDrawWindow) ((XEvent *) event)->xany.window);
+  mdebug_hook ();
+  return 0;
 }
+#endif
 
-void
-mwin__print_event (void *arg, char *win_name)
+\f
+
+/* Functions to be stored in MDeviceLibraryInterface by dlsym ().  */
+
+int
+device_init ()
 {
-  char *event_name;
-  XEvent *event = (XEvent *) arg;
+  M_iso8859_1 = msymbol ("iso8859-1");
+  M_iso10646_1 = msymbol ("iso10646-1");
 
-  switch (event->xany.type)
-    {
-    case 2: event_name = "KeyPress"; break;
-    case 3: event_name = "KeyRelease"; break;
-    case 4: event_name = "ButtonPress"; break;
-    case 5: event_name = "ButtonRelease"; break;
-    case 6: event_name = "MotionNotify"; break;
-    case 7: event_name = "EnterNotify"; break;
-    case 8: event_name = "LeaveNotify"; break;
-    case 9: event_name = "FocusIn"; break;
-    case 10: event_name = "FocusOut"; break;
-    case 11: event_name = "KeymapNotify"; break;
-    case 12: event_name = "Expose"; break;
-    case 13: event_name = "GraphicsExpose"; break;
-    case 14: event_name = "NoExpose"; break;
-    case 15: event_name = "VisibilityNotify"; break;
-    case 16: event_name = "CreateNotify"; break;
-    case 17: event_name = "DestroyNotify"; break;
-    case 18: event_name = "UnmapNotify"; break;
-    case 19: event_name = "MapNotify"; break;
-    case 20: event_name = "MapRequest"; break;
-    case 21: event_name = "ReparentNotify"; break;
-    case 22: event_name = "ConfigureNotify"; break;
-    case 23: event_name = "ConfigureRequest"; break;
-    case 24: event_name = "GravityNotify"; break;
-    case 25: event_name = "ResizeRequest"; break;
-    case 26: event_name = "CirculateNotify"; break;
-    case 27: event_name = "CirculateRequest"; break;
-    case 28: event_name = "PropertyNotify"; break;
-    case 29: event_name = "SelectionClear"; break;
-    case 30: event_name = "SelectionRequest"; break;
-    case 31: event_name = "SelectionNotify"; break;
-    case 32: event_name = "ColormapNotify"; break;
-    case 33: event_name = "ClientMessage"; break;
-    case 34: event_name = "MappingNotify"; break;
-    default: event_name = "unknown";
-    }
+  display_info_list = mplist ();
+  device_list = mplist ();
 
-  fprintf (stderr, "%s: %s\n", win_name, event_name);
-}
+#ifdef HAVE_XFT2
+  xft_driver.select = mfont__ft_driver.select;
+  xft_driver.encode_char = mfont__ft_driver.encode_char;
 #endif
 
-void
-mwin__map_window (MFrame *frame, MDrawWindow win)
-{
-  XMapRaised (FRAME_DISPLAY (frame), (Window) win);
+  Mxim = msymbol ("xim");
+  msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
+
+  return 0;
 }
 
-void
-mwin__unmap_window (MFrame *frame, MDrawWindow win)
+int
+device_fini ()
 {
-  XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
+  M17N_OBJECT_UNREF (display_info_list);
+  M17N_OBJECT_UNREF (device_list);
+  return 0;
 }
 
-void
-mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
-                      MDrawMetric *geometry)
+/** 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.  */
+
+void *
+device_open (MFrame *frame, MPlist *param)
 {
-  Display *display = FRAME_DISPLAY (frame);
+  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;
-  Window parent = (Window) parent_win, root;
+  unsigned depth = 0;
+  MPlist *plist;
+  AppData app_data;
+  MFace *face;
 
-  XGetWindowAttributes (display, (Window) win, &attr);
-  geometry->x = attr.x + attr.border_width;
-  geometry->y = attr.y + attr.border_width;
-  geometry->width = attr.width;
-  geometry->height = attr.height; 
+  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 (! parent)
-    parent = RootWindow (display, FRAME_SCREEN (frame));
-  while (1)
+  if (widget)
     {
-      Window this_parent, *children;
-      unsigned n;
+      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;
 
-      XQueryTree (display, (Window) win, &root, &this_parent, &children, &n);
-      if (children)
-       XFree (children);
-      if (this_parent == parent || this_parent == root)
-       break;
-      win = (MDrawWindow) this_parent;
-      XGetWindowAttributes (display, (Window) win, &attr);
-      geometry->x += attr.x + attr.border_width;
-      geometry->y += attr.y + attr.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);
     }
-}
 
-void
-mwin__adjust_window (MFrame *frame, MDrawWindow win,
-                    MDrawMetric *current, MDrawMetric *new)
-{
-  Display *display = FRAME_DISPLAY (frame);
-  unsigned int mask = 0;
-  XWindowChanges values;
+  if (! cmap)
+    cmap = DefaultColormap (display, screen_num);
 
-  if (current->width != new->width)
+  for (plist = display_info_list; mplist_key (plist) != Mnil;
+       plist = mplist_next (plist))
     {
-      mask |= CWWidth;
-      if (new->width <= 0)
-       new->width = 1;
-      values.width = current->width = new->width;
+      disp_info = (MDisplayInfo *) mplist_value (plist);
+      if (disp_info->display == display)
+       break;
     }
-  if (current->height != new->height)
+
+  if (mplist_key (plist) != Mnil)
+    M17N_OBJECT_REF (disp_info);
+  else
     {
-      mask |= CWHeight;
-      if (new->height <= 0)
-       new->height = 1;
-      values.height = current->height = new->height;
-    }
-  if (current->x != new->x)
+      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))
     {
-      mask |= CWX;
-      values.x = current->x = new->x;
+      device = (MWDevice *) mplist_value (plist);
+      if (device->display_info == disp_info
+         && device->depth == depth
+         && device->cmap == cmap)
+       break;
     }
-  if (current->y != new->y)
+
+  if (mplist_key (plist) != Mnil)
+    M17N_OBJECT_REF (device);
+  else
     {
-      mask |= CWY;
-      current->y = new->y;
-      values.y = current->y = new->y;
+      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);
+#ifdef HAVE_XFT2
+      device->xft_draw = XftDrawCreate (display, device->drawable,
+                                       DefaultVisual (display, screen_num),
+                                       cmap);
+#endif
     }
-  if (mask)
-    XConfigureWindow (display, (Window) win, mask, &values);
-  XClearWindow (display, (Window) win);
-}
 
-MSymbol
-mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
-{
-  XEvent *event = (XEvent *) arg;
-  MDisplayInfo *disp_info = frame->device->display_info;
-  int len;
-  char buf[512];
-  KeySym keysym;
-  MSymbol key;
+  frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
+  frame->driver = &x_driver;
+  frame->font_driver_list = mplist ();
+  mplist_add (frame->font_driver_list, Mx, &xfont_driver);
+#ifdef HAVE_XFT2
+  mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
+#else
+  mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
+#endif
+  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;
 
-  *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)
+  if (widget)
     {
-      int c = keysym;
+      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 }
+      };
 
-      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);
+      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 if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
-    return Mnil;
   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;
+      app_data.font = DEFAULT_FONT;
+      frame->foreground = msymbol ("black");
+      frame->background = msymbol ("white");
+      frame->videomode = Mnormal;
     }
-  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;
-}
+  frame->font = mfont ();
+  {
+    int nfonts;
+    char **names = XListFonts (display, app_data.font, 1, &nfonts);
+
+    if (nfonts > 0)
+      {
+       if (! xfont_parse_name (names[0], frame->font))
+         {
+           /* 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;
 
-MText *
-mwin__get_selection_text (MFrame *frame)
-{
-  return NULL;
-}
+               if (XGetFontProperty (xfont, XA_FONT, &value)
+                   && (name = ((char *)
+                               XGetAtomName (display, (Atom) value))))
+                 {
+                   if (xfont_parse_name (name, frame->font))
+                     nfonts = 1;
+                 }
+               XFreeFont (display, xfont);
+             }
+         }
+       XFreeFontNames (names);
+      }
+    if (! nfonts)
+      xfont_parse_name (FALLBACK_FONT, frame->font);
+  }
 
+  face = mface_from_font (frame->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);
 
-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;
+#ifdef X_SET_ERROR_HANDLER
+  XSetErrorHandler (x_error_handler);
+  XSetIOErrorHandler (x_io_error_handler);
+#endif
 
-  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 device;
 }
 
 /*** @} */
@@ -2395,33 +2393,6 @@ mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
 /* External API */
 
 /*=*/
-/*** @addtogroup m17nFrame */
-/*** @{ */
-/*=*/
-
-/***en
-    @name Variables: Keys of frame parameter (X specific).
-
-    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 ¸ÇÍ­).
-
-    ´Ø¿ô mframe () ¤Î¥Ñ¥é¥á¡¼¥¿¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¥·¥ó¥Ü¥ë¡£( mframe
-    () ¤ÎÀâÌÀ»²¾È¡£) #Mwidget ¤ò½ü¤¤¤Æ¤Ï¥Õ¥ì¡¼¥à¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤Ç¤â¤¢
-    ¤ë¡£
-    */
-
-/*=*/
-/*** @{ */ 
-/* Keywords for mwin__open_device ().  */
-MSymbol Mdisplay, Mscreen, Mdrawable, Mdepth, Mwidget, Mcolormap;
-
-/*** @} */
-/*** @} */
-
-/*=*/
 /*** @addtogroup m17nInputMethodWin */
 /*=*/
 /*** @{ */
@@ -2488,21 +2459,6 @@ MInputDriver minput_xim_driver =
   { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic,
     xim_filter, xim_lookup, NULL };
 
-/*=*/
-
-/***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;
-
 /*** @} */ 
 
 /*