]> code.delx.au - gnu-emacs/blobdiff - src/xterm.c
(Fchar_charset): New optional arg restriction.
[gnu-emacs] / src / xterm.c
index 147e492e7d5087b3b80fa25744522f9c6924b456..00064758cdcc02556efe1216b1e7be3600aeec03 100644 (file)
@@ -1,14 +1,14 @@
 /* X Communication module for terminals which understand the X protocol.
    Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-                 2002, 2003, 2004, 2005, 2006, 2007, 2008
+                 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
                  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,9 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* New display code by Gerd Moellmann <gerd@gnu.org>.  */
 /* Xt features made by Fred Pierresteguy.  */
@@ -70,7 +68,6 @@ Boston, MA 02110-1301, USA.  */
 #include "charset.h"
 #include "character.h"
 #include "coding.h"
-#include "ccl.h"
 #include "frame.h"
 #include "dispextern.h"
 #include "fontset.h"
@@ -86,6 +83,8 @@ Boston, MA 02110-1301, USA.  */
 #include "process.h"
 #include "atimer.h"
 #include "keymap.h"
+#include "font.h"
+#include "fontset.h"
 
 #ifdef USE_X_TOOLKIT
 #include <X11/Shell.h>
@@ -102,10 +101,6 @@ Boston, MA 02110-1301, USA.  */
 #include "gtkutil.h"
 #endif
 
-#ifdef USE_FONT_BACKEND
-#include "font.h"
-#endif /* USE_FONT_BACKEND */
-
 #ifdef USE_LUCID
 extern int xlwmenu_window_p P_ ((Widget w, Window window));
 extern void xlwmenu_redisplay P_ ((Widget));
@@ -340,8 +335,6 @@ static void x_update_window_end P_ ((struct window *, int, int));
 static int x_io_error_quitter P_ ((Display *));
 static struct terminal *x_create_terminal P_ ((struct x_display_info *));
 void x_delete_terminal P_ ((struct terminal *));
-static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
-static int x_compute_min_glyph_bounds P_ ((struct frame *));
 static void x_update_end P_ ((struct frame *));
 static void XTframe_up_to_date P_ ((struct frame *));
 static void XTset_terminal_modes P_ ((struct terminal *));
@@ -465,6 +458,89 @@ x_display_info_for_display (dpy)
   return 0;
 }
 
+#define OPAQUE  0xffffffff
+#define OPACITY "_NET_WM_WINDOW_OPACITY"
+
+void
+x_set_frame_alpha (f)
+     struct frame *f;
+{
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  Display *dpy = FRAME_X_DISPLAY (f);
+  Window win = FRAME_OUTER_WINDOW (f);
+  double alpha = 1.0;
+  double alpha_min = 1.0;
+  unsigned long opac;
+
+  if (FRAME_X_DISPLAY_INFO (f)->root_window != FRAME_X_OUTPUT (f)->parent_desc)
+    /* Since the WM decoration lies under the FRAME_OUTER_WINDOW,
+       we must treat the former instead of the latter. */
+    win = FRAME_X_OUTPUT(f)->parent_desc;
+
+  if (dpyinfo->x_highlight_frame == f)
+    alpha = f->alpha[0];
+  else
+    alpha = f->alpha[1];
+
+  if (FLOATP (Vframe_alpha_lower_limit))
+    alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
+  else if (INTEGERP (Vframe_alpha_lower_limit))
+    alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
+
+  if (alpha < 0.0)
+    return;
+  else if (alpha > 1.0)
+    alpha = 1.0;
+  else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0)
+    alpha = alpha_min;
+
+  opac = alpha * OPAQUE;
+
+  /* return unless necessary */
+  {
+    unsigned char *data;
+    Atom actual;
+    int rc, format;
+    unsigned long n, left;
+
+    x_catch_errors (dpy);
+    rc = XGetWindowProperty(dpy, win, XInternAtom(dpy, OPACITY, False),
+                           0L, 1L, False, XA_CARDINAL,
+                           &actual, &format, &n, &left,
+                           &data);
+
+    if (rc == Success && actual != None)
+      if (*(unsigned long *)data == opac)
+       {
+         XFree ((void *) data);
+         x_uncatch_errors ();
+         return;
+       }
+      else
+       XFree ((void *) data);
+    x_uncatch_errors ();
+  }
+
+  x_catch_errors (dpy);
+  XChangeProperty (dpy, win, XInternAtom (dpy, OPACITY, False),
+                  XA_CARDINAL, 32, PropModeReplace,
+                  (unsigned char *) &opac, 1L);
+  x_uncatch_errors ();
+}
+
+int
+x_display_pixel_height (dpyinfo)
+     struct x_display_info *dpyinfo;
+{
+  return HeightOfScreen (dpyinfo->screen);
+}
+
+int
+x_display_pixel_width (dpyinfo)
+     struct x_display_info *dpyinfo;
+{
+  return WidthOfScreen (dpyinfo->screen);
+}
 
 \f
 /***********************************************************************
@@ -870,155 +946,6 @@ XTreset_terminal_modes (struct terminal *terminal)
 {
 }
 
-
-\f
-/***********************************************************************
-                          Display Iterator
- ***********************************************************************/
-
-/* Function prototypes of this page.  */
-
-static int x_encode_char P_ ((int, XChar2b *, struct font_info *,
-                             struct charset *, int *));
-
-
-/* Get metrics of character CHAR2B in FONT.  Value is null if CHAR2B
-   is not contained in the font.  */
-
-static XCharStruct *
-x_per_char_metric (font, char2b, font_type)
-     XFontStruct *font;
-     XChar2b *char2b;
-     int font_type;  /* unused on X */
-{
-  /* The result metric information.  */
-  XCharStruct *pcm = NULL;
-
-  xassert (font && char2b);
-
-  if (font->per_char != NULL)
-    {
-      if (font->min_byte1 == 0 && font->max_byte1 == 0)
-       {
-         /* min_char_or_byte2 specifies the linear character index
-            corresponding to the first element of the per_char array,
-            max_char_or_byte2 is the index of the last character.  A
-            character with non-zero CHAR2B->byte1 is not in the font.
-            A character with byte2 less than min_char_or_byte2 or
-            greater max_char_or_byte2 is not in the font.  */
-         if (char2b->byte1 == 0
-             && char2b->byte2 >= font->min_char_or_byte2
-             && char2b->byte2 <= font->max_char_or_byte2)
-           pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
-       }
-      else
-       {
-         /* If either min_byte1 or max_byte1 are nonzero, both
-            min_char_or_byte2 and max_char_or_byte2 are less than
-            256, and the 2-byte character index values corresponding
-            to the per_char array element N (counting from 0) are:
-
-            byte1 = N/D + min_byte1
-            byte2 = N\D + min_char_or_byte2
-
-            where:
-
-            D = max_char_or_byte2 - min_char_or_byte2 + 1
-            / = integer division
-            \ = integer modulus  */
-         if (char2b->byte1 >= font->min_byte1
-             && char2b->byte1 <= font->max_byte1
-             && char2b->byte2 >= font->min_char_or_byte2
-             && char2b->byte2 <= font->max_char_or_byte2)
-           {
-             pcm = (font->per_char
-                    + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
-                       * (char2b->byte1 - font->min_byte1))
-                    + (char2b->byte2 - font->min_char_or_byte2));
-           }
-       }
-    }
-  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.  */
-      if (char2b->byte2 >= font->min_char_or_byte2
-         && char2b->byte2 <= font->max_char_or_byte2)
-       pcm = &font->max_bounds;
-    }
-
-  return ((pcm == NULL
-          || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
-         ? NULL : pcm);
-}
-
-
-/* Encode CHAR2B using encoding information from FONT_INFO.  CHAR2B is
-   the two-byte form of C.  Encoding is returned in *CHAR2B.  */
-
-static int
-x_encode_char (c, char2b, font_info, charset, two_byte_p)
-     int c;
-     XChar2b *char2b;
-     struct font_info *font_info;
-     struct charset *charset;
-     int *two_byte_p;
-{
-  XFontStruct *font = font_info->font;
-
-  /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
-     This may be either a program in a special encoder language or a
-     fixed encoding.  */
-  if (font_info->font_encoder)
-    {
-      /* It's a program.  */
-      struct ccl_program *ccl = font_info->font_encoder;
-
-      check_ccl_update (ccl);
-      if (CHARSET_DIMENSION (charset) == 1)
-       {
-         ccl->reg[0] = CHARSET_ID (charset);
-         ccl->reg[1] = char2b->byte2;
-         ccl->reg[2] = -1;
-       }
-      else
-       {
-         ccl->reg[0] = CHARSET_ID (charset);
-         ccl->reg[1] = char2b->byte1;
-         ccl->reg[2] = char2b->byte2;
-       }
-
-      ccl_driver (ccl, NULL, NULL, 0, 0, Qnil);
-
-      /* We assume that MSBs are appropriately set/reset by CCL
-        program.  */
-      if (font->max_byte1 == 0)        /* 1-byte font */
-       STORE_XCHAR2B (char2b, 0, ccl->reg[1]);
-      else
-       STORE_XCHAR2B (char2b, ccl->reg[1], ccl->reg[2]);
-    }
-  else if (font_info->encoding_type)
-    {
-      /* Fixed encoding scheme.  See fontset.h for the meaning of the
-        encoding numbers.  */
-      unsigned char enc = font_info->encoding_type;
-
-      if ((enc == 1 || enc == 2)
-         && CHARSET_DIMENSION (charset) == 2)
-       char2b->byte1 |= 0x80;
-
-      if (enc == 1 || enc == 3)
-       char2b->byte2 |= 0x80;
-    }
-
-  if (two_byte_p)
-    *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
-
-  return FONT_TYPE_UNKNOWN;
-}
-
-
 \f
 /***********************************************************************
                            Glyph display
@@ -1056,7 +983,7 @@ static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
                                 int, int, int, XRectangle *));
 
 #if GLYPH_DEBUG
-static void x_check_font P_ ((struct frame *, XFontStruct *));
+static void x_check_font P_ ((struct frame *, struct font *));
 #endif
 
 
@@ -1098,14 +1025,8 @@ x_set_cursor_gc (s)
        }
 
       IF_DEBUG (x_check_font (s->f, s->font));
-#ifdef USE_FONT_BACKEND
-      if (enable_font_backend)
-       xgcv.font = FRAME_X_DISPLAY_INFO (s->f)->font->fid;
-      else
-#endif
-      xgcv.font = s->font->fid;
       xgcv.graphics_exposures = False;
-      mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
+      mask = GCForeground | GCBackground | GCGraphicsExposures;
 
       if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
        XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
@@ -1141,32 +1062,19 @@ x_set_mouse_face_gc (s)
   s->face = FACE_FROM_ID (s->f, face_id);
   PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
 
-  /* If font in this face is same as S->font, use it.  */
   if (s->font == s->face->font)
     s->gc = s->face->gc;
