*** empty log message ***
[m17n/m17n-lib.git] / src / m17n-X.c
index e203254..80cbeb3 100644 (file)
@@ -17,7 +17,7 @@
 
    You should have received a copy of the GNU Lesser General Public
    License along with the m17n library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    02111-1307, USA.  */
 
 #include "config.h"
 #include "fontset.h"
 #include "face.h"
 
-typedef struct _MFontX MFontX;
-
-struct _MFontX 
-{
-  /* Record a font of the smallest pixel size.  */
-  MFont core;
-  /* Nth bit tells the existence of a font of size N + 5.  So this is
-     for 5..36 pixel size fonts.  Usually this covers all sizes.  */
-  unsigned int size5_36;
-  /* Fonts of (size < 5 || size > 36) are listed here (except for a
-     scalable whose size is 0).  */
-  MFontX *next;
-};
-
-/* S must satisfy the condition (S >= 5 && S < 36).  */
-
-#define SET_SIZE(FONTX, S) ((FONTX)->size5_36 |= (1 << ((S) - 5)))
-
-#define HAVE_SIZE(FONTX, S) ((FONTX)->size5_36 & (1 << ((S) - 5)))
-
 typedef struct
 {
   /* Common header for the m17n object.  */
@@ -92,7 +72,7 @@ typedef struct
 
   /** List of available X-core fonts on the display.  Keys are
       registries and values are plists whose keys are families and
-      values are pointers to MFontX.  */
+      values are pointers to MFont.  */
   MPlist *font_list;
 
   /** Nonzero means that <font_list> already contains all available
@@ -104,6 +84,9 @@ typedef struct
   int alt_mask;
   int super_mask;
   int hyper_mask;
+
+  Atom MULE_BASELINE_OFFSET;
+  Atom AVERAGE_WIDTH;
 } MDisplayInfo;
 
 /* Anchor of the chain of MDisplayInfo objects.  */
@@ -208,15 +191,7 @@ free_display_info (void *object)
   MPLIST_DO (plist, disp_info->font_list)
     {
       MPLIST_DO (pl, MPLIST_VAL (plist))
-       {
-         MFontX *fontx, *next;
-
-         for (fontx = MPLIST_VAL (pl); fontx; fontx = next)
-           {
-             next = fontx->next;
-             free (fontx);
-           }
-       }
+       free (MPLIST_VAL (pl));
       M17N_OBJECT_UNREF (MPLIST_VAL (plist));
     }
   M17N_OBJECT_UNREF (disp_info->font_list);
@@ -440,12 +415,13 @@ static unsigned xfont_encode_char (MFrame *, MFont *, MFont *, unsigned);
 static void xfont_render (MDrawWindow, int, int, MGlyphString *,
                          MGlyph *, MGlyph *, int, MDrawRegion);
 static int xfont_list (MFrame *, MPlist *, MFont *, int);
-
+static void xfont_list_family_names (MFrame *, MPlist *);
+static int xfont_check_capability (MRealizedFont *rfont, MSymbol capability);
 
 static MFontDriver xfont_driver =
   { xfont_select, xfont_open,
     xfont_find_metric, xfont_has_char, xfont_encode_char,
-    xfont_render, xfont_list };
+    xfont_render, xfont_list, xfont_list_family_names, xfont_check_capability };
 
 static int
 font_compare (const void *p1, const void *p2)
@@ -469,7 +445,7 @@ xfont_registry_list (MFrame *frame, MSymbol registry)
   plist = mplist_get (font_list, registry);
   if (plist)
     return plist;
-  plist = mplist ();
+  p = plist = mplist ();
   mplist_add (font_list, registry, plist);
   sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", msymbol_name (registry));
   font_names = XListFonts (disp_info->display, pattern, 0x8000, &nfonts);
@@ -487,24 +463,20 @@ xfont_registry_list (MFrame *frame, MSymbol registry)
   memcpy (names, font_names, sizeof (char *) * nfonts);
   qsort (names, nfonts, sizeof (char *), font_compare);
   MFONT_INIT (&font);
