Adjusted for the change of struct MDeviceDriver.
authorhanda <handa>
Wed, 30 Jun 2004 02:51:55 +0000 (02:51 +0000)
committerhanda <handa>
Wed, 30 Jun 2004 02:51:55 +0000 (02:51 +0000)
(m17n_init_X): New function.

src/m17n-X.c

index eb41483..28a6c0e 100644 (file)
@@ -420,1277 +420,1541 @@ set_region (MFrame *frame, GC gc, MDrawRegion region)
 }
 
 \f
-/* Functions for the device driver.  */
-
-void
-mwin__close_device (MFrame *frame)
-{
-  M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
-}
+/** X font handler */
 
-void *
-mwin__device_get_prop (MFrame *frame, MSymbol key)
-{
-  MWDevice *device = FRAME_DEVICE (frame);
+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 *, unsigned);
+static void xfont_render (MDrawWindow, int, int, MGlyphString *,
+                         MGlyph *, MGlyph *, int, MDrawRegion);
 
-  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;
-}
+static MFontDriver xfont_driver =
+  { xfont_select, xfont_open,
+    xfont_find_metric, xfont_encode_char, xfont_render };
 
-void
-mwin__realize_face (MRealizedFace *rface)
+typedef struct
 {
-  MFrame *frame;
-  MSymbol foreground, background, videomode;
-  MFaceHLineProp *hline;
-  MFaceBoxProp *box;
-  GCInfo *info;
+  M17NObject control;
+  Display *display;
+  XFontStruct *xfont;
+} MXFontInfo;
 
-  if (rface != rface->ascii_rface)
-    {
-      rface->info = rface->ascii_rface->info;
-      return;
-    }
+static MFontList *
+build_font_list (MFrame *frame, MSymbol family, MSymbol registry,
+                MPlist *plist)
+{
+  char pattern[1024];
+  MFontList *font_list;
+  char **fontnames;
+  int nfonts;
+  int i, j;
 
-  frame = rface->frame;
-  MSTRUCT_CALLOC (info, MERROR_WIN);
+  MSTRUCT_CALLOC (font_list, 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)
+  if (family == Mnil)
     {
-      info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore);
-      info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back);
+      sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s",
+              msymbol_name (registry));
+      font_list->tag = registry;
     }
   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;
+      sprintf (pattern, "-*-%s-*-*-*-*-*-*-*-*-*-*-%s",
+              msymbol_name (family), msymbol_name (registry));
+      font_list->tag = family;
     }
-  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)
+  fontnames = XListFonts (FRAME_DISPLAY (frame), pattern, 0x8000, &nfonts);
+  if (nfonts > 0)
     {
-      if (hline->color)
-       info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
-      else
-       info->gc[GC_HLINE] = info->gc[GC_NORMAL];
+      MTABLE_MALLOC (font_list->fonts, nfonts, MERROR_WIN);
+      for (i = j = 0; i < nfonts; i++)
+       if ((mfont__parse_name_into_font (fontnames[i], Mx,
+                                         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;
     }
+  mplist_add (plist, font_list->tag, font_list);
+  return (nfonts > 0 ? font_list : NULL);
+}
 
-  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];
+/* The X font driver function SELECT.  */
 
-      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];
+static MRealizedFont *
+xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
+{
+  MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
+  MRealizedFont *rfont;
+  MFontList *font_list = NULL;
+  int i;
+  MFont *best_font;
+  int best_score, score;
 
-      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 (registry == Mnil
+      || ! strchr (MSYMBOL_NAME (registry), '-'))
+    return NULL;
 
-      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];
+  /* We handles iso8859-1 and iso10646-1 fonts specially because there
+     exists so many such fonts.  */
+  if (registry == M_iso8859_1 || registry == M_iso10646_1)
+    {
+      MPlist *family_list
+       = (registry == M_iso8859_1
+          ? FRAME_DEVICE (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;
 
-  rface->info = info;
-}
+      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;
 
+  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;
+       }
+    }
 
-void
-mwin__free_realized_face (MRealizedFace *rface)
-{
-  if (rface == rface->ascii_rface)
-    free (rface->info);
+  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;
 }
 
 
-void
-mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
-                 int reverse,
-                 int x, int y, int width, int height, MDrawRegion region)
-{
-  GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
+/* The X font driver function CLOSE.  */
 
-  if (region)
-    gc = set_region (frame, gc, region);
+static void
+close_xfont (void *object)
+{
+  MXFontInfo *xfont_info = object;
 
-  XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
-                 x, y, width, height);
+  XFreeFont (xfont_info->display, xfont_info->xfont);
+  free (object);
 }
 
 
-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];
+/* The X font driver function OPEN.  */
 
-  if (from == to)
-    return;
+static int
+xfont_open (MRealizedFont *rfont)
+{
+  char *name;
+  MXFontInfo *xfont_info;
+  MFrame *frame = rfont->frame;
+  int mdebug_mask = MDEBUG_FONT;
 
-  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;
+  /* This never fail to generate a valid fontname because open_spec
+     should correspond to a font available on the system.  */
+  name = mfont_unparse_name (&rfont->font, Mx);
+  M17N_OBJECT (xfont_info, close_xfont, MERROR_WIN);
+  xfont_info->display = FRAME_DISPLAY (frame);
+  xfont_info->xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
+  if (! xfont_info->xfont)
+    {
+      rfont->status = -1;
+      free (xfont_info);
+      MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
+      free (name);
+      return -1;
     }
+  rfont->info = xfont_info;
+  MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
+  free (name);
+  rfont->status = 1;
+  rfont->ascent = xfont_info->xfont->ascent;
+  rfont->descent = xfont_info->xfont->descent;
+  return 0;
 }
 
 
-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;
-
-  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);
-
-  for (i = 0; i < rface->hline->width; i++)
-    XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
-              x, y + i, x + width - 1, y + i);
-}
-
+/* The X font driver function FIND_METRIC.  */
 
