(mwin__xft_render): Don't use anti-alias if the
[m17n/m17n-lib.git] / src / m17n-X.c
index c7b5694..7012e56 100644 (file)
@@ -24,6 +24,8 @@
 /*** @addtogroup m17nInternal
      @{ */
 
+#include "config.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <X11/StringDefs.h>
 #include <X11/Intrinsic.h>
 
+#ifdef HAVE_XFT2
+#include <X11/Xft/Xft.h>
+#endif /* HAVE_XFT2 */
+
 #include "m17n-gui.h"
 #include "m17n-X.h"
 #include "m17n-misc.h"
@@ -84,6 +90,38 @@ typedef struct
 /* Anchor of the chain of MDisplayInfo objects.  */
 static MPlist *display_info_list;
 
+
+/* Color value and the corresponding GC.  */
+typedef struct
+{
+  unsigned int rgb;           /* (red << 16) | (green << 8) | blue */
+  GC gc;
+} RGB_GC;
+
+enum gc_index
+  {
+    GC_INVERSE,
+    GC_NORMAL = GC_INVERSE + 7,
+    GC_HLINE,
+    GC_BOX_TOP,
+    GC_BOX_BOTTOM,
+    GC_BOX_LEFT,
+    GC_BOX_RIGHT,
+    GC_MAX
+  };
+
+typedef struct
+{
+  int rgb_fore;
+  int rgb_back;
+  /* The first 8 elements are indexed by an intensity for
+     anti-aliasing.  The 2nd to 7th are created on demand.  */
+  GC gc[GC_MAX];
+#ifdef HAVE_XFT2
+  XftColor xft_color_fore, xft_color_back;
+#endif
+} GCInfo;
+
 struct MWDevice
 {
   /* Common header for the m17n object.  */
@@ -99,7 +137,11 @@ struct MWDevice
 
   Colormap cmap;
 
-  unsigned long foreground, background;
+  GC scratch_gc;
+
+#ifdef HAVE_XFT2
+  XftDraw *xft_draw;
+#endif
 
   /** List of pointers to realized faces on the frame.  */
   MPlist *realized_face_list;
@@ -107,14 +149,30 @@ struct MWDevice
   /** List of pointers to realized fontsets on the frame.  */
   MPlist *realized_fontset_list;
 
+  /** List of XColors vs GCs on the frame.  */
+  MPlist *gc_list;
 };
 
 static MPlist *device_list;
 
 static MSymbol M_iso8859_1, M_iso10646_1;
 
-#define FRAME_DISPLAY(frame) (frame->device->display_info->display)
-#define FRAME_SCREEN(frame) (frame->device->screen_num)
+#define FRAME_DISPLAY(frame) ((frame)->device->display_info->display)
+#define FRAME_SCREEN(frame) ((frame)->device->screen_num)
+#define FRAME_CMAP(frame) ((frame)->device->cmap)
+#define FRAME_VISUAL(frame) DefaultVisual (FRAME_DISPLAY (frame), \
+                                          FRAME_SCREEN (frame))
+
+#define DEFAULT_FONT "-misc-fixed-medium-r-normal--*-120-*-*-*-*-iso8859-1"
+#define FALLBACK_FONT "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1"
+
+typedef struct
+{
+  String font;
+  String foreground;
+  String background;
+  Boolean reverse_video;
+} AppData, *AppDataPtr;
 
 static void
 free_display_info (void *object)
@@ -182,6 +240,19 @@ free_device (void *object)
     mface__free_realized ((MRealizedFace *) mplist_value (plist));
   M17N_OBJECT_UNREF (device->realized_face_list);
 
+  MPLIST_DO (plist, device->gc_list)
+    {
+      XFreeGC (device->display_info->display,
+              ((RGB_GC *) MPLIST_VAL (plist))->gc);
+      free (MPLIST_VAL (plist));
+    }
+  M17N_OBJECT_UNREF (device->gc_list);
+  XFreeGC (device->display_info->display, device->scratch_gc);
+
+#ifdef HAVE_XFT2
+  XftDrawDestroy (device->xft_draw);
+#endif
+
   XFreePixmap (device->display_info->display, device->drawable);
   M17N_OBJECT_UNREF (device->display_info);
   free (object);
@@ -238,22 +309,102 @@ find_modifier_bits (MDisplayInfo *disp_info)
   XFreeModifiermap (mods);
 }
 
-static unsigned long
-get_color (Display *display, Colormap cmap,
-          MSymbol color_name, MSymbol default_name,
-          unsigned long default_pixel)
+static RGB_GC *
+get_rgb_gc (MWDevice *device, XColor *xcolor)
+{
+  int rgb = (((xcolor->red >> 8) << 16) | ((xcolor->green >> 8) << 8)
+            | (xcolor->blue >> 8));
+  MPlist *plist;
+  RGB_GC *rgb_gc;
+  unsigned long valuemask = GCForeground;
+  XGCValues values;
+
+  MPLIST_DO (plist, device->gc_list)
+    {
+      rgb_gc = MPLIST_VAL (plist);
+
+      if (rgb_gc->rgb == rgb)
+       return rgb_gc;
+      if (rgb_gc->rgb > rgb)
+       break;
+    }
+
+  if (! XAllocColor (device->display_info->display, device->cmap, xcolor))
+    return NULL;
+
+  rgb_gc = malloc (sizeof (RGB_GC));
+  rgb_gc->rgb = rgb;
+  values.foreground = xcolor->pixel;
+  rgb_gc->gc = XCreateGC (device->display_info->display,
+                         device->drawable, valuemask, &values);
+  mplist_push (plist, Mt, rgb_gc);
+  return rgb_gc;
+}
+
+static GC
+get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret)
 {
-  XColor exact_def;
+  MWDevice *device = frame->device;
+  XColor xcolor;
+  RGB_GC *rgb_gc;
 
-  if (XParseColor (display, cmap, msymbol_name (color_name), &exact_def)
-      && XAllocColor (display, cmap, &exact_def))
-    return exact_def.pixel;
+  if (color == Mnil)
+    {
+      if (frame->rface)
+       goto no_color;
+      color = for_foreground ? frame->foreground : frame->background;
+    }
+  if (! XParseColor (FRAME_DISPLAY (frame), device->cmap,
+                    msymbol_name (color), &xcolor))
+    goto no_color;
+  rgb_gc = get_rgb_gc (device, &xcolor);
+  if (! rgb_gc)
+    goto no_color;
+  if (rgb_ret)
+    *rgb_ret = rgb_gc->rgb;
+  return rgb_gc->gc;
+
+ no_color:
+  {
+    GCInfo *info = frame->rface->info;
+    GC gc;
+    int rgb;
+
+    if (for_foreground)
+      rgb = info->rgb_fore, gc = info->gc[GC_NORMAL];
+    else
+      rgb = info->rgb_back, gc = info->gc[GC_INVERSE];
+    if (rgb_ret)
+      *rgb_ret = rgb;
+    return gc;
+  }
+}
 