-#ifdef USE_FONT_BACKEND
-  else if (enable_font_backend)
-    /* No need of setting a font for s->gc.  */
-    s->gc = s->face->gc;
-#endif /* USE_FONT_BACKEND */
   else
     {
       /* Otherwise construct scratch_cursor_gc with values from FACE
-        but font FONT.  */
+        except for FONT.  */
       XGCValues xgcv;
       unsigned long mask;
 
       xgcv.background = s->face->background;
       xgcv.foreground = s->face->foreground;
-      IF_DEBUG (x_check_font (s->f, s->font));
-#ifdef USE_FONT_BACKEND
-      if (enable_font_backend)
-       xgcv.font = FRAME_X_DISPLAY_INFO (s->f)->font->fid;
-      else
-#endif
-      xgcv.font = s->font->fid;
       xgcv.graphics_exposures = False;
-      mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
+      mask = GCForeground | GCBackground | GCGraphicsExposures;
 
       if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
        XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
@@ -1176,8 +1084,8 @@ x_set_mouse_face_gc (s)
          = XCreateGC (s->display, s->window, mask, &xgcv);
 
       s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
-    }
 
+    }
   xassert (s->gc != 0);
 }
 
@@ -1248,18 +1156,12 @@ static INLINE void
 x_set_glyph_string_clipping (s)
      struct glyph_string *s;
 {
-#ifdef USE_FONT_BACKEND
   XRectangle *r = s->clip;
-#else
-  XRectangle r[2];
-#endif
   int n = get_glyph_string_clip_rects (s, r, 2);
 
   if (n > 0)
     XSetClipRectangles (s->display, s->gc, 0, 0, r, n, Unsorted);
-#ifdef USE_FONT_BACKEND
   s->num_clips = n;
-#endif
 }
 
 
@@ -1273,29 +1175,12 @@ x_set_glyph_string_clipping_exactly (src, dst)
 {
   XRectangle r;
 
-#ifdef USE_FONT_BACKEND
-  if (enable_font_backend)
-    {
-      r.x = src->x;
-      r.width = src->width;
-      r.y = src->y;
-      r.height = src->height;
-      dst->clip[0] = r;
-      dst->num_clips = 1;
-    }
-  else
-    {
-#endif /* USE_FONT_BACKEND */
-  struct glyph_string *clip_head = src->clip_head;
-  struct glyph_string *clip_tail = src->clip_tail;
-
-  /* This foces clipping just this glyph string.  */
-  src->clip_head = src->clip_tail = src;
-  get_glyph_string_clip_rect (src, &r);
-  src->clip_head = clip_head, src->clip_tail = clip_tail;
-#ifdef USE_FONT_BACKEND
-    }
-#endif /* USE_FONT_BACKEND */
+  r.x = src->x;
+  r.width = src->width;
+  r.y = src->y;
+  r.height = src->height;
+  dst->clip[0] = r;
+  dst->num_clips = 1;
   XSetClipRectangles (dst->display, dst->gc, 0, 0, &r, 1, Unsorted);
 }
 
@@ -1310,30 +1195,17 @@ x_compute_glyph_string_overhangs (s)
   if (s->cmp == NULL
       && s->first_glyph->type == CHAR_GLYPH)
     {
-      XCharStruct cs;
-      int direction, font_ascent, font_descent;
-
-#ifdef USE_FONT_BACKEND
-      if (enable_font_backend)
-       {
-         unsigned *code = alloca (sizeof (unsigned) * s->nchars);
-         struct font *font = (struct font *) s->font_info;
-         struct font_metrics metrics;
-         int i;
+      unsigned *code = alloca (sizeof (unsigned) * s->nchars);
+      struct font *font = s->font;
+      struct font_metrics metrics;
+      int i;
 
-         for (i = 0; i < s->nchars; i++)
-           code[i] = (s->char2b[i].byte1 << 8) | s->char2b[i].byte2;
-         font->driver->text_extents (font, code, s->nchars, &metrics);
-         cs.rbearing = metrics.rbearing;
-         cs.lbearing = metrics.lbearing;
-         cs.width = metrics.width;
-       }
-      else
-#endif /* USE_FONT_BACKEND */
-      XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
-                     &font_ascent, &font_descent, &cs);
-      s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
-      s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
+      for (i = 0; i < s->nchars; i++)
+       code[i] = (s->char2b[i].byte1 << 8) | s->char2b[i].byte2;
+      font->driver->text_extents (font, code, s->nchars, &metrics);
+      s->right_overhang = (metrics.rbearing > metrics.width
+                          ? metrics.rbearing - metrics.width : 0);
+      s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
     }
   else if (s->cmp)
     {
@@ -1429,15 +1301,14 @@ x_draw_glyph_string_foreground (s)
          x += g->pixel_width;
        }
     }
-#ifdef USE_FONT_BACKEND
-  else if (enable_font_backend)
+  else
     {
-      int boff = s->font_info->baseline_offset;
-      struct font *font = (struct font *) s->font_info;
+      struct font *font = s->font;
+      int boff = font->baseline_offset;
       int y;
 
-      if (s->font_info->vertical_centering)
-       boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
+      if (font->vertical_centering)
+       boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
 
       y = s->ybase - boff;
       if (s->for_overlaps
@@ -1448,58 +1319,6 @@ x_draw_glyph_string_foreground (s)
       if (s->face->overstrike)
        font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
     }
-#endif /* USE_FONT_BACKEND */
-  else
-    {
-      char *char1b = (char *) s->char2b;
-      int boff = s->font_info->baseline_offset;
-
-      if (s->font_info->vertical_centering)
-       boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
-
-      /* If we can use 8-bit functions, condense S->char2b.  */
-      if (!s->two_byte_p)
-       for (i = 0; i < s->nchars; ++i)
-         char1b[i] = s->char2b[i].byte2;
-
-      /* Draw text with XDrawString if background has already been
-        filled.  Otherwise, use XDrawImageString.  (Note that
-        XDrawImageString is usually faster than XDrawString.)  Always
-        use XDrawImageString when drawing the cursor so that there is
-        no chance that characters under a box cursor are invisible.  */
-      if (s->for_overlaps
-         || (s->background_filled_p && s->hl != DRAW_CURSOR))
-       {
-         /* Draw characters with 16-bit or 8-bit functions.  */
-         if (s->two_byte_p)
-           XDrawString16 (s->display, s->window, s->gc, x,
-                          s->ybase - boff, s->char2b, s->nchars);
-         else
-           XDrawString (s->display, s->window, s->gc, x,
-                        s->ybase - boff, char1b, s->nchars);
-       }
-      else
-       {
-         if (s->two_byte_p)
-           XDrawImageString16 (s->display, s->window, s->gc, x,
-                               s->ybase - boff, s->char2b, s->nchars);
-         else
-           XDrawImageString (s->display, s->window, s->gc, x,
-                             s->ybase - boff, char1b, s->nchars);
-       }
-
-      if (s->face->overstrike)
-       {
-         /* For overstriking (to simulate bold-face), draw the
-            characters again shifted to the right by one pixel.  */
-         if (s->two_byte_p)
-           XDrawString16 (s->display, s->window, s->gc, x + 1,
-                          s->ybase - boff, s->char2b, s->nchars);
-         else
-           XDrawString (s->display, s->window, s->gc, x + 1,
-                        s->ybase - boff, char1b, s->nchars);
-       }
-    }
 }
 
 /* Draw the foreground of composite glyph string S.  */