-void
-mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
-               MGlyph *g, int x, int y, int width, MDrawRegion region)
+static void
+xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
+                  int from, int to)
 {
-  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;
-
-  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);
-
-  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];
+  MXFontInfo *xfont_info = rfont->info;
+  XFontStruct *xfont = xfont_info->xfont;
+  MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
 
-  if (g->type == GLYPH_BOX)
+  for (; g != gend; g++)
     {
-      int x0, x1;
-
-      if (g->left_padding)
-       x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
+      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
-       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);
+       {
+         int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
+         XCharStruct *pcm = NULL;
 
-      /* 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 (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 (g->left_padding > 0)
-       {
-         /* Draw the left side.  */
-         if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
-           gc_left = gc_top;
-         else
+         if (pcm)
            {
-             gc_left = info->gc[GC_BOX_LEFT];
-             if (region)
-               gc_left = set_region (frame, gc_left, region);
+             g->lbearing = pcm->lbearing;
+             g->rbearing = pcm->rbearing;
+             g->width = pcm->width;
+             g->ascent = pcm->ascent;
+             g->descent = pcm->descent;
            }
-         for (i = 0; i < rface->box->width; i++)
-           XDrawLine (display, (Window) win, gc_left,
-                      x0 + i, y0 + i, x0 + i, y1 - i);
-       }
-      else
-       {
-         /* 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);
+             /* 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;
            }
-         for (i = 0; i < rface->box->width; i++)
-           XDrawLine (display, (Window) win, gc_right,
-                      x1 - i, y0 + i, x1 - i, y1 - i);
        }
     }
+}
+
+
+/* The X font driver function GET_GLYPH_ID.  */
+
+static unsigned
+xfont_encode_char (MRealizedFont *rfont, unsigned code)
+{
+  MXFontInfo *xfont_info;
+  XFontStruct *xfont;
+  unsigned min_byte1, max_byte1, min_byte2, max_byte2;
+  int all_chars_exist;
+
+  if (rfont->status < 0 || code >= 0x10000)
+    return MCHAR_INVALID_CODE;
+  if (rfont->status == 0)
+    {
+      if (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 (min_byte1 == 0 && max_byte1 == 0)
+    {
+      XCharStruct *pcm;
+
+      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
     {
-      /* 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);
+      unsigned byte1 = code >> 8, byte2 = code & 0xFF;
+      XCharStruct *pcm;
 
-      /* 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 (byte1 < min_byte1 || byte1 > max_byte1
+         || byte2 < min_byte2 || byte2 > max_byte2)
+       return MCHAR_INVALID_CODE;
+
+      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);
     }
 }
 
+/* The X font driver function RENDER.  */
 
-#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)
+static void
+xfont_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;
+  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;
 
-  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);
-}
-#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;
+  /* It is assured that the all glyphs in the current range use the
+     same realized face.  */
+  display = FRAME_DISPLAY (rface->frame);
 
-  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);
-
-  XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
-              (XPoint *) points, num, CoordModeOrigin);
-}
+    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++)
+    {
+      code[i].byte1 = g->code >> 8;
+      code[i].byte2 = g->code & 0xFF;
+    }
 
+  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;
 
-MDrawRegion
-mwin__region_from_rect (MDrawMetric *rect)
-{
-  MDrawRegion region1 = XCreateRegion ();
-  MDrawRegion region2 = XCreateRegion ();
-  XRectangle xrect;
+             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;
 
-  xrect.x = rect->x;
-  xrect.y = rect->y;
-  xrect.width = rect->width;
-  xrect.height = rect->height;
-  XUnionRectWithRegion (&xrect, region1, region2);
-  XDestroyRegion (region1);
-  return region2;
+         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__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
-{
-  MDrawRegion region1 = XCreateRegion ();
-  XRectangle xrect;
-
-  xrect.x = rect->x;
-  xrect.y = rect->y;
-  xrect.width = rect->width;
-  xrect.height = rect->height;
+\f
+/* Xft Handler */
 
-  XUnionRegion (region, region, region1);
-  XUnionRectWithRegion (&xrect, region1, region);
-  XDestroyRegion (region1);
-}
+#ifdef HAVE_XFT2
 
-void
-mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
+typedef struct
 {
-  MDrawRegion region = XCreateRegion ();
+  M17NObject control;
+  Display *display;
+  XftFont *font_aa;
+  XftFont *font_no_aa;
+} MXftFontInfo;
 
-  XUnionRegion (region1, region1, region);
-  XIntersectRegion (region, region2, region1);
-  XDestroyRegion (region);
-}
+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);
 
-void
-mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
-{
-  MDrawRegion region1 = XCreateRegion ();
-  XRectangle xrect;
+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 };
 
-  xrect.x = rect->x;
-  xrect.y = rect->y;
-  xrect.width = rect->width;
-  xrect.height = rect->height;
-  XUnionRectWithRegion (&xrect, region1, region);
-  XDestroyRegion (region1);
-}
 
-void
-mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
+static void
+close_xft (void *object)
 {
-  XRectangle xrect;
+  MXftFontInfo *font_info = object;
 
-  XClipBox (region, &xrect);
-  rect->x = xrect.x;
-  rect->y = xrect.y;
-  rect->width = xrect.width;
-  rect->height = xrect.height;
+  XftFontClose (font_info->display, font_info->font_aa);
+  XftFontClose (font_info->display, font_info->font_no_aa);
+  free (font_info);
 }
 
-void
-mwin__free_region (MDrawRegion region)
-{
-  XDestroyRegion (region);
-}
 
-void
-mwin__dump_region (MDrawRegion region)
+static XftFont *
+xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
 {
-  XRectangle rect;
-  XClipBox (region, &rect);
-  fprintf (stderr, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height);
+  XftPattern *pattern;
+  XftFontInfo *xft_font_info;
+  XftFont *font;
+
+  pattern = XftPatternCreate ();
+  XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
+  XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
+  XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
+  xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
+  if (! xft_font_info)
+    return NULL;
+  font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
+  XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
+  return font;
 }
 
 