-  if (XParseColor (display, cmap, msymbol_name (default_name), &exact_def)
-      && XAllocColor (display, cmap, &exact_def))
-    return exact_def.pixel;
+static GC
+get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity)
+{
+  int rgb_fore, rgb_back;
+  XColor xcolor;
+  RGB_GC *rgb_gc;
+  GC gc;
 
-  return default_pixel;
+  if (info->gc[intensity])
+    return info->gc[intensity];
+
+  rgb_fore = info->rgb_fore, rgb_back = info->rgb_back;
+  xcolor.red = ((((rgb_fore & 0xFF0000) >> 16) * intensity
+                + ((rgb_back & 0xFF0000) >> 16) * (7 - intensity)) / 7) << 8;
+  xcolor.green = ((((rgb_fore & 0xFF00) >> 8) * intensity
+                  + ((rgb_back & 0xFF00) >> 8) * (7 - intensity)) / 7) << 8;
+  xcolor.blue = (((rgb_fore & 0xFF) * intensity
+                 + (rgb_back & 0xFF) * (7 - intensity)) / 7) << 8;
+  rgb_gc = get_rgb_gc (device, &xcolor);
+  if (rgb_gc)
+    gc = rgb_gc->gc;
+  else
+    gc =get_gc_for_anti_alias (device, info,
+                              intensity < 4 ? intensity - 1 : intensity + 1);
+  return (info->gc[intensity] = gc);
 }
 
 \f
@@ -447,12 +598,12 @@ build_font_list (MFrame *frame, MSymbol family, MSymbol registry,
 static MRealizedFont *xfont_select (MFrame *, MFont *, MFont *, int);
 static int xfont_open (MRealizedFont *);
 static void xfont_close (MRealizedFont *);
-static void xfont_find_metric (MRealizedFont *, MGlyph *);
+static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int);
 static unsigned xfont_encode_char (MRealizedFont *, int, unsigned);
 static void xfont_render (MDrawWindow, int, int, MGlyphString *,
                          MGlyph *, MGlyph *, int, MDrawRegion);
 
-MFontDriver xfont_driver =
+static MFontDriver xfont_driver =
   { xfont_select, xfont_open, xfont_close,
     xfont_find_metric, xfont_encode_char, xfont_render };
 
@@ -598,69 +749,74 @@ xfont_close (MRealizedFont *rfont)
 /* The X font driver function FIND_METRIC.  */
 
 static void
-xfont_find_metric (MRealizedFont *rfont, MGlyph *g)
+xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
+                  int from, int to)
 {
-  XCharStruct *pcm = NULL;
   MXFontInfo *xfont = (MXFontInfo *) rfont->info;
   XFontStruct *f = xfont->f;
-  int byte1, byte2;
+  MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
 
-  if (g->code == MCHAR_INVALID_CODE)
+  for (; g != gend; g++)
     {
-      g->lbearing = f->max_bounds.lbearing;
-      g->rbearing = f->max_bounds.rbearing;
-      g->width = f->max_bounds.width;
-      g->ascent = f->ascent;
-      g->descent = f->descent;
-      return;
-    }
-
-  byte1 = g->code >> 8;
-  byte2 = g->code & 0xFF;
-
-  if (f->per_char != NULL)
-    {
-      if (f->min_byte1 == 0 && f->max_byte1 == 0)
+      if (g->code == MCHAR_INVALID_CODE)
        {
-         if (byte1 == 0
-             && byte2 >= f->min_char_or_byte2
-             && byte2 <= f->max_char_or_byte2)
-           pcm = f->per_char + byte2 - f->min_char_or_byte2;
+         g->lbearing = f->max_bounds.lbearing;
+         g->rbearing = f->max_bounds.rbearing;
+         g->width = f->max_bounds.width;
+         g->ascent = f->ascent;
+         g->descent = f->descent;
        }
       else
        {
-         if (byte1 >= f->min_byte1
-             && byte1 <= f->max_byte1
-             && byte2 >= f->min_char_or_byte2
-             && byte2 <= f->max_char_or_byte2)
+         int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
+         XCharStruct *pcm = NULL;
+
+         if (f->per_char != NULL)
+           {
+             if (f->min_byte1 == 0 && f->max_byte1 == 0)
+               {
+                 if (byte1 == 0
+                     && byte2 >= f->min_char_or_byte2
+                     && byte2 <= f->max_char_or_byte2)
+                   pcm = f->per_char + byte2 - f->min_char_or_byte2;
+               }
+             else
+               {
+                 if (byte1 >= f->min_byte1
+                     && byte1 <= f->max_byte1
+                     && byte2 >= f->min_char_or_byte2
+                     && byte2 <= f->max_char_or_byte2)
+                   {
+                     pcm = (f->per_char
+                            + ((f->max_char_or_byte2-f->min_char_or_byte2 + 1)
+                               * (byte1 - f->min_byte1))
+                            + (byte2 - f->min_char_or_byte2));
+                   }
+               }
+           }
+
+         if (pcm)
+           {
+             g->lbearing = pcm->lbearing;
+             g->rbearing = pcm->rbearing;
+             g->width = pcm->width;
+             g->ascent = pcm->ascent;
+             g->descent = pcm->descent;
+           }
+         else
            {
-             pcm = (f->per_char
-                    + ((f->max_char_or_byte2-f->min_char_or_byte2 + 1)
-                       * (byte1 - f->min_byte1))
-                    + (byte2 - f->min_char_or_byte2));
+             /* If the per_char pointer is null, all glyphs between
+                the first and last character indexes inclusive have
+                the same information, as given by both min_bounds and
+                max_bounds.  */
+             g->lbearing = 0;
+             g->rbearing = f->max_bounds.width;
+             g->width = f->max_bounds.width;
+             g->ascent = f->ascent;
+             g->descent = f->descent;
            }
        }
     }
-
-  if (pcm)
-    {
-      g->lbearing = pcm->lbearing;
-      g->rbearing = pcm->rbearing;
-      g->width = pcm->width;
-      g->ascent = pcm->ascent;
-      g->descent = pcm->descent;
-    }
-  else
-    {
-      /* If the per_char pointer is null, all glyphs between the first
-        and last character indexes inclusive have the same
-        information, as given by both min_bounds and max_bounds.  */
-      g->lbearing = 0;
-      g->rbearing = f->max_bounds.width;
-      g->width = f->max_bounds.width;
-      g->ascent = f->ascent;
-      g->descent = f->descent;
-    }
 }
 
 