@@ -1509,6 +1328,7 @@ x_draw_composite_glyph_string_foreground (s)
      struct glyph_string *s;
 {
   int i, j, x;
+  struct font *font = s->font;
 
   /* If first glyph of S has a left box line, start drawing the text
      of S to the right of that box line.  */
@@ -1518,91 +1338,66 @@ x_draw_composite_glyph_string_foreground (s)
   else
     x = s->x;
 
-  /* S is a glyph string for a composition.  S->gidx is the index of
-     the first character drawn for glyphs of this composition.
-     S->gidx == 0 means we are drawing the very first character of
+  /* S is a glyph string for a composition.  S->cmp_from is the index
+     of the first character drawn for glyphs of this composition.
+     S->cmp_from == 0 means we are drawing the very first character of
      this composition.  */
 
   /* Draw a rectangle for the composition if the font for the very
      first character of the composition could not be loaded.  */
   if (s->font_not_found_p)
     {
-      if (s->gidx == 0)
+      if (s->cmp_from == 0)
        XDrawRectangle (s->display, s->window, s->gc, x, s->y,
                        s->width - 1, s->height - 1);
     }
-#ifdef USE_FONT_BACKEND
-  else if (enable_font_backend)
+  else if (! s->first_glyph->u.cmp.automatic)
+    {
+      int y = s->ybase;
+
+      for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
+       if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
+         {
+           int xx = x + s->cmp->offsets[j * 2];
+           int yy = y - s->cmp->offsets[j * 2 + 1];
+
+           font->driver->draw (s, j, j + 1, xx, yy, 0);
+           if (s->face->overstrike)
+             font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
+         }
+    }
+  else
     {
-      struct font *font = (struct font *) s->font_info;
+      Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
+      Lisp_Object glyph;
       int y = s->ybase;
       int width = 0;
 
-      if (s->cmp->method == COMPOSITION_WITH_GLYPH_STRING)
+      for (i = j = s->cmp_from; i < s->cmp_to; i++)
        {
-         Lisp_Object gstring = AREF (XHASH_TABLE (composition_hash_table)
-                                     ->key_and_value,
-                                     s->cmp->hash_index * 2);
-         int from;
-
-         for (i = from = 0; i < s->nchars; i++)
+         glyph = LGSTRING_GLYPH (gstring, i);
+         if (NILP (LGLYPH_ADJUSTMENT (glyph)))
+           width += LGLYPH_WIDTH (glyph);
+         else
            {
-             Lisp_Object g = LGSTRING_GLYPH (gstring, i);
-             Lisp_Object adjustment = LGLYPH_ADJUSTMENT (g);
              int xoff, yoff, wadjust;
 
-             if (! VECTORP (adjustment))
-               {
-                 width += LGLYPH_WIDTH (g);
-                 continue;
-               }
-             if (from < i)
+             if (j < i)
                {
-                 font->driver->draw (s, from, i, x, y, 0);
+                 font->driver->draw (s, j, i, x, y, 0);
                  x += width;
                }
-             xoff = XINT (AREF (adjustment, 0));
-             yoff = XINT (AREF (adjustment, 1));
-             wadjust = XINT (AREF (adjustment, 2));
-
+             xoff = LGLYPH_XOFF (glyph);
+             yoff = LGLYPH_YOFF (glyph);
+             wadjust = LGLYPH_WADJUST (glyph);
              font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
              x += wadjust;
-             from = i + 1;
+             j = i + 1;
              width = 0;
            }
-         if (from < i)
-           font->driver->draw (s, from, i, x, y, 0);
-       }
-      else
-       {
-         for (i = 0, j = s->gidx; i < s->nchars; i++, j++)
-           if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
-             {
-               int xx = x + s->cmp->offsets[j * 2];
-               int yy = y - s->cmp->offsets[j * 2 + 1];
-
-               font->driver->draw (s, j, j + 1, xx, yy, 0);
-               if (s->face->overstrike)
-                 font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
-             }
        }
-    }
-#endif /* USE_FONT_BACKEND */
-  else
-    {
-      for (i = 0, j = s->gidx; i < s->nchars; i++, j++)
-       if (s->face)
-         {
-           XDrawString16 (s->display, s->window, s->gc,
-                          x + s->cmp->offsets[j * 2],
-                          s->ybase - s->cmp->offsets[j * 2 + 1],
-                          s->char2b + j, 1);
-           if (s->face->overstrike)
-             XDrawString16 (s->display, s->window, s->gc,
-                            x + s->cmp->offsets[j * 2] + 1,
-                            s->ybase - s->cmp->offsets[j * 2 + 1],
-                            s->char2b + j, 1);
-         }
+      if (j < i)
+       font->driver->draw (s, j, i, x, y, 0);
     }
 }
 
@@ -2858,16 +2653,18 @@ x_draw_glyph_string (s)
       int width;
       struct glyph_string *next;
 
-      for (width = 0, next = s->next; next;
+      for (width = 0, next = s->next;
+          next && width < s->right_overhang;
           width += next->width, next = next->next)
        if (next->first_glyph->type != IMAGE_GLYPH)
          {
            x_set_glyph_string_gc (next);
            x_set_glyph_string_clipping (next);
-           x_draw_glyph_string_background (next, 1);
-#ifdef USE_FONT_BACKEND
+           if (next->first_glyph->type == STRETCH_GLYPH)
+             x_draw_stretch_glyph_string (next);
+           else
+             x_draw_glyph_string_background (next, 1);
            next->num_clips = 0;
-#endif /* USE_FONT_BACKEND */
          }
     }
 
@@ -2888,8 +2685,10 @@ x_draw_glyph_string (s)
       x_set_glyph_string_clipping (s);
       relief_drawn_p = 1;
     }
-  else if ((s->prev && s->prev->hl != s->hl && s->left_overhang)
-          || (s->next && s->next->hl != s->hl && s->right_overhang))
+  else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
+          && !s->clip_tail
+          && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
+              || (s->next && s->next->hl != s->hl && s->right_overhang)))
     /* We must clip just this glyph.  left_overhang part has already
        drawn when s->prev was drawn, and right_overhang part will be
        drawn later when s->next is drawn. */
@@ -2916,7 +2715,8 @@ x_draw_glyph_string (s)
       break;
 
     case COMPOSITE_GLYPH:
-      if (s->for_overlaps || s->gidx > 0)
+      if (s->for_overlaps || (s->cmp_from > 0
+                             && ! s->first_glyph->u.cmp.automatic))
        s->background_filled_p = 1;
       else
        x_draw_glyph_string_background (s, 1);
@@ -2932,33 +2732,25 @@ x_draw_glyph_string (s)
       /* Draw underline.  */
       if (s->face->underline_p)
        {
-         unsigned long tem, h;
+         unsigned long thickness, position;
          int y;
 
-         /* Get the underline thickness.  Default is 1 pixel.  */
-#ifdef USE_FONT_BACKEND
-         if (enable_font_backend)
-           /* In the future, we must use information of font.  */
-           h = 1;
-         else
-#endif /* USE_FONT_BACKEND */
-         if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
-           h = 1;
-
-#ifdef USE_FONT_BACKEND
-         if (enable_font_backend)
+         if (s->prev && s->prev->face->underline_p)
            {
-             if (s->face->font)
-               /* In the future, we must use information of font.  */
-               y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
-             else
-               y = s->y + s->height - h;
+             /* We use the same underline style as the previous one.  */
+             thickness = s->prev->underline_thickness;
+             position = s->prev->underline_position;
            }
          else
-#endif
            {
-             y = s->y + s->height - h;
-             if (!x_underline_at_descent_line)
+             /* Get the underline thickness.  Default is 1 pixel.  */
+             if (s->font && s->font->underline_thickness > 0)
+               thickness = s->font->underline_thickness;
+             else
+               thickness = 1;
+             if (x_underline_at_descent_line)
+               position = (s->height - thickness) - (s->ybase - s->y);
+             else
                {
                  /* Get the underline position.  This is the recommended
                     vertical offset in pixels from the baseline to the top of
@@ -2969,23 +2761,34 @@ x_draw_glyph_string (s)
                     ROUND(x) = floor (x + 0.5)  */
 
                  if (x_use_underline_position_properties
-                     && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
-                   y = s->ybase + (long) tem;
-                 else if (s->face->font)
-                   y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
+                     && s->font && s->font->underline_position >= 0)
+                   position = s->font->underline_position;
+                 else if (s->font)
+                   position = (s->font->descent + 1) / 2;
+                 else
+                   position = underline_minimum_offset;
                }
+             position = max (position, underline_minimum_offset);
            }
-
+         /* Check the sanity of thickness and position.  We should
+            avoid drawing underline out of the current line area.  */
+         if (s->y + s->height <= s->ybase + position)
+           position = (s->height - 1) - (s->ybase - s->y);
+         if (s->y + s->height < s->ybase + position + thickness)
+           thickness = (s->y + s->height) - (s->ybase + position);
+         s->underline_thickness = thickness;
+         s->underline_position = position;
+         y = s->ybase + position;
          if (s->face->underline_defaulted_p)
            XFillRectangle (s->display, s->window, s->gc,
-                           s->x, y, s->background_width, h);
+                           s->x, y, s->background_width, thickness);
          else
            {
              XGCValues xgcv;
              XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
              XSetForeground (s->display, s->gc, s->face->underline_color);
              XFillRectangle (s->display, s->window, s->gc,
-                             s->x, y, s->background_width, h);
+                             s->x, y, s->background_width, thickness);
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
@@ -3054,9 +2857,7 @@ x_draw_glyph_string (s)
                  x_draw_composite_glyph_string_foreground (prev);
                XSetClipMask (prev->display, prev->gc, None);
                prev->hl = save;
-#ifdef USE_FONT_BACKEND
                prev->num_clips = 0;
-#endif /* USE_FONT_BACKEND */
              }
        }
 
@@ -3081,18 +2882,14 @@ x_draw_glyph_string (s)
                  x_draw_composite_glyph_string_foreground (next);
                XSetClipMask (next->display, next->gc, None);
                next->hl = save;
-#ifdef USE_FONT_BACKEND
                next->num_clips = 0;
-#endif /* USE_FONT_BACKEND */
              }
        }
     }
 
   /* Reset clipping.  */
   XSetClipMask (s->display, s->gc, None);
-#ifdef USE_FONT_BACKEND
   s->num_clips = 0;
-#endif /* USE_FONT_BACKEND */
 }
 
 /* Shift display to make room for inserted glyphs.   */
@@ -3468,6 +3265,7 @@ frame_highlight (f)
                    f->output_data.x->border_pixel);
   UNBLOCK_INPUT;
   x_update_cursor (f, 1);
+  x_set_frame_alpha (f);
 }
 
 static void
@@ -3483,6 +3281,7 @@ frame_unhighlight (f)
                          f->output_data.x->border_tile);
   UNBLOCK_INPUT;
   x_update_cursor (f, 1);
+  x_set_frame_alpha (f);
 }
 
 /* The focus has changed.  Update the frames as necessary to reflect
@@ -4218,7 +4017,7 @@ x_window_to_scroll_bar (display, window_id)
 
       if (! FRAME_X_P (XFRAME (frame)))
         continue;
-      
+
       /* Scan this frame's scroll bar list for a scroll bar with the
          right window ID.  */
       condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
@@ -6668,7 +6467,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
              inev.ie.code = XFASTINT (c);
              goto done_keysym;
            }
+
          /* Random non-modifier sorts of keysyms.  */
          if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
                         || keysym == XK_Delete