-MDrawWindow
-mwin__create_window (MFrame *frame, MDrawWindow parent)
+static int
+xft_open (MRealizedFont *rfont)
 {
-  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;
+  MFrame *frame;
+  MFTInfo *ft_info;
+  MXftFontInfo *font_info;
+  int size;
 
-  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;
-}
+  if ((mfont__ft_driver.open) (rfont) < 0)
+    return -1;
 
-void
-mwin__destroy_window (MFrame *frame, MDrawWindow win)
-{
-  XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
-}
+  size = rfont->font.property[MFONT_SIZE] / 10;
+  frame = rfont->frame;
 
-#if 0
-MDrawWindow
-mwin__event_window (void *event)
-{
-  return ((MDrawWindow) ((XEvent *) event)->xany.window);
+  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)
+    {
+      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;
 }
 
-void
-mwin__print_event (void *arg, char *win_name)
+
+static void
+xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
+               int from, int to)
 {
-  char *event_name;
-  XEvent *event = (XEvent *) arg;
+  MFTInfo *ft_info = rfont->info;
+  MXftFontInfo *font_info = ft_info->extra_info;
+  MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
 
-  switch (event->xany.type)
+  for (; g != gend; g++)
     {
-    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";
+      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;
+
+         XftGlyphExtents (FRAME_DISPLAY (rfont->frame),
+                          font_info->font_aa, &g->code, 1, &extents);
+         g->lbearing = - extents.x;
+         g->rbearing = extents.width - extents.x;
+         g->width = extents.xOff;
+         g->ascent = extents.y;
+         g->descent = extents.height - extents.y;
+       }
     }
+}
 