@@ -674,12 +830,12 @@ xfont_encode_char (MRealizedFont *rfont, int c, unsigned code)
   unsigned min_byte1, max_byte1, min_byte2, max_byte2;
   int all_chars_exist;
 
-  if (rfont->status < 0)
-    return -1;
+  if (rfont->status < 0 || code >= 0x10000)
+    return MCHAR_INVALID_CODE;
   if (rfont->status == 0)
     {
       if (xfont_open (rfont) < 0)
-       return -1;
+       return MCHAR_INVALID_CODE;
     }
   xfont = (MXFontInfo *) rfont->info;
   f = xfont->f;
@@ -693,9 +849,10 @@ xfont_encode_char (MRealizedFont *rfont, int c, unsigned code)
     {
       XCharStruct *pcm;
 
+      if (code < min_byte2 || code > max_byte2)
+       return MCHAR_INVALID_CODE;
       if (all_chars_exist)
-       return ((code >= min_byte2 && code <= max_byte2)
-               ? code : MCHAR_INVALID_CODE);
+       return code;
       pcm = f->per_char + (code - min_byte2);
       return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
              ? code : MCHAR_INVALID_CODE);
@@ -705,10 +862,12 @@ xfont_encode_char (MRealizedFont *rfont, int c, unsigned code)
       unsigned byte1 = code >> 8, byte2 = code & 0xFF;
       XCharStruct *pcm;
 
+      if (byte1 < min_byte1 || byte1 > max_byte1
+         || byte2 < min_byte2 || byte2 > max_byte2)
+       return MCHAR_INVALID_CODE;
+
       if (all_chars_exist)
-       return ((byte1 >= min_byte1 && byte1 <= max_byte1
-                && byte2 >= min_byte2 && byte2 <= max_byte2)
-               ? code : MCHAR_INVALID_CODE);
+       return code;
       pcm = f->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1)
                           + (byte2 - min_byte2));
       return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing)
@@ -717,16 +876,14 @@ xfont_encode_char (MRealizedFont *rfont, int c, unsigned code)
 }
 
 static GC
-set_region (Display *display, MRealizedFace *rface, GC gc, MDrawRegion region)
+set_region (MFrame *frame, GC gc, MDrawRegion region)
 {
-  GC gc1;
-  XRectangle xrect;
+  unsigned long valuemask = GCForeground;
 
-  XClipBox (region, &xrect);  
-  gc1 = ((GC *) rface->info)[MFACE_GC_SCRATCH];
-  XCopyGC (display, gc, GCFont | GCForeground | GCBackground, gc1);
-  XSetRegion (display, gc1, region);
-  return gc1;
+  XCopyGC (FRAME_DISPLAY (frame), gc, valuemask,
+          frame->device->scratch_gc);
+  XSetRegion (FRAME_DISPLAY (frame), frame->device->scratch_gc, region);
+  return frame->device->scratch_gc;
 }
 
 /* The X font driver function RENDER.  */
@@ -738,8 +895,7 @@ xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
   MRealizedFace *rface = from->rface;
   Display *display;
   XChar2b *code;
-  GC *gcs = rface->info;
-  GC gc = gcs[reverse ? MFACE_GC_INVERSE : MFACE_GC_NORMAL];
+  GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
   MGlyph *g;
   int i;
 
@@ -751,9 +907,8 @@ xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
   display = FRAME_DISPLAY (rface->frame);
 
   if (region)
-    gc = set_region (display, rface, gc, region);
-
-  if (from->code == MCHAR_INVALID_CODE)
+    gc = set_region (rface->frame, gc, region);
+  if (! rface->rfont || from->code == MCHAR_INVALID_CODE)
     {
       int x0 = x;
 
@@ -767,6 +922,7 @@ xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
       return;
     }
 
+  XSetFont (display, gc, ((MXFontInfo *) (rface->rfont->info))->f->fid);
   code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
   for (i = 0, g = from; g < to; i++, g++)
     {
@@ -907,7 +1063,7 @@ xim_close_im (MInputMethod *im)
   free (im_info);
 }
 
-int
+static int
 xim_create_ic (MInputContext *ic)
 {
   MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg;
@@ -962,7 +1118,7 @@ xim_create_ic (MInputContext *ic)
   return 0;
 }
 
-void
+static void
 xim_destroy_ic (MInputContext *ic)
 {
   MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info;
@@ -1017,15 +1173,15 @@ xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt)
 
 \f
 
-#if 1
-int
+#ifdef X_SET_ERROR_HANDLER
+static int
 x_error_handler (Display *display, XErrorEvent *error)
 {
   mdebug_hook ();
   return 0;
 }
 
-int
+static int
 x_io_error_handler (Display *display)
 {
   mdebug_hook ();
@@ -1064,15 +1220,6 @@ mwin__fini ()
   M17N_OBJECT_UNREF (device_list);
 }
 