@@ -6931,8 +6730,9 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         if (f)
           {
 
-            /* Generate SELECT_WINDOW_EVENTs when needed.  */
-            if (!NILP (Vmouse_autoselect_window))
+            /* Generate SELECT_WINDOW_EVENTs when needed.
+               Don't let popup menus influence things (bug#1261).  */
+            if (!NILP (Vmouse_autoselect_window) && !popup_activated ())
               {
                 Lisp_Object window;
 
@@ -7175,6 +6975,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         if (
 #ifdef USE_GTK
             ! popup_activated ()
+            /* Gtk+ menus only react to the first three buttons. */
+            && event.xbutton.button < 3
             &&
 #endif
             f && event.type == ButtonPress
@@ -7329,15 +7131,23 @@ XTread_socket (terminal, expected, hold_quit)
   int count = 0;
   XEvent event;
   int event_found = 0;
+#if 0
   struct x_display_info *dpyinfo;
+#endif
 
   if (interrupt_input_blocked)
     {
       interrupt_input_pending = 1;
+#ifdef SYNC_INPUT
+      pending_signals = 1;
+#endif
       return -1;
     }
 
   interrupt_input_pending = 0;
+#ifdef SYNC_INPUT
+  pending_signals = pending_atimers;
+#endif
   BLOCK_INPUT;
 
   /* So people can tell when we have read the available input.  */
@@ -7366,9 +7176,9 @@ XTread_socket (terminal, expected, hold_quit)
   if (terminal->display_info.x == XTread_socket_fake_io_error)
     {
       XTread_socket_fake_io_error = 0;
-      x_io_error_quitter (dpyinfo->display);
+      x_io_error_quitter (terminal->display_info.x->display);
     }
-  
+
 #if 0 /* This loop is a noop now.  */
   /* Find the display we are supposed to read input for.
      It's the one communicating on descriptor SD.  */
@@ -7646,7 +7456,7 @@ x_draw_bar_cursor (w, row, width, kind)
                          WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
                          WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
                                                   row->height - width),
-                         cursor_glyph->pixel_width,
+                         min (FRAME_COLUMN_WIDTH (f), cursor_glyph->pixel_width),
                          width);
 
       XSetClipMask (dpy, gc, None);
@@ -8067,7 +7877,7 @@ x_connection_closed (dpy, error_message)
       dpyinfo->reference_count++;
       dpyinfo->terminal->reference_count++;
     }
-  
+
   /* First delete frames whose mini-buffers are on frames
      that are on the dead display.  */
   FOR_EACH_FRAME (tail, frame)
@@ -8079,7 +7889,7 @@ x_connection_closed (dpy, error_message)
          && FRAME_X_P (XFRAME (minibuf_frame))
          && ! EQ (frame, minibuf_frame)
          && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
-       Fdelete_frame (frame, Qnoelisp);
+       delete_frame (frame, Qnoelisp);
     }
 
   /* Now delete all remaining frames on the dead display.
@@ -8089,10 +7899,10 @@ x_connection_closed (dpy, error_message)
     if (FRAME_X_P (XFRAME (frame))
        && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
       {
-       /* Set this to t so that Fdelete_frame won't get confused
+       /* Set this to t so that delete_frame won't get confused
           trying to find a replacement.  */
        FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
-       Fdelete_frame (frame, Qnoelisp);
+       delete_frame (frame, Qnoelisp);
       }
 
   /* We have to close the display to inform Xt that it doesn't
@@ -8255,34 +8065,32 @@ x_io_error_quitter (display)
 \f
 /* Changing the font of the frame.  */
 
-/* Give frame F the font named FONTNAME as its default font, and
-   return the full name of that font.  FONTNAME may be a wildcard
-   pattern; in that case, we choose some font that fits the pattern.
-   The return value shows which font we chose.  */
+/* Give frame F the font FONT-OBJECT as its default font.  The return
+   value is FONT-OBJECT.  FONTSET is an ID of the fontset for the
+   frame.  If it is negative, generate a new fontset from
+   FONT-OBJECT.  */
 
 Lisp_Object
-x_new_font (f, fontname)
+x_new_font (f, font_object, fontset)
      struct frame *f;
-     register char *fontname;
+     Lisp_Object font_object;
+     int fontset;
 {
-  struct font_info *fontp
-    = FS_LOAD_FONT (f, fontname);
+  struct font *font = XFONT_OBJECT (font_object);
 
-  if (!fontp)
-    return Qnil;
-
-  if (FRAME_FONT (f) == (XFontStruct *) (fontp->font))
+  if (fontset < 0)
+    fontset = fontset_from_font (font_object);
+  FRAME_FONTSET (f) = fontset;
+  if (FRAME_FONT (f) == font)
     /* This font is already set in frame F.  There's nothing more to
        do.  */
-    return build_string (fontp->full_name);
-
-  FRAME_FONT (f) = (XFontStruct *) (fontp->font);
-  FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
-  FRAME_FONTSET (f) = -1;
+    return font_object;
 
-  FRAME_COLUMN_WIDTH (f) = fontp->average_width;
-  FRAME_SPACE_WIDTH (f) = fontp->space_width;
-  FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
+  FRAME_FONT (f) = font;
+  FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
+  FRAME_COLUMN_WIDTH (f) = font->average_width;
+  FRAME_SPACE_WIDTH (f) = font->space_width;
+  FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (font);
 
   compute_fringe_widths (f, 1);
 
@@ -8299,21 +8107,8 @@ x_new_font (f, fontname)
       FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
     }
 
-  /* Now make the frame display the given font.  */
   if (FRAME_X_WINDOW (f) != 0)
     {
-      Font fid;
-
-#ifdef USE_FONT_BACKEND
-      if (enable_font_backend)
-       fid = FRAME_X_DISPLAY_INFO (f)->font->fid;
-      else
-#endif
-      fid = FRAME_FONT (f)->fid;
-      XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc, fid);
-      XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc, fid);
-      XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc, fid);
-
       /* Don't change the size of a tip frame; there's no point in
         doing it because it's done in Fx_show_tip, and it leads to
         problems because the tip frame has no widget.  */
@@ -8321,121 +8116,18 @@ x_new_font (f, fontname)
        x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
     }
 
-  return build_string (fontp->full_name);
-}
-
-/* Give frame F the fontset named FONTSETNAME as its default fontset,
-   and return the full name of that fontset.  FONTSETNAME may be a
-   wildcard pattern; in that case, we choose some fontset that fits
-   the pattern.  FONTSETNAME may be a font name for ASCII characters;
-   in that case, we create a fontset from that font name.
-
-   The return value shows which fontset we chose.
-   If FONTSETNAME specifies the default fontset, return Qt.
-   If an ASCII font in the specified fontset can't be loaded, return
-   Qnil.  */
-
-Lisp_Object
-x_new_fontset (f, fontsetname)
-     struct frame *f;
-     Lisp_Object fontsetname;
-{
-  int fontset = fs_query_fontset (fontsetname, 0);
-  Lisp_Object result;
-
-  if (fontset > 0 && f->output_data.x->fontset == fontset)
-    /* This fontset is already set in frame F.  There's nothing more
-       to do.  */
-    return fontset_name (fontset);
-  else if (fontset == 0)
-    /* The default fontset can't be the default font.   */
-    return Qt;
-
-  if (fontset > 0)
-    result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
-  else
-    result = x_new_font (f, SDATA (fontsetname));
-
-  if (!STRINGP (result))
-    /* Can't load ASCII font.  */
-    return Qnil;
-
-  if (fontset < 0)
-    fontset = new_fontset_from_font_name (result);
-
-  /* Since x_new_font doesn't update any fontset information, do it now.  */
-  FRAME_FONTSET (f) = fontset;
-
 #ifdef HAVE_X_I18N
   if (FRAME_XIC (f)
       && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
-    xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
-#endif
-
-  return fontset_name (fontset);
-}
-
-#ifdef USE_FONT_BACKEND
-Lisp_Object
-x_new_fontset2 (f, fontset, font_object)
-     struct frame *f;
-     int fontset;
-     Lisp_Object font_object;
-{
-  struct font *font = XSAVE_VALUE (font_object)->pointer;
-
-  if (FRAME_FONT_OBJECT (f) == font)
-    /* This font is already set in frame F.  There's nothing more to
-       do.  */
-    return fontset_name (fontset);
-
-  BLOCK_INPUT;
-
-  FRAME_FONT_OBJECT (f) = font;
-  FRAME_FONT (f) = font->font.font;
-  FRAME_BASELINE_OFFSET (f) = font->font.baseline_offset;
-  FRAME_FONTSET (f) = fontset;
-
-  FRAME_COLUMN_WIDTH (f) = font->font.average_width;
-  FRAME_SPACE_WIDTH (f) = font->font.space_width;
-  FRAME_LINE_HEIGHT (f) = font->font.height;
-
-  compute_fringe_widths (f, 1);
-
-  /* Compute the scroll bar width in character columns.  */
-  if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
-    {
-      int wid = FRAME_COLUMN_WIDTH (f);
-      FRAME_CONFIG_SCROLL_BAR_COLS (f)
-       = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
-    }
-  else
-    {
-      int wid = FRAME_COLUMN_WIDTH (f);
-      FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
-    }
-
-  /* Now make the frame display the given font.  */
-  if (FRAME_X_WINDOW (f) != 0)
     {
-      /* Don't change the size of a tip frame; there's no point in
-        doing it because it's done in Fx_show_tip, and it leads to
-        problems because the tip frame has no widget.  */
-      if (NILP (tip_frame) || XFRAME (tip_frame) != f)
-       x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+      BLOCK_INPUT;
+      xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
+      UNBLOCK_INPUT;
     }
-
-#ifdef HAVE_X_I18N
-  if (FRAME_XIC (f)
-      && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
-    xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
 #endif
 
-  UNBLOCK_INPUT;
-
-  return fontset_name (fontset);
+  return font_object;
 }
-#endif /* USE_FONT_BACKEND */
 
 \f
 /***********************************************************************
@@ -8498,6 +8190,8 @@ xim_open_dpy (dpyinfo, resource_name)
 #ifdef HAVE_XIM
   if (use_xim)
     {
+      if (dpyinfo->xim)
+       XCloseIM (dpyinfo->xim);
       xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name,
                     EMACS_CLASS);
       dpyinfo->xim = xim;
@@ -8527,12 +8221,6 @@ xim_open_dpy (dpyinfo, resource_name)
 
 #ifdef HAVE_X11R6_XIM
 
-struct xim_inst_t
-{
-  struct x_display_info *dpyinfo;
-  char *resource_name;
-};
-
 /* XIM instantiate callback function, which is called whenever an XIM
    server is available.  DISPLAY is the display of the XIM.
    CLIENT_DATA contains a pointer to an xim_inst_t structure created
@@ -8596,6 +8284,7 @@ xim_initialize (dpyinfo, resource_name)
      struct x_display_info *dpyinfo;
      char *resource_name;
 {
+  dpyinfo->xim = NULL;
 #ifdef HAVE_XIM
   if (use_xim)
     {
@@ -8603,8 +8292,8 @@ xim_initialize (dpyinfo, resource_name)
       struct xim_inst_t *xim_inst;
       int len;
 
-      dpyinfo->xim = NULL;
       xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
+      dpyinfo->xim_callback_data = xim_inst;
       xim_inst->dpyinfo = dpyinfo;
       len = strlen (resource_name);
       xim_inst->resource_name = (char *) xmalloc (len + 1);
@@ -8617,14 +8306,10 @@ xim_initialize (dpyinfo, resource_name)
                                         least, hence the configure test.  */
                                      (XRegisterIMInstantiateCallback_arg6) xim_inst);
 #else /* not HAVE_X11R6_XIM */
-      dpyinfo->xim = NULL;
       xim_open_dpy (dpyinfo, resource_name);
 #endif /* not HAVE_X11R6_XIM */
-
     }