-  fprintf (stderr, "%s: %s\n", win_name, event_name);
+
+static void 
+xft_render (MDrawWindow win, int x, int y,
+           MGlyphString *gstring, MGlyph *from, MGlyph *to,
+           int reverse, MDrawRegion region)
+{
+  MRealizedFace *rface = from->rface;
+  MFrame *frame = rface->frame;
+  MFTInfo *ft_info = rface->rfont->info;
+  MXftFontInfo *font_info = ft_info->extra_info;
+  XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
+  XftColor *xft_color = (! reverse
+                        ? &((GCInfo *) rface->info)->xft_color_fore
+                        : &((GCInfo *) rface->info)->xft_color_back);
+  XftFont *xft_font = (gstring->control.anti_alias
+                      && FRAME_DEVICE (frame)->depth > 1
+                      ? font_info->font_aa : font_info->font_no_aa);
+  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)
+    {
+      if (g->xoff == 0 && g->yoff == 0)
+       glyphs[nglyphs++] = g->code;
+      else
+       {
+         if (nglyphs > 0)
+           XftDrawGlyphs (xft_draw, xft_color, xft_font,
+                          last_x, y, glyphs, nglyphs);
+         nglyphs = 0;
+         XftDrawGlyphs (xft_draw, xft_color, xft_font,
+                        x + g->xoff, y + g->yoff, (FT_UInt *) &g->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__map_window (MFrame *frame, MDrawWindow win)
+\f
+/* Functions for the device driver.  */
+
+static int
+mwin__device_init ()
 {
-  XMapRaised (FRAME_DISPLAY (frame), (Window) win);
+  M_iso8859_1 = msymbol ("iso8859-1");
+  M_iso10646_1 = msymbol ("iso10646-1");
+
+  display_info_list = mplist ();
+  device_list = mplist ();
+
+  Mxim = msymbol ("xim");
+  msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
+
+  return 0;
 }
 
-void
-mwin__unmap_window (MFrame *frame, MDrawWindow win)
+static int
+mwin__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.  */
+
+static int
+mwin__open_device (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;
-
-  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; 
+  unsigned depth = 0;
+  MPlist *plist;
+  AppData app_data;
+  MFace *face;
 
-  if (! parent)
-    parent = RootWindow (display, FRAME_SCREEN (frame));
-  while (1)
+  for (plist = param; (key = mplist_key (plist)) != Mnil;
+       plist = mplist_next (plist))
     {
-      Window this_parent, *children;
-      unsigned n;
-
-      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 (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);
     }
-}
-
-void
-mwin__adjust_window (MFrame *frame, MDrawWindow win,
-                    MDrawMetric *current, MDrawMetric *new)
-{
-  Display *display = FRAME_DISPLAY (frame);
-  unsigned int mask = 0;
-  XWindowChanges values;
 
-  if (current->width != new->width)
+  if (widget)
     {
-      mask |= CWWidth;
-      if (new->width <= 0)
-       new->width = 1;
-      values.width = current->width = new->width;
+      display = XtDisplay (widget);
+      screen_num = XScreenNumberOfScreen (XtScreen (widget));
+      depth = DefaultDepth (display, screen_num);
     }
-  if (current->height != new->height)
+  else if (drawable)
     {
-      mask |= CWHeight;
-      if (new->height <= 0)
-       new->height = 1;
-      values.height = current->height = new->height;
+      Window root_window;
+      int x, y;
+      unsigned width, height, border_width;
+
+      if (! display)
+       MERROR (MERROR_WIN, -1);
+      XGetGeometry (display, drawable, &root_window,
+                   &x, &y, &width, &height, &border_width, &depth);
+      XGetWindowAttributes (display, root_window, &attr);
+      screen_num = XScreenNumberOfScreen (attr.screen);
     }
-  if (current->x != new->x)
+  else
     {
-      mask |= CWX;
-      values.x = current->x = new->x;
+      if (screen)
+       display = DisplayOfScreen (screen);
+      else
+       {
+         if (! display)
+           {
+             display = XOpenDisplay (NULL);
+             if (! display)
+               MERROR (MERROR_WIN, -1);
+             auto_display = 1;
+           }
+         screen = DefaultScreenOfDisplay (display);
+       }
+      screen_num = XScreenNumberOfScreen (screen);
+      if (! depth)
+       depth = DefaultDepth (display, screen_num);
     }
-  if (current->y != new->y)
+
+  if (! cmap)
+    cmap = DefaultColormap (display, screen_num);
+
+  for (plist = display_info_list; mplist_key (plist) != Mnil;
+       plist = mplist_next (plist))
     {
-      mask |= CWY;
-      current->y = new->y;
-      values.y = current->y = new->y;
+      disp_info = (MDisplayInfo *) mplist_value (plist);
+      if (disp_info->display == display)
+       break;
     }
-  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 (frame)->display_info;
-  int len;
-  char buf[512];
-  KeySym keysym;
-  MSymbol key;
-
-  *modifiers = 0;
-  if (event->xany.type != KeyPress
-      /* && event->xany.type != KeyRelease */
-      )
-    return Mnil;
-  len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
-  if (len > 1)
-    return Mnil;
-  if (len == 1)
+  if (mplist_key (plist) != Mnil)
+    M17N_OBJECT_REF (disp_info);
+  else
     {
-      int c = keysym;
+      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 (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);
+  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;
     }
-  else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
-    return Mnil;
+
+  if (mplist_key (plist) != Mnil)
+    M17N_OBJECT_REF (device);
   else
     {
-      char *str = XKeysymToString (keysym);
+      unsigned long valuemask = GCForeground;
+      XGCValues values;
 
-      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;
+      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 (((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->device = device;
+  frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT;
+  frame->font_driver_list = mplist ();
+  mplist_add (frame->font_driver_list, Mx, &xfont_driver);
+#ifdef HAVE_XFT2
+  mplist_add (frame->font_driver_list, Mfreetype, &xft_driver);
+#elif HAVE_FREETYPE
+  mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
+#endif
+  frame->realized_font_list = disp_info->realized_font_list;
+  frame->realized_face_list = device->realized_face_list;
+  frame->realized_fontset_list = device->realized_fontset_list;
+
+  if (widget)
+    {
+      XtResource resources[] = {
+       { XtNfont, XtCFont, XtRString, sizeof (String),
+         XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
+       { XtNforeground, XtCForeground, XtRString, sizeof (String),
+         XtOffset (AppDataPtr, foreground), XtRString, "black" },
+       { XtNbackground, XtCBackground, XtRString, sizeof (String),
+         XtOffset (AppDataPtr, background), XtRString, "white" },
+       { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
+         XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
+      };
+
+      XtGetApplicationResources (widget, &app_data,
+                                resources, XtNumber (resources), NULL, 0);
+      frame->foreground = msymbol (app_data.foreground);
+      frame->background = msymbol (app_data.background);
+      frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
+    }
+  else
+    {
+      app_data.font = DEFAULT_FONT;
+      frame->foreground = msymbol ("black");
+      frame->background = msymbol ("white");
+      frame->videomode = Mnormal;
+    }
+
+  {
+    int nfonts;
+    char **names = XListFonts (display, app_data.font, 1, &nfonts);
+
+    if (nfonts > 0)
+      {
+       if (! (frame->font = mfont_parse_name (names[0], Mx)))
+         {
+           /* The font name does not conform to XLFD.  Try to open the
+              font and get XA_FONT property.  */
+           XFontStruct *xfont = XLoadQueryFont (display, names[0]);
+
+           nfonts = 0;
+           if (xfont)
+             {
+               unsigned long value;
+               char *name;
+
+               if (XGetFontProperty (xfont, XA_FONT, &value)
+                   && (name = ((char *)
+                               XGetAtomName (display, (Atom) value))))
+                 {
+                   if ((frame->font = mfont_parse_name (name, Mx)))
+                     nfonts = 1;
+                 }
+               XFreeFont (display, xfont);
+             }
+         }
+       XFreeFontNames (names);
+      }
+    if (! nfonts)
+      frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
+  }
+
+  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 0;
 }
 
 
-MText *
-mwin__get_selection_text (MFrame *frame)
+static void
+mwin__close_device (MFrame *frame)
 {
-  return NULL;
+  M17N_OBJECT_UNREF (FRAME_DEVICE (frame));
 }
 
+static void *
+mwin__device_get_prop (MFrame *frame, MSymbol key)
+{
+  MWDevice *device = FRAME_DEVICE (frame);
 
-void
-mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
+  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;
+}
+
+static void
+mwin__realize_face (MRealizedFace *rface)
 {
-  unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
-  XGCValues values;
-  Display *display = FRAME_DISPLAY (frame);
-  GCInfo *info = rface->info;
-  int i;
+  MFrame *frame;
+  MSymbol foreground, background, videomode;
+  MFaceHLineProp *hline;
+  MFaceBoxProp *box;
+  GCInfo *info;
 
-  for (i = 0; i <= GC_INVERSE; i++)
+  if (rface != rface->ascii_rface)
     {
-      XGetGCValues (display, info->gc[i], valuemask, &values);
-      fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
-              values.foreground, values.background);
-      fprintf (stderr, "\n");
+      rface->info = rface->ascii_rface->info;
+      return;
     }
-}
 
-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
-  };
+  frame = rface->frame;
+  MSTRUCT_CALLOC (info, MERROR_WIN);
 
-\f
-/** X font handler */
+  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
 
-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 *, unsigned);
-static void xfont_render (MDrawWindow, int, int, MGlyphString *,
-                         MGlyph *, MGlyph *, int, MDrawRegion);
+  hline = rface->hline;
+  if (hline)
+    {
+      if (hline->color)
+       info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
+      else
+       info->gc[GC_HLINE] = info->gc[GC_NORMAL];
+    }
 
-static MFontDriver xfont_driver =
-  { xfont_select, xfont_open,
-    xfont_find_metric, xfont_encode_char, xfont_render };
+  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];
 
-typedef struct
+      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];
+    }
+
+  rface->info = info;
+}
+
+
+static void
+mwin__free_realized_face (MRealizedFace *rface)
 {
-  M17NObject control;
-  Display *display;
-  XFontStruct *xfont;
-} MXFontInfo;
+  if (rface == rface->ascii_rface)
+    free (rface->info);
+}
 
-static MFontList *
-build_font_list (MFrame *frame, MSymbol family, MSymbol registry,
-                MPlist *plist)
+
+static 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)
+
+static void
+mwin__draw_empty_boxes (MDrawWindow win, int x, int y,
+                       MGlyphString *gstring, MGlyph *from, MGlyph *to,
+                       int reverse, MDrawRegion region)
+{
+  MRealizedFace *rface = from->rface;
+  Display *display = FRAME_DISPLAY (rface->frame);
+  GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
+
+  if (from == to)
+    return;
+
+  if (region)
+    gc = set_region (rface->frame, gc, region);
+  for (; from < to; from++)
     {
-      MTABLE_MALLOC (font_list->fonts, nfonts, MERROR_WIN);
-      for (i = j = 0; i < nfonts; i++)
-       if ((mfont__parse_name_into_font (fontnames[i], Mx,
-                                         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);
 }
 
-/* The X font driver function SELECT.  */
 
-static MRealizedFont *
-xfont_select (MFrame *frame, MFont *spec, MFont *request, int limited_size)
+static void
+mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
+                MRealizedFace *rface, int reverse,
+                int x, int y, int width, MDrawRegion region)
 {
-  MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY);
-  MRealizedFont *rfont;
-  MFontList *font_list = NULL;
+  enum MFaceHLineType type = rface->hline->type;
+  GCInfo *info = rface->info;
+  GC gc = gc = info->gc[GC_HLINE];
   int i;
-  MFont *best_font;
-  int best_score, score;
 
-  if (registry == Mnil
-      || ! strchr (MSYMBOL_NAME (registry), '-'))
-    return NULL;
+  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);
+
+  for (i = 0; i < rface->hline->width; i++)
+    XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
+              x, y + i, x + width - 1, y + i);
+}
+
+
+static void
+mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
+               MGlyph *g, int x, int y, int width, MDrawRegion region)
+{
+  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;
+
+  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);
+
+  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)
+    {
+      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;
+
+      /* Draw the top side.  */
+      for (i = 0; i < box->width; i++)
+       XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
 
-  /* We handles iso8859-1 and iso10646-1 fonts specially because there
-     exists so many such fonts.  */
-  if (registry == M_iso8859_1 || registry == M_iso10646_1)
-    {
-      MPlist *family_list
-       = (registry == M_iso8859_1
-          ? FRAME_DEVICE (frame)->display_info->iso8859_1_family_list
-          : FRAME_DEVICE (frame)->display_info->iso10646_1_family_list);
-      MSymbol family = FONT_PROPERTY (spec, MFONT_FAMILY);
+      /* 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 (family != Mnil)
+      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 (frame)->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;
-  return rfont;
-}
+#if 0
+static void
+mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
+                  int reverse, int x, int y,
+                  int width, int height, int row_bytes, unsigned char *bmp,
+                  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);
 
-/* The X font driver function CLOSE.  */
+  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
 
 static void
-close_xfont (void *object)
+mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
+                  int intensity, MDrawPoint *points, int num,
+                  MDrawRegion region)
 {
-  MXFontInfo *xfont_info = object;
+  GCInfo *info = rface->info;
+  GC gc;
 
-  XFreeFont (xfont_info->display, xfont_info->xfont);
-  free (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);
 
+  XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
+              (XPoint *) points, num, CoordModeOrigin);
+}
 