-  for (i = 0, p = NULL; i < nfonts; i++)
+  for (i = 0; i < nfonts; i++)
     if (mfont__parse_name_into_font (names[i], Mx, &font) == 0
-       && (font.size >= 50 || font.property[MFONT_RESY] == 0))
+       && (font.size > 0 || font.property[MFONT_RESY] == 0))
       {
        MSymbol family = FONT_PROPERTY (&font, MFONT_FAMILY);
-       MFontX *fontx, *fontx2;
+       MFont *fontx;
        unsigned sizes[256];
        int nsizes = 0;
-       int size, smallest;
+       int limit;
+       int size, normal_size;
        char *base_end;
        int base_len;
        int fields;
        
-       if (p && MPLIST_KEY (p) != family)
-         p = mplist_find_by_key (plist, family);
-       if (! p)
-         p = mplist_push (plist, family, NULL);
-
        /* Calculate how many bytes to compare to detect fonts of the
           same base name.  */
        for (base_end = names[i], fields = 0; *base_end; base_end++)
@@ -513,44 +485,44 @@ xfont_registry_list (MFrame *frame, MSymbol registry)
            break;
        base_len = base_end - names[i] + 1;
 
-       size = smallest = font.size / 10;
+       size = font.size / 10;
        sizes[nsizes++] = size;
-       for (j = i + 1; j < nfonts && ! strncmp (names[i], names[j], base_len);
+       normal_size = (size >= 6 && size <= 29);
+       limit = (i + 256 < nfonts ? i + 256 : nfonts);
+       for (j = i + 1; j < limit && ! memcmp (names[i], names[j], base_len);
             i = j++)
          if (mfont__parse_name_into_font (names[j], Mx, &font) == 0
-             && (font.size >= 50 || font.property[MFONT_RESY] == 0))
+             && (font.size > 0 || font.property[MFONT_RESY] == 0))
            {
              size = font.size / 10;
-             if (size < smallest)
-               smallest = size;
-             if (nsizes < 256)
-               sizes[nsizes++] = size;
+             sizes[nsizes++] = size;
+             normal_size |= (size >= 6 && size <= 29);
            }
 
        font.for_full_width = for_full_width;
        font.type = MFONT_TYPE_OBJECT;
        font.source = MFONT_SOURCE_X;
-       MSTRUCT_CALLOC (fontx, MERROR_WIN);
-       fontx->core = font;
-       fontx->core.size = smallest * 10;
-       fontx->next = MPLIST_VAL (p);
-       MPLIST_VAL (p) = fontx;
-       if (smallest > 0)
-         for (j = 0; j < nsizes; j++)
+       if (normal_size)
+         {
+           MSTRUCT_CALLOC (fontx, MERROR_WIN);
+           *fontx = font;
+           fontx->multiple_sizes = 1;
+           fontx->size = 0;
+           for (j = 0; j < nsizes; j++)
+             if (sizes[j] >= 6 && sizes[j] <= 29)
+               fontx->size |= 1 << (sizes[j] - 6);
+           p = mplist_add (p, family, fontx);
+         }
+       for (j = 0; j < nsizes; j++)
+         if (sizes[j] < 6 || sizes[j] > 29)
            {
-             if (sizes[j] <= 36)
-               {
-                 if (sizes[j] != smallest)
-                   SET_SIZE (fontx, sizes[j]);
-               }
-             else
-               {
-                 MSTRUCT_CALLOC (fontx2, MERROR_WIN);
-                 fontx2->core = font;
-                 fontx2->core.size = sizes[j] * 10;
-                 fontx2->next = MPLIST_VAL (p);
-                 MPLIST_VAL (p) = fontx2;
-               }
+             MSTRUCT_CALLOC (fontx, MERROR_WIN);
+             *fontx = font;
+             fontx->multiple_sizes = 0;
+             fontx->size = sizes[j] * 10;
+             if (sizes[j] == 0)
+               fontx->property[MFONT_RESY] = 0;
+             p = mplist_add (p, family, fontx);
            }
       }
   XFreeFontNames (font_names);