-typedef struct
-{
-  String font;
-  String foreground;
-  String background;
-  Boolean reverse_video;
-} AppData, *AppDataPtr;
-
-
 int
 mwin__parse_font_name (char *name, MFont *font)
 {
@@ -1155,6 +1302,7 @@ mwin__open_device (MFrame *frame, MPlist *param)
   XWindowAttributes attr;
   unsigned depth = 0;
   MPlist *plist;
+  AppData app_data;
 
   if (param)
     for (plist = param; (key = mplist_key (plist)) != Mnil;
@@ -1253,6 +1401,9 @@ mwin__open_device (MFrame *frame, MPlist *param)
     M17N_OBJECT_REF (device);
   else
     {
+      unsigned long valuemask = GCForeground;
+      XGCValues values;
+
       M17N_OBJECT (device, free_device, MERROR_WIN);
       device->display_info = disp_info;
       device->screen_num = screen_num;
@@ -1264,8 +1415,15 @@ mwin__open_device (MFrame *frame, MPlist *param)
       device->cmap = cmap;
       device->realized_face_list = mplist ();
       device->realized_fontset_list = mplist ();
-      device->foreground = BlackPixel (display, screen_num);
-      device->background = WhitePixel (display, screen_num);
+      device->gc_list = mplist ();
+      values.foreground = BlackPixel (display, screen_num);
+      device->scratch_gc = XCreateGC (display, device->drawable,
+                                     valuemask, &values);
+#ifdef HAVE_XFT2
+      device->xft_draw = XftDrawCreate (display, device->drawable,
+                                       DefaultVisual (display, screen_num),
+                                       cmap);
+#endif
     }
 
   frame->realized_font_list = disp_info->realized_font_list;
@@ -1274,11 +1432,9 @@ mwin__open_device (MFrame *frame, MPlist *param)
 
   if (widget)
     {
-      AppData app_data;
       XtResource resources[] = {
        { XtNfont, XtCFont, XtRString, sizeof (String),
-         XtOffset (AppDataPtr, font), XtRString,
-         "-misc-fixed-medium-r-normal--*-120-*-*-*-*-iso8859-1" },
+         XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT },
        { XtNforeground, XtCForeground, XtRString, sizeof (String),
          XtOffset (AppDataPtr, foreground), XtRString, "black" },
        { XtNbackground, XtCBackground, XtRString, sizeof (String),
@@ -1286,62 +1442,60 @@ mwin__open_device (MFrame *frame, MPlist *param)
        { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
          XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE }
       };
-      MFace *face = NULL;
-      MFont font;
-      char **names;
-      int nfonts;
 
       XtGetApplicationResources (widget, &app_data,
                                 resources, XtNumber (resources), NULL, 0);
-      names = XListFonts (display, app_data.font, 1, &nfonts);
-      if (nfonts == 1)
-       {
-         if (mwin__parse_font_name (names[0], &font) >= 0)
-           face = mface_from_font (&font);
-         else
-           {
-             /* The font name does not conform to XLFD.  Try to open the
-                font and get XA_FONT property.  */
-             XFontStruct *xfont = XLoadQueryFont (display, names[0]);
+      frame->foreground = msymbol (app_data.foreground);
+      frame->background = msymbol (app_data.background);
+      frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal;
+    }
+  else
+    {
+      app_data.font = DEFAULT_FONT;
+      frame->foreground = msymbol ("black");
+      frame->background = msymbol ("white");
+      frame->videomode = Mnormal;
+    }
 
-             if (xfont)
-               {
-                 unsigned long value;
-                 char *name;
+  frame->font = mfont ();
+  {
+    int nfonts;
+    char **names = XListFonts (display, app_data.font, 1, &nfonts);
 
-                 if (XGetFontProperty (xfont, XA_FONT, &value)
-                     && (name = ((char *)
-                                 XGetAtomName (display, (Atom) value))))
-                   {
-                     if (mwin__parse_font_name (name, &font) >= 0)
-                       face = mface_from_font (&font);
-                   }
-                 XFreeFont (display, xfont);
-               }
-           }
-         XFreeFontNames (names);
-       }
+    if (nfonts > 0)
+      {
+       if (mwin__parse_font_name (names[0], frame->font) < 0)
+         {
+           /* The font name does not conform to XLFD.  Try to open the
+              font and get XA_FONT property.  */
+           XFontStruct *xfont = XLoadQueryFont (display, names[0]);
+
+           nfonts = 0;
+           if (xfont)
+             {
+               unsigned long value;
+               char *name;
+
+               if (XGetFontProperty (xfont, XA_FONT, &value)
+                   && (name = ((char *)
+                               XGetAtomName (display, (Atom) value))))
+                 {
+                   if (mwin__parse_font_name (name, frame->font) >= 0)
+                     nfonts = 1;
+                 }
+               XFreeFont (display, xfont);
+             }
+         }
+       XFreeFontNames (names);
+      }
+    if (! nfonts)
+      mwin__parse_font_name (FALLBACK_FONT, frame->font);
+  }
 
-      if (app_data.reverse_video == True)
-       {
-         if (! face)
-           face = mface ();
-         mface_put_prop (face, Mvideomode, Mreverse);
-       }
-      if (face)
-       {
-         mplist_push (param, Mface, face);
-         M17N_OBJECT_UNREF (face);
-       }
-      device->foreground
-       = get_color (display, cmap, msymbol (app_data.foreground), Mnil,
-                    device->foreground);
-      device->background
-       = get_color (display, cmap, msymbol (app_data.background), Mnil,
-                    device->background);
-    }
+#ifdef X_SET_ERROR_HANDLER
   XSetErrorHandler (x_error_handler);
-  /* XSetIOErrorHandler (x_io_error_handler); */
+  XSetIOErrorHandler (x_io_error_handler);
+#endif
 
   return device;
 }
@@ -1367,155 +1521,101 @@ mwin__device_get_prop (MWDevice *device, MSymbol key)
   return NULL;
 }
 