-  else
 #endif /* HAVE_XIM */
-    dpyinfo->xim = NULL;
 }
 
 
@@ -8642,7 +8327,9 @@ xim_close_dpy (dpyinfo)
        XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
                                          NULL, EMACS_CLASS,
                                          xim_instantiate_callback, NULL);
-#endif /* not HAVE_X11R6_XIM */
+      xfree (dpyinfo->xim_callback_data->resource_name);
+      xfree (dpyinfo->xim_callback_data);
+#endif /* HAVE_X11R6_XIM */
       if (dpyinfo->display)
        XCloseIM (dpyinfo->xim);
       dpyinfo->xim = NULL;
@@ -8672,8 +8359,8 @@ x_calc_absolute_position (f)
   /* Treat negative positions as relative to the leftmost bottommost
      position that fits on the screen.  */
   if (flags & XNegative)
-    f->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
-                   - FRAME_PIXEL_WIDTH (f) + f->left_pos);
+    f->left_pos = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f))
+      - FRAME_PIXEL_WIDTH (f) + f->left_pos;
 
   {
     int height = FRAME_PIXEL_HEIGHT (f);
@@ -8694,8 +8381,9 @@ x_calc_absolute_position (f)
     XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
 #endif
 
-  if (flags & YNegative)
-    f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height - height + f->top_pos);
+    if (flags & YNegative)
+      f->top_pos = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f))
+       - height + f->top_pos;
   }
 
   /* The left_pos and top_pos
@@ -9768,14 +9456,11 @@ x_free_frame_resources (f)
      commands to the X server.  */
   if (dpyinfo->display)
     {
-#ifdef USE_FONT_BACKEND
       /* We must free faces before destroying windows because some
         font-driver (e.g. xft) access a window while finishing a
         face.  */
-      if (enable_font_backend
-         && FRAME_FACE_CACHE (f))
+      if (FRAME_FACE_CACHE (f))
        free_frame_faces (f);
-#endif /* USE_FONT_BACKEND */
 
       if (f->output_data.x->icon_desc)
        XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
@@ -9849,16 +9534,11 @@ x_free_frame_resources (f)
       if (f->output_data.x->black_relief.allocated_p)
        unload_color (f, f->output_data.x->black_relief.pixel);
 
-      if (FRAME_FACE_CACHE (f))
-       free_frame_faces (f);
-
       x_free_gcs (f);
       XFlush (FRAME_X_DISPLAY (f));
     }
 
-  if (f->output_data.x->saved_menu_event)
-    xfree (f->output_data.x->saved_menu_event);
-
+  xfree (f->output_data.x->saved_menu_event);
   xfree (f->output_data.x);
   f->output_data.x = NULL;
 
@@ -9946,10 +9626,10 @@ x_wm_set_size_hint (f, flags, user_position)
 
   size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
   size_hints.height_inc = FRAME_LINE_HEIGHT (f);
-  size_hints.max_width
-    = FRAME_X_DISPLAY_INFO (f)->width - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
-  size_hints.max_height
-    = FRAME_X_DISPLAY_INFO (f)->height - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
+  size_hints.max_width = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f))
+    - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
+  size_hints.max_height = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f))
+    - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
 
   /* Calculate the base and minimum sizes.
 
@@ -10142,316 +9822,6 @@ x_wm_set_icon_position (f, icon_x, icon_y)
                                Fonts
  ***********************************************************************/
 
-/* Return a pointer to struct font_info of font FONT_IDX of frame F.  */
-
-struct font_info *
-x_get_font_info (f, font_idx)
-     FRAME_PTR f;
-     int font_idx;
-{
-  return (FRAME_X_FONT_TABLE (f) + font_idx);
-}
-
-
-/* Return a list of names of available fonts matching PATTERN on frame F.
-
-   If SIZE is > 0, it is the size (maximum bounds width) of fonts
-   to be listed.
-
-   SIZE < 0 means include auto scaled fonts.
-
-   Frame F null means we have not yet created any frame on X, and
-   consult the first display in x_display_list.  MAXNAMES sets a limit
-   on how many fonts to match.  */
-
-Lisp_Object
-x_list_fonts (f, pattern, size, maxnames)
-     struct frame *f;
-     Lisp_Object pattern;
-     int size;
-     int maxnames;
-{
-  Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
-  Lisp_Object tem, second_best;
-  struct x_display_info *dpyinfo
-    = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
-  Display *dpy = dpyinfo->display;
-  int try_XLoadQueryFont = 0;
-  int allow_auto_scaled_font = 0;
-
-  if (size < 0)
-    {
-      allow_auto_scaled_font = 1;
-      size = 0;
-    }
-
-  patterns = Fassoc (pattern, Valternate_fontname_alist);
-  if (NILP (patterns))
-    patterns = Fcons (pattern, Qnil);
-
-  if (maxnames == 1 && !size)
-    /* We can return any single font matching PATTERN.  */
-    try_XLoadQueryFont = 1;
-
-  for (; CONSP (patterns); patterns = XCDR (patterns))
-    {
-      int num_fonts;
-      char **names = NULL;
-
-      pattern = XCAR (patterns);
-      /* See if we cached the result for this particular query.
-         The cache is an alist of the form:
-        ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...)  */
-      tem = XCDR (dpyinfo->name_list_element);
-      key = Fcons (Fcons (pattern, make_number (maxnames)),
-                  allow_auto_scaled_font ? Qt : Qnil);
-      list = Fassoc (key, tem);
-      if (!NILP (list))
-       {
-         list = Fcdr_safe (list);
-         /* We have a cashed list.  Don't have to get the list again.  */
-         goto label_cached;
-       }
-
-      /* At first, put PATTERN in the cache.  */
-
-      BLOCK_INPUT;
-      x_catch_errors (dpy);
-
-      if (try_XLoadQueryFont)
-       {
-         XFontStruct *font;
-         unsigned long value;
-
-         font = XLoadQueryFont (dpy, SDATA (pattern));
-         if (x_had_errors_p (dpy))
-           {
-             /* This error is perhaps due to insufficient memory on X
-                 server.  Let's just ignore it.  */
-             font = NULL;
-             x_clear_errors (dpy);
-           }
-
-         if (font
-             && XGetFontProperty (font, XA_FONT, &value))
-           {
-             char *name = (char *) XGetAtomName (dpy, (Atom) value);
-             int len = strlen (name);
-             char *tmp;
-
-             /* If DXPC (a Differential X Protocol Compressor)
-                 Ver.3.7 is running, XGetAtomName will return null
-                 string.  We must avoid such a name.  */
-             if (len == 0)
-               try_XLoadQueryFont = 0;
-             else
-               {
-                 num_fonts = 1;
-                 names = (char **) alloca (sizeof (char *));
-                 /* Some systems only allow alloca assigned to a
-                     simple var.  */
-                 tmp = (char *) alloca (len + 1);  names[0] = tmp;
-                 bcopy (name, names[0], len + 1);
-                 XFree (name);
-               }
-           }
-         else
-           try_XLoadQueryFont = 0;
-
-         if (font)
-           XFreeFont (dpy, font);
-       }
-
-      if (!try_XLoadQueryFont)
-       {
-         /* We try at least 10 fonts because XListFonts will return
-            auto-scaled fonts at the head.  */
-          if (maxnames < 0)
-            {
-              int limit;
-
-              for (limit = 500;;)
-                {
-                  names = XListFonts (dpy, SDATA (pattern), limit, &num_fonts);
-                  if (num_fonts == limit)
-                    {
-                      BLOCK_INPUT;
-                      XFreeFontNames (names);
-                      UNBLOCK_INPUT;
-                      limit *= 2;
-                    }
-                  else
-                    break;
-                }
-            }
-          else
-            names = XListFonts (dpy, SDATA (pattern), max (maxnames, 10),
-                                &num_fonts);
-
-         if (x_had_errors_p (dpy))
-           {
-             /* This error is perhaps due to insufficient memory on X
-                 server.  Let's just ignore it.  */
-             names = NULL;
-             x_clear_errors (dpy);
-           }
-       }
-
-      x_uncatch_errors ();
-      UNBLOCK_INPUT;
-
-      if (names)
-       {
-         int i;
-
-         /* Make a list of all the fonts we got back.
-            Store that in the font cache for the display.  */
-         for (i = 0; i < num_fonts; i++)
-           {
-             int width = 0;
-             char *p = names[i];
-             int average_width = -1, resx = 0, dashes = 0;
-
-             /* Count the number of dashes in NAMES[I].  If there are
-                14 dashes, the field value following 9th dash
-                (RESOLUTION_X) is nonzero, and the field value
-                following 12th dash (AVERAGE_WIDTH) is 0, this is a
-                auto-scaled font which is usually too ugly to be used
-                for editing.  Let's ignore it.  */
-             while (*p)
-               if (*p++ == '-')
-                 {
-                   dashes++;
-                   if (dashes == 7) /* PIXEL_SIZE field */
-                     width = atoi (p);
-                   else if (dashes == 9)
-                     resx = atoi (p);
-                   else if (dashes == 12) /* AVERAGE_WIDTH field */
-                     average_width = atoi (p);
-                 }
-
-             if (allow_auto_scaled_font
-                 || dashes < 14 || average_width != 0 || resx == 0)
-               {
-                 tem = build_string (names[i]);
-                 if (NILP (Fassoc (tem, list)))
-                   {
-                     if (STRINGP (Vx_pixel_size_width_font_regexp)
-                         && ((fast_c_string_match_ignore_case
-                              (Vx_pixel_size_width_font_regexp, names[i]))
-                             >= 0))
-                       /* We can set the value of PIXEL_SIZE to the
-                         width of this font.  */
-                       list = Fcons (Fcons (tem, make_number (width)), list);
-                     else
-                       /* For the moment, width is not known.  */
-                       list = Fcons (Fcons (tem, Qnil), list);
-                   }
-               }
-           }
-
-         if (!try_XLoadQueryFont)
-           {
-             BLOCK_INPUT;
-             XFreeFontNames (names);
-             UNBLOCK_INPUT;
-           }
-       }
-
-      /* Now store the result in the cache.  */
-      XSETCDR (dpyinfo->name_list_element,
-              Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element)));
-
-    label_cached:
-      if (NILP (list)) continue; /* Try the remaining alternatives.  */
-
-      newlist = second_best = Qnil;
-      /* Make a list of the fonts that have the right width.  */
-      for (; CONSP (list); list = XCDR (list))
-       {
-         int found_size;
-
-         tem = XCAR (list);
-
-         if (!CONSP (tem) || NILP (XCAR (tem)))
-           continue;
-         if (!size)
-           {
-             newlist = Fcons (XCAR (tem), newlist);
-             continue;
-           }
-
-         if (!INTEGERP (XCDR (tem)))
-           {
-             /* Since we have not yet known the size of this font, we
-                must try slow function call XLoadQueryFont.  */
-             XFontStruct *thisinfo;
-
-             BLOCK_INPUT;
-             x_catch_errors (dpy);
-             thisinfo = XLoadQueryFont (dpy,
-                                        SDATA (XCAR (tem)));
-             if (x_had_errors_p (dpy))
-               {
-                 /* This error is perhaps due to insufficient memory on X
-                    server.  Let's just ignore it.  */
-                 thisinfo = NULL;
-                 x_clear_errors (dpy);
-               }
-             x_uncatch_errors ();
-             UNBLOCK_INPUT;
-
-             if (thisinfo)
-               {
-                 XSETCDR (tem,
-                          (thisinfo->min_bounds.width == 0
-                           ? make_number (0)
-                           : make_number (thisinfo->max_bounds.width)));
-                 BLOCK_INPUT;
-                 XFreeFont (dpy, thisinfo);
-                 UNBLOCK_INPUT;
-               }
-             else
-               /* For unknown reason, the previous call of XListFont had
-                 returned a font which can't be opened.  Record the size
-                 as 0 not to try to open it again.  */
-               XSETCDR (tem, make_number (0));
-           }
-
-         found_size = XINT (XCDR (tem));
-         if (found_size == size)
-           newlist = Fcons (XCAR (tem), newlist);
-         else if (found_size > 0)
-           {
-             if (NILP (second_best))
-               second_best = tem;
-             else if (found_size < size)
-               {
-                 if (XINT (XCDR (second_best)) > size
-                     || XINT (XCDR (second_best)) < found_size)
-                   second_best = tem;
-               }
-             else
-               {
-                 if (XINT (XCDR (second_best)) > size
-                     && XINT (XCDR (second_best)) > found_size)
-                   second_best = tem;
-               }
-           }
-       }
-      if (!NILP (newlist))
-       break;
-      else if (!NILP (second_best))
-       {
-         newlist = Fcons (XCAR (second_best), Qnil);
-         break;
-       }
-    }
-
-  return newlist;
-}
-
-
 #if GLYPH_DEBUG
 
 /* Check that FONT is valid on frame F.  It is if it can be found in F's
@@ -10460,551 +9830,17 @@ x_list_fonts (f, pattern, size, maxnames)
 static void
 x_check_font (f, font)
      struct frame *f;
-     XFontStruct *font;
+     struct font *font;
 {
-  int i;
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-
-  xassert (font != NULL);
-
-#ifdef USE_FONT_BACKEND
-  if (enable_font_backend)
-    /* Fixme: Perhaps we should check all cached fonts.  */
-    return;
-#endif
-  for (i = 0; i < dpyinfo->n_fonts; i++)
-    if (dpyinfo->font_table[i].name
-       && font == dpyinfo->font_table[i].font)
-      break;
+  Lisp_Object frame;
 