@@ -621,7 +593,7 @@ close_xfont (void *object)
 static MRealizedFont *
 xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
 {
-  int size = spec->size;
+  int size;
   MRealizedFontX *x_rfont;
   char *name;
   Display *display = FRAME_DISPLAY (frame);
@@ -629,6 +601,41 @@ xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
   int mdebug_mask = MDEBUG_FONT;
   MFont this;
 
+  size = spec->size;
+  if (size)
+    {
+      int ratio = mfont_resize_ratio (font);
+
+      if (ratio != 100)
+       size = size * ratio / 100;
+    }
+  else
+    size = 120;
+
+  if (font->size)
+    {
+      /* non-scalable font */
+      if (font->multiple_sizes)
+       {
+         int i;
+
+         if (size < 60)
+           size = 60;
+         else if (size > 290)
+           size = 290;
+         for (i = size / 10 - 6; i >= 0; i--)
+           if (font->size & (1 << i))
+             break;
+         if (i == 0)
+           for (i = size / 10 - 5; i < 24; i++)
+             if (font->size & (1 << i))
+               break;
+         size = (i + 6) * 10;
+       }
+      else
+       size = font->size;
+    }
+
   if (rfont)
     {
       for (; rfont; rfont = rfont->next)
@@ -637,6 +644,7 @@ xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
     }
 
   this = *font;
+  this.multiple_sizes = 0;
   this.size = size;
   /* This never fail to generate a valid fontname.  */
   name = mfont_unparse_name (&this, Mx);
@@ -661,8 +669,19 @@ xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
   rfont->font = font;
   rfont->driver = &xfont_driver;
   rfont->info = x_rfont;
-  rfont->ascent = xfont->ascent;
-  rfont->descent = xfont->descent;
+  {
+    MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
+    unsigned long value;
+
+    rfont->baseline_offset
+      = (XGetFontProperty (xfont, disp_info->MULE_BASELINE_OFFSET, &value)
+        ? (int) value : 0);
+    rfont->average_width
+      = (XGetFontProperty (xfont, disp_info->AVERAGE_WIDTH, &value)
+        ? (int) value / 10 : 0);
+  }
+  rfont->ascent = xfont->ascent + rfont->baseline_offset;
+  rfont->descent = xfont->descent - rfont->baseline_offset;
   rfont->max_advance = xfont->max_bounds.width;
   rfont->fontp = xfont;
   rfont->next = MPLIST_VAL (frame->realized_font_list);
@@ -741,6 +760,8 @@ xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring,
              g->descent = xfont->descent;
            }
        }
+      g->ascent += rfont->baseline_offset;
+      g->descent -= rfont->baseline_offset;
     }
 }
 
@@ -765,11 +786,9 @@ xfont_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code)
     rfont = (MRealizedFont *) font;
   else if (font->type == MFONT_TYPE_OBJECT)
     {
-      int size = spec->size;
-
       for (rfont = MPLIST_VAL (frame->realized_font_list); rfont;
           rfont = rfont->next)
-       if (rfont->font == font && rfont->spec.size == size)
+       if (rfont->font == font)
          break;
       if (! rfont)
        {
@@ -829,10 +848,12 @@ xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
   GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL];
   MGlyph *g;
   int i;
+  int baseline_offset;
 
   if (from == to)
     return;
 
+  baseline_offset = rface->rfont->baseline_offset;
   if (region)
     gc = set_region (rface->frame, gc, region);
   XSetFont (display, gc, ((XFontStruct *) rface->rfont->fontp)->fid);
@@ -875,7 +896,8 @@ xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
       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->xoff, y + g->yoff - baseline_offset,
+                        code + (g - from), 1);
          x += g->width;
          g++;
        }
@@ -888,8 +910,8 @@ xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring,
               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);
+         XDrawString16 (display, (Window) win, gc,
+                        orig_x, y - baseline_offset, code + code_idx, i);
        }
     }
 }
@@ -915,62 +937,86 @@ xfont_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum)
     xfont_registry_list (frame, registry);
 
   MPLIST_DO (pl, disp_info->font_list)