-struct {
-  int size, inc, used;
-  GC *gc_table;
-} gc_list;
-
-#define REGISTER_GC(gc)                                        \
-  do {                                                 \
-    if (! gc_list.size)                                        \
-      MLIST_INIT1 (&gc_list, gc_table, 100);           \
-    MLIST_APPEND1 (&gc_list, gc_table, gc, MERROR_WIN);        \
-  } while (0)
-
-
-#define UNREGISTER_GC(gc)                      \
-  do {                                         \
-    int j;                                     \
-    for (j = 0; j < gc_list.used; j++)         \
-      if (gc_list.gc_table[j] == gc)           \
-       gc_list.gc_table[j] = (GC) NULL;        \
-  } while (0)
-
-
 void
 mwin__realize_face (MRealizedFace *rface)
 {
-  MFrame *frame = rface->frame;
-  MWDevice *device = frame->device;
-  Display *display = FRAME_DISPLAY (frame);
-  XGCValues values;
-  int mask = GCForeground | GCBackground;
-  MSymbol foreground = rface->face.property[MFACE_FOREGROUND];
-  MSymbol background = rface->face.property[MFACE_BACKGROUND];
-  MFaceHLineProp *hline = rface->hline;
-  MFaceBoxProp *box = rface->box;
-  MFaceHookFunc func = (MFaceHookFunc) rface->face.property[MFACE_HOOK_FUNC];
-  MSymbol default_foreground
-    = (MSymbol) mface_get_prop (frame->face, Mforeground);
-  MSymbol default_background
-    = (MSymbol) mface_get_prop (frame->face, Mbackground);
-  GC *gcs;
-  unsigned long pixel;
-
-  MTABLE_CALLOC (gcs, MFACE_GCS, MERROR_WIN);
-
-  values.foreground = get_color (display, device->cmap, foreground,
-                                default_foreground, device->foreground);
-  values.background = get_color (display, device->cmap, background,
-                                default_background, device->background);
-  if (rface->face.property[MFACE_VIDEOMODE] == Mreverse)
-    pixel = values.foreground,
-      values.foreground = values.background,
-      values.background = pixel;
-
-  if (rface->rfont
-      && rface->rfont->font.property[MFONT_TYPE] - 1 == MFONT_TYPE_WIN)
+  MFrame *frame;
+  MSymbol foreground, background, videomode;
+  MFaceHLineProp *hline;
+  MFaceBoxProp *box;
+  MFaceHookFunc func;
+  GCInfo *info;
+
+  if (rface != rface->ascii_rface)
     {
-      values.font = ((MXFontInfo *) (rface->rfont->info))->f->fid;
-      mask |= GCFont;
+      rface->info = rface->ascii_rface->info;
+      return;
     }
 
-  gcs[MFACE_GC_NORMAL] = XCreateGC (display, device->drawable, mask, &values);
-  REGISTER_GC (gcs[MFACE_GC_NORMAL]);
-
-  gcs[MFACE_GC_SCRATCH] = XCreateGC (display, device->drawable, mask, &values);
-  REGISTER_GC (gcs[MFACE_GC_SCRATCH]);
+  frame = rface->frame;
+  MSTRUCT_CALLOC (info, MERROR_WIN);
 
-  pixel = values.foreground;
-  values.foreground = values.background;
-  values.background = pixel;
-  gcs[MFACE_GC_INVERSE] = XCreateGC (display, device->drawable, mask, &values);
-  REGISTER_GC (gcs[MFACE_GC_INVERSE]);
-  values.background = values.foreground;
-  values.foreground = pixel;
-
-  mask &= ~GCFont;
+  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
 
-  if (rface == rface->ascii_rface)
+  hline = rface->hline;
+  if (hline)
     {
-      /* This realized face is for ASCII.  Setup GCs for hline and
-        box.  */
-      if (hline && hline->color != foreground)
-       {
-         values.foreground
-           = get_color (display, device->cmap, hline->color,
-                        default_foreground, device->foreground);
-         gcs[MFACE_GC_HLINE]
-           = XCreateGC (display, device->drawable, mask, &values);
-         REGISTER_GC (gcs[MFACE_GC_HLINE]);
-         values.foreground = pixel;
-       }
+      if (hline->color)
+       info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL);
+      else
+       info->gc[GC_HLINE] = info->gc[GC_NORMAL];
+    }
 
-      if (box)
-       {
-         if (box->color_top)
-           {
-             values.foreground
-               = get_color (display, device->cmap, box->color_top,
-                            default_foreground, device->foreground);
-             gcs[MFACE_GC_BOX_TOP]
-               = XCreateGC (display, device->drawable, mask, &values);
-             REGISTER_GC (gcs[MFACE_GC_BOX_TOP]);
-           }
+  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];
 
-         if (box->color_left
-             && box->color_left != box->color_top)
-           {
-             values.foreground
-               = get_color (display, device->cmap, box->color_left,
-                            default_foreground, device->foreground);
-             gcs[MFACE_GC_BOX_LEFT]
-               = XCreateGC (display, device->drawable, mask, &values);
-             REGISTER_GC (gcs[MFACE_GC_BOX_LEFT]);
-           }
+      if (box->color_left && box->color_left != box->color_top)
+       info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL);
+      else
+       info->gc[GC_BOX_LEFT] = info->gc[GC_NORMAL];
 
-         if (box->color_right
-             && box->color_right != box->color_top)
-           {
-             values.foreground
-               = get_color (display, device->cmap, box->color_right,
-                            default_foreground, device->foreground);
-             gcs[MFACE_GC_BOX_RIGHT]
-               = XCreateGC (display, device->drawable, mask, &values);
-             REGISTER_GC (gcs[MFACE_GC_BOX_RIGHT]);
-           }
+      if (box->color_bottom && box->color_bottom != box->color_top)
+       info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL);
+      else
+       info->gc[GC_BOX_BOTTOM] = info->gc[GC_NORMAL];
 
-         if (box->color_bottom
-             && box->color_bottom != box->color_top)
-           {
-             values.foreground
-               = get_color (display, device->cmap, box->color_bottom,
-                            default_foreground, device->foreground);
-             gcs[MFACE_GC_BOX_BOTTOM]
-               = XCreateGC (display, device->drawable, mask, &values);
-             REGISTER_GC (gcs[MFACE_GC_BOX_BOTTOM]);
-           }
-       }
+      if (box->color_right && box->color_right != box->color_top)
+       info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL);
+      else
+       info->gc[GC_BOX_RIGHT] = info->gc[GC_NORMAL];
     }
-  else
-    {
-      /* This realized face is not for ASCII.  GCs for hline and box
-        are shared with that of the corresponding ASCII face.  */
-      GC *ascii_gcs = rface->ascii_rface->info;
-      int i;
 
-      for (i = MFACE_GC_HLINE; i < MFACE_GCS; i++)
-       gcs[i] = ascii_gcs[i];
-    }
+  rface->info = info;
 
-  rface->info = gcs;
+  func = (MFaceHookFunc) rface->face.property[MFACE_HOOK_FUNC];
   if (func)
     (func) (&(rface->face), rface->info, rface->face.property[MFACE_HOOK_ARG]);
 }
@@ -1524,18 +1624,8 @@ mwin__realize_face (MRealizedFace *rface)
 void
 mwin__free_realized_face (MRealizedFace *rface)
 {
-  GC *gcs = rface->info;
-  enum face_gc limit
-    = rface == rface->ascii_rface ? MFACE_GCS : MFACE_GC_HLINE;
-  int i;
-
-  for (i = 0; i < limit; i++)
-    if (gcs[i])
-      {
-       UNREGISTER_GC (gcs[i]);
-       XFreeGC (FRAME_DISPLAY (rface->frame), gcs[i]);
-      }            
-  free (gcs);
+  if (rface == rface->ascii_rface)
+    free (rface->info);
 }
 
 