-  xassert (i < dpyinfo->n_fonts);
+  xassert (font != NULL && ! NILP (font->props[FONT_TYPE_INDEX]));
+  if (font->driver->check)
+    xassert (font->driver->check (f, font) == 0);
 }
 
 #endif /* GLYPH_DEBUG != 0 */
 
-/* Set *W to the minimum width, *H to the minimum font height of FONT.
-   Note: There are (broken) X fonts out there with invalid XFontStruct
-   min_bounds contents.  For example, handa@etl.go.jp reports that
-   "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
-   have font->min_bounds.width == 0.  */
-
-static INLINE void
-x_font_min_bounds (font, w, h)
-     XFontStruct *font;
-     int *w, *h;
-{
-  *h = FONT_HEIGHT (font);
-  *w = font->min_bounds.width;
-
-  /* Try to handle the case where FONT->min_bounds has invalid
-     contents.  Since the only font known to have invalid min_bounds
-     is fixed-width, use max_bounds if min_bounds seems to be invalid.  */
-  if (*w <= 0)
-    *w = font->max_bounds.width;
-}
-
-
-/* Compute the smallest character width and smallest font height over
-   all fonts available on frame F.  Set the members smallest_char_width
-   and smallest_font_height in F's x_display_info structure to
-   the values computed.  Value is non-zero if smallest_font_height or
-   smallest_char_width become smaller than they were before.  */
-
-static int
-x_compute_min_glyph_bounds (f)
-     struct frame *f;
-{
-  int i;
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  XFontStruct *font;
-  int old_width = dpyinfo->smallest_char_width;
-  int old_height = dpyinfo->smallest_font_height;
-
-  dpyinfo->smallest_font_height = 100000;
-  dpyinfo->smallest_char_width = 100000;
-
-  for (i = 0; i < dpyinfo->n_fonts; ++i)
-    if (dpyinfo->font_table[i].name)
-      {
-       struct font_info *fontp = dpyinfo->font_table + i;
-       int w, h;
-
-       font = (XFontStruct *) fontp->font;
-       xassert (font != (XFontStruct *) ~0);
-       x_font_min_bounds (font, &w, &h);
-
-       dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
-       dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
-      }
-
-  xassert (dpyinfo->smallest_char_width > 0
-          && dpyinfo->smallest_font_height > 0);
-
-  return (dpyinfo->n_fonts == 1
-         || dpyinfo->smallest_char_width < old_width
-         || dpyinfo->smallest_font_height < old_height);
-}
-
-
-/* Load font named FONTNAME of the size SIZE for frame F, and return a
-   pointer to the structure font_info while allocating it dynamically.
-   If SIZE is 0, load any size of font.
-   If loading is failed, return NULL.  */
-
-struct font_info *
-x_load_font (f, fontname, size)
-     struct frame *f;
-     register char *fontname;
-     int size;
-{
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  Lisp_Object font_names;
-
-  /* Get a list of all the fonts that match this name.  Once we
-     have a list of matching fonts, we compare them against the fonts
-     we already have by comparing names.  */
-  font_names = x_list_fonts (f, build_string (fontname), size, 1);
-
-  if (!NILP (font_names))
-    {
-      Lisp_Object tail;
-      int i;
-
-      for (i = 0; i < dpyinfo->n_fonts; i++)
-       for (tail = font_names; CONSP (tail); tail = XCDR (tail))
-         if (dpyinfo->font_table[i].name
-             && (!strcmp (dpyinfo->font_table[i].name,
-                          SDATA (XCAR (tail)))
-                 || !strcmp (dpyinfo->font_table[i].full_name,
-                             SDATA (XCAR (tail)))))
-           return (dpyinfo->font_table + i);
-    }
-
-  /* Load the font and add it to the table.  */
-  {
-    char *full_name;
-    XFontStruct *font;
-    struct font_info *fontp;
-    unsigned long value;
-    int i;
-
-    /* If we have found fonts by x_list_font, load one of them.  If
-       not, we still try to load a font by the name given as FONTNAME
-       because XListFonts (called in x_list_font) of some X server has
-       a bug of not finding a font even if the font surely exists and
-       is loadable by XLoadQueryFont.  */
-    if (size > 0 && !NILP (font_names))
-      fontname = (char *) SDATA (XCAR (font_names));
-
-    BLOCK_INPUT;
-    x_catch_errors (FRAME_X_DISPLAY (f));
-    font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
-    if (x_had_errors_p (FRAME_X_DISPLAY (f)))
-      {
-       /* This error is perhaps due to insufficient memory on X
-          server.  Let's just ignore it.  */
-       font = NULL;
-       x_clear_errors (FRAME_X_DISPLAY (f));
-      }
-    x_uncatch_errors ();
-    UNBLOCK_INPUT;
-    if (!font)
-      return NULL;
-
-    /* Find a free slot in the font table.  */
-    for (i = 0; i < dpyinfo->n_fonts; ++i)
-      if (dpyinfo->font_table[i].name == NULL)
-       break;
-
-    /* If no free slot found, maybe enlarge the font table.  */
-    if (i == dpyinfo->n_fonts
-       && dpyinfo->n_fonts == dpyinfo->font_table_size)
-      {
-       int sz;
-       dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
-       sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
-       dpyinfo->font_table
-         = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
-      }
-
-    fontp = dpyinfo->font_table + i;
-    if (i == dpyinfo->n_fonts)
-      ++dpyinfo->n_fonts;
-
-    /* Now fill in the slots of *FONTP.  */
-    BLOCK_INPUT;
-    bzero (fontp, sizeof (*fontp));
-    fontp->font = font;
-    fontp->font_idx = i;
-    fontp->charset = -1;       /* fs_load_font sets it.  */
-    fontp->name = (char *) xmalloc (strlen (fontname) + 1);
-    bcopy (fontname, fontp->name, strlen (fontname) + 1);
-
-    if (font->min_bounds.width == font->max_bounds.width)
-      {
-       /* Fixed width font.  */
-       fontp->average_width = fontp->space_width = font->min_bounds.width;
-      }
-    else
-      {
-       XChar2b char2b;
-       XCharStruct *pcm;
-
-       char2b.byte1 = 0x00, char2b.byte2 = 0x20;
-       pcm = x_per_char_metric (font, &char2b, 0);
-       if (pcm)
-         fontp->space_width = pcm->width;
-       else
-         fontp->space_width = FONT_WIDTH (font);
-
-       fontp->average_width
-         = (XGetFontProperty (font, dpyinfo->Xatom_AVERAGE_WIDTH, &value)
-            ? (long) value / 10 : 0);
-       if (fontp->average_width < 0)
-         fontp->average_width = - fontp->average_width;
-       if (fontp->average_width == 0)
-         {
-           if (pcm)
-             {
-               int width = pcm->width;
-               for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
-                 if ((pcm = x_per_char_metric (font, &char2b, 0)) != NULL)
-                   width += pcm->width;
-               fontp->average_width = width / 95;
-             }
-           else
-             fontp->average_width = FONT_WIDTH (font);
-         }
-      }
-
-    /* Try to get the full name of FONT.  Put it in FULL_NAME.  */
-    full_name = 0;
-    if (XGetFontProperty (font, XA_FONT, &value))
-      {
-       char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
-       char *p = name;
-       int dashes = 0;
-
-       /* Count the number of dashes in the "full name".
-          If it is too few, this isn't really the font's full name,
-          so don't use it.
-          In X11R4, the fonts did not come with their canonical names
-          stored in them.  */
-       while (*p)
-         {
-           if (*p == '-')
-             dashes++;
-           p++;
-         }
-
-       if (dashes >= 13)
-         {
-           full_name = (char *) xmalloc (p - name + 1);
-           bcopy (name, full_name, p - name + 1);
-         }
-
-       XFree (name);
-      }
-
-    if (full_name != 0)
-      fontp->full_name = full_name;
-    else
-      fontp->full_name = fontp->name;
-
-    fontp->size = font->max_bounds.width;
-    fontp->height = FONT_HEIGHT (font);
-
-    if (NILP (font_names))
-      {
-       /* We come here because of a bug of XListFonts mentioned at
-          the head of this block.  Let's store this information in
-          the cache for x_list_fonts.  */
-       Lisp_Object lispy_name = build_string (fontname);
-       Lisp_Object lispy_full_name = build_string (fontp->full_name);
-       Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
-                                Qnil);
-
-       XSETCDR (dpyinfo->name_list_element,
-                Fcons (Fcons (key,
-                              Fcons (Fcons (lispy_full_name,
-                                            make_number (fontp->size)),
-                                     Qnil)),
-                       XCDR (dpyinfo->name_list_element)));
-       if (full_name)
-         {
-           key = Fcons (Fcons (lispy_full_name, make_number (256)),
-                        Qnil);
-           XSETCDR (dpyinfo->name_list_element,
-                    Fcons (Fcons (key,
-                                  Fcons (Fcons (lispy_full_name,
-                                                make_number (fontp->size)),
-                                         Qnil)),
-                           XCDR (dpyinfo->name_list_element)));
-         }
-      }
-
-    /* The slot `encoding' specifies how to map a character
-       code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
-       the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
-       (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
-       2:0xA020..0xFF7F).  For the moment, we don't know which charset
-       uses this font.  So, we set information in fontp->encoding_type
-       which is never used by any charset.  If mapping can't be
-       decided, set FONT_ENCODING_NOT_DECIDED.  */
-    fontp->encoding_type
-      = (font->max_byte1 == 0
-        /* 1-byte font */
-        ? (font->min_char_or_byte2 < 0x80
-           ? (font->max_char_or_byte2 < 0x80
-              ? 0              /* 0x20..0x7F */
-              : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
-           : 1)                /* 0xA0..0xFF */
-        /* 2-byte font */
-        : (font->min_byte1 < 0x80
-           ? (font->max_byte1 < 0x80
-              ? (font->min_char_or_byte2 < 0x80
-                 ? (font->max_char_or_byte2 < 0x80
-                    ? 0                /* 0x2020..0x7F7F */
-                    : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
-                 : 3)          /* 0x20A0..0x7FFF */
-              : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
-           : (font->min_char_or_byte2 < 0x80
-              ? (font->max_char_or_byte2 < 0x80
-                 ? 2           /* 0xA020..0xFF7F */
-                 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
-              : 1)));          /* 0xA0A0..0xFFFF */
-
-    fontp->baseline_offset
-      = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
-        ? (long) value : 0);
-    fontp->relative_compose
-      = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
-        ? (long) value : 0);
-    fontp->default_ascent
-      = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
-        ? (long) value : 0);
-
-    /* Set global flag fonts_changed_p to non-zero if the font loaded
-       has a character with a smaller width than any other character
-       before, or if the font loaded has a smaller height than any
-       other font loaded before.  If this happens, it will make a
-       glyph matrix reallocation necessary.  */
-    fonts_changed_p |= x_compute_min_glyph_bounds (f);
-    UNBLOCK_INPUT;
-    return fontp;
-  }
-}
-
-
-/* Return a pointer to struct font_info of a font named FONTNAME for
-   frame F.  If no such font is loaded, return NULL.  */
-
-struct font_info *
-x_query_font (f, fontname)
-     struct frame *f;
-     register char *fontname;
-{
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-  int i;
-
-  for (i = 0; i < dpyinfo->n_fonts; i++)
-    if (dpyinfo->font_table[i].name
-       && (!xstricmp (dpyinfo->font_table[i].name, fontname)
-           || !xstricmp (dpyinfo->font_table[i].full_name, fontname)))
-      return (dpyinfo->font_table + i);
-  return NULL;
-}
-
-
-/* Find a CCL program for a font specified by FONTP, and set the member
- `encoder' of the structure.  */
-
-void
-x_find_ccl_program (fontp)
-     struct font_info *fontp;
-{
-  Lisp_Object list, elt;
-
-  elt = Qnil;
-  for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
-    {
-      elt = XCAR (list);
-      if (CONSP (elt)
-         && STRINGP (XCAR (elt))
-         && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
-              >= 0)
-             || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
-                 >= 0)))
-       break;
-    }
-
-  if (! NILP (list))
-    {
-      struct ccl_program *ccl
-       = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
-
-      if (setup_ccl_program (ccl, XCDR (elt)) < 0)
-       xfree (ccl);
-      else
-       fontp->font_encoder = ccl;
-    }
-}
-
-
-/* Return a char-table whose elements are t if the font FONT_INFO
-   contains a glyph for the corresponding character, and nil if
-   not.  */
-
-Lisp_Object
-x_get_font_repertory (f, font_info)
-     FRAME_PTR f;
-     struct font_info *font_info;
-{
-  XFontStruct *font = (XFontStruct *) font_info->font;
-  Lisp_Object table;
-  int min_byte1, max_byte1, min_byte2, max_byte2;
-  int c;
-  struct charset *charset = CHARSET_FROM_ID (font_info->charset);
-  int offset = CHARSET_OFFSET (charset);
-
-  table = Fmake_char_table (Qnil, Qnil);
-
-  min_byte1 = font->min_byte1;
-  max_byte1 = font->max_byte1;
-  min_byte2 = font->min_char_or_byte2;
-  max_byte2 = font->max_char_or_byte2;
-  if (min_byte1 == 0 && max_byte1 == 0)
-    {
-      if (! font->per_char || font->all_chars_exist == True)
-       {
-         if (offset >= 0)
-           char_table_set_range (table, offset + min_byte2,
-                                 offset + max_byte2, Qt);
-         else
-           for (; min_byte2 <= max_byte2; min_byte2++)
-             {
-               c = DECODE_CHAR (charset, min_byte2);
-               CHAR_TABLE_SET (table, c, Qt);
-             }
-       }
-      else
-       {
-         XCharStruct *pcm = font->per_char;
-         int from = -1;
-         int i;
-
-         for (i = min_byte2; i <= max_byte2; i++, pcm++)
-           {
-             if (pcm->width == 0 && pcm->rbearing == pcm->lbearing)
-               {
-                 if (from >= 0)
-                   {
-                     if (offset >= 0)
-                       char_table_set_range (table, offset + from,
-                                             offset + i - 1, Qt);
-                     else
-                       for (; from < i; from++)
-                         {
-                           c = DECODE_CHAR (charset, from);
-                           CHAR_TABLE_SET (table, c, Qt);
-                         }
-                     from = -1;
-                   }
-               }
-             else if (from < 0)
-               from = i;
-           }
-         if (from >= 0)
-           {
-             if (offset >= 0)
-               char_table_set_range (table, offset + from, offset + i - 1,
-                                     Qt);
-             else
-               for (; from < i; from++)
-                 {
-                   c = DECODE_CHAR (charset, from);
-                   CHAR_TABLE_SET (table, c, Qt);
-                 }
-           }
-       }
-    }
-  else
-    {
-      if (! font->per_char || font->all_chars_exist == True)
-       {
-         int i, j;
-
-         if (offset >= 0)
-           for (i = min_byte1; i <= max_byte1; i++)
-             char_table_set_range
-               (table, offset + ((i << 8) | min_byte2),
-                offset + ((i << 8) | max_byte2), Qt);
-         else
-           for (i = min_byte1; i <= max_byte1; i++)        
-             for (j = min_byte2; j <= max_byte2; j++)
-               {
-                 unsigned code = (i << 8) | j;
-                 c = DECODE_CHAR (charset, code);
-                 CHAR_TABLE_SET (table, c, Qt);
-               }
-       }
-      else
-       {
-         XCharStruct *pcm = font->per_char;
-         int i;
-
-         for (i = min_byte1; i <= max_byte1; i++)
-           {
-             int from = -1;
-             int j;
-
-             for (j = min_byte2; j <= max_byte2; j++, pcm++)
-               {
-                 if (pcm->width == 0 && pcm->rbearing == pcm->lbearing)
-                   {
-                     if (from >= 0)
-                       {
-                         if (offset >= 0)
-                           char_table_set_range
-                             (table, offset + ((i << 8) | from),
-                              offset + ((i << 8) | (j - 1)), Qt);
-                         else
-                           {
-                             for (; from < j; from++)
-                               {
-                                 unsigned code = (i << 8) | from;
-                                 c = ENCODE_CHAR (charset, code);
-                                 CHAR_TABLE_SET (table, c, Qt);
-                               }
-                           }
-                         from = -1;
-                       }
-                   }
-                 else if (from < 0)
-                   from = j;
-               }
-             if (from >= 0)
-               {
-                 if (offset >= 0)
-                   char_table_set_range
-                     (table, offset + ((i << 8) | from),
-                      offset + ((i << 8) | (j - 1)), Qt);
-                 else
-                   {
-                     for (; from < j; from++)
-                       {
-                         unsigned code = (i << 8) | from;
-                         c = DECODE_CHAR (charset, code);
-                         CHAR_TABLE_SET (table, c, Qt);
-                       }
-                   }
-               }
-           }
-       }
-    }
-
-  return table;
-}
 \f
 /***********************************************************************
                            Initialization
@@ -11040,7 +9876,6 @@ static int x_initialized;
 static int x_session_initialized;
 #endif
 
-#ifdef MULTI_KBOARD
 /* Test whether two display-name strings agree up to the dot that separates
    the screen number from the server number.  */
 static int