+    if (registry == Mnil || registry == MPLIST_KEY (pl))
+      {
+       MPLIST_DO (p, MPLIST_VAL (pl))
+         if (family == Mnil || family == MPLIST_KEY (p))
+           {
+             MFont *fontx = MPLIST_VAL (p);
+
+             if (! font || (mfont__match_p (fontx, font, MFONT_REGISTRY)))
+               {
+                 if (fontx->size != 0 && size)
+                   {
+                     if (fontx->multiple_sizes)
+                       {
+                         if (size < 60 || size > 290
+                             || ! (fontx->size & (1 << (size / 10 - 6))))
+                           continue;
+                       }
+                     else if (fontx->size != size)
+                       continue;
+                   }
+                 mplist_push (plist, MPLIST_KEY (p), fontx);
+                 num++;
+                 if (maxnum > 0 && maxnum == num)
+                   goto done;
+               }
+           }
+      }
+
+ done:
+  MDEBUG_PRINT1 (" %d found\n", num);
+  return num;
+}
+
+static void
+xfont_list_family_names (MFrame *frame, MPlist *plist)
+{
+  MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info;
+  char **font_names;
+  int i, nfonts;
+  MSymbol last_family = Mnil;
+
+  font_names = XListFonts (disp_info->display,
+                          "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", 0x8000, &nfonts);
+  for (i = 0; i < nfonts; i++)
     {
-      if (registry != Mnil && registry != MPLIST_KEY (pl))
+      MSymbol family;
+      char foundry[256], fam[256];
+      MPlist *p;
+      
+      if (sscanf (font_names[i], "-%s-%s-", foundry, fam) < 2)
+       continue;
+      family = msymbol (fam);
+      if (family == last_family)
        continue;
-      MPLIST_DO (p, MPLIST_VAL (pl))
+      last_family = family;
+
+      MPLIST_DO (p, plist)
        {
-         MFontX *fontx;
-
-         if (family != Mnil && family != MPLIST_KEY (p))
-           continue;
-         for (fontx = MPLIST_VAL (p); fontx; fontx = fontx->next)
-           if (! font
-               || (mfont__match_p (&fontx->core, font, MFONT_REGISTRY)))
-             {
-               if (fontx->core.size == size
-                   || fontx->core.size == 0)
-                 {
-                   mplist_push (plist, MPLIST_KEY (p), fontx);
-                   num++;
-                 }
-               else if (size == 0
-                        || (size <= 360 && HAVE_SIZE (fontx, (size / 10))))
-                 {
-                   unsigned size5_36 = fontx->size5_36;
-                   MFontX *fontx2;
-                   int i;
-
-                   fontx->size5_36 = 0;
-                   for (i = fontx->core.size / 10; i <= 36; i++)
-                     if (size5_36 & (1 << (i - 5)))
-                       {
-                         MSTRUCT_CALLOC (fontx2, MERROR_WIN);
-                         fontx2->core = fontx->core;
-                         fontx2->core.size = i * 10;
-                         fontx2->next = fontx->next;
-                         fontx->next = fontx2;
-                         fontx = fontx2;
-                         if ((size == 0 || size == fontx->core.size)
-                             && (maxnum == 0 || num < maxnum))
-                           {
-                             mplist_push (plist, MPLIST_KEY (p), fontx);
-                             num++;
-                           }
-                       }
-                 }
-               if (maxnum > 0 && maxnum == num)
-                 break;
-             }
-         if (maxnum > 0 && maxnum == num)
+         MSymbol sym = MPLIST_SYMBOL (p);
+
+         if (sym == family)
            break;
+         if (strcmp (MSYMBOL_NAME (sym), fam) > 0)
+           {
+             mplist_push (p, Msymbol, family);
+             break;
+           }
        }
-      if (maxnum > 0 && maxnum == num)
-       break;
+      if (MPLIST_TAIL_P (p))
+       mplist_push (p, Msymbol, family);
     }
+  if (font_names)
+    XFreeFontNames (font_names);
+}
 