-/* The X font driver function OPEN.  */
 
-static int
-xfont_open (MRealizedFont *rfont)
+static MDrawRegion
+mwin__region_from_rect (MDrawMetric *rect)
 {
-  char *name;
-  MXFontInfo *xfont_info;
-  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.  */
-  name = mfont_unparse_name (&rfont->font, Mx);
-  M17N_OBJECT (xfont_info, close_xfont, MERROR_WIN);
-  xfont_info->display = FRAME_DISPLAY (frame);
-  xfont_info->xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name);
-  if (! xfont_info->xfont)
-    {
-      rfont->status = -1;
-      free (xfont_info);
-      MDEBUG_PRINT1 (" [XFONT] x %s\n", name);
-      free (name);
-      return -1;
-    }
-  rfont->info = xfont_info;
-  MDEBUG_PRINT1 (" [XFONT] o %s\n", name);
-  free (name);
-  rfont->status = 1;
-  rfont->ascent = xfont_info->xfont->ascent;
-  rfont->descent = xfont_info->xfont->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;
 }
 
-
-/* The X font driver function FIND_METRIC.  */
-
 static void
-xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
-                  int from, int to)
+mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect)
 {
-  MXFontInfo *xfont_info = rfont->info;
-  XFontStruct *xfont = xfont_info->xfont;
-  MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
-
-  for (; g != gend; g++)
-    {
-      if (g->code == MCHAR_INVALID_CODE)
-       {
-         g->lbearing = xfont->max_bounds.lbearing;
-         g->rbearing = xfont->max_bounds.rbearing;
-         g->width = xfont->max_bounds.width;
-         g->ascent = xfont->ascent;
-         g->descent = xfont->descent;
-       }
-      else
-       {
-         int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
-         XCharStruct *pcm = NULL;
+  MDrawRegion region1 = XCreateRegion ();
+  XRectangle xrect;
 
-         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));
-                   }
-               }
-           }
+  xrect.x = rect->x;
+  xrect.y = rect->y;
+  xrect.width = rect->width;
+  xrect.height = rect->height;
 
-         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;
-           }
-       }
-    }
+  XUnionRegion (region, region, region1);
+  XUnionRectWithRegion (&xrect, region1, region);
+  XDestroyRegion (region1);
 }
 