@@ -11087,7 +9922,6 @@ same_x_server (name1, name2)
          && (*name1 == '.' || *name1 == '\0')
          && (*name2 == '.' || *name2 == '\0'));
 }
-#endif
 
 /* Count number of set bits in mask and number of bits to shift to
    get to the first bit.  With MASK 0x7e0, *BITS is set to 6, and *OFFSET
@@ -11286,7 +10120,6 @@ x_term_init (display_name, xrm_option, resource_name)
 
   terminal = x_create_terminal (dpyinfo);
 
-#ifdef MULTI_KBOARD
   {
     struct x_display_info *share;
     Lisp_Object tail;
@@ -11306,11 +10139,15 @@ x_term_init (display_name, xrm_option, resource_name)
        if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
          {
            char *vendor = ServerVendor (dpy);
+           /* Temporarily hide the partially initialized terminal */
+           terminal_list = terminal->next_terminal;
            UNBLOCK_INPUT;
            terminal->kboard->Vsystem_key_alist
              = call1 (Qvendor_specific_keysyms,
                       vendor ? build_string (vendor) : empty_unibyte_string);
            BLOCK_INPUT;
+           terminal->next_terminal = terminal_list;
+           terminal_list = terminal;
          }
 
        terminal->kboard->next_kboard = all_kboards;