-  MDEBUG_PRINT1 (" %d found\n", num);
-  return num;
+static int 
+xfont_check_capability (MRealizedFont *rfont, MSymbol capability)
+{
+  /* Currently X font driver doesn't support any capability.  */
+  return -1;
 }
 
 \f
@@ -981,10 +1027,10 @@ xfont_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum)
 typedef struct
 {
   M17NObject control;
+  FT_Face ft_face;             /* This must be the 2nd member. */
   Display *display;
   XftFont *font_aa;
   XftFont *font_no_aa;
-  FT_Face ft_face;
   /* Pointer to MRealizedFontFT */
   void *info;
 } MRealizedFontXft;
@@ -998,10 +1044,13 @@ static unsigned xft_encode_char (MFrame *frame, MFont *font, MFont *spec,
 static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int);
 static void xft_render (MDrawWindow, int, int, MGlyphString *,
                        MGlyph *, MGlyph *, int, MDrawRegion);
+static int xft_check_capability (MRealizedFont *rfont, MSymbol capability);
 
-MFontDriver xft_driver =
+static MFontDriver xft_driver =
   { NULL, xft_open,
-    xft_find_metric, xft_has_char, xft_encode_char, xft_render, NULL };
+    xft_find_metric, xft_has_char, xft_encode_char, xft_render, NULL, NULL,
+    xft_check_capability
+  };
 
 static void
 close_xft (void *object)
@@ -1041,8 +1090,21 @@ xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
   FT_Face ft_face;
   MRealizedFontXft *rfont_xft;
   FcBool anti_alias = FRAME_DEVICE (frame)->depth > 1 ? FcTrue : FcFalse;
-  double size = font->size ? font->size : spec->size;
+  int size;
   XftFont *xft_font;
+  int ascent, descent, max_advance, average_width, baseline_offset;
+
+  if (font->size)
+    /* non-scalable font */
+    size = font->size;
+  else if (spec->size)
+    {
+      int ratio = mfont_resize_ratio (font);
+
+      size = ratio == 100 ? spec->size : spec->size * ratio / 100;
+    }
+  else
+    size = 120;
 
   if (rfont)
     {
@@ -1064,6 +1126,11 @@ xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
   rfont = (mfont__ft_driver.open) (frame, font, spec, rfont);
   if (! rfont)
     return NULL;
+  ascent = rfont->ascent;
+  descent = rfont->descent;
+  max_advance = rfont->max_advance;
+  average_width = rfont->average_width;
+  baseline_offset = rfont->baseline_offset;
   spec = &rfont->spec;
   ft_face = rfont->fontp;
   xft_font = xft_open_font (display, font->file, size / 10, anti_alias);
@@ -1080,13 +1147,16 @@ xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont)
   M17N_OBJECT_REF (rfont->info);
   MSTRUCT_CALLOC (rfont, MERROR_FONT_X);
   rfont->spec = *spec;
+  rfont->spec.size = size;
   rfont->frame = frame;
   rfont->font = font;
   rfont->driver = &xft_driver;
   rfont->info = rfont_xft;
-  rfont->ascent = ft_face->size->metrics.ascender >> 6;
-  rfont->descent = - ft_face->size->metrics.descender >> 6;
-  rfont->max_advance = ft_face->size->metrics.max_advance >> 6;
+  rfont->ascent = ascent;
+  rfont->descent = descent;
+  rfont->max_advance = max_advance;
+  rfont->average_width = average_width;
+  rfont->baseline_offset = baseline_offset;
   rfont->fontp = xft_font;
   rfont->next = MPLIST_VAL (frame->realized_font_list);
   MPLIST_VAL (frame->realized_font_list) = rfont;