-
-/* The X font driver function GET_GLYPH_ID.  */
-
-static unsigned
-xfont_encode_char (MRealizedFont *rfont, unsigned code)
+static void
+mwin__intersect_region (MDrawRegion region1, MDrawRegion region2)
 {
-  MXFontInfo *xfont_info;
-  XFontStruct *xfont;
-  unsigned min_byte1, max_byte1, min_byte2, max_byte2;
-  int all_chars_exist;
-
-  if (rfont->status < 0 || code >= 0x10000)
-    return MCHAR_INVALID_CODE;
-  if (rfont->status == 0)
-    {
-      if (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 (min_byte1 == 0 && max_byte1 == 0)
-    {
-      XCharStruct *pcm;
+  MDrawRegion region = XCreateRegion ();
 
-      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
-    {
-      unsigned byte1 = code >> 8, byte2 = code & 0xFF;
-      XCharStruct *pcm;
+  XUnionRegion (region1, region1, region);
+  XIntersectRegion (region, region2, region1);
+  XDestroyRegion (region);
+}
 
-      if (byte1 < min_byte1 || byte1 > max_byte1
-         || byte2 < min_byte2 || byte2 > max_byte2)
-       return MCHAR_INVALID_CODE;
+static void
+mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect)
+{
+  MDrawRegion region1 = XCreateRegion ();
+  XRectangle xrect;
 
-      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);
-    }
+  xrect.x = rect->x;
+  xrect.y = rect->y;
+  xrect.width = rect->width;
+  xrect.height = rect->height;
+  XUnionRectWithRegion (&xrect, region1, region);
+  XDestroyRegion (region1);
 }
 
-/* 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)
+mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect)
 {
-  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;
+  XRectangle xrect;
 
-  if (from == to)
-    return;
+  XClipBox (region, &xrect);
+  rect->x = xrect.x;
+  rect->y = xrect.y;
+  rect->width = xrect.width;
+  rect->height = xrect.height;
+}
 
-  /* It is assured that the all glyphs in the current range use the
-     same realized face.  */
-  display = FRAME_DISPLAY (rface->frame);
+static void
+mwin__free_region (MDrawRegion region)
+{
+  XDestroyRegion (region);
+}
 
-  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++)
-    {
-      code[i].byte1 = g->code >> 8;
-      code[i].byte2 = g->code & 0xFF;
-    }
+static 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);
+}
 
-  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;
+static MDrawWindow
+mwin__create_window (MFrame *frame, MDrawWindow parent)
+{
+  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;
 
-         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);
-       }
-    }
+  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;
 }
 
-\f
-/* Xft Handler */
-
-#ifdef HAVE_XFT2
+static void
+mwin__destroy_window (MFrame *frame, MDrawWindow win)
+{
+  XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
+}
 
-typedef struct
+#if 0
+static MDrawWindow
+mwin__event_window (void *event)
 {
-  M17NObject control;
-  Display *display;
-  XftFont *font_aa;
-  XftFont *font_no_aa;
-} MXftFontInfo;
+  return ((MDrawWindow) ((XEvent *) event)->xany.window);
+}
 
-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);
+static void
+mwin__print_event (void *arg, char *win_name)
+{
+  char *event_name;
+  XEvent *event = (XEvent *) arg;
 
-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 };
+  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";
+    }
 
+  fprintf (stderr, "%s: %s\n", win_name, event_name);
+}
+#endif
 
 static void
-close_xft (void *object)
+mwin__map_window (MFrame *frame, MDrawWindow win)
 {
-  MXftFontInfo *font_info = object;
-
-  XftFontClose (font_info->display, font_info->font_aa);
-  XftFontClose (font_info->display, font_info->font_no_aa);
-  free (font_info);
+  XMapRaised (FRAME_DISPLAY (frame), (Window) win);
 }
 
-
-static XftFont *
-xft_open_font (MFrame *frame, MFTInfo *ft_info, int size, int anti_alias)
+static void
+mwin__unmap_window (MFrame *frame, MDrawWindow win)
 {
-  XftPattern *pattern;
-  XftFontInfo *xft_font_info;
-  XftFont *font;
-
-  pattern = XftPatternCreate ();
-  XftPatternAddString (pattern, XFT_FILE, ft_info->filename);
-  XftPatternAddDouble (pattern, XFT_PIXEL_SIZE, (double) size);
-  XftPatternAddBool (pattern, XFT_ANTIALIAS, anti_alias);
-  xft_font_info = XftFontInfoCreate (FRAME_DISPLAY (frame), pattern);
-  if (! xft_font_info)
-    return NULL;
-  font = XftFontOpenInfo (FRAME_DISPLAY (frame), pattern, xft_font_info);
-  XftFontInfoDestroy (FRAME_DISPLAY (frame), xft_font_info);
-  return font;
+  XUnmapWindow (FRAME_DISPLAY (frame), (Window) win);
 }
 
-
-static int
-xft_open (MRealizedFont *rfont)
+static void
+mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win,
+                      MDrawMetric *geometry)
 {
-  MFrame *frame;
-  MFTInfo *ft_info;
-  MXftFontInfo *font_info;
-  int size;
-
-  if ((mfont__ft_driver.open) (rfont) < 0)
-    return -1;
+  Display *display = FRAME_DISPLAY (frame);
+  XWindowAttributes attr;
+  Window parent = (Window) parent_win, root;
 
-  size = rfont->font.property[MFONT_SIZE] / 10;
-  frame = rfont->frame;
+  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; 
 
-  ft_info = rfont->info;
-  M17N_OBJECT (font_info, close_xft, MERROR_WIN);
-  ft_info->extra_info = font_info;
-  font_info->display = FRAME_DISPLAY (frame);
-  font_info->font_aa = xft_open_font (frame, ft_info, size, 1);
-  if (font_info->font_aa)
+  if (! parent)
+    parent = RootWindow (display, FRAME_SCREEN (frame));
+  while (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);
+      Window this_parent, *children;
+      unsigned n;
+
+      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;
     }
-  free (font_info);  
-  ft_info->extra_info = NULL;
-  rfont->status = -1;
-  return -1;
 }
 
-
 static void
-xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
-               int from, int to)
+mwin__adjust_window (MFrame *frame, MDrawWindow win,
+                    MDrawMetric *current, MDrawMetric *new)
 {
-  MFTInfo *ft_info = rfont->info;
-  MXftFontInfo *font_info = ft_info->extra_info;
-  MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
+  Display *display = FRAME_DISPLAY (frame);
+  unsigned int mask = 0;
+  XWindowChanges values;
 
-  for (; g != gend; g++)
+  if (current->width != new->width)
     {
-      if (g->code == MCHAR_INVALID_CODE)
-       {
-         MGlyph *start = g++;
+      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);
+}
 
-         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;
+static MSymbol
+mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
+{
+  XEvent *event = (XEvent *) arg;
+  MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
+  int len;
+  char buf[512];
+  KeySym keysym;
+  MSymbol key;
 
-         XftGlyphExtents (FRAME_DISPLAY (rfont->frame),
-                          font_info->font_aa, &g->code, 1, &extents);
-         g->lbearing = - extents.x;
-         g->rbearing = extents.width - extents.x;
-         g->width = extents.xOff;
-         g->ascent = extents.y;
-         g->descent = extents.height - extents.y;
+  *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);
+
+      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;
+
+  return key;
 }
 
 
-void 
-xft_render (MDrawWindow win, int x, int y,
-           MGlyphString *gstring, MGlyph *from, MGlyph *to,
-           int reverse, MDrawRegion region)
+void
+mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
 {
-  MRealizedFace *rface = from->rface;
-  MFrame *frame = rface->frame;
-  MFTInfo *ft_info = rface->rfont->info;
-  MXftFontInfo *font_info = ft_info->extra_info;
-  XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
-  XftColor *xft_color = (! reverse
-                        ? &((GCInfo *) rface->info)->xft_color_fore
-                        : &((GCInfo *) rface->info)->xft_color_back);
-  XftFont *xft_font = (gstring->control.anti_alias
-                      && FRAME_DEVICE (frame)->depth > 1
-                      ? font_info->font_aa : font_info->font_no_aa);
-  MGlyph *g;
-  FT_UInt *glyphs;
-  int last_x;
-  int nglyphs;
-
-  if (from == to)
-    return;
+  unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
+  XGCValues values;
+  Display *display = FRAME_DISPLAY (frame);
+  GCInfo *info = rface->info;
+  int 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)
+  for (i = 0; i <= GC_INVERSE; i++)
     {
-      if (g->xoff == 0 && g->yoff == 0)
-       glyphs[nglyphs++] = g->code;
-      else
-       {
-         if (nglyphs > 0)
-           XftDrawGlyphs (xft_draw, xft_color, xft_font,
-                          last_x, y, glyphs, nglyphs);
-         nglyphs = 0;
-         XftDrawGlyphs (xft_draw, xft_color, xft_font,
-                        x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
-         last_x = x + g->width;
-       }
+      XGetGCValues (display, info->gc[i], valuemask, &values);
+      fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
+              values.foreground, values.background);
+      fprintf (stderr, "\n");
     }
-  if (nglyphs > 0)
-    XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
 }
 
-#endif
+static MDeviceDriver x_driver =
+  {
+    0,
+    mwin__device_init,
+    mwin__device_fini,
+    mwin__open_device,
+    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
+  };
 
 \f
 
@@ -1770,415 +2034,155 @@ 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)
-{
-  MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
-  MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
-  MInputXIMContextInfo *ic_info;
-  XIC xic;
-
-  if (! arg->input_style)
-    {
-      /* By default, use Root style.  */
-      arg->input_style = XIMPreeditNothing | XIMStatusNothing;
-      arg->preedit_attrs = NULL;
-      arg->status_attrs = 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);
-  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;
-}
-
-static void
-xim_destroy_ic (MInputContext *ic)
-{
-  MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
-
-  XDestroyIC (ic_info->xic);
-  mconv_free_converter (ic_info->converter);
-  free (ic_info);
-  ic->info = NULL;
-}
-
-static int
-xim_filter (MInputContext *ic, MSymbol key, void *event)
-{
-  MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
-
-  return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
-}
-
-
-static int
-xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
-{
-  MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
-  MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
-  XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
-  KeySym keysym;
-  Status status;
-  char *buf;
-  int len;
-
-  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;
-}
-
-\f
-
-#ifdef X_SET_ERROR_HANDLER
-static int
-x_error_handler (Display *display, XErrorEvent *error)
-{
-  mdebug_hook ();
-  return 0;
-}
-
-static int
-x_io_error_handler (Display *display)
-{
-  mdebug_hook ();
-  return 0;
-}
-#endif
-
-\f
-
-/* Functions to be stored in MDeviceLibraryInterface by dlsym ().  */
-
-int
-device_init ()
-{
-  M_iso8859_1 = msymbol ("iso8859-1");
-  M_iso10646_1 = msymbol ("iso10646-1");
-
-  display_info_list = mplist ();
-  device_list = mplist ();
-
-#ifdef HAVE_XFT2
-  xft_driver.select = mfont__ft_driver.select;
-  xft_driver.encode_char = mfont__ft_driver.encode_char;
-#endif
-
-  Mxim = msymbol ("xim");
-  msymbol_put (Mxim, Minput_driver, &minput_xim_driver);
-
-  return 0;
-}
-
-int
-device_fini ()
-{
-  M17N_OBJECT_UNREF (display_info_list);
-  M17N_OBJECT_UNREF (device_list);
-  return 0;
-}
-
-/** 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 = 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;
-
-  for (plist = param; (key = mplist_key (plist)) != Mnil;
-       plist = mplist_next (plist))
-    {
-      if (key == Mdisplay)
-       display = (Display *) mplist_value (plist);
-      else if (key == Mscreen)
-       screen = mplist_value (plist);
-      else if (key == Mdrawable)
-       drawable = (Drawable) mplist_value (plist);
-      else if (key == Mdepth)
-       depth = (unsigned) mplist_value (plist);
-      else if (key == Mwidget)
-       widget = (Widget) mplist_value (plist);
-      else if (key == Mcolormap)
-       cmap = (Colormap) mplist_value (plist);
-    }
-
-  if (widget)
-    {
-      display = XtDisplay (widget);
-      screen_num = XScreenNumberOfScreen (XtScreen (widget));
-      depth = DefaultDepth (display, screen_num);
-    }
-  else if (drawable)
-    {
-      Window root_window;
-      int x, y;
-      unsigned width, height, border_width;
-
-      if (! display)
-       MERROR (MERROR_WIN, NULL);
-      XGetGeometry (display, drawable, &root_window,
-                   &x, &y, &width, &height, &border_width, &depth);
-      XGetWindowAttributes (display, root_window, &attr);
-      screen_num = XScreenNumberOfScreen (attr.screen);
-    }
-  else
-    {
-      if (screen)
-       display = DisplayOfScreen (screen);
-      else
-       {
-         if (! display)
-           {
-             display = XOpenDisplay (NULL);
-             if (! display)
-               MERROR (MERROR_WIN, NULL);
-             auto_display = 1;
-           }
-         screen = DefaultScreenOfDisplay (display);
-       }
-      screen_num = XScreenNumberOfScreen (screen);
-      if (! depth)
-       depth = DefaultDepth (display, screen_num);
-    }
+  XCloseIM (im_info->xim);
+  free (im_info);
+}
 
-  if (! cmap)
-    cmap = DefaultColormap (display, screen_num);
+static int
+xim_create_ic (MInputContext *ic)
+{
+  MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
+  MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
+  MInputXIMContextInfo *ic_info;
+  XIC xic;
 
-  for (plist = display_info_list; mplist_key (plist) != Mnil;
-       plist = mplist_next (plist))
+  if (! arg->input_style)
     {
-      disp_info = (MDisplayInfo *) mplist_value (plist);
-      if (disp_info->display == display)
-       break;
+      /* By default, use Root style.  */
+      arg->input_style = XIMPreeditNothing | XIMStatusNothing;
+      arg->preedit_attrs = NULL;
+      arg->status_attrs = NULL;
     }
 