@@ -1544,11 +1634,10 @@ mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
                  int reverse,
                  int x, int y, int width, int height, MDrawRegion region)
 {
-  GC *gcs = rface->info;
-  GC gc = gcs[reverse ? MFACE_GC_NORMAL : MFACE_GC_INVERSE];
+  GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE];
 
   if (region)
-    gc = set_region (FRAME_DISPLAY (frame), rface, gc, region);
+    gc = set_region (frame, gc, region);
 
   XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc,
                  x, y, width, height);
@@ -1561,8 +1650,8 @@ mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
                 int x, int y, int width, MDrawRegion region)
 {
   enum MFaceHLineType type = rface->hline->type;
-  GC *gcs = rface->info;
-  GC gc;
+  GCInfo *info = rface->info;
+  GC gc = gc = info->gc[GC_HLINE];
   int i;
 
   y = (type == MFACE_HLINE_BOTTOM
@@ -1572,15 +1661,8 @@ mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
        : type == MFACE_HLINE_STRIKE_THROUGH
        ? y - ((gstring->ascent + gstring->descent) / 2)
        : y - gstring->text_ascent);
-  if (reverse)
-    gc = gcs[MFACE_GC_INVERSE];
-  else if (gcs[MFACE_GC_HLINE])
-    gc = gcs[MFACE_GC_HLINE];
-  else
-    gc = gcs[MFACE_GC_NORMAL];
-
   if (region)
-    gc = set_region (FRAME_DISPLAY (frame), rface, gc, region);
+    gc = set_region (frame, gc, region);
 
   for (i = 0; i < rface->hline->width; i++)
     XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc,
@@ -1595,7 +1677,7 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
   Display *display = FRAME_DISPLAY (frame);
   MRealizedFace *rface = g->rface;
   MFaceBoxProp *box = rface->box;
-  GC *gcs = rface->info;
+  GCInfo *info = rface->info;
   GC gc_top, gc_left, gc_right, gc_btm;
   int y0, y1;
   int i;
@@ -1605,14 +1687,13 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
   y1 = y + (gstring->text_descent
            + rface->box->inner_vmargin + rface->box->width - 1);
 
-  gc_top = gcs[MFACE_GC_BOX_TOP];
-  if (! gc_top)
-    gc_top = gcs[MFACE_GC_NORMAL];
+  gc_top = info->gc[GC_BOX_TOP];
   if (region)
-    gc_top = set_region (FRAME_DISPLAY (frame), rface, gc_top, region);
-  gc_btm = gcs[MFACE_GC_BOX_BOTTOM];
-  if (! gc_btm)
+    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)
     {
@@ -1628,19 +1709,22 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
        XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i);
 
       /* Draw the bottom side.  */
-      if (region)
-       gc_btm = set_region (display, rface, gc_btm, region);
+      if (region && gc_btm != gc_top)
+       gc_btm = set_region (frame, gc_btm, region);
       for (i = 0; i < box->width; i++)
        XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i);
 
       if (g->left_padding > 0)
        {
          /* Draw the left side.  */
-         gc_left = gcs[MFACE_GC_BOX_LEFT];
-         if (! gc_left)
+         if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP])
            gc_left = gc_top;
-         else if (region)
-           gc_left = set_region (display, rface, gc_left, region);
+         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);
@@ -1648,11 +1732,14 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
       else
        {
          /* Draw the right side.  */
-         gc_right = gcs[MFACE_GC_BOX_RIGHT];
-         if (! gc_right)
+         if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP])
            gc_right = gc_top;
-         else if (region)
-           gc_right = set_region (display, rface, gc_right, region);
+         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);
@@ -1666,8 +1753,8 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
                   x, y0 + i, x + width - 1, y0 + i);
 
       /* Draw the bottom side.  */
-      if (region)
-       gc_btm = set_region (display, rface, gc_btm, region);
+      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);
@@ -1675,6 +1762,7 @@ mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring,
 }
 
 
+#if 0
 void
 mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
                   int reverse, int x, int y,
@@ -1683,17 +1771,35 @@ mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
 {
   Display *display = FRAME_DISPLAY (frame);
   int i, j;
-  GC *gcs = rface->info;
-  GC gc = gcs[reverse ? MFACE_GC_INVERSE : MFACE_GC_NORMAL];
+  GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
 
   if (region)
-    gc = set_region (FRAME_DISPLAY (frame), rface, gc, region);
+    gc = set_region (frame, gc, region);
 
   for (i = 0; i < height; i++, bmp += row_bytes)
     for (j = 0; j < width; j++)
       if (bmp[j / 8] & (1 << (7 - (j % 8))))
        XDrawPoint (display, (Window) win, gc, x + j, y + i);
 }
+#endif
+
+void
+mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface,
+                  int intensity, MDrawPoint *points, int num,
+                  MDrawRegion region)
+{
+  GCInfo *info = rface->info;
+  GC gc;
+
+  if (! (gc = info->gc[intensity]))
+    gc = info->gc[intensity] = get_gc_for_anti_alias (frame->device, info,
+                                                     intensity);
+  if (region)
+    gc = set_region (frame, gc, region);
+
+  XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc,
+              (XPoint *) points, num, CoordModeOrigin);
+}
 
 
 MDrawRegion
@@ -1781,35 +1887,33 @@ mwin__dump_region (MDrawRegion region)
 void
 mwin__verify_region (MFrame *frame, MDrawRegion region)
 {
-  set_region (FRAME_DISPLAY (frame), frame->rface,
-             ((GC *) frame->rface->info)[MFACE_GC_NORMAL], region);
+  set_region (frame, ((GCInfo *) frame->rface->info)->gc[GC_NORMAL], region);
 }
 
 MDrawWindow
 mwin__create_window (MFrame *frame, MDrawWindow parent)
 {
-  MWDevice *device = frame->device;
   Display *display = FRAME_DISPLAY (frame);
-  int screen = FRAME_SCREEN (frame);
   Window win;
   XWMHints wm_hints = { InputHint, False };
   XClassHint class_hints = { "M17N-IM", "m17n-im" };
-  XSetWindowAttributes attrs;
+  XSetWindowAttributes set_attrs;
   unsigned long mask;
-  MSymbol background = mface_get_prop (frame->face, Mbackground);
-
-  attrs.background_pixel = get_color (display, device->cmap,
-                                     background, background,
-                                     WhitePixel (display, screen));
-  attrs.backing_store = Always;
-  attrs.override_redirect = True;
-  attrs.save_under = True;
-  mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder;
+  XGCValues values;
+  GCInfo *info = frame->rface->info;
+
   if (! parent)
-    parent = (MDrawWindow) RootWindow (display, screen);
+    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, &attrs);
+                      mask, &set_attrs);
   XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0,
                    NULL, &wm_hints, &class_hints);
   XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask);