@@ -1222,6 +1292,7 @@ xft_render (MDrawWindow win, int x, int y,
   XftDrawChange (xft_draw, (Drawable) win);
   XftDrawSetClip (xft_draw, (Region) region);
       
+  y -= rfont->baseline_offset;
   glyphs = alloca (sizeof (FT_UInt) * (to - from));
   for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
     {
@@ -1242,6 +1313,18 @@ xft_render (MDrawWindow win, int x, int y,
     XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs);
 }
 
+static int
+xft_check_capability (MRealizedFont *rfont, MSymbol capability)
+{
+  MRealizedFontXft *rfont_xft = rfont->info;
+  int result;
+      
+  rfont->info = rfont_xft->info;
+  result = mfont__ft_driver.check_capability (rfont, capability);
+  rfont->info = rfont_xft;
+  return result;
+}
+
 #endif /* HAVE_XFT2 */
 
 \f
@@ -1688,6 +1771,12 @@ mwin__create_window (MFrame *frame, MDrawWindow parent)
 static void
 mwin__destroy_window (MFrame *frame, MDrawWindow win)
 {
+#ifdef HAVE_XFT2
+  XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw;
+
+  if (XftDrawDrawable (xft_draw) == (Drawable) win)
+    XftDrawChange (xft_draw, FRAME_DEVICE (frame)->drawable);
+#endif /* HAVE_XFT2 */
   XDestroyWindow (FRAME_DISPLAY (frame), (Window) win);
 }
 
@@ -1837,7 +1926,7 @@ mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
   int len;
   char buf[512];
   KeySym keysym;
-  MSymbol key = Mnil;
+  MSymbol key;
 
   *modifiers = 0;
   if (event->xany.type != KeyPress
@@ -1847,26 +1936,17 @@ mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
   len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL);
   if (len > 1)
     return Mnil;
-  if (len == 1)
+  if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
+    return Mnil;
+  if (len == 1 && keysym >= XK_space && keysym <= XK_asciitilde)
     {
       int c = keysym;
 
-      if (c < XK_space || c > XK_asciitilde)
-       c = buf[0];
-      if ((c == ' ' || c == 127) && ((XKeyEvent *) event)->state & ShiftMask)
-       *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
-      if (((XKeyEvent *) event)->state & ControlMask)
-       {
-         if (c >= 'a' && c <= 'z')
-           c += 'A' - 'a';
-         if (c >= ' ' && c < 127)
-           *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
-       }
       key = minput__char_to_key (c);
+      if (c == ' ' && ((XKeyEvent *) event)->state & ShiftMask)
+       *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
     }
-  else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R)
-    return Mnil;
-  if (key == Mnil)
+  else
     {
       char *str = XKeysymToString (keysym);
 
@@ -1875,9 +1955,9 @@ mwin__parse_event (MFrame *frame, void *arg, int *modifiers)
       key = msymbol (str);
       if (((XKeyEvent *) event)->state & ShiftMask)
        *modifiers |= MINPUT_KEY_SHIFT_MODIFIER;
-      if (((XKeyEvent *) event)->state & ControlMask)
-       *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
     }
+  if (((XKeyEvent *) event)->state & ControlMask)
+    *modifiers |= MINPUT_KEY_CONTROL_MODIFIER;
   if (((XKeyEvent *) event)->state & disp_info->meta_mask)
     *modifiers |= MINPUT_KEY_META_MODIFIER;
   if (((XKeyEvent *) event)->state & disp_info->alt_mask)
@@ -1950,6 +2030,7 @@ device_init ()
 #ifdef HAVE_XFT2
   xft_driver.select = mfont__ft_driver.select;
   xft_driver.list = mfont__ft_driver.list;
+  xft_driver.list_family_names = mfont__ft_driver.list_family_names;
 #endif
 
   Mxim = msymbol ("xim");
@@ -2106,6 +2187,10 @@ device_open (MFrame *frame, MPlist *param)
       disp_info->auto_display = auto_display;
       disp_info->font_list = mplist ();
       find_modifier_bits (disp_info);
+      disp_info->MULE_BASELINE_OFFSET
+       = XInternAtom (display, "_MULE_BASELINE_OFFSET", False);
+      disp_info->AVERAGE_WIDTH
+       = XInternAtom (display, "AVERAGE_WIDTH", False);
       mplist_add (display_info_list, Mt, disp_info);
     }