@@ -11323,7 +10160,6 @@ x_term_init (display_name, xrm_option, resource_name)
       }
     terminal->kboard->reference_count++;
   }
-#endif
 
   /* Put this display on the chain.  */
   dpyinfo->next = x_display_list;
@@ -11340,7 +10176,7 @@ x_term_init (display_name, xrm_option, resource_name)
   terminal->name = (char *) xmalloc (SBYTES (display_name) + 1);
   strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
   terminal->name[SBYTES (display_name)] = 0;
-  
+
 #if 0
   XSetAfterFunction (x_current_display, x_trace_wire);
 #endif /* ! 0 */
@@ -11379,23 +10215,12 @@ x_term_init (display_name, xrm_option, resource_name)
                                     DefaultScreen (dpyinfo->display));
   select_visual (dpyinfo);
   dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
-  dpyinfo->height = HeightOfScreen (dpyinfo->screen);
-  dpyinfo->width = WidthOfScreen (dpyinfo->screen);
   dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
   dpyinfo->client_leader_window = 0;
   dpyinfo->grabbed = 0;
   dpyinfo->reference_count = 0;
   dpyinfo->icon_bitmap_id = -1;
-  dpyinfo->font_table = NULL;
   dpyinfo->n_fonts = 0;
-  dpyinfo->font_table_size = 0;
-#ifdef USE_FONT_BACKEND
-  dpyinfo->font = XLoadQueryFont (dpyinfo->display, "fixed");
-  if (! dpyinfo->font)
-    dpyinfo->font = XLoadQueryFont (dpyinfo->display, "*");
-  if (! dpyinfo->font)
-    abort ();
-#endif /* USE_FONT_BACKEND */
   dpyinfo->bitmaps = 0;
   dpyinfo->bitmaps_size = 0;
   dpyinfo->bitmaps_last = 0;
@@ -11413,7 +10238,6 @@ x_term_init (display_name, xrm_option, resource_name)
   dpyinfo->x_focus_frame = 0;
   dpyinfo->x_focus_event_frame = 0;
   dpyinfo->x_highlight_frame = 0;
-  dpyinfo->terminal->image_cache = make_image_cache ();
   dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
 
   /* See if we can construct pixel values from RGB values.  */
@@ -11540,17 +10364,6 @@ x_term_init (display_name, xrm_option, resource_name)
   connection = ConnectionNumber (dpyinfo->display);
   dpyinfo->connection = connection;
 
-  {
-    char null_bits[1];
-
-    null_bits[0] = 0x00;
-
-    dpyinfo->null_pixel
-      = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
-                                    null_bits, 1, 1, (long) 0, (long) 0,
-                                    1);
-  }
-
   {
     extern int gray_bitmap_width, gray_bitmap_height;
     extern char *gray_bitmap_bits;
@@ -11708,43 +10521,16 @@ x_delete_display (dpyinfo)
          tail->next = tail->next->next;
     }
 
-#ifndef USE_X_TOOLKIT   /* I'm told Xt does this itself.  */
+  /* Xt and GTK do this themselves.  */
+#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
 #ifndef AIX            /* On AIX, XCloseDisplay calls this.  */
   XrmDestroyDatabase (dpyinfo->xrdb);
 #endif
 #endif
-#ifdef HAVE_X_I18N
-  if (dpyinfo->xim)
-    xim_close_dpy (dpyinfo);
-#endif
-
-#ifdef USE_FONT_BACKEND
-  if (! enable_font_backend)
-    {
-#endif
-  /* Free the font names in the font table.  */
-  for (i = 0; i < dpyinfo->n_fonts; i++)
-    if (dpyinfo->font_table[i].name)
-      {
-       if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
-         xfree (dpyinfo->font_table[i].full_name);
-       xfree (dpyinfo->font_table[i].name);
-      }
 
-  if (dpyinfo->font_table)
-    {
-      if (dpyinfo->font_table->font_encoder)
-       xfree (dpyinfo->font_table->font_encoder);
-      xfree (dpyinfo->font_table);
-    }
-#ifdef USE_FONT_BACKEND
-    }
-#endif
-
-  if (dpyinfo->x_id_name)
-    xfree (dpyinfo->x_id_name);
-  if (dpyinfo->color_cells)
-    xfree (dpyinfo->color_cells);
+  xfree (dpyinfo->x_id_name);
+  xfree (dpyinfo->x_dnd_atoms);
+  xfree (dpyinfo->color_cells);
   xfree (dpyinfo);
 }
 
@@ -11825,8 +10611,6 @@ static struct redisplay_interface x_redisplay_interface =
     x_draw_fringe_bitmap,
     0, /* define_fringe_bitmap */
     0, /* destroy_fringe_bitmap */
-    x_per_char_metric,
-    x_encode_char,
     x_compute_glyph_string_overhangs,
     x_draw_glyph_string,
     x_define_frame_cursor,
@@ -11844,28 +10628,23 @@ x_delete_terminal (struct terminal *terminal)
   struct x_display_info *dpyinfo = terminal->display_info.x;
   int i;
 
-  /* Protect against recursive calls.  Fdelete_frame in
+  /* Protect against recursive calls.  delete_frame in
      delete_terminal calls us back when it deletes our last frame.  */
   if (!terminal->name)
     return;
 
   BLOCK_INPUT;
+#ifdef HAVE_X_I18N
+  /* We must close our connection to the XIM server before closing the
+     X display.  */
+  if (dpyinfo->xim)
+    xim_close_dpy (dpyinfo);
+#endif
+
   /* If called from x_connection_closed, the display may already be closed
      and dpyinfo->display was set to 0 to indicate that.  */
   if (dpyinfo->display)
     {
-#ifdef USE_FONT_BACKEND
-      if (enable_font_backend)
-       XFreeFont (dpyinfo->display, dpyinfo->font);
-      else
-#endif
-       /* Free the fonts in the font table.  */
-       for (i = 0; i < dpyinfo->n_fonts; i++)
-         if (dpyinfo->font_table[i].name)
-           {
-             XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
-           }
-
       x_destroy_all_bitmaps (dpyinfo);
       XSetCloseDownMode (dpyinfo->display, DestroyAll);
 
@@ -11891,7 +10670,7 @@ static struct terminal *
 x_create_terminal (struct x_display_info *dpyinfo)
 {
   struct terminal *terminal;
-  
+
   terminal = create_terminal ();
 
   terminal->type = output_x_window;
@@ -11899,7 +10678,7 @@ x_create_terminal (struct x_display_info *dpyinfo)
   dpyinfo->terminal = terminal;
 
   /* kboard is initialized in x_term_init. */
-  
+
   terminal->clear_frame_hook = x_clear_frame;
   terminal->ins_del_lines_hook = x_ins_del_lines;
   terminal->delete_glyphs_hook = x_delete_glyphs;
@@ -11922,7 +10701,7 @@ x_create_terminal (struct x_display_info *dpyinfo)
 
   terminal->delete_frame_hook = x_destroy_window;
   terminal->delete_terminal_hook = x_delete_terminal;
-  
+
   terminal->rif = &x_redisplay_interface;
   terminal->scroll_region_ok = 1;    /* We'll scroll partial frames. */
   terminal->char_ins_del_ok = 1;
@@ -12018,7 +10797,9 @@ syms_of_xterm ()
      doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
 A value of nil means ignore them.  If you encounter fonts with bogus
 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
-to 4.1, set this to nil.  */);
+to 4.1, set this to nil.  You can also use `underline-minimum-offset'
+to override the font's UNDERLINE_POSITION for small font display
+sizes.  */);
   x_use_underline_position_properties = 1;
 
   DEFVAR_BOOL ("x-underline-at-descent-line",