@@ -1957,6 +2061,7 @@ mwin__adjust_window (MFrame *frame, MDrawWindow win,
     }
   if (mask)
     XConfigureWindow (display, (Window) win, mask, &values);
+  XClearWindow (display, (Window) win);
 }
 
 MSymbol
@@ -1979,18 +2084,19 @@ mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
     return Mnil;
   if (len == 1)
     {
-      int c = buf[0];
+      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)
        {
-         c &= 0x1F;
-         if (((XKeyEvent *) event)->state & ShiftMask)
-           *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
+         if (c >= 'a' && c <= 'z')
+           c += 'A' - 'a';
+         if (c >= ' ' && c < 127)
+           *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
        }
-      if (((XKeyEvent *) event)->state & disp_info->meta_mask)
-       c |= 0x80;
       key = minput__char_to_key (c);
     }
   else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
@@ -2033,18 +2139,151 @@ mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
   unsigned long valuemask = GCForeground | GCBackground | GCClipMask;
   XGCValues values;
   Display *display = FRAME_DISPLAY (frame);
-  GC *gcs = rface->info;
+  GCInfo *info = rface->info;
   int i;
 
-  for (i = 0; i <= MFACE_GC_SCRATCH; i++)
+  for (i = 0; i <= GC_INVERSE; i++)
     {
-      XGetGCValues (display, gcs[i], valuemask, &values);
+      XGetGCValues (display, info->gc[i], valuemask, &values);
       fprintf (stderr, "GC%d: fore/#%lX back/#%lX", i,
               values.foreground, values.background);
       fprintf (stderr, "\n");
     }
 }
 
+#ifdef HAVE_XFT2
+typedef struct {
+  MFrame *frame;
+  XftFont *font_aa;
+  XftFont *font_no_aa;
+} MXftFontInfo;
+
+/* Xft Handler */
+
+void
+mwin__xft_close (void *object)
+{
+  MXftFontInfo *font_info = object;
+
+  if (font_info->font_aa)
+    XftFontClose (FRAME_DISPLAY (font_info->frame), font_info->font_aa);
+  if (font_info->font_no_aa)
+    XftFontClose (FRAME_DISPLAY (font_info->frame), font_info->font_no_aa);
+  free (object);
+}
+
+
+void *
+mwin__xft_open (MFrame *frame, char *filename, int size)
+{
+  MXftFontInfo *font_info;
+  FcPattern *pattern;
+
+  MSTRUCT_CALLOC (font_info, MERROR_WIN);
+
+  font_info->frame = frame;
+  pattern = FcPatternCreate ();
+  FcPatternAddString (pattern, FC_FILE, (FcChar8 *) filename);
+  FcPatternAddInteger (pattern, FC_PIXEL_SIZE, size);
+  FcPatternAddBool (pattern, FC_ANTIALIAS, FcTrue);
+  font_info->font_aa = XftFontOpenPattern (FRAME_DISPLAY (frame), pattern);
+  if (! font_info->font_aa)
+    goto err;
+  pattern = FcPatternCreate ();
+  FcPatternAddString (pattern, FC_FILE, (FcChar8 *) filename);
+  FcPatternAddInteger (pattern, FC_PIXEL_SIZE, size);
+  FcPatternAddBool (pattern, FC_ANTIALIAS, FcFalse);
+  font_info->font_no_aa = XftFontOpenPattern (FRAME_DISPLAY (frame), pattern);
+  if (! font_info->font_aa)
+    goto err;
+  return font_info;
+
+ err:
+  if (font_info->font_aa)
+    XftFontClose (FRAME_DISPLAY (frame), font_info->font_aa);
+  FcPatternDestroy (pattern);
+  free (font_info);
+  return NULL;
+}
+
+
+void
+mwin__xft_get_metric (void *object, FT_Face ft_face, MGlyph *g)
+{
+  MXftFontInfo *font_info = object;
+  XGlyphInfo extents;
+  unsigned code;
+
+  if (g->otf_encoded)
+    code = g->code;
+  else
+    code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
+
+  XftGlyphExtents (FRAME_DISPLAY (font_info->frame),
+                  font_info->font_aa, &code, 1, &extents);
+  g->lbearing = extents.x;
+  g->rbearing = extents.width - extents.x;
+  g->width = extents.xOff;
+  g->ascent = extents.y;
+  g->descent = extents.height - extents.y;
+}
+
+
+void 
+mwin__xft_render (MDrawWindow win, int x, int y,
+                 MGlyphString *gstring, MGlyph *from, MGlyph *to,
+                 int reverse, MDrawRegion region,
+                 void *object, FT_Face ft_face)
+{
+  MXftFontInfo *font_info = object;  
+  MRealizedFace *rface = from->rface;
+  MFrame *frame = rface->frame;
+  XftDraw *xft_draw = frame->device->xft_draw;
+  XftColor *xft_color = (! reverse
+                        ? &((GCInfo *) rface->info)->xft_color_fore
+                        : &((GCInfo *) rface->info)->xft_color_back);
+  XftFont *xft_font = (gstring->control.anti_alias && frame->device->depth > 1
+                      ? font_info->font_aa : font_info->font_no_aa);
+  MGlyph *g;
+  FT_UInt *glyphs;
+  int last_x;
+  int nglyphs;
+
+  if (from == to)
+    return;
+
+  XftDrawChange (xft_draw, (Drawable) win);
+  XftDrawSetClip (xft_draw, (Region) region);
+      
+  glyphs = alloca (sizeof (FT_UInt) * (to - from));
+  for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
+    {
+      unsigned code;
+
+      if (g->otf_encoded)
+       code = g->code;
+      else
+       code = FT_Get_Char_Index (ft_face, (FT_ULong) g->code);
+      if (g->xoff == 0 && g->yoff == 0)
+       glyphs[nglyphs++] = code;
+      else
+       {
+         if (nglyphs > 0)
+           XftDrawGlyphs (xft_draw, xft_color, xft_font,
+                          last_x, y, glyphs, nglyphs);
+         nglyphs = 0;
+         XftDrawGlyphs (xft_draw, xft_color, xft_font,
+                        x + g->xoff, y + g->yoff, (FT_UInt *) &code, 1);
+         last_x = x + g->width;
+       }
+    }
+  if (nglyphs > 0)
+    XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
+}
+
+#endif
+
+\f
 /*** @} */
 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
 \f