-  if (mplist_key (plist) != Mnil)
-    M17N_OBJECT_REF (disp_info);
+  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
-    {
-      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);
-    }  
+    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);
 
-  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;
-    }
+  MSTRUCT_MALLOC (ic_info, MERROR_WIN);
+  ic_info->xic = xic;
+  ic_info->win = arg->focus_win;
+  ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0);
+  ic->info = ic_info;
+  return 0;
+}
 
-  if (mplist_key (plist) != Mnil)
-    M17N_OBJECT_REF (device);
-  else
-    {
-      unsigned long valuemask = GCForeground;
-      XGCValues values;
+static void
+xim_destroy_ic (MInputContext *ic)
+{
+  MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
 
-      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
-    }
+  XDestroyIC (ic_info->xic);
+  mconv_free_converter (ic_info->converter);
+  free (ic_info);
+  ic->info = NULL;
+}
 
-  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);
-#elif HAVE_FREETYPE
-  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;
+static int
+xim_filter (MInputContext *ic, MSymbol key, void *event)
+{
+  MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
 
-  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 }
-      };
+  return (XFilterEvent ((XEvent *) event, ic_info->win) == True);
+}
 
-      XtGetApplicationResources (widget, &app_data,
-                                resources, XtNumber (resources), NULL, 0);
-      frame->foreground = msymbol (app_data.foreground);
-      frame->background = msymbol (app_data.background);
-      frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
-    }
-  else
-    {
-      app_data.font = DEFAULT_FONT;
-      frame->foreground = msymbol ("black");
-      frame->background = msymbol ("white");
-      frame->videomode = Mnormal;
-    }
 
-  {
-    int nfonts;
-    char **names = XListFonts (display, app_data.font, 1, &nfonts);
+static int
+xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
+{
+  MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info;
+  MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
+  XKeyPressedEvent *ev = (XKeyPressedEvent *) arg;
+  KeySym keysym;
+  Status status;
+  char *buf;
+  int len;
 
-    if (nfonts > 0)
-      {
-       if (! (frame->font = mfont_parse_name (names[0], Mx)))
-         {
-           /* The font name does not conform to XLFD.  Try to open the
-              font and get XA_FONT property.  */
-           XFontStruct *xfont = XLoadQueryFont (display, names[0]);
+  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);
+    }
 
-           nfonts = 0;
-           if (xfont)
-             {
-               unsigned long value;
-               char *name;
+  mtext_reset (ic->produced);
+  if (len == 0)
+    return 1;
 
-               if (XGetFontProperty (xfont, XA_FONT, &value)
-                   && (name = ((char *)
-                               XGetAtomName (display, (Atom) value))))
-                 {
-                   if ((frame->font = mfont_parse_name (name, Mx)))
-                     nfonts = 1;
-                 }
-               XFreeFont (display, xfont);
-             }
-         }
-       XFreeFontNames (names);
-      }
-    if (! nfonts)
-      frame->font = mfont_parse_name (FALLBACK_FONT, Mx);
-  }
+  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;
+}
 
-  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);
+\f
 
 #ifdef X_SET_ERROR_HANDLER
-  XSetErrorHandler (x_error_handler);
-  XSetIOErrorHandler (x_io_error_handler);
-#endif
+static int
+x_error_handler (Display *display, XErrorEvent *error)
+{
+  mdebug_hook ();
+  return 0;
+}
 
-  return device;
+static int
+x_io_error_handler (Display *display)
+{
+  mdebug_hook ();
+  return 0;
 }
+#endif
 
 /*** @} */
 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
 \f
 /* External API */
 
+int
+m17n_init_X ()
+{
+  x_driver.initialized = 0;
+  mplist_put (m17n__device_library_list, Mx, &x_driver);
+
+#ifdef HAVE_XFT2
+  xft_driver.select = mfont__ft_driver.select;
+  xft_driver.encode_char = mfont__ft_driver.encode_char;
+#endif
+
+  return 0;
+}
+
 /*=*/
 /*** @addtogroup m17nInputMethodWin */
 /*=*/