@@ -2060,7 +2299,15 @@ mwin__dump_gc (MFrame *frame, MRealizedFace *rface)
 
     These are the symbols to use as parameter keys for the function
     mframe () (which see).  They are also keys of a frame property
-    (except for #Mwidget).  */
+    except for #Mwidget.  */
+/***ja
+    @name ÊÑ¿ô¡§ ¥Õ¥ì¡¼¥à¥Ñ¥é¥á¡¼¥¿ÍÑ¥­¡¼ (X ¸ÇÍ­).
+
+    ´Ø¿ô mframe () ¤Î¥Ñ¥é¥á¡¼¥¿¥­¡¼¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¥·¥ó¥Ü¥ë¡£( mframe
+    () ¤ÎÀâÌÀ»²¾È¡£) #Mwidget ¤ò½ü¤¤¤Æ¤Ï¥Õ¥ì¡¼¥à¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤Ç¤â¤¢
+    ¤ë¡£
+    */
+
 /*=*/
 /*** @{ */ 
 /* Keywords for mwin__open_device ().  */
@@ -2075,11 +2322,11 @@ MSymbol Mdisplay, Mscreen, Mdrawable, Mdepth, Mwidget, Mcolormap;
 /*** @{ */
 
 /***en
-    @brief Input driver for XIM.
+    @brief Input method driver for XIM.
 
-    The input driver #minput_xim_driver is for the foreign input
-    method of name #Mxim.  It uses XIM (X Input Methods) as a
-    background input engine.
+    The driver #minput_xim_driver is for the foreign input method of
+    name #Mxim.  It uses XIM (X Input Methods) as a background input
+    engine.
 
     As the symbol #Mxim has property #Minput_driver whose value is
     a pointer to this driver, the input method of language #Mnil
@@ -2104,29 +2351,28 @@ MSymbol Mdisplay, Mscreen, Mdrawable, Mdepth, Mwidget, Mcolormap;
     $KEY is ignored.  */
 
 /***ja
-    @brief XIMÍÑÆþÎϥɥ饤¥Ð
+    @brief XIMÍÑÆþÎϥɥ饤¥Ð.
 
-    ÆþÎϥɥ饤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°Éô
-    ÆþÎϥ᥽¥Ã¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤Î
-    ÆþÎÏ¥¨¥ó¥¸¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
+    ¥É¥é¥¤¥Ð #minput_xim_driver ¤Ï #Mxim ¤ò̾Á°¤È¤·¤Æ»ý¤Ä³°ÉôÆþÎϥ᥽¥Ã
+    ¥ÉÍѤǤ¢¤ê¡¢ XIM (X Input Methods) ¤ò¥Ð¥Ã¥¯¥°¥é¥¦¥ó¥É¤ÎÆþÎÏ¥¨¥ó¥¸
+    ¥ó¤È¤·¤Æ»ÈÍѤ¹¤ë¡£
 
     ¥·¥ó¥Ü¥ë #Mxim ¤Ï¤³¤Î¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥×¥í¥Ñ¥Æ¥£
-    #Minput_driver ¤ò»ý¤Ä¤¿¤á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç
-    ¤¢¤ëÆþÎϥ᥽¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
+    #Minput_driver ¤ò»ý¤Á¡¢LANGUAGE ¤¬ #Mnil ¤Ç̾Á°¤¬ #Mxim ¤Ç¤¢¤ëÆþÎÏ
+    ¥á¥½¥Ã¥É¤Ï¤³¤Î¥É¥é¥¤¥Ð¤òÍøÍѤ¹¤ë¡£
 
-    ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥ÉÍѤˤϡ¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä
-    °Ê²¼¤Î´Ø¿ô·²¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é
-    ¤Ê¤¤¡£
+    ¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ì¤é¤ÎÆþÎϥ᥽¥Ã¥É¤Ç¤Ï¡¢minput_ ¤Ç»Ï¤Þ¤ë̾Á°¤ò»ý¤Ä´Ø
+    ¿ô¤Î¥É¥é¥¤¥Ð¤Ë°Í¸¤¹¤ë°ú¿ô¤Ï¼¡¤Î¤è¤¦¤Ê¤â¤Î¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
 
-    ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIM ¤Ø¤Î
-    ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤Î¥É
-    ¥­¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
+    ´Ø¿ô minput_open_im () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIM ¤Ø¤Î¥Ý
+    ¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIM ¤ÎÀâÌÀ¤ò
+    »²¾È¡£
 
-    ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIC ¤Ø
-    ¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤Î
-    ¥É¥­¥å¥á¥ó¥È¤ò»²¾È¤Î¤³¤È¡£
+    ´Ø¿ô minput_create_ic () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ#MInputXIMArgIC ¤Ø¤Î
+    ¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¾ÜºÙ¤Ë¤Ä¤¤¤Æ¤Ï #MInputXIMArgIC ¤ÎÀâÌÀ
+    ¤ò»²¾È¡£
 
-    ´Ø¿ô minput_filter () ¤Î°ú¿ô %ARG ¤Ï¹½Â¤ÂΠ@c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
+    ´Ø¿ô minput_filter () ¤Î°ú¿ô $ARG ¤Ï¹½Â¤ÂΠ@c XEvent ¤Ø¤Î¥Ý¥¤¥ó¥¿
     ¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£°ú¿ô $KEY ¤Ï̵»ë¤µ¤ì¤ë¡£
 
     ´Ø¿ô minput_lookup () ¤Î°ú¿ô $ARG ¤Ï´Ø¿ô function minput_filter () 
@@ -2144,6 +2390,11 @@ MInputDriver minput_xim_driver =
 
     The variable Mxim is a symbol of name "xim".  It is a name of the
     input method driver #minput_xim_driver.  */ 
+/***ja
+    @brief "xim"¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë .
+
+    ÊÑ¿ô Mxim ¤Ï"xim"¤ò̾Á°¤È¤·¤Æ»ý¤Ä¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£"xim" ¤ÏÆþÎϥ᥽¥Ã
+    ¥É¥É¥é¥¤¥Ð #minput_xim_driver ¤Î̾Á°¤Ç¤¢¤ë¡£  */ 
 
 MSymbol Mxim;